vendor: 4,403 bytes, lines 1-173
1/*! 2 * jQuery JavaScript Library v2.1.0 3 * http://jquery.com/ 4 * 5 * Includes Sizzle.js 6 * http://sizzlejs.com/ 7 * 8 * Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors 9 * Released under the MIT license 10 * http://jquery.org/license 11 * 12 * Date: 2014-01-23T21:10Z 13 */ 14 15(function( global, factory ) { 16 17 if ( typeof module === "object" && typeof module.exports === "object" ) { 18 // For CommonJS and CommonJS-like environments where a proper window is present, 19 // execute the factory and get jQuery 20 // For environments that do not inherently posses a window with a document 21 // (such as Node.js), expose a jQuery-making factory as module.exports 22 // This accentuates the need for the creation of a real window 23 // e.g. var jQuery = require("jquery")(window); 24 // See ticket #14549 for more info 25 module.exports = global.document ? 26 factory( global, true ) : 27 function( w ) { 28 if ( !w.document ) { 29 throw new Error( "jQuery requires a window with a document" ); 30 } 31 return factory( w ); 32 }; 33 } else { 34 factory( global ); 35 } 36 37// Pass this if window is not defined yet 38}(typeof window !== "undefined" ? window : this, function( window, noGlobal ) { 39 40// Can't do this because several apps including ASP.NET trace 41// the stack via arguments.caller.callee and Firefox dies if 42// you try to trace through "use strict" call chains. (#13335) 43// Support: Firefox 18+ 44// 45 46var arr = []; 47 48var slice = arr.slice; 49 50var concat = arr.concat; 51 52var push = arr.push; 53 54var indexOf = arr.indexOf; 55 56var class2type = {}; 57 58var toString = class2type.toString; 59 60var hasOwn = class2type.hasOwnProperty; 61 62var trim = "".trim; 63 64var support = {}; 65 66 67 68var 69 // Use the correct document accordingly with window argument (sandbox) 70 document = window.document, 71 72 version = "2.1.0", 73 74 // Define a local copy of jQuery 75 jQuery = function( selector, context ) { 76 // The jQuery object is actually just the init constructor 'enhanced' 77 // Need init if jQuery is called (just allow error to be thrown if not included) 78 return new jQuery.fn.init( selector, context ); 79 }, 80 81 // Matches dashed string for camelizing 82 rmsPrefix = /^-ms-/, 83 rdashAlpha = /-([\da-z])/gi, 84 85 // Used by jQuery.camelCase as callback to replace() 86 fcamelCase = function( all, letter ) { 87 return letter.toUpperCase(); 88 }; 89 90jQuery.fn = jQuery.prototype = { 91 // The current version of jQuery being used 92 jquery: version, 93 94 constructor: jQuery, 95 96 // Start with an empty selector 97 selector: "", 98 99 // The default length of a jQuery object is 0 100 length: 0, 101 102 toArray: function() { 103 return slice.call( this ); 104 }, 105 106 // Get the Nth element in the matched element set OR 107 // Get the whole matched element set as a clean array 108 get: function( num ) { 109 return num != null ? 110 111 // Return a 'clean' array 112 ( num < 0 ? this[ num + this.length ] : this[ num ] ) : 113 114 // Return just the object 115 slice.call( this ); 116 }, 117 118 // Take an array of elements and push it onto the stack 119 // (returning the new matched element set) 120 pushStack: function( elems ) { 121 122 // Build a new jQuery matched element set 123 var ret = jQuery.merge( this.constructor(), elems ); 124 125 // Add the old object onto the stack (as a reference) 126 ret.prevObject = this; 127 ret.context = this.context; 128 129 // Return the newly-formed element set 130 return ret; 131 }, 132 133 // Execute a callback for every element in the matched set. 134 // (You can seed the arguments with an array of args, but this is 135 // only used internally.) 136 each: function( callback, args ) { 137 return jQuery.each( this, callback, args ); 138 }, 139 140 map: function( callback ) { 141 return this.pushStack( jQuery.map(this, function( elem, i ) { 142 return callback.call( elem, i, elem ); 143 })); 144 }, 145 146 slice: function() { 147 return this.pushStack( slice.apply( this, arguments ) ); 148 }, 149 150 first: function() { 151 return this.eq( 0 ); 152 }, 153 154 last: function() { 155 return this.eq( -1 ); 156 }, 157 158 eq: function( i ) { 159 var len = this.length, 160 j = +i + ( i < 0 ? len : 0 ); 161 return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] ); 162 }, 163 164 end: function() { 165 return this.prevObject || this.constructor(null); 166 }, 167 168 // For internal use only. 169 // Behaves like an Array's method, not like a jQuery method. 170 push: push, 171 sort: arr.sort, 172 splice: arr.splice 173};
vendor: 5,813 bytes, lines 174-398
174 175jQuery.extend = jQuery.fn.extend = function() { 176 var options, name, src, copy, copyIsArray, clone, 177 target = arguments[0] || {}, 178 i = 1, 179 length = arguments.length, 180 deep = false; 181 182 // Handle a deep copy situation 183 if ( typeof target === "boolean" ) { 184 deep = target; 185 186 // skip the boolean and the target 187 target = arguments[ i ] || {}; 188 i++; 189 } 190 191 // Handle case when target is a string or something (possible in deep copy) 192 if ( typeof target !== "object" && !jQuery.isFunction(target) ) { 193 target = {}; 194 } 195 196 // extend jQuery itself if only one argument is passed 197 if ( i === length ) { 198 target = this; 199 i--; 200 } 201 202 for ( ; i < length; i++ ) { 203 // Only deal with non-null/undefined values 204 if ( (options = arguments[ i ]) != null ) { 205 // Extend the base object 206 for ( name in options ) { 207 src = target[ name ]; 208 copy = options[ name ]; 209 210 // Prevent never-ending loop 211 if ( target === copy ) { 212 continue; 213 } 214 215 // Recurse if we're merging plain objects or arrays 216 if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { 217 if ( copyIsArray ) { 218 copyIsArray = false; 219 clone = src && jQuery.isArray(src) ? src : []; 220 221 } else { 222 clone = src && jQuery.isPlainObject(src) ? src : {}; 223 } 224 225 // Never move original objects, clone them 226 target[ name ] = jQuery.extend( deep, clone, copy ); 227 228 // Don't bring in undefined values 229 } else if ( copy !== undefined ) { 230 target[ name ] = copy; 231 } 232 } 233 } 234 } 235 236 // Return the modified object 237 return target; 238}; 239 240jQuery.extend({ 241 // Unique for each copy of jQuery on the page 242 expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), 243 244 // Assume jQuery is ready without the ready module 245 isReady: true, 246 247 error: function( msg ) { 248 throw new Error( msg ); 249 }, 250 251 noop: function() {}, 252 253 // See test/unit/core.js for details concerning isFunction. 254 // Since version 1.3, DOM methods and functions like alert 255 // aren't supported. They return false on IE (#2968). 256 isFunction: function( obj ) { 257 return jQuery.type(obj) === "function"; 258 }, 259 260 isArray: Array.isArray, 261 262 isWindow: function( obj ) { 263 return obj != null && obj === obj.window; 264 }, 265 266 isNumeric: function( obj ) { 267 // parseFloat NaNs numeric-cast false positives (null|true|false|"") 268 // ...but misinterprets leading-number strings, particularly hex literals ("0x...") 269 // subtraction forces infinities to NaN 270 return obj - parseFloat( obj ) >= 0; 271 }, 272 273 isPlainObject: function( obj ) { 274 // Not plain objects: 275 // - Any object or value whose internal [[Class]] property is not "[object Object]" 276 // - DOM nodes 277 // - window 278 if ( jQuery.type( obj ) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { 279 return false; 280 } 281 282 // Support: Firefox <20 283 // The try/catch suppresses exceptions thrown when attempting to access 284 // the "constructor" property of certain host objects, ie. |window.location| 285 // https://bugzilla.mozilla.org/show_bug.cgi?id=814622 286 try { 287 if ( obj.constructor && 288 !hasOwn.call( obj.constructor.prototype, "isPrototypeOf" ) ) { 289 return false; 290 } 291 } catch ( e ) { 292 return false; 293 } 294 295 // If the function hasn't returned already, we're confident that 296 // |obj| is a plain object, created by {} or constructed with new Object 297 return true; 298 }, 299 300 isEmptyObject: function( obj ) { 301 var name; 302 for ( name in obj ) { 303 return false; 304 } 305 return true; 306 }, 307 308 type: function( obj ) { 309 if ( obj == null ) { 310 return obj + ""; 311 } 312 // Support: Android < 4.0, iOS < 6 (functionish RegExp) 313 return typeof obj === "object" || typeof obj === "function" ? 314 class2type[ toString.call(obj) ] || "object" : 315 typeof obj; 316 }, 317 318 // Evaluates a script in a global context 319 globalEval: function( code ) { 320 var script, 321 indirect = eval; 322 323 code = jQuery.trim( code ); 324 325 if ( code ) { 326 // If the code includes a valid, prologue position 327 // strict mode pragma, execute code by injecting a 328 // script tag into the document. 329 if ( code.indexOf("use strict") === 1 ) { 330 script = document.createElement("script"); 331 script.text = code; 332 document.head.appendChild( script ).parentNode.removeChild( script ); 333 } else { 334 // Otherwise, avoid the DOM node creation, insertion 335 // and removal by using an indirect global eval 336 indirect( code ); 337 } 338 } 339 }, 340 341 // Convert dashed to camelCase; used by the css and data modules 342 // Microsoft forgot to hump their vendor prefix (#9572) 343 camelCase: function( string ) { 344 return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); 345 }, 346 347 nodeName: function( elem, name ) { 348 return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); 349 }, 350 351 // args is for internal usage only 352 each: function( obj, callback, args ) { 353 var value, 354 i = 0, 355 length = obj.length, 356 isArray = isArraylike( obj ); 357 358 if ( args ) { 359 if ( isArray ) { 360 for ( ; i < length; i++ ) { 361 value = callback.apply( obj[ i ], args ); 362 363 if ( value === false ) { 364 break; 365 } 366 } 367 } else { 368 for ( i in obj ) { 369 value = callback.apply( obj[ i ], args ); 370 371 if ( value === false ) { 372 break; 373 } 374 } 375 } 376 377 // A special, fast, case for the most common use of each 378 } else { 379 if ( isArray ) { 380 for ( ; i < length; i++ ) { 381 value = callback.call( obj[ i ], i, obj[ i ] ); 382 383 if ( value === false ) { 384 break; 385 } 386 } 387 } else { 388 for ( i in obj ) { 389 value = callback.call( obj[ i ], i, obj[ i ] ); 390 391 if ( value === false ) { 392 break; 393 } 394 } 395 } 396 } 397 398 return obj;
vendor: 60,029 bytes, lines 399-2462
399 }, 400 401 trim: function( text ) { 402 return text == null ? "" : trim.call( text ); 403 }, 404 405 // results is for internal usage only 406 makeArray: function( arr, results ) { 407 var ret = results || []; 408 409 if ( arr != null ) { 410 if ( isArraylike( Object(arr) ) ) { 411 jQuery.merge( ret, 412 typeof arr === "string" ? 413 [ arr ] : arr 414 ); 415 } else { 416 push.call( ret, arr ); 417 } 418 } 419 420 return ret; 421 }, 422 423 inArray: function( elem, arr, i ) { 424 return arr == null ? -1 : indexOf.call( arr, elem, i ); 425 }, 426 427 merge: function( first, second ) { 428 var len = +second.length, 429 j = 0, 430 i = first.length; 431 432 for ( ; j < len; j++ ) { 433 first[ i++ ] = second[ j ]; 434 } 435 436 first.length = i; 437 438 return first; 439 }, 440 441 grep: function( elems, callback, invert ) { 442 var callbackInverse, 443 matches = [], 444 i = 0, 445 length = elems.length, 446 callbackExpect = !invert; 447 448 // Go through the array, only saving the items 449 // that pass the validator function 450 for ( ; i < length; i++ ) { 451 callbackInverse = !callback( elems[ i ], i ); 452 if ( callbackInverse !== callbackExpect ) { 453 matches.push( elems[ i ] ); 454 } 455 } 456 457 return matches; 458 }, 459 460 // arg is for internal usage only 461 map: function( elems, callback, arg ) { 462 var value, 463 i = 0, 464 length = elems.length, 465 isArray = isArraylike( elems ), 466 ret = []; 467 468 // Go through the array, translating each of the items to their new values 469 if ( isArray ) { 470 for ( ; i < length; i++ ) { 471 value = callback( elems[ i ], i, arg ); 472 473 if ( value != null ) { 474 ret.push( value ); 475 } 476 } 477 478 // Go through every key on the object, 479 } else { 480 for ( i in elems ) { 481 value = callback( elems[ i ], i, arg ); 482 483 if ( value != null ) { 484 ret.push( value ); 485 } 486 } 487 } 488 489 // Flatten any nested arrays 490 return concat.apply( [], ret ); 491 }, 492 493 // A global GUID counter for objects 494 guid: 1, 495 496 // Bind a function to a context, optionally partially applying any 497 // arguments. 498 proxy: function( fn, context ) { 499 var tmp, args, proxy; 500 501 if ( typeof context === "string" ) { 502 tmp = fn[ context ]; 503 context = fn; 504 fn = tmp; 505 } 506 507 // Quick check to determine if target is callable, in the spec 508 // this throws a TypeError, but we will just return undefined. 509 if ( !jQuery.isFunction( fn ) ) { 510 return undefined; 511 } 512 513 // Simulated bind 514 args = slice.call( arguments, 2 ); 515 proxy = function() { 516 return fn.apply( context || this, args.concat( slice.call( arguments ) ) ); 517 }; 518 519 // Set the guid of unique handler to the same of original handler, so it can be removed 520 proxy.guid = fn.guid = fn.guid || jQuery.guid++; 521 522 return proxy; 523 }, 524 525 now: Date.now, 526 527 // jQuery.support is not used in Core but other projects attach their 528 // properties to it so it needs to exist. 529 support: support 530}); 531 532// Populate the class2type map 533jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) { 534 class2type[ "[object " + name + "]" ] = name.toLowerCase(); 535}); 536 537function isArraylike( obj ) { 538 var length = obj.length, 539 type = jQuery.type( obj ); 540 541 if ( type === "function" || jQuery.isWindow( obj ) ) { 542 return false; 543 } 544 545 if ( obj.nodeType === 1 && length ) { 546 return true; 547 } 548 549 return type === "array" || length === 0 || 550 typeof length === "number" && length > 0 && ( length - 1 ) in obj; 551} 552var Sizzle = 553/*! 554 * Sizzle CSS Selector Engine v1.10.16 555 * http://sizzlejs.com/ 556 * 557 * Copyright 2013 jQuery Foundation, Inc. and other contributors 558 * Released under the MIT license 559 * http://jquery.org/license 560 * 561 * Date: 2014-01-13 562 */ 563(function( window ) { 564 565var i, 566 support, 567 Expr, 568 getText, 569 isXML, 570 compile, 571 outermostContext, 572 sortInput, 573 hasDuplicate, 574 575 // Local document vars 576 setDocument, 577 document, 578 docElem, 579 documentIsHTML, 580 rbuggyQSA, 581 rbuggyMatches, 582 matches, 583 contains, 584 585 // Instance-specific data 586 expando = "sizzle" + -(new Date()), 587 preferredDoc = window.document, 588 dirruns = 0, 589 done = 0, 590 classCache = createCache(), 591 tokenCache = createCache(), 592 compilerCache = createCache(), 593 sortOrder = function( a, b ) { 594 if ( a === b ) { 595 hasDuplicate = true; 596 } 597 return 0; 598 }, 599 600 // General-purpose constants 601 strundefined = typeof undefined, 602 MAX_NEGATIVE = 1 << 31, 603 604 // Instance methods 605 hasOwn = ({}).hasOwnProperty, 606 arr = [], 607 pop = arr.pop, 608 push_native = arr.push, 609 push = arr.push, 610 slice = arr.slice, 611 // Use a stripped-down indexOf if we can't use a native one 612 indexOf = arr.indexOf || function( elem ) { 613 var i = 0, 614 len = this.length; 615 for ( ; i < len; i++ ) { 616 if ( this[i] === elem ) { 617 return i; 618 } 619 } 620 return -1; 621 }, 622 623 booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", 624 625 // Regular expressions 626 627 // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace 628 whitespace = "[\\x20\\t\\r\\n\\f]", 629 // http://www.w3.org/TR/css3-syntax/#characters 630 characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+", 631 632 // Loosely modeled on CSS identifier characters 633 // An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors 634 // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier 635 identifier = characterEncoding.replace( "w", "w#" ), 636 637 // Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors 638 attributes = "\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace + 639 "*(?:([*^$|!~]?=)" + whitespace + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" + whitespace + "*\\]", 640 641 // Prefer arguments quoted, 642 // then not containing pseudos/brackets, 643 // then attribute selectors/non-parenthetical expressions, 644 // then anything else 645 // These preferences are here to reduce the number of selectors 646 // needing tokenize in the PSEUDO preFilter 647 pseudos = ":(" + characterEncoding + ")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|" + attributes.replace( 3, 8 ) + ")*)|.*)\\)|)", 648 649 // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter 650 rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), 651 652 rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), 653 rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), 654 655 rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ), 656 657 rpseudo = new RegExp( pseudos ), 658 ridentifier = new RegExp( "^" + identifier + "$" ), 659 660 matchExpr = { 661 "ID": new RegExp( "^#(" + characterEncoding + ")" ), 662 "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ), 663 "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ), 664 "ATTR": new RegExp( "^" + attributes ), 665 "PSEUDO": new RegExp( "^" + pseudos ), 666 "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + 667 "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + 668 "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), 669 "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), 670 // For use in libraries implementing .is() 671 // We use this for POS matching in `select` 672 "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + 673 whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) 674 }, 675 676 rinputs = /^(?:input|select|textarea|button)$/i, 677 rheader = /^h\d$/i, 678 679 rnative = /^[^{]+\{\s*\[native \w/, 680 681 // Easily-parseable/retrievable ID or TAG or CLASS selectors 682 rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, 683 684 rsibling = /[+~]/, 685 rescape = /'|\\/g, 686 687 // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters 688 runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ), 689 funescape = function( _, escaped, escapedWhitespace ) { 690 var high = "0x" + escaped - 0x10000; 691 // NaN means non-codepoint 692 // Support: Firefox 693 // Workaround erroneous numeric interpretation of +"0x" 694 return high !== high || escapedWhitespace ? 695 escaped : 696 high < 0 ? 697 // BMP codepoint 698 String.fromCharCode( high + 0x10000 ) : 699 // Supplemental Plane codepoint (surrogate pair) 700 String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); 701 }; 702 703// Optimize for push.apply( _, NodeList ) 704try { 705 push.apply( 706 (arr = slice.call( preferredDoc.childNodes )), 707 preferredDoc.childNodes 708 ); 709 // Support: Android<4.0 710 // Detect silently failing push.apply 711 arr[ preferredDoc.childNodes.length ].nodeType; 712} catch ( e ) { 713 push = { apply: arr.length ? 714 715 // Leverage slice if possible 716 function( target, els ) { 717 push_native.apply( target, slice.call(els) ); 718 } : 719 720 // Support: IE<9 721 // Otherwise append directly 722 function( target, els ) { 723 var j = target.length, 724 i = 0; 725 // Can't trust NodeList.length 726 while ( (target[j++] = els[i++]) ) {} 727 target.length = j - 1; 728 } 729 }; 730} 731 732function Sizzle( selector, context, results, seed ) { 733 var match, elem, m, nodeType, 734 // QSA vars 735 i, groups, old, nid, newContext, newSelector; 736 737 if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { 738 setDocument( context ); 739 } 740 741 context = context || document; 742 results = results || []; 743 744 if ( !selector || typeof selector !== "string" ) { 745 return results; 746 } 747 748 if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) { 749 return []; 750 } 751 752 if ( documentIsHTML && !seed ) { 753 754 // Shortcuts 755 if ( (match = rquickExpr.exec( selector )) ) { 756 // Speed-up: Sizzle("#ID") 757 if ( (m = match[1]) ) { 758 if ( nodeType === 9 ) { 759 elem = context.getElementById( m ); 760 // Check parentNode to catch when Blackberry 4.6 returns 761 // nodes that are no longer in the document (jQuery #6963) 762 if ( elem && elem.parentNode ) { 763 // Handle the case where IE, Opera, and Webkit return items 764 // by name instead of ID 765 if ( elem.id === m ) { 766 results.push( elem ); 767 return results; 768 } 769 } else { 770 return results; 771 } 772 } else { 773 // Context is not a document 774 if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) && 775 contains( context, elem ) && elem.id === m ) { 776 results.push( elem ); 777 return results; 778 } 779 } 780 781 // Speed-up: Sizzle("TAG") 782 } else if ( match[2] ) { 783 push.apply( results, context.getElementsByTagName( selector ) ); 784 return results; 785 786 // Speed-up: Sizzle(".CLASS") 787 } else if ( (m = match[3]) && support.getElementsByClassName && context.getElementsByClassName ) { 788 push.apply( results, context.getElementsByClassName( m ) ); 789 return results; 790 } 791 } 792 793 // QSA path 794 if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { 795 nid = old = expando; 796 newContext = context; 797 newSelector = nodeType === 9 && selector; 798 799 // qSA works strangely on Element-rooted queries 800 // We can work around this by specifying an extra ID on the root 801 // and working up from there (Thanks to Andrew Dupont for the technique) 802 // IE 8 doesn't work on object elements 803 if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { 804 groups = tokenize( selector ); 805 806 if ( (old = context.getAttribute("id")) ) { 807 nid = old.replace( rescape, "\\$&" ); 808 } else { 809 context.setAttribute( "id", nid ); 810 } 811 nid = "[id='" + nid + "'] "; 812 813 i = groups.length; 814 while ( i-- ) { 815 groups[i] = nid + toSelector( groups[i] ); 816 } 817 newContext = rsibling.test( selector ) && testContext( context.parentNode ) || context; 818 newSelector = groups.join(","); 819 } 820 821 if ( newSelector ) { 822 try { 823 push.apply( results, 824 newContext.querySelectorAll( newSelector ) 825 ); 826 return results; 827 } catch(qsaError) { 828 } finally { 829 if ( !old ) { 830 context.removeAttribute("id"); 831 } 832 } 833 } 834 } 835 } 836 837 // All others 838 return select( selector.replace( rtrim, "$1" ), context, results, seed ); 839} 840 841/** 842 * Create key-value caches of limited size 843 * @returns {Function(string, Object)} Returns the Object data after storing it on itself with 844 * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) 845 * deleting the oldest entry 846 */ 847function createCache() { 848 var keys = []; 849 850 function cache( key, value ) { 851 // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) 852 if ( keys.push( key + " " ) > Expr.cacheLength ) { 853 // Only keep the most recent entries 854 delete cache[ keys.shift() ]; 855 } 856 return (cache[ key + " " ] = value); 857 } 858 return cache; 859} 860 861/** 862 * Mark a function for special use by Sizzle 863 * @param {Function} fn The function to mark 864 */ 865function markFunction( fn ) { 866 fn[ expando ] = true; 867 return fn; 868} 869 870/** 871 * Support testing using an element 872 * @param {Function} fn Passed the created div and expects a boolean result 873 */ 874function assert( fn ) { 875 var div = document.createElement("div"); 876 877 try { 878 return !!fn( div ); 879 } catch (e) { 880 return false; 881 } finally { 882 // Remove from its parent by default 883 if ( div.parentNode ) { 884 div.parentNode.removeChild( div ); 885 } 886 // release memory in IE 887 div = null; 888 } 889} 890 891/** 892 * Adds the same handler for all of the specified attrs 893 * @param {String} attrs Pipe-separated list of attributes 894 * @param {Function} handler The method that will be applied 895 */ 896function addHandle( attrs, handler ) { 897 var arr = attrs.split("|"), 898 i = attrs.length; 899 900 while ( i-- ) { 901 Expr.attrHandle[ arr[i] ] = handler; 902 } 903} 904 905/** 906 * Checks document order of two siblings 907 * @param {Element} a 908 * @param {Element} b 909 * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b 910 */ 911function siblingCheck( a, b ) { 912 var cur = b && a, 913 diff = cur && a.nodeType === 1 && b.nodeType === 1 && 914 ( ~b.sourceIndex || MAX_NEGATIVE ) - 915 ( ~a.sourceIndex || MAX_NEGATIVE ); 916 917 // Use IE sourceIndex if available on both nodes 918 if ( diff ) { 919 return diff; 920 } 921 922 // Check if b follows a 923 if ( cur ) { 924 while ( (cur = cur.nextSibling) ) { 925 if ( cur === b ) { 926 return -1; 927 } 928 } 929 } 930 931 return a ? 1 : -1; 932} 933 934/** 935 * Returns a function to use in pseudos for input types 936 * @param {String} type 937 */ 938function createInputPseudo( type ) { 939 return function( elem ) { 940 var name = elem.nodeName.toLowerCase(); 941 return name === "input" && elem.type === type; 942 }; 943} 944 945/** 946 * Returns a function to use in pseudos for buttons 947 * @param {String} type 948 */ 949function createButtonPseudo( type ) { 950 return function( elem ) { 951 var name = elem.nodeName.toLowerCase(); 952 return (name === "input" || name === "button") && elem.type === type; 953 }; 954} 955 956/** 957 * Returns a function to use in pseudos for positionals 958 * @param {Function} fn 959 */ 960function createPositionalPseudo( fn ) { 961 return markFunction(function( argument ) { 962 argument = +argument; 963 return markFunction(function( seed, matches ) { 964 var j, 965 matchIndexes = fn( [], seed.length, argument ), 966 i = matchIndexes.length; 967 968 // Match elements found at the specified indexes 969 while ( i-- ) { 970 if ( seed[ (j = matchIndexes[i]) ] ) { 971 seed[j] = !(matches[j] = seed[j]); 972 } 973 } 974 }); 975 }); 976} 977 978/** 979 * Checks a node for validity as a Sizzle context 980 * @param {Element|Object=} context 981 * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value 982 */ 983function testContext( context ) { 984 return context && typeof context.getElementsByTagName !== strundefined && context; 985} 986 987// Expose support vars for convenience 988support = Sizzle.support = {}; 989 990/** 991 * Detects XML nodes 992 * @param {Element|Object} elem An element or a document 993 * @returns {Boolean} True iff elem is a non-HTML XML node 994 */ 995isXML = Sizzle.isXML = function( elem ) { 996 // documentElement is verified for cases where it doesn't yet exist 997 // (such as loading iframes in IE - #4833) 998 var documentElement = elem && (elem.ownerDocument || elem).documentElement; 999 return documentElement ? documentElement.nodeName !== "HTML" : false; 1000}; 1001 1002/** 1003 * Sets document-related variables once based on the current document 1004 * @param {Element|Object} [doc] An element or document object to use to set the document 1005 * @returns {Object} Returns the current document 1006 */ 1007setDocument = Sizzle.setDocument = function( node ) { 1008 var hasCompare, 1009 doc = node ? node.ownerDocument || node : preferredDoc, 1010 parent = doc.defaultView; 1011 1012 // If no document and documentElement is available, return 1013 if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) { 1014 return document; 1015 } 1016 1017 // Set our document 1018 document = doc; 1019 docElem = doc.documentElement; 1020 1021 // Support tests 1022 documentIsHTML = !isXML( doc ); 1023 1024 // Support: IE>8 1025 // If iframe document is assigned to "document" variable and if iframe has been reloaded, 1026 // IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936 1027 // IE6-8 do not support the defaultView property so parent will be undefined 1028 if ( parent && parent !== parent.top ) { 1029 // IE11 does not have attachEvent, so all must suffer 1030 if ( parent.addEventListener ) { 1031 parent.addEventListener( "unload", function() { 1032 setDocument(); 1033 }, false ); 1034 } else if ( parent.attachEvent ) { 1035 parent.attachEvent( "onunload", function() { 1036 setDocument(); 1037 }); 1038 } 1039 } 1040 1041 /* Attributes 1042 ---------------------------------------------------------------------- */ 1043 1044 // Support: IE<8 1045 // Verify that getAttribute really returns attributes and not properties (excepting IE8 booleans) 1046 support.attributes = assert(function( div ) { 1047 div.className = "i"; 1048 return !div.getAttribute("className"); 1049 }); 1050 1051 /* getElement(s)By* 1052 ---------------------------------------------------------------------- */ 1053 1054 // Check if getElementsByTagName("*") returns only elements 1055 support.getElementsByTagName = assert(function( div ) { 1056 div.appendChild( doc.createComment("") ); 1057 return !div.getElementsByTagName("*").length; 1058 }); 1059 1060 // Check if getElementsByClassName can be trusted 1061 support.getElementsByClassName = rnative.test( doc.getElementsByClassName ) && assert(function( div ) { 1062 div.innerHTML = "<div class='a'></div><div class='a i'></div>"; 1063 1064 // Support: Safari<4 1065 // Catch class over-caching 1066 div.firstChild.className = "i"; 1067 // Support: Opera<10 1068 // Catch gEBCN failure to find non-leading classes 1069 return div.getElementsByClassName("i").length === 2; 1070 }); 1071 1072 // Support: IE<10 1073 // Check if getElementById returns elements by name 1074 // The broken getElementById methods don't pick up programatically-set names, 1075 // so use a roundabout getElementsByName test 1076 support.getById = assert(function( div ) { 1077 docElem.appendChild( div ).id = expando; 1078 return !doc.getElementsByName || !doc.getElementsByName( expando ).length; 1079 }); 1080 1081 // ID find and filter 1082 if ( support.getById ) { 1083 Expr.find["ID"] = function( id, context ) { 1084 if ( typeof context.getElementById !== strundefined && documentIsHTML ) { 1085 var m = context.getElementById( id ); 1086 // Check parentNode to catch when Blackberry 4.6 returns 1087 // nodes that are no longer in the document #6963 1088 return m && m.parentNode ? [m] : []; 1089 } 1090 }; 1091 Expr.filter["ID"] = function( id ) { 1092 var attrId = id.replace( runescape, funescape ); 1093 return function( elem ) { 1094 return elem.getAttribute("id") === attrId; 1095 }; 1096 }; 1097 } else { 1098 // Support: IE6/7 1099 // getElementById is not reliable as a find shortcut 1100 delete Expr.find["ID"]; 1101 1102 Expr.filter["ID"] = function( id ) { 1103 var attrId = id.replace( runescape, funescape ); 1104 return function( elem ) { 1105 var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id"); 1106 return node && node.value === attrId; 1107 }; 1108 }; 1109 } 1110 1111 // Tag 1112 Expr.find["TAG"] = support.getElementsByTagName ? 1113 function( tag, context ) { 1114 if ( typeof context.getElementsByTagName !== strundefined ) { 1115 return context.getElementsByTagName( tag ); 1116 } 1117 } : 1118 function( tag, context ) { 1119 var elem, 1120 tmp = [], 1121 i = 0, 1122 results = context.getElementsByTagName( tag ); 1123 1124 // Filter out possible comments 1125 if ( tag === "*" ) { 1126 while ( (elem = results[i++]) ) { 1127 if ( elem.nodeType === 1 ) { 1128 tmp.push( elem ); 1129 } 1130 } 1131 1132 return tmp; 1133 } 1134 return results; 1135 }; 1136 1137 // Class 1138 Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) { 1139 if ( typeof context.getElementsByClassName !== strundefined && documentIsHTML ) { 1140 return context.getElementsByClassName( className ); 1141 } 1142 }; 1143 1144 /* QSA/matchesSelector 1145 ---------------------------------------------------------------------- */ 1146 1147 // QSA and matchesSelector support 1148 1149 // matchesSelector(:active) reports false when true (IE9/Opera 11.5) 1150 rbuggyMatches = []; 1151 1152 // qSa(:focus) reports false when true (Chrome 21) 1153 // We allow this because of a bug in IE8/9 that throws an error 1154 // whenever `document.activeElement` is accessed on an iframe 1155 // So, we allow :focus to pass through QSA all the time to avoid the IE error 1156 // See http://bugs.jquery.com/ticket/13378 1157 rbuggyQSA = []; 1158 1159 if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) { 1160 // Build QSA regex 1161 // Regex strategy adopted from Diego Perini 1162 assert(function( div ) { 1163 // Select is set to empty string on purpose 1164 // This is to test IE's treatment of not explicitly 1165 // setting a boolean content attribute, 1166 // since its presence should be enough 1167 // http://bugs.jquery.com/ticket/12359 1168 div.innerHTML = "<select t=''><option selected=''></option></select>"; 1169 1170 // Support: IE8, Opera 10-12 1171 // Nothing should be selected when empty strings follow ^= or $= or *= 1172 if ( div.querySelectorAll("[t^='']").length ) { 1173 rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); 1174 } 1175 1176 // Support: IE8 1177 // Boolean attributes and "value" are not treated correctly 1178 if ( !div.querySelectorAll("[selected]").length ) { 1179 rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); 1180 } 1181 1182 // Webkit/Opera - :checked should return selected option elements 1183 // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked 1184 // IE8 throws error here and will not see later tests 1185 if ( !div.querySelectorAll(":checked").length ) { 1186 rbuggyQSA.push(":checked"); 1187 } 1188 }); 1189 1190 assert(function( div ) { 1191 // Support: Windows 8 Native Apps 1192 // The type and name attributes are restricted during .innerHTML assignment 1193 var input = doc.createElement("input"); 1194 input.setAttribute( "type", "hidden" ); 1195 div.appendChild( input ).setAttribute( "name", "D" ); 1196 1197 // Support: IE8 1198 // Enforce case-sensitivity of name attribute 1199 if ( div.querySelectorAll("[name=d]").length ) { 1200 rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); 1201 } 1202 1203 // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) 1204 // IE8 throws error here and will not see later tests 1205 if ( !div.querySelectorAll(":enabled").length ) { 1206 rbuggyQSA.push( ":enabled", ":disabled" ); 1207 } 1208 1209 // Opera 10-11 does not throw on post-comma invalid pseudos 1210 div.querySelectorAll("*,:x"); 1211 rbuggyQSA.push(",.*:"); 1212 }); 1213 } 1214 1215 if ( (support.matchesSelector = rnative.test( (matches = docElem.webkitMatchesSelector || 1216 docElem.mozMatchesSelector || 1217 docElem.oMatchesSelector || 1218 docElem.msMatchesSelector) )) ) { 1219 1220 assert(function( div ) { 1221 // Check to see if it's possible to do matchesSelector 1222 // on a disconnected node (IE 9) 1223 support.disconnectedMatch = matches.call( div, "div" ); 1224 1225 // This should fail with an exception 1226 // Gecko does not error, returns false instead 1227 matches.call( div, "[s!='']:x" ); 1228 rbuggyMatches.push( "!=", pseudos ); 1229 }); 1230 } 1231 1232 rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") ); 1233 rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") ); 1234 1235 /* Contains 1236 ---------------------------------------------------------------------- */ 1237 hasCompare = rnative.test( docElem.compareDocumentPosition ); 1238 1239 // Element contains another 1240 // Purposefully does not implement inclusive descendent 1241 // As in, an element does not contain itself 1242 contains = hasCompare || rnative.test( docElem.contains ) ? 1243 function( a, b ) { 1244 var adown = a.nodeType === 9 ? a.documentElement : a, 1245 bup = b && b.parentNode; 1246 return a === bup || !!( bup && bup.nodeType === 1 && ( 1247 adown.contains ? 1248 adown.contains( bup ) : 1249 a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 1250 )); 1251 } : 1252 function( a, b ) { 1253 if ( b ) { 1254 while ( (b = b.parentNode) ) { 1255 if ( b === a ) { 1256 return true; 1257 } 1258 } 1259 } 1260 return false; 1261 }; 1262 1263 /* Sorting 1264 ---------------------------------------------------------------------- */ 1265 1266 // Document order sorting 1267 sortOrder = hasCompare ? 1268 function( a, b ) { 1269 1270 // Flag for duplicate removal 1271 if ( a === b ) { 1272 hasDuplicate = true; 1273 return 0; 1274 } 1275 1276 // Sort on method existence if only one input has compareDocumentPosition 1277 var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; 1278 if ( compare ) { 1279 return compare; 1280 } 1281 1282 // Calculate position if both inputs belong to the same document 1283 compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ? 1284 a.compareDocumentPosition( b ) : 1285 1286 // Otherwise we know they are disconnected 1287 1; 1288 1289 // Disconnected nodes 1290 if ( compare & 1 || 1291 (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) { 1292 1293 // Choose the first element that is related to our preferred document 1294 if ( a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) { 1295 return -1; 1296 } 1297 if ( b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) { 1298 return 1; 1299 } 1300 1301 // Maintain original order 1302 return sortInput ? 1303 ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) : 1304 0; 1305 } 1306 1307 return compare & 4 ? -1 : 1; 1308 } : 1309 function( a, b ) { 1310 // Exit early if the nodes are identical 1311 if ( a === b ) { 1312 hasDuplicate = true; 1313 return 0; 1314 } 1315 1316 var cur, 1317 i = 0, 1318 aup = a.parentNode, 1319 bup = b.parentNode, 1320 ap = [ a ], 1321 bp = [ b ]; 1322 1323 // Parentless nodes are either documents or disconnected 1324 if ( !aup || !bup ) { 1325 return a === doc ? -1 : 1326 b === doc ? 1 : 1327 aup ? -1 : 1328 bup ? 1 : 1329 sortInput ? 1330 ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) : 1331 0; 1332 1333 // If the nodes are siblings, we can do a quick check 1334 } else if ( aup === bup ) { 1335 return siblingCheck( a, b ); 1336 } 1337 1338 // Otherwise we need full lists of their ancestors for comparison 1339 cur = a; 1340 while ( (cur = cur.parentNode) ) { 1341 ap.unshift( cur ); 1342 } 1343 cur = b; 1344 while ( (cur = cur.parentNode) ) { 1345 bp.unshift( cur ); 1346 } 1347 1348 // Walk down the tree looking for a discrepancy 1349 while ( ap[i] === bp[i] ) { 1350 i++; 1351 } 1352 1353 return i ? 1354 // Do a sibling check if the nodes have a common ancestor 1355 siblingCheck( ap[i], bp[i] ) : 1356 1357 // Otherwise nodes in our document sort first 1358 ap[i] === preferredDoc ? -1 : 1359 bp[i] === preferredDoc ? 1 : 1360 0; 1361 }; 1362 1363 return doc; 1364}; 1365 1366Sizzle.matches = function( expr, elements ) { 1367 return Sizzle( expr, null, null, elements ); 1368}; 1369 1370Sizzle.matchesSelector = function( elem, expr ) { 1371 // Set document vars if needed 1372 if ( ( elem.ownerDocument || elem ) !== document ) { 1373 setDocument( elem ); 1374 } 1375 1376 // Make sure that attribute selectors are quoted 1377 expr = expr.replace( rattributeQuotes, "='$1']" ); 1378 1379 if ( support.matchesSelector && documentIsHTML && 1380 ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && 1381 ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { 1382 1383 try { 1384 var ret = matches.call( elem, expr ); 1385 1386 // IE 9's matchesSelector returns false on disconnected nodes 1387 if ( ret || support.disconnectedMatch || 1388 // As well, disconnected nodes are said to be in a document 1389 // fragment in IE 9 1390 elem.document && elem.document.nodeType !== 11 ) { 1391 return ret; 1392 } 1393 } catch(e) {} 1394 } 1395 1396 return Sizzle( expr, document, null, [elem] ).length > 0; 1397}; 1398 1399Sizzle.contains = function( context, elem ) { 1400 // Set document vars if needed 1401 if ( ( context.ownerDocument || context ) !== document ) { 1402 setDocument( context ); 1403 } 1404 return contains( context, elem ); 1405}; 1406 1407Sizzle.attr = function( elem, name ) { 1408 // Set document vars if needed 1409 if ( ( elem.ownerDocument || elem ) !== document ) { 1410 setDocument( elem ); 1411 } 1412 1413 var fn = Expr.attrHandle[ name.toLowerCase() ], 1414 // Don't get fooled by Object.prototype properties (jQuery #13807) 1415 val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? 1416 fn( elem, name, !documentIsHTML ) : 1417 undefined; 1418 1419 return val !== undefined ? 1420 val : 1421 support.attributes || !documentIsHTML ? 1422 elem.getAttribute( name ) : 1423 (val = elem.getAttributeNode(name)) && val.specified ? 1424 val.value : 1425 null; 1426}; 1427 1428Sizzle.error = function( msg ) { 1429 throw new Error( "Syntax error, unrecognized expression: " + msg ); 1430}; 1431 1432/** 1433 * Document sorting and removing duplicates 1434 * @param {ArrayLike} results 1435 */ 1436Sizzle.uniqueSort = function( results ) { 1437 var elem, 1438 duplicates = [], 1439 j = 0, 1440 i = 0; 1441 1442 // Unless we *know* we can detect duplicates, assume their presence 1443 hasDuplicate = !support.detectDuplicates; 1444 sortInput = !support.sortStable && results.slice( 0 ); 1445 results.sort( sortOrder ); 1446 1447 if ( hasDuplicate ) { 1448 while ( (elem = results[i++]) ) { 1449 if ( elem === results[ i ] ) { 1450 j = duplicates.push( i ); 1451 } 1452 } 1453 while ( j-- ) { 1454 results.splice( duplicates[ j ], 1 ); 1455 } 1456 } 1457 1458 // Clear input after sorting to release objects 1459 // See https://github.com/jquery/sizzle/pull/225 1460 sortInput = null; 1461 1462 return results; 1463}; 1464 1465/** 1466 * Utility function for retrieving the text value of an array of DOM nodes 1467 * @param {Array|Element} elem 1468 */ 1469getText = Sizzle.getText = function( elem ) { 1470 var node, 1471 ret = "", 1472 i = 0, 1473 nodeType = elem.nodeType; 1474 1475 if ( !nodeType ) { 1476 // If no nodeType, this is expected to be an array 1477 while ( (node = elem[i++]) ) { 1478 // Do not traverse comment nodes 1479 ret += getText( node ); 1480 } 1481 } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { 1482 // Use textContent for elements 1483 // innerText usage removed for consistency of new lines (jQuery #11153) 1484 if ( typeof elem.textContent === "string" ) { 1485 return elem.textContent; 1486 } else { 1487 // Traverse its children 1488 for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { 1489 ret += getText( elem ); 1490 } 1491 } 1492 } else if ( nodeType === 3 || nodeType === 4 ) { 1493 return elem.nodeValue; 1494 } 1495 // Do not include comment or processing instruction nodes 1496 1497 return ret; 1498}; 1499 1500Expr = Sizzle.selectors = { 1501 1502 // Can be adjusted by the user 1503 cacheLength: 50, 1504 1505 createPseudo: markFunction, 1506 1507 match: matchExpr, 1508 1509 attrHandle: {}, 1510 1511 find: {}, 1512 1513 relative: { 1514 ">": { dir: "parentNode", first: true }, 1515 " ": { dir: "parentNode" }, 1516 "+": { dir: "previousSibling", first: true }, 1517 "~": { dir: "previousSibling" } 1518 }, 1519 1520 preFilter: { 1521 "ATTR": function( match ) { 1522 match[1] = match[1].replace( runescape, funescape ); 1523 1524 // Move the given value to match[3] whether quoted or unquoted 1525 match[3] = ( match[4] || match[5] || "" ).replace( runescape, funescape ); 1526 1527 if ( match[2] === "~=" ) { 1528 match[3] = " " + match[3] + " "; 1529 } 1530 1531 return match.slice( 0, 4 ); 1532 }, 1533 1534 "CHILD": function( match ) { 1535 /* matches from matchExpr["CHILD"] 1536 1 type (only|nth|...) 1537 2 what (child|of-type) 1538 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) 1539 4 xn-component of xn+y argument ([+-]?\d*n|) 1540 5 sign of xn-component 1541 6 x of xn-component 1542 7 sign of y-component 1543 8 y of y-component 1544 */ 1545 match[1] = match[1].toLowerCase(); 1546 1547 if ( match[1].slice( 0, 3 ) === "nth" ) { 1548 // nth-* requires argument 1549 if ( !match[3] ) { 1550 Sizzle.error( match[0] ); 1551 } 1552 1553 // numeric x and y parameters for Expr.filter.CHILD 1554 // remember that false/true cast respectively to 0/1 1555 match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) ); 1556 match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" ); 1557 1558 // other types prohibit arguments 1559 } else if ( match[3] ) { 1560 Sizzle.error( match[0] ); 1561 } 1562 1563 return match; 1564 }, 1565 1566 "PSEUDO": function( match ) { 1567 var excess, 1568 unquoted = !match[5] && match[2]; 1569 1570 if ( matchExpr["CHILD"].test( match[0] ) ) { 1571 return null; 1572 } 1573 1574 // Accept quoted arguments as-is 1575 if ( match[3] && match[4] !== undefined ) { 1576 match[2] = match[4]; 1577 1578 // Strip excess characters from unquoted arguments 1579 } else if ( unquoted && rpseudo.test( unquoted ) && 1580 // Get excess from tokenize (recursively) 1581 (excess = tokenize( unquoted, true )) && 1582 // advance to the next closing parenthesis 1583 (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { 1584 1585 // excess is a negative index 1586 match[0] = match[0].slice( 0, excess ); 1587 match[2] = unquoted.slice( 0, excess ); 1588 } 1589 1590 // Return only captures needed by the pseudo filter method (type and argument) 1591 return match.slice( 0, 3 ); 1592 } 1593 }, 1594 1595 filter: { 1596 1597 "TAG": function( nodeNameSelector ) { 1598 var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); 1599 return nodeNameSelector === "*" ? 1600 function() { return true; } : 1601 function( elem ) { 1602 return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; 1603 }; 1604 }, 1605 1606 "CLASS": function( className ) { 1607 var pattern = classCache[ className + " " ]; 1608 1609 return pattern || 1610 (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && 1611 classCache( className, function( elem ) { 1612 return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== strundefined && elem.getAttribute("class") || "" ); 1613 }); 1614 }, 1615 1616 "ATTR": function( name, operator, check ) { 1617 return function( elem ) { 1618 var result = Sizzle.attr( elem, name ); 1619 1620 if ( result == null ) { 1621 return operator === "!="; 1622 } 1623 if ( !operator ) { 1624 return true; 1625 } 1626 1627 result += ""; 1628 1629 return operator === "=" ? result === check : 1630 operator === "!=" ? result !== check : 1631 operator === "^=" ? check && result.indexOf( check ) === 0 : 1632 operator === "*=" ? check && result.indexOf( check ) > -1 : 1633 operator === "$=" ? check && result.slice( -check.length ) === check : 1634 operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 : 1635 operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : 1636 false; 1637 }; 1638 }, 1639 1640 "CHILD": function( type, what, argument, first, last ) { 1641 var simple = type.slice( 0, 3 ) !== "nth", 1642 forward = type.slice( -4 ) !== "last", 1643 ofType = what === "of-type"; 1644 1645 return first === 1 && last === 0 ? 1646 1647 // Shortcut for :nth-*(n) 1648 function( elem ) { 1649 return !!elem.parentNode; 1650 } : 1651 1652 function( elem, context, xml ) { 1653 var cache, outerCache, node, diff, nodeIndex, start, 1654 dir = simple !== forward ? "nextSibling" : "previousSibling", 1655 parent = elem.parentNode, 1656 name = ofType && elem.nodeName.toLowerCase(), 1657 useCache = !xml && !ofType; 1658 1659 if ( parent ) { 1660 1661 // :(first|last|only)-(child|of-type) 1662 if ( simple ) { 1663 while ( dir ) { 1664 node = elem; 1665 while ( (node = node[ dir ]) ) { 1666 if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) { 1667 return false; 1668 } 1669 } 1670 // Reverse direction for :only-* (if we haven't yet done so) 1671 start = dir = type === "only" && !start && "nextSibling"; 1672 } 1673 return true; 1674 } 1675 1676 start = [ forward ? parent.firstChild : parent.lastChild ]; 1677 1678 // non-xml :nth-child(...) stores cache data on `parent` 1679 if ( forward && useCache ) { 1680 // Seek `elem` from a previously-cached index 1681 outerCache = parent[ expando ] || (parent[ expando ] = {}); 1682 cache = outerCache[ type ] || []; 1683 nodeIndex = cache[0] === dirruns && cache[1]; 1684 diff = cache[0] === dirruns && cache[2]; 1685 node = nodeIndex && parent.childNodes[ nodeIndex ]; 1686 1687 while ( (node = ++nodeIndex && node && node[ dir ] || 1688 1689 // Fallback to seeking `elem` from the start 1690 (diff = nodeIndex = 0) || start.pop()) ) { 1691 1692 // When found, cache indexes on `parent` and break 1693 if ( node.nodeType === 1 && ++diff && node === elem ) { 1694 outerCache[ type ] = [ dirruns, nodeIndex, diff ]; 1695 break; 1696 } 1697 } 1698 1699 // Use previously-cached element index if available 1700 } else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) { 1701 diff = cache[1]; 1702 1703 // xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...) 1704 } else { 1705 // Use the same loop as above to seek `elem` from the start 1706 while ( (node = ++nodeIndex && node && node[ dir ] || 1707 (diff = nodeIndex = 0) || start.pop()) ) { 1708 1709 if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) { 1710 // Cache the index of each encountered element 1711 if ( useCache ) { 1712 (node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ]; 1713 } 1714 1715 if ( node === elem ) { 1716 break; 1717 } 1718 } 1719 } 1720 } 1721 1722 // Incorporate the offset, then check against cycle size 1723 diff -= last; 1724 return diff === first || ( diff % first === 0 && diff / first >= 0 ); 1725 } 1726 }; 1727 }, 1728 1729 "PSEUDO": function( pseudo, argument ) { 1730 // pseudo-class names are case-insensitive 1731 // http://www.w3.org/TR/selectors/#pseudo-classes 1732 // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters 1733 // Remember that setFilters inherits from pseudos 1734 var args, 1735 fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || 1736 Sizzle.error( "unsupported pseudo: " + pseudo ); 1737 1738 // The user may use createPseudo to indicate that 1739 // arguments are needed to create the filter function 1740 // just as Sizzle does 1741 if ( fn[ expando ] ) { 1742 return fn( argument ); 1743 } 1744 1745 // But maintain support for old signatures 1746 if ( fn.length > 1 ) { 1747 args = [ pseudo, pseudo, "", argument ]; 1748 return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? 1749 markFunction(function( seed, matches ) { 1750 var idx, 1751 matched = fn( seed, argument ), 1752 i = matched.length; 1753 while ( i-- ) { 1754 idx = indexOf.call( seed, matched[i] ); 1755 seed[ idx ] = !( matches[ idx ] = matched[i] ); 1756 } 1757 }) : 1758 function( elem ) { 1759 return fn( elem, 0, args ); 1760 }; 1761 } 1762 1763 return fn; 1764 } 1765 }, 1766 1767 pseudos: { 1768 // Potentially complex pseudos 1769 "not": markFunction(function( selector ) { 1770 // Trim the selector passed to compile 1771 // to avoid treating leading and trailing 1772 // spaces as combinators 1773 var input = [], 1774 results = [], 1775 matcher = compile( selector.replace( rtrim, "$1" ) ); 1776 1777 return matcher[ expando ] ? 1778 markFunction(function( seed, matches, context, xml ) { 1779 var elem, 1780 unmatched = matcher( seed, null, xml, [] ), 1781 i = seed.length; 1782 1783 // Match elements unmatched by `matcher` 1784 while ( i-- ) { 1785 if ( (elem = unmatched[i]) ) { 1786 seed[i] = !(matches[i] = elem); 1787 } 1788 } 1789 }) : 1790 function( elem, context, xml ) { 1791 input[0] = elem; 1792 matcher( input, null, xml, results ); 1793 return !results.pop(); 1794 }; 1795 }), 1796 1797 "has": markFunction(function( selector ) { 1798 return function( elem ) { 1799 return Sizzle( selector, elem ).length > 0; 1800 }; 1801 }), 1802 1803 "contains": markFunction(function( text ) { 1804 return function( elem ) { 1805 return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; 1806 }; 1807 }), 1808 1809 // "Whether an element is represented by a :lang() selector 1810 // is based solely on the element's language value 1811 // being equal to the identifier C, 1812 // or beginning with the identifier C immediately followed by "-". 1813 // The matching of C against the element's language value is performed case-insensitively. 1814 // The identifier C does not have to be a valid language name." 1815 // http://www.w3.org/TR/selectors/#lang-pseudo 1816 "lang": markFunction( function( lang ) { 1817 // lang value must be a valid identifier 1818 if ( !ridentifier.test(lang || "") ) { 1819 Sizzle.error( "unsupported lang: " + lang ); 1820 } 1821 lang = lang.replace( runescape, funescape ).toLowerCase(); 1822 return function( elem ) { 1823 var elemLang; 1824 do { 1825 if ( (elemLang = documentIsHTML ? 1826 elem.lang : 1827 elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) { 1828 1829 elemLang = elemLang.toLowerCase(); 1830 return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; 1831 } 1832 } while ( (elem = elem.parentNode) && elem.nodeType === 1 ); 1833 return false; 1834 }; 1835 }), 1836 1837 // Miscellaneous 1838 "target": function( elem ) { 1839 var hash = window.location && window.location.hash; 1840 return hash && hash.slice( 1 ) === elem.id; 1841 }, 1842 1843 "root": function( elem ) { 1844 return elem === docElem; 1845 }, 1846 1847 "focus": function( elem ) { 1848 return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); 1849 }, 1850 1851 // Boolean properties 1852 "enabled": function( elem ) { 1853 return elem.disabled === false; 1854 }, 1855 1856 "disabled": function( elem ) { 1857 return elem.disabled === true; 1858 }, 1859 1860 "checked": function( elem ) { 1861 // In CSS3, :checked should return both checked and selected elements 1862 // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked 1863 var nodeName = elem.nodeName.toLowerCase(); 1864 return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); 1865 }, 1866 1867 "selected": function( elem ) { 1868 // Accessing this property makes selected-by-default 1869 // options in Safari work properly 1870 if ( elem.parentNode ) { 1871 elem.parentNode.selectedIndex; 1872 } 1873 1874 return elem.selected === true; 1875 }, 1876 1877 // Contents 1878 "empty": function( elem ) { 1879 // http://www.w3.org/TR/selectors/#empty-pseudo 1880 // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), 1881 // but not by others (comment: 8; processing instruction: 7; etc.) 1882 // nodeType < 6 works because attributes (2) do not appear as children 1883 for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { 1884 if ( elem.nodeType < 6 ) { 1885 return false; 1886 } 1887 } 1888 return true; 1889 }, 1890 1891 "parent": function( elem ) { 1892 return !Expr.pseudos["empty"]( elem ); 1893 }, 1894 1895 // Element/input types 1896 "header": function( elem ) { 1897 return rheader.test( elem.nodeName ); 1898 }, 1899 1900 "input": function( elem ) { 1901 return rinputs.test( elem.nodeName ); 1902 }, 1903 1904 "button": function( elem ) { 1905 var name = elem.nodeName.toLowerCase(); 1906 return name === "input" && elem.type === "button" || name === "button"; 1907 }, 1908 1909 "text": function( elem ) { 1910 var attr; 1911 return elem.nodeName.toLowerCase() === "input" && 1912 elem.type === "text" && 1913 1914 // Support: IE<8 1915 // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" 1916 ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" ); 1917 }, 1918 1919 // Position-in-collection 1920 "first": createPositionalPseudo(function() { 1921 return [ 0 ]; 1922 }), 1923 1924 "last": createPositionalPseudo(function( matchIndexes, length ) { 1925 return [ length - 1 ]; 1926 }), 1927 1928 "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { 1929 return [ argument < 0 ? argument + length : argument ]; 1930 }), 1931 1932 "even": createPositionalPseudo(function( matchIndexes, length ) { 1933 var i = 0; 1934 for ( ; i < length; i += 2 ) { 1935 matchIndexes.push( i ); 1936 } 1937 return matchIndexes; 1938 }), 1939 1940 "odd": createPositionalPseudo(function( matchIndexes, length ) { 1941 var i = 1; 1942 for ( ; i < length; i += 2 ) { 1943 matchIndexes.push( i ); 1944 } 1945 return matchIndexes; 1946 }), 1947 1948 "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { 1949 var i = argument < 0 ? argument + length : argument; 1950 for ( ; --i >= 0; ) { 1951 matchIndexes.push( i ); 1952 } 1953 return matchIndexes; 1954 }), 1955 1956 "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { 1957 var i = argument < 0 ? argument + length : argument; 1958 for ( ; ++i < length; ) { 1959 matchIndexes.push( i ); 1960 } 1961 return matchIndexes; 1962 }) 1963 } 1964}; 1965 1966Expr.pseudos["nth"] = Expr.pseudos["eq"]; 1967 1968// Add button/input type pseudos 1969for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { 1970 Expr.pseudos[ i ] = createInputPseudo( i ); 1971} 1972for ( i in { submit: true, reset: true } ) { 1973 Expr.pseudos[ i ] = createButtonPseudo( i ); 1974} 1975 1976// Easy API for creating new setFilters 1977function setFilters() {} 1978setFilters.prototype = Expr.filters = Expr.pseudos; 1979Expr.setFilters = new setFilters(); 1980 1981function tokenize( selector, parseOnly ) { 1982 var matched, match, tokens, type, 1983 soFar, groups, preFilters, 1984 cached = tokenCache[ selector + " " ]; 1985 1986 if ( cached ) { 1987 return parseOnly ? 0 : cached.slice( 0 ); 1988 } 1989 1990 soFar = selector; 1991 groups = []; 1992 preFilters = Expr.preFilter; 1993 1994 while ( soFar ) { 1995 1996 // Comma and first run 1997 if ( !matched || (match = rcomma.exec( soFar )) ) { 1998 if ( match ) { 1999 // Don't consume trailing commas as valid 2000 soFar = soFar.slice( match[0].length ) || soFar; 2001 } 2002 groups.push( (tokens = []) ); 2003 } 2004 2005 matched = false; 2006 2007 // Combinators 2008 if ( (match = rcombinators.exec( soFar )) ) { 2009 matched = match.shift(); 2010 tokens.push({ 2011 value: matched, 2012 // Cast descendant combinators to space 2013 type: match[0].replace( rtrim, " " ) 2014 }); 2015 soFar = soFar.slice( matched.length ); 2016 } 2017 2018 // Filters 2019 for ( type in Expr.filter ) { 2020 if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || 2021 (match = preFilters[ type ]( match ))) ) { 2022 matched = match.shift(); 2023 tokens.push({ 2024 value: matched, 2025 type: type, 2026 matches: match 2027 }); 2028 soFar = soFar.slice( matched.length ); 2029 } 2030 } 2031 2032 if ( !matched ) { 2033 break; 2034 } 2035 } 2036 2037 // Return the length of the invalid excess 2038 // if we're just parsing 2039 // Otherwise, throw an error or return tokens 2040 return parseOnly ? 2041 soFar.length : 2042 soFar ? 2043 Sizzle.error( selector ) : 2044 // Cache the tokens 2045 tokenCache( selector, groups ).slice( 0 ); 2046} 2047 2048function toSelector( tokens ) { 2049 var i = 0, 2050 len = tokens.length, 2051 selector = ""; 2052 for ( ; i < len; i++ ) { 2053 selector += tokens[i].value; 2054 } 2055 return selector; 2056} 2057 2058function addCombinator( matcher, combinator, base ) { 2059 var dir = combinator.dir, 2060 checkNonElements = base && dir === "parentNode", 2061 doneName = done++; 2062 2063 return combinator.first ? 2064 // Check against closest ancestor/preceding element 2065 function( elem, context, xml ) { 2066 while ( (elem = elem[ dir ]) ) { 2067 if ( elem.nodeType === 1 || checkNonElements ) { 2068 return matcher( elem, context, xml ); 2069 } 2070 } 2071 } : 2072 2073 // Check against all ancestor/preceding elements 2074 function( elem, context, xml ) { 2075 var oldCache, outerCache, 2076 newCache = [ dirruns, doneName ]; 2077 2078 // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching 2079 if ( xml ) { 2080 while ( (elem = elem[ dir ]) ) { 2081 if ( elem.nodeType === 1 || checkNonElements ) { 2082 if ( matcher( elem, context, xml ) ) { 2083 return true; 2084 } 2085 } 2086 } 2087 } else { 2088 while ( (elem = elem[ dir ]) ) { 2089 if ( elem.nodeType === 1 || checkNonElements ) { 2090 outerCache = elem[ expando ] || (elem[ expando ] = {}); 2091 if ( (oldCache = outerCache[ dir ]) && 2092 oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { 2093 2094 // Assign to newCache so results back-propagate to previous elements 2095 return (newCache[ 2 ] = oldCache[ 2 ]); 2096 } else { 2097 // Reuse newcache so results back-propagate to previous elements 2098 outerCache[ dir ] = newCache; 2099 2100 // A match means we're done; a fail means we have to keep checking 2101 if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) { 2102 return true; 2103 } 2104 } 2105 } 2106 } 2107 } 2108 }; 2109} 2110 2111function elementMatcher( matchers ) { 2112 return matchers.length > 1 ? 2113 function( elem, context, xml ) { 2114 var i = matchers.length; 2115 while ( i-- ) { 2116 if ( !matchers[i]( elem, context, xml ) ) { 2117 return false; 2118 } 2119 } 2120 return true; 2121 } : 2122 matchers[0]; 2123} 2124 2125function condense( unmatched, map, filter, context, xml ) { 2126 var elem, 2127 newUnmatched = [], 2128 i = 0, 2129 len = unmatched.length, 2130 mapped = map != null; 2131 2132 for ( ; i < len; i++ ) { 2133 if ( (elem = unmatched[i]) ) { 2134 if ( !filter || filter( elem, context, xml ) ) { 2135 newUnmatched.push( elem ); 2136 if ( mapped ) { 2137 map.push( i ); 2138 } 2139 } 2140 } 2141 } 2142 2143 return newUnmatched; 2144} 2145 2146function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { 2147 if ( postFilter && !postFilter[ expando ] ) { 2148 postFilter = setMatcher( postFilter ); 2149 } 2150 if ( postFinder && !postFinder[ expando ] ) { 2151 postFinder = setMatcher( postFinder, postSelector ); 2152 } 2153 return markFunction(function( seed, results, context, xml ) { 2154 var temp, i, elem, 2155 preMap = [], 2156 postMap = [], 2157 preexisting = results.length, 2158 2159 // Get initial elements from seed or context 2160 elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ), 2161 2162 // Prefilter to get matcher input, preserving a map for seed-results synchronization 2163 matcherIn = preFilter && ( seed || !selector ) ? 2164 condense( elems, preMap, preFilter, context, xml ) : 2165 elems, 2166 2167 matcherOut = matcher ? 2168 // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, 2169 postFinder || ( seed ? preFilter : preexisting || postFilter ) ? 2170 2171 // ...intermediate processing is necessary 2172 [] : 2173 2174 // ...otherwise use results directly 2175 results : 2176 matcherIn; 2177 2178 // Find primary matches 2179 if ( matcher ) { 2180 matcher( matcherIn, matcherOut, context, xml ); 2181 } 2182 2183 // Apply postFilter 2184 if ( postFilter ) { 2185 temp = condense( matcherOut, postMap ); 2186 postFilter( temp, [], context, xml ); 2187 2188 // Un-match failing elements by moving them back to matcherIn 2189 i = temp.length; 2190 while ( i-- ) { 2191 if ( (elem = temp[i]) ) { 2192 matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); 2193 } 2194 } 2195 } 2196 2197 if ( seed ) { 2198 if ( postFinder || preFilter ) { 2199 if ( postFinder ) { 2200 // Get the final matcherOut by condensing this intermediate into postFinder contexts 2201 temp = []; 2202 i = matcherOut.length; 2203 while ( i-- ) { 2204 if ( (elem = matcherOut[i]) ) { 2205 // Restore matcherIn since elem is not yet a final match 2206 temp.push( (matcherIn[i] = elem) ); 2207 } 2208 } 2209 postFinder( null, (matcherOut = []), temp, xml ); 2210 } 2211 2212 // Move matched elements from seed to results to keep them synchronized 2213 i = matcherOut.length; 2214 while ( i-- ) { 2215 if ( (elem = matcherOut[i]) && 2216 (temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) { 2217 2218 seed[temp] = !(results[temp] = elem); 2219 } 2220 } 2221 } 2222 2223 // Add elements to results, through postFinder if defined 2224 } else { 2225 matcherOut = condense( 2226 matcherOut === results ? 2227 matcherOut.splice( preexisting, matcherOut.length ) : 2228 matcherOut 2229 ); 2230 if ( postFinder ) { 2231 postFinder( null, results, matcherOut, xml ); 2232 } else { 2233 push.apply( results, matcherOut ); 2234 } 2235 } 2236 }); 2237} 2238 2239function matcherFromTokens( tokens ) { 2240 var checkContext, matcher, j, 2241 len = tokens.length, 2242 leadingRelative = Expr.relative[ tokens[0].type ], 2243 implicitRelative = leadingRelative || Expr.relative[" "], 2244 i = leadingRelative ? 1 : 0, 2245 2246 // The foundational matcher ensures that elements are reachable from top-level context(s) 2247 matchContext = addCombinator( function( elem ) { 2248 return elem === checkContext; 2249 }, implicitRelative, true ), 2250 matchAnyContext = addCombinator( function( elem ) { 2251 return indexOf.call( checkContext, elem ) > -1; 2252 }, implicitRelative, true ), 2253 matchers = [ function( elem, context, xml ) { 2254 return ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( 2255 (checkContext = context).nodeType ? 2256 matchContext( elem, context, xml ) : 2257 matchAnyContext( elem, context, xml ) ); 2258 } ]; 2259 2260 for ( ; i < len; i++ ) { 2261 if ( (matcher = Expr.relative[ tokens[i].type ]) ) { 2262 matchers = [ addCombinator(elementMatcher( matchers ), matcher) ]; 2263 } else { 2264 matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); 2265 2266 // Return special upon seeing a positional matcher 2267 if ( matcher[ expando ] ) { 2268 // Find the next relative operator (if any) for proper handling 2269 j = ++i; 2270 for ( ; j < len; j++ ) { 2271 if ( Expr.relative[ tokens[j].type ] ) { 2272 break; 2273 } 2274 } 2275 return setMatcher( 2276 i > 1 && elementMatcher( matchers ), 2277 i > 1 && toSelector( 2278 // If the preceding token was a descendant combinator, insert an implicit any-element `*` 2279 tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" }) 2280 ).replace( rtrim, "$1" ), 2281 matcher, 2282 i < j && matcherFromTokens( tokens.slice( i, j ) ), 2283 j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), 2284 j < len && toSelector( tokens ) 2285 ); 2286 } 2287 matchers.push( matcher ); 2288 } 2289 } 2290 2291 return elementMatcher( matchers ); 2292} 2293 2294function matcherFromGroupMatchers( elementMatchers, setMatchers ) { 2295 var bySet = setMatchers.length > 0, 2296 byElement = elementMatchers.length > 0, 2297 superMatcher = function( seed, context, xml, results, outermost ) { 2298 var elem, j, matcher, 2299 matchedCount = 0, 2300 i = "0", 2301 unmatched = seed && [], 2302 setMatched = [], 2303 contextBackup = outermostContext, 2304 // We must always have either seed elements or outermost context 2305 elems = seed || byElement && Expr.find["TAG"]( "*", outermost ), 2306 // Use integer dirruns iff this is the outermost matcher 2307 dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1), 2308 len = elems.length; 2309 2310 if ( outermost ) { 2311 outermostContext = context !== document && context; 2312 } 2313 2314 // Add elements passing elementMatchers directly to results 2315 // Keep `i` a string if there are no elements so `matchedCount` will be "00" below 2316 // Support: IE<9, Safari 2317 // Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id 2318 for ( ; i !== len && (elem = elems[i]) != null; i++ ) { 2319 if ( byElement && elem ) { 2320 j = 0; 2321 while ( (matcher = elementMatchers[j++]) ) { 2322 if ( matcher( elem, context, xml ) ) { 2323 results.push( elem ); 2324 break; 2325 } 2326 } 2327 if ( outermost ) { 2328 dirruns = dirrunsUnique; 2329 } 2330 } 2331 2332 // Track unmatched elements for set filters 2333 if ( bySet ) { 2334 // They will have gone through all possible matchers 2335 if ( (elem = !matcher && elem) ) { 2336 matchedCount--; 2337 } 2338 2339 // Lengthen the array for every element, matched or not 2340 if ( seed ) { 2341 unmatched.push( elem ); 2342 } 2343 } 2344 } 2345 2346 // Apply set filters to unmatched elements 2347 matchedCount += i; 2348 if ( bySet && i !== matchedCount ) { 2349 j = 0; 2350 while ( (matcher = setMatchers[j++]) ) { 2351 matcher( unmatched, setMatched, context, xml ); 2352 } 2353 2354 if ( seed ) { 2355 // Reintegrate element matches to eliminate the need for sorting 2356 if ( matchedCount > 0 ) { 2357 while ( i-- ) { 2358 if ( !(unmatched[i] || setMatched[i]) ) { 2359 setMatched[i] = pop.call( results ); 2360 } 2361 } 2362 } 2363 2364 // Discard index placeholder values to get only actual matches 2365 setMatched = condense( setMatched ); 2366 } 2367 2368 // Add matches to results 2369 push.apply( results, setMatched ); 2370 2371 // Seedless set matches succeeding multiple successful matchers stipulate sorting 2372 if ( outermost && !seed && setMatched.length > 0 && 2373 ( matchedCount + setMatchers.length ) > 1 ) { 2374 2375 Sizzle.uniqueSort( results ); 2376 } 2377 } 2378 2379 // Override manipulation of globals by nested matchers 2380 if ( outermost ) { 2381 dirruns = dirrunsUnique; 2382 outermostContext = contextBackup; 2383 } 2384 2385 return unmatched; 2386 }; 2387 2388 return bySet ? 2389 markFunction( superMatcher ) : 2390 superMatcher; 2391} 2392 2393compile = Sizzle.compile = function( selector, group /* Internal Use Only */ ) { 2394 var i, 2395 setMatchers = [], 2396 elementMatchers = [], 2397 cached = compilerCache[ selector + " " ]; 2398 2399 if ( !cached ) { 2400 // Generate a function of recursive functions that can be used to check each element 2401 if ( !group ) { 2402 group = tokenize( selector ); 2403 } 2404 i = group.length; 2405 while ( i-- ) { 2406 cached = matcherFromTokens( group[i] ); 2407 if ( cached[ expando ] ) { 2408 setMatchers.push( cached ); 2409 } else { 2410 elementMatchers.push( cached ); 2411 } 2412 } 2413 2414 // Cache the compiled function 2415 cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); 2416 } 2417 return cached; 2418}; 2419 2420function multipleContexts( selector, contexts, results ) { 2421 var i = 0, 2422 len = contexts.length; 2423 for ( ; i < len; i++ ) { 2424 Sizzle( selector, contexts[i], results ); 2425 } 2426 return results; 2427} 2428 2429function select( selector, context, results, seed ) { 2430 var i, tokens, token, type, find, 2431 match = tokenize( selector ); 2432 2433 if ( !seed ) { 2434 // Try to minimize operations if there is only one group 2435 if ( match.length === 1 ) { 2436 2437 // Take a shortcut and set the context if the root selector is an ID 2438 tokens = match[0] = match[0].slice( 0 ); 2439 if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && 2440 support.getById && context.nodeType === 9 && documentIsHTML && 2441 Expr.relative[ tokens[1].type ] ) { 2442 2443 context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0]; 2444 if ( !context ) { 2445 return results; 2446 } 2447 selector = selector.slice( tokens.shift().value.length ); 2448 } 2449 2450 // Fetch a seed set for right-to-left matching 2451 i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length; 2452 while ( i-- ) { 2453 token = tokens[i]; 2454 2455 // Abort if we hit a combinator 2456 if ( Expr.relative[ (type = token.type) ] ) { 2457 break; 2458 } 2459 if ( (find = Expr.find[ type ]) ) { 2460 // Search, expanding context for leading sibling combinators 2461 if ( (seed = find( 2462 token.matches[0].replace( runescape, funescape ),
vendor: 15,344 bytes, lines 2463-3035
2463 rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context 2464 )) ) { 2465 2466 // If seed is empty or no tokens remain, we can return early 2467 tokens.splice( i, 1 ); 2468 selector = seed.length && toSelector( tokens ); 2469 if ( !selector ) { 2470 push.apply( results, seed ); 2471 return results; 2472 } 2473 2474 break; 2475 } 2476 } 2477 } 2478 } 2479 } 2480 2481 // Compile and execute a filtering function 2482 // Provide `match` to avoid retokenization if we modified the selector above 2483 compile( selector, match )( 2484 seed, 2485 context, 2486 !documentIsHTML, 2487 results, 2488 rsibling.test( selector ) && testContext( context.parentNode ) || context 2489 ); 2490 return results; 2491} 2492 2493// One-time assignments 2494 2495// Sort stability 2496support.sortStable = expando.split("").sort( sortOrder ).join("") === expando; 2497 2498// Support: Chrome<14 2499// Always assume duplicates if they aren't passed to the comparison function 2500support.detectDuplicates = !!hasDuplicate; 2501 2502// Initialize against the default document 2503setDocument(); 2504 2505// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) 2506// Detached nodes confoundingly follow *each other* 2507support.sortDetached = assert(function( div1 ) { 2508 // Should return 1, but returns 4 (following) 2509 return div1.compareDocumentPosition( document.createElement("div") ) & 1; 2510}); 2511 2512// Support: IE<8 2513// Prevent attribute/property "interpolation" 2514// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx 2515if ( !assert(function( div ) { 2516 div.innerHTML = "<a href='#'></a>"; 2517 return div.firstChild.getAttribute("href") === "#" ; 2518}) ) { 2519 addHandle( "type|href|height|width", function( elem, name, isXML ) { 2520 if ( !isXML ) { 2521 return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); 2522 } 2523 }); 2524} 2525 2526// Support: IE<9 2527// Use defaultValue in place of getAttribute("value") 2528if ( !support.attributes || !assert(function( div ) { 2529 div.innerHTML = "<input/>"; 2530 div.firstChild.setAttribute( "value", "" ); 2531 return div.firstChild.getAttribute( "value" ) === ""; 2532}) ) { 2533 addHandle( "value", function( elem, name, isXML ) { 2534 if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { 2535 return elem.defaultValue; 2536 } 2537 }); 2538} 2539 2540// Support: IE<9 2541// Use getAttributeNode to fetch booleans when getAttribute lies 2542if ( !assert(function( div ) { 2543 return div.getAttribute("disabled") == null; 2544}) ) { 2545 addHandle( booleans, function( elem, name, isXML ) { 2546 var val; 2547 if ( !isXML ) { 2548 return elem[ name ] === true ? name.toLowerCase() : 2549 (val = elem.getAttributeNode( name )) && val.specified ? 2550 val.value : 2551 null; 2552 } 2553 }); 2554} 2555 2556return Sizzle; 2557 2558})( window ); 2559 2560 2561 2562jQuery.find = Sizzle; 2563jQuery.expr = Sizzle.selectors; 2564jQuery.expr[":"] = jQuery.expr.pseudos; 2565jQuery.unique = Sizzle.uniqueSort; 2566jQuery.text = Sizzle.getText; 2567jQuery.isXMLDoc = Sizzle.isXML; 2568jQuery.contains = Sizzle.contains; 2569 2570 2571 2572var rneedsContext = jQuery.expr.match.needsContext; 2573 2574var rsingleTag = (/^<(\w+)\s*\/?>(?:<\/\1>|)$/); 2575 2576 2577 2578var risSimple = /^.[^:#\[\.,]*$/; 2579 2580// Implement the identical functionality for filter and not 2581function winnow( elements, qualifier, not ) { 2582 if ( jQuery.isFunction( qualifier ) ) { 2583 return jQuery.grep( elements, function( elem, i ) { 2584 /* jshint -W018 */ 2585 return !!qualifier.call( elem, i, elem ) !== not; 2586 }); 2587 2588 } 2589 2590 if ( qualifier.nodeType ) { 2591 return jQuery.grep( elements, function( elem ) { 2592 return ( elem === qualifier ) !== not; 2593 }); 2594 2595 } 2596 2597 if ( typeof qualifier === "string" ) { 2598 if ( risSimple.test( qualifier ) ) { 2599 return jQuery.filter( qualifier, elements, not ); 2600 } 2601 2602 qualifier = jQuery.filter( qualifier, elements ); 2603 } 2604 2605 return jQuery.grep( elements, function( elem ) { 2606 return ( indexOf.call( qualifier, elem ) >= 0 ) !== not; 2607 }); 2608} 2609 2610jQuery.filter = function( expr, elems, not ) { 2611 var elem = elems[ 0 ]; 2612 2613 if ( not ) { 2614 expr = ":not(" + expr + ")"; 2615 } 2616 2617 return elems.length === 1 && elem.nodeType === 1 ? 2618 jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] : 2619 jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { 2620 return elem.nodeType === 1; 2621 })); 2622}; 2623 2624jQuery.fn.extend({ 2625 find: function( selector ) { 2626 var i, 2627 len = this.length, 2628 ret = [], 2629 self = this; 2630 2631 if ( typeof selector !== "string" ) { 2632 return this.pushStack( jQuery( selector ).filter(function() { 2633 for ( i = 0; i < len; i++ ) { 2634 if ( jQuery.contains( self[ i ], this ) ) { 2635 return true; 2636 } 2637 } 2638 }) ); 2639 } 2640 2641 for ( i = 0; i < len; i++ ) { 2642 jQuery.find( selector, self[ i ], ret ); 2643 } 2644 2645 // Needed because $( selector, context ) becomes $( context ).find( selector ) 2646 ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret ); 2647 ret.selector = this.selector ? this.selector + " " + selector : selector; 2648 return ret; 2649 }, 2650 filter: function( selector ) { 2651 return this.pushStack( winnow(this, selector || [], false) ); 2652 }, 2653 not: function( selector ) { 2654 return this.pushStack( winnow(this, selector || [], true) ); 2655 }, 2656 is: function( selector ) { 2657 return !!winnow( 2658 this, 2659 2660 // If this is a positional/relative selector, check membership in the returned set 2661 // so $("p:first").is("p:last") won't return true for a doc with two "p". 2662 typeof selector === "string" && rneedsContext.test( selector ) ? 2663 jQuery( selector ) : 2664 selector || [], 2665 false 2666 ).length; 2667 } 2668}); 2669 2670 2671// Initialize a jQuery object 2672 2673 2674// A central reference to the root jQuery(document) 2675var rootjQuery, 2676 2677 // A simple way to check for HTML strings 2678 // Prioritize #id over <tag> to avoid XSS via location.hash (#9521) 2679 // Strict HTML recognition (#11290: must start with <) 2680 rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/, 2681 2682 init = jQuery.fn.init = function( selector, context ) { 2683 var match, elem; 2684 2685 // HANDLE: $(""), $(null), $(undefined), $(false) 2686 if ( !selector ) { 2687 return this; 2688 } 2689 2690 // Handle HTML strings 2691 if ( typeof selector === "string" ) { 2692 if ( selector[0] === "<" && selector[ selector.length - 1 ] === ">" && selector.length >= 3 ) { 2693 // Assume that strings that start and end with <> are HTML and skip the regex check 2694 match = [ null, selector, null ]; 2695 2696 } else { 2697 match = rquickExpr.exec( selector ); 2698 } 2699 2700 // Match html or make sure no context is specified for #id 2701 if ( match && (match[1] || !context) ) { 2702 2703 // HANDLE: $(html) -> $(array) 2704 if ( match[1] ) { 2705 context = context instanceof jQuery ? context[0] : context; 2706 2707 // scripts is true for back-compat 2708 // Intentionally let the error be thrown if parseHTML is not present 2709 jQuery.merge( this, jQuery.parseHTML( 2710 match[1], 2711 context && context.nodeType ? context.ownerDocument || context : document, 2712 true 2713 ) ); 2714 2715 // HANDLE: $(html, props) 2716 if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) { 2717 for ( match in context ) { 2718 // Properties of context are called as methods if possible 2719 if ( jQuery.isFunction( this[ match ] ) ) { 2720 this[ match ]( context[ match ] ); 2721 2722 // ...and otherwise set as attributes 2723 } else { 2724 this.attr( match, context[ match ] ); 2725 } 2726 } 2727 } 2728 2729 return this; 2730 2731 // HANDLE: $(#id) 2732 } else { 2733 elem = document.getElementById( match[2] ); 2734 2735 // Check parentNode to catch when Blackberry 4.6 returns 2736 // nodes that are no longer in the document #6963 2737 if ( elem && elem.parentNode ) { 2738 // Inject the element directly into the jQuery object 2739 this.length = 1; 2740 this[0] = elem; 2741 } 2742 2743 this.context = document; 2744 this.selector = selector; 2745 return this; 2746 } 2747 2748 // HANDLE: $(expr, $(...)) 2749 } else if ( !context || context.jquery ) { 2750 return ( context || rootjQuery ).find( selector ); 2751 2752 // HANDLE: $(expr, context) 2753 // (which is just equivalent to: $(context).find(expr) 2754 } else { 2755 return this.constructor( context ).find( selector ); 2756 } 2757 2758 // HANDLE: $(DOMElement) 2759 } else if ( selector.nodeType ) { 2760 this.context = this[0] = selector; 2761 this.length = 1; 2762 return this; 2763 2764 // HANDLE: $(function) 2765 // Shortcut for document ready 2766 } else if ( jQuery.isFunction( selector ) ) { 2767 return typeof rootjQuery.ready !== "undefined" ? 2768 rootjQuery.ready( selector ) : 2769 // Execute immediately if ready is not present 2770 selector( jQuery ); 2771 } 2772 2773 if ( selector.selector !== undefined ) { 2774 this.selector = selector.selector; 2775 this.context = selector.context; 2776 } 2777 2778 return jQuery.makeArray( selector, this ); 2779 }; 2780 2781// Give the init function the jQuery prototype for later instantiation 2782init.prototype = jQuery.fn; 2783 2784// Initialize central reference 2785rootjQuery = jQuery( document ); 2786 2787 2788var rparentsprev = /^(?:parents|prev(?:Until|All))/, 2789 // methods guaranteed to produce a unique set when starting from a unique set 2790 guaranteedUnique = { 2791 children: true, 2792 contents: true, 2793 next: true, 2794 prev: true 2795 }; 2796 2797jQuery.extend({ 2798 dir: function( elem, dir, until ) { 2799 var matched = [], 2800 truncate = until !== undefined; 2801 2802 while ( (elem = elem[ dir ]) && elem.nodeType !== 9 ) { 2803 if ( elem.nodeType === 1 ) { 2804 if ( truncate && jQuery( elem ).is( until ) ) { 2805 break; 2806 } 2807 matched.push( elem ); 2808 } 2809 } 2810 return matched; 2811 }, 2812 2813 sibling: function( n, elem ) { 2814 var matched = []; 2815 2816 for ( ; n; n = n.nextSibling ) { 2817 if ( n.nodeType === 1 && n !== elem ) { 2818 matched.push( n ); 2819 } 2820 } 2821 2822 return matched; 2823 } 2824}); 2825 2826jQuery.fn.extend({ 2827 has: function( target ) { 2828 var targets = jQuery( target, this ), 2829 l = targets.length; 2830 2831 return this.filter(function() { 2832 var i = 0; 2833 for ( ; i < l; i++ ) { 2834 if ( jQuery.contains( this, targets[i] ) ) { 2835 return true; 2836 } 2837 } 2838 }); 2839 }, 2840 2841 closest: function( selectors, context ) { 2842 var cur, 2843 i = 0, 2844 l = this.length, 2845 matched = [], 2846 pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ? 2847 jQuery( selectors, context || this.context ) : 2848 0; 2849 2850 for ( ; i < l; i++ ) { 2851 for ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) { 2852 // Always skip document fragments 2853 if ( cur.nodeType < 11 && (pos ? 2854 pos.index(cur) > -1 : 2855 2856 // Don't pass non-elements to Sizzle 2857 cur.nodeType === 1 && 2858 jQuery.find.matchesSelector(cur, selectors)) ) { 2859 2860 matched.push( cur ); 2861 break; 2862 } 2863 } 2864 } 2865 2866 return this.pushStack( matched.length > 1 ? jQuery.unique( matched ) : matched ); 2867 }, 2868 2869 // Determine the position of an element within 2870 // the matched set of elements 2871 index: function( elem ) { 2872 2873 // No argument, return index in parent 2874 if ( !elem ) { 2875 return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1; 2876 } 2877 2878 // index in selector 2879 if ( typeof elem === "string" ) { 2880 return indexOf.call( jQuery( elem ), this[ 0 ] ); 2881 } 2882 2883 // Locate the position of the desired element 2884 return indexOf.call( this, 2885 2886 // If it receives a jQuery object, the first element is used 2887 elem.jquery ? elem[ 0 ] : elem 2888 ); 2889 }, 2890 2891 add: function( selector, context ) { 2892 return this.pushStack( 2893 jQuery.unique( 2894 jQuery.merge( this.get(), jQuery( selector, context ) ) 2895 ) 2896 ); 2897 }, 2898 2899 addBack: function( selector ) { 2900 return this.add( selector == null ? 2901 this.prevObject : this.prevObject.filter(selector) 2902 ); 2903 } 2904}); 2905 2906function sibling( cur, dir ) { 2907 while ( (cur = cur[dir]) && cur.nodeType !== 1 ) {} 2908 return cur; 2909} 2910 2911jQuery.each({ 2912 parent: function( elem ) { 2913 var parent = elem.parentNode; 2914 return parent && parent.nodeType !== 11 ? parent : null; 2915 }, 2916 parents: function( elem ) { 2917 return jQuery.dir( elem, "parentNode" ); 2918 }, 2919 parentsUntil: function( elem, i, until ) { 2920 return jQuery.dir( elem, "parentNode", until ); 2921 }, 2922 next: function( elem ) { 2923 return sibling( elem, "nextSibling" ); 2924 }, 2925 prev: function( elem ) { 2926 return sibling( elem, "previousSibling" ); 2927 }, 2928 nextAll: function( elem ) { 2929 return jQuery.dir( elem, "nextSibling" ); 2930 }, 2931 prevAll: function( elem ) { 2932 return jQuery.dir( elem, "previousSibling" ); 2933 }, 2934 nextUntil: function( elem, i, until ) { 2935 return jQuery.dir( elem, "nextSibling", until ); 2936 }, 2937 prevUntil: function( elem, i, until ) { 2938 return jQuery.dir( elem, "previousSibling", until ); 2939 }, 2940 siblings: function( elem ) { 2941 return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem ); 2942 }, 2943 children: function( elem ) { 2944 return jQuery.sibling( elem.firstChild ); 2945 }, 2946 contents: function( elem ) { 2947 return elem.contentDocument || jQuery.merge( [], elem.childNodes ); 2948 } 2949}, function( name, fn ) { 2950 jQuery.fn[ name ] = function( until, selector ) { 2951 var matched = jQuery.map( this, fn, until ); 2952 2953 if ( name.slice( -5 ) !== "Until" ) { 2954 selector = until; 2955 } 2956 2957 if ( selector && typeof selector === "string" ) { 2958 matched = jQuery.filter( selector, matched ); 2959 } 2960 2961 if ( this.length > 1 ) { 2962 // Remove duplicates 2963 if ( !guaranteedUnique[ name ] ) { 2964 jQuery.unique( matched ); 2965 } 2966 2967 // Reverse order for parents* and prev-derivatives 2968 if ( rparentsprev.test( name ) ) { 2969 matched.reverse(); 2970 } 2971 } 2972 2973 return this.pushStack( matched ); 2974 }; 2975}); 2976var rnotwhite = (/\S+/g); 2977 2978 2979 2980// String to Object options format cache 2981var optionsCache = {}; 2982 2983// Convert String-formatted options into Object-formatted ones and store in cache 2984function createOptions( options ) { 2985 var object = optionsCache[ options ] = {}; 2986 jQuery.each( options.match( rnotwhite ) || [], function( _, flag ) { 2987 object[ flag ] = true; 2988 }); 2989 return object; 2990} 2991 2992/* 2993 * Create a callback list using the following parameters: 2994 * 2995 * options: an optional list of space-separated options that will change how 2996 * the callback list behaves or a more traditional option object 2997 * 2998 * By default a callback list will act like an event callback list and can be 2999 * "fired" multiple times. 3000 * 3001 * Possible options: 3002 * 3003 * once: will ensure the callback list can only be fired once (like a Deferred) 3004 * 3005 * memory: will keep track of previous values and will call any callback added 3006 * after the list has been fired right away with the latest "memorized" 3007 * values (like a Deferred) 3008 * 3009 * unique: will ensure a callback can only be added once (no duplicate in the list) 3010 * 3011 * stopOnFalse: interrupt callings when a callback returns false 3012 * 3013 */ 3014jQuery.Callbacks = function( options ) { 3015 3016 // Convert options from String-formatted to Object-formatted if needed 3017 // (we check in cache first) 3018 options = typeof options === "string" ? 3019 ( optionsCache[ options ] || createOptions( options ) ) : 3020 jQuery.extend( {}, options ); 3021 3022 var // Last fire value (for non-forgettable lists) 3023 memory, 3024 // Flag to know if list was already fired 3025 fired, 3026 // Flag to know if list is currently firing 3027 firing, 3028 // First callback to fire (used internally by add and fireWith) 3029 firingStart, 3030 // End of the loop when firing 3031 firingLength, 3032 // Index of currently firing callback (modified by remove if needed) 3033 firingIndex, 3034 // Actual callback list 3035 list = [],
vendor: 5,061 bytes, lines 3036-3213
3036 // Stack of fire calls for repeatable lists 3037 stack = !options.once && [], 3038 // Fire callbacks 3039 fire = function( data ) { 3040 memory = options.memory && data; 3041 fired = true; 3042 firingIndex = firingStart || 0; 3043 firingStart = 0; 3044 firingLength = list.length; 3045 firing = true; 3046 for ( ; list && firingIndex < firingLength; firingIndex++ ) { 3047 if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) { 3048 memory = false; // To prevent further calls using add 3049 break; 3050 } 3051 } 3052 firing = false; 3053 if ( list ) { 3054 if ( stack ) { 3055 if ( stack.length ) { 3056 fire( stack.shift() ); 3057 } 3058 } else if ( memory ) { 3059 list = []; 3060 } else { 3061 self.disable(); 3062 } 3063 } 3064 }, 3065 // Actual Callbacks object 3066 self = { 3067 // Add a callback or a collection of callbacks to the list 3068 add: function() { 3069 if ( list ) { 3070 // First, we save the current length 3071 var start = list.length; 3072 (function add( args ) { 3073 jQuery.each( args, function( _, arg ) { 3074 var type = jQuery.type( arg ); 3075 if ( type === "function" ) { 3076 if ( !options.unique || !self.has( arg ) ) { 3077 list.push( arg ); 3078 } 3079 } else if ( arg && arg.length && type !== "string" ) { 3080 // Inspect recursively 3081 add( arg ); 3082 } 3083 }); 3084 })( arguments ); 3085 // Do we need to add the callbacks to the 3086 // current firing batch? 3087 if ( firing ) { 3088 firingLength = list.length; 3089 // With memory, if we're not firing then 3090 // we should call right away 3091 } else if ( memory ) { 3092 firingStart = start; 3093 fire( memory ); 3094 } 3095 } 3096 return this; 3097 }, 3098 // Remove a callback from the list 3099 remove: function() { 3100 if ( list ) { 3101 jQuery.each( arguments, function( _, arg ) { 3102 var index; 3103 while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { 3104 list.splice( index, 1 ); 3105 // Handle firing indexes 3106 if ( firing ) { 3107 if ( index <= firingLength ) { 3108 firingLength--; 3109 } 3110 if ( index <= firingIndex ) { 3111 firingIndex--; 3112 } 3113 } 3114 } 3115 }); 3116 } 3117 return this; 3118 }, 3119 // Check if a given callback is in the list. 3120 // If no argument is given, return whether or not list has callbacks attached. 3121 has: function( fn ) { 3122 return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length ); 3123 }, 3124 // Remove all callbacks from the list 3125 empty: function() { 3126 list = []; 3127 firingLength = 0; 3128 return this; 3129 }, 3130 // Have the list do nothing anymore 3131 disable: function() { 3132 list = stack = memory = undefined; 3133 return this; 3134 }, 3135 // Is it disabled? 3136 disabled: function() { 3137 return !list; 3138 }, 3139 // Lock the list in its current state 3140 lock: function() { 3141 stack = undefined; 3142 if ( !memory ) { 3143 self.disable(); 3144 } 3145 return this; 3146 }, 3147 // Is it locked? 3148 locked: function() { 3149 return !stack; 3150 }, 3151 // Call all callbacks with the given context and arguments 3152 fireWith: function( context, args ) { 3153 if ( list && ( !fired || stack ) ) { 3154 args = args || []; 3155 args = [ context, args.slice ? args.slice() : args ]; 3156 if ( firing ) { 3157 stack.push( args ); 3158 } else { 3159 fire( args ); 3160 } 3161 } 3162 return this; 3163 }, 3164 // Call all the callbacks with the given arguments 3165 fire: function() { 3166 self.fireWith( this, arguments ); 3167 return this; 3168 }, 3169 // To know if the callbacks have already been called at least once 3170 fired: function() { 3171 return !!fired; 3172 } 3173 }; 3174 3175 return self; 3176}; 3177 3178 3179jQuery.extend({ 3180 3181 Deferred: function( func ) { 3182 var tuples = [ 3183 // action, add listener, listener list, final state 3184 [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ], 3185 [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ], 3186 [ "notify", "progress", jQuery.Callbacks("memory") ] 3187 ], 3188 state = "pending", 3189 promise = { 3190 state: function() { 3191 return state; 3192 }, 3193 always: function() { 3194 deferred.done( arguments ).fail( arguments ); 3195 return this; 3196 }, 3197 then: function( /* fnDone, fnFail, fnProgress */ ) { 3198 var fns = arguments; 3199 return jQuery.Deferred(function( newDefer ) { 3200 jQuery.each( tuples, function( i, tuple ) { 3201 var fn = jQuery.isFunction( fns[ i ] ) && fns[ i ]; 3202 // deferred[ done | fail | progress ] for forwarding actions to newDefer 3203 deferred[ tuple[1] ](function() { 3204 var returned = fn && fn.apply( this, arguments ); 3205 if ( returned && jQuery.isFunction( returned.promise ) ) { 3206 returned.promise() 3207 .done( newDefer.resolve ) 3208 .fail( newDefer.reject ) 3209 .progress( newDefer.notify ); 3210 } else { 3211 newDefer[ tuple[ 0 ] + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments ); 3212 } 3213 });
vendor: 4,082 bytes, lines 3214-3363
3214 }); 3215 fns = null; 3216 }).promise(); 3217 }, 3218 // Get a promise for this deferred 3219 // If obj is provided, the promise aspect is added to the object 3220 promise: function( obj ) { 3221 return obj != null ? jQuery.extend( obj, promise ) : promise; 3222 } 3223 }, 3224 deferred = {}; 3225 3226 // Keep pipe for back-compat 3227 promise.pipe = promise.then; 3228 3229 // Add list-specific methods 3230 jQuery.each( tuples, function( i, tuple ) { 3231 var list = tuple[ 2 ], 3232 stateString = tuple[ 3 ]; 3233 3234 // promise[ done | fail | progress ] = list.add 3235 promise[ tuple[1] ] = list.add; 3236 3237 // Handle state 3238 if ( stateString ) { 3239 list.add(function() { 3240 // state = [ resolved | rejected ] 3241 state = stateString; 3242 3243 // [ reject_list | resolve_list ].disable; progress_list.lock 3244 }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock ); 3245 } 3246 3247 // deferred[ resolve | reject | notify ] 3248 deferred[ tuple[0] ] = function() { 3249 deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments ); 3250 return this; 3251 }; 3252 deferred[ tuple[0] + "With" ] = list.fireWith; 3253 }); 3254 3255 // Make the deferred a promise 3256 promise.promise( deferred ); 3257 3258 // Call given func if any 3259 if ( func ) { 3260 func.call( deferred, deferred ); 3261 } 3262 3263 // All done! 3264 return deferred; 3265 }, 3266 3267 // Deferred helper 3268 when: function( subordinate /* , ..., subordinateN */ ) { 3269 var i = 0, 3270 resolveValues = slice.call( arguments ), 3271 length = resolveValues.length, 3272 3273 // the count of uncompleted subordinates 3274 remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0, 3275 3276 // the master Deferred. If resolveValues consist of only a single Deferred, just use that. 3277 deferred = remaining === 1 ? subordinate : jQuery.Deferred(), 3278 3279 // Update function for both resolve and progress values 3280 updateFunc = function( i, contexts, values ) { 3281 return function( value ) { 3282 contexts[ i ] = this; 3283 values[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; 3284 if ( values === progressValues ) { 3285 deferred.notifyWith( contexts, values ); 3286 } else if ( !( --remaining ) ) { 3287 deferred.resolveWith( contexts, values ); 3288 } 3289 }; 3290 }, 3291 3292 progressValues, progressContexts, resolveContexts; 3293 3294 // add listeners to Deferred subordinates; treat others as resolved 3295 if ( length > 1 ) { 3296 progressValues = new Array( length ); 3297 progressContexts = new Array( length ); 3298 resolveContexts = new Array( length ); 3299 for ( ; i < length; i++ ) { 3300 if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) { 3301 resolveValues[ i ].promise() 3302 .done( updateFunc( i, resolveContexts, resolveValues ) ) 3303 .fail( deferred.reject ) 3304 .progress( updateFunc( i, progressContexts, progressValues ) ); 3305 } else { 3306 --remaining; 3307 } 3308 } 3309 } 3310 3311 // if we're not waiting on anything, resolve the master 3312 if ( !remaining ) { 3313 deferred.resolveWith( resolveContexts, resolveValues ); 3314 } 3315 3316 return deferred.promise(); 3317 } 3318}); 3319 3320 3321// The deferred used on DOM ready 3322var readyList; 3323 3324jQuery.fn.ready = function( fn ) { 3325 // Add the callback 3326 jQuery.ready.promise().done( fn ); 3327 3328 return this; 3329}; 3330 3331jQuery.extend({ 3332 // Is the DOM ready to be used? Set to true once it occurs. 3333 isReady: false, 3334 3335 // A counter to track how many items to wait for before 3336 // the ready event fires. See #6781 3337 readyWait: 1, 3338 3339 // Hold (or release) the ready event 3340 holdReady: function( hold ) { 3341 if ( hold ) { 3342 jQuery.readyWait++; 3343 } else { 3344 jQuery.ready( true ); 3345 } 3346 }, 3347 3348 // Handle when the DOM is ready 3349 ready: function( wait ) { 3350 3351 // Abort if there are pending holds or we're already ready 3352 if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { 3353 return; 3354 } 3355 3356 // Remember that the DOM is ready 3357 jQuery.isReady = true; 3358 3359 // If a normal DOM Ready event fired, decrement, and wait if need be 3360 if ( wait !== true && --jQuery.readyWait > 0 ) { 3361 return; 3362 } 3363
vendor: 4,755 bytes, lines 3364-3549
3364 // If there are functions bound, to execute 3365 readyList.resolveWith( document, [ jQuery ] ); 3366 3367 // Trigger any bound ready events 3368 if ( jQuery.fn.trigger ) { 3369 jQuery( document ).trigger("ready").off("ready"); 3370 } 3371 } 3372}); 3373 3374/** 3375 * The ready event handler and self cleanup method 3376 */ 3377function completed() { 3378 document.removeEventListener( "DOMContentLoaded", completed, false ); 3379 window.removeEventListener( "load", completed, false ); 3380 jQuery.ready(); 3381} 3382 3383jQuery.ready.promise = function( obj ) { 3384 if ( !readyList ) { 3385 3386 readyList = jQuery.Deferred(); 3387 3388 // Catch cases where $(document).ready() is called after the browser event has already occurred. 3389 // we once tried to use readyState "interactive" here, but it caused issues like the one 3390 // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15 3391 if ( document.readyState === "complete" ) { 3392 // Handle it asynchronously to allow scripts the opportunity to delay ready 3393 setTimeout( jQuery.ready ); 3394 3395 } else { 3396 3397 // Use the handy event callback 3398 document.addEventListener( "DOMContentLoaded", completed, false ); 3399 3400 // A fallback to window.onload, that will always work 3401 window.addEventListener( "load", completed, false ); 3402 } 3403 } 3404 return readyList.promise( obj ); 3405}; 3406 3407// Kick off the DOM ready check even if the user does not 3408jQuery.ready.promise(); 3409 3410 3411 3412 3413// Multifunctional method to get and set values of a collection 3414// The value/s can optionally be executed if it's a function 3415var access = jQuery.access = function( elems, fn, key, value, chainable, emptyGet, raw ) { 3416 var i = 0, 3417 len = elems.length, 3418 bulk = key == null; 3419 3420 // Sets many values 3421 if ( jQuery.type( key ) === "object" ) { 3422 chainable = true; 3423 for ( i in key ) { 3424 jQuery.access( elems, fn, i, key[i], true, emptyGet, raw ); 3425 } 3426 3427 // Sets one value 3428 } else if ( value !== undefined ) { 3429 chainable = true; 3430 3431 if ( !jQuery.isFunction( value ) ) { 3432 raw = true; 3433 } 3434 3435 if ( bulk ) { 3436 // Bulk operations run against the entire set 3437 if ( raw ) { 3438 fn.call( elems, value ); 3439 fn = null; 3440 3441 // ...except when executing function values 3442 } else { 3443 bulk = fn; 3444 fn = function( elem, key, value ) { 3445 return bulk.call( jQuery( elem ), value ); 3446 }; 3447 } 3448 } 3449 3450 if ( fn ) { 3451 for ( ; i < len; i++ ) { 3452 fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) ); 3453 } 3454 } 3455 } 3456 3457 return chainable ? 3458 elems : 3459 3460 // Gets 3461 bulk ? 3462 fn.call( elems ) : 3463 len ? fn( elems[0], key ) : emptyGet; 3464}; 3465 3466 3467/** 3468 * Determines whether an object can have data 3469 */ 3470jQuery.acceptData = function( owner ) { 3471 // Accepts only: 3472 // - Node 3473 // - Node.ELEMENT_NODE 3474 // - Node.DOCUMENT_NODE 3475 // - Object 3476 // - Any 3477 /* jshint -W018 */ 3478 return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType ); 3479}; 3480 3481 3482function Data() { 3483 // Support: Android < 4, 3484 // Old WebKit does not have Object.preventExtensions/freeze method, 3485 // return new empty object instead with no [[set]] accessor 3486 Object.defineProperty( this.cache = {}, 0, { 3487 get: function() { 3488 return {}; 3489 } 3490 }); 3491 3492 this.expando = jQuery.expando + Math.random(); 3493} 3494 3495Data.uid = 1; 3496Data.accepts = jQuery.acceptData; 3497 3498Data.prototype = { 3499 key: function( owner ) { 3500 // We can accept data for non-element nodes in modern browsers, 3501 // but we should not, see #8335. 3502 // Always return the key for a frozen object. 3503 if ( !Data.accepts( owner ) ) { 3504 return 0; 3505 } 3506 3507 var descriptor = {}, 3508 // Check if the owner object already has a cache key 3509 unlock = owner[ this.expando ]; 3510 3511 // If not, create one 3512 if ( !unlock ) { 3513 unlock = Data.uid++; 3514 3515 // Secure it in a non-enumerable, non-writable property 3516 try { 3517 descriptor[ this.expando ] = { value: unlock }; 3518 Object.defineProperties( owner, descriptor ); 3519 3520 // Support: Android < 4 3521 // Fallback to a less secure definition 3522 } catch ( e ) { 3523 descriptor[ this.expando ] = unlock; 3524 jQuery.extend( owner, descriptor ); 3525 } 3526 } 3527 3528 // Ensure the cache object 3529 if ( !this.cache[ unlock ] ) { 3530 this.cache[ unlock ] = {}; 3531 } 3532 3533 return unlock; 3534 }, 3535 set: function( owner, data, value ) { 3536 var prop, 3537 // There may be an unlock assigned to this node, 3538 // if there is no entry for this "owner", create one inline 3539 // and set the unlock as though an owner entry had always existed 3540 unlock = this.key( owner ), 3541 cache = this.cache[ unlock ]; 3542 3543 // Handle: [ owner, key, value ] args 3544 if ( typeof data === "string" ) { 3545 cache[ data ] = value; 3546 3547 // Handle: [ owner, { properties } ] args 3548 } else { 3549 // Fresh assignments by object are shallow copied
vendor: 111,241 bytes, lines 3550-7520
3550 if ( jQuery.isEmptyObject( cache ) ) { 3551 jQuery.extend( this.cache[ unlock ], data ); 3552 // Otherwise, copy the properties one-by-one to the cache object 3553 } else { 3554 for ( prop in data ) { 3555 cache[ prop ] = data[ prop ]; 3556 } 3557 } 3558 } 3559 return cache; 3560 }, 3561 get: function( owner, key ) { 3562 // Either a valid cache is found, or will be created. 3563 // New caches will be created and the unlock returned, 3564 // allowing direct access to the newly created 3565 // empty data object. A valid owner object must be provided. 3566 var cache = this.cache[ this.key( owner ) ]; 3567 3568 return key === undefined ? 3569 cache : cache[ key ]; 3570 }, 3571 access: function( owner, key, value ) { 3572 var stored; 3573 // In cases where either: 3574 // 3575 // 1. No key was specified 3576 // 2. A string key was specified, but no value provided 3577 // 3578 // Take the "read" path and allow the get method to determine 3579 // which value to return, respectively either: 3580 // 3581 // 1. The entire cache object 3582 // 2. The data stored at the key 3583 // 3584 if ( key === undefined || 3585 ((key && typeof key === "string") && value === undefined) ) { 3586 3587 stored = this.get( owner, key ); 3588 3589 return stored !== undefined ? 3590 stored : this.get( owner, jQuery.camelCase(key) ); 3591 } 3592 3593 // [*]When the key is not a string, or both a key and value 3594 // are specified, set or extend (existing objects) with either: 3595 // 3596 // 1. An object of properties 3597 // 2. A key and value 3598 // 3599 this.set( owner, key, value ); 3600 3601 // Since the "set" path can have two possible entry points 3602 // return the expected data based on which path was taken[*] 3603 return value !== undefined ? value : key; 3604 }, 3605 remove: function( owner, key ) { 3606 var i, name, camel, 3607 unlock = this.key( owner ), 3608 cache = this.cache[ unlock ]; 3609 3610 if ( key === undefined ) { 3611 this.cache[ unlock ] = {}; 3612 3613 } else { 3614 // Support array or space separated string of keys 3615 if ( jQuery.isArray( key ) ) { 3616 // If "name" is an array of keys... 3617 // When data is initially created, via ("key", "val") signature, 3618 // keys will be converted to camelCase. 3619 // Since there is no way to tell _how_ a key was added, remove 3620 // both plain key and camelCase key. #12786 3621 // This will only penalize the array argument path. 3622 name = key.concat( key.map( jQuery.camelCase ) ); 3623 } else { 3624 camel = jQuery.camelCase( key ); 3625 // Try the string as a key before any manipulation 3626 if ( key in cache ) { 3627 name = [ key, camel ]; 3628 } else { 3629 // If a key with the spaces exists, use it. 3630 // Otherwise, create an array by matching non-whitespace 3631 name = camel; 3632 name = name in cache ? 3633 [ name ] : ( name.match( rnotwhite ) || [] ); 3634 } 3635 } 3636 3637 i = name.length; 3638 while ( i-- ) { 3639 delete cache[ name[ i ] ]; 3640 } 3641 } 3642 }, 3643 hasData: function( owner ) { 3644 return !jQuery.isEmptyObject( 3645 this.cache[ owner[ this.expando ] ] || {} 3646 ); 3647 }, 3648 discard: function( owner ) { 3649 if ( owner[ this.expando ] ) { 3650 delete this.cache[ owner[ this.expando ] ]; 3651 } 3652 } 3653}; 3654var data_priv = new Data(); 3655 3656var data_user = new Data(); 3657 3658 3659 3660/* 3661 Implementation Summary 3662 3663 1. Enforce API surface and semantic compatibility with 1.9.x branch 3664 2. Improve the module's maintainability by reducing the storage 3665 paths to a single mechanism. 3666 3. Use the same single mechanism to support "private" and "user" data. 3667 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData) 3668 5. Avoid exposing implementation details on user objects (eg. expando properties) 3669 6. Provide a clear path for implementation upgrade to WeakMap in 2014 3670*/ 3671var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, 3672 rmultiDash = /([A-Z])/g; 3673 3674function dataAttr( elem, key, data ) { 3675 var name; 3676 3677 // If nothing was found internally, try to fetch any 3678 // data from the HTML5 data-* attribute 3679 if ( data === undefined && elem.nodeType === 1 ) { 3680 name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase(); 3681 data = elem.getAttribute( name ); 3682 3683 if ( typeof data === "string" ) { 3684 try { 3685 data = data === "true" ? true : 3686 data === "false" ? false : 3687 data === "null" ? null : 3688 // Only convert to a number if it doesn't change the string 3689 +data + "" === data ? +data : 3690 rbrace.test( data ) ? jQuery.parseJSON( data ) : 3691 data; 3692 } catch( e ) {} 3693 3694 // Make sure we set the data so it isn't changed later 3695 data_user.set( elem, key, data ); 3696 } else { 3697 data = undefined; 3698 } 3699 } 3700 return data; 3701} 3702 3703jQuery.extend({ 3704 hasData: function( elem ) { 3705 return data_user.hasData( elem ) || data_priv.hasData( elem ); 3706 }, 3707 3708 data: function( elem, name, data ) { 3709 return data_user.access( elem, name, data ); 3710 }, 3711 3712 removeData: function( elem, name ) { 3713 data_user.remove( elem, name ); 3714 }, 3715 3716 // TODO: Now that all calls to _data and _removeData have been replaced 3717 // with direct calls to data_priv methods, these can be deprecated. 3718 _data: function( elem, name, data ) { 3719 return data_priv.access( elem, name, data ); 3720 }, 3721 3722 _removeData: function( elem, name ) { 3723 data_priv.remove( elem, name ); 3724 } 3725}); 3726 3727jQuery.fn.extend({ 3728 data: function( key, value ) { 3729 var i, name, data, 3730 elem = this[ 0 ], 3731 attrs = elem && elem.attributes; 3732 3733 // Gets all values 3734 if ( key === undefined ) { 3735 if ( this.length ) { 3736 data = data_user.get( elem ); 3737 3738 if ( elem.nodeType === 1 && !data_priv.get( elem, "hasDataAttrs" ) ) { 3739 i = attrs.length; 3740 while ( i-- ) { 3741 name = attrs[ i ].name; 3742 3743 if ( name.indexOf( "data-" ) === 0 ) { 3744 name = jQuery.camelCase( name.slice(5) ); 3745 dataAttr( elem, name, data[ name ] ); 3746 } 3747 } 3748 data_priv.set( elem, "hasDataAttrs", true ); 3749 } 3750 } 3751 3752 return data; 3753 } 3754 3755 // Sets multiple values 3756 if ( typeof key === "object" ) { 3757 return this.each(function() { 3758 data_user.set( this, key ); 3759 }); 3760 } 3761 3762 return access( this, function( value ) { 3763 var data, 3764 camelKey = jQuery.camelCase( key ); 3765 3766 // The calling jQuery object (element matches) is not empty 3767 // (and therefore has an element appears at this[ 0 ]) and the 3768 // `value` parameter was not undefined. An empty jQuery object 3769 // will result in `undefined` for elem = this[ 0 ] which will 3770 // throw an exception if an attempt to read a data cache is made. 3771 if ( elem && value === undefined ) { 3772 // Attempt to get data from the cache 3773 // with the key as-is 3774 data = data_user.get( elem, key ); 3775 if ( data !== undefined ) { 3776 return data; 3777 } 3778 3779 // Attempt to get data from the cache 3780 // with the key camelized 3781 data = data_user.get( elem, camelKey ); 3782 if ( data !== undefined ) { 3783 return data; 3784 } 3785 3786 // Attempt to "discover" the data in 3787 // HTML5 custom data-* attrs 3788 data = dataAttr( elem, camelKey, undefined ); 3789 if ( data !== undefined ) { 3790 return data; 3791 } 3792 3793 // We tried really hard, but the data doesn't exist. 3794 return; 3795 } 3796 3797 // Set the data... 3798 this.each(function() { 3799 // First, attempt to store a copy or reference of any 3800 // data that might've been store with a camelCased key. 3801 var data = data_user.get( this, camelKey ); 3802 3803 // For HTML5 data-* attribute interop, we have to 3804 // store property names with dashes in a camelCase form. 3805 // This might not apply to all properties...* 3806 data_user.set( this, camelKey, value ); 3807 3808 // *... In the case of properties that might _actually_ 3809 // have dashes, we need to also store a copy of that 3810 // unchanged property. 3811 if ( key.indexOf("-") !== -1 && data !== undefined ) { 3812 data_user.set( this, key, value ); 3813 } 3814 }); 3815 }, null, value, arguments.length > 1, null, true ); 3816 }, 3817 3818 removeData: function( key ) { 3819 return this.each(function() { 3820 data_user.remove( this, key ); 3821 }); 3822 } 3823}); 3824 3825 3826jQuery.extend({ 3827 queue: function( elem, type, data ) { 3828 var queue; 3829 3830 if ( elem ) { 3831 type = ( type || "fx" ) + "queue"; 3832 queue = data_priv.get( elem, type ); 3833 3834 // Speed up dequeue by getting out quickly if this is just a lookup 3835 if ( data ) { 3836 if ( !queue || jQuery.isArray( data ) ) { 3837 queue = data_priv.access( elem, type, jQuery.makeArray(data) ); 3838 } else { 3839 queue.push( data ); 3840 } 3841 } 3842 return queue || []; 3843 } 3844 }, 3845 3846 dequeue: function( elem, type ) { 3847 type = type || "fx"; 3848 3849 var queue = jQuery.queue( elem, type ), 3850 startLength = queue.length, 3851 fn = queue.shift(), 3852 hooks = jQuery._queueHooks( elem, type ), 3853 next = function() { 3854 jQuery.dequeue( elem, type ); 3855 }; 3856 3857 // If the fx queue is dequeued, always remove the progress sentinel 3858 if ( fn === "inprogress" ) { 3859 fn = queue.shift(); 3860 startLength--; 3861 } 3862 3863 if ( fn ) { 3864 3865 // Add a progress sentinel to prevent the fx queue from being 3866 // automatically dequeued 3867 if ( type === "fx" ) { 3868 queue.unshift( "inprogress" ); 3869 } 3870 3871 // clear up the last queue stop function 3872 delete hooks.stop; 3873 fn.call( elem, next, hooks ); 3874 } 3875 3876 if ( !startLength && hooks ) { 3877 hooks.empty.fire(); 3878 } 3879 }, 3880 3881 // not intended for public consumption - generates a queueHooks object, or returns the current one 3882 _queueHooks: function( elem, type ) { 3883 var key = type + "queueHooks"; 3884 return data_priv.get( elem, key ) || data_priv.access( elem, key, { 3885 empty: jQuery.Callbacks("once memory").add(function() { 3886 data_priv.remove( elem, [ type + "queue", key ] ); 3887 }) 3888 }); 3889 } 3890}); 3891 3892jQuery.fn.extend({ 3893 queue: function( type, data ) { 3894 var setter = 2; 3895 3896 if ( typeof type !== "string" ) { 3897 data = type; 3898 type = "fx"; 3899 setter--; 3900 } 3901 3902 if ( arguments.length < setter ) { 3903 return jQuery.queue( this[0], type ); 3904 } 3905 3906 return data === undefined ? 3907 this : 3908 this.each(function() { 3909 var queue = jQuery.queue( this, type, data ); 3910 3911 // ensure a hooks for this queue 3912 jQuery._queueHooks( this, type ); 3913 3914 if ( type === "fx" && queue[0] !== "inprogress" ) { 3915 jQuery.dequeue( this, type ); 3916 } 3917 }); 3918 }, 3919 dequeue: function( type ) { 3920 return this.each(function() { 3921 jQuery.dequeue( this, type ); 3922 }); 3923 }, 3924 clearQueue: function( type ) { 3925 return this.queue( type || "fx", [] ); 3926 }, 3927 // Get a promise resolved when queues of a certain type 3928 // are emptied (fx is the type by default) 3929 promise: function( type, obj ) { 3930 var tmp, 3931 count = 1, 3932 defer = jQuery.Deferred(), 3933 elements = this, 3934 i = this.length, 3935 resolve = function() { 3936 if ( !( --count ) ) { 3937 defer.resolveWith( elements, [ elements ] ); 3938 } 3939 }; 3940 3941 if ( typeof type !== "string" ) { 3942 obj = type; 3943 type = undefined; 3944 } 3945 type = type || "fx"; 3946 3947 while ( i-- ) { 3948 tmp = data_priv.get( elements[ i ], type + "queueHooks" ); 3949 if ( tmp && tmp.empty ) { 3950 count++; 3951 tmp.empty.add( resolve ); 3952 } 3953 } 3954 resolve(); 3955 return defer.promise( obj ); 3956 } 3957}); 3958var pnum = (/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/).source; 3959 3960var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; 3961 3962var isHidden = function( elem, el ) { 3963 // isHidden might be called from jQuery#filter function; 3964 // in that case, element will be second argument 3965 elem = el || elem; 3966 return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem ); 3967 }; 3968 3969var rcheckableType = (/^(?:checkbox|radio)$/i); 3970 3971 3972 3973(function() { 3974 var fragment = document.createDocumentFragment(), 3975 div = fragment.appendChild( document.createElement( "div" ) ); 3976 3977 // #11217 - WebKit loses check when the name is after the checked attribute 3978 div.innerHTML = "<input type='radio' checked='checked' name='t'/>"; 3979 3980 // Support: Safari 5.1, iOS 5.1, Android 4.x, Android 2.3 3981 // old WebKit doesn't clone checked state correctly in fragments 3982 support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; 3983 3984 // Make sure textarea (and checkbox) defaultValue is properly cloned 3985 // Support: IE9-IE11+ 3986 div.innerHTML = "<textarea>x</textarea>"; 3987 support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; 3988})(); 3989var strundefined = typeof undefined; 3990 3991 3992 3993support.focusinBubbles = "onfocusin" in window; 3994 3995 3996var 3997 rkeyEvent = /^key/, 3998 rmouseEvent = /^(?:mouse|contextmenu)|click/, 3999 rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, 4000 rtypenamespace = /^([^.]*)(?:\.(.+)|)$/; 4001 4002function returnTrue() { 4003 return true; 4004} 4005 4006function returnFalse() { 4007 return false; 4008} 4009 4010function safeActiveElement() { 4011 try { 4012 return document.activeElement; 4013 } catch ( err ) { } 4014} 4015 4016/* 4017 * Helper functions for managing events -- not part of the public interface. 4018 * Props to Dean Edwards' addEvent library for many of the ideas. 4019 */ 4020jQuery.event = { 4021 4022 global: {}, 4023 4024 add: function( elem, types, handler, data, selector ) { 4025 4026 var handleObjIn, eventHandle, tmp, 4027 events, t, handleObj, 4028 special, handlers, type, namespaces, origType, 4029 elemData = data_priv.get( elem ); 4030 4031 // Don't attach events to noData or text/comment nodes (but allow plain objects) 4032 if ( !elemData ) { 4033 return; 4034 } 4035 4036 // Caller can pass in an object of custom data in lieu of the handler 4037 if ( handler.handler ) { 4038 handleObjIn = handler; 4039 handler = handleObjIn.handler; 4040 selector = handleObjIn.selector; 4041 } 4042 4043 // Make sure that the handler has a unique ID, used to find/remove it later 4044 if ( !handler.guid ) { 4045 handler.guid = jQuery.guid++; 4046 } 4047 4048 // Init the element's event structure and main handler, if this is the first 4049 if ( !(events = elemData.events) ) { 4050 events = elemData.events = {}; 4051 } 4052 if ( !(eventHandle = elemData.handle) ) { 4053 eventHandle = elemData.handle = function( e ) { 4054 // Discard the second event of a jQuery.event.trigger() and 4055 // when an event is called after a page has unloaded 4056 return typeof jQuery !== strundefined && jQuery.event.triggered !== e.type ? 4057 jQuery.event.dispatch.apply( elem, arguments ) : undefined; 4058 }; 4059 } 4060 4061 // Handle multiple events separated by a space 4062 types = ( types || "" ).match( rnotwhite ) || [ "" ]; 4063 t = types.length; 4064 while ( t-- ) { 4065 tmp = rtypenamespace.exec( types[t] ) || []; 4066 type = origType = tmp[1]; 4067 namespaces = ( tmp[2] || "" ).split( "." ).sort(); 4068 4069 // There *must* be a type, no attaching namespace-only handlers 4070 if ( !type ) { 4071 continue; 4072 } 4073 4074 // If event changes its type, use the special event handlers for the changed type 4075 special = jQuery.event.special[ type ] || {}; 4076 4077 // If selector defined, determine special event api type, otherwise given type 4078 type = ( selector ? special.delegateType : special.bindType ) || type; 4079 4080 // Update special based on newly reset type 4081 special = jQuery.event.special[ type ] || {}; 4082 4083 // handleObj is passed to all event handlers 4084 handleObj = jQuery.extend({ 4085 type: type, 4086 origType: origType, 4087 data: data, 4088 handler: handler, 4089 guid: handler.guid, 4090 selector: selector, 4091 needsContext: selector && jQuery.expr.match.needsContext.test( selector ), 4092 namespace: namespaces.join(".") 4093 }, handleObjIn ); 4094 4095 // Init the event handler queue if we're the first 4096 if ( !(handlers = events[ type ]) ) { 4097 handlers = events[ type ] = []; 4098 handlers.delegateCount = 0; 4099 4100 // Only use addEventListener if the special events handler returns false 4101 if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { 4102 if ( elem.addEventListener ) { 4103 elem.addEventListener( type, eventHandle, false ); 4104 } 4105 } 4106 } 4107 4108 if ( special.add ) { 4109 special.add.call( elem, handleObj ); 4110 4111 if ( !handleObj.handler.guid ) { 4112 handleObj.handler.guid = handler.guid; 4113 } 4114 } 4115 4116 // Add to the element's handler list, delegates in front 4117 if ( selector ) { 4118 handlers.splice( handlers.delegateCount++, 0, handleObj ); 4119 } else { 4120 handlers.push( handleObj ); 4121 } 4122 4123 // Keep track of which events have ever been used, for event optimization 4124 jQuery.event.global[ type ] = true; 4125 } 4126 4127 }, 4128 4129 // Detach an event or set of events from an element 4130 remove: function( elem, types, handler, selector, mappedTypes ) { 4131 4132 var j, origCount, tmp, 4133 events, t, handleObj, 4134 special, handlers, type, namespaces, origType, 4135 elemData = data_priv.hasData( elem ) && data_priv.get( elem ); 4136 4137 if ( !elemData || !(events = elemData.events) ) { 4138 return; 4139 } 4140 4141 // Once for each type.namespace in types; type may be omitted 4142 types = ( types || "" ).match( rnotwhite ) || [ "" ]; 4143 t = types.length; 4144 while ( t-- ) { 4145 tmp = rtypenamespace.exec( types[t] ) || []; 4146 type = origType = tmp[1]; 4147 namespaces = ( tmp[2] || "" ).split( "." ).sort(); 4148 4149 // Unbind all events (on this namespace, if provided) for the element 4150 if ( !type ) { 4151 for ( type in events ) { 4152 jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); 4153 } 4154 continue; 4155 } 4156 4157 special = jQuery.event.special[ type ] || {}; 4158 type = ( selector ? special.delegateType : special.bindType ) || type; 4159 handlers = events[ type ] || []; 4160 tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ); 4161 4162 // Remove matching events 4163 origCount = j = handlers.length; 4164 while ( j-- ) { 4165 handleObj = handlers[ j ]; 4166 4167 if ( ( mappedTypes || origType === handleObj.origType ) && 4168 ( !handler || handler.guid === handleObj.guid ) && 4169 ( !tmp || tmp.test( handleObj.namespace ) ) && 4170 ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) { 4171 handlers.splice( j, 1 ); 4172 4173 if ( handleObj.selector ) { 4174 handlers.delegateCount--; 4175 } 4176 if ( special.remove ) { 4177 special.remove.call( elem, handleObj ); 4178 } 4179 } 4180 } 4181 4182 // Remove generic event handler if we removed something and no more handlers exist 4183 // (avoids potential for endless recursion during removal of special event handlers) 4184 if ( origCount && !handlers.length ) { 4185 if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) { 4186 jQuery.removeEvent( elem, type, elemData.handle ); 4187 } 4188 4189 delete events[ type ]; 4190 } 4191 } 4192 4193 // Remove the expando if it's no longer used 4194 if ( jQuery.isEmptyObject( events ) ) { 4195 delete elemData.handle; 4196 data_priv.remove( elem, "events" ); 4197 } 4198 }, 4199 4200 trigger: function( event, data, elem, onlyHandlers ) { 4201 4202 var i, cur, tmp, bubbleType, ontype, handle, special, 4203 eventPath = [ elem || document ], 4204 type = hasOwn.call( event, "type" ) ? event.type : event, 4205 namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : []; 4206 4207 cur = tmp = elem = elem || document; 4208 4209 // Don't do events on text and comment nodes 4210 if ( elem.nodeType === 3 || elem.nodeType === 8 ) { 4211 return; 4212 } 4213 4214 // focus/blur morphs to focusin/out; ensure we're not firing them right now 4215 if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { 4216 return; 4217 } 4218 4219 if ( type.indexOf(".") >= 0 ) { 4220 // Namespaced trigger; create a regexp to match event type in handle() 4221 namespaces = type.split("."); 4222 type = namespaces.shift(); 4223 namespaces.sort(); 4224 } 4225 ontype = type.indexOf(":") < 0 && "on" + type; 4226 4227 // Caller can pass in a jQuery.Event object, Object, or just an event type string 4228 event = event[ jQuery.expando ] ? 4229 event : 4230 new jQuery.Event( type, typeof event === "object" && event ); 4231 4232 // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) 4233 event.isTrigger = onlyHandlers ? 2 : 3; 4234 event.namespace = namespaces.join("."); 4235 event.namespace_re = event.namespace ? 4236 new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) : 4237 null; 4238 4239 // Clean up the event in case it is being reused 4240 event.result = undefined; 4241 if ( !event.target ) { 4242 event.target = elem; 4243 } 4244 4245 // Clone any incoming data and prepend the event, creating the handler arg list 4246 data = data == null ? 4247 [ event ] : 4248 jQuery.makeArray( data, [ event ] ); 4249 4250 // Allow special events to draw outside the lines 4251 special = jQuery.event.special[ type ] || {}; 4252 if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { 4253 return; 4254 } 4255 4256 // Determine event propagation path in advance, per W3C events spec (#9951) 4257 // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) 4258 if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) { 4259 4260 bubbleType = special.delegateType || type; 4261 if ( !rfocusMorph.test( bubbleType + type ) ) { 4262 cur = cur.parentNode; 4263 } 4264 for ( ; cur; cur = cur.parentNode ) { 4265 eventPath.push( cur ); 4266 tmp = cur; 4267 } 4268 4269 // Only add window if we got to document (e.g., not plain obj or detached DOM) 4270 if ( tmp === (elem.ownerDocument || document) ) { 4271 eventPath.push( tmp.defaultView || tmp.parentWindow || window ); 4272 } 4273 } 4274 4275 // Fire handlers on the event path 4276 i = 0; 4277 while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) { 4278 4279 event.type = i > 1 ? 4280 bubbleType : 4281 special.bindType || type; 4282 4283 // jQuery handler 4284 handle = ( data_priv.get( cur, "events" ) || {} )[ event.type ] && data_priv.get( cur, "handle" ); 4285 if ( handle ) { 4286 handle.apply( cur, data ); 4287 } 4288 4289 // Native handler 4290 handle = ontype && cur[ ontype ]; 4291 if ( handle && handle.apply && jQuery.acceptData( cur ) ) { 4292 event.result = handle.apply( cur, data ); 4293 if ( event.result === false ) { 4294 event.preventDefault(); 4295 } 4296 } 4297 } 4298 event.type = type; 4299 4300 // If nobody prevented the default action, do it now 4301 if ( !onlyHandlers && !event.isDefaultPrevented() ) { 4302 4303 if ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) && 4304 jQuery.acceptData( elem ) ) { 4305 4306 // Call a native DOM method on the target with the same name name as the event. 4307 // Don't do default actions on window, that's where global variables be (#6170) 4308 if ( ontype && jQuery.isFunction( elem[ type ] ) && !jQuery.isWindow( elem ) ) { 4309 4310 // Don't re-trigger an onFOO event when we call its FOO() method 4311 tmp = elem[ ontype ]; 4312 4313 if ( tmp ) { 4314 elem[ ontype ] = null; 4315 } 4316 4317 // Prevent re-triggering of the same event, since we already bubbled it above 4318 jQuery.event.triggered = type; 4319 elem[ type ](); 4320 jQuery.event.triggered = undefined; 4321 4322 if ( tmp ) { 4323 elem[ ontype ] = tmp; 4324 } 4325 } 4326 } 4327 } 4328 4329 return event.result; 4330 }, 4331 4332 dispatch: function( event ) { 4333 4334 // Make a writable jQuery.Event from the native event object 4335 event = jQuery.event.fix( event ); 4336 4337 var i, j, ret, matched, handleObj, 4338 handlerQueue = [], 4339 args = slice.call( arguments ), 4340 handlers = ( data_priv.get( this, "events" ) || {} )[ event.type ] || [], 4341 special = jQuery.event.special[ event.type ] || {}; 4342 4343 // Use the fix-ed jQuery.Event rather than the (read-only) native event 4344 args[0] = event; 4345 event.delegateTarget = this; 4346 4347 // Call the preDispatch hook for the mapped type, and let it bail if desired 4348 if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { 4349 return; 4350 } 4351 4352 // Determine handlers 4353 handlerQueue = jQuery.event.handlers.call( this, event, handlers ); 4354 4355 // Run delegates first; they may want to stop propagation beneath us 4356 i = 0; 4357 while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) { 4358 event.currentTarget = matched.elem; 4359 4360 j = 0; 4361 while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) { 4362 4363 // Triggered event must either 1) have no namespace, or 4364 // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace). 4365 if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) { 4366 4367 event.handleObj = handleObj; 4368 event.data = handleObj.data; 4369 4370 ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler ) 4371 .apply( matched.elem, args ); 4372 4373 if ( ret !== undefined ) { 4374 if ( (event.result = ret) === false ) { 4375 event.preventDefault(); 4376 event.stopPropagation(); 4377 } 4378 } 4379 } 4380 } 4381 } 4382 4383 // Call the postDispatch hook for the mapped type 4384 if ( special.postDispatch ) { 4385 special.postDispatch.call( this, event ); 4386 } 4387 4388 return event.result; 4389 }, 4390 4391 handlers: function( event, handlers ) { 4392 var i, matches, sel, handleObj, 4393 handlerQueue = [], 4394 delegateCount = handlers.delegateCount, 4395 cur = event.target; 4396 4397 // Find delegate handlers 4398 // Black-hole SVG <use> instance trees (#13180) 4399 // Avoid non-left-click bubbling in Firefox (#3861) 4400 if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) { 4401 4402 for ( ; cur !== this; cur = cur.parentNode || this ) { 4403 4404 // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) 4405 if ( cur.disabled !== true || event.type !== "click" ) { 4406 matches = []; 4407 for ( i = 0; i < delegateCount; i++ ) { 4408 handleObj = handlers[ i ]; 4409 4410 // Don't conflict with Object.prototype properties (#13203) 4411 sel = handleObj.selector + " "; 4412 4413 if ( matches[ sel ] === undefined ) { 4414 matches[ sel ] = handleObj.needsContext ? 4415 jQuery( sel, this ).index( cur ) >= 0 : 4416 jQuery.find( sel, this, null, [ cur ] ).length; 4417 } 4418 if ( matches[ sel ] ) { 4419 matches.push( handleObj ); 4420 } 4421 } 4422 if ( matches.length ) { 4423 handlerQueue.push({ elem: cur, handlers: matches }); 4424 } 4425 } 4426 } 4427 } 4428 4429 // Add the remaining (directly-bound) handlers 4430 if ( delegateCount < handlers.length ) { 4431 handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) }); 4432 } 4433 4434 return handlerQueue; 4435 }, 4436 4437 // Includes some event props shared by KeyEvent and MouseEvent 4438 props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "), 4439 4440 fixHooks: {}, 4441 4442 keyHooks: { 4443 props: "char charCode key keyCode".split(" "), 4444 filter: function( event, original ) { 4445 4446 // Add which for key events 4447 if ( event.which == null ) { 4448 event.which = original.charCode != null ? original.charCode : original.keyCode; 4449 } 4450 4451 return event; 4452 } 4453 }, 4454 4455 mouseHooks: { 4456 props: "button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement".split(" "), 4457 filter: function( event, original ) { 4458 var eventDoc, doc, body, 4459 button = original.button; 4460 4461 // Calculate pageX/Y if missing and clientX/Y available 4462 if ( event.pageX == null && original.clientX != null ) { 4463 eventDoc = event.target.ownerDocument || document; 4464 doc = eventDoc.documentElement; 4465 body = eventDoc.body; 4466 4467 event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 ); 4468 event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 ); 4469 } 4470 4471 // Add which for click: 1 === left; 2 === middle; 3 === right 4472 // Note: button is not normalized, so don't use it 4473 if ( !event.which && button !== undefined ) { 4474 event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) ); 4475 } 4476 4477 return event; 4478 } 4479 }, 4480 4481 fix: function( event ) { 4482 if ( event[ jQuery.expando ] ) { 4483 return event; 4484 } 4485 4486 // Create a writable copy of the event object and normalize some properties 4487 var i, prop, copy, 4488 type = event.type, 4489 originalEvent = event, 4490 fixHook = this.fixHooks[ type ]; 4491 4492 if ( !fixHook ) { 4493 this.fixHooks[ type ] = fixHook = 4494 rmouseEvent.test( type ) ? this.mouseHooks : 4495 rkeyEvent.test( type ) ? this.keyHooks : 4496 {}; 4497 } 4498 copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props; 4499 4500 event = new jQuery.Event( originalEvent ); 4501 4502 i = copy.length; 4503 while ( i-- ) { 4504 prop = copy[ i ]; 4505 event[ prop ] = originalEvent[ prop ]; 4506 } 4507 4508 // Support: Cordova 2.5 (WebKit) (#13255) 4509 // All events should have a target; Cordova deviceready doesn't 4510 if ( !event.target ) { 4511 event.target = document; 4512 } 4513 4514 // Support: Safari 6.0+, Chrome < 28 4515 // Target should not be a text node (#504, #13143) 4516 if ( event.target.nodeType === 3 ) { 4517 event.target = event.target.parentNode; 4518 } 4519 4520 return fixHook.filter ? fixHook.filter( event, originalEvent ) : event; 4521 }, 4522 4523 special: { 4524 load: { 4525 // Prevent triggered image.load events from bubbling to window.load 4526 noBubble: true 4527 }, 4528 focus: { 4529 // Fire native event if possible so blur/focus sequence is correct 4530 trigger: function() { 4531 if ( this !== safeActiveElement() && this.focus ) { 4532 this.focus(); 4533 return false; 4534 } 4535 }, 4536 delegateType: "focusin" 4537 }, 4538 blur: { 4539 trigger: function() { 4540 if ( this === safeActiveElement() && this.blur ) { 4541 this.blur(); 4542 return false; 4543 } 4544 }, 4545 delegateType: "focusout" 4546 }, 4547 click: { 4548 // For checkbox, fire native event so checked state will be right 4549 trigger: function() { 4550 if ( this.type === "checkbox" && this.click && jQuery.nodeName( this, "input" ) ) { 4551 this.click(); 4552 return false; 4553 } 4554 }, 4555 4556 // For cross-browser consistency, don't fire native .click() on links 4557 _default: function( event ) { 4558 return jQuery.nodeName( event.target, "a" ); 4559 } 4560 }, 4561 4562 beforeunload: { 4563 postDispatch: function( event ) { 4564 4565 // Support: Firefox 20+ 4566 // Firefox doesn't alert if the returnValue field is not set. 4567 if ( event.result !== undefined ) { 4568 event.originalEvent.returnValue = event.result; 4569 } 4570 } 4571 } 4572 }, 4573 4574 simulate: function( type, elem, event, bubble ) { 4575 // Piggyback on a donor event to simulate a different one. 4576 // Fake originalEvent to avoid donor's stopPropagation, but if the 4577 // simulated event prevents default then we do the same on the donor. 4578 var e = jQuery.extend( 4579 new jQuery.Event(), 4580 event, 4581 { 4582 type: type, 4583 isSimulated: true, 4584 originalEvent: {} 4585 } 4586 ); 4587 if ( bubble ) { 4588 jQuery.event.trigger( e, null, elem ); 4589 } else { 4590 jQuery.event.dispatch.call( elem, e ); 4591 } 4592 if ( e.isDefaultPrevented() ) { 4593 event.preventDefault(); 4594 } 4595 } 4596}; 4597 4598jQuery.removeEvent = function( elem, type, handle ) { 4599 if ( elem.removeEventListener ) { 4600 elem.removeEventListener( type, handle, false ); 4601 } 4602}; 4603 4604jQuery.Event = function( src, props ) { 4605 // Allow instantiation without the 'new' keyword 4606 if ( !(this instanceof jQuery.Event) ) { 4607 return new jQuery.Event( src, props ); 4608 } 4609 4610 // Event object 4611 if ( src && src.type ) { 4612 this.originalEvent = src; 4613 this.type = src.type; 4614 4615 // Events bubbling up the document may have been marked as prevented 4616 // by a handler lower down the tree; reflect the correct value. 4617 this.isDefaultPrevented = src.defaultPrevented || 4618 // Support: Android < 4.0 4619 src.defaultPrevented === undefined && 4620 src.getPreventDefault && src.getPreventDefault() ? 4621 returnTrue : 4622 returnFalse; 4623 4624 // Event type 4625 } else { 4626 this.type = src; 4627 } 4628 4629 // Put explicitly provided properties onto the event object 4630 if ( props ) { 4631 jQuery.extend( this, props ); 4632 } 4633 4634 // Create a timestamp if incoming event doesn't have one 4635 this.timeStamp = src && src.timeStamp || jQuery.now(); 4636 4637 // Mark it as fixed 4638 this[ jQuery.expando ] = true; 4639}; 4640 4641// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding 4642// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html 4643jQuery.Event.prototype = { 4644 isDefaultPrevented: returnFalse, 4645 isPropagationStopped: returnFalse, 4646 isImmediatePropagationStopped: returnFalse, 4647 4648 preventDefault: function() { 4649 var e = this.originalEvent; 4650 4651 this.isDefaultPrevented = returnTrue; 4652 4653 if ( e && e.preventDefault ) { 4654 e.preventDefault(); 4655 } 4656 }, 4657 stopPropagation: function() { 4658 var e = this.originalEvent; 4659 4660 this.isPropagationStopped = returnTrue; 4661 4662 if ( e && e.stopPropagation ) { 4663 e.stopPropagation(); 4664 } 4665 }, 4666 stopImmediatePropagation: function() { 4667 this.isImmediatePropagationStopped = returnTrue; 4668 this.stopPropagation(); 4669 } 4670}; 4671 4672// Create mouseenter/leave events using mouseover/out and event-time checks 4673// Support: Chrome 15+ 4674jQuery.each({ 4675 mouseenter: "mouseover", 4676 mouseleave: "mouseout" 4677}, function( orig, fix ) { 4678 jQuery.event.special[ orig ] = { 4679 delegateType: fix, 4680 bindType: fix, 4681 4682 handle: function( event ) { 4683 var ret, 4684 target = this, 4685 related = event.relatedTarget, 4686 handleObj = event.handleObj; 4687 4688 // For mousenter/leave call the handler if related is outside the target. 4689 // NB: No relatedTarget if the mouse left/entered the browser window 4690 if ( !related || (related !== target && !jQuery.contains( target, related )) ) { 4691 event.type = handleObj.origType; 4692 ret = handleObj.handler.apply( this, arguments ); 4693 event.type = fix; 4694 } 4695 return ret; 4696 } 4697 }; 4698}); 4699 4700// Create "bubbling" focus and blur events 4701// Support: Firefox, Chrome, Safari 4702if ( !support.focusinBubbles ) { 4703 jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { 4704 4705 // Attach a single capturing handler on the document while someone wants focusin/focusout 4706 var handler = function( event ) { 4707 jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true ); 4708 }; 4709 4710 jQuery.event.special[ fix ] = { 4711 setup: function() { 4712 var doc = this.ownerDocument || this, 4713 attaches = data_priv.access( doc, fix ); 4714 4715 if ( !attaches ) { 4716 doc.addEventListener( orig, handler, true ); 4717 } 4718 data_priv.access( doc, fix, ( attaches || 0 ) + 1 ); 4719 }, 4720 teardown: function() { 4721 var doc = this.ownerDocument || this, 4722 attaches = data_priv.access( doc, fix ) - 1; 4723 4724 if ( !attaches ) { 4725 doc.removeEventListener( orig, handler, true ); 4726 data_priv.remove( doc, fix ); 4727 4728 } else { 4729 data_priv.access( doc, fix, attaches ); 4730 } 4731 } 4732 }; 4733 }); 4734} 4735 4736jQuery.fn.extend({ 4737 4738 on: function( types, selector, data, fn, /*INTERNAL*/ one ) { 4739 var origFn, type; 4740 4741 // Types can be a map of types/handlers 4742 if ( typeof types === "object" ) { 4743 // ( types-Object, selector, data ) 4744 if ( typeof selector !== "string" ) { 4745 // ( types-Object, data ) 4746 data = data || selector; 4747 selector = undefined; 4748 } 4749 for ( type in types ) { 4750 this.on( type, selector, data, types[ type ], one ); 4751 } 4752 return this; 4753 } 4754 4755 if ( data == null && fn == null ) { 4756 // ( types, fn ) 4757 fn = selector; 4758 data = selector = undefined; 4759 } else if ( fn == null ) { 4760 if ( typeof selector === "string" ) { 4761 // ( types, selector, fn ) 4762 fn = data; 4763 data = undefined; 4764 } else { 4765 // ( types, data, fn ) 4766 fn = data; 4767 data = selector; 4768 selector = undefined; 4769 } 4770 } 4771 if ( fn === false ) { 4772 fn = returnFalse; 4773 } else if ( !fn ) { 4774 return this; 4775 } 4776 4777 if ( one === 1 ) { 4778 origFn = fn; 4779 fn = function( event ) { 4780 // Can use an empty set, since event contains the info 4781 jQuery().off( event ); 4782 return origFn.apply( this, arguments ); 4783 }; 4784 // Use same guid so caller can remove using origFn 4785 fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); 4786 } 4787 return this.each( function() { 4788 jQuery.event.add( this, types, fn, data, selector ); 4789 }); 4790 }, 4791 one: function( types, selector, data, fn ) { 4792 return this.on( types, selector, data, fn, 1 ); 4793 }, 4794 off: function( types, selector, fn ) { 4795 var handleObj, type; 4796 if ( types && types.preventDefault && types.handleObj ) { 4797 // ( event ) dispatched jQuery.Event 4798 handleObj = types.handleObj; 4799 jQuery( types.delegateTarget ).off( 4800 handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType, 4801 handleObj.selector, 4802 handleObj.handler 4803 ); 4804 return this; 4805 } 4806 if ( typeof types === "object" ) { 4807 // ( types-object [, selector] ) 4808 for ( type in types ) { 4809 this.off( type, selector, types[ type ] ); 4810 } 4811 return this; 4812 } 4813 if ( selector === false || typeof selector === "function" ) { 4814 // ( types [, fn] ) 4815 fn = selector; 4816 selector = undefined; 4817 } 4818 if ( fn === false ) { 4819 fn = returnFalse; 4820 } 4821 return this.each(function() { 4822 jQuery.event.remove( this, types, fn, selector ); 4823 }); 4824 }, 4825 4826 trigger: function( type, data ) { 4827 return this.each(function() { 4828 jQuery.event.trigger( type, data, this ); 4829 }); 4830 }, 4831 triggerHandler: function( type, data ) { 4832 var elem = this[0]; 4833 if ( elem ) { 4834 return jQuery.event.trigger( type, data, elem, true ); 4835 } 4836 } 4837}); 4838 4839 4840var 4841 rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi, 4842 rtagName = /<([\w:]+)/, 4843 rhtml = /<|&#?\w+;/, 4844 rnoInnerhtml = /<(?:script|style|link)/i, 4845 // checked="checked" or checked 4846 rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i, 4847 rscriptType = /^$|\/(?:java|ecma)script/i, 4848 rscriptTypeMasked = /^true\/(.*)/, 4849 rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g, 4850 4851 // We have to close these tags to support XHTML (#13200) 4852 wrapMap = { 4853 4854 // Support: IE 9 4855 option: [ 1, "<select multiple='multiple'>", "</select>" ], 4856 4857 thead: [ 1, "<table>", "</table>" ], 4858 col: [ 2, "<table><colgroup>", "</colgroup></table>" ], 4859 tr: [ 2, "<table><tbody>", "</tbody></table>" ], 4860 td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ], 4861 4862 _default: [ 0, "", "" ] 4863 }; 4864 4865// Support: IE 9 4866wrapMap.optgroup = wrapMap.option; 4867 4868wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; 4869wrapMap.th = wrapMap.td; 4870 4871// Support: 1.x compatibility 4872// Manipulating tables requires a tbody 4873function manipulationTarget( elem, content ) { 4874 return jQuery.nodeName( elem, "table" ) && 4875 jQuery.nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ? 4876 4877 elem.getElementsByTagName("tbody")[0] || 4878 elem.appendChild( elem.ownerDocument.createElement("tbody") ) : 4879 elem; 4880} 4881 4882// Replace/restore the type attribute of script elements for safe DOM manipulation 4883function disableScript( elem ) { 4884 elem.type = (elem.getAttribute("type") !== null) + "/" + elem.type; 4885 return elem; 4886} 4887function restoreScript( elem ) { 4888 var match = rscriptTypeMasked.exec( elem.type ); 4889 4890 if ( match ) { 4891 elem.type = match[ 1 ]; 4892 } else { 4893 elem.removeAttribute("type"); 4894 } 4895 4896 return elem; 4897} 4898 4899// Mark scripts as having already been evaluated 4900function setGlobalEval( elems, refElements ) { 4901 var i = 0, 4902 l = elems.length; 4903 4904 for ( ; i < l; i++ ) { 4905 data_priv.set( 4906 elems[ i ], "globalEval", !refElements || data_priv.get( refElements[ i ], "globalEval" ) 4907 ); 4908 } 4909} 4910 4911function cloneCopyEvent( src, dest ) { 4912 var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events; 4913 4914 if ( dest.nodeType !== 1 ) { 4915 return; 4916 } 4917 4918 // 1. Copy private data: events, handlers, etc. 4919 if ( data_priv.hasData( src ) ) { 4920 pdataOld = data_priv.access( src ); 4921 pdataCur = data_priv.set( dest, pdataOld ); 4922 events = pdataOld.events; 4923 4924 if ( events ) { 4925 delete pdataCur.handle; 4926 pdataCur.events = {}; 4927 4928 for ( type in events ) { 4929 for ( i = 0, l = events[ type ].length; i < l; i++ ) { 4930 jQuery.event.add( dest, type, events[ type ][ i ] ); 4931 } 4932 } 4933 } 4934 } 4935 4936 // 2. Copy user data 4937 if ( data_user.hasData( src ) ) { 4938 udataOld = data_user.access( src ); 4939 udataCur = jQuery.extend( {}, udataOld ); 4940 4941 data_user.set( dest, udataCur ); 4942 } 4943} 4944 4945function getAll( context, tag ) { 4946 var ret = context.getElementsByTagName ? context.getElementsByTagName( tag || "*" ) : 4947 context.querySelectorAll ? context.querySelectorAll( tag || "*" ) : 4948 []; 4949 4950 return tag === undefined || tag && jQuery.nodeName( context, tag ) ? 4951 jQuery.merge( [ context ], ret ) : 4952 ret; 4953} 4954 4955// Support: IE >= 9 4956function fixInput( src, dest ) { 4957 var nodeName = dest.nodeName.toLowerCase(); 4958 4959 // Fails to persist the checked state of a cloned checkbox or radio button. 4960 if ( nodeName === "input" && rcheckableType.test( src.type ) ) { 4961 dest.checked = src.checked; 4962 4963 // Fails to return the selected option to the default selected state when cloning options 4964 } else if ( nodeName === "input" || nodeName === "textarea" ) { 4965 dest.defaultValue = src.defaultValue; 4966 } 4967} 4968 4969jQuery.extend({ 4970 clone: function( elem, dataAndEvents, deepDataAndEvents ) { 4971 var i, l, srcElements, destElements, 4972 clone = elem.cloneNode( true ), 4973 inPage = jQuery.contains( elem.ownerDocument, elem ); 4974 4975 // Support: IE >= 9 4976 // Fix Cloning issues 4977 if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && 4978 !jQuery.isXMLDoc( elem ) ) { 4979 4980 // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2 4981 destElements = getAll( clone ); 4982 srcElements = getAll( elem ); 4983 4984 for ( i = 0, l = srcElements.length; i < l; i++ ) { 4985 fixInput( srcElements[ i ], destElements[ i ] ); 4986 } 4987 } 4988 4989 // Copy the events from the original to the clone 4990 if ( dataAndEvents ) { 4991 if ( deepDataAndEvents ) { 4992 srcElements = srcElements || getAll( elem ); 4993 destElements = destElements || getAll( clone ); 4994 4995 for ( i = 0, l = srcElements.length; i < l; i++ ) { 4996 cloneCopyEvent( srcElements[ i ], destElements[ i ] ); 4997 } 4998 } else { 4999 cloneCopyEvent( elem, clone ); 5000 } 5001 } 5002 5003 // Preserve script evaluation history 5004 destElements = getAll( clone, "script" ); 5005 if ( destElements.length > 0 ) { 5006 setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); 5007 } 5008 5009 // Return the cloned set 5010 return clone; 5011 }, 5012 5013 buildFragment: function( elems, context, scripts, selection ) { 5014 var elem, tmp, tag, wrap, contains, j, 5015 fragment = context.createDocumentFragment(), 5016 nodes = [], 5017 i = 0, 5018 l = elems.length; 5019 5020 for ( ; i < l; i++ ) { 5021 elem = elems[ i ]; 5022 5023 if ( elem || elem === 0 ) { 5024 5025 // Add nodes directly 5026 if ( jQuery.type( elem ) === "object" ) { 5027 // Support: QtWebKit 5028 // jQuery.merge because push.apply(_, arraylike) throws 5029 jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); 5030 5031 // Convert non-html into a text node 5032 } else if ( !rhtml.test( elem ) ) { 5033 nodes.push( context.createTextNode( elem ) ); 5034 5035 // Convert html into DOM nodes 5036 } else { 5037 tmp = tmp || fragment.appendChild( context.createElement("div") ); 5038 5039 // Deserialize a standard representation 5040 tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); 5041 wrap = wrapMap[ tag ] || wrapMap._default; 5042 tmp.innerHTML = wrap[ 1 ] + elem.replace( rxhtmlTag, "<$1></$2>" ) + wrap[ 2 ]; 5043 5044 // Descend through wrappers to the right content 5045 j = wrap[ 0 ]; 5046 while ( j-- ) { 5047 tmp = tmp.lastChild; 5048 } 5049 5050 // Support: QtWebKit 5051 // jQuery.merge because push.apply(_, arraylike) throws 5052 jQuery.merge( nodes, tmp.childNodes ); 5053 5054 // Remember the top-level container 5055 tmp = fragment.firstChild; 5056 5057 // Fixes #12346 5058 // Support: Webkit, IE 5059 tmp.textContent = ""; 5060 } 5061 } 5062 } 5063 5064 // Remove wrapper from fragment 5065 fragment.textContent = ""; 5066 5067 i = 0; 5068 while ( (elem = nodes[ i++ ]) ) { 5069 5070 // #4087 - If origin and destination elements are the same, and this is 5071 // that element, do not do anything 5072 if ( selection && jQuery.inArray( elem, selection ) !== -1 ) { 5073 continue; 5074 } 5075 5076 contains = jQuery.contains( elem.ownerDocument, elem ); 5077 5078 // Append to fragment 5079 tmp = getAll( fragment.appendChild( elem ), "script" ); 5080 5081 // Preserve script evaluation history 5082 if ( contains ) { 5083 setGlobalEval( tmp ); 5084 } 5085 5086 // Capture executables 5087 if ( scripts ) { 5088 j = 0; 5089 while ( (elem = tmp[ j++ ]) ) { 5090 if ( rscriptType.test( elem.type || "" ) ) { 5091 scripts.push( elem ); 5092 } 5093 } 5094 } 5095 } 5096 5097 return fragment; 5098 }, 5099 5100 cleanData: function( elems ) { 5101 var data, elem, events, type, key, j, 5102 special = jQuery.event.special, 5103 i = 0; 5104 5105 for ( ; (elem = elems[ i ]) !== undefined; i++ ) { 5106 if ( jQuery.acceptData( elem ) ) { 5107 key = elem[ data_priv.expando ]; 5108 5109 if ( key && (data = data_priv.cache[ key ]) ) { 5110 events = Object.keys( data.events || {} ); 5111 if ( events.length ) { 5112 for ( j = 0; (type = events[j]) !== undefined; j++ ) { 5113 if ( special[ type ] ) { 5114 jQuery.event.remove( elem, type ); 5115 5116 // This is a shortcut to avoid jQuery.event.remove's overhead 5117 } else { 5118 jQuery.removeEvent( elem, type, data.handle ); 5119 } 5120 } 5121 } 5122 if ( data_priv.cache[ key ] ) { 5123 // Discard any remaining `private` data 5124 delete data_priv.cache[ key ]; 5125 } 5126 } 5127 } 5128 // Discard any remaining `user` data 5129 delete data_user.cache[ elem[ data_user.expando ] ]; 5130 } 5131 } 5132}); 5133 5134jQuery.fn.extend({ 5135 text: function( value ) { 5136 return access( this, function( value ) { 5137 return value === undefined ? 5138 jQuery.text( this ) : 5139 this.empty().each(function() { 5140 if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { 5141 this.textContent = value; 5142 } 5143 }); 5144 }, null, value, arguments.length ); 5145 }, 5146 5147 append: function() { 5148 return this.domManip( arguments, function( elem ) { 5149 if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { 5150 var target = manipulationTarget( this, elem ); 5151 target.appendChild( elem ); 5152 } 5153 }); 5154 }, 5155 5156 prepend: function() { 5157 return this.domManip( arguments, function( elem ) { 5158 if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { 5159 var target = manipulationTarget( this, elem ); 5160 target.insertBefore( elem, target.firstChild ); 5161 } 5162 }); 5163 }, 5164 5165 before: function() { 5166 return this.domManip( arguments, function( elem ) { 5167 if ( this.parentNode ) { 5168 this.parentNode.insertBefore( elem, this ); 5169 } 5170 }); 5171 }, 5172 5173 after: function() { 5174 return this.domManip( arguments, function( elem ) { 5175 if ( this.parentNode ) { 5176 this.parentNode.insertBefore( elem, this.nextSibling ); 5177 } 5178 }); 5179 }, 5180 5181 remove: function( selector, keepData /* Internal Use Only */ ) { 5182 var elem, 5183 elems = selector ? jQuery.filter( selector, this ) : this, 5184 i = 0; 5185 5186 for ( ; (elem = elems[i]) != null; i++ ) { 5187 if ( !keepData && elem.nodeType === 1 ) { 5188 jQuery.cleanData( getAll( elem ) ); 5189 } 5190 5191 if ( elem.parentNode ) { 5192 if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) { 5193 setGlobalEval( getAll( elem, "script" ) ); 5194 } 5195 elem.parentNode.removeChild( elem ); 5196 } 5197 } 5198 5199 return this; 5200 }, 5201 5202 empty: function() { 5203 var elem, 5204 i = 0; 5205 5206 for ( ; (elem = this[i]) != null; i++ ) { 5207 if ( elem.nodeType === 1 ) { 5208 5209 // Prevent memory leaks 5210 jQuery.cleanData( getAll( elem, false ) ); 5211 5212 // Remove any remaining nodes 5213 elem.textContent = ""; 5214 } 5215 } 5216 5217 return this; 5218 }, 5219 5220 clone: function( dataAndEvents, deepDataAndEvents ) { 5221 dataAndEvents = dataAndEvents == null ? false : dataAndEvents; 5222 deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; 5223 5224 return this.map(function() { 5225 return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); 5226 }); 5227 }, 5228 5229 html: function( value ) { 5230 return access( this, function( value ) { 5231 var elem = this[ 0 ] || {}, 5232 i = 0, 5233 l = this.length; 5234 5235 if ( value === undefined && elem.nodeType === 1 ) { 5236 return elem.innerHTML; 5237 } 5238 5239 // See if we can take a shortcut and just use innerHTML 5240 if ( typeof value === "string" && !rnoInnerhtml.test( value ) && 5241 !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { 5242 5243 value = value.replace( rxhtmlTag, "<$1></$2>" ); 5244 5245 try { 5246 for ( ; i < l; i++ ) { 5247 elem = this[ i ] || {}; 5248 5249 // Remove element nodes and prevent memory leaks 5250 if ( elem.nodeType === 1 ) { 5251 jQuery.cleanData( getAll( elem, false ) ); 5252 elem.innerHTML = value; 5253 } 5254 } 5255 5256 elem = 0; 5257 5258 // If using innerHTML throws an exception, use the fallback method 5259 } catch( e ) {} 5260 } 5261 5262 if ( elem ) { 5263 this.empty().append( value ); 5264 } 5265 }, null, value, arguments.length ); 5266 }, 5267 5268 replaceWith: function() { 5269 var arg = arguments[ 0 ]; 5270 5271 // Make the changes, replacing each context element with the new content 5272 this.domManip( arguments, function( elem ) { 5273 arg = this.parentNode; 5274 5275 jQuery.cleanData( getAll( this ) ); 5276 5277 if ( arg ) { 5278 arg.replaceChild( elem, this ); 5279 } 5280 }); 5281 5282 // Force removal if there was no new content (e.g., from empty arguments) 5283 return arg && (arg.length || arg.nodeType) ? this : this.remove(); 5284 }, 5285 5286 detach: function( selector ) { 5287 return this.remove( selector, true ); 5288 }, 5289 5290 domManip: function( args, callback ) { 5291 5292 // Flatten any nested arrays 5293 args = concat.apply( [], args ); 5294 5295 var fragment, first, scripts, hasScripts, node, doc, 5296 i = 0, 5297 l = this.length, 5298 set = this, 5299 iNoClone = l - 1, 5300 value = args[ 0 ], 5301 isFunction = jQuery.isFunction( value ); 5302 5303 // We can't cloneNode fragments that contain checked, in WebKit 5304 if ( isFunction || 5305 ( l > 1 && typeof value === "string" && 5306 !support.checkClone && rchecked.test( value ) ) ) { 5307 return this.each(function( index ) { 5308 var self = set.eq( index ); 5309 if ( isFunction ) { 5310 args[ 0 ] = value.call( this, index, self.html() ); 5311 } 5312 self.domManip( args, callback ); 5313 }); 5314 } 5315 5316 if ( l ) { 5317 fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this ); 5318 first = fragment.firstChild; 5319 5320 if ( fragment.childNodes.length === 1 ) { 5321 fragment = first; 5322 } 5323 5324 if ( first ) { 5325 scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); 5326 hasScripts = scripts.length; 5327 5328 // Use the original fragment for the last item instead of the first because it can end up 5329 // being emptied incorrectly in certain situations (#8070). 5330 for ( ; i < l; i++ ) { 5331 node = fragment; 5332 5333 if ( i !== iNoClone ) { 5334 node = jQuery.clone( node, true, true ); 5335 5336 // Keep references to cloned scripts for later restoration 5337 if ( hasScripts ) { 5338 // Support: QtWebKit 5339 // jQuery.merge because push.apply(_, arraylike) throws 5340 jQuery.merge( scripts, getAll( node, "script" ) ); 5341 } 5342 } 5343 5344 callback.call( this[ i ], node, i ); 5345 } 5346 5347 if ( hasScripts ) { 5348 doc = scripts[ scripts.length - 1 ].ownerDocument; 5349 5350 // Reenable scripts 5351 jQuery.map( scripts, restoreScript ); 5352 5353 // Evaluate executable scripts on first document insertion 5354 for ( i = 0; i < hasScripts; i++ ) { 5355 node = scripts[ i ]; 5356 if ( rscriptType.test( node.type || "" ) && 5357 !data_priv.access( node, "globalEval" ) && jQuery.contains( doc, node ) ) { 5358 5359 if ( node.src ) { 5360 // Optional AJAX dependency, but won't run scripts if not present 5361 if ( jQuery._evalUrl ) { 5362 jQuery._evalUrl( node.src ); 5363 } 5364 } else { 5365 jQuery.globalEval( node.textContent.replace( rcleanScript, "" ) ); 5366 } 5367 } 5368 } 5369 } 5370 } 5371 } 5372 5373 return this; 5374 } 5375}); 5376 5377jQuery.each({ 5378 appendTo: "append", 5379 prependTo: "prepend", 5380 insertBefore: "before", 5381 insertAfter: "after", 5382 replaceAll: "replaceWith" 5383}, function( name, original ) { 5384 jQuery.fn[ name ] = function( selector ) { 5385 var elems, 5386 ret = [], 5387 insert = jQuery( selector ), 5388 last = insert.length - 1, 5389 i = 0; 5390 5391 for ( ; i <= last; i++ ) { 5392 elems = i === last ? this : this.clone( true ); 5393 jQuery( insert[ i ] )[ original ]( elems ); 5394 5395 // Support: QtWebKit 5396 // .get() because push.apply(_, arraylike) throws 5397 push.apply( ret, elems.get() ); 5398 } 5399 5400 return this.pushStack( ret ); 5401 }; 5402}); 5403 5404 5405var iframe, 5406 elemdisplay = {}; 5407 5408/** 5409 * Retrieve the actual display of a element 5410 * @param {String} name nodeName of the element 5411 * @param {Object} doc Document object 5412 */ 5413// Called only from within defaultDisplay 5414function actualDisplay( name, doc ) { 5415 var elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ), 5416 5417 // getDefaultComputedStyle might be reliably used only on attached element 5418 display = window.getDefaultComputedStyle ? 5419 5420 // Use of this method is a temporary fix (more like optmization) until something better comes along, 5421 // since it was removed from specification and supported only in FF 5422 window.getDefaultComputedStyle( elem[ 0 ] ).display : jQuery.css( elem[ 0 ], "display" ); 5423 5424 // We don't have any data stored on the element, 5425 // so use "detach" method as fast way to get rid of the element 5426 elem.detach(); 5427 5428 return display; 5429} 5430 5431/** 5432 * Try to determine the default display value of an element 5433 * @param {String} nodeName 5434 */ 5435function defaultDisplay( nodeName ) { 5436 var doc = document, 5437 display = elemdisplay[ nodeName ]; 5438 5439 if ( !display ) { 5440 display = actualDisplay( nodeName, doc ); 5441 5442 // If the simple way fails, read from inside an iframe 5443 if ( display === "none" || !display ) { 5444 5445 // Use the already-created iframe if possible 5446 iframe = (iframe || jQuery( "<iframe frameborder='0' width='0' height='0'/>" )).appendTo( doc.documentElement ); 5447 5448 // Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse 5449 doc = iframe[ 0 ].contentDocument; 5450 5451 // Support: IE 5452 doc.write(); 5453 doc.close(); 5454 5455 display = actualDisplay( nodeName, doc ); 5456 iframe.detach(); 5457 } 5458 5459 // Store the correct default display 5460 elemdisplay[ nodeName ] = display; 5461 } 5462 5463 return display; 5464} 5465var rmargin = (/^margin/); 5466 5467var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" ); 5468 5469var getStyles = function( elem ) { 5470 return elem.ownerDocument.defaultView.getComputedStyle( elem, null ); 5471 }; 5472 5473 5474 5475function curCSS( elem, name, computed ) { 5476 var width, minWidth, maxWidth, ret, 5477 style = elem.style; 5478 5479 computed = computed || getStyles( elem ); 5480 5481 // Support: IE9 5482 // getPropertyValue is only needed for .css('filter') in IE9, see #12537 5483 if ( computed ) { 5484 ret = computed.getPropertyValue( name ) || computed[ name ]; 5485 } 5486 5487 if ( computed ) { 5488 5489 if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) { 5490 ret = jQuery.style( elem, name ); 5491 } 5492 5493 // Support: iOS < 6 5494 // A tribute to the "awesome hack by Dean Edwards" 5495 // iOS < 6 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels 5496 // this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values 5497 if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) { 5498 5499 // Remember the original values 5500 width = style.width; 5501 minWidth = style.minWidth; 5502 maxWidth = style.maxWidth; 5503 5504 // Put in the new values to get a computed value out 5505 style.minWidth = style.maxWidth = style.width = ret; 5506 ret = computed.width; 5507 5508 // Revert the changed values 5509 style.width = width; 5510 style.minWidth = minWidth; 5511 style.maxWidth = maxWidth; 5512 } 5513 } 5514 5515 return ret !== undefined ? 5516 // Support: IE 5517 // IE returns zIndex value as an integer. 5518 ret + "" : 5519 ret; 5520} 5521 5522 5523function addGetHookIf( conditionFn, hookFn ) { 5524 // Define the hook, we'll check on the first run if it's really needed. 5525 return { 5526 get: function() { 5527 if ( conditionFn() ) { 5528 // Hook not needed (or it's not possible to use it due to missing dependency), 5529 // remove it. 5530 // Since there are no other hooks for marginRight, remove the whole object. 5531 delete this.get; 5532 return; 5533 } 5534 5535 // Hook needed; redefine it so that the support test is not executed again. 5536 5537 return (this.get = hookFn).apply( this, arguments ); 5538 } 5539 }; 5540} 5541 5542 5543(function() { 5544 var pixelPositionVal, boxSizingReliableVal, 5545 // Support: Firefox, Android 2.3 (Prefixed box-sizing versions). 5546 divReset = "padding:0;margin:0;border:0;display:block;-webkit-box-sizing:content-box;" + 5547 "-moz-box-sizing:content-box;box-sizing:content-box", 5548 docElem = document.documentElement, 5549 container = document.createElement( "div" ), 5550 div = document.createElement( "div" ); 5551 5552 div.style.backgroundClip = "content-box"; 5553 div.cloneNode( true ).style.backgroundClip = ""; 5554 support.clearCloneStyle = div.style.backgroundClip === "content-box"; 5555 5556 container.style.cssText = "border:0;width:0;height:0;position:absolute;top:0;left:-9999px;" + 5557 "margin-top:1px"; 5558 container.appendChild( div ); 5559 5560 // Executing both pixelPosition & boxSizingReliable tests require only one layout 5561 // so they're executed at the same time to save the second computation. 5562 function computePixelPositionAndBoxSizingReliable() { 5563 // Support: Firefox, Android 2.3 (Prefixed box-sizing versions). 5564 div.style.cssText = "-webkit-box-sizing:border-box;-moz-box-sizing:border-box;" + 5565 "box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;" + 5566 "position:absolute;top:1%"; 5567 docElem.appendChild( container ); 5568 5569 var divStyle = window.getComputedStyle( div, null ); 5570 pixelPositionVal = divStyle.top !== "1%"; 5571 boxSizingReliableVal = divStyle.width === "4px"; 5572 5573 docElem.removeChild( container ); 5574 } 5575 5576 // Use window.getComputedStyle because jsdom on node.js will break without it. 5577 if ( window.getComputedStyle ) { 5578 jQuery.extend(support, { 5579 pixelPosition: function() { 5580 // This test is executed only once but we still do memoizing 5581 // since we can use the boxSizingReliable pre-computing. 5582 // No need to check if the test was already performed, though. 5583 computePixelPositionAndBoxSizingReliable(); 5584 return pixelPositionVal; 5585 }, 5586 boxSizingReliable: function() { 5587 if ( boxSizingReliableVal == null ) { 5588 computePixelPositionAndBoxSizingReliable(); 5589 } 5590 return boxSizingReliableVal; 5591 }, 5592 reliableMarginRight: function() { 5593 // Support: Android 2.3 5594 // Check if div with explicit width and no margin-right incorrectly 5595 // gets computed margin-right based on width of container. (#3333) 5596 // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right 5597 // This support function is only executed once so no memoizing is needed. 5598 var ret, 5599 marginDiv = div.appendChild( document.createElement( "div" ) ); 5600 marginDiv.style.cssText = div.style.cssText = divReset; 5601 marginDiv.style.marginRight = marginDiv.style.width = "0"; 5602 div.style.width = "1px"; 5603 docElem.appendChild( container ); 5604 5605 ret = !parseFloat( window.getComputedStyle( marginDiv, null ).marginRight ); 5606 5607 docElem.removeChild( container ); 5608 5609 // Clean up the div for other support tests. 5610 div.innerHTML = ""; 5611 5612 return ret; 5613 } 5614 }); 5615 } 5616})(); 5617 5618 5619// A method for quickly swapping in/out CSS properties to get correct calculations. 5620jQuery.swap = function( elem, options, callback, args ) { 5621 var ret, name, 5622 old = {}; 5623 5624 // Remember the old values, and insert the new ones 5625 for ( name in options ) { 5626 old[ name ] = elem.style[ name ]; 5627 elem.style[ name ] = options[ name ]; 5628 } 5629 5630 ret = callback.apply( elem, args || [] ); 5631 5632 // Revert the old values 5633 for ( name in options ) { 5634 elem.style[ name ] = old[ name ]; 5635 } 5636 5637 return ret; 5638}; 5639 5640 5641var 5642 // swappable if display is none or starts with table except "table", "table-cell", or "table-caption" 5643 // see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display 5644 rdisplayswap = /^(none|table(?!-c[ea]).+)/, 5645 rnumsplit = new RegExp( "^(" + pnum + ")(.*)$", "i" ), 5646 rrelNum = new RegExp( "^([+-])=(" + pnum + ")", "i" ), 5647 5648 cssShow = { position: "absolute", visibility: "hidden", display: "block" }, 5649 cssNormalTransform = { 5650 letterSpacing: 0, 5651 fontWeight: 400 5652 }, 5653 5654 cssPrefixes = [ "Webkit", "O", "Moz", "ms" ]; 5655 5656// return a css property mapped to a potentially vendor prefixed property 5657function vendorPropName( style, name ) { 5658 5659 // shortcut for names that are not vendor prefixed 5660 if ( name in style ) { 5661 return name; 5662 } 5663 5664 // check for vendor prefixed names 5665 var capName = name[0].toUpperCase() + name.slice(1), 5666 origName = name, 5667 i = cssPrefixes.length; 5668 5669 while ( i-- ) { 5670 name = cssPrefixes[ i ] + capName; 5671 if ( name in style ) { 5672 return name; 5673 } 5674 } 5675 5676 return origName; 5677} 5678 5679function setPositiveNumber( elem, value, subtract ) { 5680 var matches = rnumsplit.exec( value ); 5681 return matches ? 5682 // Guard against undefined "subtract", e.g., when used as in cssHooks 5683 Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) : 5684 value; 5685} 5686 5687function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) { 5688 var i = extra === ( isBorderBox ? "border" : "content" ) ? 5689 // If we already have the right measurement, avoid augmentation 5690 4 : 5691 // Otherwise initialize for horizontal or vertical properties 5692 name === "width" ? 1 : 0, 5693 5694 val = 0; 5695 5696 for ( ; i < 4; i += 2 ) { 5697 // both box models exclude margin, so add it if we want it 5698 if ( extra === "margin" ) { 5699 val += jQuery.css( elem, extra + cssExpand[ i ], true, styles ); 5700 } 5701 5702 if ( isBorderBox ) { 5703 // border-box includes padding, so remove it if we want content 5704 if ( extra === "content" ) { 5705 val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); 5706 } 5707 5708 // at this point, extra isn't border nor margin, so remove border 5709 if ( extra !== "margin" ) { 5710 val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); 5711 } 5712 } else { 5713 // at this point, extra isn't content, so add padding 5714 val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); 5715 5716 // at this point, extra isn't content nor padding, so add border 5717 if ( extra !== "padding" ) { 5718 val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); 5719 } 5720 } 5721 } 5722 5723 return val; 5724} 5725 5726function getWidthOrHeight( elem, name, extra ) { 5727 5728 // Start with offset property, which is equivalent to the border-box value 5729 var valueIsBorderBox = true, 5730 val = name === "width" ? elem.offsetWidth : elem.offsetHeight, 5731 styles = getStyles( elem ), 5732 isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; 5733 5734 // some non-html elements return undefined for offsetWidth, so check for null/undefined 5735 // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285 5736 // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668 5737 if ( val <= 0 || val == null ) { 5738 // Fall back to computed then uncomputed css if necessary 5739 val = curCSS( elem, name, styles ); 5740 if ( val < 0 || val == null ) { 5741 val = elem.style[ name ]; 5742 } 5743 5744 // Computed unit is not pixels. Stop here and return. 5745 if ( rnumnonpx.test(val) ) { 5746 return val; 5747 } 5748 5749 // we need the check for style in case a browser which returns unreliable values 5750 // for getComputedStyle silently falls back to the reliable elem.style 5751 valueIsBorderBox = isBorderBox && 5752 ( support.boxSizingReliable() || val === elem.style[ name ] ); 5753 5754 // Normalize "", auto, and prepare for extra 5755 val = parseFloat( val ) || 0; 5756 } 5757 5758 // use the active box-sizing model to add/subtract irrelevant styles 5759 return ( val + 5760 augmentWidthOrHeight( 5761 elem, 5762 name, 5763 extra || ( isBorderBox ? "border" : "content" ), 5764 valueIsBorderBox, 5765 styles 5766 ) 5767 ) + "px"; 5768} 5769 5770function showHide( elements, show ) { 5771 var display, elem, hidden, 5772 values = [], 5773 index = 0, 5774 length = elements.length; 5775 5776 for ( ; index < length; index++ ) { 5777 elem = elements[ index ]; 5778 if ( !elem.style ) { 5779 continue; 5780 } 5781 5782 values[ index ] = data_priv.get( elem, "olddisplay" ); 5783 display = elem.style.display; 5784 if ( show ) { 5785 // Reset the inline display of this element to learn if it is 5786 // being hidden by cascaded rules or not 5787 if ( !values[ index ] && display === "none" ) { 5788 elem.style.display = ""; 5789 } 5790 5791 // Set elements which have been overridden with display: none 5792 // in a stylesheet to whatever the default browser style is 5793 // for such an element 5794 if ( elem.style.display === "" && isHidden( elem ) ) { 5795 values[ index ] = data_priv.access( elem, "olddisplay", defaultDisplay(elem.nodeName) ); 5796 } 5797 } else { 5798 5799 if ( !values[ index ] ) { 5800 hidden = isHidden( elem ); 5801 5802 if ( display && display !== "none" || !hidden ) { 5803 data_priv.set( elem, "olddisplay", hidden ? display : jQuery.css(elem, "display") ); 5804 } 5805 } 5806 } 5807 } 5808 5809 // Set the display of most of the elements in a second loop 5810 // to avoid the constant reflow 5811 for ( index = 0; index < length; index++ ) { 5812 elem = elements[ index ]; 5813 if ( !elem.style ) { 5814 continue; 5815 } 5816 if ( !show || elem.style.display === "none" || elem.style.display === "" ) { 5817 elem.style.display = show ? values[ index ] || "" : "none"; 5818 } 5819 } 5820 5821 return elements; 5822} 5823 5824jQuery.extend({ 5825 // Add in style property hooks for overriding the default 5826 // behavior of getting and setting a style property 5827 cssHooks: { 5828 opacity: { 5829 get: function( elem, computed ) { 5830 if ( computed ) { 5831 // We should always get a number back from opacity 5832 var ret = curCSS( elem, "opacity" ); 5833 return ret === "" ? "1" : ret; 5834 } 5835 } 5836 } 5837 }, 5838 5839 // Don't automatically add "px" to these possibly-unitless properties 5840 cssNumber: { 5841 "columnCount": true, 5842 "fillOpacity": true, 5843 "fontWeight": true, 5844 "lineHeight": true, 5845 "opacity": true, 5846 "order": true, 5847 "orphans": true, 5848 "widows": true, 5849 "zIndex": true, 5850 "zoom": true 5851 }, 5852 5853 // Add in properties whose names you wish to fix before 5854 // setting or getting the value 5855 cssProps: { 5856 // normalize float css property 5857 "float": "cssFloat" 5858 }, 5859 5860 // Get and set the style property on a DOM Node 5861 style: function( elem, name, value, extra ) { 5862 // Don't set styles on text and comment nodes 5863 if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { 5864 return; 5865 } 5866 5867 // Make sure that we're working with the right name 5868 var ret, type, hooks, 5869 origName = jQuery.camelCase( name ), 5870 style = elem.style; 5871 5872 name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) ); 5873 5874 // gets hook for the prefixed version 5875 // followed by the unprefixed version 5876 hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; 5877 5878 // Check if we're setting a value 5879 if ( value !== undefined ) { 5880 type = typeof value; 5881 5882 // convert relative number strings (+= or -=) to relative numbers. #7345 5883 if ( type === "string" && (ret = rrelNum.exec( value )) ) { 5884 value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) ); 5885 // Fixes bug #9237 5886 type = "number"; 5887 } 5888 5889 // Make sure that null and NaN values aren't set. See: #7116 5890 if ( value == null || value !== value ) { 5891 return; 5892 } 5893 5894 // If a number was passed in, add 'px' to the (except for certain CSS properties) 5895 if ( type === "number" && !jQuery.cssNumber[ origName ] ) { 5896 value += "px"; 5897 } 5898 5899 // Fixes #8908, it can be done more correctly by specifying setters in cssHooks, 5900 // but it would mean to define eight (for every problematic property) identical functions 5901 if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) { 5902 style[ name ] = "inherit"; 5903 } 5904 5905 // If a hook was provided, use that value, otherwise just set the specified value 5906 if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) { 5907 // Support: Chrome, Safari 5908 // Setting style to blank string required to delete "style: x !important;" 5909 style[ name ] = ""; 5910 style[ name ] = value; 5911 } 5912 5913 } else { 5914 // If a hook was provided get the non-computed value from there 5915 if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) { 5916 return ret; 5917 } 5918 5919 // Otherwise just get the value from the style object 5920 return style[ name ]; 5921 } 5922 }, 5923 5924 css: function( elem, name, extra, styles ) { 5925 var val, num, hooks, 5926 origName = jQuery.camelCase( name ); 5927 5928 // Make sure that we're working with the right name 5929 name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) ); 5930 5931 // gets hook for the prefixed version 5932 // followed by the unprefixed version 5933 hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; 5934 5935 // If a hook was provided get the computed value from there 5936 if ( hooks && "get" in hooks ) { 5937 val = hooks.get( elem, true, extra ); 5938 } 5939 5940 // Otherwise, if a way to get the computed value exists, use that 5941 if ( val === undefined ) { 5942 val = curCSS( elem, name, styles ); 5943 } 5944 5945 //convert "normal" to computed value 5946 if ( val === "normal" && name in cssNormalTransform ) { 5947 val = cssNormalTransform[ name ]; 5948 } 5949 5950 // Return, converting to number if forced or a qualifier was provided and val looks numeric 5951 if ( extra === "" || extra ) { 5952 num = parseFloat( val ); 5953 return extra === true || jQuery.isNumeric( num ) ? num || 0 : val; 5954 } 5955 return val; 5956 } 5957}); 5958 5959jQuery.each([ "height", "width" ], function( i, name ) { 5960 jQuery.cssHooks[ name ] = { 5961 get: function( elem, computed, extra ) { 5962 if ( computed ) { 5963 // certain elements can have dimension info if we invisibly show them 5964 // however, it must have a current display style that would benefit from this 5965 return elem.offsetWidth === 0 && rdisplayswap.test( jQuery.css( elem, "display" ) ) ? 5966 jQuery.swap( elem, cssShow, function() { 5967 return getWidthOrHeight( elem, name, extra ); 5968 }) : 5969 getWidthOrHeight( elem, name, extra ); 5970 } 5971 }, 5972 5973 set: function( elem, value, extra ) { 5974 var styles = extra && getStyles( elem ); 5975 return setPositiveNumber( elem, value, extra ? 5976 augmentWidthOrHeight( 5977 elem, 5978 name, 5979 extra, 5980 jQuery.css( elem, "boxSizing", false, styles ) === "border-box", 5981 styles 5982 ) : 0 5983 ); 5984 } 5985 }; 5986}); 5987 5988// Support: Android 2.3 5989jQuery.cssHooks.marginRight = addGetHookIf( support.reliableMarginRight, 5990 function( elem, computed ) { 5991 if ( computed ) { 5992 // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right 5993 // Work around by temporarily setting element display to inline-block 5994 return jQuery.swap( elem, { "display": "inline-block" }, 5995 curCSS, [ elem, "marginRight" ] ); 5996 } 5997 } 5998); 5999 6000// These hooks are used by animate to expand properties 6001jQuery.each({ 6002 margin: "", 6003 padding: "", 6004 border: "Width" 6005}, function( prefix, suffix ) { 6006 jQuery.cssHooks[ prefix + suffix ] = { 6007 expand: function( value ) { 6008 var i = 0, 6009 expanded = {}, 6010 6011 // assumes a single number if not a string 6012 parts = typeof value === "string" ? value.split(" ") : [ value ]; 6013 6014 for ( ; i < 4; i++ ) { 6015 expanded[ prefix + cssExpand[ i ] + suffix ] = 6016 parts[ i ] || parts[ i - 2 ] || parts[ 0 ]; 6017 } 6018 6019 return expanded; 6020 } 6021 }; 6022 6023 if ( !rmargin.test( prefix ) ) { 6024 jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber; 6025 } 6026}); 6027 6028jQuery.fn.extend({ 6029 css: function( name, value ) { 6030 return access( this, function( elem, name, value ) { 6031 var styles, len, 6032 map = {}, 6033 i = 0; 6034 6035 if ( jQuery.isArray( name ) ) { 6036 styles = getStyles( elem ); 6037 len = name.length; 6038 6039 for ( ; i < len; i++ ) { 6040 map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); 6041 } 6042 6043 return map; 6044 } 6045 6046 return value !== undefined ? 6047 jQuery.style( elem, name, value ) : 6048 jQuery.css( elem, name ); 6049 }, name, value, arguments.length > 1 ); 6050 }, 6051 show: function() { 6052 return showHide( this, true ); 6053 }, 6054 hide: function() { 6055 return showHide( this ); 6056 }, 6057 toggle: function( state ) { 6058 if ( typeof state === "boolean" ) { 6059 return state ? this.show() : this.hide(); 6060 } 6061 6062 return this.each(function() { 6063 if ( isHidden( this ) ) { 6064 jQuery( this ).show(); 6065 } else { 6066 jQuery( this ).hide(); 6067 } 6068 }); 6069 } 6070}); 6071 6072 6073function Tween( elem, options, prop, end, easing ) { 6074 return new Tween.prototype.init( elem, options, prop, end, easing ); 6075} 6076jQuery.Tween = Tween; 6077 6078Tween.prototype = { 6079 constructor: Tween, 6080 init: function( elem, options, prop, end, easing, unit ) { 6081 this.elem = elem; 6082 this.prop = prop; 6083 this.easing = easing || "swing"; 6084 this.options = options; 6085 this.start = this.now = this.cur(); 6086 this.end = end; 6087 this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" ); 6088 }, 6089 cur: function() { 6090 var hooks = Tween.propHooks[ this.prop ]; 6091 6092 return hooks && hooks.get ? 6093 hooks.get( this ) : 6094 Tween.propHooks._default.get( this ); 6095 }, 6096 run: function( percent ) { 6097 var eased, 6098 hooks = Tween.propHooks[ this.prop ]; 6099 6100 if ( this.options.duration ) { 6101 this.pos = eased = jQuery.easing[ this.easing ]( 6102 percent, this.options.duration * percent, 0, 1, this.options.duration 6103 ); 6104 } else { 6105 this.pos = eased = percent; 6106 } 6107 this.now = ( this.end - this.start ) * eased + this.start; 6108 6109 if ( this.options.step ) { 6110 this.options.step.call( this.elem, this.now, this ); 6111 } 6112 6113 if ( hooks && hooks.set ) { 6114 hooks.set( this ); 6115 } else { 6116 Tween.propHooks._default.set( this ); 6117 } 6118 return this; 6119 } 6120}; 6121 6122Tween.prototype.init.prototype = Tween.prototype; 6123 6124Tween.propHooks = { 6125 _default: { 6126 get: function( tween ) { 6127 var result; 6128 6129 if ( tween.elem[ tween.prop ] != null && 6130 (!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) { 6131 return tween.elem[ tween.prop ]; 6132 } 6133 6134 // passing an empty string as a 3rd parameter to .css will automatically 6135 // attempt a parseFloat and fallback to a string if the parse fails 6136 // so, simple values such as "10px" are parsed to Float. 6137 // complex values such as "rotate(1rad)" are returned as is. 6138 result = jQuery.css( tween.elem, tween.prop, "" ); 6139 // Empty strings, null, undefined and "auto" are converted to 0. 6140 return !result || result === "auto" ? 0 : result; 6141 }, 6142 set: function( tween ) { 6143 // use step hook for back compat - use cssHook if its there - use .style if its 6144 // available and use plain properties where available 6145 if ( jQuery.fx.step[ tween.prop ] ) { 6146 jQuery.fx.step[ tween.prop ]( tween ); 6147 } else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) { 6148 jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); 6149 } else { 6150 tween.elem[ tween.prop ] = tween.now; 6151 } 6152 } 6153 } 6154}; 6155 6156// Support: IE9 6157// Panic based approach to setting things on disconnected nodes 6158 6159Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { 6160 set: function( tween ) { 6161 if ( tween.elem.nodeType && tween.elem.parentNode ) { 6162 tween.elem[ tween.prop ] = tween.now; 6163 } 6164 } 6165}; 6166 6167jQuery.easing = { 6168 linear: function( p ) { 6169 return p; 6170 }, 6171 swing: function( p ) { 6172 return 0.5 - Math.cos( p * Math.PI ) / 2; 6173 } 6174}; 6175 6176jQuery.fx = Tween.prototype.init; 6177 6178// Back Compat <1.8 extension point 6179jQuery.fx.step = {}; 6180 6181 6182 6183 6184var 6185 fxNow, timerId, 6186 rfxtypes = /^(?:toggle|show|hide)$/, 6187 rfxnum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ), 6188 rrun = /queueHooks$/, 6189 animationPrefilters = [ defaultPrefilter ], 6190 tweeners = { 6191 "*": [ function( prop, value ) { 6192 var tween = this.createTween( prop, value ), 6193 target = tween.cur(), 6194 parts = rfxnum.exec( value ), 6195 unit = parts && parts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), 6196 6197 // Starting value computation is required for potential unit mismatches 6198 start = ( jQuery.cssNumber[ prop ] || unit !== "px" && +target ) && 6199 rfxnum.exec( jQuery.css( tween.elem, prop ) ), 6200 scale = 1, 6201 maxIterations = 20; 6202 6203 if ( start && start[ 3 ] !== unit ) { 6204 // Trust units reported by jQuery.css 6205 unit = unit || start[ 3 ]; 6206 6207 // Make sure we update the tween properties later on 6208 parts = parts || []; 6209 6210 // Iteratively approximate from a nonzero starting point 6211 start = +target || 1; 6212 6213 do { 6214 // If previous iteration zeroed out, double until we get *something* 6215 // Use a string for doubling factor so we don't accidentally see scale as unchanged below 6216 scale = scale || ".5"; 6217 6218 // Adjust and apply 6219 start = start / scale; 6220 jQuery.style( tween.elem, prop, start + unit ); 6221 6222 // Update scale, tolerating zero or NaN from tween.cur() 6223 // And breaking the loop if scale is unchanged or perfect, or if we've just had enough 6224 } while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations ); 6225 } 6226 6227 // Update tween properties 6228 if ( parts ) { 6229 start = tween.start = +start || +target || 0; 6230 tween.unit = unit; 6231 // If a +=/-= token was provided, we're doing a relative animation 6232 tween.end = parts[ 1 ] ? 6233 start + ( parts[ 1 ] + 1 ) * parts[ 2 ] : 6234 +parts[ 2 ]; 6235 } 6236 6237 return tween; 6238 } ] 6239 }; 6240 6241// Animations created synchronously will run synchronously 6242function createFxNow() { 6243 setTimeout(function() { 6244 fxNow = undefined; 6245 }); 6246 return ( fxNow = jQuery.now() ); 6247} 6248 6249// Generate parameters to create a standard animation 6250function genFx( type, includeWidth ) { 6251 var which, 6252 i = 0, 6253 attrs = { height: type }; 6254 6255 // if we include width, step value is 1 to do all cssExpand values, 6256 // if we don't include width, step value is 2 to skip over Left and Right 6257 includeWidth = includeWidth ? 1 : 0; 6258 for ( ; i < 4 ; i += 2 - includeWidth ) { 6259 which = cssExpand[ i ]; 6260 attrs[ "margin" + which ] = attrs[ "padding" + which ] = type; 6261 } 6262 6263 if ( includeWidth ) { 6264 attrs.opacity = attrs.width = type; 6265 } 6266 6267 return attrs; 6268} 6269 6270function createTween( value, prop, animation ) { 6271 var tween, 6272 collection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ), 6273 index = 0, 6274 length = collection.length; 6275 for ( ; index < length; index++ ) { 6276 if ( (tween = collection[ index ].call( animation, prop, value )) ) { 6277 6278 // we're done with this property 6279 return tween; 6280 } 6281 } 6282} 6283 6284function defaultPrefilter( elem, props, opts ) { 6285 /* jshint validthis: true */ 6286 var prop, value, toggle, tween, hooks, oldfire, display, 6287 anim = this, 6288 orig = {}, 6289 style = elem.style, 6290 hidden = elem.nodeType && isHidden( elem ), 6291 dataShow = data_priv.get( elem, "fxshow" ); 6292 6293 // handle queue: false promises 6294 if ( !opts.queue ) { 6295 hooks = jQuery._queueHooks( elem, "fx" ); 6296 if ( hooks.unqueued == null ) { 6297 hooks.unqueued = 0; 6298 oldfire = hooks.empty.fire; 6299 hooks.empty.fire = function() { 6300 if ( !hooks.unqueued ) { 6301 oldfire(); 6302 } 6303 }; 6304 } 6305 hooks.unqueued++; 6306 6307 anim.always(function() { 6308 // doing this makes sure that the complete handler will be called 6309 // before this completes 6310 anim.always(function() { 6311 hooks.unqueued--; 6312 if ( !jQuery.queue( elem, "fx" ).length ) { 6313 hooks.empty.fire(); 6314 } 6315 }); 6316 }); 6317 } 6318 6319 // height/width overflow pass 6320 if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) { 6321 // Make sure that nothing sneaks out 6322 // Record all 3 overflow attributes because IE9-10 do not 6323 // change the overflow attribute when overflowX and 6324 // overflowY are set to the same value 6325 opts.overflow = [ style.overflow, style.overflowX, style.overflowY ]; 6326 6327 // Set display property to inline-block for height/width 6328 // animations on inline elements that are having width/height animated 6329 display = jQuery.css( elem, "display" ); 6330 // Get default display if display is currently "none" 6331 if ( display === "none" ) { 6332 display = defaultDisplay( elem.nodeName ); 6333 } 6334 if ( display === "inline" && 6335 jQuery.css( elem, "float" ) === "none" ) { 6336 6337 style.display = "inline-block"; 6338 } 6339 } 6340 6341 if ( opts.overflow ) { 6342 style.overflow = "hidden"; 6343 anim.always(function() { 6344 style.overflow = opts.overflow[ 0 ]; 6345 style.overflowX = opts.overflow[ 1 ]; 6346 style.overflowY = opts.overflow[ 2 ]; 6347 }); 6348 } 6349 6350 // show/hide pass 6351 for ( prop in props ) { 6352 value = props[ prop ]; 6353 if ( rfxtypes.exec( value ) ) { 6354 delete props[ prop ]; 6355 toggle = toggle || value === "toggle"; 6356 if ( value === ( hidden ? "hide" : "show" ) ) { 6357 6358 // If there is dataShow left over from a stopped hide or show and we are going to proceed with show, we should pretend to be hidden 6359 if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) { 6360 hidden = true; 6361 } else { 6362 continue; 6363 } 6364 } 6365 orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop ); 6366 } 6367 } 6368 6369 if ( !jQuery.isEmptyObject( orig ) ) { 6370 if ( dataShow ) { 6371 if ( "hidden" in dataShow ) { 6372 hidden = dataShow.hidden; 6373 } 6374 } else { 6375 dataShow = data_priv.access( elem, "fxshow", {} ); 6376 } 6377 6378 // store state if its toggle - enables .stop().toggle() to "reverse" 6379 if ( toggle ) { 6380 dataShow.hidden = !hidden; 6381 } 6382 if ( hidden ) { 6383 jQuery( elem ).show(); 6384 } else { 6385 anim.done(function() { 6386 jQuery( elem ).hide(); 6387 }); 6388 } 6389 anim.done(function() { 6390 var prop; 6391 6392 data_priv.remove( elem, "fxshow" ); 6393 for ( prop in orig ) { 6394 jQuery.style( elem, prop, orig[ prop ] ); 6395 } 6396 }); 6397 for ( prop in orig ) { 6398 tween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim ); 6399 6400 if ( !( prop in dataShow ) ) { 6401 dataShow[ prop ] = tween.start; 6402 if ( hidden ) { 6403 tween.end = tween.start; 6404 tween.start = prop === "width" || prop === "height" ? 1 : 0; 6405 } 6406 } 6407 } 6408 } 6409} 6410 6411function propFilter( props, specialEasing ) { 6412 var index, name, easing, value, hooks; 6413 6414 // camelCase, specialEasing and expand cssHook pass 6415 for ( index in props ) { 6416 name = jQuery.camelCase( index ); 6417 easing = specialEasing[ name ]; 6418 value = props[ index ]; 6419 if ( jQuery.isArray( value ) ) { 6420 easing = value[ 1 ]; 6421 value = props[ index ] = value[ 0 ]; 6422 } 6423 6424 if ( index !== name ) { 6425 props[ name ] = value; 6426 delete props[ index ]; 6427 } 6428 6429 hooks = jQuery.cssHooks[ name ]; 6430 if ( hooks && "expand" in hooks ) { 6431 value = hooks.expand( value ); 6432 delete props[ name ]; 6433 6434 // not quite $.extend, this wont overwrite keys already present. 6435 // also - reusing 'index' from above because we have the correct "name" 6436 for ( index in value ) { 6437 if ( !( index in props ) ) { 6438 props[ index ] = value[ index ]; 6439 specialEasing[ index ] = easing; 6440 } 6441 } 6442 } else { 6443 specialEasing[ name ] = easing; 6444 } 6445 } 6446} 6447 6448function Animation( elem, properties, options ) { 6449 var result, 6450 stopped, 6451 index = 0, 6452 length = animationPrefilters.length, 6453 deferred = jQuery.Deferred().always( function() { 6454 // don't match elem in the :animated selector 6455 delete tick.elem; 6456 }), 6457 tick = function() { 6458 if ( stopped ) { 6459 return false; 6460 } 6461 var currentTime = fxNow || createFxNow(), 6462 remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ), 6463 // archaic crash bug won't allow us to use 1 - ( 0.5 || 0 ) (#12497) 6464 temp = remaining / animation.duration || 0, 6465 percent = 1 - temp, 6466 index = 0, 6467 length = animation.tweens.length; 6468 6469 for ( ; index < length ; index++ ) { 6470 animation.tweens[ index ].run( percent ); 6471 } 6472 6473 deferred.notifyWith( elem, [ animation, percent, remaining ]); 6474 6475 if ( percent < 1 && length ) { 6476 return remaining; 6477 } else { 6478 deferred.resolveWith( elem, [ animation ] ); 6479 return false; 6480 } 6481 }, 6482 animation = deferred.promise({ 6483 elem: elem, 6484 props: jQuery.extend( {}, properties ), 6485 opts: jQuery.extend( true, { specialEasing: {} }, options ), 6486 originalProperties: properties, 6487 originalOptions: options, 6488 startTime: fxNow || createFxNow(), 6489 duration: options.duration, 6490 tweens: [], 6491 createTween: function( prop, end ) { 6492 var tween = jQuery.Tween( elem, animation.opts, prop, end, 6493 animation.opts.specialEasing[ prop ] || animation.opts.easing ); 6494 animation.tweens.push( tween ); 6495 return tween; 6496 }, 6497 stop: function( gotoEnd ) { 6498 var index = 0, 6499 // if we are going to the end, we want to run all the tweens 6500 // otherwise we skip this part 6501 length = gotoEnd ? animation.tweens.length : 0; 6502 if ( stopped ) { 6503 return this; 6504 } 6505 stopped = true; 6506 for ( ; index < length ; index++ ) { 6507 animation.tweens[ index ].run( 1 ); 6508 } 6509 6510 // resolve when we played the last frame 6511 // otherwise, reject 6512 if ( gotoEnd ) { 6513 deferred.resolveWith( elem, [ animation, gotoEnd ] ); 6514 } else { 6515 deferred.rejectWith( elem, [ animation, gotoEnd ] ); 6516 } 6517 return this; 6518 } 6519 }), 6520 props = animation.props; 6521 6522 propFilter( props, animation.opts.specialEasing ); 6523 6524 for ( ; index < length ; index++ ) { 6525 result = animationPrefilters[ index ].call( animation, elem, props, animation.opts ); 6526 if ( result ) { 6527 return result; 6528 } 6529 } 6530 6531 jQuery.map( props, createTween, animation ); 6532 6533 if ( jQuery.isFunction( animation.opts.start ) ) { 6534 animation.opts.start.call( elem, animation ); 6535 } 6536 6537 jQuery.fx.timer( 6538 jQuery.extend( tick, { 6539 elem: elem, 6540 anim: animation, 6541 queue: animation.opts.queue 6542 }) 6543 ); 6544 6545 // attach callbacks from options 6546 return animation.progress( animation.opts.progress ) 6547 .done( animation.opts.done, animation.opts.complete ) 6548 .fail( animation.opts.fail ) 6549 .always( animation.opts.always ); 6550} 6551 6552jQuery.Animation = jQuery.extend( Animation, { 6553 6554 tweener: function( props, callback ) { 6555 if ( jQuery.isFunction( props ) ) { 6556 callback = props; 6557 props = [ "*" ]; 6558 } else { 6559 props = props.split(" "); 6560 } 6561 6562 var prop, 6563 index = 0, 6564 length = props.length; 6565 6566 for ( ; index < length ; index++ ) { 6567 prop = props[ index ]; 6568 tweeners[ prop ] = tweeners[ prop ] || []; 6569 tweeners[ prop ].unshift( callback ); 6570 } 6571 }, 6572 6573 prefilter: function( callback, prepend ) { 6574 if ( prepend ) { 6575 animationPrefilters.unshift( callback ); 6576 } else { 6577 animationPrefilters.push( callback ); 6578 } 6579 } 6580}); 6581 6582jQuery.speed = function( speed, easing, fn ) { 6583 var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { 6584 complete: fn || !fn && easing || 6585 jQuery.isFunction( speed ) && speed, 6586 duration: speed, 6587 easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing 6588 }; 6589 6590 opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration : 6591 opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default; 6592 6593 // normalize opt.queue - true/undefined/null -> "fx" 6594 if ( opt.queue == null || opt.queue === true ) { 6595 opt.queue = "fx"; 6596 } 6597 6598 // Queueing 6599 opt.old = opt.complete; 6600 6601 opt.complete = function() { 6602 if ( jQuery.isFunction( opt.old ) ) { 6603 opt.old.call( this ); 6604 } 6605 6606 if ( opt.queue ) { 6607 jQuery.dequeue( this, opt.queue ); 6608 } 6609 }; 6610 6611 return opt; 6612}; 6613 6614jQuery.fn.extend({ 6615 fadeTo: function( speed, to, easing, callback ) { 6616 6617 // show any hidden elements after setting opacity to 0 6618 return this.filter( isHidden ).css( "opacity", 0 ).show() 6619 6620 // animate to the value specified 6621 .end().animate({ opacity: to }, speed, easing, callback ); 6622 }, 6623 animate: function( prop, speed, easing, callback ) { 6624 var empty = jQuery.isEmptyObject( prop ), 6625 optall = jQuery.speed( speed, easing, callback ), 6626 doAnimation = function() { 6627 // Operate on a copy of prop so per-property easing won't be lost 6628 var anim = Animation( this, jQuery.extend( {}, prop ), optall ); 6629 6630 // Empty animations, or finishing resolves immediately 6631 if ( empty || data_priv.get( this, "finish" ) ) { 6632 anim.stop( true ); 6633 } 6634 }; 6635 doAnimation.finish = doAnimation; 6636 6637 return empty || optall.queue === false ? 6638 this.each( doAnimation ) : 6639 this.queue( optall.queue, doAnimation ); 6640 }, 6641 stop: function( type, clearQueue, gotoEnd ) { 6642 var stopQueue = function( hooks ) { 6643 var stop = hooks.stop; 6644 delete hooks.stop; 6645 stop( gotoEnd ); 6646 }; 6647 6648 if ( typeof type !== "string" ) { 6649 gotoEnd = clearQueue; 6650 clearQueue = type; 6651 type = undefined; 6652 } 6653 if ( clearQueue && type !== false ) { 6654 this.queue( type || "fx", [] ); 6655 } 6656 6657 return this.each(function() { 6658 var dequeue = true, 6659 index = type != null && type + "queueHooks", 6660 timers = jQuery.timers, 6661 data = data_priv.get( this ); 6662 6663 if ( index ) { 6664 if ( data[ index ] && data[ index ].stop ) { 6665 stopQueue( data[ index ] ); 6666 } 6667 } else { 6668 for ( index in data ) { 6669 if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) { 6670 stopQueue( data[ index ] ); 6671 } 6672 } 6673 } 6674 6675 for ( index = timers.length; index--; ) { 6676 if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) { 6677 timers[ index ].anim.stop( gotoEnd ); 6678 dequeue = false; 6679 timers.splice( index, 1 ); 6680 } 6681 } 6682 6683 // start the next in the queue if the last step wasn't forced 6684 // timers currently will call their complete callbacks, which will dequeue 6685 // but only if they were gotoEnd 6686 if ( dequeue || !gotoEnd ) { 6687 jQuery.dequeue( this, type ); 6688 } 6689 }); 6690 }, 6691 finish: function( type ) { 6692 if ( type !== false ) { 6693 type = type || "fx"; 6694 } 6695 return this.each(function() { 6696 var index, 6697 data = data_priv.get( this ), 6698 queue = data[ type + "queue" ], 6699 hooks = data[ type + "queueHooks" ], 6700 timers = jQuery.timers, 6701 length = queue ? queue.length : 0; 6702 6703 // enable finishing flag on private data 6704 data.finish = true; 6705 6706 // empty the queue first 6707 jQuery.queue( this, type, [] ); 6708 6709 if ( hooks && hooks.stop ) { 6710 hooks.stop.call( this, true ); 6711 } 6712 6713 // look for any active animations, and finish them 6714 for ( index = timers.length; index--; ) { 6715 if ( timers[ index ].elem === this && timers[ index ].queue === type ) { 6716 timers[ index ].anim.stop( true ); 6717 timers.splice( index, 1 ); 6718 } 6719 } 6720 6721 // look for any animations in the old queue and finish them 6722 for ( index = 0; index < length; index++ ) { 6723 if ( queue[ index ] && queue[ index ].finish ) { 6724 queue[ index ].finish.call( this ); 6725 } 6726 } 6727 6728 // turn off finishing flag 6729 delete data.finish; 6730 }); 6731 } 6732}); 6733 6734jQuery.each([ "toggle", "show", "hide" ], function( i, name ) { 6735 var cssFn = jQuery.fn[ name ]; 6736 jQuery.fn[ name ] = function( speed, easing, callback ) { 6737 return speed == null || typeof speed === "boolean" ? 6738 cssFn.apply( this, arguments ) : 6739 this.animate( genFx( name, true ), speed, easing, callback ); 6740 }; 6741}); 6742 6743// Generate shortcuts for custom animations 6744jQuery.each({ 6745 slideDown: genFx("show"), 6746 slideUp: genFx("hide"), 6747 slideToggle: genFx("toggle"), 6748 fadeIn: { opacity: "show" }, 6749 fadeOut: { opacity: "hide" }, 6750 fadeToggle: { opacity: "toggle" } 6751}, function( name, props ) { 6752 jQuery.fn[ name ] = function( speed, easing, callback ) { 6753 return this.animate( props, speed, easing, callback ); 6754 }; 6755}); 6756 6757jQuery.timers = []; 6758jQuery.fx.tick = function() { 6759 var timer, 6760 i = 0, 6761 timers = jQuery.timers; 6762 6763 fxNow = jQuery.now(); 6764 6765 for ( ; i < timers.length; i++ ) { 6766 timer = timers[ i ]; 6767 // Checks the timer has not already been removed 6768 if ( !timer() && timers[ i ] === timer ) { 6769 timers.splice( i--, 1 ); 6770 } 6771 } 6772 6773 if ( !timers.length ) { 6774 jQuery.fx.stop(); 6775 } 6776 fxNow = undefined; 6777}; 6778 6779jQuery.fx.timer = function( timer ) { 6780 jQuery.timers.push( timer ); 6781 if ( timer() ) { 6782 jQuery.fx.start(); 6783 } else { 6784 jQuery.timers.pop(); 6785 } 6786}; 6787 6788jQuery.fx.interval = 13; 6789 6790jQuery.fx.start = function() { 6791 if ( !timerId ) { 6792 timerId = setInterval( jQuery.fx.tick, jQuery.fx.interval ); 6793 } 6794}; 6795 6796jQuery.fx.stop = function() { 6797 clearInterval( timerId ); 6798 timerId = null; 6799}; 6800 6801jQuery.fx.speeds = { 6802 slow: 600, 6803 fast: 200, 6804 // Default speed 6805 _default: 400 6806}; 6807 6808 6809// Based off of the plugin by Clint Helfers, with permission. 6810// http://blindsignals.com/index.php/2009/07/jquery-delay/ 6811jQuery.fn.delay = function( time, type ) { 6812 time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; 6813 type = type || "fx"; 6814 6815 return this.queue( type, function( next, hooks ) { 6816 var timeout = setTimeout( next, time ); 6817 hooks.stop = function() { 6818 clearTimeout( timeout ); 6819 }; 6820 }); 6821}; 6822 6823 6824(function() { 6825 var input = document.createElement( "input" ), 6826 select = document.createElement( "select" ), 6827 opt = select.appendChild( document.createElement( "option" ) ); 6828 6829 input.type = "checkbox"; 6830 6831 // Support: iOS 5.1, Android 4.x, Android 2.3 6832 // Check the default checkbox/radio value ("" on old WebKit; "on" elsewhere) 6833 support.checkOn = input.value !== ""; 6834 6835 // Must access the parent to make an option select properly 6836 // Support: IE9, IE10 6837 support.optSelected = opt.selected; 6838 6839 // Make sure that the options inside disabled selects aren't marked as disabled 6840 // (WebKit marks them as disabled) 6841 select.disabled = true; 6842 support.optDisabled = !opt.disabled; 6843 6844 // Check if an input maintains its value after becoming a radio 6845 // Support: IE9, IE10 6846 input = document.createElement( "input" ); 6847 input.value = "t"; 6848 input.type = "radio"; 6849 support.radioValue = input.value === "t"; 6850})(); 6851 6852 6853var nodeHook, boolHook, 6854 attrHandle = jQuery.expr.attrHandle; 6855 6856jQuery.fn.extend({ 6857 attr: function( name, value ) { 6858 return access( this, jQuery.attr, name, value, arguments.length > 1 ); 6859 }, 6860 6861 removeAttr: function( name ) { 6862 return this.each(function() { 6863 jQuery.removeAttr( this, name ); 6864 }); 6865 } 6866}); 6867 6868jQuery.extend({ 6869 attr: function( elem, name, value ) { 6870 var hooks, ret, 6871 nType = elem.nodeType; 6872 6873 // don't get/set attributes on text, comment and attribute nodes 6874 if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { 6875 return; 6876 } 6877 6878 // Fallback to prop when attributes are not supported 6879 if ( typeof elem.getAttribute === strundefined ) { 6880 return jQuery.prop( elem, name, value ); 6881 } 6882 6883 // All attributes are lowercase 6884 // Grab necessary hook if one is defined 6885 if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { 6886 name = name.toLowerCase(); 6887 hooks = jQuery.attrHooks[ name ] || 6888 ( jQuery.expr.match.bool.test( name ) ? boolHook : nodeHook ); 6889 } 6890 6891 if ( value !== undefined ) { 6892 6893 if ( value === null ) { 6894 jQuery.removeAttr( elem, name ); 6895 6896 } else if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { 6897 return ret; 6898 6899 } else { 6900 elem.setAttribute( name, value + "" ); 6901 return value; 6902 } 6903 6904 } else if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) { 6905 return ret; 6906 6907 } else { 6908 ret = jQuery.find.attr( elem, name ); 6909 6910 // Non-existent attributes return null, we normalize to undefined 6911 return ret == null ? 6912 undefined : 6913 ret; 6914 } 6915 }, 6916 6917 removeAttr: function( elem, value ) { 6918 var name, propName, 6919 i = 0, 6920 attrNames = value && value.match( rnotwhite ); 6921 6922 if ( attrNames && elem.nodeType === 1 ) { 6923 while ( (name = attrNames[i++]) ) { 6924 propName = jQuery.propFix[ name ] || name; 6925 6926 // Boolean attributes get special treatment (#10870) 6927 if ( jQuery.expr.match.bool.test( name ) ) { 6928 // Set corresponding property to false 6929 elem[ propName ] = false; 6930 } 6931 6932 elem.removeAttribute( name ); 6933 } 6934 } 6935 }, 6936 6937 attrHooks: { 6938 type: { 6939 set: function( elem, value ) { 6940 if ( !support.radioValue && value === "radio" && 6941 jQuery.nodeName( elem, "input" ) ) { 6942 // Setting the type on a radio button after the value resets the value in IE6-9 6943 // Reset value to default in case type is set after value during creation 6944 var val = elem.value; 6945 elem.setAttribute( "type", value ); 6946 if ( val ) { 6947 elem.value = val; 6948 } 6949 return value; 6950 } 6951 } 6952 } 6953 } 6954}); 6955 6956// Hooks for boolean attributes 6957boolHook = { 6958 set: function( elem, value, name ) { 6959 if ( value === false ) { 6960 // Remove boolean attributes when set to false 6961 jQuery.removeAttr( elem, name ); 6962 } else { 6963 elem.setAttribute( name, name ); 6964 } 6965 return name; 6966 } 6967}; 6968jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) { 6969 var getter = attrHandle[ name ] || jQuery.find.attr; 6970 6971 attrHandle[ name ] = function( elem, name, isXML ) { 6972 var ret, handle; 6973 if ( !isXML ) { 6974 // Avoid an infinite loop by temporarily removing this function from the getter 6975 handle = attrHandle[ name ]; 6976 attrHandle[ name ] = ret; 6977 ret = getter( elem, name, isXML ) != null ? 6978 name.toLowerCase() : 6979 null; 6980 attrHandle[ name ] = handle; 6981 } 6982 return ret; 6983 }; 6984}); 6985 6986 6987 6988 6989var rfocusable = /^(?:input|select|textarea|button)$/i; 6990 6991jQuery.fn.extend({ 6992 prop: function( name, value ) { 6993 return access( this, jQuery.prop, name, value, arguments.length > 1 ); 6994 }, 6995 6996 removeProp: function( name ) { 6997 return this.each(function() { 6998 delete this[ jQuery.propFix[ name ] || name ]; 6999 }); 7000 } 7001}); 7002 7003jQuery.extend({ 7004 propFix: { 7005 "for": "htmlFor", 7006 "class": "className" 7007 }, 7008 7009 prop: function( elem, name, value ) { 7010 var ret, hooks, notxml, 7011 nType = elem.nodeType; 7012 7013 // don't get/set properties on text, comment and attribute nodes 7014 if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { 7015 return; 7016 } 7017 7018 notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); 7019 7020 if ( notxml ) { 7021 // Fix name and attach hooks 7022 name = jQuery.propFix[ name ] || name; 7023 hooks = jQuery.propHooks[ name ]; 7024 } 7025 7026 if ( value !== undefined ) { 7027 return hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ? 7028 ret : 7029 ( elem[ name ] = value ); 7030 7031 } else { 7032 return hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ? 7033 ret : 7034 elem[ name ]; 7035 } 7036 }, 7037 7038 propHooks: { 7039 tabIndex: { 7040 get: function( elem ) { 7041 return elem.hasAttribute( "tabindex" ) || rfocusable.test( elem.nodeName ) || elem.href ? 7042 elem.tabIndex : 7043 -1; 7044 } 7045 } 7046 } 7047}); 7048 7049// Support: IE9+ 7050// Selectedness for an option in an optgroup can be inaccurate 7051if ( !support.optSelected ) { 7052 jQuery.propHooks.selected = { 7053 get: function( elem ) { 7054 var parent = elem.parentNode; 7055 if ( parent && parent.parentNode ) { 7056 parent.parentNode.selectedIndex; 7057 } 7058 return null; 7059 } 7060 }; 7061} 7062 7063jQuery.each([ 7064 "tabIndex", 7065 "readOnly", 7066 "maxLength", 7067 "cellSpacing", 7068 "cellPadding", 7069 "rowSpan", 7070 "colSpan", 7071 "useMap", 7072 "frameBorder", 7073 "contentEditable" 7074], function() { 7075 jQuery.propFix[ this.toLowerCase() ] = this; 7076}); 7077 7078 7079 7080 7081var rclass = /[\t\r\n\f]/g; 7082 7083jQuery.fn.extend({ 7084 addClass: function( value ) { 7085 var classes, elem, cur, clazz, j, finalValue, 7086 proceed = typeof value === "string" && value, 7087 i = 0, 7088 len = this.length; 7089 7090 if ( jQuery.isFunction( value ) ) { 7091 return this.each(function( j ) { 7092 jQuery( this ).addClass( value.call( this, j, this.className ) ); 7093 }); 7094 } 7095 7096 if ( proceed ) { 7097 // The disjunction here is for better compressibility (see removeClass) 7098 classes = ( value || "" ).match( rnotwhite ) || []; 7099 7100 for ( ; i < len; i++ ) { 7101 elem = this[ i ]; 7102 cur = elem.nodeType === 1 && ( elem.className ? 7103 ( " " + elem.className + " " ).replace( rclass, " " ) : 7104 " " 7105 ); 7106 7107 if ( cur ) { 7108 j = 0; 7109 while ( (clazz = classes[j++]) ) { 7110 if ( cur.indexOf( " " + clazz + " " ) < 0 ) { 7111 cur += clazz + " "; 7112 } 7113 } 7114 7115 // only assign if different to avoid unneeded rendering. 7116 finalValue = jQuery.trim( cur ); 7117 if ( elem.className !== finalValue ) { 7118 elem.className = finalValue; 7119 } 7120 } 7121 } 7122 } 7123 7124 return this; 7125 }, 7126 7127 removeClass: function( value ) { 7128 var classes, elem, cur, clazz, j, finalValue, 7129 proceed = arguments.length === 0 || typeof value === "string" && value, 7130 i = 0, 7131 len = this.length; 7132 7133 if ( jQuery.isFunction( value ) ) { 7134 return this.each(function( j ) { 7135 jQuery( this ).removeClass( value.call( this, j, this.className ) ); 7136 }); 7137 } 7138 if ( proceed ) { 7139 classes = ( value || "" ).match( rnotwhite ) || []; 7140 7141 for ( ; i < len; i++ ) { 7142 elem = this[ i ]; 7143 // This expression is here for better compressibility (see addClass) 7144 cur = elem.nodeType === 1 && ( elem.className ? 7145 ( " " + elem.className + " " ).replace( rclass, " " ) : 7146 "" 7147 ); 7148 7149 if ( cur ) { 7150 j = 0; 7151 while ( (clazz = classes[j++]) ) { 7152 // Remove *all* instances 7153 while ( cur.indexOf( " " + clazz + " " ) >= 0 ) { 7154 cur = cur.replace( " " + clazz + " ", " " ); 7155 } 7156 } 7157 7158 // only assign if different to avoid unneeded rendering. 7159 finalValue = value ? jQuery.trim( cur ) : ""; 7160 if ( elem.className !== finalValue ) { 7161 elem.className = finalValue; 7162 } 7163 } 7164 } 7165 } 7166 7167 return this; 7168 }, 7169 7170 toggleClass: function( value, stateVal ) { 7171 var type = typeof value; 7172 7173 if ( typeof stateVal === "boolean" && type === "string" ) { 7174 return stateVal ? this.addClass( value ) : this.removeClass( value ); 7175 } 7176 7177 if ( jQuery.isFunction( value ) ) { 7178 return this.each(function( i ) { 7179 jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal ); 7180 }); 7181 } 7182 7183 return this.each(function() { 7184 if ( type === "string" ) { 7185 // toggle individual class names 7186 var className, 7187 i = 0, 7188 self = jQuery( this ), 7189 classNames = value.match( rnotwhite ) || []; 7190 7191 while ( (className = classNames[ i++ ]) ) { 7192 // check each className given, space separated list 7193 if ( self.hasClass( className ) ) { 7194 self.removeClass( className ); 7195 } else { 7196 self.addClass( className ); 7197 } 7198 } 7199 7200 // Toggle whole class name 7201 } else if ( type === strundefined || type === "boolean" ) { 7202 if ( this.className ) { 7203 // store className if set 7204 data_priv.set( this, "__className__", this.className ); 7205 } 7206 7207 // If the element has a class name or if we're passed "false", 7208 // then remove the whole classname (if there was one, the above saved it). 7209 // Otherwise bring back whatever was previously saved (if anything), 7210 // falling back to the empty string if nothing was stored. 7211 this.className = this.className || value === false ? "" : data_priv.get( this, "__className__" ) || ""; 7212 } 7213 }); 7214 }, 7215 7216 hasClass: function( selector ) { 7217 var className = " " + selector + " ", 7218 i = 0, 7219 l = this.length; 7220 for ( ; i < l; i++ ) { 7221 if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) { 7222 return true; 7223 } 7224 } 7225 7226 return false; 7227 } 7228}); 7229 7230 7231 7232 7233var rreturn = /\r/g; 7234 7235jQuery.fn.extend({ 7236 val: function( value ) { 7237 var hooks, ret, isFunction, 7238 elem = this[0]; 7239 7240 if ( !arguments.length ) { 7241 if ( elem ) { 7242 hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ]; 7243 7244 if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) { 7245 return ret; 7246 } 7247 7248 ret = elem.value; 7249 7250 return typeof ret === "string" ? 7251 // handle most common string cases 7252 ret.replace(rreturn, "") : 7253 // handle cases where value is null/undef or number 7254 ret == null ? "" : ret; 7255 } 7256 7257 return; 7258 } 7259 7260 isFunction = jQuery.isFunction( value ); 7261 7262 return this.each(function( i ) { 7263 var val; 7264 7265 if ( this.nodeType !== 1 ) { 7266 return; 7267 } 7268 7269 if ( isFunction ) { 7270 val = value.call( this, i, jQuery( this ).val() ); 7271 } else { 7272 val = value; 7273 } 7274 7275 // Treat null/undefined as ""; convert numbers to string 7276 if ( val == null ) { 7277 val = ""; 7278 7279 } else if ( typeof val === "number" ) { 7280 val += ""; 7281 7282 } else if ( jQuery.isArray( val ) ) { 7283 val = jQuery.map( val, function( value ) { 7284 return value == null ? "" : value + ""; 7285 }); 7286 } 7287 7288 hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; 7289 7290 // If set returns undefined, fall back to normal setting 7291 if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) { 7292 this.value = val; 7293 } 7294 }); 7295 } 7296}); 7297 7298jQuery.extend({ 7299 valHooks: { 7300 select: { 7301 get: function( elem ) { 7302 var value, option, 7303 options = elem.options, 7304 index = elem.selectedIndex, 7305 one = elem.type === "select-one" || index < 0, 7306 values = one ? null : [], 7307 max = one ? index + 1 : options.length, 7308 i = index < 0 ? 7309 max : 7310 one ? index : 0; 7311 7312 // Loop through all the selected options 7313 for ( ; i < max; i++ ) { 7314 option = options[ i ]; 7315 7316 // IE6-9 doesn't update selected after form reset (#2551) 7317 if ( ( option.selected || i === index ) && 7318 // Don't return options that are disabled or in a disabled optgroup 7319 ( support.optDisabled ? !option.disabled : option.getAttribute( "disabled" ) === null ) && 7320 ( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) { 7321 7322 // Get the specific value for the option 7323 value = jQuery( option ).val(); 7324 7325 // We don't need an array for one selects 7326 if ( one ) { 7327 return value; 7328 } 7329 7330 // Multi-Selects return an array 7331 values.push( value ); 7332 } 7333 } 7334 7335 return values; 7336 }, 7337 7338 set: function( elem, value ) { 7339 var optionSet, option, 7340 options = elem.options, 7341 values = jQuery.makeArray( value ), 7342 i = options.length; 7343 7344 while ( i-- ) { 7345 option = options[ i ]; 7346 if ( (option.selected = jQuery.inArray( jQuery(option).val(), values ) >= 0) ) { 7347 optionSet = true; 7348 } 7349 } 7350 7351 // force browsers to behave consistently when non-matching value is set 7352 if ( !optionSet ) { 7353 elem.selectedIndex = -1; 7354 } 7355 return values; 7356 } 7357 } 7358 } 7359}); 7360 7361// Radios and checkboxes getter/setter 7362jQuery.each([ "radio", "checkbox" ], function() { 7363 jQuery.valHooks[ this ] = { 7364 set: function( elem, value ) { 7365 if ( jQuery.isArray( value ) ) { 7366 return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 ); 7367 } 7368 } 7369 }; 7370 if ( !support.checkOn ) { 7371 jQuery.valHooks[ this ].get = function( elem ) { 7372 // Support: Webkit 7373 // "" is returned instead of "on" if a value isn't specified 7374 return elem.getAttribute("value") === null ? "on" : elem.value; 7375 }; 7376 } 7377}); 7378 7379 7380 7381 7382// Return jQuery for attributes-only inclusion 7383 7384 7385jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " + 7386 "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + 7387 "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) { 7388 7389 // Handle event binding 7390 jQuery.fn[ name ] = function( data, fn ) { 7391 return arguments.length > 0 ? 7392 this.on( name, null, data, fn ) : 7393 this.trigger( name ); 7394 }; 7395}); 7396 7397jQuery.fn.extend({ 7398 hover: function( fnOver, fnOut ) { 7399 return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); 7400 }, 7401 7402 bind: function( types, data, fn ) { 7403 return this.on( types, null, data, fn ); 7404 }, 7405 unbind: function( types, fn ) { 7406 return this.off( types, null, fn ); 7407 }, 7408 7409 delegate: function( selector, types, data, fn ) { 7410 return this.on( types, selector, data, fn ); 7411 }, 7412 undelegate: function( selector, types, fn ) { 7413 // ( namespace ) or ( selector, types [, fn] ) 7414 return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn ); 7415 } 7416}); 7417 7418 7419var nonce = jQuery.now(); 7420 7421var rquery = (/\?/); 7422 7423 7424 7425// Support: Android 2.3 7426// Workaround failure to string-cast null input 7427jQuery.parseJSON = function( data ) { 7428 return JSON.parse( data + "" ); 7429}; 7430 7431 7432// Cross-browser xml parsing 7433jQuery.parseXML = function( data ) { 7434 var xml, tmp; 7435 if ( !data || typeof data !== "string" ) { 7436 return null; 7437 } 7438 7439 // Support: IE9 7440 try { 7441 tmp = new DOMParser(); 7442 xml = tmp.parseFromString( data, "text/xml" ); 7443 } catch ( e ) { 7444 xml = undefined; 7445 } 7446 7447 if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) { 7448 jQuery.error( "Invalid XML: " + data ); 7449 } 7450 return xml; 7451}; 7452 7453 7454var 7455 // Document location 7456 ajaxLocParts, 7457 ajaxLocation, 7458 7459 rhash = /#.*$/, 7460 rts = /([?&])_=[^&]*/, 7461 rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg, 7462 // #7653, #8125, #8152: local protocol detection 7463 rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, 7464 rnoContent = /^(?:GET|HEAD)$/, 7465 rprotocol = /^\/\//, 7466 rurl = /^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/, 7467 7468 /* Prefilters 7469 * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) 7470 * 2) These are called: 7471 * - BEFORE asking for a transport 7472 * - AFTER param serialization (s.data is a string if s.processData is true) 7473 * 3) key is the dataType 7474 * 4) the catchall symbol "*" can be used 7475 * 5) execution will start with transport dataType and THEN continue down to "*" if needed 7476 */ 7477 prefilters = {}, 7478 7479 /* Transports bindings 7480 * 1) key is the dataType 7481 * 2) the catchall symbol "*" can be used 7482 * 3) selection will start with transport dataType and THEN go to "*" if needed 7483 */ 7484 transports = {}, 7485 7486 // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression 7487 allTypes = "*/".concat("*"); 7488 7489// #8138, IE may throw an exception when accessing 7490// a field from window.location if document.domain has been set 7491try { 7492 ajaxLocation = location.href; 7493} catch( e ) { 7494 // Use the href attribute of an A element 7495 // since IE will modify it given document.location 7496 ajaxLocation = document.createElement( "a" ); 7497 ajaxLocation.href = ""; 7498 ajaxLocation = ajaxLocation.href; 7499} 7500 7501// Segment location into parts 7502ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || []; 7503 7504// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport 7505function addToPrefiltersOrTransports( structure ) { 7506 7507 // dataTypeExpression is optional and defaults to "*" 7508 return function( dataTypeExpression, func ) { 7509 7510 if ( typeof dataTypeExpression !== "string" ) { 7511 func = dataTypeExpression; 7512 dataTypeExpression = "*"; 7513 } 7514 7515 var dataType, 7516 i = 0, 7517 dataTypes = dataTypeExpression.toLowerCase().match( rnotwhite ) || []; 7518 7519 if ( jQuery.isFunction( func ) ) { 7520 // For each dataType in the dataTypeExpression
vendor: 4,244 bytes, lines 7521-7671
7521 while ( (dataType = dataTypes[i++]) ) { 7522 // Prepend if requested 7523 if ( dataType[0] === "+" ) { 7524 dataType = dataType.slice( 1 ) || "*"; 7525 (structure[ dataType ] = structure[ dataType ] || []).unshift( func ); 7526 7527 // Otherwise append 7528 } else { 7529 (structure[ dataType ] = structure[ dataType ] || []).push( func ); 7530 } 7531 } 7532 } 7533 }; 7534} 7535 7536// Base inspection function for prefilters and transports 7537function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) { 7538 7539 var inspected = {}, 7540 seekingTransport = ( structure === transports ); 7541 7542 function inspect( dataType ) { 7543 var selected; 7544 inspected[ dataType ] = true; 7545 jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) { 7546 var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR ); 7547 if ( typeof dataTypeOrTransport === "string" && !seekingTransport && !inspected[ dataTypeOrTransport ] ) { 7548 options.dataTypes.unshift( dataTypeOrTransport ); 7549 inspect( dataTypeOrTransport ); 7550 return false; 7551 } else if ( seekingTransport ) { 7552 return !( selected = dataTypeOrTransport ); 7553 } 7554 }); 7555 return selected; 7556 } 7557 7558 return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" ); 7559} 7560 7561// A special extend for ajax options 7562// that takes "flat" options (not to be deep extended) 7563// Fixes #9887 7564function ajaxExtend( target, src ) { 7565 var key, deep, 7566 flatOptions = jQuery.ajaxSettings.flatOptions || {}; 7567 7568 for ( key in src ) { 7569 if ( src[ key ] !== undefined ) { 7570 ( flatOptions[ key ] ? target : ( deep || (deep = {}) ) )[ key ] = src[ key ]; 7571 } 7572 } 7573 if ( deep ) { 7574 jQuery.extend( true, target, deep ); 7575 } 7576 7577 return target; 7578} 7579 7580/* Handles responses to an ajax request: 7581 * - finds the right dataType (mediates between content-type and expected dataType) 7582 * - returns the corresponding response 7583 */ 7584function ajaxHandleResponses( s, jqXHR, responses ) { 7585 7586 var ct, type, finalDataType, firstDataType, 7587 contents = s.contents, 7588 dataTypes = s.dataTypes; 7589 7590 // Remove auto dataType and get content-type in the process 7591 while ( dataTypes[ 0 ] === "*" ) { 7592 dataTypes.shift(); 7593 if ( ct === undefined ) { 7594 ct = s.mimeType || jqXHR.getResponseHeader("Content-Type"); 7595 } 7596 } 7597 7598 // Check if we're dealing with a known content-type 7599 if ( ct ) { 7600 for ( type in contents ) { 7601 if ( contents[ type ] && contents[ type ].test( ct ) ) { 7602 dataTypes.unshift( type ); 7603 break; 7604 } 7605 } 7606 } 7607 7608 // Check to see if we have a response for the expected dataType 7609 if ( dataTypes[ 0 ] in responses ) { 7610 finalDataType = dataTypes[ 0 ]; 7611 } else { 7612 // Try convertible dataTypes 7613 for ( type in responses ) { 7614 if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) { 7615 finalDataType = type; 7616 break; 7617 } 7618 if ( !firstDataType ) { 7619 firstDataType = type; 7620 } 7621 } 7622 // Or just use first one 7623 finalDataType = finalDataType || firstDataType; 7624 } 7625 7626 // If we found a dataType 7627 // We add the dataType to the list if needed 7628 // and return the corresponding response 7629 if ( finalDataType ) { 7630 if ( finalDataType !== dataTypes[ 0 ] ) { 7631 dataTypes.unshift( finalDataType ); 7632 } 7633 return responses[ finalDataType ]; 7634 } 7635} 7636 7637/* Chain conversions given the request and the original response 7638 * Also sets the responseXXX fields on the jqXHR instance 7639 */ 7640function ajaxConvert( s, response, jqXHR, isSuccess ) { 7641 var conv2, current, conv, tmp, prev, 7642 converters = {}, 7643 // Work with a copy of dataTypes in case we need to modify it for conversion 7644 dataTypes = s.dataTypes.slice(); 7645 7646 // Create converters map with lowercased keys 7647 if ( dataTypes[ 1 ] ) { 7648 for ( conv in s.converters ) { 7649 converters[ conv.toLowerCase() ] = s.converters[ conv ]; 7650 } 7651 } 7652 7653 current = dataTypes.shift(); 7654 7655 // Convert to each sequential dataType 7656 while ( current ) { 7657 7658 if ( s.responseFields[ current ] ) { 7659 jqXHR[ s.responseFields[ current ] ] = response; 7660 } 7661 7662 // Apply the dataFilter if provided 7663 if ( !prev && isSuccess && s.dataFilter ) { 7664 response = s.dataFilter( response, s.dataType ); 7665 } 7666 7667 prev = current; 7668 current = dataTypes.shift(); 7669 7670 if ( current ) { 7671
vendor: 9,105 bytes, lines 7672-8002
7672 // There's only work to do if current dataType is non-auto 7673 if ( current === "*" ) { 7674 7675 current = prev; 7676 7677 // Convert response if prev dataType is non-auto and differs from current 7678 } else if ( prev !== "*" && prev !== current ) { 7679 7680 // Seek a direct converter 7681 conv = converters[ prev + " " + current ] || converters[ "* " + current ]; 7682 7683 // If none found, seek a pair 7684 if ( !conv ) { 7685 for ( conv2 in converters ) { 7686 7687 // If conv2 outputs current 7688 tmp = conv2.split( " " ); 7689 if ( tmp[ 1 ] === current ) { 7690 7691 // If prev can be converted to accepted input 7692 conv = converters[ prev + " " + tmp[ 0 ] ] || 7693 converters[ "* " + tmp[ 0 ] ]; 7694 if ( conv ) { 7695 // Condense equivalence converters 7696 if ( conv === true ) { 7697 conv = converters[ conv2 ]; 7698 7699 // Otherwise, insert the intermediate dataType 7700 } else if ( converters[ conv2 ] !== true ) { 7701 current = tmp[ 0 ]; 7702 dataTypes.unshift( tmp[ 1 ] ); 7703 } 7704 break; 7705 } 7706 } 7707 } 7708 } 7709 7710 // Apply converter (if not an equivalence) 7711 if ( conv !== true ) { 7712 7713 // Unless errors are allowed to bubble, catch and return them 7714 if ( conv && s[ "throws" ] ) { 7715 response = conv( response ); 7716 } else { 7717 try { 7718 response = conv( response ); 7719 } catch ( e ) { 7720 return { state: "parsererror", error: conv ? e : "No conversion from " + prev + " to " + current }; 7721 } 7722 } 7723 } 7724 } 7725 } 7726 } 7727 7728 return { state: "success", data: response }; 7729} 7730 7731jQuery.extend({ 7732 7733 // Counter for holding the number of active queries 7734 active: 0, 7735 7736 // Last-Modified header cache for next request 7737 lastModified: {}, 7738 etag: {}, 7739 7740 ajaxSettings: { 7741 url: ajaxLocation, 7742 type: "GET", 7743 isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ), 7744 global: true, 7745 processData: true, 7746 async: true, 7747 contentType: "application/x-www-form-urlencoded; charset=UTF-8", 7748 /* 7749 timeout: 0, 7750 data: null, 7751 dataType: null, 7752 username: null, 7753 password: null, 7754 cache: null, 7755 throws: false, 7756 traditional: false, 7757 headers: {}, 7758 */ 7759 7760 accepts: { 7761 "*": allTypes, 7762 text: "text/plain", 7763 html: "text/html", 7764 xml: "application/xml, text/xml", 7765 json: "application/json, text/javascript" 7766 }, 7767 7768 contents: { 7769 xml: /xml/, 7770 html: /html/, 7771 json: /json/ 7772 }, 7773 7774 responseFields: { 7775 xml: "responseXML", 7776 text: "responseText", 7777 json: "responseJSON" 7778 }, 7779 7780 // Data converters 7781 // Keys separate source (or catchall "*") and destination types with a single space 7782 converters: { 7783 7784 // Convert anything to text 7785 "* text": String, 7786 7787 // Text to html (true = no transformation) 7788 "text html": true, 7789 7790 // Evaluate text as a json expression 7791 "text json": jQuery.parseJSON, 7792 7793 // Parse text as xml 7794 "text xml": jQuery.parseXML 7795 }, 7796 7797 // For options that shouldn't be deep extended: 7798 // you can add your own custom options here if 7799 // and when you create one that shouldn't be 7800 // deep extended (see ajaxExtend) 7801 flatOptions: { 7802 url: true, 7803 context: true 7804 } 7805 }, 7806 7807 // Creates a full fledged settings object into target 7808 // with both ajaxSettings and settings fields. 7809 // If target is omitted, writes into ajaxSettings. 7810 ajaxSetup: function( target, settings ) { 7811 return settings ? 7812 7813 // Building a settings object 7814 ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) : 7815 7816 // Extending ajaxSettings 7817 ajaxExtend( jQuery.ajaxSettings, target ); 7818 }, 7819 7820 ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), 7821 ajaxTransport: addToPrefiltersOrTransports( transports ), 7822 7823 // Main method 7824 ajax: function( url, options ) { 7825 7826 // If url is an object, simulate pre-1.5 signature 7827 if ( typeof url === "object" ) { 7828 options = url; 7829 url = undefined; 7830 } 7831 7832 // Force options to be an object 7833 options = options || {}; 7834 7835 var transport, 7836 // URL without anti-cache param 7837 cacheURL, 7838 // Response headers 7839 responseHeadersString, 7840 responseHeaders, 7841 // timeout handle 7842 timeoutTimer, 7843 // Cross-domain detection vars 7844 parts, 7845 // To know if global events are to be dispatched 7846 fireGlobals, 7847 // Loop variable 7848 i, 7849 // Create the final options object 7850 s = jQuery.ajaxSetup( {}, options ), 7851 // Callbacks context 7852 callbackContext = s.context || s, 7853 // Context for global events is callbackContext if it is a DOM node or jQuery collection 7854 globalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jquery ) ? 7855 jQuery( callbackContext ) : 7856 jQuery.event, 7857 // Deferreds 7858 deferred = jQuery.Deferred(), 7859 completeDeferred = jQuery.Callbacks("once memory"), 7860 // Status-dependent callbacks 7861 statusCode = s.statusCode || {}, 7862 // Headers (they are sent all at once) 7863 requestHeaders = {}, 7864 requestHeadersNames = {}, 7865 // The jqXHR state 7866 state = 0, 7867 // Default abort message 7868 strAbort = "canceled", 7869 // Fake xhr 7870 jqXHR = { 7871 readyState: 0, 7872 7873 // Builds headers hashtable if needed 7874 getResponseHeader: function( key ) { 7875 var match; 7876 if ( state === 2 ) { 7877 if ( !responseHeaders ) { 7878 responseHeaders = {}; 7879 while ( (match = rheaders.exec( responseHeadersString )) ) { 7880 responseHeaders[ match[1].toLowerCase() ] = match[ 2 ]; 7881 } 7882 } 7883 match = responseHeaders[ key.toLowerCase() ]; 7884 } 7885 return match == null ? null : match; 7886 }, 7887 7888 // Raw string 7889 getAllResponseHeaders: function() { 7890 return state === 2 ? responseHeadersString : null; 7891 }, 7892 7893 // Caches the header 7894 setRequestHeader: function( name, value ) { 7895 var lname = name.toLowerCase(); 7896 if ( !state ) { 7897 name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name; 7898 requestHeaders[ name ] = value; 7899 } 7900 return this; 7901 }, 7902 7903 // Overrides response content-type header 7904 overrideMimeType: function( type ) { 7905 if ( !state ) { 7906 s.mimeType = type; 7907 } 7908 return this; 7909 }, 7910 7911 // Status-dependent callbacks 7912 statusCode: function( map ) { 7913 var code; 7914 if ( map ) { 7915 if ( state < 2 ) { 7916 for ( code in map ) { 7917 // Lazy-add the new callback in a way that preserves old ones 7918 statusCode[ code ] = [ statusCode[ code ], map[ code ] ]; 7919 } 7920 } else { 7921 // Execute the appropriate callbacks 7922 jqXHR.always( map[ jqXHR.status ] ); 7923 } 7924 } 7925 return this; 7926 }, 7927 7928 // Cancel the request 7929 abort: function( statusText ) { 7930 var finalText = statusText || strAbort; 7931 if ( transport ) { 7932 transport.abort( finalText ); 7933 } 7934 done( 0, finalText ); 7935 return this; 7936 } 7937 }; 7938 7939 // Attach deferreds 7940 deferred.promise( jqXHR ).complete = completeDeferred.add; 7941 jqXHR.success = jqXHR.done; 7942 jqXHR.error = jqXHR.fail; 7943 7944 // Remove hash character (#7531: and string promotion) 7945 // Add protocol if not provided (prefilters might expect it) 7946 // Handle falsy url in the settings object (#10093: consistency with old signature) 7947 // We also use the url parameter if available 7948 s.url = ( ( url || s.url || ajaxLocation ) + "" ).replace( rhash, "" ) 7949 .replace( rprotocol, ajaxLocParts[ 1 ] + "//" ); 7950 7951 // Alias method option to type as per ticket #12004 7952 s.type = options.method || options.type || s.method || s.type; 7953 7954 // Extract dataTypes list 7955 s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().match( rnotwhite ) || [ "" ]; 7956 7957 // A cross-domain request is in order when we have a protocol:host:port mismatch 7958 if ( s.crossDomain == null ) { 7959 parts = rurl.exec( s.url.toLowerCase() ); 7960 s.crossDomain = !!( parts && 7961 ( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] || 7962 ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? "80" : "443" ) ) !== 7963 ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? "80" : "443" ) ) ) 7964 ); 7965 } 7966 7967 // Convert data if not already a string 7968 if ( s.data && s.processData && typeof s.data !== "string" ) { 7969 s.data = jQuery.param( s.data, s.traditional ); 7970 } 7971 7972 // Apply prefilters 7973 inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); 7974 7975 // If request was aborted inside a prefilter, stop there 7976 if ( state === 2 ) { 7977 return jqXHR; 7978 } 7979 7980 // We can fire global events as of now if asked to 7981 fireGlobals = s.global; 7982 7983 // Watch for a new set of requests 7984 if ( fireGlobals && jQuery.active++ === 0 ) { 7985 jQuery.event.trigger("ajaxStart"); 7986 } 7987 7988 // Uppercase the type 7989 s.type = s.type.toUpperCase(); 7990 7991 // Determine if request has content 7992 s.hasContent = !rnoContent.test( s.type ); 7993 7994 // Save the URL in case we're toying with the If-Modified-Since 7995 // and/or If-None-Match header later on 7996 cacheURL = s.url; 7997 7998 // More options handling for requests with no content 7999 if ( !s.hasContent ) { 8000 8001 // If data is available, append data to url 8002 if ( s.data ) {
vendor: 17,837 bytes, lines 8003-8669
8003 cacheURL = ( s.url += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data ); 8004 // #9682: remove data so that it's not used in an eventual retry 8005 delete s.data; 8006 } 8007 8008 // Add anti-cache in url if needed 8009 if ( s.cache === false ) { 8010 s.url = rts.test( cacheURL ) ? 8011 8012 // If there is already a '_' parameter, set its value 8013 cacheURL.replace( rts, "$1_=" + nonce++ ) : 8014 8015 // Otherwise add one to the end 8016 cacheURL + ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + nonce++; 8017 } 8018 } 8019 8020 // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. 8021 if ( s.ifModified ) { 8022 if ( jQuery.lastModified[ cacheURL ] ) { 8023 jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] ); 8024 } 8025 if ( jQuery.etag[ cacheURL ] ) { 8026 jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] ); 8027 } 8028 } 8029 8030 // Set the correct header, if data is being sent 8031 if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { 8032 jqXHR.setRequestHeader( "Content-Type", s.contentType ); 8033 } 8034 8035 // Set the Accepts header for the server, depending on the dataType 8036 jqXHR.setRequestHeader( 8037 "Accept", 8038 s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ? 8039 s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : 8040 s.accepts[ "*" ] 8041 ); 8042 8043 // Check for headers option 8044 for ( i in s.headers ) { 8045 jqXHR.setRequestHeader( i, s.headers[ i ] ); 8046 } 8047 8048 // Allow custom headers/mimetypes and early abort 8049 if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) { 8050 // Abort if not done already and return 8051 return jqXHR.abort(); 8052 } 8053 8054 // aborting is no longer a cancellation 8055 strAbort = "abort"; 8056 8057 // Install callbacks on deferreds 8058 for ( i in { success: 1, error: 1, complete: 1 } ) { 8059 jqXHR[ i ]( s[ i ] ); 8060 } 8061 8062 // Get transport 8063 transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); 8064 8065 // If no transport, we auto-abort 8066 if ( !transport ) { 8067 done( -1, "No Transport" ); 8068 } else { 8069 jqXHR.readyState = 1; 8070 8071 // Send global event 8072 if ( fireGlobals ) { 8073 globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); 8074 } 8075 // Timeout 8076 if ( s.async && s.timeout > 0 ) { 8077 timeoutTimer = setTimeout(function() { 8078 jqXHR.abort("timeout"); 8079 }, s.timeout ); 8080 } 8081 8082 try { 8083 state = 1; 8084 transport.send( requestHeaders, done ); 8085 } catch ( e ) { 8086 // Propagate exception as error if not done 8087 if ( state < 2 ) { 8088 done( -1, e ); 8089 // Simply rethrow otherwise 8090 } else { 8091 throw e; 8092 } 8093 } 8094 } 8095 8096 // Callback for when everything is done 8097 function done( status, nativeStatusText, responses, headers ) { 8098 var isSuccess, success, error, response, modified, 8099 statusText = nativeStatusText; 8100 8101 // Called once 8102 if ( state === 2 ) { 8103 return; 8104 } 8105 8106 // State is "done" now 8107 state = 2; 8108 8109 // Clear timeout if it exists 8110 if ( timeoutTimer ) { 8111 clearTimeout( timeoutTimer ); 8112 } 8113 8114 // Dereference transport for early garbage collection 8115 // (no matter how long the jqXHR object will be used) 8116 transport = undefined; 8117 8118 // Cache response headers 8119 responseHeadersString = headers || ""; 8120 8121 // Set readyState 8122 jqXHR.readyState = status > 0 ? 4 : 0; 8123 8124 // Determine if successful 8125 isSuccess = status >= 200 && status < 300 || status === 304; 8126 8127 // Get response data 8128 if ( responses ) { 8129 response = ajaxHandleResponses( s, jqXHR, responses ); 8130 } 8131 8132 // Convert no matter what (that way responseXXX fields are always set) 8133 response = ajaxConvert( s, response, jqXHR, isSuccess ); 8134 8135 // If successful, handle type chaining 8136 if ( isSuccess ) { 8137 8138 // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. 8139 if ( s.ifModified ) { 8140 modified = jqXHR.getResponseHeader("Last-Modified"); 8141 if ( modified ) { 8142 jQuery.lastModified[ cacheURL ] = modified; 8143 } 8144 modified = jqXHR.getResponseHeader("etag"); 8145 if ( modified ) { 8146 jQuery.etag[ cacheURL ] = modified; 8147 } 8148 } 8149 8150 // if no content 8151 if ( status === 204 || s.type === "HEAD" ) { 8152 statusText = "nocontent"; 8153 8154 // if not modified 8155 } else if ( status === 304 ) { 8156 statusText = "notmodified"; 8157 8158 // If we have data, let's convert it 8159 } else { 8160 statusText = response.state; 8161 success = response.data; 8162 error = response.error; 8163 isSuccess = !error; 8164 } 8165 } else { 8166 // We extract error from statusText 8167 // then normalize statusText and status for non-aborts 8168 error = statusText; 8169 if ( status || !statusText ) { 8170 statusText = "error"; 8171 if ( status < 0 ) { 8172 status = 0; 8173 } 8174 } 8175 } 8176 8177 // Set data for the fake xhr object 8178 jqXHR.status = status; 8179 jqXHR.statusText = ( nativeStatusText || statusText ) + ""; 8180 8181 // Success/Error 8182 if ( isSuccess ) { 8183 deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); 8184 } else { 8185 deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); 8186 } 8187 8188 // Status-dependent callbacks 8189 jqXHR.statusCode( statusCode ); 8190 statusCode = undefined; 8191 8192 if ( fireGlobals ) { 8193 globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError", 8194 [ jqXHR, s, isSuccess ? success : error ] ); 8195 } 8196 8197 // Complete 8198 completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); 8199 8200 if ( fireGlobals ) { 8201 globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); 8202 // Handle the global AJAX counter 8203 if ( !( --jQuery.active ) ) { 8204 jQuery.event.trigger("ajaxStop"); 8205 } 8206 } 8207 } 8208 8209 return jqXHR; 8210 }, 8211 8212 getJSON: function( url, data, callback ) { 8213 return jQuery.get( url, data, callback, "json" ); 8214 }, 8215 8216 getScript: function( url, callback ) { 8217 return jQuery.get( url, undefined, callback, "script" ); 8218 } 8219}); 8220 8221jQuery.each( [ "get", "post" ], function( i, method ) { 8222 jQuery[ method ] = function( url, data, callback, type ) { 8223 // shift arguments if data argument was omitted 8224 if ( jQuery.isFunction( data ) ) { 8225 type = type || callback; 8226 callback = data; 8227 data = undefined; 8228 } 8229 8230 return jQuery.ajax({ 8231 url: url, 8232 type: method, 8233 dataType: type, 8234 data: data, 8235 success: callback 8236 }); 8237 }; 8238}); 8239 8240// Attach a bunch of functions for handling common AJAX events 8241jQuery.each( [ "ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend" ], function( i, type ) { 8242 jQuery.fn[ type ] = function( fn ) { 8243 return this.on( type, fn ); 8244 }; 8245}); 8246 8247 8248jQuery._evalUrl = function( url ) { 8249 return jQuery.ajax({ 8250 url: url, 8251 type: "GET", 8252 dataType: "script", 8253 async: false, 8254 global: false, 8255 "throws": true 8256 }); 8257}; 8258 8259 8260jQuery.fn.extend({ 8261 wrapAll: function( html ) { 8262 var wrap; 8263 8264 if ( jQuery.isFunction( html ) ) { 8265 return this.each(function( i ) { 8266 jQuery( this ).wrapAll( html.call(this, i) ); 8267 }); 8268 } 8269 8270 if ( this[ 0 ] ) { 8271 8272 // The elements to wrap the target around 8273 wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true ); 8274 8275 if ( this[ 0 ].parentNode ) { 8276 wrap.insertBefore( this[ 0 ] ); 8277 } 8278 8279 wrap.map(function() { 8280 var elem = this; 8281 8282 while ( elem.firstElementChild ) { 8283 elem = elem.firstElementChild; 8284 } 8285 8286 return elem; 8287 }).append( this ); 8288 } 8289 8290 return this; 8291 }, 8292 8293 wrapInner: function( html ) { 8294 if ( jQuery.isFunction( html ) ) { 8295 return this.each(function( i ) { 8296 jQuery( this ).wrapInner( html.call(this, i) ); 8297 }); 8298 } 8299 8300 return this.each(function() { 8301 var self = jQuery( this ), 8302 contents = self.contents(); 8303 8304 if ( contents.length ) { 8305 contents.wrapAll( html ); 8306 8307 } else { 8308 self.append( html ); 8309 } 8310 }); 8311 }, 8312 8313 wrap: function( html ) { 8314 var isFunction = jQuery.isFunction( html ); 8315 8316 return this.each(function( i ) { 8317 jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html ); 8318 }); 8319 }, 8320 8321 unwrap: function() { 8322 return this.parent().each(function() { 8323 if ( !jQuery.nodeName( this, "body" ) ) { 8324 jQuery( this ).replaceWith( this.childNodes ); 8325 } 8326 }).end(); 8327 } 8328}); 8329 8330 8331jQuery.expr.filters.hidden = function( elem ) { 8332 // Support: Opera <= 12.12 8333 // Opera reports offsetWidths and offsetHeights less than zero on some elements 8334 return elem.offsetWidth <= 0 && elem.offsetHeight <= 0; 8335}; 8336jQuery.expr.filters.visible = function( elem ) { 8337 return !jQuery.expr.filters.hidden( elem ); 8338}; 8339 8340 8341 8342 8343var r20 = /%20/g, 8344 rbracket = /\[\]$/, 8345 rCRLF = /\r?\n/g, 8346 rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i, 8347 rsubmittable = /^(?:input|select|textarea|keygen)/i; 8348 8349function buildParams( prefix, obj, traditional, add ) { 8350 var name; 8351 8352 if ( jQuery.isArray( obj ) ) { 8353 // Serialize array item. 8354 jQuery.each( obj, function( i, v ) { 8355 if ( traditional || rbracket.test( prefix ) ) { 8356 // Treat each array item as a scalar. 8357 add( prefix, v ); 8358 8359 } else { 8360 // Item is non-scalar (array or object), encode its numeric index. 8361 buildParams( prefix + "[" + ( typeof v === "object" ? i : "" ) + "]", v, traditional, add ); 8362 } 8363 }); 8364 8365 } else if ( !traditional && jQuery.type( obj ) === "object" ) { 8366 // Serialize object item. 8367 for ( name in obj ) { 8368 buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add ); 8369 } 8370 8371 } else { 8372 // Serialize scalar item. 8373 add( prefix, obj ); 8374 } 8375} 8376 8377// Serialize an array of form elements or a set of 8378// key/values into a query string 8379jQuery.param = function( a, traditional ) { 8380 var prefix, 8381 s = [], 8382 add = function( key, value ) { 8383 // If value is a function, invoke it and return its value 8384 value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value ); 8385 s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value ); 8386 }; 8387 8388 // Set traditional to true for jQuery <= 1.3.2 behavior. 8389 if ( traditional === undefined ) { 8390 traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional; 8391 } 8392 8393 // If an array was passed in, assume that it is an array of form elements. 8394 if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { 8395 // Serialize the form elements 8396 jQuery.each( a, function() { 8397 add( this.name, this.value ); 8398 }); 8399 8400 } else { 8401 // If traditional, encode the "old" way (the way 1.3.2 or older 8402 // did it), otherwise encode params recursively. 8403 for ( prefix in a ) { 8404 buildParams( prefix, a[ prefix ], traditional, add ); 8405 } 8406 } 8407 8408 // Return the resulting serialization 8409 return s.join( "&" ).replace( r20, "+" ); 8410}; 8411 8412jQuery.fn.extend({ 8413 serialize: function() { 8414 return jQuery.param( this.serializeArray() ); 8415 }, 8416 serializeArray: function() { 8417 return this.map(function() { 8418 // Can add propHook for "elements" to filter or add form elements 8419 var elements = jQuery.prop( this, "elements" ); 8420 return elements ? jQuery.makeArray( elements ) : this; 8421 }) 8422 .filter(function() { 8423 var type = this.type; 8424 8425 // Use .is( ":disabled" ) so that fieldset[disabled] works 8426 return this.name && !jQuery( this ).is( ":disabled" ) && 8427 rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) && 8428 ( this.checked || !rcheckableType.test( type ) ); 8429 }) 8430 .map(function( i, elem ) { 8431 var val = jQuery( this ).val(); 8432 8433 return val == null ? 8434 null : 8435 jQuery.isArray( val ) ? 8436 jQuery.map( val, function( val ) { 8437 return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; 8438 }) : 8439 { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; 8440 }).get(); 8441 } 8442}); 8443 8444 8445jQuery.ajaxSettings.xhr = function() { 8446 try { 8447 return new XMLHttpRequest(); 8448 } catch( e ) {} 8449}; 8450 8451var xhrId = 0, 8452 xhrCallbacks = {}, 8453 xhrSuccessStatus = { 8454 // file protocol always yields status code 0, assume 200 8455 0: 200, 8456 // Support: IE9 8457 // #1450: sometimes IE returns 1223 when it should be 204 8458 1223: 204 8459 }, 8460 xhrSupported = jQuery.ajaxSettings.xhr(); 8461 8462// Support: IE9 8463// Open requests must be manually aborted on unload (#5280) 8464if ( window.ActiveXObject ) { 8465 jQuery( window ).on( "unload", function() { 8466 for ( var key in xhrCallbacks ) { 8467 xhrCallbacks[ key ](); 8468 } 8469 }); 8470} 8471 8472support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ); 8473support.ajax = xhrSupported = !!xhrSupported; 8474 8475jQuery.ajaxTransport(function( options ) { 8476 var callback; 8477 8478 // Cross domain only allowed if supported through XMLHttpRequest 8479 if ( support.cors || xhrSupported && !options.crossDomain ) { 8480 return { 8481 send: function( headers, complete ) { 8482 var i, 8483 xhr = options.xhr(), 8484 id = ++xhrId; 8485 8486 xhr.open( options.type, options.url, options.async, options.username, options.password ); 8487 8488 // Apply custom fields if provided 8489 if ( options.xhrFields ) { 8490 for ( i in options.xhrFields ) { 8491 xhr[ i ] = options.xhrFields[ i ]; 8492 } 8493 } 8494 8495 // Override mime type if needed 8496 if ( options.mimeType && xhr.overrideMimeType ) { 8497 xhr.overrideMimeType( options.mimeType ); 8498 } 8499 8500 // X-Requested-With header 8501 // For cross-domain requests, seeing as conditions for a preflight are 8502 // akin to a jigsaw puzzle, we simply never set it to be sure. 8503 // (it can always be set on a per-request basis or even using ajaxSetup) 8504 // For same-domain requests, won't change header if already provided. 8505 if ( !options.crossDomain && !headers["X-Requested-With"] ) { 8506 headers["X-Requested-With"] = "XMLHttpRequest"; 8507 } 8508 8509 // Set headers 8510 for ( i in headers ) { 8511 xhr.setRequestHeader( i, headers[ i ] ); 8512 } 8513 8514 // Callback 8515 callback = function( type ) { 8516 return function() { 8517 if ( callback ) { 8518 delete xhrCallbacks[ id ]; 8519 callback = xhr.onload = xhr.onerror = null; 8520 8521 if ( type === "abort" ) { 8522 xhr.abort(); 8523 } else if ( type === "error" ) { 8524 complete( 8525 // file: protocol always yields status 0; see #8605, #14207 8526 xhr.status, 8527 xhr.statusText 8528 ); 8529 } else { 8530 complete( 8531 xhrSuccessStatus[ xhr.status ] || xhr.status, 8532 xhr.statusText, 8533 // Support: IE9 8534 // Accessing binary-data responseText throws an exception 8535 // (#11426) 8536 typeof xhr.responseText === "string" ? { 8537 text: xhr.responseText 8538 } : undefined, 8539 xhr.getAllResponseHeaders() 8540 ); 8541 } 8542 } 8543 }; 8544 }; 8545 8546 // Listen to events 8547 xhr.onload = callback(); 8548 xhr.onerror = callback("error"); 8549 8550 // Create the abort callback 8551 callback = xhrCallbacks[ id ] = callback("abort"); 8552 8553 // Do send the request 8554 // This may raise an exception which is actually 8555 // handled in jQuery.ajax (so no try/catch here) 8556 xhr.send( options.hasContent && options.data || null ); 8557 }, 8558 8559 abort: function() { 8560 if ( callback ) { 8561 callback(); 8562 } 8563 } 8564 }; 8565 } 8566}); 8567 8568 8569 8570 8571// Install script dataType 8572jQuery.ajaxSetup({ 8573 accepts: { 8574 script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript" 8575 }, 8576 contents: { 8577 script: /(?:java|ecma)script/ 8578 }, 8579 converters: { 8580 "text script": function( text ) { 8581 jQuery.globalEval( text ); 8582 return text; 8583 } 8584 } 8585}); 8586 8587// Handle cache's special case and crossDomain 8588jQuery.ajaxPrefilter( "script", function( s ) { 8589 if ( s.cache === undefined ) { 8590 s.cache = false; 8591 } 8592 if ( s.crossDomain ) { 8593 s.type = "GET"; 8594 } 8595}); 8596 8597// Bind script tag hack transport 8598jQuery.ajaxTransport( "script", function( s ) { 8599 // This transport only deals with cross domain requests 8600 if ( s.crossDomain ) { 8601 var script, callback; 8602 return { 8603 send: function( _, complete ) { 8604 script = jQuery("<script>").prop({ 8605 async: true, 8606 charset: s.scriptCharset, 8607 src: s.url 8608 }).on( 8609 "load error", 8610 callback = function( evt ) { 8611 script.remove(); 8612 callback = null; 8613 if ( evt ) { 8614 complete( evt.type === "error" ? 404 : 200, evt.type ); 8615 } 8616 } 8617 ); 8618 document.head.appendChild( script[ 0 ] ); 8619 }, 8620 abort: function() { 8621 if ( callback ) { 8622 callback(); 8623 } 8624 } 8625 }; 8626 } 8627}); 8628 8629 8630 8631 8632var oldCallbacks = [], 8633 rjsonp = /(=)\?(?=&|$)|\?\?/; 8634 8635// Default jsonp settings 8636jQuery.ajaxSetup({ 8637 jsonp: "callback", 8638 jsonpCallback: function() { 8639 var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce++ ) ); 8640 this[ callback ] = true; 8641 return callback; 8642 } 8643}); 8644 8645// Detect, normalize options and install callbacks for jsonp requests 8646jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) { 8647 8648 var callbackName, overwritten, responseContainer, 8649 jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ? 8650 "url" : 8651 typeof s.data === "string" && !( s.contentType || "" ).indexOf("application/x-www-form-urlencoded") && rjsonp.test( s.data ) && "data" 8652 ); 8653 8654 // Handle iff the expected data type is "jsonp" or we have a parameter to set 8655 if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) { 8656 8657 // Get callback name, remembering preexisting value associated with it 8658 callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ? 8659 s.jsonpCallback() : 8660 s.jsonpCallback; 8661 8662 // Insert callback into url or form data 8663 if ( jsonProp ) { 8664 s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName ); 8665 } else if ( s.jsonp !== false ) { 8666 s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName; 8667 } 8668 8669 // Use data converter to retrieve json after script execution
vendor: 1,849 bytes, lines 8670-8739
8670 s.converters["script json"] = function() { 8671 if ( !responseContainer ) { 8672 jQuery.error( callbackName + " was not called" ); 8673 } 8674 return responseContainer[ 0 ]; 8675 }; 8676 8677 // force json dataType 8678 s.dataTypes[ 0 ] = "json"; 8679 8680 // Install callback 8681 overwritten = window[ callbackName ]; 8682 window[ callbackName ] = function() { 8683 responseContainer = arguments; 8684 }; 8685 8686 // Clean-up function (fires after converters) 8687 jqXHR.always(function() { 8688 // Restore preexisting value 8689 window[ callbackName ] = overwritten; 8690 8691 // Save back as free 8692 if ( s[ callbackName ] ) { 8693 // make sure that re-using the options doesn't screw things around 8694 s.jsonpCallback = originalSettings.jsonpCallback; 8695 8696 // save the callback name for future use 8697 oldCallbacks.push( callbackName ); 8698 } 8699 8700 // Call if it was a function and we have a response 8701 if ( responseContainer && jQuery.isFunction( overwritten ) ) { 8702 overwritten( responseContainer[ 0 ] ); 8703 } 8704 8705 responseContainer = overwritten = undefined; 8706 }); 8707 8708 // Delegate to script 8709 return "script"; 8710 } 8711}); 8712 8713 8714 8715 8716// data: string of html 8717// context (optional): If specified, the fragment will be created in this context, defaults to document 8718// keepScripts (optional): If true, will include scripts passed in the html string 8719jQuery.parseHTML = function( data, context, keepScripts ) { 8720 if ( !data || typeof data !== "string" ) { 8721 return null; 8722 } 8723 if ( typeof context === "boolean" ) { 8724 keepScripts = context; 8725 context = false; 8726 } 8727 context = context || document; 8728 8729 var parsed = rsingleTag.exec( data ), 8730 scripts = !keepScripts && []; 8731 8732 // Single tag 8733 if ( parsed ) { 8734 return [ context.createElement( parsed[1] ) ]; 8735 } 8736 8737 parsed = jQuery.buildFragment( [ data ], context, scripts ); 8738 8739 if ( scripts && scripts.length ) {
vendor: 13,330 bytes, lines 8740-9193
8740 jQuery( scripts ).remove(); 8741 } 8742 8743 return jQuery.merge( [], parsed.childNodes ); 8744}; 8745 8746 8747// Keep a copy of the old load method 8748var _load = jQuery.fn.load; 8749 8750/** 8751 * Load a url into a page 8752 */ 8753jQuery.fn.load = function( url, params, callback ) { 8754 if ( typeof url !== "string" && _load ) { 8755 return _load.apply( this, arguments ); 8756 } 8757 8758 var selector, type, response, 8759 self = this, 8760 off = url.indexOf(" "); 8761 8762 if ( off >= 0 ) { 8763 selector = url.slice( off ); 8764 url = url.slice( 0, off ); 8765 } 8766 8767 // If it's a function 8768 if ( jQuery.isFunction( params ) ) { 8769 8770 // We assume that it's the callback 8771 callback = params; 8772 params = undefined; 8773 8774 // Otherwise, build a param string 8775 } else if ( params && typeof params === "object" ) { 8776 type = "POST"; 8777 } 8778 8779 // If we have elements to modify, make the request 8780 if ( self.length > 0 ) { 8781 jQuery.ajax({ 8782 url: url, 8783 8784 // if "type" variable is undefined, then "GET" method will be used 8785 type: type, 8786 dataType: "html", 8787 data: params 8788 }).done(function( responseText ) { 8789 8790 // Save response for use in complete callback 8791 response = arguments; 8792 8793 self.html( selector ? 8794 8795 // If a selector was specified, locate the right elements in a dummy div 8796 // Exclude scripts to avoid IE 'Permission Denied' errors 8797 jQuery("<div>").append( jQuery.parseHTML( responseText ) ).find( selector ) : 8798 8799 // Otherwise use the full result 8800 responseText ); 8801 8802 }).complete( callback && function( jqXHR, status ) { 8803 self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] ); 8804 }); 8805 } 8806 8807 return this; 8808}; 8809 8810 8811 8812 8813jQuery.expr.filters.animated = function( elem ) { 8814 return jQuery.grep(jQuery.timers, function( fn ) { 8815 return elem === fn.elem; 8816 }).length; 8817}; 8818 8819 8820 8821 8822var docElem = window.document.documentElement; 8823 8824/** 8825 * Gets a window from an element 8826 */ 8827function getWindow( elem ) { 8828 return jQuery.isWindow( elem ) ? elem : elem.nodeType === 9 && elem.defaultView; 8829} 8830 8831jQuery.offset = { 8832 setOffset: function( elem, options, i ) { 8833 var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition, 8834 position = jQuery.css( elem, "position" ), 8835 curElem = jQuery( elem ), 8836 props = {}; 8837 8838 // Set position first, in-case top/left are set even on static elem 8839 if ( position === "static" ) { 8840 elem.style.position = "relative"; 8841 } 8842 8843 curOffset = curElem.offset(); 8844 curCSSTop = jQuery.css( elem, "top" ); 8845 curCSSLeft = jQuery.css( elem, "left" ); 8846 calculatePosition = ( position === "absolute" || position === "fixed" ) && 8847 ( curCSSTop + curCSSLeft ).indexOf("auto") > -1; 8848 8849 // Need to be able to calculate position if either top or left is auto and position is either absolute or fixed 8850 if ( calculatePosition ) { 8851 curPosition = curElem.position(); 8852 curTop = curPosition.top; 8853 curLeft = curPosition.left; 8854 8855 } else { 8856 curTop = parseFloat( curCSSTop ) || 0; 8857 curLeft = parseFloat( curCSSLeft ) || 0; 8858 } 8859 8860 if ( jQuery.isFunction( options ) ) { 8861 options = options.call( elem, i, curOffset ); 8862 } 8863 8864 if ( options.top != null ) { 8865 props.top = ( options.top - curOffset.top ) + curTop; 8866 } 8867 if ( options.left != null ) { 8868 props.left = ( options.left - curOffset.left ) + curLeft; 8869 } 8870 8871 if ( "using" in options ) { 8872 options.using.call( elem, props ); 8873 8874 } else { 8875 curElem.css( props ); 8876 } 8877 } 8878}; 8879 8880jQuery.fn.extend({ 8881 offset: function( options ) { 8882 if ( arguments.length ) { 8883 return options === undefined ? 8884 this : 8885 this.each(function( i ) { 8886 jQuery.offset.setOffset( this, options, i ); 8887 }); 8888 } 8889 8890 var docElem, win, 8891 elem = this[ 0 ], 8892 box = { top: 0, left: 0 }, 8893 doc = elem && elem.ownerDocument; 8894 8895 if ( !doc ) { 8896 return; 8897 } 8898 8899 docElem = doc.documentElement; 8900 8901 // Make sure it's not a disconnected DOM node 8902 if ( !jQuery.contains( docElem, elem ) ) { 8903 return box; 8904 } 8905 8906 // If we don't have gBCR, just use 0,0 rather than error 8907 // BlackBerry 5, iOS 3 (original iPhone) 8908 if ( typeof elem.getBoundingClientRect !== strundefined ) { 8909 box = elem.getBoundingClientRect(); 8910 } 8911 win = getWindow( doc ); 8912 return { 8913 top: box.top + win.pageYOffset - docElem.clientTop, 8914 left: box.left + win.pageXOffset - docElem.clientLeft 8915 }; 8916 }, 8917 8918 position: function() { 8919 if ( !this[ 0 ] ) { 8920 return; 8921 } 8922 8923 var offsetParent, offset, 8924 elem = this[ 0 ], 8925 parentOffset = { top: 0, left: 0 }; 8926 8927 // Fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is its only offset parent 8928 if ( jQuery.css( elem, "position" ) === "fixed" ) { 8929 // We assume that getBoundingClientRect is available when computed position is fixed 8930 offset = elem.getBoundingClientRect(); 8931 8932 } else { 8933 // Get *real* offsetParent 8934 offsetParent = this.offsetParent(); 8935 8936 // Get correct offsets 8937 offset = this.offset(); 8938 if ( !jQuery.nodeName( offsetParent[ 0 ], "html" ) ) { 8939 parentOffset = offsetParent.offset(); 8940 } 8941 8942 // Add offsetParent borders 8943 parentOffset.top += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true ); 8944 parentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true ); 8945 } 8946 8947 // Subtract parent offsets and element margins 8948 return { 8949 top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ), 8950 left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true ) 8951 }; 8952 }, 8953 8954 offsetParent: function() { 8955 return this.map(function() { 8956 var offsetParent = this.offsetParent || docElem; 8957 8958 while ( offsetParent && ( !jQuery.nodeName( offsetParent, "html" ) && jQuery.css( offsetParent, "position" ) === "static" ) ) { 8959 offsetParent = offsetParent.offsetParent; 8960 } 8961 8962 return offsetParent || docElem; 8963 }); 8964 } 8965}); 8966 8967// Create scrollLeft and scrollTop methods 8968jQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( method, prop ) { 8969 var top = "pageYOffset" === prop; 8970 8971 jQuery.fn[ method ] = function( val ) { 8972 return access( this, function( elem, method, val ) { 8973 var win = getWindow( elem ); 8974 8975 if ( val === undefined ) { 8976 return win ? win[ prop ] : elem[ method ]; 8977 } 8978 8979 if ( win ) { 8980 win.scrollTo( 8981 !top ? val : window.pageXOffset, 8982 top ? val : window.pageYOffset 8983 ); 8984 8985 } else { 8986 elem[ method ] = val; 8987 } 8988 }, method, val, arguments.length, null ); 8989 }; 8990}); 8991 8992// Add the top/left cssHooks using jQuery.fn.position 8993// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084 8994// getComputedStyle returns percent when specified for top/left/bottom/right 8995// rather than make the css module depend on the offset module, we just check for it here 8996jQuery.each( [ "top", "left" ], function( i, prop ) { 8997 jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition, 8998 function( elem, computed ) { 8999 if ( computed ) { 9000 computed = curCSS( elem, prop ); 9001 // if curCSS returns percentage, fallback to offset 9002 return rnumnonpx.test( computed ) ? 9003 jQuery( elem ).position()[ prop ] + "px" : 9004 computed; 9005 } 9006 } 9007 ); 9008}); 9009 9010 9011// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods 9012jQuery.each( { Height: "height", Width: "width" }, function( name, type ) { 9013 jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, function( defaultExtra, funcName ) { 9014 // margin is only for outerHeight, outerWidth 9015 jQuery.fn[ funcName ] = function( margin, value ) { 9016 var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ), 9017 extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" ); 9018 9019 return access( this, function( elem, type, value ) { 9020 var doc; 9021 9022 if ( jQuery.isWindow( elem ) ) { 9023 // As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there 9024 // isn't a whole lot we can do. See pull request at this URL for discussion: 9025 // https://github.com/jquery/jquery/pull/764 9026 return elem.document.documentElement[ "client" + name ]; 9027 } 9028 9029 // Get document width or height 9030 if ( elem.nodeType === 9 ) { 9031 doc = elem.documentElement; 9032 9033 // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height], 9034 // whichever is greatest 9035 return Math.max( 9036 elem.body[ "scroll" + name ], doc[ "scroll" + name ], 9037 elem.body[ "offset" + name ], doc[ "offset" + name ], 9038 doc[ "client" + name ] 9039 ); 9040 } 9041 9042 return value === undefined ? 9043 // Get width or height on the element, requesting but not forcing parseFloat 9044 jQuery.css( elem, type, extra ) : 9045 9046 // Set width or height on the element 9047 jQuery.style( elem, type, value, extra ); 9048 }, type, chainable ? margin : undefined, chainable, null ); 9049 }; 9050 }); 9051}); 9052 9053 9054// The number of elements contained in the matched element set 9055jQuery.fn.size = function() { 9056 return this.length; 9057}; 9058 9059jQuery.fn.andSelf = jQuery.fn.addBack; 9060 9061 9062 9063 9064// Register as a named AMD module, since jQuery can be concatenated with other 9065// files that may use define, but not via a proper concatenation script that 9066// understands anonymous AMD modules. A named AMD is safest and most robust 9067// way to register. Lowercase jquery is used because AMD module names are 9068// derived from file names, and jQuery is normally delivered in a lowercase 9069// file name. Do this after creating the global so that if an AMD module wants 9070// to call noConflict to hide this version of jQuery, it will work. 9071if ( typeof define === "function" && define.amd ) { 9072 define( "jquery", [], function() { 9073 return jQuery; 9074 }); 9075} 9076 9077 9078 9079 9080var 9081 // Map over jQuery in case of overwrite 9082 _jQuery = window.jQuery, 9083 9084 // Map over the $ in case of overwrite 9085 _$ = window.$; 9086 9087jQuery.noConflict = function( deep ) { 9088 if ( window.$ === jQuery ) { 9089 window.$ = _$; 9090 } 9091 9092 if ( deep && window.jQuery === jQuery ) { 9093 window.jQuery = _jQuery; 9094 } 9095 9096 return jQuery; 9097}; 9098 9099// Expose jQuery and $ identifiers, even in 9100// AMD (#7102#comment:10, https://github.com/jquery/jquery/pull/557) 9101// and CommonJS for browser emulators (#13566) 9102if ( typeof noGlobal === strundefined ) { 9103 window.jQuery = window.$ = jQuery; 9104} 9105 9106 9107 9108 9109return jQuery; 9110 9111})); 9112 9113 9114 9115let bililiteRange; // create one global variable 9116 9117(function(){ 9118 9119const datakey = Symbol(); // use as the key to modify elements. 9120 9121bililiteRange = function(el){ 9122 var ret; 9123 if (el.setSelectionRange){ 9124 // Element is an input or textarea 9125 // note that some input elements do not allow selections 9126 try{ 9127 el.selectionStart = el.selectionStart; 9128 ret = new InputRange(); 9129 }catch(e){ 9130 ret = new NothingRange(); 9131 } 9132 }else{ 9133 // Standards, with any other kind of element 9134 ret = new W3CRange(); 9135 } 9136 ret._el = el; 9137 // determine parent document, as implemented by John McLear <[email protected]> 9138 ret._doc = el.ownerDocument; 9139 ret._win = ret._doc.defaultView; 9140 ret._bounds = [0, ret.length]; 9141 9142 // selection tracking. We want clicks to set the selection to the clicked location but tabbing in or element.focus() should restore 9143 // the selection to what it was. 9144 // There's no good way to do this. I just assume that a mousedown (or a drag and drop 9145 // into the element) within 100 ms of the focus event must have caused the focus, and 9146 // therefore we should not restore the selection. 9147 if (!(el[datakey])){ // we haven't processed this element yet 9148 const data = createDataObject (el); 9149 startupHooks.forEach ( hook => hook (el, ret, data) ); 9150 } 9151 return ret; 9152} 9153 9154bililiteRange.version = 3.2; 9155 9156const startupHooks = new Set(); 9157bililiteRange.addStartupHook = fn => startupHooks.add(fn); 9158startupHooks.add (trackSelection); 9159startupHooks.add (fixInputEvents); 9160startupHooks.add (correctNewlines); 9161 9162function trackSelection (element, range, data){ 9163 data.selection = [0,0]; 9164 range.listen('focusout', evt => data.selection = range._nativeSelection() ); 9165 range.listen('mousedown', evt => data.mousetime = evt.timeStamp ); 9166 range.listen('drop', evt => data.mousetime = evt.timeStamp ); 9167 range.listen('focus', evt => { 9168 if ('mousetime' in data && evt.timeStamp - data.mousetime < 100) return; 9169 range._nativeSelect(range._nativeRange(data.selection)) 9170 }) 9171} 9172 9173function fixInputEvents (element, range, data){ 9174 // DOM 3 input events, https://www.w3.org/TR/input-events-1/ 9175 // have a data field with the text inserted, but thatisn't enough to fully describe the change; 9176 // we need to know the old text (or at least its length) 9177 // and *where* the new text was inserted. 9178 // So we enhance input events with that information. 9179 // the "newText" should always be the same as the 'data' field, if it is defined 9180 data.oldText = range.all(); 9181 data.liveRanges = new Set(); 9182 range.listen('input', evt => { 9183 const newText = range.all(); 9184 if (!evt.bililiteRange){ 9185 evt.bililiteRange = diff (data.oldText, newText); 9186 if (evt.bililiteRange.unchanged){ 9187 // no change. Assume that whatever happened, happened at the selection point (and use whatever data the browser gives us). 9188 evt.bililiteRange.start = range.clone().bounds('selection')[1] - (evt.data || '').length; 9189 } 9190 } 9191 data.oldText = newText; 9192 9193 // Also update live ranges on this element
9194 data.liveRanges.forEach( rng => { 9195 const start = evt.bililiteRange.start; 9196 const oldend = start + evt.bililiteRange.oldText.length; 9197 const newend = start + evt.bililiteRange.newText.length; 9198 // adjust bounds; this tries to emulate the algorithm that Microsoft Word uses for bookmarks 9199 let [b0, b1] = rng.bounds(); 9200 if (b0 <= start){ 9201 // no change 9202 }else if (b0 > oldend){ 9203 b0 += newend - oldend; 9204 }else{ 9205 b0 = newend; 9206 } 9207 if (b1 < start){ 9208 // no change 9209 }else if (b1 >= oldend){ 9210 b1 += newend - oldend; 9211 }else{ 9212 b1 = start; 9213 } 9214 rng.bounds([b0, b1]); 9215 }) 9216 }); 9217} 9218 9219function diff (oldText, newText){ 9220 // Try to find the changed text, assuming it was a continuous change 9221 if (oldText == newText){ 9222 return { 9223 unchanged: true, 9224 start: 0, 9225 oldText, 9226 newText 9227 } 9228 } 9229 9230 const oldlen = oldText.length; 9231 const newlen = newText.length; 9232 for (var i = 0; i < newlen && i < oldlen; ++i){ 9233 if (newText.charAt(i) != oldText.charAt(i)) break; 9234 } 9235 const start = i; 9236 for (i = 0; i < newlen && i < oldlen; ++i){ 9237 let newpos = newlen-i-1, oldpos = oldlen-i-1; 9238 if (newpos < start || oldpos < start) break; 9239 if (newText.charAt(newpos) != oldText.charAt(oldpos)) break; 9240 } 9241 const oldend = oldlen-i; 9242 const newend = newlen-i; 9243 return { 9244 start, 9245 oldText: oldText.slice(start, oldend), 9246 newText: newText.slice(start, newend) 9247 } 9248}; 9249bililiteRange.diff = diff; // expose 9250 9251function correctNewlines (element, range, data){ 9252 // we need to insert newlines rather than create new elements, so character-based calculations work 9253 range.listen('paste', evt => { 9254 if (evt.defaultPrevented) return; 9255 // windows adds \r's to clipboard! 9256 range.clone().bounds('selection'). 9257 text(evt.clipboardData.getData("text/plain").replace(/\r/g,''), {inputType: 'insertFromPaste'}). 9258 bounds('endbounds'). 9259 select(). 9260 scrollIntoView(); 9261 evt.preventDefault(); 9262 }); 9263 range.listen('keydown', function(evt){ 9264 if (evt.ctrlKey || evt.altKey || evt.shiftKey || evt.metaKey) return; 9265 if (evt.defaultPrevented) return; 9266 if (evt.key == 'Enter'){ 9267 range.clone().bounds('selection'). 9268 text('\n', {inputType: 'insertLineBreak'}). 9269 bounds('endbounds'). 9270 select(). 9271 scrollIntoView(); 9272 evt.preventDefault(); 9273 } 9274 }); 9275} 9276 9277// convenience function for defining input events 9278function inputEventInit(type, oldText, newText, start, inputType){ 9279 return { 9280 type, 9281 inputType, 9282 data: newText, 9283 bubbles: true, 9284 bililiteRange: { 9285 unchanged: (oldText == newText), 9286 start, 9287 oldText, 9288 newText 9289 } 9290 }; 9291} 9292 9293// base class 9294function Range(){} 9295Range.prototype = { 9296 // allow use of range[0] and range[1] for start and end of bounds 9297 get 0(){ 9298 return this.bounds()[0]; 9299 }, 9300 set 0(x){ 9301 this.bounds([x, this[1]]); 9302 return x; 9303 }, 9304 get 1(){ 9305 return this.bounds()[1]; 9306 }, 9307 set 1(x){ 9308 this.bounds([this[0], x]); 9309 return x; 9310 }, 9311 all: function(text){ 9312 if (arguments.length){ 9313 return this.bounds('all').text(text, {inputType: 'insertReplacementText'}); 9314 }else{ 9315 return this._el[this._textProp]; 9316 } 9317 }, 9318 bounds: function(s){ 9319 if (typeof s === 'number'){ 9320 this._bounds = [s,s]; 9321 }else if (bililiteRange.bounds[s]){ 9322 this.bounds(bililiteRange.bounds[s].apply(this, arguments)); 9323 }else if (s && s.bounds){ 9324 this._bounds = s.bounds(); // copy bounds from an existing range 9325 }else if (s){ 9326 this._bounds = s; // don't do error checking now; things may change at a moment's notice 9327 }else{ 9328 // constrain bounds now 9329 var b = [ 9330 Math.max(0, Math.min (this.length, this._bounds[0])), 9331 Math.max(0, Math.min (this.length, this._bounds[1])) 9332 ]; 9333 b[1] = Math.max(b[0], b[1]); 9334 return b; 9335 } 9336 return this; // allow for chaining 9337 }, 9338 clone: function(){ 9339 return bililiteRange(this._el).bounds(this.bounds()); 9340 }, 9341 get data(){ 9342 return this._el[datakey]; 9343 }, 9344 dispatch: function(opts = {}){ 9345 var event = new Event (opts.type, opts); 9346 event.view = this._win; 9347 for (let prop in opts) try { event[prop] = opts[prop] } catch(e){}; // ignore read-only errors for properties that were copied in the previous line 9348 this._el.dispatchEvent(event); // note that the event handlers will be called synchronously, before the "return this;" 9349 return this; 9350 }, 9351 get document() { 9352 return this._doc; 9353 }, 9354 dontlisten: function (type, func = console.log){ 9355 this._el.removeEventListener(type, func); 9356 return this; 9357 },
9358 get element() { 9359 return this._el 9360 }, 9361 get length() { 9362 return this._el[this._textProp].length; 9363 }, 9364 live (on = true){ 9365 this.data.liveRanges[on ? 'add' : 'delete'](this); 9366 return this; 9367 }, 9368 listen: function (type, func = console.log){ 9369 this._el.addEventListener(type, func); 9370 return this; 9371 }, 9372 scrollIntoView: function(scroller = (top => this._el.scrollTop = top) ){ 9373 var top = this.top(); 9374 // scroll into position if necessary 9375 if (this._el.scrollTop > top || this._el.scrollTop+this._el.clientHeight < top){ 9376 scroller.call(this._el, top); 9377 } 9378 return this; 9379 }, 9380 select: function(){ 9381 var b = this.data.selection = this.bounds(); 9382 if (this._el === this._doc.activeElement){ 9383 // only actually select if this element is active! 9384 this._nativeSelect(this._nativeRange(b)); 9385 } 9386 this.dispatch({type: 'select', bubbles: true}); 9387 return this; // allow for chaining 9388 }, 9389 selection: function(text){ 9390 if (arguments.length){ 9391 return this.bounds('selection').text(text).bounds('endbounds').select(); 9392 }else{ 9393 return this.bounds('selection').text(); 9394 } 9395 }, 9396 sendkeys: function (text){ 9397 this.data.sendkeysOriginalText = this.text(); 9398 this.data.sendkeysBounds = undefined; 9399 function simplechar (rng, c){ 9400 if (/^{[^}]*}$/.test(c)) c = c.slice(1,-1); // deal with unknown {key}s 9401 rng.text(c).bounds('endbounds'); 9402 } 9403 text.replace(/{[^}]*}|[^{]+|{/g, part => (bililiteRange.sendkeys[part] || simplechar)(this, part, simplechar) ); 9404 this.bounds(this.data.sendkeysBounds); 9405 this.dispatch({type: 'sendkeys', detail: text}); 9406 return this; 9407 }, 9408 text: function(text, {inputType = 'insertText'} = {}){ 9409 if ( text !== undefined ){ 9410 let eventparams = [this.text(), text, this[0], inputType]; 9411 this.dispatch (inputEventInit('beforeinput',...eventparams)); 9412 this._nativeSetText(text, this._nativeRange(this.bounds())); 9413 this[1] = this[0]+text.length; 9414 this.dispatch (inputEventInit('input',...eventparams)); 9415 return this; // allow for chaining 9416 }else{ 9417 return this._nativeGetText(this._nativeRange(this.bounds())); 9418 } 9419 }, 9420 top: function(){ 9421 return this._nativeTop(this._nativeRange(this.bounds())); 9422 }, 9423 get window() { 9424 return this._win; 9425 }, 9426 wrap: function (n){ 9427 this._nativeWrap(n, this._nativeRange(this.bounds())); 9428 return this; 9429 }, 9430}; 9431 9432// allow extensions ala jQuery 9433bililiteRange.prototype = Range.prototype; 9434bililiteRange.extend = function(fns){ 9435 Object.assign(bililiteRange.prototype, fns); 9436}; 9437 9438bililiteRange.override = (name, fn) => { 9439 const oldfn = bililiteRange.prototype[name]; 9440 bililiteRange.prototype[name] = function(){ 9441 const oldsuper = this.super; 9442 this.super = oldfn; 9443 const ret = fn.apply(this, arguments); 9444 this.super = oldsuper; 9445 return ret; 9446 }; 9447} 9448 9449//bounds functions 9450bililiteRange.bounds = { 9451 all: function() { return [0, this.length] }, 9452 start: function() { return 0 }, 9453 end: function() { return this.length }, 9454 selection: function() { 9455 if (this._el === this._doc.activeElement){ 9456 this.bounds ('all'); // first select the whole thing for constraining 9457 return this._nativeSelection(); 9458 }else{ 9459 return this.data.selection; 9460 } 9461 }, 9462 startbounds: function() { return this[0] }, 9463 endbounds: function() { return this[1] }, 9464 union: function (name,...rest) { 9465 const b = this.clone().bounds(...rest); 9466 return [ Math.min(this[0], b[0]), Math.max(this[1], b[1]) ]; 9467 }, 9468 intersection: function (name,...rest) { 9469 const b = this.clone().bounds(...rest); 9470 return [ Math.max(this[0], b[0]), Math.min(this[1], b[1]) ]; 9471 } 9472}; 9473 9474// sendkeys functions 9475bililiteRange.sendkeys = { 9476 '{tab}': function (rng, c, simplechar){ 9477 simplechar(rng, '\t'); // useful for inserting what would be whitespace 9478 }, 9479 '{newline}': function (rng){ 9480 rng.text('\n', {inputType: 'insertLineBreak'}).bounds('endbounds'); 9481 }, 9482 '{backspace}': function (rng){ 9483 var b = rng.bounds(); 9484 if (b[0] == b[1]) rng.bounds([b[0]-1, b[0]]); // no characters selected; it's just an insertion point. Remove the previous character 9485 rng.text('', {inputType: 'deleteContentBackward'}); // delete the characters and update the selection 9486 }, 9487 '{del}': function (rng){ 9488 var b = rng.bounds(); 9489 if (b[0] == b[1]) rng.bounds([b[0], b[0]+1]); // no characters selected; it's just an insertion point. Remove the next character 9490 rng.text('', {inputType: 'deleteContentForward'}).bounds('endbounds'); // delete the characters and update the selection 9491 }, 9492 '{rightarrow}': function (rng){ 9493 var b = rng.bounds(); 9494 if (b[0] == b[1]) ++b[1]; // no characters selected; it's just an insertion point. Move to the right 9495 rng.bounds([b[1], b[1]]); 9496 }, 9497 '{leftarrow}': function (rng){ 9498 var b = rng.bounds(); 9499 if (b[0] == b[1]) --b[0]; // no characters selected; it's just an insertion point. Move to the left 9500 rng.bounds([b[0], b[0]]); 9501 }, 9502 '{selectall}': function (rng){ 9503 rng.bounds('all'); 9504 }, 9505 '{selection}': function (rng){ 9506 // insert the characters without the sendkeys processing 9507 rng.text(rng.data.sendkeysOriginalText).bounds('endbounds'); 9508 }, 9509 '{mark}': function (rng){ 9510 rng.data.sendkeysBounds = rng.bounds(); 9511 } 9512};
9513// Synonyms from the DOM standard (http://www.w3.org/TR/DOM-Level-3-Events-key/) 9514bililiteRange.sendkeys['{Enter}'] = bililiteRange.sendkeys['{enter}'] = bililiteRange.sendkeys['{newline}']; 9515bililiteRange.sendkeys['{Backspace}'] = bililiteRange.sendkeys['{backspace}']; 9516bililiteRange.sendkeys['{Delete}'] = bililiteRange.sendkeys['{del}']; 9517bililiteRange.sendkeys['{ArrowRight}'] = bililiteRange.sendkeys['{rightarrow}']; 9518bililiteRange.sendkeys['{ArrowLeft}'] = bililiteRange.sendkeys['{leftarrow}']; 9519 9520// an input element in a standards document. "Native Range" is just the bounds array 9521function InputRange(){} 9522InputRange.prototype = new Range(); 9523InputRange.prototype._textProp = 'value'; 9524InputRange.prototype._nativeRange = function(bounds) { 9525 return bounds || [0, this.length]; 9526}; 9527InputRange.prototype._nativeSelect = function (rng){ 9528 this._el.setSelectionRange(rng[0], rng[1]); 9529}; 9530InputRange.prototype._nativeSelection = function(){ 9531 return [this._el.selectionStart, this._el.selectionEnd]; 9532}; 9533InputRange.prototype._nativeGetText = function(rng){ 9534 return this._el.value.substring(rng[0], rng[1]); 9535}; 9536InputRange.prototype._nativeSetText = function(text, rng){ 9537 var val = this._el.value; 9538 this._el.value = val.substring(0, rng[0]) + text + val.substring(rng[1]); 9539}; 9540InputRange.prototype._nativeEOL = function(){ 9541 this.text('\n'); 9542}; 9543InputRange.prototype._nativeTop = function(rng){ 9544 if (rng[0] == 0) return 0; // the range starts at the top 9545 // I can't remember where I found this clever hack to find the location of text in a text area 9546 var clone = this._el.cloneNode(true); 9547 clone.style.visibility = 'hidden'; 9548 clone.style.position = 'absolute'; 9549 this._el.parentNode.insertBefore(clone, this._el); 9550 clone.style.height = '1px'; 9551 clone.value = this._el.value.slice(0, rng[0]); 9552 var top = clone.scrollHeight; 9553 // this gives the bottom of the text, so we have to subtract the height of a single line 9554 clone.value = 'X'; 9555 top -= clone.scrollHeight; 9556 clone.parentNode.removeChild(clone); 9557 return top; 9558} 9559InputRange.prototype._nativeWrap = function() {throw new Error("Cannot wrap in a text element")}; 9560 9561function W3CRange(){} 9562W3CRange.prototype = new Range(); 9563W3CRange.prototype._textProp = 'textContent'; 9564W3CRange.prototype._nativeRange = function (bounds){ 9565 var rng = this._doc.createRange(); 9566 rng.selectNodeContents(this._el); 9567 if (bounds){ 9568 w3cmoveBoundary (rng, bounds[0], true, this._el); 9569 rng.collapse (true);
9570 w3cmoveBoundary (rng, bounds[1]-bounds[0], false, this._el); 9571 } 9572 return rng; 9573}; 9574W3CRange.prototype._nativeSelect = function (rng){ 9575 this._win.getSelection().removeAllRanges(); 9576 this._win.getSelection().addRange (rng); 9577}; 9578W3CRange.prototype._nativeSelection = function (){ 9579 // returns [start, end] for the selection constrained to be in element 9580 var rng = this._nativeRange(); // range of the element to constrain to 9581 if (this._win.getSelection().rangeCount == 0) return [this.length, this.length]; // append to the end 9582 var sel = this._win.getSelection().getRangeAt(0); 9583 return [ 9584 w3cstart(sel, rng), 9585 w3cend (sel, rng) 9586 ]; 9587}; 9588W3CRange.prototype._nativeGetText = function (rng){ 9589 return rng.toString(); 9590}; 9591W3CRange.prototype._nativeSetText = function (text, rng){ 9592 rng.deleteContents(); 9593 rng.insertNode (this._doc.createTextNode(text)); 9594 this._el.normalize(); // merge the text with the surrounding text 9595}; 9596W3CRange.prototype._nativeEOL = function(){ 9597 var rng = this._nativeRange(this.bounds()); 9598 rng.deleteContents(); 9599 var br = this._doc.createElement('br'); 9600 br.setAttribute ('_moz_dirty', ''); // for Firefox 9601 rng.insertNode (br); 9602 rng.insertNode (this._doc.createTextNode('\n')); 9603 rng.collapse (false); 9604}; 9605W3CRange.prototype._nativeTop = function(rng){ 9606 if (this.length == 0) return 0; // no text, no scrolling 9607 if (rng.toString() == ''){ 9608 var textnode = this._doc.createTextNode('X'); 9609 rng.insertNode (textnode); 9610 } 9611 var startrng = this._nativeRange([0,1]); 9612 var top = rng.getBoundingClientRect().top - startrng.getBoundingClientRect().top; 9613 if (textnode) textnode.parentNode.removeChild(textnode); 9614 return top; 9615} 9616W3CRange.prototype._nativeWrap = function(n, rng) { 9617 rng.surroundContents(n); 9618}; 9619 9620// W3C internals 9621function nextnode (node, root){ 9622 // in-order traversal 9623 // we've already visited node, so get kids then siblings 9624 if (node.firstChild) return node.firstChild; 9625 if (node.nextSibling) return node.nextSibling; 9626 if (node===root) return null; 9627 while (node.parentNode){ 9628 // get uncles 9629 node = node.parentNode; 9630 if (node == root) return null; 9631 if (node.nextSibling) return node.nextSibling; 9632 } 9633 return null; 9634} 9635function w3cmoveBoundary (rng, n, bStart, el){ 9636 // move the boundary (bStart == true ? start : end) n characters forward, up to the end of element el. Forward only! 9637 // if the start is moved after the end, then an exception is raised 9638 if (n <= 0) return; 9639 var node = rng[bStart ? 'startContainer' : 'endContainer']; 9640 if (node.nodeType == 3){ 9641 // we may be starting somewhere into the text 9642 n += rng[bStart ? 'startOffset' : 'endOffset']; 9643 } 9644 while (node){ 9645 if (node.nodeType == 3){ 9646 var length = node.nodeValue.length; 9647 if (n <= length){ 9648 rng[bStart ? 'setStart' : 'setEnd'](node, n); 9649 // special case: if we end next to a <br>, include that node. 9650 if (n == length){ 9651 // skip past zero-length text nodes 9652 for (var next = nextnode (node, el); next && next.nodeType==3 && next.nodeValue.length == 0; next = nextnode(next, el)){ 9653 rng[bStart ? 'setStartAfter' : 'setEndAfter'](next); 9654 } 9655 if (next && next.nodeType == 1 && next.nodeName == "BR") rng[bStart ? 'setStartAfter' : 'setEndAfter'](next); 9656 } 9657 return; 9658 }else{ 9659 rng[bStart ? 'setStartAfter' : 'setEndAfter'](node); // skip past this one 9660 n -= length; // and eat these characters 9661 } 9662 } 9663 node = nextnode (node, el); 9664 } 9665} 9666var START_TO_START = 0; // from the w3c definitions 9667var START_TO_END = 1; 9668var END_TO_END = 2; 9669var END_TO_START = 3; 9670// from the Mozilla documentation, for range.compareBoundaryPoints(how, sourceRange) 9671// -1, 0, or 1, indicating whether the corresponding boundary-point of range is respectively before, equal to, or after the corresponding boundary-point of sourceRange. 9672 // * Range.END_TO_END compares the end boundary-point of sourceRange to the end boundary-point of range. 9673 // * Range.END_TO_START compares the end boundary-point of sourceRange to the start boundary-point of range. 9674 // * Range.START_TO_END compares the start boundary-point of sourceRange to the end boundary-point of range. 9675 // * Range.START_TO_START compares the start boundary-point of sourceRange to the start boundary-point of range. 9676function w3cstart(rng, constraint){ 9677 if (rng.compareBoundaryPoints (START_TO_START, constraint) <= 0) return 0; // at or before the beginning 9678 if (rng.compareBoundaryPoints (END_TO_START, constraint) >= 0) return constraint.toString().length; 9679 rng = rng.cloneRange(); // don't change the original
9680 rng.setEnd (constraint.endContainer, constraint.endOffset); // they now end at the same place 9681 return constraint.toString().length - rng.toString().length; 9682} 9683function w3cend (rng, constraint){ 9684 if (rng.compareBoundaryPoints (END_TO_END, constraint) >= 0) return constraint.toString().length; // at or after the end 9685 if (rng.compareBoundaryPoints (START_TO_END, constraint) <= 0) return 0; 9686 rng = rng.cloneRange(); // don't change the original 9687 rng.setStart (constraint.startContainer, constraint.startOffset); // they now start at the same place 9688 return rng.toString().length; 9689} 9690 9691function NothingRange(){} 9692NothingRange.prototype = new Range(); 9693NothingRange.prototype._textProp = 'value'; 9694NothingRange.prototype._nativeRange = function(bounds) { 9695 return bounds || [0,this.length]; 9696}; 9697NothingRange.prototype._nativeSelect = function (rng){ // do nothing 9698}; 9699NothingRange.prototype._nativeSelection = function(){ 9700 return [0,0]; 9701}; 9702NothingRange.prototype._nativeGetText = function (rng){ 9703 return this._el[this._textProp].substring(rng[0], rng[1]); 9704}; 9705NothingRange.prototype._nativeSetText = function (text, rng){ 9706 var val = this._el[this._textProp]; 9707 this._el[this._textProp] = val.substring(0, rng[0]) + text + val.substring(rng[1]); 9708}; 9709NothingRange.prototype._nativeEOL = function(){ 9710 this.text('\n'); 9711}; 9712NothingRange.prototype._nativeTop = function(){ 9713 return 0; 9714}; 9715NothingRange.prototype._nativeWrap = function() {throw new Error("Wrapping not implemented")}; 9716 9717 9718// data for elements, similar to jQuery data, but allows for monitoring with custom events 9719const monitored = new Set(); 9720 9721function signalMonitor(prop, value, element){ 9722 const attr = `data-${prop}`; 9723 element.dispatchEvent(new CustomEvent(attr, {bubbles: true, detail: value})); 9724 try{ 9725 element.setAttribute (attr, value); // illegal attribute names will throw. Ignore it 9726 } finally { /* ignore */ } 9727} 9728 9729function createDataObject (el){ 9730 return el[datakey] = new Proxy(new Data(el), { 9731 set(obj, prop, value) { 9732 obj[prop] = value; 9733 if (monitored.has(prop)) signalMonitor(prop, value, obj.sourceElement); 9734 return true; // in strict mode, 'set' returns a success flag 9735 } 9736 }); 9737} 9738 9739var Data = function(el) { 9740 Object.defineProperty(this, 'sourceElement', { 9741 value: el 9742 }); 9743} 9744 9745Data.prototype = {}; 9746// for use with ex options. JSON.stringify(range.data) should return only the options that were 9747// both defined with bililiteRange.option() *and* actually had a value set on this particular data object. 9748// JSON.stringify (range.data.all) should return all the options that were defined. 9749Object.defineProperty(Data.prototype, 'toJSON', { 9750 value: function(){ 9751 let ret = {}; 9752 for (let key in Data.prototype) if (this.hasOwnProperty(key)) ret[key] = this[key]; 9753 return ret; 9754 } 9755}); 9756Object.defineProperty(Data.prototype, 'all', { 9757 get: function(){ 9758 let ret = {}; 9759 for (let key in Data.prototype) ret[key] = this[key]; 9760 return ret; 9761 } 9762}); 9763Object.defineProperty(Data.prototype, 'trigger', { 9764 value: function(){ 9765 monitored.forEach(prop => signalMonitor (prop, this[prop], this.sourceElement)); 9766 } 9767}); 9768 9769bililiteRange.createOption = function (name, desc = {}){ 9770 desc = Object.assign({ 9771 enumerable: true, // use these as the defaults 9772 writable: true, 9773 configurable: true 9774 }, Object.getOwnPropertyDescriptor(Data.prototype, name), desc); 9775 if ('monitored' in desc) monitored[desc.monitored ? 'add' : 'delete'](name); 9776 Object.defineProperty(Data.prototype, name, desc); 9777 return Data.prototype[name]; // return the default value 9778} 9779 9780})(); 9781 9782define("bililiteRange", ["jquery"], function(){}); 9783 9784/* ======================================================================== 9785 * Bootstrap: transition.js v3.3.1 9786 * http://getbootstrap.com/javascript/#transitions 9787 * ======================================================================== 9788 * Copyright 2011-2014 Twitter, Inc. 9789 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 9790 * ======================================================================== */ 9791 9792 9793+function ($) { 9794 'use strict'; 9795
vendor: 66,327 bytes, lines 9796-12087
9796 // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/) 9797 // ============================================================ 9798 9799 function transitionEnd() { 9800 var el = document.createElement('bootstrap') 9801 9802 var transEndEventNames = { 9803 WebkitTransition : 'webkitTransitionEnd', 9804 MozTransition : 'transitionend', 9805 OTransition : 'oTransitionEnd otransitionend', 9806 transition : 'transitionend' 9807 } 9808 9809 for (var name in transEndEventNames) { 9810 if (el.style[name] !== undefined) { 9811 return { end: transEndEventNames[name] } 9812 } 9813 } 9814 9815 return false // explicit for ie8 ( ._.) 9816 } 9817 9818 // http://blog.alexmaccaw.com/css-transitions 9819 $.fn.emulateTransitionEnd = function (duration) { 9820 var called = false 9821 var $el = this 9822 $(this).one('bsTransitionEnd', function () { called = true }) 9823 var callback = function () { if (!called) $($el).trigger($.support.transition.end) } 9824 setTimeout(callback, duration) 9825 return this 9826 } 9827 9828 $(function () { 9829 $.support.transition = transitionEnd() 9830 9831 if (!$.support.transition) return 9832 9833 $.event.special.bsTransitionEnd = { 9834 bindType: $.support.transition.end, 9835 delegateType: $.support.transition.end, 9836 handle: function (e) { 9837 if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments) 9838 } 9839 } 9840 }) 9841 9842}(jQuery); 9843 9844define("bootstrapTransition", ["jquery"], (function (global) { 9845 return function () { 9846 var ret, fn; 9847 return ret || global.$; 9848 }; 9849}(this))); 9850 9851/* ======================================================================== 9852 * Bootstrap: alert.js v3.3.1 9853 * http://getbootstrap.com/javascript/#alerts 9854 * ======================================================================== 9855 * Copyright 2011-2014 Twitter, Inc. 9856 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 9857 * ======================================================================== */ 9858 9859 9860+function ($) { 9861 'use strict'; 9862 9863 // ALERT CLASS DEFINITION 9864 // ====================== 9865 9866 var dismiss = '[data-dismiss="alert"]' 9867 var Alert = function (el) { 9868 $(el).on('click', dismiss, this.close) 9869 } 9870 9871 Alert.VERSION = '3.3.1' 9872 9873 Alert.TRANSITION_DURATION = 150 9874 9875 Alert.prototype.close = function (e) { 9876 var $this = $(this) 9877 var selector = $this.attr('data-target') 9878 9879 if (!selector) { 9880 selector = $this.attr('href') 9881 selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 9882 } 9883 9884 var $parent = $(selector) 9885 9886 if (e) e.preventDefault() 9887 9888 if (!$parent.length) { 9889 $parent = $this.closest('.alert') 9890 } 9891 9892 $parent.trigger(e = $.Event('close.bs.alert')) 9893 9894 if (e.isDefaultPrevented()) return 9895 9896 $parent.removeClass('in') 9897 9898 function removeElement() { 9899 // detach from parent, fire event then clean up data 9900 $parent.detach().trigger('closed.bs.alert').remove() 9901 } 9902 9903 $.support.transition && $parent.hasClass('fade') ? 9904 $parent 9905 .one('bsTransitionEnd', removeElement) 9906 .emulateTransitionEnd(Alert.TRANSITION_DURATION) : 9907 removeElement() 9908 } 9909 9910 9911 // ALERT PLUGIN DEFINITION 9912 // ======================= 9913 9914 function Plugin(option) { 9915 return this.each(function () { 9916 var $this = $(this) 9917 var data = $this.data('bs.alert') 9918 9919 if (!data) $this.data('bs.alert', (data = new Alert(this))) 9920 if (typeof option == 'string') data[option].call($this) 9921 }) 9922 } 9923 9924 var old = $.fn.alert 9925 9926 $.fn.alert = Plugin 9927 $.fn.alert.Constructor = Alert 9928 9929 9930 // ALERT NO CONFLICT 9931 // ================= 9932 9933 $.fn.alert.noConflict = function () { 9934 $.fn.alert = old 9935 return this 9936 } 9937 9938 9939 // ALERT DATA-API 9940 // ============== 9941 9942 $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close) 9943 9944}(jQuery); 9945 9946define("bootstrapAlert", ["jquery","bootstrapTransition"], (function (global) { 9947 return function () { 9948 var ret, fn; 9949 return ret || global.$; 9950 }; 9951}(this))); 9952 9953/* ======================================================================== 9954 * Bootstrap: button.js v3.3.1 9955 * http://getbootstrap.com/javascript/#buttons 9956 * ======================================================================== 9957 * Copyright 2011-2014 Twitter, Inc. 9958 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 9959 * ======================================================================== */ 9960 9961 9962+function ($) { 9963 'use strict'; 9964 9965 // BUTTON PUBLIC CLASS DEFINITION 9966 // ============================== 9967 9968 var Button = function (element, options) { 9969 this.$element = $(element) 9970 this.options = $.extend({}, Button.DEFAULTS, options) 9971 this.isLoading = false 9972 } 9973 9974 Button.VERSION = '3.3.1' 9975 9976 Button.DEFAULTS = { 9977 loadingText: 'loading...' 9978 } 9979 9980 Button.prototype.setState = function (state) { 9981 var d = 'disabled' 9982 var $el = this.$element 9983 var val = $el.is('input') ? 'val' : 'html' 9984 var data = $el.data() 9985 9986 state = state + 'Text' 9987 9988 if (data.resetText == null) $el.data('resetText', $el[val]()) 9989 9990 // push to event loop to allow forms to submit 9991 setTimeout($.proxy(function () { 9992 $el[val](data[state] == null ? this.options[state] : data[state]) 9993 9994 if (state == 'loadingText') { 9995 this.isLoading = true 9996 $el.addClass(d).attr(d, d) 9997 } else if (this.isLoading) { 9998 this.isLoading = false 9999 $el.removeClass(d).removeAttr(d) 10000 } 10001 }, this), 0) 10002 } 10003 10004 Button.prototype.toggle = function () { 10005 var changed = true 10006 var $parent = this.$element.closest('[data-toggle="buttons"]') 10007 10008 if ($parent.length) { 10009 var $input = this.$element.find('input') 10010 if ($input.prop('type') == 'radio') { 10011 if ($input.prop('checked') && this.$element.hasClass('active')) changed = false 10012 else $parent.find('.active').removeClass('active') 10013 } 10014 if (changed) $input.prop('checked', !this.$element.hasClass('active')).trigger('change') 10015 } else { 10016 this.$element.attr('aria-pressed', !this.$element.hasClass('active')) 10017 } 10018 10019 if (changed) this.$element.toggleClass('active') 10020 } 10021 10022 10023 // BUTTON PLUGIN DEFINITION 10024 // ======================== 10025 10026 function Plugin(option) { 10027 return this.each(function () { 10028 var $this = $(this) 10029 var data = $this.data('bs.button') 10030 var options = typeof option == 'object' && option 10031 10032 if (!data) $this.data('bs.button', (data = new Button(this, options))) 10033 10034 if (option == 'toggle') data.toggle() 10035 else if (option) data.setState(option) 10036 }) 10037 } 10038 10039 var old = $.fn.button 10040 10041 $.fn.button = Plugin 10042 $.fn.button.Constructor = Button 10043 10044 10045 // BUTTON NO CONFLICT 10046 // ================== 10047 10048 $.fn.button.noConflict = function () { 10049 $.fn.button = old 10050 return this 10051 } 10052 10053 10054 // BUTTON DATA-API 10055 // =============== 10056 10057 $(document) 10058 .on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) { 10059 var $btn = $(e.target) 10060 if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn') 10061 Plugin.call($btn, 'toggle') 10062 e.preventDefault() 10063 }) 10064 .on('focus.bs.button.data-api blur.bs.button.data-api', '[data-toggle^="button"]', function (e) { 10065 $(e.target).closest('.btn').toggleClass('focus', /^focus(in)?$/.test(e.type)) 10066 }) 10067 10068}(jQuery); 10069 10070define("bootstrapButton", ["jquery","bootstrapTransition"], (function (global) { 10071 return function () { 10072 var ret, fn; 10073 return ret || global.$; 10074 }; 10075}(this))); 10076 10077/* ======================================================================== 10078 * Bootstrap: carousel.js v3.3.1 10079 * http://getbootstrap.com/javascript/#carousel 10080 * ======================================================================== 10081 * Copyright 2011-2014 Twitter, Inc. 10082 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 10083 * ======================================================================== */ 10084 10085 10086+function ($) { 10087 'use strict'; 10088 10089 // CAROUSEL CLASS DEFINITION 10090 // ========================= 10091 10092 var Carousel = function (element, options) { 10093 this.$element = $(element) 10094 this.$indicators = this.$element.find('.carousel-indicators') 10095 this.options = options 10096 this.paused = 10097 this.sliding = 10098 this.interval = 10099 this.$active = 10100 this.$items = null 10101 10102 this.options.keyboard && this.$element.on('keydown.bs.carousel', $.proxy(this.keydown, this)) 10103 10104 this.options.pause == 'hover' && !('ontouchstart' in document.documentElement) && this.$element 10105 .on('mouseenter.bs.carousel', $.proxy(this.pause, this)) 10106 .on('mouseleave.bs.carousel', $.proxy(this.cycle, this)) 10107 } 10108 10109 Carousel.VERSION = '3.3.1' 10110 10111 Carousel.TRANSITION_DURATION = 600 10112 10113 Carousel.DEFAULTS = { 10114 interval: 5000, 10115 pause: 'hover', 10116 wrap: true, 10117 keyboard: true 10118 } 10119 10120 Carousel.prototype.keydown = function (e) { 10121 if (/input|textarea/i.test(e.target.tagName)) return 10122 switch (e.which) { 10123 case 37: this.prev(); break 10124 case 39: this.next(); break 10125 default: return 10126 } 10127 10128 e.preventDefault() 10129 } 10130 10131 Carousel.prototype.cycle = function (e) { 10132 e || (this.paused = false) 10133 10134 this.interval && clearInterval(this.interval) 10135 10136 this.options.interval 10137 && !this.paused 10138 && (this.interval = setInterval($.proxy(this.next, this), this.options.interval)) 10139 10140 return this 10141 } 10142 10143 Carousel.prototype.getItemIndex = function (item) { 10144 this.$items = item.parent().children('.item') 10145 return this.$items.index(item || this.$active) 10146 } 10147 10148 Carousel.prototype.getItemForDirection = function (direction, active) { 10149 var delta = direction == 'prev' ? -1 : 1 10150 var activeIndex = this.getItemIndex(active) 10151 var itemIndex = (activeIndex + delta) % this.$items.length 10152 return this.$items.eq(itemIndex) 10153 } 10154 10155 Carousel.prototype.to = function (pos) { 10156 var that = this 10157 var activeIndex = this.getItemIndex(this.$active = this.$element.find('.item.active')) 10158 10159 if (pos > (this.$items.length - 1) || pos < 0) return 10160 10161 if (this.sliding) return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) // yes, "slid" 10162 if (activeIndex == pos) return this.pause().cycle() 10163 10164 return this.slide(pos > activeIndex ? 'next' : 'prev', this.$items.eq(pos)) 10165 } 10166 10167 Carousel.prototype.pause = function (e) { 10168 e || (this.paused = true) 10169 10170 if (this.$element.find('.next, .prev').length && $.support.transition) { 10171 this.$element.trigger($.support.transition.end) 10172 this.cycle(true) 10173 } 10174 10175 this.interval = clearInterval(this.interval) 10176 10177 return this 10178 } 10179 10180 Carousel.prototype.next = function () { 10181 if (this.sliding) return 10182 return this.slide('next') 10183 } 10184 10185 Carousel.prototype.prev = function () { 10186 if (this.sliding) return 10187 return this.slide('prev') 10188 } 10189 10190 Carousel.prototype.slide = function (type, next) { 10191 var $active = this.$element.find('.item.active') 10192 var $next = next || this.getItemForDirection(type, $active) 10193 var isCycling = this.interval 10194 var direction = type == 'next' ? 'left' : 'right' 10195 var fallback = type == 'next' ? 'first' : 'last' 10196 var that = this 10197 10198 if (!$next.length) { 10199 if (!this.options.wrap) return 10200 $next = this.$element.find('.item')[fallback]() 10201 } 10202 10203 if ($next.hasClass('active')) return (this.sliding = false) 10204 10205 var relatedTarget = $next[0] 10206 var slideEvent = $.Event('slide.bs.carousel', { 10207 relatedTarget: relatedTarget, 10208 direction: direction 10209 }) 10210 this.$element.trigger(slideEvent) 10211 if (slideEvent.isDefaultPrevented()) return 10212 10213 this.sliding = true 10214 10215 isCycling && this.pause() 10216 10217 if (this.$indicators.length) { 10218 this.$indicators.find('.active').removeClass('active') 10219 var $nextIndicator = $(this.$indicators.children()[this.getItemIndex($next)]) 10220 $nextIndicator && $nextIndicator.addClass('active') 10221 } 10222 10223 var slidEvent = $.Event('slid.bs.carousel', { relatedTarget: relatedTarget, direction: direction }) // yes, "slid" 10224 if ($.support.transition && this.$element.hasClass('slide')) { 10225 $next.addClass(type) 10226 $next[0].offsetWidth // force reflow 10227 $active.addClass(direction) 10228 $next.addClass(direction) 10229 $active 10230 .one('bsTransitionEnd', function () { 10231 $next.removeClass([type, direction].join(' ')).addClass('active') 10232 $active.removeClass(['active', direction].join(' ')) 10233 that.sliding = false 10234 setTimeout(function () { 10235 that.$element.trigger(slidEvent) 10236 }, 0) 10237 }) 10238 .emulateTransitionEnd(Carousel.TRANSITION_DURATION) 10239 } else { 10240 $active.removeClass('active') 10241 $next.addClass('active') 10242 this.sliding = false 10243 this.$element.trigger(slidEvent) 10244 } 10245 10246 isCycling && this.cycle() 10247 10248 return this 10249 } 10250 10251 10252 // CAROUSEL PLUGIN DEFINITION 10253 // ========================== 10254 10255 function Plugin(option) { 10256 return this.each(function () { 10257 var $this = $(this) 10258 var data = $this.data('bs.carousel') 10259 var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option) 10260 var action = typeof option == 'string' ? option : options.slide 10261 10262 if (!data) $this.data('bs.carousel', (data = new Carousel(this, options))) 10263 if (typeof option == 'number') data.to(option) 10264 else if (action) data[action]() 10265 else if (options.interval) data.pause().cycle() 10266 }) 10267 } 10268 10269 var old = $.fn.carousel 10270 10271 $.fn.carousel = Plugin 10272 $.fn.carousel.Constructor = Carousel 10273 10274 10275 // CAROUSEL NO CONFLICT 10276 // ==================== 10277 10278 $.fn.carousel.noConflict = function () { 10279 $.fn.carousel = old 10280 return this 10281 } 10282 10283 10284 // CAROUSEL DATA-API 10285 // ================= 10286 10287 var clickHandler = function (e) { 10288 var href 10289 var $this = $(this) 10290 var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) // strip for ie7 10291 if (!$target.hasClass('carousel')) return 10292 var options = $.extend({}, $target.data(), $this.data()) 10293 var slideIndex = $this.attr('data-slide-to') 10294 if (slideIndex) options.interval = false 10295 10296 Plugin.call($target, options) 10297 10298 if (slideIndex) { 10299 $target.data('bs.carousel').to(slideIndex) 10300 } 10301 10302 e.preventDefault() 10303 } 10304 10305 $(document) 10306 .on('click.bs.carousel.data-api', '[data-slide]', clickHandler) 10307 .on('click.bs.carousel.data-api', '[data-slide-to]', clickHandler) 10308 10309 $(window).on('load', function () { 10310 $('[data-ride="carousel"]').each(function () { 10311 var $carousel = $(this) 10312 Plugin.call($carousel, $carousel.data()) 10313 }) 10314 }) 10315 10316}(jQuery); 10317 10318define("bootstrapCarousel", ["jquery","bootstrapTransition"], (function (global) { 10319 return function () { 10320 var ret, fn; 10321 return ret || global.$; 10322 }; 10323}(this))); 10324 10325/* ======================================================================== 10326 * Bootstrap: collapse.js v3.3.1 10327 * http://getbootstrap.com/javascript/#collapse 10328 * ======================================================================== 10329 * Copyright 2011-2014 Twitter, Inc. 10330 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 10331 * ======================================================================== */ 10332 10333 10334+function ($) { 10335 'use strict'; 10336 10337 // COLLAPSE PUBLIC CLASS DEFINITION 10338 // ================================ 10339 10340 var Collapse = function (element, options) { 10341 this.$element = $(element) 10342 this.options = $.extend({}, Collapse.DEFAULTS, options) 10343 this.$trigger = $(this.options.trigger).filter('[href="#' + element.id + '"], [data-target="#' + element.id + '"]') 10344 this.transitioning = null 10345 10346 if (this.options.parent) { 10347 this.$parent = this.getParent() 10348 } else { 10349 this.addAriaAndCollapsedClass(this.$element, this.$trigger) 10350 } 10351 10352 if (this.options.toggle) this.toggle() 10353 } 10354 10355 Collapse.VERSION = '3.3.1' 10356 10357 Collapse.TRANSITION_DURATION = 350 10358 10359 Collapse.DEFAULTS = { 10360 toggle: true, 10361 trigger: '[data-toggle="collapse"]' 10362 } 10363 10364 Collapse.prototype.dimension = function () { 10365 var hasWidth = this.$element.hasClass('width') 10366 return hasWidth ? 'width' : 'height' 10367 } 10368 10369 Collapse.prototype.show = function () { 10370 if (this.transitioning || this.$element.hasClass('in')) return 10371 10372 var activesData 10373 var actives = this.$parent && this.$parent.find('> .panel').children('.in, .collapsing') 10374 10375 if (actives && actives.length) { 10376 activesData = actives.data('bs.collapse') 10377 if (activesData && activesData.transitioning) return 10378 } 10379 10380 var startEvent = $.Event('show.bs.collapse') 10381 this.$element.trigger(startEvent) 10382 if (startEvent.isDefaultPrevented()) return 10383 10384 if (actives && actives.length) { 10385 Plugin.call(actives, 'hide') 10386 activesData || actives.data('bs.collapse', null) 10387 } 10388 10389 var dimension = this.dimension() 10390 10391 this.$element 10392 .removeClass('collapse') 10393 .addClass('collapsing')[dimension](0) 10394 .attr('aria-expanded', true) 10395 10396 this.$trigger 10397 .removeClass('collapsed') 10398 .attr('aria-expanded', true) 10399 10400 this.transitioning = 1 10401 10402 var complete = function () { 10403 this.$element 10404 .removeClass('collapsing') 10405 .addClass('collapse in')[dimension]('') 10406 this.transitioning = 0 10407 this.$element 10408 .trigger('shown.bs.collapse') 10409 } 10410 10411 if (!$.support.transition) return complete.call(this) 10412 10413 var scrollSize = $.camelCase(['scroll', dimension].join('-')) 10414 10415 this.$element 10416 .one('bsTransitionEnd', $.proxy(complete, this)) 10417 .emulateTransitionEnd(Collapse.TRANSITION_DURATION)[dimension](this.$element[0][scrollSize]) 10418 } 10419 10420 Collapse.prototype.hide = function () { 10421 if (this.transitioning || !this.$element.hasClass('in')) return 10422 10423 var startEvent = $.Event('hide.bs.collapse') 10424 this.$element.trigger(startEvent) 10425 if (startEvent.isDefaultPrevented()) return 10426 10427 var dimension = this.dimension() 10428 10429 this.$element[dimension](this.$element[dimension]())[0].offsetHeight 10430 10431 this.$element 10432 .addClass('collapsing') 10433 .removeClass('collapse in') 10434 .attr('aria-expanded', false) 10435 10436 this.$trigger 10437 .addClass('collapsed') 10438 .attr('aria-expanded', false) 10439 10440 this.transitioning = 1 10441 10442 var complete = function () { 10443 this.transitioning = 0 10444 this.$element 10445 .removeClass('collapsing') 10446 .addClass('collapse') 10447 .trigger('hidden.bs.collapse') 10448 } 10449 10450 if (!$.support.transition) return complete.call(this) 10451 10452 this.$element 10453 [dimension](0) 10454 .one('bsTransitionEnd', $.proxy(complete, this)) 10455 .emulateTransitionEnd(Collapse.TRANSITION_DURATION) 10456 } 10457 10458 Collapse.prototype.toggle = function () { 10459 this[this.$element.hasClass('in') ? 'hide' : 'show']() 10460 } 10461 10462 Collapse.prototype.getParent = function () { 10463 return $(this.options.parent) 10464 .find('[data-toggle="collapse"][data-parent="' + this.options.parent + '"]') 10465 .each($.proxy(function (i, element) { 10466 var $element = $(element) 10467 this.addAriaAndCollapsedClass(getTargetFromTrigger($element), $element) 10468 }, this)) 10469 .end() 10470 } 10471 10472 Collapse.prototype.addAriaAndCollapsedClass = function ($element, $trigger) { 10473 var isOpen = $element.hasClass('in') 10474 10475 $element.attr('aria-expanded', isOpen) 10476 $trigger 10477 .toggleClass('collapsed', !isOpen) 10478 .attr('aria-expanded', isOpen) 10479 } 10480 10481 function getTargetFromTrigger($trigger) { 10482 var href 10483 var target = $trigger.attr('data-target') 10484 || (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7 10485 10486 return $(target) 10487 } 10488 10489 10490 // COLLAPSE PLUGIN DEFINITION 10491 // ========================== 10492 10493 function Plugin(option) { 10494 return this.each(function () { 10495 var $this = $(this) 10496 var data = $this.data('bs.collapse') 10497 var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option) 10498 10499 if (!data && options.toggle && option == 'show') options.toggle = false 10500 if (!data) $this.data('bs.collapse', (data = new Collapse(this, options))) 10501 if (typeof option == 'string') data[option]() 10502 }) 10503 } 10504 10505 var old = $.fn.collapse 10506 10507 $.fn.collapse = Plugin 10508 $.fn.collapse.Constructor = Collapse 10509 10510 10511 // COLLAPSE NO CONFLICT 10512 // ==================== 10513 10514 $.fn.collapse.noConflict = function () { 10515 $.fn.collapse = old 10516 return this 10517 } 10518 10519 10520 // COLLAPSE DATA-API 10521 // ================= 10522 10523 $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) { 10524 var $this = $(this) 10525 10526 if (!$this.attr('data-target')) e.preventDefault() 10527 10528 var $target = getTargetFromTrigger($this) 10529 var data = $target.data('bs.collapse') 10530 var option = data ? 'toggle' : $.extend({}, $this.data(), { trigger: this }) 10531 10532 Plugin.call($target, option) 10533 }) 10534 10535}(jQuery); 10536 10537define("bootstrapCollapse", ["jquery","bootstrapTransition"], (function (global) { 10538 return function () { 10539 var ret, fn; 10540 return ret || global.$; 10541 }; 10542}(this))); 10543 10544/* ======================================================================== 10545 * Bootstrap: dropdown.js v3.3.1 10546 * http://getbootstrap.com/javascript/#dropdowns 10547 * ======================================================================== 10548 * Copyright 2011-2014 Twitter, Inc. 10549 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 10550 * ======================================================================== */ 10551 10552 10553+function ($) { 10554 'use strict'; 10555 10556 // DROPDOWN CLASS DEFINITION 10557 // ========================= 10558 10559 var backdrop = '.dropdown-backdrop' 10560 var toggle = '[data-toggle="dropdown"]' 10561 var Dropdown = function (element) { 10562 $(element).on('click.bs.dropdown', this.toggle) 10563 } 10564 10565 Dropdown.VERSION = '3.3.1' 10566 10567 Dropdown.prototype.toggle = function (e) { 10568 var $this = $(this) 10569 10570 if ($this.is('.disabled, :disabled')) return 10571 10572 var $parent = getParent($this) 10573 var isActive = $parent.hasClass('open') 10574 10575 clearMenus() 10576 10577 if (!isActive) { 10578 if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) { 10579 // if mobile we use a backdrop because click events don't delegate 10580 $('<div class="dropdown-backdrop"/>').insertAfter($(this)).on('click', clearMenus) 10581 } 10582 10583 var relatedTarget = { relatedTarget: this } 10584 $parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget)) 10585 10586 if (e.isDefaultPrevented()) return 10587 10588 $this 10589 .trigger('focus') 10590 .attr('aria-expanded', 'true') 10591 10592 $parent 10593 .toggleClass('open') 10594 .trigger('shown.bs.dropdown', relatedTarget) 10595 } 10596 10597 return false 10598 } 10599 10600 Dropdown.prototype.keydown = function (e) { 10601 if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return 10602 10603 var $this = $(this) 10604 10605 e.preventDefault() 10606 e.stopPropagation() 10607 10608 if ($this.is('.disabled, :disabled')) return 10609 10610 var $parent = getParent($this) 10611 var isActive = $parent.hasClass('open') 10612 10613 if ((!isActive && e.which != 27) || (isActive && e.which == 27)) { 10614 if (e.which == 27) $parent.find(toggle).trigger('focus') 10615 return $this.trigger('click') 10616 } 10617 10618 var desc = ' li:not(.divider):visible a' 10619 var $items = $parent.find('[role="menu"]' + desc + ', [role="listbox"]' + desc) 10620 10621 if (!$items.length) return 10622 10623 var index = $items.index(e.target) 10624 10625 if (e.which == 38 && index > 0) index-- // up 10626 if (e.which == 40 && index < $items.length - 1) index++ // down 10627 if (!~index) index = 0 10628 10629 $items.eq(index).trigger('focus') 10630 } 10631 10632 function clearMenus(e) { 10633 if (e && e.which === 3) return 10634 $(backdrop).remove() 10635 $(toggle).each(function () { 10636 var $this = $(this) 10637 var $parent = getParent($this) 10638 var relatedTarget = { relatedTarget: this } 10639 10640 if (!$parent.hasClass('open')) return 10641 10642 $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget)) 10643 10644 if (e.isDefaultPrevented()) return 10645 10646 $this.attr('aria-expanded', 'false') 10647 $parent.removeClass('open').trigger('hidden.bs.dropdown', relatedTarget) 10648 }) 10649 } 10650 10651 function getParent($this) { 10652 var selector = $this.attr('data-target') 10653 10654 if (!selector) { 10655 selector = $this.attr('href') 10656 selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 10657 } 10658 10659 var $parent = selector && $(selector) 10660 10661 return $parent && $parent.length ? $parent : $this.parent() 10662 } 10663 10664 10665 // DROPDOWN PLUGIN DEFINITION 10666 // ========================== 10667 10668 function Plugin(option) { 10669 return this.each(function () { 10670 var $this = $(this) 10671 var data = $this.data('bs.dropdown') 10672 10673 if (!data) $this.data('bs.dropdown', (data = new Dropdown(this))) 10674 if (typeof option == 'string') data[option].call($this) 10675 }) 10676 } 10677 10678 var old = $.fn.dropdown 10679 10680 $.fn.dropdown = Plugin 10681 $.fn.dropdown.Constructor = Dropdown 10682 10683 10684 // DROPDOWN NO CONFLICT 10685 // ==================== 10686 10687 $.fn.dropdown.noConflict = function () { 10688 $.fn.dropdown = old 10689 return this 10690 } 10691 10692 10693 // APPLY TO STANDARD DROPDOWN ELEMENTS 10694 // =================================== 10695 10696 $(document) 10697 .on('click.bs.dropdown.data-api', clearMenus) 10698 .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() }) 10699 .on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle) 10700 .on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown) 10701 .on('keydown.bs.dropdown.data-api', '[role="menu"]', Dropdown.prototype.keydown) 10702 .on('keydown.bs.dropdown.data-api', '[role="listbox"]', Dropdown.prototype.keydown) 10703 10704}(jQuery); 10705 10706define("bootstrapDropdown", ["jquery","bootstrapTransition"], (function (global) { 10707 return function () { 10708 var ret, fn; 10709 return ret || global.$; 10710 }; 10711}(this))); 10712 10713/* ======================================================================== 10714 * Bootstrap: modal.js v3.3.1 10715 * http://getbootstrap.com/javascript/#modals 10716 * ======================================================================== 10717 * Copyright 2011-2014 Twitter, Inc. 10718 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 10719 * ======================================================================== */ 10720 10721 10722+function ($) { 10723 'use strict'; 10724 10725 // MODAL CLASS DEFINITION 10726 // ====================== 10727 10728 var Modal = function (element, options) { 10729 this.options = options 10730 this.$body = $(document.body) 10731 this.$element = $(element) 10732 this.$backdrop = 10733 this.isShown = null 10734 this.scrollbarWidth = 0 10735 10736 if (this.options.remote) { 10737 this.$element 10738 .find('.modal-content') 10739 .load(this.options.remote, $.proxy(function () { 10740 this.$element.trigger('loaded.bs.modal') 10741 }, this)) 10742 } 10743 } 10744 10745 Modal.VERSION = '3.3.1' 10746 10747 Modal.TRANSITION_DURATION = 300 10748 Modal.BACKDROP_TRANSITION_DURATION = 150 10749 10750 Modal.DEFAULTS = { 10751 backdrop: true, 10752 keyboard: true, 10753 show: true 10754 } 10755 10756 Modal.prototype.toggle = function (_relatedTarget) { 10757 return this.isShown ? this.hide() : this.show(_relatedTarget) 10758 } 10759 10760 Modal.prototype.show = function (_relatedTarget) { 10761 var that = this 10762 var e = $.Event('show.bs.modal', { relatedTarget: _relatedTarget }) 10763 10764 this.$element.trigger(e) 10765 10766 if (this.isShown || e.isDefaultPrevented()) return 10767 10768 this.isShown = true 10769 10770 this.checkScrollbar() 10771 this.setScrollbar() 10772 this.$body.addClass('modal-open') 10773 10774 this.escape() 10775 this.resize() 10776 10777 this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this)) 10778 10779 this.backdrop(function () { 10780 var transition = $.support.transition && that.$element.hasClass('fade') 10781 10782 if (!that.$element.parent().length) { 10783 that.$element.appendTo(that.$body) // don't move modals dom position 10784 } 10785 10786 that.$element 10787 .show() 10788 .scrollTop(0) 10789 10790 if (that.options.backdrop) that.adjustBackdrop() 10791 that.adjustDialog() 10792 10793 if (transition) { 10794 that.$element[0].offsetWidth // force reflow 10795 } 10796 10797 that.$element 10798 .addClass('in') 10799 .attr('aria-hidden', false) 10800 10801 that.enforceFocus() 10802 10803 var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget }) 10804 10805 transition ? 10806 that.$element.find('.modal-dialog') // wait for modal to slide in 10807 .one('bsTransitionEnd', function () { 10808 that.$element.trigger('focus').trigger(e) 10809 }) 10810 .emulateTransitionEnd(Modal.TRANSITION_DURATION) : 10811 that.$element.trigger('focus').trigger(e) 10812 }) 10813 } 10814 10815 Modal.prototype.hide = function (e) { 10816 if (e) e.preventDefault() 10817 10818 e = $.Event('hide.bs.modal') 10819 10820 this.$element.trigger(e) 10821 10822 if (!this.isShown || e.isDefaultPrevented()) return 10823 10824 this.isShown = false 10825 10826 this.escape() 10827 this.resize() 10828 10829 $(document).off('focusin.bs.modal') 10830 10831 this.$element 10832 .removeClass('in') 10833 .attr('aria-hidden', true) 10834 .off('click.dismiss.bs.modal') 10835 10836 $.support.transition && this.$element.hasClass('fade') ? 10837 this.$element 10838 .one('bsTransitionEnd', $.proxy(this.hideModal, this)) 10839 .emulateTransitionEnd(Modal.TRANSITION_DURATION) : 10840 this.hideModal() 10841 } 10842 10843 Modal.prototype.enforceFocus = function () { 10844 $(document) 10845 .off('focusin.bs.modal') // guard against infinite focus loop 10846 .on('focusin.bs.modal', $.proxy(function (e) { 10847 if (this.$element[0] !== e.target && !this.$element.has(e.target).length) { 10848 this.$element.trigger('focus') 10849 } 10850 }, this)) 10851 } 10852 10853 Modal.prototype.escape = function () { 10854 if (this.isShown && this.options.keyboard) { 10855 this.$element.on('keydown.dismiss.bs.modal', $.proxy(function (e) { 10856 e.which == 27 && this.hide() 10857 }, this)) 10858 } else if (!this.isShown) { 10859 this.$element.off('keydown.dismiss.bs.modal') 10860 } 10861 } 10862 10863 Modal.prototype.resize = function () { 10864 if (this.isShown) { 10865 $(window).on('resize.bs.modal', $.proxy(this.handleUpdate, this)) 10866 } else { 10867 $(window).off('resize.bs.modal') 10868 } 10869 } 10870 10871 Modal.prototype.hideModal = function () { 10872 var that = this 10873 this.$element.hide() 10874 this.backdrop(function () { 10875 that.$body.removeClass('modal-open') 10876 that.resetAdjustments() 10877 that.resetScrollbar() 10878 that.$element.trigger('hidden.bs.modal') 10879 }) 10880 } 10881 10882 Modal.prototype.removeBackdrop = function () { 10883 this.$backdrop && this.$backdrop.remove() 10884 this.$backdrop = null 10885 } 10886 10887 Modal.prototype.backdrop = function (callback) { 10888 var that = this 10889 var animate = this.$element.hasClass('fade') ? 'fade' : '' 10890 10891 if (this.isShown && this.options.backdrop) { 10892 var doAnimate = $.support.transition && animate 10893 10894 this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />') 10895 .prependTo(this.$element) 10896 .on('click.dismiss.bs.modal', $.proxy(function (e) { 10897 if (e.target !== e.currentTarget) return 10898 this.options.backdrop == 'static' 10899 ? this.$element[0].focus.call(this.$element[0]) 10900 : this.hide.call(this) 10901 }, this)) 10902 10903 if (doAnimate) this.$backdrop[0].offsetWidth // force reflow 10904 10905 this.$backdrop.addClass('in') 10906 10907 if (!callback) return 10908 10909 doAnimate ? 10910 this.$backdrop 10911 .one('bsTransitionEnd', callback) 10912 .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) : 10913 callback() 10914 10915 } else if (!this.isShown && this.$backdrop) { 10916 this.$backdrop.removeClass('in') 10917 10918 var callbackRemove = function () { 10919 that.removeBackdrop() 10920 callback && callback() 10921 } 10922 $.support.transition && this.$element.hasClass('fade') ? 10923 this.$backdrop 10924 .one('bsTransitionEnd', callbackRemove) 10925 .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) : 10926 callbackRemove() 10927 10928 } else if (callback) { 10929 callback() 10930 } 10931 } 10932 10933 // these following methods are used to handle overflowing modals 10934 10935 Modal.prototype.handleUpdate = function () { 10936 if (this.options.backdrop) this.adjustBackdrop() 10937 this.adjustDialog() 10938 } 10939 10940 Modal.prototype.adjustBackdrop = function () { 10941 this.$backdrop 10942 .css('height', 0) 10943 .css('height', this.$element[0].scrollHeight) 10944 } 10945 10946 Modal.prototype.adjustDialog = function () { 10947 var modalIsOverflowing = this.$element[0].scrollHeight > document.documentElement.clientHeight 10948 10949 this.$element.css({ 10950 paddingLeft: !this.bodyIsOverflowing && modalIsOverflowing ? this.scrollbarWidth : '', 10951 paddingRight: this.bodyIsOverflowing && !modalIsOverflowing ? this.scrollbarWidth : '' 10952 }) 10953 } 10954 10955 Modal.prototype.resetAdjustments = function () { 10956 this.$element.css({ 10957 paddingLeft: '', 10958 paddingRight: '' 10959 }) 10960 } 10961 10962 Modal.prototype.checkScrollbar = function () { 10963 this.bodyIsOverflowing = document.body.scrollHeight > document.documentElement.clientHeight 10964 this.scrollbarWidth = this.measureScrollbar() 10965 } 10966 10967 Modal.prototype.setScrollbar = function () { 10968 var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10) 10969 if (this.bodyIsOverflowing) this.$body.css('padding-right', bodyPad + this.scrollbarWidth) 10970 } 10971 10972 Modal.prototype.resetScrollbar = function () { 10973 this.$body.css('padding-right', '') 10974 } 10975 10976 Modal.prototype.measureScrollbar = function () { // thx walsh 10977 var scrollDiv = document.createElement('div') 10978 scrollDiv.className = 'modal-scrollbar-measure' 10979 this.$body.append(scrollDiv) 10980 var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth 10981 this.$body[0].removeChild(scrollDiv) 10982 return scrollbarWidth 10983 } 10984 10985 10986 // MODAL PLUGIN DEFINITION 10987 // ======================= 10988 10989 function Plugin(option, _relatedTarget) { 10990 return this.each(function () { 10991 var $this = $(this) 10992 var data = $this.data('bs.modal') 10993 var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option) 10994 10995 if (!data) $this.data('bs.modal', (data = new Modal(this, options))) 10996 if (typeof option == 'string') data[option](_relatedTarget) 10997 else if (options.show) data.show(_relatedTarget) 10998 }) 10999 } 11000 11001 var old = $.fn.modal 11002 11003 $.fn.modal = Plugin 11004 $.fn.modal.Constructor = Modal 11005 11006 11007 // MODAL NO CONFLICT 11008 // ================= 11009 11010 $.fn.modal.noConflict = function () { 11011 $.fn.modal = old 11012 return this 11013 } 11014 11015 11016 // MODAL DATA-API 11017 // ============== 11018 11019 $(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) { 11020 var $this = $(this) 11021 var href = $this.attr('href') 11022 var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) // strip for ie7 11023 var option = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data()) 11024 11025 if ($this.is('a')) e.preventDefault() 11026 11027 $target.one('show.bs.modal', function (showEvent) { 11028 if (showEvent.isDefaultPrevented()) return // only register focus restorer if modal will actually get shown 11029 $target.one('hidden.bs.modal', function () { 11030 $this.is(':visible') && $this.trigger('focus') 11031 }) 11032 }) 11033 Plugin.call($target, option, this) 11034 }) 11035 11036}(jQuery); 11037 11038define("bootstrapModal", ["jquery","bootstrapTransition"], (function (global) { 11039 return function () { 11040 var ret, fn; 11041 return ret || global.$; 11042 }; 11043}(this))); 11044 11045/* ======================================================================== 11046 * Bootstrap: tooltip.js v3.3.1 11047 * http://getbootstrap.com/javascript/#tooltip 11048 * Inspired by the original jQuery.tipsy by Jason Frame 11049 * ======================================================================== 11050 * Copyright 2011-2014 Twitter, Inc. 11051 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 11052 * ======================================================================== */ 11053 11054 11055+function ($) { 11056 'use strict'; 11057 11058 // TOOLTIP PUBLIC CLASS DEFINITION 11059 // =============================== 11060 11061 var Tooltip = function (element, options) { 11062 this.type = 11063 this.options = 11064 this.enabled = 11065 this.timeout = 11066 this.hoverState = 11067 this.$element = null 11068 11069 this.init('tooltip', element, options) 11070 } 11071 11072 Tooltip.VERSION = '3.3.1' 11073 11074 Tooltip.TRANSITION_DURATION = 150 11075 11076 Tooltip.DEFAULTS = { 11077 animation: true, 11078 placement: 'top', 11079 selector: false, 11080 template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>', 11081 trigger: 'hover focus', 11082 title: '', 11083 delay: 0, 11084 html: false, 11085 container: false, 11086 viewport: { 11087 selector: 'body', 11088 padding: 0 11089 } 11090 } 11091 11092 Tooltip.prototype.init = function (type, element, options) { 11093 this.enabled = true 11094 this.type = type 11095 this.$element = $(element) 11096 this.options = this.getOptions(options) 11097 this.$viewport = this.options.viewport && $(this.options.viewport.selector || this.options.viewport) 11098 11099 var triggers = this.options.trigger.split(' ') 11100 11101 for (var i = triggers.length; i--;) { 11102 var trigger = triggers[i] 11103 11104 if (trigger == 'click') { 11105 this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this)) 11106 } else if (trigger != 'manual') { 11107 var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin' 11108 var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout' 11109 11110 this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this)) 11111 this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this)) 11112 } 11113 } 11114 11115 this.options.selector ? 11116 (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) : 11117 this.fixTitle() 11118 } 11119 11120 Tooltip.prototype.getDefaults = function () { 11121 return Tooltip.DEFAULTS 11122 } 11123 11124 Tooltip.prototype.getOptions = function (options) { 11125 options = $.extend({}, this.getDefaults(), this.$element.data(), options) 11126 11127 if (options.delay && typeof options.delay == 'number') { 11128 options.delay = { 11129 show: options.delay, 11130 hide: options.delay 11131 } 11132 } 11133 11134 return options 11135 } 11136 11137 Tooltip.prototype.getDelegateOptions = function () { 11138 var options = {} 11139 var defaults = this.getDefaults() 11140 11141 this._options && $.each(this._options, function (key, value) { 11142 if (defaults[key] != value) options[key] = value 11143 }) 11144 11145 return options 11146 } 11147 11148 Tooltip.prototype.enter = function (obj) { 11149 var self = obj instanceof this.constructor ? 11150 obj : $(obj.currentTarget).data('bs.' + this.type) 11151 11152 if (self && self.$tip && self.$tip.is(':visible')) { 11153 self.hoverState = 'in' 11154 return 11155 } 11156 11157 if (!self) { 11158 self = new this.constructor(obj.currentTarget, this.getDelegateOptions()) 11159 $(obj.currentTarget).data('bs.' + this.type, self) 11160 } 11161 11162 clearTimeout(self.timeout) 11163 11164 self.hoverState = 'in' 11165 11166 if (!self.options.delay || !self.options.delay.show) return self.show() 11167 11168 self.timeout = setTimeout(function () { 11169 if (self.hoverState == 'in') self.show() 11170 }, self.options.delay.show) 11171 } 11172 11173 Tooltip.prototype.leave = function (obj) { 11174 var self = obj instanceof this.constructor ? 11175 obj : $(obj.currentTarget).data('bs.' + this.type) 11176 11177 if (!self) { 11178 self = new this.constructor(obj.currentTarget, this.getDelegateOptions()) 11179 $(obj.currentTarget).data('bs.' + this.type, self) 11180 } 11181 11182 clearTimeout(self.timeout) 11183 11184 self.hoverState = 'out' 11185 11186 if (!self.options.delay || !self.options.delay.hide) return self.hide() 11187 11188 self.timeout = setTimeout(function () { 11189 if (self.hoverState == 'out') self.hide() 11190 }, self.options.delay.hide) 11191 } 11192 11193 Tooltip.prototype.show = function () { 11194 var e = $.Event('show.bs.' + this.type) 11195 11196 if (this.hasContent() && this.enabled) { 11197 this.$element.trigger(e) 11198 11199 var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0]) 11200 if (e.isDefaultPrevented() || !inDom) return 11201 var that = this 11202 11203 var $tip = this.tip() 11204 11205 var tipId = this.getUID(this.type) 11206 11207 this.setContent() 11208 $tip.attr('id', tipId) 11209 this.$element.attr('aria-describedby', tipId) 11210 11211 if (this.options.animation) $tip.addClass('fade') 11212 11213 var placement = typeof this.options.placement == 'function' ? 11214 this.options.placement.call(this, $tip[0], this.$element[0]) : 11215 this.options.placement 11216 11217 var autoToken = /\s?auto?\s?/i 11218 var autoPlace = autoToken.test(placement) 11219 if (autoPlace) placement = placement.replace(autoToken, '') || 'top' 11220 11221 $tip 11222 .detach() 11223 .css({ top: 0, left: 0, display: 'block' }) 11224 .addClass(placement) 11225 .data('bs.' + this.type, this) 11226 11227 this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element) 11228 11229 var pos = this.getPosition() 11230 var actualWidth = $tip[0].offsetWidth 11231 var actualHeight = $tip[0].offsetHeight 11232 11233 if (autoPlace) { 11234 var orgPlacement = placement 11235 var $container = this.options.container ? $(this.options.container) : this.$element.parent() 11236 var containerDim = this.getPosition($container) 11237 11238 placement = placement == 'bottom' && pos.bottom + actualHeight > containerDim.bottom ? 'top' : 11239 placement == 'top' && pos.top - actualHeight < containerDim.top ? 'bottom' : 11240 placement == 'right' && pos.right + actualWidth > containerDim.width ? 'left' : 11241 placement == 'left' && pos.left - actualWidth < containerDim.left ? 'right' : 11242 placement 11243 11244 $tip 11245 .removeClass(orgPlacement) 11246 .addClass(placement) 11247 } 11248 11249 var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight) 11250 11251 this.applyPlacement(calculatedOffset, placement) 11252 11253 var complete = function () { 11254 var prevHoverState = that.hoverState 11255 that.$element.trigger('shown.bs.' + that.type) 11256 that.hoverState = null 11257 11258 if (prevHoverState == 'out') that.leave(that) 11259 } 11260 11261 $.support.transition && this.$tip.hasClass('fade') ? 11262 $tip 11263 .one('bsTransitionEnd', complete) 11264 .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) : 11265 complete() 11266 } 11267 } 11268 11269 Tooltip.prototype.applyPlacement = function (offset, placement) { 11270 var $tip = this.tip() 11271 var width = $tip[0].offsetWidth 11272 var height = $tip[0].offsetHeight 11273 11274 // manually read margins because getBoundingClientRect includes difference 11275 var marginTop = parseInt($tip.css('margin-top'), 10) 11276 var marginLeft = parseInt($tip.css('margin-left'), 10) 11277 11278 // we must check for NaN for ie 8/9 11279 if (isNaN(marginTop)) marginTop = 0 11280 if (isNaN(marginLeft)) marginLeft = 0 11281 11282 offset.top = offset.top + marginTop 11283 offset.left = offset.left + marginLeft 11284 11285 // $.fn.offset doesn't round pixel values 11286 // so we use setOffset directly with our own function B-0 11287 $.offset.setOffset($tip[0], $.extend({ 11288 using: function (props) { 11289 $tip.css({ 11290 top: Math.round(props.top), 11291 left: Math.round(props.left) 11292 }) 11293 } 11294 }, offset), 0) 11295 11296 $tip.addClass('in') 11297 11298 // check to see if placing tip in new offset caused the tip to resize itself 11299 var actualWidth = $tip[0].offsetWidth 11300 var actualHeight = $tip[0].offsetHeight 11301 11302 if (placement == 'top' && actualHeight != height) { 11303 offset.top = offset.top + height - actualHeight 11304 } 11305 11306 var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight) 11307 11308 if (delta.left) offset.left += delta.left 11309 else offset.top += delta.top 11310 11311 var isVertical = /top|bottom/.test(placement) 11312 var arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight 11313 var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight' 11314 11315 $tip.offset(offset) 11316 this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical) 11317 } 11318 11319 Tooltip.prototype.replaceArrow = function (delta, dimension, isHorizontal) { 11320 this.arrow() 11321 .css(isHorizontal ? 'left' : 'top', 50 * (1 - delta / dimension) + '%') 11322 .css(isHorizontal ? 'top' : 'left', '') 11323 } 11324 11325 Tooltip.prototype.setContent = function () { 11326 var $tip = this.tip() 11327 var title = this.getTitle() 11328 11329 $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title) 11330 $tip.removeClass('fade in top bottom left right') 11331 } 11332 11333 Tooltip.prototype.hide = function (callback) { 11334 var that = this 11335 var $tip = this.tip() 11336 var e = $.Event('hide.bs.' + this.type) 11337 11338 function complete() { 11339 if (that.hoverState != 'in') $tip.detach() 11340 that.$element 11341 .removeAttr('aria-describedby') 11342 .trigger('hidden.bs.' + that.type) 11343 callback && callback() 11344 } 11345 11346 this.$element.trigger(e) 11347 11348 if (e.isDefaultPrevented()) return 11349 11350 $tip.removeClass('in') 11351 11352 $.support.transition && this.$tip.hasClass('fade') ? 11353 $tip 11354 .one('bsTransitionEnd', complete) 11355 .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) : 11356 complete() 11357 11358 this.hoverState = null 11359 11360 return this 11361 } 11362 11363 Tooltip.prototype.fixTitle = function () { 11364 var $e = this.$element 11365 if ($e.attr('title') || typeof ($e.attr('data-original-title')) != 'string') { 11366 $e.attr('data-original-title', $e.attr('title') || '').attr('title', '') 11367 } 11368 } 11369 11370 Tooltip.prototype.hasContent = function () { 11371 return this.getTitle() 11372 } 11373 11374 Tooltip.prototype.getPosition = function ($element) { 11375 $element = $element || this.$element 11376 11377 var el = $element[0] 11378 var isBody = el.tagName == 'BODY' 11379 11380 var elRect = el.getBoundingClientRect() 11381 if (elRect.width == null) { 11382 // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093 11383 elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top }) 11384 } 11385 var elOffset = isBody ? { top: 0, left: 0 } : $element.offset() 11386 var scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() } 11387 var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null 11388 11389 return $.extend({}, elRect, scroll, outerDims, elOffset) 11390 } 11391 11392 Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) { 11393 return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } : 11394 placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } : 11395 placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } : 11396 /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width } 11397 11398 } 11399 11400 Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) { 11401 var delta = { top: 0, left: 0 } 11402 if (!this.$viewport) return delta 11403 11404 var viewportPadding = this.options.viewport && this.options.viewport.padding || 0 11405 var viewportDimensions = this.getPosition(this.$viewport) 11406 11407 if (/right|left/.test(placement)) { 11408 var topEdgeOffset = pos.top - viewportPadding - viewportDimensions.scroll 11409 var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight 11410 if (topEdgeOffset < viewportDimensions.top) { // top overflow 11411 delta.top = viewportDimensions.top - topEdgeOffset 11412 } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow 11413 delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset 11414 } 11415 } else { 11416 var leftEdgeOffset = pos.left - viewportPadding 11417 var rightEdgeOffset = pos.left + viewportPadding + actualWidth 11418 if (leftEdgeOffset < viewportDimensions.left) { // left overflow 11419 delta.left = viewportDimensions.left - leftEdgeOffset 11420 } else if (rightEdgeOffset > viewportDimensions.width) { // right overflow 11421 delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset 11422 } 11423 } 11424 11425 return delta 11426 } 11427 11428 Tooltip.prototype.getTitle = function () { 11429 var title 11430 var $e = this.$element 11431 var o = this.options 11432 11433 title = $e.attr('data-original-title') 11434 || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title) 11435 11436 return title 11437 } 11438 11439 Tooltip.prototype.getUID = function (prefix) { 11440 do prefix += ~~(Math.random() * 1000000) 11441 while (document.getElementById(prefix)) 11442 return prefix 11443 } 11444 11445 Tooltip.prototype.tip = function () { 11446 return (this.$tip = this.$tip || $(this.options.template)) 11447 } 11448 11449 Tooltip.prototype.arrow = function () { 11450 return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow')) 11451 } 11452 11453 Tooltip.prototype.enable = function () { 11454 this.enabled = true 11455 } 11456 11457 Tooltip.prototype.disable = function () { 11458 this.enabled = false 11459 } 11460 11461 Tooltip.prototype.toggleEnabled = function () { 11462 this.enabled = !this.enabled 11463 } 11464 11465 Tooltip.prototype.toggle = function (e) { 11466 var self = this 11467 if (e) { 11468 self = $(e.currentTarget).data('bs.' + this.type) 11469 if (!self) { 11470 self = new this.constructor(e.currentTarget, this.getDelegateOptions()) 11471 $(e.currentTarget).data('bs.' + this.type, self) 11472 } 11473 } 11474 11475 self.tip().hasClass('in') ? self.leave(self) : self.enter(self) 11476 } 11477 11478 Tooltip.prototype.destroy = function () { 11479 var that = this 11480 clearTimeout(this.timeout) 11481 this.hide(function () { 11482 that.$element.off('.' + that.type).removeData('bs.' + that.type) 11483 }) 11484 } 11485 11486 11487 // TOOLTIP PLUGIN DEFINITION 11488 // ========================= 11489 11490 function Plugin(option) { 11491 return this.each(function () { 11492 var $this = $(this) 11493 var data = $this.data('bs.tooltip') 11494 var options = typeof option == 'object' && option 11495 var selector = options && options.selector 11496 11497 if (!data && option == 'destroy') return 11498 if (selector) { 11499 if (!data) $this.data('bs.tooltip', (data = {})) 11500 if (!data[selector]) data[selector] = new Tooltip(this, options) 11501 } else { 11502 if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options))) 11503 } 11504 if (typeof option == 'string') data[option]() 11505 }) 11506 } 11507 11508 var old = $.fn.tooltip 11509 11510 $.fn.tooltip = Plugin 11511 $.fn.tooltip.Constructor = Tooltip 11512 11513 11514 // TOOLTIP NO CONFLICT 11515 // =================== 11516 11517 $.fn.tooltip.noConflict = function () { 11518 $.fn.tooltip = old 11519 return this 11520 } 11521 11522}(jQuery); 11523 11524define("bootstrapTooltip", ["jquery","bootstrapTransition"], (function (global) { 11525 return function () { 11526 var ret, fn; 11527 return ret || global.$; 11528 }; 11529}(this))); 11530 11531/* ======================================================================== 11532 * Bootstrap: popover.js v3.3.1 11533 * http://getbootstrap.com/javascript/#popovers 11534 * ======================================================================== 11535 * Copyright 2011-2014 Twitter, Inc. 11536 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 11537 * ======================================================================== */ 11538 11539 11540+function ($) { 11541 'use strict'; 11542 11543 // POPOVER PUBLIC CLASS DEFINITION 11544 // =============================== 11545 11546 var Popover = function (element, options) { 11547 this.init('popover', element, options) 11548 } 11549 11550 if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js') 11551 11552 Popover.VERSION = '3.3.1' 11553 11554 Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, { 11555 placement: 'right', 11556 trigger: 'click', 11557 content: '', 11558 template: '<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>' 11559 }) 11560 11561 11562 // NOTE: POPOVER EXTENDS tooltip.js 11563 // ================================ 11564 11565 Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype) 11566 11567 Popover.prototype.constructor = Popover 11568 11569 Popover.prototype.getDefaults = function () { 11570 return Popover.DEFAULTS 11571 } 11572 11573 Popover.prototype.setContent = function () { 11574 var $tip = this.tip() 11575 var title = this.getTitle() 11576 var content = this.getContent() 11577 11578 $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title) 11579 $tip.find('.popover-content').children().detach().end()[ // we use append for html objects to maintain js events 11580 this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text' 11581 ](content) 11582 11583 $tip.removeClass('fade top bottom left right in') 11584 11585 // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do 11586 // this manually by checking the contents. 11587 if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide() 11588 } 11589 11590 Popover.prototype.hasContent = function () { 11591 return this.getTitle() || this.getContent() 11592 } 11593 11594 Popover.prototype.getContent = function () { 11595 var $e = this.$element 11596 var o = this.options 11597 11598 return $e.attr('data-content') 11599 || (typeof o.content == 'function' ? 11600 o.content.call($e[0]) : 11601 o.content) 11602 } 11603 11604 Popover.prototype.arrow = function () { 11605 return (this.$arrow = this.$arrow || this.tip().find('.arrow')) 11606 } 11607 11608 Popover.prototype.tip = function () { 11609 if (!this.$tip) this.$tip = $(this.options.template) 11610 return this.$tip 11611 } 11612 11613 11614 // POPOVER PLUGIN DEFINITION 11615 // ========================= 11616 11617 function Plugin(option) { 11618 return this.each(function () { 11619 var $this = $(this) 11620 var data = $this.data('bs.popover') 11621 var options = typeof option == 'object' && option 11622 var selector = options && options.selector 11623 11624 if (!data && option == 'destroy') return 11625 if (selector) { 11626 if (!data) $this.data('bs.popover', (data = {})) 11627 if (!data[selector]) data[selector] = new Popover(this, options) 11628 } else { 11629 if (!data) $this.data('bs.popover', (data = new Popover(this, options))) 11630 } 11631 if (typeof option == 'string') data[option]() 11632 }) 11633 } 11634 11635 var old = $.fn.popover 11636 11637 $.fn.popover = Plugin 11638 $.fn.popover.Constructor = Popover 11639 11640 11641 // POPOVER NO CONFLICT 11642 // =================== 11643 11644 $.fn.popover.noConflict = function () { 11645 $.fn.popover = old 11646 return this 11647 } 11648 11649}(jQuery); 11650 11651define("bootstrapPopover", ["jquery","bootstrapTooltip","bootstrapTransition"], (function (global) { 11652 return function () { 11653 var ret, fn; 11654 return ret || global.$; 11655 }; 11656}(this))); 11657 11658/* ======================================================================== 11659 * Bootstrap: scrollspy.js v3.3.1 11660 * http://getbootstrap.com/javascript/#scrollspy 11661 * ======================================================================== 11662 * Copyright 2011-2014 Twitter, Inc. 11663 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 11664 * ======================================================================== */ 11665 11666 11667+function ($) { 11668 'use strict'; 11669 11670 // SCROLLSPY CLASS DEFINITION 11671 // ========================== 11672 11673 function ScrollSpy(element, options) { 11674 var process = $.proxy(this.process, this) 11675 11676 this.$body = $('body') 11677 this.$scrollElement = $(element).is('body') ? $(window) : $(element) 11678 this.options = $.extend({}, ScrollSpy.DEFAULTS, options) 11679 this.selector = (this.options.target || '') + ' .nav li > a' 11680 this.offsets = [] 11681 this.targets = [] 11682 this.activeTarget = null 11683 this.scrollHeight = 0 11684 11685 this.$scrollElement.on('scroll.bs.scrollspy', process) 11686 this.refresh() 11687 this.process() 11688 } 11689 11690 ScrollSpy.VERSION = '3.3.1' 11691 11692 ScrollSpy.DEFAULTS = { 11693 offset: 10 11694 } 11695 11696 ScrollSpy.prototype.getScrollHeight = function () { 11697 return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight) 11698 } 11699 11700 ScrollSpy.prototype.refresh = function () { 11701 var offsetMethod = 'offset' 11702 var offsetBase = 0 11703 11704 if (!$.isWindow(this.$scrollElement[0])) { 11705 offsetMethod = 'position' 11706 offsetBase = this.$scrollElement.scrollTop() 11707 } 11708 11709 this.offsets = [] 11710 this.targets = [] 11711 this.scrollHeight = this.getScrollHeight() 11712 11713 var self = this 11714 11715 this.$body 11716 .find(this.selector) 11717 .map(function () { 11718 var $el = $(this) 11719 var href = $el.data('target') || $el.attr('href') 11720 var $href = /^#./.test(href) && $(href) 11721 11722 return ($href 11723 && $href.length 11724 && $href.is(':visible') 11725 && [[$href[offsetMethod]().top + offsetBase, href]]) || null 11726 }) 11727 .sort(function (a, b) { return a[0] - b[0] }) 11728 .each(function () { 11729 self.offsets.push(this[0]) 11730 self.targets.push(this[1]) 11731 }) 11732 } 11733 11734 ScrollSpy.prototype.process = function () { 11735 var scrollTop = this.$scrollElement.scrollTop() + this.options.offset 11736 var scrollHeight = this.getScrollHeight() 11737 var maxScroll = this.options.offset + scrollHeight - this.$scrollElement.height() 11738 var offsets = this.offsets 11739 var targets = this.targets 11740 var activeTarget = this.activeTarget 11741 var i 11742 11743 if (this.scrollHeight != scrollHeight) { 11744 this.refresh() 11745 } 11746 11747 if (scrollTop >= maxScroll) { 11748 return activeTarget != (i = targets[targets.length - 1]) && this.activate(i) 11749 } 11750 11751 if (activeTarget && scrollTop < offsets[0]) { 11752 this.activeTarget = null 11753 return this.clear() 11754 } 11755 11756 for (i = offsets.length; i--;) { 11757 activeTarget != targets[i] 11758 && scrollTop >= offsets[i] 11759 && (!offsets[i + 1] || scrollTop <= offsets[i + 1]) 11760 && this.activate(targets[i]) 11761 } 11762 } 11763 11764 ScrollSpy.prototype.activate = function (target) { 11765 this.activeTarget = target 11766 11767 this.clear() 11768 11769 var selector = this.selector + 11770 '[data-target="' + target + '"],' + 11771 this.selector + '[href="' + target + '"]' 11772 11773 var active = $(selector) 11774 .parents('li') 11775 .addClass('active') 11776 11777 if (active.parent('.dropdown-menu').length) { 11778 active = active 11779 .closest('li.dropdown') 11780 .addClass('active') 11781 } 11782 11783 active.trigger('activate.bs.scrollspy') 11784 } 11785 11786 ScrollSpy.prototype.clear = function () { 11787 $(this.selector) 11788 .parentsUntil(this.options.target, '.active') 11789 .removeClass('active') 11790 } 11791 11792 11793 // SCROLLSPY PLUGIN DEFINITION 11794 // =========================== 11795 11796 function Plugin(option) { 11797 return this.each(function () { 11798 var $this = $(this) 11799 var data = $this.data('bs.scrollspy') 11800 var options = typeof option == 'object' && option 11801 11802 if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options))) 11803 if (typeof option == 'string') data[option]() 11804 }) 11805 } 11806 11807 var old = $.fn.scrollspy 11808 11809 $.fn.scrollspy = Plugin 11810 $.fn.scrollspy.Constructor = ScrollSpy 11811 11812 11813 // SCROLLSPY NO CONFLICT 11814 // ===================== 11815 11816 $.fn.scrollspy.noConflict = function () { 11817 $.fn.scrollspy = old 11818 return this 11819 } 11820 11821 11822 // SCROLLSPY DATA-API 11823 // ================== 11824 11825 $(window).on('load.bs.scrollspy.data-api', function () { 11826 $('[data-spy="scroll"]').each(function () { 11827 var $spy = $(this) 11828 Plugin.call($spy, $spy.data()) 11829 }) 11830 }) 11831 11832}(jQuery); 11833 11834define("bootstrapScrollspy", ["jquery","bootstrapTransition"], (function (global) { 11835 return function () { 11836 var ret, fn; 11837 return ret || global.$; 11838 }; 11839}(this))); 11840 11841/* ======================================================================== 11842 * Bootstrap: tab.js v3.3.1 11843 * http://getbootstrap.com/javascript/#tabs 11844 * ======================================================================== 11845 * Copyright 2011-2014 Twitter, Inc. 11846 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 11847 * ======================================================================== */ 11848 11849 11850+function ($) { 11851 'use strict'; 11852 11853 // TAB CLASS DEFINITION 11854 // ==================== 11855 11856 var Tab = function (element) { 11857 this.element = $(element) 11858 } 11859 11860 Tab.VERSION = '3.3.1' 11861 11862 Tab.TRANSITION_DURATION = 150 11863 11864 Tab.prototype.show = function () { 11865 var $this = this.element 11866 var $ul = $this.closest('ul:not(.dropdown-menu)') 11867 var selector = $this.data('target') 11868 11869 if (!selector) { 11870 selector = $this.attr('href') 11871 selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 11872 } 11873 11874 if ($this.parent('li').hasClass('active')) return 11875 11876 var $previous = $ul.find('.active:last a') 11877 var hideEvent = $.Event('hide.bs.tab', { 11878 relatedTarget: $this[0] 11879 }) 11880 var showEvent = $.Event('show.bs.tab', { 11881 relatedTarget: $previous[0] 11882 }) 11883 11884 $previous.trigger(hideEvent) 11885 $this.trigger(showEvent) 11886 11887 if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return 11888 11889 var $target = $(selector) 11890 11891 this.activate($this.closest('li'), $ul) 11892 this.activate($target, $target.parent(), function () { 11893 $previous.trigger({ 11894 type: 'hidden.bs.tab', 11895 relatedTarget: $this[0] 11896 }) 11897 $this.trigger({ 11898 type: 'shown.bs.tab', 11899 relatedTarget: $previous[0] 11900 }) 11901 }) 11902 } 11903 11904 Tab.prototype.activate = function (element, container, callback) { 11905 var $active = container.find('> .active') 11906 var transition = callback 11907 && $.support.transition 11908 && (($active.length && $active.hasClass('fade')) || !!container.find('> .fade').length) 11909 11910 function next() { 11911 $active 11912 .removeClass('active') 11913 .find('> .dropdown-menu > .active') 11914 .removeClass('active') 11915 .end() 11916 .find('[data-toggle="tab"]') 11917 .attr('aria-expanded', false) 11918 11919 element 11920 .addClass('active') 11921 .find('[data-toggle="tab"]') 11922 .attr('aria-expanded', true) 11923 11924 if (transition) { 11925 element[0].offsetWidth // reflow for transition 11926 element.addClass('in') 11927 } else { 11928 element.removeClass('fade') 11929 } 11930 11931 if (element.parent('.dropdown-menu')) { 11932 element 11933 .closest('li.dropdown') 11934 .addClass('active') 11935 .end() 11936 .find('[data-toggle="tab"]') 11937 .attr('aria-expanded', true) 11938 } 11939 11940 callback && callback() 11941 } 11942 11943 $active.length && transition ? 11944 $active 11945 .one('bsTransitionEnd', next) 11946 .emulateTransitionEnd(Tab.TRANSITION_DURATION) : 11947 next() 11948 11949 $active.removeClass('in') 11950 } 11951 11952 11953 // TAB PLUGIN DEFINITION 11954 // ===================== 11955 11956 function Plugin(option) { 11957 return this.each(function () { 11958 var $this = $(this) 11959 var data = $this.data('bs.tab') 11960 11961 if (!data) $this.data('bs.tab', (data = new Tab(this))) 11962 if (typeof option == 'string') data[option]() 11963 }) 11964 } 11965 11966 var old = $.fn.tab 11967 11968 $.fn.tab = Plugin 11969 $.fn.tab.Constructor = Tab 11970 11971 11972 // TAB NO CONFLICT 11973 // =============== 11974 11975 $.fn.tab.noConflict = function () { 11976 $.fn.tab = old 11977 return this 11978 } 11979 11980 11981 // TAB DATA-API 11982 // ============ 11983 11984 var clickHandler = function (e) { 11985 e.preventDefault() 11986 Plugin.call($(this), 'show') 11987 } 11988 11989 $(document) 11990 .on('click.bs.tab.data-api', '[data-toggle="tab"]', clickHandler) 11991 .on('click.bs.tab.data-api', '[data-toggle="pill"]', clickHandler) 11992 11993}(jQuery); 11994 11995define("bootstrapTab", ["jquery","bootstrapTransition"], (function (global) { 11996 return function () { 11997 var ret, fn; 11998 return ret || global.$; 11999 }; 12000}(this))); 12001 12002/* ======================================================================== 12003 * Bootstrap: affix.js v3.3.1 12004 * http://getbootstrap.com/javascript/#affix 12005 * ======================================================================== 12006 * Copyright 2011-2014 Twitter, Inc. 12007 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 12008 * ======================================================================== */ 12009 12010 12011+function ($) { 12012 'use strict'; 12013 12014 // AFFIX CLASS DEFINITION 12015 // ====================== 12016 12017 var Affix = function (element, options) { 12018 this.options = $.extend({}, Affix.DEFAULTS, options) 12019 12020 this.$target = $(this.options.target) 12021 .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this)) 12022 .on('click.bs.affix.data-api', $.proxy(this.checkPositionWithEventLoop, this)) 12023 12024 this.$element = $(element) 12025 this.affixed = 12026 this.unpin = 12027 this.pinnedOffset = null 12028 12029 this.checkPosition() 12030 } 12031 12032 Affix.VERSION = '3.3.1' 12033 12034 Affix.RESET = 'affix affix-top affix-bottom' 12035 12036 Affix.DEFAULTS = { 12037 offset: 0, 12038 target: window 12039 } 12040 12041 Affix.prototype.getState = function (scrollHeight, height, offsetTop, offsetBottom) { 12042 var scrollTop = this.$target.scrollTop() 12043 var position = this.$element.offset() 12044 var targetHeight = this.$target.height() 12045 12046 if (offsetTop != null && this.affixed == 'top') return scrollTop < offsetTop ? 'top' : false 12047 12048 if (this.affixed == 'bottom') { 12049 if (offsetTop != null) return (scrollTop + this.unpin <= position.top) ? false : 'bottom' 12050 return (scrollTop + targetHeight <= scrollHeight - offsetBottom) ? false : 'bottom' 12051 } 12052 12053 var initializing = this.affixed == null 12054 var colliderTop = initializing ? scrollTop : position.top 12055 var colliderHeight = initializing ? targetHeight : height 12056 12057 if (offsetTop != null && colliderTop <= offsetTop) return 'top' 12058 if (offsetBottom != null && (colliderTop + colliderHeight >= scrollHeight - offsetBottom)) return 'bottom' 12059 12060 return false 12061 } 12062 12063 Affix.prototype.getPinnedOffset = function () { 12064 if (this.pinnedOffset) return this.pinnedOffset 12065 this.$element.removeClass(Affix.RESET).addClass('affix') 12066 var scrollTop = this.$target.scrollTop() 12067 var position = this.$element.offset() 12068 return (this.pinnedOffset = position.top - scrollTop) 12069 } 12070 12071 Affix.prototype.checkPositionWithEventLoop = function () { 12072 setTimeout($.proxy(this.checkPosition, this), 1) 12073 } 12074 12075 Affix.prototype.checkPosition = function () { 12076 if (!this.$element.is(':visible')) return 12077 12078 var height = this.$element.height() 12079 var offset = this.options.offset 12080 var offsetTop = offset.top 12081 var offsetBottom = offset.bottom 12082 var scrollHeight = $('body').height() 12083 12084 if (typeof offset != 'object') offsetBottom = offsetTop = offset 12085 if (typeof offsetTop == 'function') offsetTop = offset.top(this.$element) 12086 if (typeof offsetBottom == 'function') offsetBottom = offset.bottom(this.$element) 12087
vendor: 2,644 bytes, lines 12088-12198
12088 var affix = this.getState(scrollHeight, height, offsetTop, offsetBottom) 12089 12090 if (this.affixed != affix) { 12091 if (this.unpin != null) this.$element.css('top', '') 12092 12093 var affixType = 'affix' + (affix ? '-' + affix : '') 12094 var e = $.Event(affixType + '.bs.affix') 12095 12096 this.$element.trigger(e) 12097 12098 if (e.isDefaultPrevented()) return 12099 12100 this.affixed = affix 12101 this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null 12102 12103 this.$element 12104 .removeClass(Affix.RESET) 12105 .addClass(affixType) 12106 .trigger(affixType.replace('affix', 'affixed') + '.bs.affix') 12107 } 12108 12109 if (affix == 'bottom') { 12110 this.$element.offset({ 12111 top: scrollHeight - height - offsetBottom 12112 }) 12113 } 12114 } 12115 12116 12117 // AFFIX PLUGIN DEFINITION 12118 // ======================= 12119 12120 function Plugin(option) { 12121 return this.each(function () { 12122 var $this = $(this) 12123 var data = $this.data('bs.affix') 12124 var options = typeof option == 'object' && option 12125 12126 if (!data) $this.data('bs.affix', (data = new Affix(this, options))) 12127 if (typeof option == 'string') data[option]() 12128 }) 12129 } 12130 12131 var old = $.fn.affix 12132 12133 $.fn.affix = Plugin 12134 $.fn.affix.Constructor = Affix 12135 12136 12137 // AFFIX NO CONFLICT 12138 // ================= 12139 12140 $.fn.affix.noConflict = function () { 12141 $.fn.affix = old 12142 return this 12143 } 12144 12145 12146 // AFFIX DATA-API 12147 // ============== 12148 12149 $(window).on('load', function () { 12150 $('[data-spy="affix"]').each(function () { 12151 var $spy = $(this) 12152 var data = $spy.data() 12153 12154 data.offset = data.offset || {} 12155 12156 if (data.offsetBottom != null) data.offset.bottom = data.offsetBottom 12157 if (data.offsetTop != null) data.offset.top = data.offsetTop 12158 12159 Plugin.call($spy, data) 12160 }) 12161 }) 12162 12163}(jQuery); 12164 12165define("bootstrapAffix", ["jquery","bootstrapTransition"], (function (global) { 12166 return function () { 12167 var ret, fn; 12168 return ret || global.$; 12169 }; 12170}(this))); 12171 12172define('bootstrap',[ 12173 "jquery", 12174 "bootstrapAlert", 12175 "bootstrapButton", 12176 "bootstrapCarousel", 12177 "bootstrapCollapse", 12178 "bootstrapDropdown", 12179 "bootstrapModal", 12180 "bootstrapPopover", 12181 "bootstrapScrollspy", 12182 "bootstrapTab", 12183 "bootstrapTooltip", 12184 "bootstrapTransition", 12185 "bootstrapAffix" 12186], function () { 12187 12188}); 12189 12190//! moment.js 12191//! version : 2.31.0 12192//! authors : Tim Wood, Iskren Chernev, Moment.js contributors 12193//! license : MIT 12194//! momentjs.com 12195 12196;(function (global, factory) { 12197 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : 12198 typeof define === 'function' && define.amd ? define('moment',
vendor: 183,142 bytes, lines 12198-18106
12198factory) : 12199 global.moment = factory() 12200}(this, (function () { 'use strict'; 12201 12202 var hookCallback; 12203 12204 function hooks() { 12205 return hookCallback.apply(null, arguments); 12206 } 12207 12208 // This is done to register the method called with moment() 12209 // without creating circular dependencies. 12210 function setHookCallback(callback) { 12211 hookCallback = callback; 12212 } 12213 12214 function isArray(input) { 12215 return ( 12216 input instanceof Array || 12217 Object.prototype.toString.call(input) === '[object Array]' 12218 ); 12219 } 12220 12221 function isObject(input) { 12222 // IE8 will treat undefined and null as object if it wasn't for 12223 // input != null 12224 return ( 12225 input != null && 12226 Object.prototype.toString.call(input) === '[object Object]' 12227 ); 12228 } 12229 12230 function hasOwnProp(a, b) { 12231 return Object.prototype.hasOwnProperty.call(a, b); 12232 } 12233 12234 function isObjectEmpty(obj) { 12235 if (Object.getOwnPropertyNames) { 12236 return Object.getOwnPropertyNames(obj).length === 0; 12237 } else { 12238 var k; 12239 for (k in obj) { 12240 if (hasOwnProp(obj, k)) { 12241 return false; 12242 } 12243 } 12244 return true; 12245 } 12246 } 12247 12248 function isUndefined(input) { 12249 return input === void 0; 12250 } 12251 12252 function isNumber(input) { 12253 return ( 12254 typeof input === 'number' || 12255 Object.prototype.toString.call(input) === '[object Number]' 12256 ); 12257 } 12258 12259 function isDate(input) { 12260 return ( 12261 input instanceof Date || 12262 Object.prototype.toString.call(input) === '[object Date]' 12263 ); 12264 } 12265 12266 function map(arr, fn) { 12267 var res = [], 12268 i, 12269 arrLen = arr.length; 12270 for (i = 0; i < arrLen; ++i) { 12271 res.push(fn(arr[i], i)); 12272 } 12273 return res; 12274 } 12275 12276 function extend(a, b) { 12277 for (var i in b) { 12278 if (hasOwnProp(b, i)) { 12279 a[i] = b[i]; 12280 } 12281 } 12282 12283 if (hasOwnProp(b, 'toString')) { 12284 a.toString = b.toString; 12285 } 12286 12287 if (hasOwnProp(b, 'valueOf')) { 12288 a.valueOf = b.valueOf; 12289 } 12290 12291 return a; 12292 } 12293 12294 function createUTC(input, format, locale, strict) { 12295 return createLocalOrUTC(input, format, locale, strict, true).utc(); 12296 } 12297 12298 function defaultParsingFlags() { 12299 // We need to deep clone this object. 12300 return { 12301 empty: false, 12302 unusedTokens: [], 12303 unusedInput: [], 12304 overflow: -2, 12305 charsLeftOver: 0, 12306 nullInput: false, 12307 invalidEra: null, 12308 invalidMonth: null, 12309 invalidOffset: null, 12310 invalidFormat: false, 12311 userInvalidated: false, 12312 iso: false, 12313 parsedDateParts: [], 12314 era: null, 12315 meridiem: null, 12316 rfc2822: false, 12317 weekdayMismatch: false, 12318 }; 12319 } 12320 12321 function getParsingFlags(m) { 12322 if (m._pf == null) { 12323 m._pf = defaultParsingFlags(); 12324 } 12325 return m._pf; 12326 } 12327 12328 var some; 12329 if (Array.prototype.some) { 12330 some = Array.prototype.some; 12331 } else { 12332 some = function (fun) { 12333 var t = Object(this), 12334 len = t.length >>> 0, 12335 i; 12336 12337 for (i = 0; i < len; i++) { 12338 if (i in t && fun.call(this, t[i], i, t)) { 12339 return true; 12340 } 12341 } 12342 12343 return false; 12344 }; 12345 } 12346 12347 function isValid$2(m) { 12348 var flags = null, 12349 parsedParts = false, 12350 isNowValid = m._d && !isNaN(m._d.getTime()); 12351 if (isNowValid) { 12352 flags = getParsingFlags(m); 12353 parsedParts = some.call(flags.parsedDateParts, function (i) { 12354 return i != null; 12355 }); 12356 isNowValid = 12357 flags.overflow < 0 && 12358 !flags.empty && 12359 !flags.invalidEra && 12360 !flags.invalidMonth && 12361 !flags.invalidOffset && 12362 !flags.invalidWeekday && 12363 !flags.weekdayMismatch && 12364 !flags.nullInput && 12365 !flags.invalidFormat && 12366 !flags.userInvalidated && 12367 (!flags.meridiem || (flags.meridiem && parsedParts)); 12368 if (m._strict) { 12369 isNowValid = 12370 isNowValid && 12371 flags.charsLeftOver === 0 && 12372 flags.unusedTokens.length === 0 && 12373 flags.bigHour === undefined; 12374 } 12375 } 12376 if (Object.isFrozen == null || !Object.isFrozen(m)) { 12377 m._isValid = isNowValid; 12378 } else { 12379 return isNowValid; 12380 } 12381 return m._isValid; 12382 } 12383 12384 function createInvalid$1(flags) { 12385 var m = createUTC(NaN); 12386 if (flags != null) { 12387 extend(getParsingFlags(m), flags); 12388 } else { 12389 getParsingFlags(m).userInvalidated = true; 12390 } 12391 12392 return m; 12393 } 12394 12395 // Plugins that add properties should also add the key here (null value), 12396 // so we can properly clone ourselves. 12397 var momentProperties = (hooks.momentProperties = []), 12398 updateInProgress = false; 12399 12400 function copyConfig(to, from) { 12401 var i, 12402 prop, 12403 val, 12404 momentPropertiesLen = momentProperties.length; 12405 12406 if (!isUndefined(from._isAMomentObject)) { 12407 to._isAMomentObject = from._isAMomentObject; 12408 } 12409 if (!isUndefined(from._i)) { 12410 to._i = from._i; 12411 } 12412 if (!isUndefined(from._f)) { 12413 to._f = from._f; 12414 } 12415 if (!isUndefined(from._l)) { 12416 to._l = from._l; 12417 } 12418 if (!isUndefined(from._strict)) { 12419 to._strict = from._strict; 12420 } 12421 if (!isUndefined(from._tzm)) { 12422 to._tzm = from._tzm; 12423 } 12424 if (!isUndefined(from._isUTC)) { 12425 to._isUTC = from._isUTC; 12426 } 12427 if (!isUndefined(from._offset)) { 12428 to._offset = from._offset; 12429 } 12430 if (!isUndefined(from._pf)) { 12431 to._pf = getParsingFlags(from); 12432 } 12433 if (!isUndefined(from._locale)) { 12434 to._locale = from._locale; 12435 } 12436 12437 if (momentPropertiesLen > 0) { 12438 for (i = 0; i < momentPropertiesLen; i++) { 12439 prop = momentProperties[i]; 12440 val = from[prop]; 12441 if (!isUndefined(val)) { 12442 to[prop] = val; 12443 } 12444 } 12445 } 12446 12447 return to; 12448 } 12449 12450 // Moment prototype object 12451 function Moment(config) { 12452 copyConfig(this, config); 12453 this._d = new Date(config._d != null ? config._d.getTime() : NaN); 12454 if (!this.isValid()) { 12455 this._d = new Date(NaN); 12456 } 12457 // Prevent infinite loop in case updateOffset creates new moment 12458 // objects. 12459 if (updateInProgress === false) { 12460 updateInProgress = true; 12461 hooks.updateOffset(this); 12462 updateInProgress = false; 12463 } 12464 } 12465 12466 function isMoment(obj) { 12467 return ( 12468 obj instanceof Moment || (obj != null && obj._isAMomentObject != null) 12469 ); 12470 } 12471 12472 function warn(msg) { 12473 if ( 12474 hooks.suppressDeprecationWarnings === false && 12475 typeof console !== 'undefined' && 12476 console.warn 12477 ) { 12478 console.warn('Deprecation warning: ' + msg); 12479 } 12480 } 12481 12482 function deprecate(msg, fn) { 12483 var firstTime = true; 12484 12485 return extend(function () { 12486 if (hooks.deprecationHandler != null) { 12487 hooks.deprecationHandler(null, msg); 12488 } 12489 if (firstTime) { 12490 var args = [], 12491 arg, 12492 i, 12493 key, 12494 argLen = arguments.length; 12495 for (i = 0; i < argLen; i++) { 12496 arg = ''; 12497 if (typeof arguments[i] === 'object') { 12498 arg += '\n[' + i + '] '; 12499 for (key in arguments[0]) { 12500 if (hasOwnProp(arguments[0], key)) { 12501 arg += key + ': ' + arguments[0][key] + ', '; 12502 } 12503 } 12504 arg = arg.slice(0, -2); // Remove trailing comma and space 12505 } else { 12506 arg = arguments[i]; 12507 } 12508 args.push(arg); 12509 } 12510 warn( 12511 msg + 12512 '\nArguments: ' + 12513 Array.prototype.slice.call(args).join('') + 12514 '\n' + 12515 new Error().stack 12516 ); 12517 firstTime = false; 12518 } 12519 return fn.apply(this, arguments); 12520 }, fn); 12521 } 12522 12523 var deprecations = {}; 12524 12525 function deprecateSimple(name, msg) { 12526 if (hooks.deprecationHandler != null) { 12527 hooks.deprecationHandler(name, msg); 12528 } 12529 if (!deprecations[name]) { 12530 warn(msg + '\n' + new Error().stack); 12531 deprecations[name] = true; 12532 } 12533 } 12534 12535 hooks.suppressDeprecationWarnings = false; 12536 hooks.deprecationHandler = null; 12537 12538 function isFunction(input) { 12539 return ( 12540 (typeof Function !== 'undefined' && input instanceof Function) || 12541 Object.prototype.toString.call(input) === '[object Function]' 12542 ); 12543 } 12544 12545 var aliases = { 12546 D: 'date', 12547 dates: 'date', 12548 date: 'date', 12549 d: 'day', 12550 days: 'day', 12551 day: 'day', 12552 e: 'weekday', 12553 weekdays: 'weekday', 12554 weekday: 'weekday', 12555 E: 'isoWeekday', 12556 isoweekdays: 'isoWeekday', 12557 isoweekday: 'isoWeekday', 12558 DDD: 'dayOfYear', 12559 dayofyears: 'dayOfYear', 12560 dayofyear: 'dayOfYear', 12561 h: 'hour', 12562 hours: 'hour', 12563 hour: 'hour', 12564 ms: 'millisecond', 12565 milliseconds: 'millisecond', 12566 millisecond: 'millisecond', 12567 m: 'minute', 12568 minutes: 'minute', 12569 minute: 'minute', 12570 M: 'month', 12571 months: 'month', 12572 month: 'month', 12573 Q: 'quarter', 12574 quarters: 'quarter', 12575 quarter: 'quarter', 12576 s: 'second', 12577 seconds: 'second', 12578 second: 'second', 12579 gg: 'weekYear', 12580 weekyears: 'weekYear', 12581 weekyear: 'weekYear', 12582 GG: 'isoWeekYear', 12583 isoweekyears: 'isoWeekYear', 12584 isoweekyear: 'isoWeekYear', 12585 w: 'week', 12586 weeks: 'week', 12587 week: 'week', 12588 W: 'isoWeek', 12589 isoweeks: 'isoWeek', 12590 isoweek: 'isoWeek', 12591 y: 'year', 12592 years: 'year', 12593 year: 'year', 12594 }; 12595 12596 function normalizeUnits(units) { 12597 return typeof units === 'string' 12598 ? aliases[units] || aliases[units.toLowerCase()] 12599 : undefined; 12600 } 12601 12602 function normalizeObjectUnits(inputObject) { 12603 var normalizedInput = {}, 12604 normalizedProp, 12605 prop; 12606 12607 for (prop in inputObject) { 12608 if (hasOwnProp(inputObject, prop)) { 12609 normalizedProp = normalizeUnits(prop); 12610 if (normalizedProp) { 12611 normalizedInput[normalizedProp] = inputObject[prop]; 12612 } 12613 } 12614 } 12615 12616 return normalizedInput; 12617 } 12618 12619 var priorities = { 12620 date: 9, 12621 day: 11, 12622 weekday: 11, 12623 isoWeekday: 11, 12624 dayOfYear: 4, 12625 hour: 13, 12626 millisecond: 16, 12627 minute: 14, 12628 month: 8, 12629 quarter: 7, 12630 second: 15, 12631 weekYear: 1, 12632 isoWeekYear: 1, 12633 week: 5, 12634 isoWeek: 5, 12635 year: 1, 12636 }; 12637 12638 function getPrioritizedUnits(unitsObj) { 12639 var units = [], 12640 u; 12641 for (u in unitsObj) { 12642 if (hasOwnProp(unitsObj, u)) { 12643 units.push({ unit: u, priority: priorities[u] }); 12644 } 12645 } 12646 units.sort(function (a, b) { 12647 return a.priority - b.priority; 12648 }); 12649 return units; 12650 } 12651 12652 function zeroFill(number, targetLength, forceSign) { 12653 var absNumber = '' + Math.abs(number), 12654 zerosToFill = targetLength - absNumber.length, 12655 sign = number >= 0; 12656 return ( 12657 (sign ? (forceSign ? '+' : '') : '-') + 12658 Math.pow(10, Math.max(0, zerosToFill)).toString().substr(1) + 12659 absNumber 12660 ); 12661 } 12662 12663 var formattingTokens = 12664 /(\[[^\[]*\])|(\\e)|(\\)?(eHHmm|[Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|N{1,5}|YYYYYY|YYYYY|YYYY|YY|y{2,4}|yo?|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g, 12665 localFormattingTokens = /(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g, 12666 formatFunctions = {}, 12667 formatTokenFunctions = {}; 12668 12669 // token: 'M' 12670 // padded: ['MM', 2] 12671 // ordinal: 'Mo' 12672 // callback: function () { this.month() + 1 } 12673 function addFormatToken(token, padded, ordinal, callback) { 12674 var func = callback; 12675 if (typeof callback === 'string') { 12676 func = function () { 12677 return this[callback](); 12678 }; 12679 } 12680 if (token) { 12681 formatTokenFunctions[token] = func; 12682 } 12683 if (padded) { 12684 formatTokenFunctions[padded[0]] = function () { 12685 return zeroFill(func.apply(this, arguments), padded[1], padded[2]); 12686 }; 12687 } 12688 if (ordinal) { 12689 formatTokenFunctions[ordinal] = function () { 12690 return this.localeData().ordinal( 12691 func.apply(this, arguments), 12692 token 12693 ); 12694 }; 12695 } 12696 } 12697 12698 function removeFormattingTokens(input) { 12699 if (input.match(/\[[\s\S]/)) { 12700 return input.replace(/^\[|\]$/g, ''); 12701 } 12702 return input.replace(/\\/g, ''); 12703 } 12704 12705 function makeFormatFunction(format) { 12706 var array = format.match(formattingTokens), 12707 i, 12708 length; 12709 12710 for (i = 0, length = array.length; i < length; i++) { 12711 if (formatTokenFunctions[array[i]]) { 12712 array[i] = formatTokenFunctions[array[i]]; 12713 } else { 12714 array[i] = removeFormattingTokens(array[i]); 12715 } 12716 } 12717 12718 return function (mom) { 12719 var output = '', 12720 i; 12721 for (i = 0; i < length; i++) { 12722 output += isFunction(array[i]) 12723 ? array[i].call(mom, format) 12724 : array[i]; 12725 } 12726 return output; 12727 }; 12728 } 12729 12730 // format date using native date object 12731 function formatMoment(m, format) { 12732 if (!m.isValid()) { 12733 return m.localeData().invalidDate(); 12734 } 12735 12736 format = expandFormat(format, m.localeData()); 12737 var cacheKey = '$' + format; 12738 if (!hasOwnProp(formatFunctions, cacheKey)) { 12739 formatFunctions[cacheKey] = makeFormatFunction(format); 12740 } 12741 12742 return formatFunctions[cacheKey](m); 12743 } 12744 12745 function expandFormat(format, locale) { 12746 var i = 5; 12747 12748 function replaceLongDateFormatTokens(input) { 12749 return locale.longDateFormat(input) || input; 12750 } 12751 12752 localFormattingTokens.lastIndex = 0; 12753 while (i >= 0 && localFormattingTokens.test(format)) { 12754 format = format.replace( 12755 localFormattingTokens, 12756 replaceLongDateFormatTokens 12757 ); 12758 localFormattingTokens.lastIndex = 0; 12759 i -= 1; 12760 } 12761 12762 return format; 12763 } 12764 12765 var match1 = /\d/, // 0 - 9 12766 match2 = /\d\d/, // 00 - 99 12767 match3 = /\d{3}/, // 000 - 999 12768 match4 = /\d{4}/, // 0000 - 9999 12769 match6 = /[+-]?\d{6}/, // -999999 - 999999 12770 match1to2 = /\d\d?/, // 0 - 99 12771 match3to4 = /\d\d\d\d?/, // 999 - 9999 12772 match5to6 = /\d\d\d\d\d\d?/, // 99999 - 999999 12773 match1to3 = /\d{1,3}/, // 0 - 999 12774 match1to4 = /\d{1,4}/, // 0 - 9999 12775 match1to6 = /[+-]?\d{1,6}/, // -999999 - 999999 12776 matchUnsigned = /\d+/, // 0 - inf 12777 matchSigned = /[+-]?\d+/, // -inf - inf 12778 matchOffset = /Z|[+-]\d\d:?\d\d/gi, // +00:00 -00:00 +0000 -0000 or Z 12779 matchShortOffset = /Z|[+-]\d\d(?::?\d\d)?/gi, // +00 -00 +00:00 -00:00 +0000 -0000 or Z 12780 matchTimestamp = /[+-]?\d+(\.\d{1,3})?/, // 123456789 123456789.123 12781 // any word (or two) characters or numbers including two/three word month in arabic. 12782 // includes scottish gaelic two word and hyphenated months 12783 matchWord = 12784 /[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, 12785 match1to2NoLeadingZero = /^[1-9]\d?/, // 1-99 12786 match1to2HasZero = /^([1-9]\d|\d)/, // 0-99 12787 regexes; 12788 12789 regexes = {}; 12790 12791 function addRegexToken(token, regex, strictRegex) { 12792 regexes[token] = isFunction(regex) 12793 ? regex 12794 : function (isStrict, localeData) { 12795 return isStrict && strictRegex ? strictRegex : regex; 12796 }; 12797 } 12798 12799 function getParseRegexForToken(token, config) { 12800 if (!hasOwnProp(regexes, token)) { 12801 return new RegExp(unescapeFormat(token)); 12802 } 12803 12804 return regexes[token](config._strict, config._locale); 12805 } 12806 12807 // Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript 12808 function unescapeFormat(s) { 12809 return regexEscape( 12810 s 12811 .replace('\\', '') 12812 .replace( 12813 /\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, 12814 function (matched, p1, p2, p3, p4) { 12815 return p1 || p2 || p3 || p4; 12816 } 12817 ) 12818 ); 12819 } 12820 12821 function regexEscape(s) { 12822 return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); 12823 } 12824 12825 function absFloor(number) { 12826 if (number < 0) { 12827 // -0 -> 0 12828 return Math.ceil(number) || 0; 12829 } else { 12830 return Math.floor(number); 12831 } 12832 } 12833 12834 function toInt(argumentForCoercion) { 12835 var coercedNumber = +argumentForCoercion, 12836 value = 0; 12837 12838 if (coercedNumber !== 0 && isFinite(coercedNumber)) { 12839 value = absFloor(coercedNumber); 12840 } 12841 12842 return value; 12843 } 12844 12845 var tokens = {}; 12846 12847 function addParseToken(token, callback) { 12848 var i, 12849 func = callback, 12850 tokenLen; 12851 if (typeof token === 'string') { 12852 token = [token]; 12853 } 12854 if (isNumber(callback)) { 12855 func = function (input, array) { 12856 array[callback] = toInt(input); 12857 }; 12858 } 12859 tokenLen = token.length; 12860 for (i = 0; i < tokenLen; i++) { 12861 tokens[token[i]] = func; 12862 } 12863 } 12864 12865 function addWeekParseToken(token, callback) { 12866 addParseToken(token, function (input, array, config, token) { 12867 config._w = config._w || {}; 12868 callback(input, config._w, config, token); 12869 }); 12870 } 12871 12872 function addTimeToArrayFromToken(token, input, config) { 12873 if (input != null && hasOwnProp(tokens, token)) { 12874 tokens[token](input, config._a, config, token); 12875 } 12876 } 12877 12878 function isLeapYear(year) { 12879 return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0; 12880 } 12881 12882 var YEAR = 0, 12883 MONTH = 1, 12884 DATE = 2, 12885 HOUR = 3, 12886 MINUTE = 4, 12887 SECOND = 5, 12888 MILLISECOND = 6, 12889 WEEK = 7, 12890 WEEKDAY = 8; 12891 12892 // FORMATTING 12893 12894 addFormatToken('Y', 0, 0, function () { 12895 var y = this.year(); 12896 return y <= 9999 ? zeroFill(y, 4) : '+' + y; 12897 }); 12898 12899 addFormatToken(0, ['YY', 2], 0, function () { 12900 return this.year() % 100; 12901 }); 12902 12903 addFormatToken(0, ['YYYY', 4], 0, 'year'); 12904 addFormatToken(0, ['YYYYY', 5], 0, 'year'); 12905 addFormatToken(0, ['YYYYYY', 6, true], 0, 'year'); 12906 12907 // PARSING 12908 12909 addRegexToken('Y', matchSigned); 12910 addRegexToken('YY', match1to2, match2); 12911 addRegexToken('YYYY', match1to4, match4); 12912 addRegexToken('YYYYY', match1to6, match6); 12913 addRegexToken('YYYYYY', match1to6, match6); 12914 12915 addParseToken(['YYYYY', 'YYYYYY'], YEAR); 12916 addParseToken('YYYY', function (input, array) { 12917 array[YEAR] = 12918 input.length === 2 ? hooks.parseTwoDigitYear(input) : toInt(input); 12919 }); 12920 addParseToken('YY', function (input, array) { 12921 array[YEAR] = hooks.parseTwoDigitYear(input); 12922 }); 12923 addParseToken('Y', function (input, array) { 12924 array[YEAR] = parseInt(input, 10); 12925 }); 12926 12927 // HELPERS 12928 12929 function daysInYear(year) { 12930 return isLeapYear(year) ? 366 : 365; 12931 } 12932 12933 // HOOKS 12934 12935 hooks.parseTwoDigitYear = function (input) { 12936 return toInt(input) + (toInt(input) > 68 ? 1900 : 2000); 12937 }; 12938 12939 // MOMENTS 12940 12941 var getSetYear = makeGetSet('FullYear', true); 12942 12943 function getIsLeapYear() { 12944 return isLeapYear(this.year()); 12945 } 12946 12947 function makeGetSet(unit, keepTime) { 12948 return function (value) { 12949 if (value != null) { 12950 set$1(this, unit, value); 12951 hooks.updateOffset(this, keepTime); 12952 return this; 12953 } else { 12954 return get$2(this, unit); 12955 } 12956 }; 12957 } 12958 12959 function get$2(mom, unit) { 12960 if (!mom.isValid()) { 12961 return NaN; 12962 } 12963 12964 var d = mom._d, 12965 isUTC = mom._isUTC; 12966 12967 switch (unit) { 12968 case 'Milliseconds': 12969 return isUTC ? d.getUTCMilliseconds() : d.getMilliseconds(); 12970 case 'Seconds': 12971 return isUTC ? d.getUTCSeconds() : d.getSeconds(); 12972 case 'Minutes': 12973 return isUTC ? d.getUTCMinutes() : d.getMinutes(); 12974 case 'Hours': 12975 return isUTC ? d.getUTCHours() : d.getHours(); 12976 case 'Date': 12977 return isUTC ? d.getUTCDate() : d.getDate(); 12978 case 'Day': 12979 return isUTC ? d.getUTCDay() : d.getDay(); 12980 case 'Month': 12981 return isUTC ? d.getUTCMonth() : d.getMonth(); 12982 case 'FullYear': 12983 return isUTC ? d.getUTCFullYear() : d.getFullYear(); 12984 default: 12985 return NaN; // Just in case 12986 } 12987 } 12988 12989 function set$1(mom, unit, value) { 12990 var d, isUTC, year, month, date; 12991 12992 if (!mom.isValid() || isNaN(value)) { 12993 return; 12994 } 12995 12996 d = mom._d; 12997 isUTC = mom._isUTC; 12998 12999 switch (unit) { 13000 case 'Milliseconds': 13001 return void (isUTC 13002 ? d.setUTCMilliseconds(value) 13003 : d.setMilliseconds(value)); 13004 case 'Seconds': 13005 return void (isUTC ? d.setUTCSeconds(value) : d.setSeconds(value)); 13006 case 'Minutes': 13007 return void (isUTC ? d.setUTCMinutes(value) : d.setMinutes(value)); 13008 case 'Hours': 13009 return void (isUTC ? d.setUTCHours(value) : d.setHours(value)); 13010 case 'Date': 13011 return void (isUTC ? d.setUTCDate(value) : d.setDate(value)); 13012 // case 'Day': // Not real 13013 // return void (isUTC ? d.setUTCDay(value) : d.setDay(value)); 13014 // case 'Month': // Not used because we need to pass two variables 13015 // return void (isUTC ? d.setUTCMonth(value) : d.setMonth(value)); 13016 case 'FullYear': 13017 break; // See below ... 13018 default: 13019 return; // Just in case 13020 } 13021 13022 year = value; 13023 month = mom.month(); 13024 date = mom.date(); 13025 date = date === 29 && month === 1 && !isLeapYear(year) ? 28 : date; 13026 void (isUTC 13027 ? d.setUTCFullYear(year, month, date) 13028 : d.setFullYear(year, month, date)); 13029 } 13030 13031 // MOMENTS 13032 13033 function stringGet(units) { 13034 units = normalizeUnits(units); 13035 if (isFunction(this[units])) { 13036 return this[units](); 13037 } 13038 return this; 13039 } 13040 13041 function stringSet(units, value) { 13042 if (typeof units === 'object') { 13043 units = normalizeObjectUnits(units); 13044 var prioritized = getPrioritizedUnits(units), 13045 i, 13046 prioritizedLen = prioritized.length; 13047 for (i = 0; i < prioritizedLen; i++) { 13048 this[prioritized[i].unit](units[prioritized[i].unit]); 13049 } 13050 } else { 13051 units = normalizeUnits(units); 13052 if (isFunction(this[units])) { 13053 return this[units](value); 13054 } 13055 } 13056 return this; 13057 } 13058 13059 function mod$1(n, x) { 13060 return ((n % x) + x) % x; 13061 } 13062 13063 var indexOf; 13064 13065 if (Array.prototype.indexOf) { 13066 indexOf = Array.prototype.indexOf; 13067 } else { 13068 indexOf = function (o) { 13069 // I know 13070 var i; 13071 for (i = 0; i < this.length; ++i) { 13072 if (this[i] === o) { 13073 return i; 13074 } 13075 } 13076 return -1; 13077 }; 13078 } 13079 13080 function daysInMonth(year, month) { 13081 if (isNaN(year) || isNaN(month)) { 13082 return NaN; 13083 } 13084 var modMonth = mod$1(month, 12); 13085 year += (month - modMonth) / 12; 13086 return modMonth === 1 13087 ? isLeapYear(year) 13088 ? 29 13089 : 28 13090 : 31 - ((modMonth % 7) % 2); 13091 } 13092 13093 // FORMATTING 13094 13095 addFormatToken('M', ['MM', 2], 'Mo', function () { 13096 return this.month() + 1; 13097 }); 13098 13099 addFormatToken('MMM', 0, 0, function (format) { 13100 return this.localeData().monthsShort(this, format); 13101 }); 13102 13103 addFormatToken('MMMM', 0, 0, function (format) { 13104 return this.localeData().months(this, format); 13105 }); 13106 13107 // PARSING 13108 13109 addRegexToken('M', match1to2, match1to2NoLeadingZero); 13110 addRegexToken('MM', match1to2, match2); 13111 addRegexToken('MMM', function (isStrict, locale) { 13112 return locale.monthsShortRegex(isStrict); 13113 }); 13114 addRegexToken('MMMM', function (isStrict, locale) { 13115 return locale.monthsRegex(isStrict); 13116 }); 13117 13118 addParseToken(['M', 'MM'], function (input, array) { 13119 array[MONTH] = toInt(input) - 1; 13120 }); 13121 13122 addParseToken(['MMM', 'MMMM'], function (input, array, config, token) { 13123 var month = config._locale.monthsParse(input, token, config._strict); 13124 // if we didn't find a month name, mark the date as invalid. 13125 if (month != null) { 13126 array[MONTH] = month; 13127 } else { 13128 getParsingFlags(config).invalidMonth = input; 13129 } 13130 }); 13131 13132 // LOCALES 13133 13134 var defaultLocaleMonths = 13135 'January_February_March_April_May_June_July_August_September_October_November_December'.split( 13136 '_' 13137 ), 13138 defaultLocaleMonthsShort = 13139 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'), 13140 MONTHS_IN_FORMAT = /D[oD]?(\[[^\[\]]*\]|\s)+MMMM?/, 13141 defaultMonthsShortRegex = matchWord, 13142 defaultMonthsRegex = matchWord, 13143 monthsParseProperties = [ 13144 'monthsParse', 13145 'longMonthsParse', 13146 'shortMonthsParse', 13147 'monthsRegex', 13148 'monthsShortRegex', 13149 'monthsStrictRegex', 13150 'monthsShortStrictRegex', 13151 ]; 13152 13153 function clearMonthsParseCache(locale, config) { 13154 var i, prop; 13155 for (i = 0; i < monthsParseProperties.length; i++) { 13156 prop = monthsParseProperties[i]; 13157 if (!hasOwnProp(config, prop)) { 13158 delete locale['_' + prop]; 13159 } 13160 } 13161 } 13162 13163 function localeMonths(m, format) { 13164 if (!m) { 13165 return isArray(this._months) 13166 ? this._months 13167 : this._months['standalone']; 13168 } 13169 return isArray(this._months) 13170 ? this._months[m.month()] 13171 : this._months[ 13172 (this._months.isFormat || MONTHS_IN_FORMAT).test(format) 13173 ? 'format' 13174 : 'standalone' 13175 ][m.month()]; 13176 } 13177 13178 function localeMonthsShort(m, format) { 13179 if (!m) { 13180 return isArray(this._monthsShort) 13181 ? this._monthsShort 13182 : this._monthsShort['standalone']; 13183 } 13184 return isArray(this._monthsShort) 13185 ? this._monthsShort[m.month()] 13186 : this._monthsShort[ 13187 MONTHS_IN_FORMAT.test(format) ? 'format' : 'standalone' 13188 ][m.month()]; 13189 } 13190 13191 function handleStrictParse$1(monthName, format, strict) { 13192 var i, 13193 ii, 13194 mom, 13195 llc = monthName.toLocaleLowerCase(); 13196 if (!this._monthsParse) { 13197 // this is not used 13198 this._monthsParse = []; 13199 this._longMonthsParse = []; 13200 this._shortMonthsParse = []; 13201 for (i = 0; i < 12; ++i) { 13202 mom = createUTC([2000, i]); 13203 this._shortMonthsParse[i] = this.monthsShort( 13204 mom, 13205 '' 13206 ).toLocaleLowerCase(); 13207 this._longMonthsParse[i] = this.months(mom, '').toLocaleLowerCase(); 13208 } 13209 } 13210 13211 if (strict) { 13212 if (format === 'MMM') { 13213 ii = indexOf.call(this._shortMonthsParse, llc); 13214 return ii !== -1 ? ii : null; 13215 } else { 13216 ii = indexOf.call(this._longMonthsParse, llc); 13217 return ii !== -1 ? ii : null; 13218 } 13219 } else { 13220 if (format === 'MMM') { 13221 ii = indexOf.call(this._shortMonthsParse, llc); 13222 if (ii !== -1) { 13223 return ii; 13224 } 13225 ii = indexOf.call(this._longMonthsParse, llc); 13226 return ii !== -1 ? ii : null; 13227 } else { 13228 ii = indexOf.call(this._longMonthsParse, llc); 13229 if (ii !== -1) { 13230 return ii; 13231 } 13232 ii = indexOf.call(this._shortMonthsParse, llc); 13233 return ii !== -1 ? ii : null; 13234 } 13235 } 13236 } 13237 13238 function localeMonthsParse(monthName, format, strict) { 13239 var i, mom, regex; 13240 13241 if (this._monthsParseExact) { 13242 return handleStrictParse$1.call(this, monthName, format, strict); 13243 } 13244 13245 if (!this._monthsParse) { 13246 this._monthsParse = []; 13247 this._longMonthsParse = []; 13248 this._shortMonthsParse = []; 13249 } 13250 13251 // TODO: add sorting 13252 // Sorting makes sure if one month (or abbr) is a prefix of another 13253 // see sorting in computeMonthsParse 13254 for (i = 0; i < 12; i++) { 13255 // make the regex if we don't have it already 13256 mom = createUTC([2000, i]); 13257 if (strict && !this._longMonthsParse[i]) { 13258 this._longMonthsParse[i] = new RegExp( 13259 '^' + this.months(mom, '').replace('.', '') + '$', 13260 'i' 13261 ); 13262 this._shortMonthsParse[i] = new RegExp( 13263 '^' + this.monthsShort(mom, '').replace('.', '') + '$', 13264 'i' 13265 ); 13266 } 13267 if (!strict && !this._monthsParse[i]) { 13268 regex = 13269 '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, ''); 13270 this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i'); 13271 } 13272 // test the regex 13273 if ( 13274 strict && 13275 format === 'MMMM' && 13276 this._longMonthsParse[i].test(monthName) 13277 ) { 13278 return i; 13279 } else if ( 13280 strict && 13281 format === 'MMM' && 13282 this._shortMonthsParse[i].test(monthName) 13283 ) { 13284 return i; 13285 } else if (!strict && this._monthsParse[i].test(monthName)) { 13286 return i; 13287 } 13288 } 13289 } 13290 13291 // MOMENTS 13292 13293 function setMonth(mom, value) { 13294 if (!mom.isValid()) { 13295 // No op 13296 return mom; 13297 } 13298 13299 if (typeof value === 'string') { 13300 if (/^\d+$/.test(value)) { 13301 value = toInt(value); 13302 } else { 13303 value = mom.localeData().monthsParse(value); 13304 // TODO: Another silent failure? 13305 if (!isNumber(value)) { 13306 return mom; 13307 } 13308 } 13309 } 13310 13311 var month = value, 13312 date = mom.date(); 13313 13314 date = date < 29 ? date : Math.min(date, daysInMonth(mom.year(), month)); 13315 void (mom._isUTC 13316 ? mom._d.setUTCMonth(month, date) 13317 : mom._d.setMonth(month, date)); 13318 return mom; 13319 } 13320 13321 function getSetMonth(value) { 13322 if (value != null) { 13323 setMonth(this, value); 13324 hooks.updateOffset(this, true); 13325 return this; 13326 } else { 13327 return get$2(this, 'Month'); 13328 } 13329 } 13330 13331 function getDaysInMonth() { 13332 return daysInMonth(this.year(), this.month()); 13333 } 13334 13335 function monthsShortRegex(isStrict) { 13336 if (this._monthsParseExact) { 13337 if (!hasOwnProp(this, '_monthsRegex')) { 13338 computeMonthsParse.call(this); 13339 } 13340 if (isStrict) { 13341 return this._monthsShortStrictRegex; 13342 } else { 13343 return this._monthsShortRegex; 13344 } 13345 } else { 13346 if (!hasOwnProp(this, '_monthsShortRegex')) { 13347 this._monthsShortRegex = defaultMonthsShortRegex; 13348 } 13349 return this._monthsShortStrictRegex && isStrict 13350 ? this._monthsShortStrictRegex 13351 : this._monthsShortRegex; 13352 } 13353 } 13354 13355 function monthsRegex(isStrict) { 13356 if (this._monthsParseExact) { 13357 if (!hasOwnProp(this, '_monthsRegex')) { 13358 computeMonthsParse.call(this); 13359 } 13360 if (isStrict) { 13361 return this._monthsStrictRegex; 13362 } else { 13363 return this._monthsRegex; 13364 } 13365 } else { 13366 if (!hasOwnProp(this, '_monthsRegex')) { 13367 this._monthsRegex = defaultMonthsRegex; 13368 } 13369 return this._monthsStrictRegex && isStrict 13370 ? this._monthsStrictRegex 13371 : this._monthsRegex; 13372 } 13373 } 13374 13375 function computeMonthsParse() { 13376 function cmpLenRev(a, b) { 13377 return b.length - a.length; 13378 } 13379 13380 var shortPieces = [], 13381 longPieces = [], 13382 mixedPieces = [], 13383 i, 13384 mom, 13385 shortP, 13386 longP; 13387 for (i = 0; i < 12; i++) { 13388 // make the regex if we don't have it already 13389 mom = createUTC([2000, i]); 13390 shortP = regexEscape(this.monthsShort(mom, '')); 13391 longP = regexEscape(this.months(mom, '')); 13392 shortPieces.push(shortP); 13393 longPieces.push(longP); 13394 mixedPieces.push(longP); 13395 mixedPieces.push(shortP); 13396 } 13397 // Sorting makes sure if one month (or abbr) is a prefix of another it 13398 // will match the longer piece. 13399 shortPieces.sort(cmpLenRev); 13400 longPieces.sort(cmpLenRev); 13401 mixedPieces.sort(cmpLenRev); 13402 13403 this._monthsRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i'); 13404 this._monthsShortRegex = this._monthsRegex; 13405 this._monthsStrictRegex = new RegExp( 13406 '^(' + longPieces.join('|') + ')', 13407 'i' 13408 ); 13409 this._monthsShortStrictRegex = new RegExp( 13410 '^(' + shortPieces.join('|') + ')', 13411 'i' 13412 ); 13413 } 13414 13415 // FORMATTING 13416 13417 addFormatToken('d', 0, 'do', 'day'); 13418 13419 addFormatToken('dd', 0, 0, function (format) { 13420 return this.localeData().weekdaysMin(this, format); 13421 }); 13422 13423 addFormatToken('ddd', 0, 0, function (format) { 13424 return this.localeData().weekdaysShort(this, format); 13425 }); 13426 13427 addFormatToken('dddd', 0, 0, function (format) { 13428 return this.localeData().weekdays(this, format); 13429 }); 13430 13431 addFormatToken('e', 0, 0, 'weekday'); 13432 addFormatToken('E', 0, 0, 'isoWeekday'); 13433 addFormatToken('eHHmm', 0, 0, function () { 13434 return ( 13435 '' + 13436 this.weekday() + 13437 zeroFill(this.hours(), 2) + 13438 zeroFill(this.minutes(), 2) 13439 ); 13440 }); 13441 13442 // PARSING 13443 13444 addRegexToken('d', match1to2); 13445 addRegexToken('e', match1to2); 13446 addRegexToken('E', match1to2); 13447 addRegexToken('eHHmm', match5to6); 13448 addRegexToken('dd', function (isStrict, locale) { 13449 return locale.weekdaysMinRegex(isStrict); 13450 }); 13451 addRegexToken('ddd', function (isStrict, locale) { 13452 return locale.weekdaysShortRegex(isStrict); 13453 }); 13454 addRegexToken('dddd', function (isStrict, locale) { 13455 return locale.weekdaysRegex(isStrict); 13456 }); 13457 13458 addWeekParseToken(['dd', 'ddd', 'dddd'], function (input, week, config, token) { 13459 var weekday = config._locale.weekdaysParse(input, token, config._strict); 13460 // if we didn't get a weekday name, mark the date as invalid 13461 if (weekday != null) { 13462 week.d = weekday; 13463 } else { 13464 getParsingFlags(config).invalidWeekday = input; 13465 } 13466 }); 13467 13468 addWeekParseToken(['d', 'e', 'E'], function (input, week, config, token) { 13469 week[token] = toInt(input); 13470 }); 13471 13472 addWeekParseToken('eHHmm', function (input, week, config) { 13473 var weekdayEnd = input.length - 4; 13474 13475 week.e = toInt(input.substr(0, weekdayEnd)); 13476 config._a[HOUR] = toInt(input.substr(weekdayEnd, 2)); 13477 config._a[MINUTE] = toInt(input.substr(weekdayEnd + 2)); 13478 }); 13479 13480 // HELPERS 13481 13482 function parseWeekday(input, locale) { 13483 if (typeof input !== 'string') { 13484 return input; 13485 } 13486 13487 if (!isNaN(input)) { 13488 return parseInt(input, 10); 13489 } 13490 13491 input = locale.weekdaysParse(input); 13492 if (typeof input === 'number') { 13493 return input; 13494 } 13495 13496 return null; 13497 } 13498 13499 function parseIsoWeekday(input, locale) { 13500 if (typeof input === 'string') { 13501 return locale.weekdaysParse(input) % 7 || 7; 13502 } 13503 return isNaN(input) ? null : input; 13504 } 13505 13506 // LOCALES 13507 function shiftWeekdays(ws, n) { 13508 return ws.slice(n, 7).concat(ws.slice(0, n)); 13509 } 13510 13511 var defaultLocaleWeekdays = 13512 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'), 13513 defaultLocaleWeekdaysShort = 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'), 13514 defaultLocaleWeekdaysMin = 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'), 13515 defaultWeekdaysRegex = matchWord, 13516 defaultWeekdaysShortRegex = matchWord, 13517 defaultWeekdaysMinRegex = matchWord, 13518 weekdaysParseProperties = [ 13519 'weekdaysParse', 13520 'fullWeekdaysParse', 13521 'shortWeekdaysParse', 13522 'minWeekdaysParse', 13523 'weekdaysRegex', 13524 'weekdaysShortRegex', 13525 'weekdaysMinRegex', 13526 'weekdaysStrictRegex', 13527 'weekdaysShortStrictRegex', 13528 'weekdaysMinStrictRegex', 13529 ]; 13530 13531 function clearWeekdaysParseCache(locale, config) { 13532 var i, prop; 13533 for (i = 0; i < weekdaysParseProperties.length; i++) { 13534 prop = weekdaysParseProperties[i]; 13535 if (!hasOwnProp(config, prop)) { 13536 delete locale['_' + prop]; 13537 } 13538 } 13539 } 13540 13541 function localeWeekdays(m, format) { 13542 var weekdays = isArray(this._weekdays) 13543 ? this._weekdays 13544 : this._weekdays[ 13545 m && m !== true && this._weekdays.isFormat.test(format) 13546 ? 'format' 13547 : 'standalone' 13548 ]; 13549 return m === true 13550 ? shiftWeekdays(weekdays, this._week.dow) 13551 : m 13552 ? weekdays[m.day()] 13553 : weekdays; 13554 } 13555 13556 function localeWeekdaysShort(m) { 13557 return m === true 13558 ? shiftWeekdays(this._weekdaysShort, this._week.dow) 13559 : m 13560 ? this._weekdaysShort[m.day()] 13561 : this._weekdaysShort; 13562 } 13563 13564 function localeWeekdaysMin(m) { 13565 return m === true 13566 ? shiftWeekdays(this._weekdaysMin, this._week.dow) 13567 : m 13568 ? this._weekdaysMin[m.day()] 13569 : this._weekdaysMin; 13570 } 13571 13572 function handleStrictParse(weekdayName, format, strict) { 13573 var i, 13574 ii, 13575 mom, 13576 llc = weekdayName.toLocaleLowerCase(); 13577 if (!this._weekdaysParse) { 13578 this._weekdaysParse = []; 13579 this._shortWeekdaysParse = []; 13580 this._minWeekdaysParse = []; 13581 13582 for (i = 0; i < 7; ++i) { 13583 mom = createUTC([2000, 1]).day(i); 13584 this._minWeekdaysParse[i] = this.weekdaysMin( 13585 mom, 13586 '' 13587 ).toLocaleLowerCase(); 13588 this._shortWeekdaysParse[i] = this.weekdaysShort( 13589 mom, 13590 '' 13591 ).toLocaleLowerCase(); 13592 this._weekdaysParse[i] = this.weekdays(mom, '').toLocaleLowerCase(); 13593 } 13594 } 13595 13596 if (strict) { 13597 if (format === 'dddd') { 13598 ii = indexOf.call(this._weekdaysParse, llc); 13599 return ii !== -1 ? ii : null; 13600 } else if (format === 'ddd') { 13601 ii = indexOf.call(this._shortWeekdaysParse, llc); 13602 return ii !== -1 ? ii : null; 13603 } else { 13604 ii = indexOf.call(this._minWeekdaysParse, llc); 13605 return ii !== -1 ? ii : null; 13606 } 13607 } else { 13608 if (format === 'dddd') { 13609 ii = indexOf.call(this._weekdaysParse, llc); 13610 if (ii !== -1) { 13611 return ii; 13612 } 13613 ii = indexOf.call(this._shortWeekdaysParse, llc); 13614 if (ii !== -1) { 13615 return ii; 13616 } 13617 ii = indexOf.call(this._minWeekdaysParse, llc); 13618 return ii !== -1 ? ii : null; 13619 } else if (format === 'ddd') { 13620 ii = indexOf.call(this._shortWeekdaysParse, llc); 13621 if (ii !== -1) { 13622 return ii; 13623 } 13624 ii = indexOf.call(this._weekdaysParse, llc); 13625 if (ii !== -1) { 13626 return ii; 13627 } 13628 ii = indexOf.call(this._minWeekdaysParse, llc); 13629 return ii !== -1 ? ii : null; 13630 } else { 13631 ii = indexOf.call(this._minWeekdaysParse, llc); 13632 if (ii !== -1) { 13633 return ii; 13634 } 13635 ii = indexOf.call(this._weekdaysParse, llc); 13636 if (ii !== -1) { 13637 return ii; 13638 } 13639 ii = indexOf.call(this._shortWeekdaysParse, llc); 13640 return ii !== -1 ? ii : null; 13641 } 13642 } 13643 } 13644 13645 function localeWeekdaysParse(weekdayName, format, strict) { 13646 var i, mom, regex; 13647 13648 if (this._weekdaysParseExact) { 13649 return handleStrictParse.call(this, weekdayName, format, strict); 13650 } 13651 13652 if (!this._weekdaysParse) { 13653 this._weekdaysParse = []; 13654 this._minWeekdaysParse = []; 13655 this._shortWeekdaysParse = []; 13656 this._fullWeekdaysParse = []; 13657 } 13658 13659 for (i = 0; i < 7; i++) { 13660 // make the regex if we don't have it already 13661 13662 mom = createUTC([2000, 1]).day(i); 13663 if (strict && !this._fullWeekdaysParse[i]) { 13664 this._fullWeekdaysParse[i] = new RegExp( 13665 '^' + this.weekdays(mom, '').replace('.', '\\.?') + '$', 13666 'i' 13667 ); 13668 this._shortWeekdaysParse[i] = new RegExp( 13669 '^' + this.weekdaysShort(mom, '').replace('.', '\\.?') + '$', 13670 'i' 13671 ); 13672 this._minWeekdaysParse[i] = new RegExp( 13673 '^' + this.weekdaysMin(mom, '').replace('.', '\\.?') + '$', 13674 'i' 13675 ); 13676 } 13677 if (!this._weekdaysParse[i]) { 13678 regex = 13679 '^' + 13680 this.weekdays(mom, '') + 13681 '|^' + 13682 this.weekdaysShort(mom, '') + 13683 '|^' + 13684 this.weekdaysMin(mom, ''); 13685 this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i'); 13686 } 13687 // test the regex 13688 if ( 13689 strict && 13690 format === 'dddd' && 13691 this._fullWeekdaysParse[i].test(weekdayName) 13692 ) { 13693 return i; 13694 } else if ( 13695 strict && 13696 format === 'ddd' && 13697 this._shortWeekdaysParse[i].test(weekdayName) 13698 ) { 13699 return i; 13700 } else if ( 13701 strict && 13702 format === 'dd' && 13703 this._minWeekdaysParse[i].test(weekdayName) 13704 ) { 13705 return i; 13706 } else if (!strict && this._weekdaysParse[i].test(weekdayName)) { 13707 return i; 13708 } 13709 } 13710 } 13711 13712 // MOMENTS 13713 13714 function getSetDayOfWeek(input) { 13715 if (!this.isValid()) { 13716 return input != null ? this : NaN; 13717 } 13718 13719 var day = get$2(this, 'Day'); 13720 if (input != null) { 13721 input = parseWeekday(input, this.localeData()); 13722 return this.add(input - day, 'd'); 13723 } else { 13724 return day; 13725 } 13726 } 13727 13728 function getSetLocaleDayOfWeek(input) { 13729 if (!this.isValid()) { 13730 return input != null ? this : NaN; 13731 } 13732 var weekday = (this.day() + 7 - this.localeData()._week.dow) % 7; 13733 return input == null ? weekday : this.add(input - weekday, 'd'); 13734 } 13735 13736 function getSetISODayOfWeek(input) { 13737 if (!this.isValid()) { 13738 return input != null ? this : NaN; 13739 } 13740 13741 // behaves the same as moment#day except 13742 // as a getter, returns 7 instead of 0 (1-7 range instead of 0-6) 13743 // as a setter, sunday should belong to the previous week. 13744 13745 if (input != null) { 13746 var weekday = parseIsoWeekday(input, this.localeData()); 13747 return this.day(this.day() % 7 ? weekday : weekday - 7); 13748 } else { 13749 return this.day() || 7; 13750 } 13751 } 13752 13753 function weekdaysRegex(isStrict) { 13754 if (this._weekdaysParseExact) { 13755 if (!hasOwnProp(this, '_weekdaysRegex')) { 13756 computeWeekdaysParse.call(this); 13757 } 13758 if (isStrict) { 13759 return this._weekdaysStrictRegex; 13760 } else { 13761 return this._weekdaysRegex; 13762 } 13763 } else { 13764 if (!hasOwnProp(this, '_weekdaysRegex')) { 13765 this._weekdaysRegex = defaultWeekdaysRegex; 13766 } 13767 return this._weekdaysStrictRegex && isStrict 13768 ? this._weekdaysStrictRegex 13769 : this._weekdaysRegex; 13770 } 13771 } 13772 13773 function weekdaysShortRegex(isStrict) { 13774 if (this._weekdaysParseExact) { 13775 if (!hasOwnProp(this, '_weekdaysRegex')) { 13776 computeWeekdaysParse.call(this); 13777 } 13778 if (isStrict) { 13779 return this._weekdaysShortStrictRegex; 13780 } else { 13781 return this._weekdaysShortRegex; 13782 } 13783 } else { 13784 if (!hasOwnProp(this, '_weekdaysShortRegex')) { 13785 this._weekdaysShortRegex = defaultWeekdaysShortRegex; 13786 } 13787 return this._weekdaysShortStrictRegex && isStrict 13788 ? this._weekdaysShortStrictRegex 13789 : this._weekdaysShortRegex; 13790 } 13791 } 13792 13793 function weekdaysMinRegex(isStrict) { 13794 if (this._weekdaysParseExact) { 13795 if (!hasOwnProp(this, '_weekdaysRegex')) { 13796 computeWeekdaysParse.call(this); 13797 } 13798 if (isStrict) { 13799 return this._weekdaysMinStrictRegex; 13800 } else { 13801 return this._weekdaysMinRegex; 13802 } 13803 } else { 13804 if (!hasOwnProp(this, '_weekdaysMinRegex')) { 13805 this._weekdaysMinRegex = defaultWeekdaysMinRegex; 13806 } 13807 return this._weekdaysMinStrictRegex && isStrict 13808 ? this._weekdaysMinStrictRegex 13809 : this._weekdaysMinRegex; 13810 } 13811 } 13812 13813 function computeWeekdaysParse() { 13814 function cmpLenRev(a, b) { 13815 return b.length - a.length; 13816 } 13817 13818 var minPieces = [], 13819 shortPieces = [], 13820 longPieces = [], 13821 mixedPieces = [], 13822 i, 13823 mom, 13824 minp, 13825 shortp, 13826 longp; 13827 for (i = 0; i < 7; i++) { 13828 // make the regex if we don't have it already 13829 mom = createUTC([2000, 1]).day(i); 13830 minp = regexEscape(this.weekdaysMin(mom, '')); 13831 shortp = regexEscape(this.weekdaysShort(mom, '')); 13832 longp = regexEscape(this.weekdays(mom, '')); 13833 minPieces.push(minp); 13834 shortPieces.push(shortp); 13835 longPieces.push(longp); 13836 mixedPieces.push(minp); 13837 mixedPieces.push(shortp); 13838 mixedPieces.push(longp); 13839 } 13840 // Sorting makes sure if one weekday (or abbr) is a prefix of another it 13841 // will match the longer piece. 13842 minPieces.sort(cmpLenRev); 13843 shortPieces.sort(cmpLenRev); 13844 longPieces.sort(cmpLenRev); 13845 mixedPieces.sort(cmpLenRev); 13846 13847 this._weekdaysRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i'); 13848 this._weekdaysShortRegex = this._weekdaysRegex; 13849 this._weekdaysMinRegex = this._weekdaysRegex; 13850 13851 this._weekdaysStrictRegex = new RegExp( 13852 '^(' + longPieces.join('|') + ')', 13853 'i' 13854 ); 13855 this._weekdaysShortStrictRegex = new RegExp( 13856 '^(' + shortPieces.join('|') + ')', 13857 'i' 13858 ); 13859 this._weekdaysMinStrictRegex = new RegExp( 13860 '^(' + minPieces.join('|') + ')', 13861 'i' 13862 ); 13863 } 13864 13865 function set(config) { 13866 var prop, i; 13867 clearMonthsParseCache(this, config); 13868 clearWeekdaysParseCache(this, config); 13869 for (i in config) { 13870 if (hasOwnProp(config, i)) { 13871 prop = config[i]; 13872 if (isFunction(prop)) { 13873 this[i] = prop; 13874 } else { 13875 this['_' + i] = prop; 13876 } 13877 } 13878 } 13879 this._config = config; 13880 // Lenient ordinal parsing accepts just a number in addition to 13881 // number + (possibly) stuff coming from _dayOfMonthOrdinalParse. 13882 // TODO: Remove "ordinalParse" fallback in next major release. 13883 this._dayOfMonthOrdinalParseLenient = new RegExp( 13884 (this._dayOfMonthOrdinalParse.source || this._ordinalParse.source) + 13885 '|' + 13886 /\d{1,2}/.source 13887 ); 13888 } 13889 13890 function mergeConfigs(parentConfig, childConfig) { 13891 var res = extend({}, parentConfig), 13892 prop; 13893 for (prop in childConfig) { 13894 if (hasOwnProp(childConfig, prop)) { 13895 if (isObject(parentConfig[prop]) && isObject(childConfig[prop])) { 13896 res[prop] = {}; 13897 extend(res[prop], parentConfig[prop]); 13898 extend(res[prop], childConfig[prop]); 13899 } else if (childConfig[prop] != null) { 13900 res[prop] = childConfig[prop]; 13901 } else { 13902 delete res[prop]; 13903 } 13904 } 13905 } 13906 for (prop in parentConfig) { 13907 if ( 13908 hasOwnProp(parentConfig, prop) && 13909 !hasOwnProp(childConfig, prop) && 13910 isObject(parentConfig[prop]) 13911 ) { 13912 // make sure changes to properties don't modify parent config 13913 res[prop] = extend({}, res[prop]); 13914 } 13915 } 13916 return res; 13917 } 13918 13919 function Locale(config) { 13920 if (config != null) { 13921 this.set(config); 13922 } 13923 } 13924 13925 var keys; 13926 13927 if (Object.keys) { 13928 keys = Object.keys; 13929 } else { 13930 keys = function (obj) { 13931 var i, 13932 res = []; 13933 for (i in obj) { 13934 if (hasOwnProp(obj, i)) { 13935 res.push(i); 13936 } 13937 } 13938 return res; 13939 }; 13940 } 13941 13942 var defaultCalendar = { 13943 sameDay: '[Today at] LT', 13944 nextDay: '[Tomorrow at] LT', 13945 nextWeek: 'dddd [at] LT', 13946 lastDay: '[Yesterday at] LT', 13947 lastWeek: '[Last] dddd [at] LT', 13948 sameElse: 'L', 13949 }; 13950 13951 function calendar$1(key, mom, now) { 13952 var output = this._calendar[key] || this._calendar['sameElse']; 13953 return isFunction(output) ? output.call(mom, now) : output; 13954 } 13955 13956 var defaultLongDateFormat = { 13957 LTS: 'h:mm:ss A', 13958 LT: 'h:mm A', 13959 L: 'MM/DD/YYYY', 13960 LL: 'MMMM D, YYYY', 13961 LLL: 'MMMM D, YYYY h:mm A', 13962 LLLL: 'dddd, MMMM D, YYYY h:mm A', 13963 }; 13964 13965 function longDateFormat(key) { 13966 var format = this._longDateFormat[key], 13967 formatUpper = this._longDateFormat[key.toUpperCase()], 13968 formatCache = this._longDateFormatCache; 13969 13970 if (format || !formatUpper) { 13971 return format; 13972 } 13973 13974 if ( 13975 formatCache && 13976 formatCache[key] && 13977 formatCache[key].formatUpper === formatUpper 13978 ) { 13979 return formatCache[key].format; 13980 } 13981 13982 format = formatUpper 13983 .match(formattingTokens) 13984 .map(function (tok) { 13985 if ( 13986 tok === 'MMMM' || 13987 tok === 'MM' || 13988 tok === 'DD' || 13989 tok === 'dddd' 13990 ) { 13991 return tok.slice(1); 13992 } 13993 return tok; 13994 }) 13995 .join(''); 13996 13997 if (!formatCache) { 13998 formatCache = this._longDateFormatCache = {}; 13999 } 14000 formatCache[key] = { 14001 formatUpper: formatUpper, 14002 format: format, 14003 }; 14004 return format; 14005 } 14006 14007 var defaultInvalidDate = 'Invalid date'; 14008 14009 function invalidDate() { 14010 return this._invalidDate; 14011 } 14012 14013 var defaultOrdinal = '%d', 14014 defaultDayOfMonthOrdinalParse = /\d{1,2}/; 14015 14016 function ordinal(number) { 14017 return this._ordinal.replace('%d', number); 14018 } 14019 14020 var defaultRelativeTime = { 14021 future: 'in %s', 14022 past: '%s ago', 14023 s: 'a few seconds', 14024 ss: '%d seconds', 14025 m: 'a minute', 14026 mm: '%d minutes', 14027 h: 'an hour', 14028 hh: '%d hours', 14029 d: 'a day', 14030 dd: '%d days', 14031 w: 'a week', 14032 ww: '%d weeks', 14033 M: 'a month', 14034 MM: '%d months', 14035 y: 'a year', 14036 yy: '%d years', 14037 }; 14038 14039 function relativeTimeWithoutPostformat( 14040 number, 14041 withoutSuffix, 14042 string, 14043 isFuture 14044 ) { 14045 var output = this._relativeTime[string]; 14046 return isFunction(output) 14047 ? output(number, withoutSuffix, string, isFuture) 14048 : output.replace(/%d/i, number); 14049 } 14050 14051 function relativeTime$1(number, withoutSuffix, string, isFuture) { 14052 return this.postformat( 14053 relativeTimeWithoutPostformat.call( 14054 this, 14055 number, 14056 withoutSuffix, 14057 string, 14058 isFuture 14059 ) 14060 ); 14061 } 14062 14063 function pastFutureWithoutPostformat(diff, output) { 14064 var format = this._relativeTime[diff > 0 ? 'future' : 'past']; 14065 return isFunction(format) ? format(output) : format.replace(/%s/i, output); 14066 } 14067 14068 function pastFuture(diff, output) { 14069 return this.postformat( 14070 pastFutureWithoutPostformat.call(this, diff, output) 14071 ); 14072 } 14073 14074 function createDate(y, m, d, h, M, s, ms) { 14075 // can't just apply() to create a date: 14076 // https://stackoverflow.com/q/181348 14077 var date; 14078 // the date constructor remaps years 0-99 to 1900-1999 14079 if (y < 100 && y >= 0) { 14080 // preserve leap years using a full 400 year cycle, then reset 14081 date = new Date(y + 400, m, d, h, M, s, ms); 14082 if (isFinite(date.getFullYear())) { 14083 date.setFullYear(y); 14084 } 14085 } else { 14086 date = new Date(y, m, d, h, M, s, ms); 14087 } 14088 14089 return date; 14090 } 14091 14092 function createUTCDate(y) { 14093 var date, args; 14094 // the Date.UTC function remaps years 0-99 to 1900-1999 14095 if (y < 100 && y >= 0) { 14096 args = Array.prototype.slice.call(arguments); 14097 // preserve leap years using a full 400 year cycle, then reset 14098 args[0] = y + 400; 14099 date = new Date(Date.UTC.apply(null, args)); 14100 if (isFinite(date.getUTCFullYear())) { 14101 date.setUTCFullYear(y); 14102 } 14103 } else { 14104 date = new Date(Date.UTC.apply(null, arguments)); 14105 } 14106 14107 return date; 14108 } 14109 14110 // start-of-first-week - start-of-year 14111 function firstWeekOffset(year, dow, doy) { 14112 var // first-week day -- which january is always in the first week (4 for iso, 1 for other) 14113 fwd = 7 + dow - doy, 14114 // first-week day local weekday -- which local weekday is fwd 14115 fwdlw = (7 + createUTCDate(year, 0, fwd).getUTCDay() - dow) % 7; 14116 14117 return -fwdlw + fwd - 1; 14118 } 14119 14120 // https://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday 14121 function dayOfYearFromWeeks(year, week, weekday, dow, doy) { 14122 var localWeekday = (7 + weekday - dow) % 7, 14123 weekOffset = firstWeekOffset(year, dow, doy), 14124 dayOfYear = 1 + 7 * (week - 1) + localWeekday + weekOffset, 14125 resYear, 14126 resDayOfYear; 14127 14128 if (dayOfYear <= 0) { 14129 resYear = year - 1; 14130 resDayOfYear = daysInYear(resYear) + dayOfYear; 14131 } else if (dayOfYear > daysInYear(year)) { 14132 resYear = year + 1; 14133 resDayOfYear = dayOfYear - daysInYear(year); 14134 } else { 14135 resYear = year; 14136 resDayOfYear = dayOfYear; 14137 } 14138 14139 return { 14140 year: resYear, 14141 dayOfYear: resDayOfYear, 14142 }; 14143 } 14144 14145 function weekOfYearFromDayOfYear(year, dayOfYear, dow, doy) { 14146 var weekOffset = firstWeekOffset(year, dow, doy), 14147 week = Math.floor((dayOfYear - weekOffset - 1) / 7) + 1, 14148 resWeek, 14149 resYear; 14150 14151 if (week < 1) { 14152 resYear = year - 1; 14153 resWeek = week + weeksInYear(resYear, dow, doy); 14154 } else if (week > weeksInYear(year, dow, doy)) { 14155 resWeek = week - weeksInYear(year, dow, doy); 14156 resYear = year + 1; 14157 } else { 14158 resYear = year; 14159 resWeek = week; 14160 } 14161 14162 return { 14163 week: resWeek, 14164 year: resYear, 14165 }; 14166 } 14167 14168 function weekOfYear(mom, dow, doy) { 14169 return weekOfYearFromDayOfYear(mom.year(), mom.dayOfYear(), dow, doy); 14170 } 14171 14172 function weekOfYearFromDate(year, month, date, dow, doy) { 14173 var dayOfYear = 14174 Math.round( 14175 (createUTCDate(year, month, date) - createUTCDate(year, 0, 1)) / 14176 864e5 14177 ) + 1; 14178 14179 return weekOfYearFromDayOfYear(year, dayOfYear, dow, doy); 14180 } 14181 14182 function weeksInYear(year, dow, doy) { 14183 var weekOffset = firstWeekOffset(year, dow, doy), 14184 weekOffsetNext = firstWeekOffset(year + 1, dow, doy); 14185 return (daysInYear(year) - weekOffset + weekOffsetNext) / 7; 14186 } 14187 14188 // FORMATTING 14189 14190 addFormatToken('w', ['ww', 2], 'wo', 'week'); 14191 addFormatToken('W', ['WW', 2], 'Wo', 'isoWeek'); 14192 14193 // PARSING 14194 14195 addRegexToken('w', match1to2, match1to2NoLeadingZero); 14196 addRegexToken('ww', match1to2, match2); 14197 addRegexToken('W', match1to2, match1to2NoLeadingZero); 14198 addRegexToken('WW', match1to2, match2); 14199 14200 addWeekParseToken( 14201 ['w', 'ww', 'W', 'WW'], 14202 function (input, week, config, token) { 14203 week[token.substr(0, 1)] = toInt(input); 14204 } 14205 ); 14206 14207 // HELPERS 14208 14209 // LOCALES 14210 14211 function localeWeek(mom) { 14212 return weekOfYear(mom, this._week.dow, this._week.doy).week; 14213 } 14214 14215 var defaultLocaleWeek = { 14216 dow: 0, // Sunday is the first day of the week. 14217 doy: 6, // The week that contains Jan 6th is the first week of the year. 14218 }; 14219 14220 function localeFirstDayOfWeek() { 14221 return this._week.dow; 14222 } 14223 14224 function localeFirstDayOfYear() { 14225 return this._week.doy; 14226 } 14227 14228 // MOMENTS 14229 14230 function getSetWeek(input) { 14231 var week = this.localeData().week(this); 14232 return input == null ? week : this.add((input - week) * 7, 'd'); 14233 } 14234 14235 function getSetISOWeek(input) { 14236 var week = weekOfYear(this, 1, 4).week; 14237 return input == null ? week : this.add((input - week) * 7, 'd'); 14238 } 14239 14240 // FORMATTING 14241 14242 function hFormat() { 14243 return this.hours() % 12 || 12; 14244 } 14245 14246 function kFormat() { 14247 return this.hours() || 24; 14248 } 14249 14250 addFormatToken('H', ['HH', 2], 0, 'hour'); 14251 addFormatToken('h', ['hh', 2], 0, hFormat); 14252 addFormatToken('k', ['kk', 2], 0, kFormat); 14253 14254 addFormatToken('hmm', 0, 0, function () { 14255 return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2); 14256 }); 14257 14258 addFormatToken('hmmss', 0, 0, function () { 14259 return ( 14260 '' + 14261 hFormat.apply(this) + 14262 zeroFill(this.minutes(), 2) + 14263 zeroFill(this.seconds(), 2) 14264 ); 14265 }); 14266 14267 addFormatToken('Hmm', 0, 0, function () { 14268 return '' + this.hours() + zeroFill(this.minutes(), 2); 14269 }); 14270 14271 addFormatToken('Hmmss', 0, 0, function () { 14272 return ( 14273 '' + 14274 this.hours() + 14275 zeroFill(this.minutes(), 2) + 14276 zeroFill(this.seconds(), 2) 14277 ); 14278 }); 14279 14280 function meridiem(token, lowercase) { 14281 addFormatToken(token, 0, 0, function () { 14282 return this.localeData().meridiem( 14283 this.hours(), 14284 this.minutes(), 14285 lowercase 14286 ); 14287 }); 14288 } 14289 14290 meridiem('a', true); 14291 meridiem('A', false); 14292 14293 // PARSING 14294 14295 function matchMeridiem(isStrict, locale) { 14296 return locale._meridiemParse; 14297 } 14298 14299 addRegexToken('a', matchMeridiem); 14300 addRegexToken('A', matchMeridiem); 14301 addRegexToken('H', match1to2, match1to2HasZero); 14302 addRegexToken('h', match1to2, match1to2NoLeadingZero); 14303 addRegexToken('k', match1to2, match1to2NoLeadingZero); 14304 addRegexToken('HH', match1to2, match2); 14305 addRegexToken('hh', match1to2, match2); 14306 addRegexToken('kk', match1to2, match2); 14307 14308 addRegexToken('hmm', match3to4); 14309 addRegexToken('hmmss', match5to6); 14310 addRegexToken('Hmm', match3to4); 14311 addRegexToken('Hmmss', match5to6); 14312 14313 addParseToken(['H', 'HH'], HOUR); 14314 addParseToken(['k', 'kk'], function (input, array, config) { 14315 var kInput = toInt(input); 14316 array[HOUR] = kInput === 24 ? 0 : kInput; 14317 }); 14318 addParseToken(['a', 'A'], function (input, array, config) { 14319 config._isPm = config._locale.isPM(input); 14320 config._meridiem = input; 14321 }); 14322 addParseToken(['h', 'hh'], function (input, array, config) { 14323 array[HOUR] = toInt(input); 14324 getParsingFlags(config).bigHour = true; 14325 }); 14326 addParseToken('hmm', function (input, array, config) { 14327 var pos = input.length - 2; 14328 array[HOUR] = toInt(input.substr(0, pos)); 14329 array[MINUTE] = toInt(input.substr(pos)); 14330 getParsingFlags(config).bigHour = true; 14331 }); 14332 addParseToken('hmmss', function (input, array, config) { 14333 var pos1 = input.length - 4, 14334 pos2 = input.length - 2; 14335 array[HOUR] = toInt(input.substr(0, pos1)); 14336 array[MINUTE] = toInt(input.substr(pos1, 2)); 14337 array[SECOND] = toInt(input.substr(pos2)); 14338 getParsingFlags(config).bigHour = true; 14339 }); 14340 addParseToken('Hmm', function (input, array, config) { 14341 var pos = input.length - 2; 14342 array[HOUR] = toInt(input.substr(0, pos)); 14343 array[MINUTE] = toInt(input.substr(pos)); 14344 }); 14345 addParseToken('Hmmss', function (input, array, config) { 14346 var pos1 = input.length - 4, 14347 pos2 = input.length - 2; 14348 array[HOUR] = toInt(input.substr(0, pos1)); 14349 array[MINUTE] = toInt(input.substr(pos1, 2)); 14350 array[SECOND] = toInt(input.substr(pos2)); 14351 }); 14352 14353 // LOCALES 14354 14355 function localeIsPM(input) { 14356 // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays 14357 // Using charAt should be more compatible. 14358 return (input + '').toLowerCase().charAt(0) === 'p'; 14359 } 14360 14361 var defaultLocaleMeridiemParse = /[ap]\.?m?\.?/i, 14362 // Setting the hour should keep the time, because the user explicitly 14363 // specified which hour they want. So trying to maintain the same hour (in 14364 // a new timezone) makes sense. Adding/subtracting hours does not follow 14365 // this rule. 14366 getSetHour = makeGetSet('Hours', true); 14367 14368 function localeMeridiem(hours, minutes, isLower) { 14369 if (hours > 11) { 14370 return isLower ? 'pm' : 'PM'; 14371 } else { 14372 return isLower ? 'am' : 'AM'; 14373 } 14374 } 14375 14376 var baseConfig = { 14377 calendar: defaultCalendar, 14378 longDateFormat: defaultLongDateFormat, 14379 invalidDate: defaultInvalidDate, 14380 ordinal: defaultOrdinal, 14381 dayOfMonthOrdinalParse: defaultDayOfMonthOrdinalParse, 14382 relativeTime: defaultRelativeTime, 14383 14384 months: defaultLocaleMonths, 14385 monthsShort: defaultLocaleMonthsShort, 14386 14387 week: defaultLocaleWeek, 14388 14389 weekdays: defaultLocaleWeekdays, 14390 weekdaysMin: defaultLocaleWeekdaysMin, 14391 weekdaysShort: defaultLocaleWeekdaysShort, 14392 14393 meridiemParse: defaultLocaleMeridiemParse, 14394 }; 14395 14396 // internal storage for locale config files 14397 var locales = {}, 14398 localeFamilies = {}, 14399 globalLocale; 14400 14401 function commonPrefix(arr1, arr2) { 14402 var i, 14403 minl = Math.min(arr1.length, arr2.length); 14404 for (i = 0; i < minl; i += 1) { 14405 if (arr1[i] !== arr2[i]) { 14406 return i; 14407 } 14408 } 14409 return minl; 14410 } 14411 14412 function normalizeLocale(key) { 14413 return key ? key.toLowerCase().replace('_', '-') : key; 14414 } 14415 14416 // pick the locale from the array 14417 // try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each 14418 // substring from most specific to least, but move to the next array item if it's a more specific variant than the current root 14419 function chooseLocale(names) { 14420 var i = 0, 14421 j, 14422 next, 14423 locale, 14424 split; 14425 14426 while (i < names.length) { 14427 split = normalizeLocale(names[i]).split('-'); 14428 j = split.length; 14429 next = normalizeLocale(names[i + 1]); 14430 next = next ? next.split('-') : null; 14431 while (j > 0) { 14432 locale = loadLocale(split.slice(0, j).join('-')); 14433 if (locale) { 14434 return locale; 14435 } 14436 if ( 14437 next && 14438 next.length >= j && 14439 commonPrefix(split, next) >= j - 1 14440 ) { 14441 //the next array item is better than a shallower substring of this one 14442 break; 14443 } 14444 j--; 14445 } 14446 i++; 14447 } 14448 return globalLocale; 14449 } 14450 14451 function isLocaleNameSane(name) { 14452 // Only canonical locale module names are safe to append to the require path. 14453 return typeof name === 'string' && /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(name); 14454 } 14455 14456 function loadLocale(name) { 14457 var oldLocale = null, 14458 aliasedRequire, 14459 normalizedName; 14460 14461 // Preserve exact custom locale names before trying the canonical built-in name. 14462 // Use hasOwnProp rather than a plain lookup so that names like "__proto__", 14463 // "constructor", or "prototype" can't resolve to an inherited Object.prototype 14464 // property instead of a real (or missing) locale entry. 14465 if (hasOwnProp(locales, name)) { 14466 return locales[name]; 14467 } 14468 14469 normalizedName = normalizeLocale(name); 14470 if (hasOwnProp(locales, normalizedName)) { 14471 return locales[normalizedName]; 14472 } 14473 14474 // TODO: Find a better way to register and load all the locales in Node 14475 if ( 14476 typeof module !== 'undefined' && 14477 module && 14478 module.exports && 14479 isLocaleNameSane(normalizedName) 14480 ) { 14481 try { 14482 oldLocale = globalLocale._abbr; 14483 aliasedRequire = require; 14484 aliasedRequire('./locale/' + normalizedName); 14485 getSetGlobalLocale(oldLocale); 14486 } catch (e) { 14487 // mark as not found to avoid repeating expensive file require call causing high CPU 14488 // when trying to find en-US, en_US, en-us for every format call 14489 locales[normalizedName] = null; // null means not found 14490 } 14491 } 14492 if (hasOwnProp(locales, normalizedName)) { 14493 return locales[normalizedName]; 14494 } 14495 } 14496 14497 // This function will load locale and then set the global locale. If 14498 // no arguments are passed in, it will simply return the current global 14499 // locale key. 14500 function getSetGlobalLocale(key, values) { 14501 var data; 14502 if (key) { 14503 if (isUndefined(values)) { 14504 data = getLocale(key); 14505 } else { 14506 data = defineLocale(key, values); 14507 } 14508 14509 if (data) { 14510 // moment.duration._locale = moment._locale = data; 14511 globalLocale = data; 14512 } else { 14513 if (typeof console !== 'undefined' && console.warn) { 14514 //warn user if arguments are passed but the locale could not be set 14515 console.warn( 14516 'Locale ' + key + ' not found. Did you forget to load it?' 14517 ); 14518 } 14519 } 14520 } 14521 14522 return globalLocale._abbr; 14523 } 14524 14525 function defineLocale(name, config) { 14526 if (config !== null) { 14527 var locale, 14528 parentConfig = baseConfig; 14529 config.abbr = name; 14530 if (locales[name] != null) { 14531 deprecateSimple( 14532 'defineLocaleOverride', 14533 'use moment.updateLocale(localeName, config) to change ' + 14534 'an existing locale. moment.defineLocale(localeName, ' + 14535 'config) should only be used for creating a new locale ' + 14536 'See http://momentjs.com/guides/#/warnings/define-locale/ for more info.' 14537 ); 14538 parentConfig = locales[name]._config; 14539 } else if (config.parentLocale != null) { 14540 if (locales[config.parentLocale] != null) { 14541 parentConfig = locales[config.parentLocale]._config; 14542 } else { 14543 locale = loadLocale(config.parentLocale); 14544 if (locale != null) { 14545 parentConfig = locale._config; 14546 } else { 14547 if (!localeFamilies[config.parentLocale]) { 14548 localeFamilies[config.parentLocale] = []; 14549 } 14550 localeFamilies[config.parentLocale].push({ 14551 name: name, 14552 config: config, 14553 }); 14554 return null; 14555 } 14556 } 14557 } 14558 locales[name] = new Locale(mergeConfigs(parentConfig, config)); 14559 14560 if (localeFamilies[name]) { 14561 localeFamilies[name].forEach(function (x) { 14562 defineLocale(x.name, x.config); 14563 }); 14564 } 14565 14566 // backwards compat for now: also set the locale 14567 // make sure we set the locale AFTER all child locales have been 14568 // created, so we won't end up with the child locale set. 14569 getSetGlobalLocale(name); 14570 14571 return locales[name]; 14572 } else { 14573 // useful for testing 14574 delete locales[name]; 14575 return null; 14576 } 14577 } 14578 14579 function updateLocale(name, config) { 14580 var locale, 14581 tmpLocale = loadLocale(name), 14582 parentConfig = baseConfig; 14583 14584 if (tmpLocale != null) { 14585 name = tmpLocale._abbr; 14586 } 14587 14588 if (config != null) { 14589 if (locales[name] != null && locales[name].parentLocale != null) { 14590 // Update existing child locale in-place to avoid memory-leaks 14591 locales[name].set(mergeConfigs(locales[name]._config, config)); 14592 } else { 14593 // MERGE 14594 if (tmpLocale != null) { 14595 parentConfig = tmpLocale._config; 14596 } 14597 config = mergeConfigs(parentConfig, config); 14598 if (tmpLocale == null) { 14599 // updateLocale is called for creating a new locale 14600 // Set abbr so it will have a name (getters return 14601 // undefined otherwise). 14602 config.abbr = name; 14603 } 14604 locale = new Locale(config); 14605 locale.parentLocale = locales[name]; 14606 locales[name] = locale; 14607 } 14608 14609 // backwards compat for now: also set the locale 14610 getSetGlobalLocale(name); 14611 } else { 14612 // pass null for config to unupdate, useful for tests 14613 if (locales[name] != null) { 14614 if (locales[name].parentLocale != null) { 14615 locales[name] = locales[name].parentLocale; 14616 if (name === getSetGlobalLocale()) { 14617 getSetGlobalLocale(name); 14618 } 14619 } else if (locales[name] != null) { 14620 delete locales[name]; 14621 } 14622 } 14623 } 14624 return locales[name]; 14625 } 14626 14627 // returns locale data 14628 function getLocale(key) { 14629 var locale; 14630 14631 if (key && key._locale && key._locale._abbr) { 14632 key = key._locale._abbr; 14633 } 14634 14635 if (!key) { 14636 return globalLocale; 14637 } 14638 14639 if (!isArray(key)) { 14640 //short-circuit everything else 14641 locale = loadLocale(key); 14642 if (locale) { 14643 return locale; 14644 } 14645 key = [key]; 14646 } 14647 14648 return chooseLocale(key); 14649 } 14650 14651 function listLocales() { 14652 return keys(locales); 14653 } 14654 14655 function checkOverflow(m) { 14656 var overflow, 14657 a = m._a; 14658 14659 if (a && getParsingFlags(m).overflow === -2) { 14660 overflow = 14661 a[MONTH] < 0 || a[MONTH] > 11 14662 ? MONTH 14663 : a[DATE] < 1 || a[DATE] > daysInMonth(a[YEAR], a[MONTH]) 14664 ? DATE 14665 : a[HOUR] < 0 || 14666 a[HOUR] > 24 || 14667 (a[HOUR] === 24 && 14668 (a[MINUTE] !== 0 || 14669 a[SECOND] !== 0 || 14670 a[MILLISECOND] !== 0)) 14671 ? HOUR 14672 : a[MINUTE] < 0 || a[MINUTE] > 59 14673 ? MINUTE 14674 : a[SECOND] < 0 || a[SECOND] > 59 14675 ? SECOND 14676 : a[MILLISECOND] < 0 || a[MILLISECOND] > 999 14677 ? MILLISECOND 14678 : -1; 14679 14680 if ( 14681 getParsingFlags(m)._overflowDayOfYear && 14682 (overflow < YEAR || overflow > DATE) 14683 ) { 14684 overflow = DATE; 14685 } 14686 if (getParsingFlags(m)._overflowWeeks && overflow === -1) { 14687 overflow = WEEK; 14688 } 14689 if (getParsingFlags(m)._overflowWeekday && overflow === -1) { 14690 overflow = WEEKDAY; 14691 } 14692 14693 getParsingFlags(m).overflow = overflow; 14694 } 14695 14696 return m; 14697 } 14698 14699 // iso 8601 regex 14700 // 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) 14701 var extendedIsoRegex = 14702 /^\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)?)?$/, 14703 basicIsoRegex = 14704 /^\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)?)?$/, 14705 tzRegex = /Z|[+-]\d\d(?::?\d\d)?/, 14706 isoDates = [ 14707 ['YYYYYY-MM-DD', /[+-]\d{6}-\d\d-\d\d/], 14708 ['YYYY-MM-DD', /\d{4}-\d\d-\d\d/], 14709 ['GGGG-[W]WW-E', /\d{4}-W\d\d-\d/], 14710 ['GGGG-[W]WW', /\d{4}-W\d\d/, false], 14711 ['YYYY-DDD', /\d{4}-\d{3}/], 14712 ['YYYY-MM', /\d{4}-\d\d/, false], 14713 ['YYYYYYMMDD', /[+-]\d{10}/], 14714 ['YYYYMMDD', /\d{8}/], 14715 ['GGGG[W]WWE', /\d{4}W\d{3}/], 14716 ['GGGG[W]WW', /\d{4}W\d{2}/, false], 14717 ['YYYYDDD', /\d{7}/], 14718 ['YYYYMM', /\d{6}/, false], 14719 ['YYYY', /\d{4}/, false], 14720 ], 14721 // iso time formats and regexes 14722 isoTimes = [ 14723 ['HH:mm:ss.SSSS', /\d\d:\d\d:\d\d\.\d+/], 14724 ['HH:mm:ss,SSSS', /\d\d:\d\d:\d\d,\d+/], 14725 ['HH:mm:ss', /\d\d:\d\d:\d\d/], 14726 ['HH:mm', /\d\d:\d\d/], 14727 ['HHmmss.SSSS', /\d\d\d\d\d\d\.\d+/], 14728 ['HHmmss,SSSS', /\d\d\d\d\d\d,\d+/], 14729 ['HHmmss', /\d\d\d\d\d\d/], 14730 ['HHmm', /\d\d\d\d/], 14731 ['HH', /\d\d/], 14732 ], 14733 aspNetJsonRegex = /^\/?Date\((-?\d+)/i, 14734 // RFC 2822 regex: For details see https://tools.ietf.org/html/rfc2822#section-3.3 14735 rfc2822 = 14736 /^(?:(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}))$/, 14737 obsOffsets = { 14738 UT: 0, 14739 GMT: 0, 14740 EDT: -4 * 60, 14741 EST: -5 * 60, 14742 CDT: -5 * 60, 14743 CST: -6 * 60, 14744 MDT: -6 * 60, 14745 MST: -7 * 60, 14746 PDT: -7 * 60, 14747 PST: -8 * 60, 14748 }; 14749 14750 // date from iso format 14751 function configFromISO(config) { 14752 var i, 14753 l, 14754 string = config._i, 14755 match = extendedIsoRegex.exec(string) || basicIsoRegex.exec(string), 14756 allowTime, 14757 dateFormat, 14758 timeFormat, 14759 tzFormat, 14760 isoDatesLen = isoDates.length, 14761 isoTimesLen = isoTimes.length; 14762 14763 if (match) { 14764 getParsingFlags(config).iso = true; 14765 for (i = 0, l = isoDatesLen; i < l; i++) { 14766 if (isoDates[i][1].exec(match[1])) { 14767 dateFormat = isoDates[i][0]; 14768 allowTime = isoDates[i][2] !== false; 14769 break; 14770 } 14771 } 14772 if (dateFormat == null) { 14773 config._isValid = false; 14774 return; 14775 } 14776 if (match[3]) { 14777 for (i = 0, l = isoTimesLen; i < l; i++) { 14778 if (isoTimes[i][1].exec(match[3])) { 14779 // match[2] should be 'T' or space 14780 timeFormat = (match[2] || ' ') + isoTimes[i][0]; 14781 break; 14782 } 14783 } 14784 if (timeFormat == null) { 14785 config._isValid = false; 14786 return; 14787 } 14788 } 14789 if (!allowTime && timeFormat != null) { 14790 config._isValid = false; 14791 return; 14792 } 14793 if (match[4]) { 14794 if (tzRegex.exec(match[4])) { 14795 tzFormat = 'Z'; 14796 } else { 14797 config._isValid = false; 14798 return; 14799 } 14800 } 14801 config._f = dateFormat + (timeFormat || '') + (tzFormat || ''); 14802 configFromStringAndFormat(config); 14803 } else { 14804 config._isValid = false; 14805 } 14806 } 14807 14808 function extractFromRFC2822Strings( 14809 yearStr, 14810 monthStr, 14811 dayStr, 14812 hourStr, 14813 minuteStr, 14814 secondStr 14815 ) { 14816 var result = [ 14817 untruncateYear(yearStr), 14818 defaultLocaleMonthsShort.indexOf(monthStr), 14819 parseInt(dayStr, 10), 14820 parseInt(hourStr, 10), 14821 parseInt(minuteStr, 10), 14822 ]; 14823 14824 if (secondStr) { 14825 result.push(parseInt(secondStr, 10)); 14826 } 14827 14828 return result; 14829 } 14830 14831 function untruncateYear(yearStr) { 14832 var year = parseInt(yearStr, 10); 14833 if (year <= 49) { 14834 return 2000 + year; 14835 } else if (year <= 999) { 14836 return 1900 + year; 14837 } 14838 return year; 14839 } 14840 14841 function preprocessRFC2822(s) { 14842 // Remove comments and folding whitespace and replace multiple-spaces with a single space 14843 return s 14844 .replace(/\([^()]*\)|[\n\t]/g, ' ') 14845 .replace(/(\s\s+)/g, ' ') 14846 .replace(/^\s\s*/, '') 14847 .replace(/\s\s*$/, ''); 14848 } 14849 14850 function checkWeekday(weekdayStr, parsedInput, config) { 14851 if (weekdayStr) { 14852 // TODO: Replace the vanilla JS Date object with an independent day-of-week check. 14853 var weekdayProvided = defaultLocaleWeekdaysShort.indexOf(weekdayStr), 14854 weekdayActual = new Date( 14855 parsedInput[0], 14856 parsedInput[1], 14857 parsedInput[2] 14858 ).getDay(); 14859 if (weekdayProvided !== weekdayActual) { 14860 getParsingFlags(config).weekdayMismatch = true; 14861 config._isValid = false; 14862 return false; 14863 } 14864 } 14865 return true; 14866 } 14867 14868 function calculateOffset(obsOffset, militaryOffset, numOffset) { 14869 if (obsOffset) { 14870 return obsOffsets[obsOffset]; 14871 } else if (militaryOffset) { 14872 // the only allowed military tz is Z 14873 return 0; 14874 } else { 14875 var hm = parseInt(numOffset, 10), 14876 m = hm % 100, 14877 h = (hm - m) / 100; 14878 return h * 60 + m; 14879 } 14880 } 14881 14882 // date and time from ref 2822 format 14883 function configFromRFC2822(config) { 14884 var match = rfc2822.exec(preprocessRFC2822(config._i)), 14885 parsedArray; 14886 if (match) { 14887 parsedArray = extractFromRFC2822Strings( 14888 match[4], 14889 match[3], 14890 match[2], 14891 match[5], 14892 match[6], 14893 match[7] 14894 ); 14895 if (!checkWeekday(match[1], parsedArray, config)) { 14896 return; 14897 } 14898 14899 config._a = parsedArray; 14900 config._tzm = calculateOffset(match[8], match[9], match[10]); 14901 14902 config._d = createUTCDate.apply(null, config._a); 14903 config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm); 14904 14905 getParsingFlags(config).rfc2822 = true; 14906 } else { 14907 config._isValid = false; 14908 } 14909 } 14910 14911 // date from 1) ASP.NET, 2) ISO, 3) RFC 2822 formats, or 4) optional fallback if parsing isn't strict 14912 function configFromString(config) { 14913 var matched = aspNetJsonRegex.exec(config._i); 14914 if (matched !== null) { 14915 config._d = new Date(+matched[1]); 14916 return; 14917 } 14918 14919 configFromISO(config); 14920 if (config._isValid === false) { 14921 delete config._isValid; 14922 } else { 14923 return; 14924 } 14925 14926 configFromRFC2822(config); 14927 if (config._isValid === false) { 14928 delete config._isValid; 14929 } else { 14930 return; 14931 } 14932 14933 if (config._strict) { 14934 config._isValid = false; 14935 } else { 14936 // Final attempt, use Input Fallback 14937 hooks.createFromInputFallback(config); 14938 } 14939 } 14940 14941 hooks.createFromInputFallback = deprecate( 14942 'value provided is not in a recognized RFC2822 or ISO format. moment construction falls back to js Date(), ' + 14943 'which is not reliable across all browsers and versions. Non RFC2822/ISO date formats are ' + 14944 'discouraged. Please refer to http://momentjs.com/guides/#/warnings/js-date/ for more info.', 14945 function (config) { 14946 config._d = new Date(config._i + (config._useUTC ? ' UTC' : '')); 14947 } 14948 ); 14949 14950 // Pick the first defined of two or three arguments. 14951 function defaults(a, b, c) { 14952 if (a != null) { 14953 return a; 14954 } 14955 if (b != null) { 14956 return b; 14957 } 14958 return c; 14959 } 14960 14961 function currentDateArray(config, now, forWeek) { 14962 var hadWeekContext = Object.prototype.hasOwnProperty.call( 14963 config, 14964 '_isDefaultDatePartsForWeek' 14965 ), 14966 weekContext = config._isDefaultDatePartsForWeek; 14967 14968 // hooks is actually the exported moment object 14969 config._isDefaultDatePartsForWeek = !!forWeek; 14970 try { 14971 return hooks._getDefaultDateParts(config, now, forWeek); 14972 } finally { 14973 if (hadWeekContext) { 14974 config._isDefaultDatePartsForWeek = weekContext; 14975 } else { 14976 delete config._isDefaultDatePartsForWeek; 14977 } 14978 } 14979 } 14980 14981 function currentDateNow(config) { 14982 var now = config._defaultDatePartsNow; 14983 14984 if (!now) { 14985 return hooks.now(); 14986 } 14987 if (!now.hasValue) { 14988 now.value = hooks.now(); 14989 now.hasValue = true; 14990 } 14991 return now.value; 14992 } 14993 14994 // Internal hook for extensions that supply omitted calendar fields. 14995 function getDefaultDateParts(config, now, forWeek) { 14996 var useWeekDefaults = forWeek || config._isDefaultDatePartsForWeek, 14997 nowValue = useWeekDefaults ? createLocal(now) : new Date(now); 14998 if (useWeekDefaults) { 14999 return [nowValue.year(), nowValue.month(), nowValue.date()]; 15000 } 15001 if (config._useUTC) { 15002 return [ 15003 nowValue.getUTCFullYear(), 15004 nowValue.getUTCMonth(), 15005 nowValue.getUTCDate(), 15006 ]; 15007 } 15008 return [nowValue.getFullYear(), nowValue.getMonth(), nowValue.getDate()]; 15009 } 15010 15011 hooks._getDefaultDateParts = getDefaultDateParts; 15012 15013 // convert an array to a date. 15014 // the array should mirror the parameters below 15015 // note: all values past the year are optional and will default to the lowest possible value. 15016 // [year, month, day , hour, minute, second, millisecond] 15017 function configFromArray(config) { 15018 var i, 15019 date, 15020 input = [], 15021 now, 15022 currentDate, 15023 expectedWeekday, 15024 yearToUse, 15025 dateIsDefaulted; 15026 15027 if (config._d) { 15028 return; 15029 } 15030 15031 if ( 15032 config._a[YEAR] == null || 15033 config._a[MONTH] == null || 15034 config._a[DATE] == null 15035 ) { 15036 now = currentDateNow(config); 15037 currentDate = currentDateArray(config, now); 15038 } 15039 15040 //compute day of the year from weeks and weekdays 15041 if (config._w && config._a[DATE] == null && config._a[MONTH] == null) { 15042 dayOfYearFromWeekInfo(config, currentDateArray(config, now, true)); 15043 } 15044 15045 //if the day of the year is set, figure out what it is 15046 if (config._dayOfYear != null) { 15047 yearToUse = 15048 config._a[YEAR] != null ? config._a[YEAR] : currentDate[YEAR]; 15049 15050 if ( 15051 config._dayOfYear > daysInYear(yearToUse) || 15052 config._dayOfYear === 0 15053 ) { 15054 getParsingFlags(config)._overflowDayOfYear = true; 15055 } 15056 15057 date = createUTCDate(yearToUse, 0, config._dayOfYear); 15058 config._a[MONTH] = date.getUTCMonth(); 15059 config._a[DATE] = date.getUTCDate(); 15060 } 15061 15062 dateIsDefaulted = 15063 config._a[YEAR] == null || 15064 config._a[MONTH] == null || 15065 config._a[DATE] == null; 15066 15067 // Default to current date. 15068 // * if no year, month, day of month are given, default to today 15069 // * if day of month is given, default month and year 15070 // * if month is given, default only year 15071 // * if year is given, don't default anything 15072 for (i = 0; i < 3 && config._a[i] == null; ++i) { 15073 config._a[i] = input[i] = currentDate[i]; 15074 } 15075 15076 // Zero out whatever was not defaulted, including time 15077 for (; i < 7; i++) { 15078 config._a[i] = input[i] = 15079 config._a[i] == null ? (i === 2 ? 1 : 0) : config._a[i]; 15080 } 15081 15082 // Check for 24:00:00.000 15083 if ( 15084 config._a[HOUR] === 24 && 15085 config._a[MINUTE] === 0 && 15086 config._a[SECOND] === 0 && 15087 config._a[MILLISECOND] === 0 15088 ) { 15089 config._nextDay = true; 15090 config._a[HOUR] = 0; 15091 } 15092 15093 config._d = (config._useUTC ? createUTCDate : createDate).apply( 15094 null, 15095 input 15096 ); 15097 expectedWeekday = config._useUTC 15098 ? config._d.getUTCDay() 15099 : config._d.getDay(); 15100 15101 // Apply timezone offset from input. The actual utcOffset can be changed 15102 // with parseZone. 15103 if (config._tzm != null) { 15104 config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm); 15105 } 15106 15107 if (config._nextDay) { 15108 config._a[HOUR] = 24; 15109 } 15110 15111 // check for mismatching day of week 15112 if ( 15113 config._w && 15114 typeof config._w.d !== 'undefined' && 15115 !dateIsDefaulted && 15116 config._w.d !== expectedWeekday 15117 ) { 15118 getParsingFlags(config).weekdayMismatch = true; 15119 } 15120 } 15121 15122 function dayOfYearFromWeekInfo(config, currentDate) { 15123 var w, weekYear, week, weekday, dow, doy, temp, weekdayOverflow, curWeek; 15124 15125 w = config._w; 15126 if (w.GG != null || w.W != null || w.E != null) { 15127 dow = 1; 15128 doy = 4; 15129 15130 // TODO: We need to take the current isoWeekYear, but that depends on 15131 // how we interpret now (local, utc, fixed offset). So create 15132 // a now version of current config (take local/utc/offset flags, and 15133 // create now). 15134 weekYear = defaults( 15135 w.GG, 15136 config._a[YEAR], 15137 weekOfYearFromDate( 15138 currentDate[YEAR], 15139 currentDate[MONTH], 15140 currentDate[DATE], 15141 1, 15142 4 15143 ).year 15144 ); 15145 week = defaults(w.W, 1); 15146 weekday = defaults(w.E, 1); 15147 if (weekday < 1 || weekday > 7) { 15148 weekdayOverflow = true; 15149 } 15150 } else { 15151 dow = config._locale._week.dow; 15152 doy = config._locale._week.doy; 15153 15154 curWeek = weekOfYearFromDate( 15155 currentDate[YEAR], 15156 currentDate[MONTH], 15157 currentDate[DATE], 15158 dow, 15159 doy 15160 ); 15161 15162 weekYear = defaults(w.gg, config._a[YEAR], curWeek.year); 15163 15164 // Default to current week. 15165 week = defaults(w.w, curWeek.week); 15166 15167 if (w.d != null) { 15168 // weekday -- low day numbers are considered next week 15169 weekday = w.d; 15170 if (weekday < 0 || weekday > 6) { 15171 weekdayOverflow = true; 15172 } 15173 } else if (w.e != null) { 15174 // local weekday -- counting starts from beginning of week 15175 weekday = w.e + dow; 15176 if (w.e < 0 || w.e > 6) { 15177 weekdayOverflow = true; 15178 } 15179 } else { 15180 // default to beginning of week 15181 weekday = dow; 15182 } 15183 } 15184 if (week < 1 || week > weeksInYear(weekYear, dow, doy)) { 15185 getParsingFlags(config)._overflowWeeks = true; 15186 } else if (weekdayOverflow != null) { 15187 getParsingFlags(config)._overflowWeekday = true; 15188 } else { 15189 temp = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy); 15190 config._a[YEAR] = temp.year; 15191 config._dayOfYear = temp.dayOfYear; 15192 } 15193 } 15194 15195 // constant that refers to the ISO standard 15196 hooks.ISO_8601 = function () {}; 15197 15198 // constant that refers to the RFC 2822 form 15199 hooks.RFC_2822 = function () {}; 15200 15201 // date from string and format string 15202 function configFromStringAndFormat(config) { 15203 // TODO: Move this to another part of the creation flow to prevent circular deps 15204 if (config._f === hooks.ISO_8601) { 15205 configFromISO(config); 15206 return; 15207 } 15208 if (config._f === hooks.RFC_2822) { 15209 configFromRFC2822(config); 15210 return; 15211 } 15212 config._a = []; 15213 getParsingFlags(config).empty = true; 15214 15215 // This array is used to make a Date, either with `new Date` or `Date.UTC` 15216 var string = '' + config._i, 15217 i, 15218 parsedInput, 15219 tokens, 15220 token, 15221 skipped, 15222 stringLength = string.length, 15223 totalParsedInputLength = 0, 15224 era, 15225 tokenLen; 15226 15227 tokens = 15228 expandFormat(config._f, config._locale).match(formattingTokens) || []; 15229 tokenLen = tokens.length; 15230 for (i = 0; i < tokenLen; i++) { 15231 token = tokens[i]; 15232 parsedInput = (string.match(getParseRegexForToken(token, config)) || 15233 [])[0]; 15234 if (parsedInput) { 15235 skipped = string.substr(0, string.indexOf(parsedInput)); 15236 if (skipped.length > 0) { 15237 getParsingFlags(config).unusedInput.push(skipped); 15238 } 15239 string = string.slice( 15240 string.indexOf(parsedInput) + parsedInput.length 15241 ); 15242 totalParsedInputLength += parsedInput.length; 15243 } 15244 // don't parse if it's not a known token 15245 if (formatTokenFunctions[token]) { 15246 if (parsedInput) { 15247 getParsingFlags(config).empty = false; 15248 } else { 15249 getParsingFlags(config).unusedTokens.push(token); 15250 } 15251 addTimeToArrayFromToken(token, parsedInput, config); 15252 } else if (config._strict && !parsedInput) { 15253 getParsingFlags(config).unusedTokens.push(token); 15254 } 15255 } 15256 15257 // add remaining unparsed input length to the string 15258 getParsingFlags(config).charsLeftOver = 15259 stringLength - totalParsedInputLength; 15260 if (string.length > 0) { 15261 getParsingFlags(config).unusedInput.push(string); 15262 } 15263 15264 // clear _12h flag if hour is <= 12 15265 if ( 15266 config._a[HOUR] <= 12 && 15267 getParsingFlags(config).bigHour === true && 15268 config._a[HOUR] > 0 15269 ) { 15270 getParsingFlags(config).bigHour = undefined; 15271 } 15272 15273 getParsingFlags(config).parsedDateParts = config._a.slice(0); 15274 getParsingFlags(config).meridiem = config._meridiem; 15275 // handle meridiem 15276 config._a[HOUR] = meridiemFixWrap( 15277 config._locale, 15278 config._a[HOUR], 15279 config._meridiem 15280 ); 15281 15282 // handle era 15283 era = getParsingFlags(config).era; 15284 if (era !== null) { 15285 config._a[YEAR] = config._locale.erasConvertYear(era, config._a[YEAR]); 15286 } 15287 15288 configFromArray(config); 15289 checkOverflow(config); 15290 } 15291 15292 function meridiemFixWrap(locale, hour, meridiem) { 15293 var isPm; 15294 15295 if (meridiem == null) { 15296 // nothing to do 15297 return hour; 15298 } 15299 if (locale.meridiemHour != null) { 15300 return locale.meridiemHour(hour, meridiem); 15301 } else if (locale.isPM != null) { 15302 // Fallback 15303 isPm = locale.isPM(meridiem); 15304 if (isPm && hour < 12) { 15305 hour += 12; 15306 } 15307 if (!isPm && hour === 12) { 15308 hour = 0; 15309 } 15310 return hour; 15311 } else { 15312 // this is not supposed to happen 15313 return hour; 15314 } 15315 } 15316 15317 // date from string and array of format strings 15318 function configFromStringAndArray(config) { 15319 var tempConfig, 15320 bestMoment, 15321 scoreToBeat, 15322 i, 15323 currentScore, 15324 validFormatFound, 15325 bestFormatIsValid = false, 15326 defaultDatePartsNow = {}, 15327 configfLen = config._f.length; 15328 15329 if (configfLen === 0) { 15330 getParsingFlags(config).invalidFormat = true; 15331 config._d = new Date(NaN); 15332 return; 15333 } 15334 15335 for (i = 0; i < configfLen; i++) { 15336 currentScore = 0; 15337 validFormatFound = false; 15338 tempConfig = copyConfig({}, config); 15339 if (config._useUTC != null) { 15340 tempConfig._useUTC = config._useUTC; 15341 } 15342 tempConfig._defaultDatePartsNow = defaultDatePartsNow; 15343 tempConfig._f = config._f[i]; 15344 configFromStringAndFormat(tempConfig); 15345 15346 if (isValid$2(tempConfig)) { 15347 validFormatFound = true; 15348 } 15349 15350 // if there is any input that was not parsed add a penalty for that format 15351 currentScore += getParsingFlags(tempConfig).charsLeftOver; 15352 15353 //or tokens 15354 currentScore += getParsingFlags(tempConfig).unusedTokens.length * 10; 15355 15356 getParsingFlags(tempConfig).score = currentScore; 15357 15358 if (!bestFormatIsValid) { 15359 if ( 15360 scoreToBeat == null || 15361 currentScore < scoreToBeat || 15362 validFormatFound 15363 ) { 15364 scoreToBeat = currentScore; 15365 bestMoment = tempConfig; 15366 if (validFormatFound) { 15367 bestFormatIsValid = true; 15368 } 15369 } 15370 } else { 15371 if (currentScore < scoreToBeat) { 15372 scoreToBeat = currentScore; 15373 bestMoment = tempConfig; 15374 } 15375 } 15376 } 15377 15378 extend(config, bestMoment || tempConfig); 15379 } 15380 15381 function configFromObject(config) { 15382 if (config._d) { 15383 return; 15384 } 15385 15386 var i = normalizeObjectUnits(config._i), 15387 dayOrDate = i.day === undefined ? i.date : i.day; 15388 config._a = map( 15389 [i.year, i.month, dayOrDate, i.hour, i.minute, i.second, i.millisecond], 15390 function (obj) { 15391 return obj && parseInt(obj, 10); 15392 } 15393 ); 15394 15395 configFromArray(config); 15396 } 15397 15398 function createFromConfig(config) { 15399 var res = new Moment(checkOverflow(prepareConfig(config))); 15400 if (res._nextDay) { 15401 // Adding is smart enough around DST 15402 res.add(1, 'd'); 15403 res._nextDay = undefined; 15404 } 15405 15406 return res; 15407 } 15408 15409 function prepareConfig(config) { 15410 var input = config._i, 15411 format = config._f; 15412 15413 config._locale = config._locale || getLocale(config._l); 15414 15415 if (input === null || (format === undefined && input === '')) { 15416 return createInvalid$1({ nullInput: true }); 15417 } 15418 15419 if (typeof input === 'string') { 15420 config._i = input = config._locale.preparse(input); 15421 } 15422 15423 if (isMoment(input)) { 15424 return new Moment(checkOverflow(input)); 15425 } else if (isDate(input)) { 15426 config._d = input; 15427 } else if (isArray(format)) { 15428 configFromStringAndArray(config); 15429 } else if (format) { 15430 configFromStringAndFormat(config); 15431 } else { 15432 configFromInput(config); 15433 } 15434 15435 if (!isValid$2(config)) { 15436 config._d = null; 15437 } 15438 15439 return config; 15440 } 15441 15442 function configFromInput(config) { 15443 var input = config._i; 15444 if (isUndefined(input)) { 15445 config._d = new Date(hooks.now()); 15446 } else if (isDate(input)) { 15447 config._d = new Date(input.valueOf()); 15448 } else if (typeof input === 'string') { 15449 configFromString(config); 15450 } else if (isArray(input)) { 15451 config._a = map(input.slice(0), function (obj) { 15452 return parseInt(obj, 10); 15453 }); 15454 configFromArray(config); 15455 } else if (isObject(input)) { 15456 configFromObject(config); 15457 } else if (isNumber(input)) { 15458 // from milliseconds 15459 config._d = new Date(input); 15460 } else { 15461 hooks.createFromInputFallback(config); 15462 } 15463 } 15464 15465 function createLocalOrUTC(input, format, locale, strict, isUTC) { 15466 var c = {}; 15467 15468 if (format === true || format === false) { 15469 strict = format; 15470 format = undefined; 15471 } 15472 15473 if (locale === true || locale === false) { 15474 strict = locale; 15475 locale = undefined; 15476 } 15477 15478 if ( 15479 (isObject(input) && isObjectEmpty(input)) || 15480 (isArray(input) && input.length === 0) 15481 ) { 15482 input = undefined; 15483 } 15484 // object construction must be done this way. 15485 // https://github.com/moment/moment/issues/1423 15486 c._isAMomentObject = true; 15487 c._useUTC = c._isUTC = isUTC; 15488 c._l = locale; 15489 c._i = input; 15490 c._f = format; 15491 c._strict = strict; 15492 15493 return createFromConfig(c); 15494 } 15495 15496 function createLocal(input, format, locale, strict) { 15497 return createLocalOrUTC(input, format, locale, strict, false); 15498 } 15499 15500 var prototypeMin = deprecate( 15501 'moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/', 15502 function () { 15503 var other = createLocal.apply(null, arguments); 15504 if (this.isValid() && other.isValid()) { 15505 return other < this ? this : other; 15506 } else { 15507 return createInvalid$1(); 15508 } 15509 } 15510 ), 15511 prototypeMax = deprecate( 15512 'moment().max is deprecated, use moment.min instead. http://momentjs.com/guides/#/warnings/min-max/', 15513 function () { 15514 var other = createLocal.apply(null, arguments); 15515 if (this.isValid() && other.isValid()) { 15516 return other > this ? this : other; 15517 } else { 15518 return createInvalid$1(); 15519 } 15520 } 15521 ); 15522 15523 // Pick a moment m from moments so that m[fn](other) is true for all 15524 // other. This relies on the function fn to be transitive. 15525 // 15526 // moments should either be an array of moment objects or an array, whose 15527 // first element is an array of moment objects. 15528 function pickBy(fn, moments) { 15529 var res, i; 15530 if (moments.length === 1 && isArray(moments[0])) { 15531 moments = moments[0]; 15532 } 15533 if (!moments.length) { 15534 return createLocal(); 15535 } 15536 for (i = 0; i < moments.length; ++i) { 15537 if (isMoment(moments[i])) { 15538 res = moments[i]; 15539 break; 15540 } 15541 } 15542 if (!res) { 15543 return createInvalid$1(); 15544 } 15545 for (++i; i < moments.length; ++i) { 15546 if ( 15547 isMoment(moments[i]) && 15548 (!moments[i].isValid() || moments[i][fn](res)) 15549 ) { 15550 res = moments[i]; 15551 } 15552 } 15553 return res; 15554 } 15555 15556 // TODO: Use [].sort instead? 15557 function min() { 15558 var args = [].slice.call(arguments, 0); 15559 15560 return pickBy('isBefore', args); 15561 } 15562 15563 function max() { 15564 var args = [].slice.call(arguments, 0); 15565 15566 return pickBy('isAfter', args); 15567 } 15568 15569 var now = function () { 15570 return Date.now ? Date.now() : +new Date(); 15571 }; 15572 15573 var ordering = [ 15574 'year', 15575 'quarter', 15576 'month', 15577 'week', 15578 'day', 15579 'hour', 15580 'minute', 15581 'second', 15582 'millisecond', 15583 ]; 15584 15585 function isDurationValid(m) { 15586 var key, 15587 unitHasDecimal = false, 15588 i, 15589 orderLen = ordering.length; 15590 for (key in m) { 15591 if ( 15592 hasOwnProp(m, key) && 15593 !( 15594 indexOf.call(ordering, key) !== -1 && 15595 (m[key] == null || !isNaN(m[key])) 15596 ) 15597 ) { 15598 return false; 15599 } 15600 } 15601 15602 for (i = 0; i < orderLen; ++i) { 15603 if (m[ordering[i]]) { 15604 if (unitHasDecimal) { 15605 return false; // only allow non-integers for smallest unit 15606 } 15607 if (parseFloat(m[ordering[i]]) !== toInt(m[ordering[i]])) { 15608 unitHasDecimal = true; 15609 } 15610 } 15611 } 15612 15613 return true; 15614 } 15615 15616 function isValid$1() { 15617 return this._isValid; 15618 } 15619 15620 function createInvalid() { 15621 return createDuration(NaN); 15622 } 15623 15624 function Duration(duration) { 15625 var normalizedInput = normalizeObjectUnits(duration), 15626 years = normalizedInput.year || 0, 15627 quarters = normalizedInput.quarter || 0, 15628 months = normalizedInput.month || 0, 15629 weeks = normalizedInput.week || normalizedInput.isoWeek || 0, 15630 days = normalizedInput.day || 0, 15631 hours = normalizedInput.hour || 0, 15632 minutes = normalizedInput.minute || 0, 15633 seconds = normalizedInput.second || 0, 15634 milliseconds = normalizedInput.millisecond || 0; 15635 15636 this._isValid = isDurationValid(normalizedInput); 15637 15638 // representation for dateAddRemove 15639 this._milliseconds = 15640 +milliseconds + 15641 seconds * 1e3 + // 1000 15642 minutes * 6e4 + // 1000 * 60 15643 hours * 1000 * 60 * 60; //using 1000 * 60 * 60 instead of 36e5 to avoid floating point rounding errors https://github.com/moment/moment/issues/2978 15644 // Because of dateAddRemove treats 24 hours as different from a 15645 // day when working around DST, we need to store them separately 15646 this._days = +days + weeks * 7; 15647 // It is impossible to translate months into days without knowing 15648 // which months you are are talking about, so we have to store 15649 // it separately. 15650 this._months = +months + quarters * 3 + years * 12; 15651 15652 this._data = {}; 15653 15654 this._locale = getLocale(); 15655 15656 this._bubble(); 15657 } 15658 15659 function isDuration(obj) { 15660 return obj instanceof Duration; 15661 } 15662 15663 function absRound(number) { 15664 if (number < 0) { 15665 return Math.round(-1 * number) * -1; 15666 } else { 15667 return Math.round(number); 15668 } 15669 } 15670 15671 // compare two arrays, return the number of differences 15672 function compareArrays(array1, array2, dontConvert) { 15673 var len = Math.min(array1.length, array2.length), 15674 lengthDiff = Math.abs(array1.length - array2.length), 15675 diffs = 0, 15676 i; 15677 for (i = 0; i < len; i++) { 15678 if ( 15679 (toInt(array1[i]) !== toInt(array2[i])) 15680 ) { 15681 diffs++; 15682 } 15683 } 15684 return diffs + lengthDiff; 15685 } 15686 15687 // FORMATTING 15688 15689 function offset(token, separator) { 15690 addFormatToken(token, 0, 0, function () { 15691 var offset = this.utcOffset(), 15692 sign = '+'; 15693 if (offset < 0) { 15694 offset = -offset; 15695 sign = '-'; 15696 } 15697 return ( 15698 sign + 15699 zeroFill(~~(offset / 60), 2) + 15700 separator + 15701 zeroFill(~~offset % 60, 2) 15702 ); 15703 }); 15704 } 15705 15706 offset('Z', ':'); 15707 offset('ZZ', ''); 15708 15709 // PARSING 15710 15711 addRegexToken('Z', matchShortOffset); 15712 addRegexToken('ZZ', matchShortOffset); 15713 addParseToken(['Z', 'ZZ'], function (input, array, config) { 15714 var offset = offsetFromString(matchShortOffset, input); 15715 config._useUTC = true; 15716 config._tzm = offset; 15717 if (offset === null) { 15718 getParsingFlags(config).invalidOffset = input; 15719 } 15720 }); 15721 15722 // HELPERS 15723 15724 // timezone chunker 15725 // '+10:00' > ['10', '00'] 15726 // '-1530' > ['-15', '30'] 15727 var chunkOffset = /([\+\-]|\d\d)/gi; 15728 15729 function offsetFromString(matcher, string) { 15730 var matches = (string || '').match(matcher), 15731 chunk, 15732 parts, 15733 minutes; 15734 15735 if (matches === null) { 15736 return null; 15737 } 15738 15739 chunk = matches[matches.length - 1] || []; 15740 parts = (chunk + '').match(chunkOffset) || ['-', 0, 0]; 15741 minutes = +(parts[1] * 60) + toInt(parts[2]); 15742 15743 if ( 15744 toInt(parts[2]) > 59 || 15745 (parts[0] === '+' ? minutes > 14 * 60 : minutes > 12 * 60) 15746 ) { 15747 return null; 15748 } 15749 15750 return minutes === 0 ? 0 : parts[0] === '+' ? minutes : -minutes; 15751 } 15752 15753 // Return a moment from input, that is local/utc/zone equivalent to model. 15754 function cloneWithOffset(input, model) { 15755 var res, diff; 15756 if (model._isUTC) { 15757 res = model.clone(); 15758 diff = 15759 (isMoment(input) || isDate(input) 15760 ? input.valueOf() 15761 : createLocal(input).valueOf()) - res.valueOf(); 15762 // Use low-level api, because this fn is low-level api. 15763 res._d.setTime(res._d.valueOf() + diff); 15764 hooks.updateOffset(res, false); 15765 return res; 15766 } else { 15767 return createLocal(input).local(); 15768 } 15769 } 15770 15771 function getDateOffset(m) { 15772 // On Firefox.24 Date#getTimezoneOffset returns a floating point. 15773 // https://github.com/moment/moment/pull/1871 15774 return -Math.round(m._d.getTimezoneOffset()); 15775 } 15776 15777 // HOOKS 15778 15779 // This function will be called whenever a moment is mutated. 15780 // It is intended to keep the offset in sync with the timezone. 15781 hooks.updateOffset = function () {}; 15782 15783 // MOMENTS 15784 15785 // keepLocalTime = true means only change the timezone, without 15786 // affecting the local hour. So 5:31:26 +0300 --[utcOffset(2, true)]--> 15787 // 5:31:26 +0200 It is possible that 5:31:26 doesn't exist with offset 15788 // +0200, so we adjust the time as needed, to be valid. 15789 // 15790 // Keeping the time actually adds/subtracts (one hour) 15791 // from the actual represented time. That is why we call updateOffset 15792 // a second time. In case it wants us to change the offset again 15793 // _changeInProgress == true case, then we have to adjust, because 15794 // there is no such time in the given timezone. 15795 function getSetOffset(input, keepLocalTime, keepMinutes) { 15796 var offset = this._offset || 0, 15797 localAdjust; 15798 if (!this.isValid()) { 15799 return input != null ? this : NaN; 15800 } 15801 if (input != null) { 15802 if (typeof input === 'string') { 15803 input = offsetFromString(matchShortOffset, input); 15804 if (input === null) { 15805 return this; 15806 } 15807 } else if (Math.abs(input) < 16 && !keepMinutes) { 15808 input = input * 60; 15809 } 15810 if (!this._isUTC && keepLocalTime) { 15811 localAdjust = getDateOffset(this); 15812 } 15813 this._offset = input; 15814 this._isUTC = true; 15815 if (localAdjust != null) { 15816 this.add(localAdjust, 'm'); 15817 } 15818 if (offset !== input) { 15819 if (!keepLocalTime || this._changeInProgress) { 15820 addSubtract$1( 15821 this, 15822 createDuration(input - offset, 'm'), 15823 1, 15824 false 15825 ); 15826 } else if (!this._changeInProgress) { 15827 this._changeInProgress = true; 15828 hooks.updateOffset(this, true); 15829 this._changeInProgress = null; 15830 } 15831 } 15832 return this; 15833 } else { 15834 return this._isUTC ? offset : getDateOffset(this); 15835 } 15836 } 15837 15838 function getSetZone(input, keepLocalTime) { 15839 if (input != null) { 15840 if (typeof input !== 'string') { 15841 input = -input; 15842 } 15843 15844 this.utcOffset(input, keepLocalTime); 15845 15846 return this; 15847 } else { 15848 return -this.utcOffset(); 15849 } 15850 } 15851 15852 function setOffsetToUTC(keepLocalTime) { 15853 return this.utcOffset(0, keepLocalTime); 15854 } 15855 15856 function setOffsetToLocal(keepLocalTime) { 15857 if (this._isUTC) { 15858 this.utcOffset(0, keepLocalTime); 15859 this._isUTC = false; 15860 15861 if (keepLocalTime) { 15862 this.subtract(getDateOffset(this), 'm'); 15863 } 15864 } 15865 return this; 15866 } 15867 15868 function setOffsetToParsedOffset() { 15869 if (this._tzm != null) { 15870 this.utcOffset(this._tzm, false, true); 15871 } else if (typeof this._i === 'string') { 15872 var tZone = offsetFromString(matchOffset, this._i); 15873 if (tZone != null) { 15874 this.utcOffset(tZone); 15875 } else { 15876 this.utcOffset(0, true); 15877 } 15878 } 15879 return this; 15880 } 15881 15882 function hasAlignedHourOffset(input) { 15883 if (!this.isValid()) { 15884 return false; 15885 } 15886 input = input ? createLocal(input).utcOffset() : 0; 15887 15888 return (this.utcOffset() - input) % 60 === 0; 15889 } 15890 15891 function isDaylightSavingTime() { 15892 return ( 15893 this.utcOffset() > this.clone().month(0).utcOffset() || 15894 this.utcOffset() > this.clone().month(5).utcOffset() 15895 ); 15896 } 15897 15898 function isDaylightSavingTimeShifted() { 15899 if (!isUndefined(this._isDSTShifted)) { 15900 return this._isDSTShifted; 15901 } 15902 15903 var c = {}, 15904 other; 15905 15906 copyConfig(c, this); 15907 c = prepareConfig(c); 15908 15909 if (c._a) { 15910 other = c._isUTC ? createUTC(c._a) : createLocal(c._a); 15911 this._isDSTShifted = 15912 this.isValid() && compareArrays(c._a, other.toArray()) > 0; 15913 } else { 15914 this._isDSTShifted = false; 15915 } 15916 15917 return this._isDSTShifted; 15918 } 15919 15920 function isLocal() { 15921 return this.isValid() ? !this._isUTC : false; 15922 } 15923 15924 function isUtcOffset() { 15925 return this.isValid() ? this._isUTC : false; 15926 } 15927 15928 function isUtc() { 15929 return this.isValid() ? this._isUTC && this._offset === 0 : false; 15930 } 15931 15932 // ASP.NET json date format regex 15933 var aspNetRegex = /^(-|\+)?(?:(\d*)[. ])?(\d+):(\d+)(?::(\d+)(\.\d*)?)?$/, 15934 // from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html 15935 // somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere 15936 // and further modified to allow for strings containing both week and day 15937 isoRegex = 15938 /^(-|\+)?P(?:([-+]?[0-9,.]*)Y)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)W)?(?:([-+]?[0-9,.]*)D)?(?:T(?:([-+]?[0-9,.]*)H)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)S)?)?$/; 15939 15940 function createDuration(input, key) { 15941 var duration = input, 15942 // matching against regexp is expensive, do it on demand 15943 match = null, 15944 sign, 15945 ret, 15946 diffRes; 15947 15948 if (isDuration(input)) { 15949 duration = { 15950 ms: input._milliseconds, 15951 d: input._days, 15952 M: input._months, 15953 }; 15954 } else if (isNumber(input) || !isNaN(+input)) { 15955 duration = {}; 15956 if (key) { 15957 duration[key] = +input; 15958 } else { 15959 duration.milliseconds = +input; 15960 } 15961 } else if ((match = aspNetRegex.exec(input))) { 15962 sign = match[1] === '-' ? -1 : 1; 15963 duration = { 15964 y: 0, 15965 d: toInt(match[DATE]) * sign, 15966 h: toInt(match[HOUR]) * sign, 15967 m: toInt(match[MINUTE]) * sign, 15968 s: toInt(match[SECOND]) * sign, 15969 ms: toInt(absRound(match[MILLISECOND] * 1000)) * sign, // the millisecond decimal point is included in the match 15970 }; 15971 } else if ((match = isoRegex.exec(input))) { 15972 sign = match[1] === '-' ? -1 : 1; 15973 duration = { 15974 y: parseIso(match[2], sign), 15975 M: parseIso(match[3], sign), 15976 w: parseIso(match[4], sign), 15977 d: parseIso(match[5], sign), 15978 h: parseIso(match[6], sign), 15979 m: parseIso(match[7], sign), 15980 s: parseIso(match[8], sign), 15981 }; 15982 } else if (duration == null) { 15983 // checks for null or undefined 15984 duration = {}; 15985 } else if ( 15986 typeof duration === 'object' && 15987 ('from' in duration || 'to' in duration) 15988 ) { 15989 diffRes = momentsDifference( 15990 createLocal(duration.from), 15991 createLocal(duration.to) 15992 ); 15993 15994 duration = {}; 15995 duration.ms = diffRes.milliseconds; 15996 duration.M = diffRes.months; 15997 } 15998 15999 ret = new Duration(duration); 16000 16001 if (isDuration(input) && hasOwnProp(input, '_locale')) { 16002 ret._locale = input._locale; 16003 } 16004 16005 if (isDuration(input) && hasOwnProp(input, '_isValid')) { 16006 ret._isValid = input._isValid; 16007 } 16008 16009 return ret; 16010 } 16011 16012 createDuration.fn = Duration.prototype; 16013 createDuration.invalid = createInvalid; 16014 16015 function parseIso(inp, sign) { 16016 // We'd normally use ~~inp for this, but unfortunately it also 16017 // converts floats to ints. 16018 // inp may be undefined, so careful calling replace on it. 16019 var res = inp && parseFloat(inp.replace(',', '.')); 16020 // apply sign while we're at it 16021 return (isNaN(res) ? 0 : res) * sign; 16022 } 16023 16024 function positiveMomentsDifference(base, other) { 16025 var res = {}; 16026 16027 res.months = 16028 other.month() - base.month() + (other.year() - base.year()) * 12; 16029 if (base.clone().add(res.months, 'M').isAfter(other)) { 16030 --res.months; 16031 } 16032 16033 res.milliseconds = +other - +base.clone().add(res.months, 'M'); 16034 16035 return res; 16036 } 16037 16038 function momentsDifference(base, other) { 16039 var res; 16040 if (!(base.isValid() && other.isValid())) { 16041 return { milliseconds: 0, months: 0 }; 16042 } 16043 16044 other = cloneWithOffset(other, base); 16045 if (base.isBefore(other)) { 16046 res = positiveMomentsDifference(base, other); 16047 } else { 16048 res = positiveMomentsDifference(other, base); 16049 res.milliseconds = -res.milliseconds; 16050 res.months = -res.months; 16051 } 16052 16053 return res; 16054 } 16055 16056 // TODO: remove 'name' arg after deprecation is removed 16057 function createAdder(direction, name) { 16058 return function (val, period) { 16059 var dur, tmp; 16060 //invert the arguments, but complain about it 16061 if (period !== null && !isNaN(+period)) { 16062 deprecateSimple( 16063 name, 16064 'moment().' + 16065 name + 16066 '(period, number) is deprecated. Please use moment().' + 16067 name + 16068 '(number, period). ' + 16069 'See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info.' 16070 ); 16071 tmp = val; 16072 val = period; 16073 period = tmp; 16074 } 16075 16076 dur = createDuration(val, period); 16077 addSubtract$1(this, dur, direction); 16078 return this; 16079 }; 16080 } 16081 16082 function addSubtract$1(mom, duration, isAdding, updateOffset) { 16083 var milliseconds = duration._milliseconds, 16084 days = absRound(duration._days), 16085 months = absRound(duration._months); 16086 16087 if (!mom.isValid()) { 16088 // No op 16089 return; 16090 } 16091 16092 updateOffset = updateOffset == null ? true : updateOffset; 16093 16094 if (months) { 16095 setMonth(mom, get$2(mom, 'Month') + months * isAdding); 16096 } 16097 if (days) { 16098 set$1(mom, 'Date', get$2(mom, 'Date') + days * isAdding); 16099 } 16100 if (milliseconds) { 16101 mom._d.setTime(mom._d.valueOf() + milliseconds * isAdding); 16102 } 16103 if (updateOffset) { 16104 hooks.updateOffset(mom, days || months); 16105 } 16106 } 16107 16108 var add$1 = createAdder(1, 'add'), 16109 subtract$1 = createAdder(-1, 'subtract'); 16110 16111 function isString(input) { 16112 return typeof input === 'string' || input instanceof String; 16113 } 16114 16115 // type MomentInput = Moment | Date | string | number | (number | string)[] | MomentInputObject | void; // null | undefined 16116 function isMomentInput(input) { 16117 return ( 16118 isMoment(input) || 16119 isDate(input) || 16120 isString(input) || 16121 isNumber(input) || 16122 isNumberOrStringArray(input) || 16123 isMomentInputObject(input) || 16124 input === null || 16125 input === undefined 16126 ); 16127 } 16128 16129 function isMomentInputObject(input) { 16130 var objectTest = isObject(input) && !isObjectEmpty(input), 16131 propertyTest = false, 16132 properties = [ 16133 'years', 16134 'year', 16135 'y', 16136 'months', 16137 'month', 16138 'M', 16139 'days', 16140 'day', 16141 'd', 16142 'dates', 16143 'date', 16144 'D', 16145 'hours', 16146 'hour', 16147 'h', 16148 'minutes', 16149 'minute', 16150 'm', 16151 'seconds', 16152 'second', 16153 's', 16154 'milliseconds', 16155 'millisecond', 16156 'ms', 16157 ], 16158 i, 16159 property, 16160 propertyLen = properties.length; 16161 16162 for (i = 0; i < propertyLen; i += 1) { 16163 property = properties[i]; 16164 propertyTest = propertyTest || hasOwnProp(input, property); 16165 } 16166 16167 return objectTest && propertyTest; 16168 } 16169 16170 function isNumberOrStringArray(input) { 16171 var arrayTest = isArray(input), 16172 dataTypeTest = false; 16173 if (arrayTest) { 16174 dataTypeTest = 16175 input.filter(function (item) { 16176 return !isNumber(item) && isString(input); 16177 }).length === 0; 16178 } 16179 return arrayTest && dataTypeTest; 16180 } 16181 16182 function isCalendarSpec(input) { 16183 var objectTest = isObject(input) && !isObjectEmpty(input), 16184 propertyTest = false, 16185 properties = [ 16186 'sameDay', 16187 'nextDay', 16188 'lastDay', 16189 'nextWeek', 16190 'lastWeek', 16191 'sameElse', 16192 ], 16193 i, 16194 property; 16195 16196 for (i = 0; i < properties.length; i += 1) { 16197 property = properties[i]; 16198 propertyTest = propertyTest || hasOwnProp(input, property); 16199 } 16200 16201 return objectTest && propertyTest; 16202 } 16203 16204 function getCalendarFormat(myMoment, now) { 16205 var diff = myMoment.diff(now, 'days', true); 16206 return diff < -6 16207 ? 'sameElse' 16208 : diff < -1 16209 ? 'lastWeek' 16210 : diff < 0 16211 ? 'lastDay' 16212 : diff < 1 16213 ? 'sameDay' 16214 : diff < 2 16215 ? 'nextDay' 16216 : diff < 7 16217 ? 'nextWeek' 16218 : 'sameElse'; 16219 } 16220 16221 function calendar(time, formats) { 16222 // Support for single parameter, formats only overload to the calendar function 16223 if (arguments.length === 1) { 16224 if (!arguments[0]) { 16225 time = undefined; 16226 formats = undefined; 16227 } else if (isMomentInput(arguments[0])) { 16228 time = arguments[0]; 16229 formats = undefined; 16230 } else if (isCalendarSpec(arguments[0])) { 16231 formats = arguments[0]; 16232 time = undefined; 16233 } 16234 } 16235 // We want to compare the start of today, vs this. 16236 // Getting start-of-today depends on whether we're local/utc/offset or not. 16237 var now = time || createLocal(), 16238 sod = cloneWithOffset(now, this).startOf('day'), 16239 format = hooks.calendarFormat(this, sod) || 'sameElse', 16240 output = 16241 formats && 16242 (isFunction(formats[format]) 16243 ? formats[format].call(this, now) 16244 : formats[format]); 16245 16246 return this.format( 16247 output || this.localeData().calendar(format, this, createLocal(now)) 16248 ); 16249 } 16250 16251 function clone$1() { 16252 return new Moment(this); 16253 } 16254 16255 function isAfter(input, units) { 16256 var localInput = isMoment(input) ? input : createLocal(input); 16257 if (!(this.isValid() && localInput.isValid())) { 16258 return false; 16259 } 16260 units = normalizeUnits(units) || 'millisecond'; 16261 if (units === 'millisecond') { 16262 return this.valueOf() > localInput.valueOf(); 16263 } else { 16264 return localInput.valueOf() < this.clone().startOf(units).valueOf(); 16265 } 16266 } 16267 16268 function isBefore(input, units) { 16269 var localInput = isMoment(input) ? input : createLocal(input); 16270 if (!(this.isValid() && localInput.isValid())) { 16271 return false; 16272 } 16273 units = normalizeUnits(units) || 'millisecond'; 16274 if (units === 'millisecond') { 16275 return this.valueOf() < localInput.valueOf(); 16276 } else { 16277 return this.clone().endOf(units).valueOf() < localInput.valueOf(); 16278 } 16279 } 16280 16281 function isBetween(from, to, units, inclusivity) { 16282 var localFrom = isMoment(from) ? from : createLocal(from), 16283 localTo = isMoment(to) ? to : createLocal(to); 16284 if (!(this.isValid() && localFrom.isValid() && localTo.isValid())) { 16285 return false; 16286 } 16287 inclusivity = inclusivity || '()'; 16288 return ( 16289 (inclusivity[0] === '(' 16290 ? this.isAfter(localFrom, units) 16291 : !this.isBefore(localFrom, units)) && 16292 (inclusivity[1] === ')' 16293 ? this.isBefore(localTo, units) 16294 : !this.isAfter(localTo, units)) 16295 ); 16296 } 16297 16298 function isSame(input, units) { 16299 var localInput = isMoment(input) ? input : createLocal(input), 16300 inputMs; 16301 if (!(this.isValid() && localInput.isValid())) { 16302 return false; 16303 } 16304 units = normalizeUnits(units) || 'millisecond'; 16305 if (units === 'millisecond') { 16306 return this.valueOf() === localInput.valueOf(); 16307 } else { 16308 inputMs = localInput.valueOf(); 16309 return ( 16310 this.clone().startOf(units).valueOf() <= inputMs && 16311 inputMs <= this.clone().endOf(units).valueOf() 16312 ); 16313 } 16314 } 16315 16316 function isSameOrAfter(input, units) { 16317 return this.isSame(input, units) || this.isAfter(input, units); 16318 } 16319 16320 function isSameOrBefore(input, units) { 16321 return this.isSame(input, units) || this.isBefore(input, units); 16322 } 16323 16324 function diff(input, units, asFloat) { 16325 var that, zoneDelta, output; 16326 16327 if (!this.isValid()) { 16328 return NaN; 16329 } 16330 16331 that = cloneWithOffset(input, this); 16332 16333 if (!that.isValid()) { 16334 return NaN; 16335 } 16336 16337 zoneDelta = (that.utcOffset() - this.utcOffset()) * 6e4; 16338 16339 units = normalizeUnits(units); 16340 16341 switch (units) { 16342 case 'year': 16343 output = monthDiff(this, that) / 12; 16344 break; 16345 case 'month': 16346 output = monthDiff(this, that); 16347 break; 16348 case 'quarter': 16349 output = monthDiff(this, that) / 3; 16350 break; 16351 case 'second': 16352 output = (this - that) / 1e3; 16353 break; // 1000 16354 case 'minute': 16355 output = (this - that) / 6e4; 16356 break; // 1000 * 60 16357 case 'hour': 16358 output = (this - that) / 36e5; 16359 break; // 1000 * 60 * 60 16360 case 'day': 16361 output = (this - that - zoneDelta) / 864e5; 16362 break; // 1000 * 60 * 60 * 24, negate dst 16363 case 'week': 16364 output = (this - that - zoneDelta) / 6048e5; 16365 break; // 1000 * 60 * 60 * 24 * 7, negate dst 16366 default: 16367 output = this - that; 16368 } 16369 16370 return asFloat ? output : absFloor(output); 16371 } 16372 16373 function monthDiff(a, b) { 16374 if (a.date() < b.date()) { 16375 // end-of-month calculations work correct when the start month has more 16376 // days than the end month. 16377 return -monthDiff(b, a); 16378 } 16379 // difference in months 16380 var wholeMonthDiff = (b.year() - a.year()) * 12 + (b.month() - a.month()), 16381 // b is in (anchor - 1 month, anchor + 1 month) 16382 anchor = a.clone().add(wholeMonthDiff, 'months'), 16383 anchor2, 16384 adjust; 16385 16386 if (b - anchor < 0) { 16387 anchor2 = a.clone().add(wholeMonthDiff - 1, 'months'); 16388 // linear across the month 16389 adjust = (b - anchor) / (anchor - anchor2); 16390 } else { 16391 anchor2 = a.clone().add(wholeMonthDiff + 1, 'months'); 16392 // linear across the month 16393 adjust = (b - anchor) / (anchor2 - anchor); 16394 } 16395 16396 //check for negative zero, return zero if negative zero 16397 return -(wholeMonthDiff + adjust) || 0; 16398 } 16399 16400 hooks.defaultFormat = 'YYYY-MM-DDTHH:mm:ssZ'; 16401 hooks.defaultFormatUtc = 'YYYY-MM-DDTHH:mm:ss[Z]'; 16402 16403 function toString() { 16404 return this.clone().locale('en').format('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ'); 16405 } 16406 16407 function toISOString$1(keepOffset) { 16408 if (!this.isValid()) { 16409 return null; 16410 } 16411 var utc = keepOffset !== true, 16412 m = utc ? this.clone().utc() : this; 16413 if (m.year() < 0 || m.year() > 9999) { 16414 return formatMoment( 16415 m, 16416 utc 16417 ? 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]' 16418 : 'YYYYYY-MM-DD[T]HH:mm:ss.SSSZ' 16419 ); 16420 } 16421 if (isFunction(Date.prototype.toISOString)) { 16422 // native implementation is ~50x faster, use it when we can 16423 if (utc) { 16424 return this.toDate().toISOString(); 16425 } else { 16426 return new Date(this.valueOf() + this.utcOffset() * 60 * 1000) 16427 .toISOString() 16428 .replace('Z', formatMoment(m, 'Z')); 16429 } 16430 } 16431 return formatMoment( 16432 m, 16433 utc ? 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]' : 'YYYY-MM-DD[T]HH:mm:ss.SSSZ' 16434 ); 16435 } 16436 16437 /** 16438 * Return a human readable representation of a moment that can 16439 * also be evaluated to get a new moment which is the same 16440 * 16441 * @link https://nodejs.org/dist/latest/docs/api/util.html#util_custom_inspect_function_on_objects 16442 */ 16443 function inspect() { 16444 if (!this.isValid()) { 16445 return 'moment.invalid(/* ' + this._i + ' */)'; 16446 } 16447 var func = 'moment', 16448 zone = '', 16449 prefix, 16450 year, 16451 datetime, 16452 suffix; 16453 if (!this.isLocal()) { 16454 func = this.utcOffset() === 0 ? 'moment.utc' : 'moment.parseZone'; 16455 zone = 'Z'; 16456 } 16457 prefix = '[' + func + '("]'; 16458 year = 0 <= this.year() && this.year() <= 9999 ? 'YYYY' : 'YYYYYY'; 16459 datetime = '-MM-DD[T]HH:mm:ss.SSS'; 16460 suffix = zone + '[")]'; 16461 16462 return this.format(prefix + year + datetime + suffix); 16463 } 16464 16465 function format(inputString) { 16466 if (!inputString) { 16467 inputString = this.isUtc() 16468 ? hooks.defaultFormatUtc 16469 : hooks.defaultFormat; 16470 } 16471 var output = formatMoment(this, inputString); 16472 return this.localeData().postformat(output); 16473 } 16474 16475 function from(time, withoutSuffix) { 16476 if ( 16477 this.isValid() && 16478 ((isMoment(time) && time.isValid()) || createLocal(time).isValid()) 16479 ) { 16480 return createDuration({ to: this, from: time }) 16481 .locale(this.locale()) 16482 .humanize(!withoutSuffix); 16483 } else { 16484 return this.localeData().invalidDate(); 16485 } 16486 } 16487 16488 function fromNow(withoutSuffix) { 16489 return this.from(createLocal(), withoutSuffix); 16490 } 16491 16492 function to(time, withoutSuffix) { 16493 if ( 16494 this.isValid() && 16495 ((isMoment(time) && time.isValid()) || createLocal(time).isValid()) 16496 ) { 16497 return createDuration({ from: this, to: time }) 16498 .locale(this.locale()) 16499 .humanize(!withoutSuffix); 16500 } else { 16501 return this.localeData().invalidDate(); 16502 } 16503 } 16504 16505 function toNow(withoutSuffix) { 16506 return this.to(createLocal(), withoutSuffix); 16507 } 16508 16509 // If passed a locale key, it will set the locale for this 16510 // instance. Otherwise, it will return the locale configuration 16511 // variables for this instance. 16512 function locale(key) { 16513 var newLocaleData; 16514 16515 if (key === undefined) { 16516 return this._locale._abbr; 16517 } else { 16518 newLocaleData = getLocale(key); 16519 if (newLocaleData != null) { 16520 this._locale = newLocaleData; 16521 } 16522 return this; 16523 } 16524 } 16525 16526 var lang = deprecate( 16527 'moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.', 16528 function (key) { 16529 if (key === undefined) { 16530 return this.localeData(); 16531 } else { 16532 return this.locale(key); 16533 } 16534 } 16535 ); 16536 16537 function localeData() { 16538 return this._locale; 16539 } 16540 16541 var MS_PER_SECOND = 1000, 16542 MS_PER_MINUTE = 60 * MS_PER_SECOND, 16543 MS_PER_HOUR = 60 * MS_PER_MINUTE, 16544 MS_PER_400_YEARS = (365 * 400 + 97) * 24 * MS_PER_HOUR; 16545 16546 // actual modulo - handles negative numbers (for dates before 1970): 16547 function mod(dividend, divisor) { 16548 return ((dividend % divisor) + divisor) % divisor; 16549 } 16550 16551 function localStartOfDate(y, m, d) { 16552 // the date constructor remaps years 0-99 to 1900-1999 16553 if (y < 100 && y >= 0) { 16554 // preserve leap years using a full 400 year cycle, then reset 16555 return new Date(y + 400, m, d) - MS_PER_400_YEARS; 16556 } else { 16557 return new Date(y, m, d).valueOf(); 16558 } 16559 } 16560 16561 function utcStartOfDate(y, m, d) { 16562 // Date.UTC remaps years 0-99 to 1900-1999 16563 if (y < 100 && y >= 0) { 16564 // preserve leap years using a full 400 year cycle, then reset 16565 return Date.UTC(y + 400, m, d) - MS_PER_400_YEARS; 16566 } else { 16567 return Date.UTC(y, m, d); 16568 } 16569 } 16570 16571 function startOf(units) { 16572 var time, startOfDate; 16573 units = normalizeUnits(units); 16574 if (units === undefined || units === 'millisecond' || !this.isValid()) { 16575 return this; 16576 } 16577 16578 startOfDate = this._isUTC ? utcStartOfDate : localStartOfDate; 16579 16580 switch (units) { 16581 case 'year': 16582 time = startOfDate(this.year(), 0, 1); 16583 break; 16584 case 'quarter': 16585 time = startOfDate( 16586 this.year(), 16587 this.month() - (this.month() % 3), 16588 1 16589 ); 16590 break; 16591 case 'month': 16592 time = startOfDate(this.year(), this.month(), 1); 16593 break; 16594 case 'week': 16595 time = startOfDate( 16596 this.year(), 16597 this.month(), 16598 this.date() - this.weekday() 16599 ); 16600 break; 16601 case 'isoWeek': 16602 time = startOfDate( 16603 this.year(), 16604 this.month(), 16605 this.date() - (this.isoWeekday() - 1) 16606 ); 16607 break; 16608 case 'day': 16609 case 'date': 16610 time = startOfDate(this.year(), this.month(), this.date()); 16611 break; 16612 case 'hour': 16613 time = this._d.valueOf(); 16614 time -= mod( 16615 time + (this._isUTC ? 0 : this.utcOffset() * MS_PER_MINUTE), 16616 MS_PER_HOUR 16617 ); 16618 break; 16619 case 'minute': 16620 time = this._d.valueOf(); 16621 time -= mod(time, MS_PER_MINUTE); 16622 break; 16623 case 'second': 16624 time = this._d.valueOf(); 16625 time -= mod(time, MS_PER_SECOND); 16626 break; 16627 } 16628 16629 this._d.setTime(time); 16630 hooks.updateOffset(this, true); 16631 return this; 16632 } 16633 16634 function endOf(units) { 16635 var time, startOfDate; 16636 units = normalizeUnits(units); 16637 if (units === undefined || units === 'millisecond' || !this.isValid()) { 16638 return this; 16639 } 16640 16641 startOfDate = this._isUTC ? utcStartOfDate : localStartOfDate; 16642 16643 switch (units) { 16644 case 'year': 16645 time = startOfDate(this.year() + 1, 0, 1) - 1; 16646 break; 16647 case 'quarter': 16648 time = 16649 startOfDate( 16650 this.year(), 16651 this.month() - (this.month() % 3) + 3, 16652 1 16653 ) - 1; 16654 break; 16655 case 'month': 16656 time = startOfDate(this.year(), this.month() + 1, 1) - 1; 16657 break; 16658 case 'week': 16659 time = 16660 startOfDate( 16661 this.year(), 16662 this.month(), 16663 this.date() - this.weekday() + 7 16664 ) - 1; 16665 break; 16666 case 'isoWeek': 16667 time = 16668 startOfDate( 16669 this.year(), 16670 this.month(), 16671 this.date() - (this.isoWeekday() - 1) + 7 16672 ) - 1; 16673 break; 16674 case 'day': 16675 case 'date': 16676 time = startOfDate(this.year(), this.month(), this.date() + 1) - 1; 16677 break; 16678 case 'hour': 16679 time = this._d.valueOf(); 16680 time += 16681 MS_PER_HOUR - 16682 mod( 16683 time + (this._isUTC ? 0 : this.utcOffset() * MS_PER_MINUTE), 16684 MS_PER_HOUR 16685 ) - 16686 1; 16687 break; 16688 case 'minute': 16689 time = this._d.valueOf(); 16690 time += MS_PER_MINUTE - mod(time, MS_PER_MINUTE) - 1; 16691 break; 16692 case 'second': 16693 time = this._d.valueOf(); 16694 time += MS_PER_SECOND - mod(time, MS_PER_SECOND) - 1; 16695 break; 16696 } 16697 16698 this._d.setTime(time); 16699 hooks.updateOffset(this, true); 16700 return this; 16701 } 16702 16703 function valueOf$1() { 16704 return this._d.valueOf() - (this._offset || 0) * 60000; 16705 } 16706 16707 function unix() { 16708 return Math.floor(this.valueOf() / 1000); 16709 } 16710 16711 function toDate() { 16712 return new Date(this.valueOf()); 16713 } 16714 16715 function toArray() { 16716 var m = this; 16717 return [ 16718 m.year(), 16719 m.month(), 16720 m.date(), 16721 m.hour(), 16722 m.minute(), 16723 m.second(), 16724 m.millisecond(), 16725 ]; 16726 } 16727 16728 function toObject() { 16729 var m = this; 16730 return { 16731 years: m.year(), 16732 months: m.month(), 16733 date: m.date(), 16734 hours: m.hours(), 16735 minutes: m.minutes(), 16736 seconds: m.seconds(), 16737 milliseconds: m.milliseconds(), 16738 }; 16739 } 16740 16741 function toJSON() { 16742 // new Date(NaN).toJSON() === null 16743 return this.isValid() ? this.toISOString() : null; 16744 } 16745 16746 function isValid() { 16747 return isValid$2(this); 16748 } 16749 16750 function parsingFlags() { 16751 return extend({}, getParsingFlags(this)); 16752 } 16753 16754 function invalidAt() { 16755 return getParsingFlags(this).overflow; 16756 } 16757 16758 function creationData() { 16759 return { 16760 input: this._i, 16761 format: this._f, 16762 locale: this._locale, 16763 isUTC: this._isUTC, 16764 strict: this._strict, 16765 }; 16766 } 16767 16768 addFormatToken('N', 0, 0, 'eraAbbr'); 16769 addFormatToken('NN', 0, 0, 'eraAbbr'); 16770 addFormatToken('NNN', 0, 0, 'eraAbbr'); 16771 addFormatToken('NNNN', 0, 0, 'eraName'); 16772 addFormatToken('NNNNN', 0, 0, 'eraNarrow'); 16773 16774 addFormatToken('y', ['y', 1], 'yo', 'eraYear'); 16775 addFormatToken('y', ['yy', 2], 0, 'eraYear'); 16776 addFormatToken('y', ['yyy', 3], 0, 'eraYear'); 16777 addFormatToken('y', ['yyyy', 4], 0, 'eraYear'); 16778 16779 addRegexToken('N', matchEraAbbr); 16780 addRegexToken('NN', matchEraAbbr); 16781 addRegexToken('NNN', matchEraAbbr); 16782 addRegexToken('NNNN', matchEraName); 16783 addRegexToken('NNNNN', matchEraNarrow); 16784 16785 addParseToken( 16786 ['N', 'NN', 'NNN', 'NNNN', 'NNNNN'], 16787 function (input, array, config, token) { 16788 var era = config._locale.erasParse(input, token, config._strict); 16789 if (era) { 16790 getParsingFlags(config).era = era; 16791 } else { 16792 getParsingFlags(config).invalidEra = input; 16793 } 16794 } 16795 ); 16796 16797 addRegexToken('y', matchUnsigned); 16798 addRegexToken('yy', matchUnsigned); 16799 addRegexToken('yyy', matchUnsigned); 16800 addRegexToken('yyyy', matchUnsigned); 16801 addRegexToken('yo', matchEraYearOrdinal); 16802 16803 addParseToken(['y', 'yy', 'yyy', 'yyyy'], YEAR); 16804 addParseToken(['yo'], function (input, array, config, token) { 16805 var match; 16806 if (config._locale._eraYearOrdinalRegex) { 16807 match = input.match(config._locale._eraYearOrdinalRegex); 16808 } 16809 16810 if (config._locale.eraYearOrdinalParse) { 16811 array[YEAR] = config._locale.eraYearOrdinalParse(input, match); 16812 } else { 16813 array[YEAR] = parseInt(input, 10); 16814 } 16815 }); 16816 16817 function localeEras(m, format) { 16818 var i, 16819 l, 16820 date, 16821 eras = this._eras || getLocale('en')._eras; 16822 for (i = 0, l = eras.length; i < l; ++i) { 16823 switch (typeof eras[i].since) { 16824 case 'string': 16825 // truncate time 16826 date = hooks(eras[i].since).startOf('day'); 16827 eras[i].since = date.valueOf(); 16828 break; 16829 } 16830 16831 switch (typeof eras[i].until) { 16832 case 'undefined': 16833 eras[i].until = +Infinity; 16834 break; 16835 case 'string': 16836 // truncate time 16837 date = hooks(eras[i].until).startOf('day').valueOf(); 16838 eras[i].until = date.valueOf(); 16839 break; 16840 } 16841 } 16842 return eras; 16843 } 16844 16845 function localeErasParse(eraName, format, strict) { 16846 var i, 16847 l, 16848 eras = this.eras(), 16849 name, 16850 abbr, 16851 narrow; 16852 eraName = eraName.toUpperCase(); 16853 16854 for (i = 0, l = eras.length; i < l; ++i) { 16855 name = eras[i].name.toUpperCase(); 16856 abbr = eras[i].abbr.toUpperCase(); 16857 narrow = eras[i].narrow.toUpperCase(); 16858 16859 if (strict) { 16860 switch (format) { 16861 case 'N': 16862 case 'NN': 16863 case 'NNN': 16864 if (abbr === eraName) { 16865 return eras[i]; 16866 } 16867 break; 16868 16869 case 'NNNN': 16870 if (name === eraName) { 16871 return eras[i]; 16872 } 16873 break; 16874 16875 case 'NNNNN': 16876 if (narrow === eraName) { 16877 return eras[i]; 16878 } 16879 break; 16880 } 16881 } else if ([name, abbr, narrow].indexOf(eraName) >= 0) { 16882 return eras[i]; 16883 } 16884 } 16885 } 16886 16887 function localeErasConvertYear(era, year) { 16888 var dir = era.since <= era.until ? 1 : -1; 16889 if (year === undefined) { 16890 return hooks(era.since).year(); 16891 } else { 16892 return hooks(era.since).year() + (year - era.offset) * dir; 16893 } 16894 } 16895 16896 function getEraName() { 16897 var i, 16898 l, 16899 val, 16900 eras = this.localeData().eras(); 16901 for (i = 0, l = eras.length; i < l; ++i) { 16902 // truncate time 16903 val = this.clone().startOf('day').valueOf(); 16904 16905 if (eras[i].since <= val && val <= eras[i].until) { 16906 return eras[i].name; 16907 } 16908 if (eras[i].until <= val && val <= eras[i].since) { 16909 return eras[i].name; 16910 } 16911 } 16912 16913 return ''; 16914 } 16915 16916 function getEraNarrow() { 16917 var i, 16918 l, 16919 val, 16920 eras = this.localeData().eras(); 16921 for (i = 0, l = eras.length; i < l; ++i) { 16922 // truncate time 16923 val = this.clone().startOf('day').valueOf(); 16924 16925 if (eras[i].since <= val && val <= eras[i].until) { 16926 return eras[i].narrow; 16927 } 16928 if (eras[i].until <= val && val <= eras[i].since) { 16929 return eras[i].narrow; 16930 } 16931 } 16932 16933 return ''; 16934 } 16935 16936 function getEraAbbr() { 16937 var i, 16938 l, 16939 val, 16940 eras = this.localeData().eras(); 16941 for (i = 0, l = eras.length; i < l; ++i) { 16942 // truncate time 16943 val = this.clone().startOf('day').valueOf(); 16944 16945 if (eras[i].since <= val && val <= eras[i].until) { 16946 return eras[i].abbr; 16947 } 16948 if (eras[i].until <= val && val <= eras[i].since) { 16949 return eras[i].abbr; 16950 } 16951 } 16952 16953 return ''; 16954 } 16955 16956 function getEraYear() { 16957 var i, 16958 l, 16959 dir, 16960 val, 16961 eras = this.localeData().eras(); 16962 for (i = 0, l = eras.length; i < l; ++i) { 16963 dir = eras[i].since <= eras[i].until ? 1 : -1; 16964 16965 // truncate time 16966 val = this.clone().startOf('day').valueOf(); 16967 16968 if ( 16969 (eras[i].since <= val && val <= eras[i].until) || 16970 (eras[i].until <= val && val <= eras[i].since) 16971 ) { 16972 return ( 16973 (this.year() - hooks(eras[i].since).year()) * dir + 16974 eras[i].offset 16975 ); 16976 } 16977 } 16978 16979 return this.year(); 16980 } 16981 16982 function erasNameRegex(isStrict) { 16983 if (!hasOwnProp(this, '_erasNameRegex')) { 16984 computeErasParse.call(this); 16985 } 16986 return isStrict ? this._erasNameRegex : this._erasRegex; 16987 } 16988 16989 function erasAbbrRegex(isStrict) { 16990 if (!hasOwnProp(this, '_erasAbbrRegex')) { 16991 computeErasParse.call(this); 16992 } 16993 return isStrict ? this._erasAbbrRegex : this._erasRegex; 16994 } 16995 16996 function erasNarrowRegex(isStrict) { 16997 if (!hasOwnProp(this, '_erasNarrowRegex')) { 16998 computeErasParse.call(this); 16999 } 17000 return isStrict ? this._erasNarrowRegex : this._erasRegex; 17001 } 17002 17003 function matchEraAbbr(isStrict, locale) { 17004 return locale.erasAbbrRegex(isStrict); 17005 } 17006 17007 function matchEraName(isStrict, locale) { 17008 return locale.erasNameRegex(isStrict); 17009 } 17010 17011 function matchEraNarrow(isStrict, locale) { 17012 return locale.erasNarrowRegex(isStrict); 17013 } 17014 17015 function matchEraYearOrdinal(isStrict, locale) { 17016 return locale._eraYearOrdinalRegex || matchUnsigned; 17017 } 17018 17019 function computeErasParse() { 17020 var abbrPieces = [], 17021 namePieces = [], 17022 narrowPieces = [], 17023 mixedPieces = [], 17024 i, 17025 l, 17026 erasName, 17027 erasAbbr, 17028 erasNarrow, 17029 eras = this.eras(); 17030 17031 for (i = 0, l = eras.length; i < l; ++i) { 17032 erasName = regexEscape(eras[i].name); 17033 erasAbbr = regexEscape(eras[i].abbr); 17034 erasNarrow = regexEscape(eras[i].narrow); 17035 17036 namePieces.push(erasName); 17037 abbrPieces.push(erasAbbr); 17038 narrowPieces.push(erasNarrow); 17039 mixedPieces.push(erasName); 17040 mixedPieces.push(erasAbbr); 17041 mixedPieces.push(erasNarrow); 17042 } 17043 17044 this._erasRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i'); 17045 this._erasNameRegex = new RegExp('^(' + namePieces.join('|') + ')', 'i'); 17046 this._erasAbbrRegex = new RegExp('^(' + abbrPieces.join('|') + ')', 'i'); 17047 this._erasNarrowRegex = new RegExp( 17048 '^(' + narrowPieces.join('|') + ')', 17049 'i' 17050 ); 17051 } 17052 17053 // FORMATTING 17054 17055 addFormatToken(0, ['gg', 2], 0, function () { 17056 return this.weekYear() % 100; 17057 }); 17058 17059 addFormatToken(0, ['GG', 2], 0, function () { 17060 return this.isoWeekYear() % 100; 17061 }); 17062 17063 function addWeekYearFormatToken(token, getter) { 17064 addFormatToken(0, [token, token.length], 0, getter); 17065 } 17066 17067 addWeekYearFormatToken('gggg', 'weekYear'); 17068 addWeekYearFormatToken('ggggg', 'weekYear'); 17069 addWeekYearFormatToken('GGGG', 'isoWeekYear'); 17070 addWeekYearFormatToken('GGGGG', 'isoWeekYear'); 17071 17072 // ALIASES 17073 17074 // PARSING 17075 17076 addRegexToken('G', matchSigned); 17077 addRegexToken('g', matchSigned); 17078 addRegexToken('GG', match1to2, match2); 17079 addRegexToken('gg', match1to2, match2); 17080 addRegexToken('GGGG', match1to4, match4); 17081 addRegexToken('gggg', match1to4, match4); 17082 addRegexToken('GGGGG', match1to6, match6); 17083 addRegexToken('ggggg', match1to6, match6); 17084 17085 addWeekParseToken( 17086 ['gggg', 'ggggg', 'GGGG', 'GGGGG'], 17087 function (input, week, config, token) { 17088 week[token.substr(0, 2)] = toInt(input); 17089 } 17090 ); 17091 17092 addWeekParseToken(['gg', 'GG'], function (input, week, config, token) { 17093 week[token] = hooks.parseTwoDigitYear(input); 17094 }); 17095 17096 // MOMENTS 17097 17098 function getSetWeekYear(input) { 17099 return getSetWeekYearHelper.call( 17100 this, 17101 input, 17102 this.week(), 17103 this.weekday() + this.localeData()._week.dow, 17104 this.localeData()._week.dow, 17105 this.localeData()._week.doy 17106 ); 17107 } 17108 17109 function getSetISOWeekYear(input) { 17110 return getSetWeekYearHelper.call( 17111 this, 17112 input, 17113 this.isoWeek(), 17114 this.isoWeekday(), 17115 1, 17116 4 17117 ); 17118 } 17119 17120 function getISOWeeksInYear() { 17121 return weeksInYear(this.year(), 1, 4); 17122 } 17123 17124 function getISOWeeksInISOWeekYear() { 17125 return weeksInYear(this.isoWeekYear(), 1, 4); 17126 } 17127 17128 function getWeeksInYear() { 17129 var weekInfo = this.localeData()._week; 17130 return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy); 17131 } 17132 17133 function getWeeksInWeekYear() { 17134 var weekInfo = this.localeData()._week; 17135 return weeksInYear(this.weekYear(), weekInfo.dow, weekInfo.doy); 17136 } 17137 17138 function getSetWeekYearHelper(input, week, weekday, dow, doy) { 17139 var weeksTarget; 17140 if (input == null) { 17141 return weekOfYear(this, dow, doy).year; 17142 } else { 17143 weeksTarget = weeksInYear(input, dow, doy); 17144 if (week > weeksTarget) { 17145 week = weeksTarget; 17146 } 17147 return setWeekAll.call(this, input, week, weekday, dow, doy); 17148 } 17149 } 17150 17151 function setWeekAll(weekYear, week, weekday, dow, doy) { 17152 var dayOfYearData = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy), 17153 date = createUTCDate(dayOfYearData.year, 0, dayOfYearData.dayOfYear); 17154 17155 this.year(date.getUTCFullYear()); 17156 this.month(date.getUTCMonth()); 17157 this.date(date.getUTCDate()); 17158 return this; 17159 } 17160 17161 // FORMATTING 17162 17163 addFormatToken('Q', 0, 'Qo', 'quarter'); 17164 17165 // PARSING 17166 17167 addRegexToken('Q', match1); 17168 addParseToken('Q', function (input, array) { 17169 array[MONTH] = (toInt(input) - 1) * 3; 17170 }); 17171 17172 // MOMENTS 17173 17174 function getSetQuarter(input) { 17175 return input == null 17176 ? Math.ceil((this.month() + 1) / 3) 17177 : this.month((input - 1) * 3 + (this.month() % 3)); 17178 } 17179 17180 // FORMATTING 17181 17182 addFormatToken('D', ['DD', 2], 'Do', 'date'); 17183 17184 // PARSING 17185 17186 addRegexToken('D', match1to2, match1to2NoLeadingZero); 17187 addRegexToken('DD', match1to2, match2); 17188 addRegexToken('Do', function (isStrict, locale) { 17189 // TODO: Remove "ordinalParse" fallback in next major release. 17190 return isStrict 17191 ? locale._dayOfMonthOrdinalParse || locale._ordinalParse 17192 : locale._dayOfMonthOrdinalParseLenient; 17193 }); 17194 17195 addParseToken(['D', 'DD'], DATE); 17196 addParseToken('Do', function (input, array) { 17197 array[DATE] = toInt(input.match(match1to2)[0]); 17198 }); 17199 17200 // MOMENTS 17201 17202 var getSetDayOfMonth = makeGetSet('Date', true); 17203 17204 // FORMATTING 17205 17206 addFormatToken('DDD', ['DDDD', 3], 'DDDo', 'dayOfYear'); 17207 17208 // PARSING 17209 17210 addRegexToken('DDD', match1to3); 17211 addRegexToken('DDDD', match3); 17212 addParseToken(['DDD', 'DDDD'], function (input, array, config) { 17213 config._dayOfYear = toInt(input); 17214 }); 17215 17216 // HELPERS 17217 17218 // MOMENTS 17219 17220 function getSetDayOfYear(input) { 17221 var dayOfYear = 17222 Math.round( 17223 (this.clone().startOf('day') - this.clone().startOf('year')) / 864e5 17224 ) + 1; 17225 return input == null ? dayOfYear : this.add(input - dayOfYear, 'd'); 17226 } 17227 17228 // FORMATTING 17229 17230 addFormatToken('m', ['mm', 2], 0, 'minute'); 17231 17232 // PARSING 17233 17234 addRegexToken('m', match1to2, match1to2HasZero); 17235 addRegexToken('mm', match1to2, match2); 17236 addParseToken(['m', 'mm'], MINUTE); 17237 17238 // MOMENTS 17239 17240 var getSetMinute = makeGetSet('Minutes', false); 17241 17242 // FORMATTING 17243 17244 addFormatToken('s', ['ss', 2], 0, 'second'); 17245 17246 // PARSING 17247 17248 addRegexToken('s', match1to2, match1to2HasZero); 17249 addRegexToken('ss', match1to2, match2); 17250 addParseToken(['s', 'ss'], SECOND); 17251 17252 // MOMENTS 17253 17254 var getSetSecond = makeGetSet('Seconds', false); 17255 17256 // FORMATTING 17257 17258 addFormatToken('S', 0, 0, function () { 17259 return ~~(this.millisecond() / 100); 17260 }); 17261 17262 addFormatToken(0, ['SS', 2], 0, function () { 17263 return ~~(this.millisecond() / 10); 17264 }); 17265 17266 addFormatToken(0, ['SSS', 3], 0, 'millisecond'); 17267 addFormatToken(0, ['SSSS', 4], 0, function () { 17268 return this.millisecond() * 10; 17269 }); 17270 addFormatToken(0, ['SSSSS', 5], 0, function () { 17271 return this.millisecond() * 100; 17272 }); 17273 addFormatToken(0, ['SSSSSS', 6], 0, function () { 17274 return this.millisecond() * 1000; 17275 }); 17276 addFormatToken(0, ['SSSSSSS', 7], 0, function () { 17277 return this.millisecond() * 10000; 17278 }); 17279 addFormatToken(0, ['SSSSSSSS', 8], 0, function () { 17280 return this.millisecond() * 100000; 17281 }); 17282 addFormatToken(0, ['SSSSSSSSS', 9], 0, function () { 17283 return this.millisecond() * 1000000; 17284 }); 17285 17286 // PARSING 17287 17288 addRegexToken('S', match1to3, match1); 17289 addRegexToken('SS', match1to3, match2); 17290 addRegexToken('SSS', match1to3, match3); 17291 17292 var token, getSetMillisecond; 17293 for (token = 'SSSS'; token.length <= 9; token += 'S') { 17294 addRegexToken(token, matchUnsigned); 17295 } 17296 17297 function parseMs(input, array) { 17298 array[MILLISECOND] = toInt(('0.' + input) * 1000); 17299 } 17300 17301 for (token = 'S'; token.length <= 9; token += 'S') { 17302 addParseToken(token, parseMs); 17303 } 17304 17305 getSetMillisecond = makeGetSet('Milliseconds', false); 17306 17307 // FORMATTING 17308 17309 addFormatToken('z', 0, 0, 'zoneAbbr'); 17310 addFormatToken('zz', 0, 0, 'zoneName'); 17311 17312 // MOMENTS 17313 17314 function getZoneAbbr() { 17315 return this._isUTC ? 'UTC' : ''; 17316 } 17317 17318 function getZoneName() { 17319 return this._isUTC ? 'Coordinated Universal Time' : ''; 17320 } 17321 17322 var proto$2 = Moment.prototype; 17323 17324 proto$2.add = add$1; 17325 proto$2.calendar = calendar; 17326 proto$2.clone = clone$1; 17327 proto$2.diff = diff; 17328 proto$2.endOf = endOf; 17329 proto$2.format = format; 17330 proto$2.from = from; 17331 proto$2.fromNow = fromNow; 17332 proto$2.to = to; 17333 proto$2.toNow = toNow; 17334 proto$2.get = stringGet; 17335 proto$2.invalidAt = invalidAt; 17336 proto$2.isAfter = isAfter; 17337 proto$2.isBefore = isBefore; 17338 proto$2.isBetween = isBetween; 17339 proto$2.isSame = isSame; 17340 proto$2.isSameOrAfter = isSameOrAfter; 17341 proto$2.isSameOrBefore = isSameOrBefore; 17342 proto$2.isValid = isValid; 17343 proto$2.lang = lang; 17344 proto$2.locale = locale; 17345 proto$2.localeData = localeData; 17346 proto$2.max = prototypeMax; 17347 proto$2.min = prototypeMin; 17348 proto$2.parsingFlags = parsingFlags; 17349 proto$2.set = stringSet; 17350 proto$2.startOf = startOf; 17351 proto$2.subtract = subtract$1; 17352 proto$2.toArray = toArray; 17353 proto$2.toObject = toObject; 17354 proto$2.toDate = toDate; 17355 proto$2.toISOString = toISOString$1; 17356 proto$2.inspect = inspect; 17357 if (typeof Symbol !== 'undefined' && Symbol.for != null) { 17358 proto$2[Symbol.for('nodejs.util.inspect.custom')] = function () { 17359 return 'Moment<' + this.format() + '>'; 17360 }; 17361 } 17362 proto$2.toJSON = toJSON; 17363 proto$2.toString = toString; 17364 proto$2.unix = unix; 17365 proto$2.valueOf = valueOf$1; 17366 proto$2.creationData = creationData; 17367 proto$2.eraName = getEraName; 17368 proto$2.eraNarrow = getEraNarrow; 17369 proto$2.eraAbbr = getEraAbbr; 17370 proto$2.eraYear = getEraYear; 17371 proto$2.year = getSetYear; 17372 proto$2.isLeapYear = getIsLeapYear; 17373 proto$2.weekYear = getSetWeekYear; 17374 proto$2.isoWeekYear = getSetISOWeekYear; 17375 proto$2.quarter = proto$2.quarters = getSetQuarter; 17376 proto$2.month = getSetMonth; 17377 proto$2.daysInMonth = getDaysInMonth; 17378 proto$2.week = proto$2.weeks = getSetWeek; 17379 proto$2.isoWeek = proto$2.isoWeeks = getSetISOWeek; 17380 proto$2.weeksInYear = getWeeksInYear; 17381 proto$2.weeksInWeekYear = getWeeksInWeekYear; 17382 proto$2.isoWeeksInYear = getISOWeeksInYear; 17383 proto$2.isoWeeksInISOWeekYear = getISOWeeksInISOWeekYear; 17384 proto$2.date = getSetDayOfMonth; 17385 proto$2.day = proto$2.days = getSetDayOfWeek; 17386 proto$2.weekday = getSetLocaleDayOfWeek; 17387 proto$2.isoWeekday = getSetISODayOfWeek; 17388 proto$2.dayOfYear = getSetDayOfYear; 17389 proto$2.hour = proto$2.hours = getSetHour; 17390 proto$2.minute = proto$2.minutes = getSetMinute; 17391 proto$2.second = proto$2.seconds = getSetSecond; 17392 proto$2.millisecond = proto$2.milliseconds = getSetMillisecond; 17393 proto$2.utcOffset = getSetOffset; 17394 proto$2.utc = setOffsetToUTC; 17395 proto$2.local = setOffsetToLocal; 17396 proto$2.parseZone = setOffsetToParsedOffset; 17397 proto$2.hasAlignedHourOffset = hasAlignedHourOffset; 17398 proto$2.isDST = isDaylightSavingTime; 17399 proto$2.isLocal = isLocal; 17400 proto$2.isUtcOffset = isUtcOffset; 17401 proto$2.isUtc = isUtc; 17402 proto$2.isUTC = isUtc; 17403 proto$2.zoneAbbr = getZoneAbbr; 17404 proto$2.zoneName = getZoneName; 17405 proto$2.dates = deprecate( 17406 'dates accessor is deprecated. Use date instead.', 17407 getSetDayOfMonth 17408 ); 17409 proto$2.months = deprecate( 17410 'months accessor is deprecated. Use month instead', 17411 getSetMonth 17412 ); 17413 proto$2.years = deprecate( 17414 'years accessor is deprecated. Use year instead', 17415 getSetYear 17416 ); 17417 proto$2.zone = deprecate( 17418 'moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/', 17419 getSetZone 17420 ); 17421 proto$2.isDSTShifted = deprecate( 17422 'isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information', 17423 isDaylightSavingTimeShifted 17424 ); 17425 17426 function createUnix(input) { 17427 return createLocal(input * 1000); 17428 } 17429 17430 function createInZone() { 17431 return createLocal.apply(null, arguments).parseZone(); 17432 } 17433 17434 function preParsePostFormat(string) { 17435 return string; 17436 } 17437 17438 var proto$1 = Locale.prototype; 17439 17440 proto$1.calendar = calendar$1; 17441 proto$1.longDateFormat = longDateFormat; 17442 proto$1.invalidDate = invalidDate; 17443 proto$1.ordinal = ordinal; 17444 proto$1.preparse = preParsePostFormat; 17445 proto$1.postformat = preParsePostFormat; 17446 proto$1.relativeTime = relativeTime$1; 17447 proto$1.pastFuture = pastFuture; 17448 proto$1.set = set; 17449 proto$1.eras = localeEras; 17450 proto$1.erasParse = localeErasParse; 17451 proto$1.erasConvertYear = localeErasConvertYear; 17452 proto$1.erasAbbrRegex = erasAbbrRegex; 17453 proto$1.erasNameRegex = erasNameRegex; 17454 proto$1.erasNarrowRegex = erasNarrowRegex; 17455 17456 proto$1.months = localeMonths; 17457 proto$1.monthsShort = localeMonthsShort; 17458 proto$1.monthsParse = localeMonthsParse; 17459 proto$1.monthsRegex = monthsRegex; 17460 proto$1.monthsShortRegex = monthsShortRegex; 17461 proto$1.week = localeWeek; 17462 proto$1.firstDayOfYear = localeFirstDayOfYear; 17463 proto$1.firstDayOfWeek = localeFirstDayOfWeek; 17464 17465 proto$1.weekdays = localeWeekdays; 17466 proto$1.weekdaysMin = localeWeekdaysMin; 17467 proto$1.weekdaysShort = localeWeekdaysShort; 17468 proto$1.weekdaysParse = localeWeekdaysParse; 17469 17470 proto$1.weekdaysRegex = weekdaysRegex; 17471 proto$1.weekdaysShortRegex = weekdaysShortRegex; 17472 proto$1.weekdaysMinRegex = weekdaysMinRegex; 17473 17474 proto$1.isPM = localeIsPM; 17475 proto$1.meridiem = localeMeridiem; 17476 17477 function get$1(format, index, field, setter) { 17478 var locale = getLocale(), 17479 utc = createUTC().set(setter, index); 17480 return locale[field](utc, format); 17481 } 17482 17483 function listMonthsImpl(format, index, field) { 17484 if (isNumber(format)) { 17485 index = format; 17486 format = undefined; 17487 } 17488 17489 format = format || ''; 17490 17491 if (index != null) { 17492 return get$1(format, index, field, 'month'); 17493 } 17494 17495 var i, 17496 out = []; 17497 for (i = 0; i < 12; i++) { 17498 out[i] = get$1(format, i, field, 'month'); 17499 } 17500 return out; 17501 } 17502 17503 // () 17504 // (5) 17505 // (fmt, 5) 17506 // (fmt) 17507 // (true) 17508 // (true, 5) 17509 // (true, fmt, 5) 17510 // (true, fmt) 17511 function listWeekdaysImpl(localeSorted, format, index, field) { 17512 if (typeof localeSorted === 'boolean') { 17513 if (isNumber(format)) { 17514 index = format; 17515 format = undefined; 17516 } 17517 17518 format = format || ''; 17519 } else { 17520 format = localeSorted; 17521 index = format; 17522 localeSorted = false; 17523 17524 if (isNumber(format)) { 17525 index = format; 17526 format = undefined; 17527 } 17528 17529 format = format || ''; 17530 } 17531 17532 var locale = getLocale(), 17533 shift = localeSorted ? locale._week.dow : 0, 17534 i, 17535 out = []; 17536 17537 if (index != null) { 17538 return get$1(format, (index + shift) % 7, field, 'day'); 17539 } 17540 17541 for (i = 0; i < 7; i++) { 17542 out[i] = get$1(format, (i + shift) % 7, field, 'day'); 17543 } 17544 return out; 17545 } 17546 17547 function listMonths(format, index) { 17548 return listMonthsImpl(format, index, 'months'); 17549 } 17550 17551 function listMonthsShort(format, index) { 17552 return listMonthsImpl(format, index, 'monthsShort'); 17553 } 17554 17555 function listWeekdays(localeSorted, format, index) { 17556 return listWeekdaysImpl(localeSorted, format, index, 'weekdays'); 17557 } 17558 17559 function listWeekdaysShort(localeSorted, format, index) { 17560 return listWeekdaysImpl(localeSorted, format, index, 'weekdaysShort'); 17561 } 17562 17563 function listWeekdaysMin(localeSorted, format, index) { 17564 return listWeekdaysImpl(localeSorted, format, index, 'weekdaysMin'); 17565 } 17566 17567 getSetGlobalLocale('en', { 17568 eras: [ 17569 { 17570 since: '0001-01-01', 17571 until: +Infinity, 17572 offset: 1, 17573 name: 'Anno Domini', 17574 narrow: 'AD', 17575 abbr: 'AD', 17576 }, 17577 { 17578 since: '0000-12-31', 17579 until: -Infinity, 17580 offset: 1, 17581 name: 'Before Christ', 17582 narrow: 'BC', 17583 abbr: 'BC', 17584 }, 17585 ], 17586 dayOfMonthOrdinalParse: /\d{1,2}(th|st|nd|rd)/, 17587 ordinal: function (number) { 17588 var b = number % 10, 17589 output = 17590 toInt((number % 100) / 10) === 1 17591 ? 'th' 17592 : b === 1 17593 ? 'st' 17594 : b === 2 17595 ? 'nd' 17596 : b === 3 17597 ? 'rd' 17598 : 'th'; 17599 return number + output; 17600 }, 17601 }); 17602 17603 // Side effect imports 17604 17605 hooks.lang = deprecate( 17606 'moment.lang is deprecated. Use moment.locale instead.', 17607 getSetGlobalLocale 17608 ); 17609 hooks.langData = deprecate( 17610 'moment.langData is deprecated. Use moment.localeData instead.', 17611 getLocale 17612 ); 17613 17614 var mathAbs = Math.abs; 17615 17616 function abs$1() { 17617 var data = this._data; 17618 17619 this._milliseconds = mathAbs(this._milliseconds); 17620 this._days = mathAbs(this._days); 17621 this._months = mathAbs(this._months); 17622 17623 data.milliseconds = mathAbs(data.milliseconds); 17624 data.seconds = mathAbs(data.seconds); 17625 data.minutes = mathAbs(data.minutes); 17626 data.hours = mathAbs(data.hours); 17627 data.months = mathAbs(data.months); 17628 data.years = mathAbs(data.years); 17629 17630 return this; 17631 } 17632 17633 function addSubtract(duration, input, value, direction) { 17634 var other = createDuration(input, value); 17635 17636 duration._milliseconds += direction * other._milliseconds; 17637 duration._days += direction * other._days; 17638 duration._months += direction * other._months; 17639 17640 return duration._bubble(); 17641 } 17642 17643 // supports only 2.0-style add(1, 's') or add(duration) 17644 function add(input, value) { 17645 return addSubtract(this, input, value, 1); 17646 } 17647 17648 // supports only 2.0-style subtract(1, 's') or subtract(duration) 17649 function subtract(input, value) { 17650 return addSubtract(this, input, value, -1); 17651 } 17652 17653 function absCeil(number) { 17654 if (number < 0) { 17655 return Math.floor(number); 17656 } else { 17657 return Math.ceil(number); 17658 } 17659 } 17660 17661 function bubble() { 17662 var milliseconds = this._milliseconds, 17663 days = this._days, 17664 months = this._months, 17665 data = this._data, 17666 seconds, 17667 minutes, 17668 hours, 17669 years, 17670 monthsFromDays; 17671 17672 // if we have a mix of positive and negative values, bubble down first 17673 // check: https://github.com/moment/moment/issues/2166 17674 if (!( 17675 (milliseconds >= 0 && days >= 0 && months >= 0) || 17676 (milliseconds <= 0 && days <= 0 && months <= 0) 17677 )) { 17678 milliseconds += absCeil(monthsToDays(months) + days) * 864e5; 17679 days = 0; 17680 months = 0; 17681 } 17682 17683 // The following code bubbles up values, see the tests for 17684 // examples of what that means. 17685 data.milliseconds = milliseconds % 1000; 17686 17687 seconds = absFloor(milliseconds / 1000); 17688 data.seconds = seconds % 60; 17689 17690 minutes = absFloor(seconds / 60); 17691 data.minutes = minutes % 60; 17692 17693 hours = absFloor(minutes / 60); 17694 data.hours = hours % 24; 17695 17696 days += absFloor(hours / 24); 17697 17698 // convert days to months 17699 monthsFromDays = absFloor(daysToMonths(days)); 17700 months += monthsFromDays; 17701 days -= absCeil(monthsToDays(monthsFromDays)); 17702 17703 // 12 months -> 1 year 17704 years = absFloor(months / 12); 17705 months %= 12; 17706 17707 data.days = days; 17708 data.months = months; 17709 data.years = years; 17710 17711 return this; 17712 } 17713 17714 function daysToMonths(days) { 17715 // 400 years have 146097 days (taking into account leap year rules) 17716 // 400 years have 12 months === 4800 17717 return (days * 4800) / 146097; 17718 } 17719 17720 function monthsToDays(months) { 17721 // the reverse of daysToMonths 17722 return (months * 146097) / 4800; 17723 } 17724 17725 function as(units) { 17726 if (!this.isValid()) { 17727 return NaN; 17728 } 17729 var days, 17730 months, 17731 milliseconds = this._milliseconds; 17732 17733 units = normalizeUnits(units); 17734 17735 if (units === 'month' || units === 'quarter' || units === 'year') { 17736 days = this._days + milliseconds / 864e5; 17737 months = this._months + daysToMonths(days); 17738 switch (units) { 17739 case 'month': 17740 return months; 17741 case 'quarter': 17742 return months / 3; 17743 case 'year': 17744 return months / 12; 17745 } 17746 } else { 17747 // handle milliseconds separately because of floating point math errors (issue #1867) 17748 days = this._days + Math.round(monthsToDays(this._months)); 17749 switch (units) { 17750 case 'week': 17751 return days / 7 + milliseconds / 6048e5; 17752 case 'day': 17753 return days + milliseconds / 864e5; 17754 case 'hour': 17755 return days * 24 + milliseconds / 36e5; 17756 case 'minute': 17757 return days * 1440 + milliseconds / 6e4; 17758 case 'second': 17759 return days * 86400 + milliseconds / 1000; 17760 // Math.floor prevents floating point math errors here 17761 case 'millisecond': 17762 return Math.floor(days * 864e5) + milliseconds; 17763 default: 17764 throw new Error('Unknown unit ' + units); 17765 } 17766 } 17767 } 17768 17769 function makeAs(alias) { 17770 return function () { 17771 return this.as(alias); 17772 }; 17773 } 17774 17775 var asMilliseconds = makeAs('ms'), 17776 asSeconds = makeAs('s'), 17777 asMinutes = makeAs('m'), 17778 asHours = makeAs('h'), 17779 asDays = makeAs('d'), 17780 asWeeks = makeAs('w'), 17781 asMonths = makeAs('M'), 17782 asQuarters = makeAs('Q'), 17783 asYears = makeAs('y'), 17784 valueOf = asMilliseconds; 17785 17786 function clone() { 17787 return createDuration(this); 17788 } 17789 17790 function get(units) { 17791 units = normalizeUnits(units); 17792 return this.isValid() ? this[units + 's']() : NaN; 17793 } 17794 17795 function makeGetter(name) { 17796 return function () { 17797 return this.isValid() ? this._data[name] : NaN; 17798 }; 17799 } 17800 17801 var milliseconds = makeGetter('milliseconds'), 17802 seconds = makeGetter('seconds'), 17803 minutes = makeGetter('minutes'), 17804 hours = makeGetter('hours'), 17805 days = makeGetter('days'), 17806 months = makeGetter('months'), 17807 years = makeGetter('years'); 17808 17809 function weeks() { 17810 return absFloor(this.days() / 7); 17811 } 17812 17813 var round = Math.round, 17814 thresholds = { 17815 ss: 44, // a few seconds to seconds 17816 s: 45, // seconds to minute 17817 m: 45, // minutes to hour 17818 h: 22, // hours to day 17819 d: 26, // days to month/week 17820 w: null, // weeks to month 17821 M: 11, // months to year 17822 }; 17823 17824 // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize 17825 function substituteTimeAgo(string, number, withoutSuffix, isFuture, locale) { 17826 return relativeTimeWithoutPostformat.call( 17827 locale, 17828 number || 1, 17829 !!withoutSuffix, 17830 string, 17831 isFuture 17832 ); 17833 } 17834 17835 function relativeTime(posNegDuration, withoutSuffix, thresholds, locale) { 17836 var duration = createDuration(posNegDuration).abs(), 17837 seconds = round(duration.as('s')), 17838 minutes = round(duration.as('m')), 17839 hours = round(duration.as('h')), 17840 days = round(duration.as('d')), 17841 months = round(duration.as('M')), 17842 weeks = round(duration.as('w')), 17843 years = round(duration.as('y')), 17844 a = 17845 (seconds <= thresholds.ss && ['s', seconds]) || 17846 (seconds < thresholds.s && ['ss', seconds]) || 17847 (minutes <= 1 && ['m']) || 17848 (minutes < thresholds.m && ['mm', minutes]) || 17849 (hours <= 1 && ['h']) || 17850 (hours < thresholds.h && ['hh', hours]) || 17851 (days <= 1 && ['d']) || 17852 (days < thresholds.d && ['dd', days]); 17853 17854 if (thresholds.w != null) { 17855 a = 17856 a || 17857 (weeks <= 1 && ['w']) || 17858 (weeks < thresholds.w && ['ww', weeks]); 17859 } 17860 a = a || 17861 (months <= 1 && ['M']) || 17862 (months < thresholds.M && ['MM', months]) || 17863 (years <= 1 && ['y']) || ['yy', years]; 17864 17865 a[2] = withoutSuffix; 17866 a[3] = +posNegDuration > 0; 17867 a[4] = locale; 17868 return substituteTimeAgo.apply(null, a); 17869 } 17870 17871 // This function allows you to set the rounding function for relative time strings 17872 function getSetRelativeTimeRounding(roundingFunction) { 17873 if (roundingFunction === undefined) { 17874 return round; 17875 } 17876 if (typeof roundingFunction === 'function') { 17877 round = roundingFunction; 17878 return true; 17879 } 17880 return false; 17881 } 17882 17883 // This function allows you to set a threshold for relative time strings 17884 function getSetRelativeTimeThreshold(threshold, limit) { 17885 if (thresholds[threshold] === undefined) { 17886 return false; 17887 } 17888 if (limit === undefined) { 17889 return thresholds[threshold]; 17890 } 17891 thresholds[threshold] = limit; 17892 if (threshold === 's') { 17893 thresholds.ss = limit - 1; 17894 } 17895 return true; 17896 } 17897 17898 function humanize(argWithSuffix, argThresholds) { 17899 if (!this.isValid()) { 17900 return this.localeData().invalidDate(); 17901 } 17902 17903 var withSuffix = false, 17904 th = thresholds, 17905 locale, 17906 output; 17907 17908 if (typeof argWithSuffix === 'object') { 17909 argThresholds = argWithSuffix; 17910 argWithSuffix = false; 17911 } 17912 if (typeof argWithSuffix === 'boolean') { 17913 withSuffix = argWithSuffix; 17914 } 17915 if (typeof argThresholds === 'object') { 17916 th = extend(extend({}, thresholds), argThresholds || {}); 17917 if (argThresholds.s != null && argThresholds.ss == null) { 17918 th.ss = argThresholds.s - 1; 17919 } 17920 } 17921 17922 locale = this.localeData(); 17923 output = relativeTime(this, !withSuffix, th, locale); 17924 17925 if (withSuffix) { 17926 output = pastFutureWithoutPostformat.call(locale, +this, output); 17927 } 17928 17929 return locale.postformat(output); 17930 } 17931 17932 var abs = Math.abs; 17933 17934 function sign(x) { 17935 return (x > 0) - (x < 0) || +x; 17936 } 17937 17938 function toISOString() { 17939 // for ISO strings we do not use the normal bubbling rules: 17940 // * milliseconds bubble up until they become hours 17941 // * days do not bubble at all 17942 // * months bubble up until they become years 17943 // This is because there is no context-free conversion between hours and days 17944 // (think of clock changes) 17945 // and also not between days and months (28-31 days per month) 17946 if (!this.isValid()) { 17947 return this.localeData().invalidDate(); 17948 } 17949 17950 var seconds = abs(this._milliseconds) / 1000, 17951 days = abs(this._days), 17952 months = abs(this._months), 17953 minutes, 17954 hours, 17955 years, 17956 s, 17957 total = this.asSeconds(), 17958 totalSign, 17959 ymSign, 17960 daysSign, 17961 hmsSign; 17962 17963 if (!total) { 17964 // this is the same as C#'s (Noda) and python (isodate)... 17965 // but not other JS (goog.date) 17966 return 'P0D'; 17967 } 17968 17969 // 3600 seconds -> 60 minutes -> 1 hour 17970 minutes = absFloor(seconds / 60); 17971 hours = absFloor(minutes / 60); 17972 seconds %= 60; 17973 minutes %= 60; 17974 17975 // 12 months -> 1 year 17976 years = absFloor(months / 12); 17977 months %= 12; 17978 17979 // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js 17980 s = seconds ? seconds.toFixed(3).replace(/\.?0+$/, '') : ''; 17981 17982 totalSign = total < 0 ? '-' : ''; 17983 ymSign = sign(this._months) !== sign(total) ? '-' : ''; 17984 daysSign = sign(this._days) !== sign(total) ? '-' : ''; 17985 hmsSign = sign(this._milliseconds) !== sign(total) ? '-' : ''; 17986 17987 return ( 17988 totalSign + 17989 'P' + 17990 (years ? ymSign + years + 'Y' : '') + 17991 (months ? ymSign + months + 'M' : '') + 17992 (days ? daysSign + days + 'D' : '') + 17993 (hours || minutes || seconds ? 'T' : '') + 17994 (hours ? hmsSign + hours + 'H' : '') + 17995 (minutes ? hmsSign + minutes + 'M' : '') + 17996 (seconds ? hmsSign + s + 'S' : '') 17997 ); 17998 } 17999 18000 var proto = Duration.prototype; 18001 18002 proto.isValid = isValid$1; 18003 proto.abs = abs$1; 18004 proto.add = add; 18005 proto.subtract = subtract; 18006 proto.as = as; 18007 proto.asMilliseconds = asMilliseconds; 18008 proto.asSeconds = asSeconds; 18009 proto.asMinutes = asMinutes; 18010 proto.asHours = asHours; 18011 proto.asDays = asDays; 18012 proto.asWeeks = asWeeks; 18013 proto.asMonths = asMonths; 18014 proto.asQuarters = asQuarters; 18015 proto.asYears = asYears; 18016 proto.valueOf = valueOf; 18017 proto._bubble = bubble; 18018 proto.clone = clone; 18019 proto.get = get; 18020 proto.milliseconds = milliseconds; 18021 proto.seconds = seconds; 18022 proto.minutes = minutes; 18023 proto.hours = hours; 18024 proto.days = days; 18025 proto.weeks = weeks; 18026 proto.months = months; 18027 proto.years = years; 18028 proto.humanize = humanize; 18029 proto.toISOString = toISOString; 18030 proto.toString = toISOString; 18031 proto.toJSON = toISOString; 18032 proto.locale = locale; 18033 proto.localeData = localeData; 18034 18035 proto.toIsoString = deprecate( 18036 'toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)', 18037 toISOString 18038 ); 18039 proto.lang = lang; 18040 18041 // FORMATTING 18042 18043 addFormatToken('X', 0, 0, 'unix'); 18044 addFormatToken('x', 0, 0, 'valueOf'); 18045 18046 // PARSING 18047 18048 addRegexToken('x', matchSigned); 18049 addRegexToken('X', matchTimestamp); 18050 addParseToken('X', function (input, array, config) { 18051 config._d = new Date(parseFloat(input) * 1000); 18052 }); 18053 addParseToken('x', function (input, array, config) { 18054 config._d = new Date(toInt(input)); 18055 }); 18056 18057 //! moment.js 18058 18059 hooks.version = '2.31.0'; 18060 18061 setHookCallback(createLocal); 18062 18063 hooks.fn = proto$2; 18064 hooks.min = min; 18065 hooks.max = max; 18066 hooks.now = now; 18067 hooks.utc = createUTC; 18068 hooks.unix = createUnix; 18069 hooks.months = listMonths; 18070 hooks.isDate = isDate; 18071 hooks.locale = getSetGlobalLocale; 18072 hooks.invalid = createInvalid$1; 18073 hooks.duration = createDuration; 18074 hooks.isMoment = isMoment; 18075 hooks.weekdays = listWeekdays; 18076 hooks.parseZone = createInZone; 18077 hooks.localeData = getLocale; 18078 hooks.isDuration = isDuration; 18079 hooks.monthsShort = listMonthsShort; 18080 hooks.weekdaysMin = listWeekdaysMin; 18081 hooks.defineLocale = defineLocale; 18082 hooks.updateLocale = updateLocale; 18083 hooks.locales = listLocales; 18084 hooks.weekdaysShort = listWeekdaysShort; 18085 hooks.normalizeUnits = normalizeUnits; 18086 hooks.relativeTimeRounding = getSetRelativeTimeRounding; 18087 hooks.relativeTimeThreshold = getSetRelativeTimeThreshold; 18088 hooks.calendarFormat = getCalendarFormat; 18089 hooks.prototype = proto$2; 18090 18091 // currently HTML5 input type only supports 24-hour formats 18092 hooks.HTML5_FMT = { 18093 DATETIME_LOCAL: 'YYYY-MM-DDTHH:mm', // <input type="datetime-local" /> 18094 DATETIME_LOCAL_SECONDS: 'YYYY-MM-DDTHH:mm:ss', // <input type="datetime-local" step="1" /> 18095 DATETIME_LOCAL_MS: 'YYYY-MM-DDTHH:mm:ss.SSS', // <input type="datetime-local" step="0.001" /> 18096 DATE: 'YYYY-MM-DD', // <input type="date" /> 18097 TIME: 'HH:mm', // <input type="time" /> 18098 TIME_SECONDS: 'HH:mm:ss', // <input type="time" step="1" /> 18099 TIME_MS: 'HH:mm:ss.SSS', // <input type="time" step="0.001" /> 18100 WEEK: 'GGGG-[W]WW', // <input type="week" /> 18101 MONTH: 'YYYY-MM', // <input type="month" /> 18102 }; 18103 18104 return hooks; 18105 18106})));
18107 18108/* 18109//! version : 3.0.3 18110========================================================= 18111bootstrap-datetimepicker.js 18112https://github.com/Eonasdan/bootstrap-datetimepicker 18113========================================================= 18114The MIT License (MIT) 18115 18116Copyright (c) 2014 Jonathan Peterson 18117 18118Permission is hereby granted, free of charge, to any person obtaining a copy 18119of this software and associated documentation files (the "Software"), to deal 18120in the Software without restriction, including without limitation the rights 18121to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18122copies of the Software, and to permit persons to whom the Software is 18123furnished to do so, subject to the following conditions: 18124 18125The above copyright notice and this permission notice shall be included in 18126all copies or substantial portions of the Software. 18127 18128THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18129IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18130FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18131AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18132LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18133OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 18134THE SOFTWARE. 18135*/ 18136;(function (root, factory) { 18137 'use strict'; 18138 if (typeof define === 'function' && define.amd) { 18139 // AMD is used - Register as an anonymous module. 18140 define('bootstrapDateTimePicker',['jquery', 'moment'], factory); 18141 } else { 18142 // AMD is not used - Attempt to fetch dependencies from scope. 18143 if (!jQuery) { 18144 throw new Error('bootstrap-datetimepicker requires jQuery to be loaded first'); 18145 } 18146 if (!moment) { 18147 throw new Error('bootstrap-datetimepicker requires moment.js to be loaded first'); 18148 } 18149 factory(root.jQuery, moment); 18150 } 18151}(this, function ($, moment) { 18152 'use strict'; 18153 if (typeof moment === 'undefined') { 18154 throw new Error('momentjs is required'); 18155 } 18156 18157 var dpgId = 0, 18158 18159 DateTimePicker = function (element, options) { 18160 var defaults = $.fn.datetimepicker.defaults, 18161 18162 icons = { 18163 time: 'glyphicon glyphicon-time', 18164 date: 'glyphicon glyphicon-calendar', 18165 up: 'glyphicon glyphicon-chevron-up', 18166 down: 'glyphicon glyphicon-chevron-down' 18167 }, 18168 18169 picker = this, 18170 18171 dDate, 18172 18173 init = function () { 18174 var icon = false, localeData, rInterval; 18175 picker.options = $.extend({}, defaults, options); 18176 picker.options.icons = $.extend({}, icons, picker.options.icons); 18177 18178 picker.element = $(element); 18179 18180 dataToOptions(); 18181 18182 if (!(picker.options.pickTime || picker.options.pickDate)) { 18183 throw new Error('Must choose at least one picker'); 18184 } 18185 18186 picker.id = dpgId++; 18187 moment.locale(picker.options.language); 18188 picker.date = moment(); 18189 picker.unset = false; 18190 picker.isInput = picker.element.is('input'); 18191 picker.component = false; 18192 18193 if (picker.element.hasClass('input-group')) { 18194 if (picker.element.find('.datepickerbutton').size() === 0) {//in case there is more then one 'input-group-addon' Issue #48 18195 picker.component = picker.element.find('[class^="input-group-"]'); 18196 } 18197 else { 18198 picker.component = picker.element.find('.datepickerbutton'); 18199 } 18200 } 18201 picker.format = picker.options.format; 18202 18203 localeData = moment().localeData(); 18204 18205 if (!picker.format) { 18206 picker.format = (picker.options.pickDate ? localeData.longDateFormat('L') : ''); 18207 if (picker.options.pickDate && picker.options.pickTime) { 18208 picker.format += ' '; 18209 } 18210 picker.format += (picker.options.pickTime ? localeData.longDateFormat('LT') : ''); 18211 if (picker.options.useSeconds) { 18212 if (localeData.longDateFormat('LT').indexOf(' A') !== -1) { 18213 picker.format = picker.format.split(' A')[0] + ':ss A'; 18214 } 18215 else { 18216 picker.format += ':ss'; 18217 } 18218 } 18219 } 18220 picker.use24hours = picker.format.toLowerCase().indexOf('a') < 1; 18221 18222 if (picker.component) { 18223 icon = picker.component.find('span'); 18224 } 18225 18226 if (picker.options.pickTime) { 18227 if (icon) { 18228 icon.addClass(picker.options.icons.time); 18229 } 18230 } 18231 if (picker.options.pickDate) { 18232 if (icon) { 18233 icon.removeClass(picker.options.icons.time); 18234 icon.addClass(picker.options.icons.date); 18235 } 18236 } 18237 18238 picker.options.widgetParent = 18239 typeof picker.options.widgetParent === 'string' && picker.options.widgetParent || 18240 picker.element.parents().filter(function () { 18241 return 'scroll' === $(this).css('overflow-y'); 18242 }).get(0) || 18243 'body'; 18244 18245 picker.widget = $(getTemplate()).appendTo(picker.options.widgetParent); 18246 18247 picker.minViewMode = picker.options.minViewMode || 0; 18248 if (typeof picker.minViewMode === 'string') { 18249 switch (picker.minViewMode) { 18250 case 'months': 18251 picker.minViewMode = 1; 18252 break; 18253 case 'years': 18254 picker.minViewMode = 2; 18255 break; 18256 default: 18257 picker.minViewMode = 0; 18258 break; 18259 } 18260 } 18261 picker.viewMode = picker.options.viewMode || 0; 18262 if (typeof picker.viewMode === 'string') { 18263 switch (picker.viewMode) { 18264 case 'months': 18265 picker.viewMode = 1; 18266 break; 18267 case 'years': 18268 picker.viewMode = 2; 18269 break; 18270 default: 18271 picker.viewMode = 0; 18272 break; 18273 } 18274 } 18275 18276 picker.viewMode = Math.max(picker.viewMode, picker.minViewMode); 18277 18278 picker.options.disabledDates = indexGivenDates(picker.options.disabledDates); 18279 picker.options.enabledDates = indexGivenDates(picker.options.enabledDates); 18280 18281 picker.startViewMode = picker.viewMode; 18282 picker.setMinDate(picker.options.minDate); 18283 picker.setMaxDate(picker.options.maxDate); 18284 fillDow(); 18285 fillMonths(); 18286 fillHours(); 18287 fillMinutes(); 18288 fillSeconds(); 18289 update(); 18290 showMode(); 18291 attachDatePickerEvents(); 18292 if (picker.options.defaultDate !== '' && getPickerInput().val() === '') { 18293 picker.setValue(picker.options.defaultDate); 18294 } 18295 if (picker.options.minuteStepping !== 1) { 18296 rInterval = picker.options.minuteStepping; 18297 picker.date.minutes((Math.round(picker.date.minutes() / rInterval) * rInterval) % 60).seconds(0); 18298 } 18299 }, 18300 18301 getPickerInput = function () { 18302 var input; 18303 18304 if (picker.isInput) { 18305 return picker.element; 18306 } 18307 input = picker.element.find('.datepickerinput'); 18308 if (input.size() === 0) { 18309 input = picker.element.find('input'); 18310 } 18311 else if (!input.is('input')) { 18312 throw new Error('CSS class "datepickerinput" cannot be applied to non input element'); 18313 } 18314 return input; 18315 }, 18316 18317 dataToOptions = function () { 18318 var eData; 18319 if (picker.element.is('input')) { 18320 eData = picker.element.data(); 18321 } 18322 else { 18323 eData = picker.element.find('input').data(); 18324 } 18325 if (eData.dateFormat !== undefined) { 18326 picker.options.format = eData.dateFormat; 18327 } 18328 if (eData.datePickdate !== undefined) { 18329 picker.options.pickDate = eData.datePickdate; 18330 } 18331 if (eData.datePicktime !== undefined) { 18332 picker.options.pickTime = eData.datePicktime; 18333 } 18334 if (eData.dateUseminutes !== undefined) { 18335 picker.options.useMinutes = eData.dateUseminutes; 18336 } 18337 if (eData.dateUseseconds !== undefined) { 18338 picker.options.useSeconds = eData.dateUseseconds; 18339 } 18340 if (eData.dateUsecurrent !== undefined) { 18341 picker.options.useCurrent = eData.dateUsecurrent; 18342 } 18343 if (eData.dateMinutestepping !== undefined) { 18344 picker.options.minuteStepping = eData.dateMinutestepping; 18345 } 18346 if (eData.dateMindate !== undefined) { 18347 picker.options.minDate = eData.dateMindate; 18348 } 18349 if (eData.dateMaxdate !== undefined) { 18350 picker.options.maxDate = eData.dateMaxdate; 18351 } 18352 if (eData.dateShowtoday !== undefined) { 18353 picker.options.showToday = eData.dateShowtoday; 18354 } 18355 if (eData.dateCollapse !== undefined) { 18356 picker.options.collapse = eData.dateCollapse; 18357 } 18358 if (eData.dateLanguage !== undefined) { 18359 picker.options.language = eData.dateLanguage; 18360 } 18361 if (eData.dateDefaultdate !== undefined) { 18362 picker.options.defaultDate = eData.dateDefaultdate; 18363 } 18364 if (eData.dateDisableddates !== undefined) { 18365 picker.options.disabledDates = eData.dateDisableddates; 18366 } 18367 if (eData.dateEnableddates !== undefined) { 18368 picker.options.enabledDates = eData.dateEnableddates; 18369 } 18370 if (eData.dateIcons !== undefined) { 18371 picker.options.icons = eData.dateIcons; 18372 } 18373 if (eData.dateUsestrict !== undefined) { 18374 picker.options.useStrict = eData.dateUsestrict; 18375 } 18376 if (eData.dateDirection !== undefined) { 18377 picker.options.direction = eData.dateDirection; 18378 } 18379 if (eData.dateSidebyside !== undefined) { 18380 picker.options.sideBySide = eData.dateSidebyside; 18381 } 18382 if (eData.dateDaysofweekdisabled !== undefined) { 18383 picker.options.daysOfWeekDisabled = eData.dateDaysofweekdisabled; 18384 } 18385// $.each(defaults, function (key) { 18386// var attributeName = 'date' + key.charAt(0).toUpperCase() + key.slice(1); 18387// if (eData[attributeName] !== undefined) { 18388// picker.options[key] = eData[attributeName]; 18389// } 18390// }); 18391 }, 18392 18393 place = function () { 18394 var position = 'absolute', 18395 offset = picker.component ? picker.component.offset() : picker.element.offset(), 18396 $window = $(window), 18397 placePosition; 18398 18399 picker.width = picker.component ? picker.component.outerWidth() : picker.element.outerWidth(); 18400 offset.top = offset.top + picker.element.outerHeight(); 18401 18402 if (picker.options.direction === 'up') { 18403 placePosition = 'top'; 18404 } else if (picker.options.direction === 'bottom') { 18405 placePosition = 'bottom'; 18406 } else if (picker.options.direction === 'auto') { 18407 if (offset.top + picker.widget.height() > $window.height() + $window.scrollTop() && picker.widget.height() + picker.element.outerHeight() < offset.top) { 18408 placePosition = 'top'; 18409 } else { 18410 placePosition = 'bottom'; 18411 } 18412 } 18413 if (placePosition === 'top') { 18414 offset.top -= picker.widget.height() + picker.element.outerHeight() + 15; 18415 picker.widget.addClass('top').removeClass('bottom'); 18416 } else { 18417 offset.top += 1; 18418 picker.widget.addClass('bottom').removeClass('top'); 18419 } 18420 18421 if (picker.options.width !== undefined) { 18422 picker.widget.width(picker.options.width); 18423 } 18424 18425 if (picker.options.orientation === 'left') { 18426 picker.widget.addClass('left-oriented'); 18427 offset.left = offset.left - picker.widget.width() + 20; 18428 } 18429 18430 if (isInFixed()) { 18431 position = 'fixed'; 18432 offset.top -= $window.scrollTop(); 18433 offset.left -= $window.scrollLeft(); 18434 } 18435 18436 if ($window.width() < offset.left + picker.widget.outerWidth()) { 18437 offset.right = $window.width() - offset.left - picker.width; 18438 offset.left = 'auto'; 18439 picker.widget.addClass('pull-right'); 18440 } else { 18441 offset.right = 'auto'; 18442 picker.widget.removeClass('pull-right'); 18443 } 18444 18445 picker.widget.css({ 18446 position: position, 18447 top: offset.top, 18448 left: offset.left, 18449 right: offset.right 18450 }); 18451 }, 18452 18453 notifyChange = function (oldDate, eventType) { 18454 if (moment(picker.date).isSame(moment(oldDate))) { 18455 return; 18456 } 18457 picker.element.trigger({ 18458 type: 'dp.change', 18459 date: moment(picker.date), 18460 oldDate: moment(oldDate) 18461 }); 18462 18463 if (eventType !== 'change') { 18464 picker.element.change(); 18465 } 18466 }, 18467 18468 notifyError = function (date) { 18469 picker.element.trigger({ 18470 type: 'dp.error', 18471 date: moment(date, picker.format, picker.options.useStrict) 18472 }); 18473 }, 18474 18475 update = function (newDate) { 18476 moment.locale(picker.options.language); 18477 var dateStr = newDate; 18478 if (!dateStr) { 18479 dateStr = getPickerInput().val(); 18480 if (dateStr) { 18481 picker.date = moment(dateStr, picker.format, picker.options.useStrict); 18482 } 18483 if (!picker.date) { 18484 picker.date = moment(); 18485 } 18486 } 18487 picker.viewDate = moment(picker.date).startOf('month'); 18488 fillDate(); 18489 fillTime(); 18490 }, 18491 18492 fillDow = function () { 18493 moment.locale(picker.options.language); 18494 var html = $('<tr>'), weekdaysMin = moment.weekdaysMin(), i; 18495 if (moment().localeData()._week.dow === 0) { // starts on Sunday 18496 for (i = 0; i < 7; i++) { 18497 html.append('<th class="dow">' + weekdaysMin[i] + '</th>'); 18498 } 18499 } else { 18500 for (i = 1; i < 8; i++) { 18501 if (i === 7) { 18502 html.append('<th class="dow">' + weekdaysMin[0] + '</th>'); 18503 } else { 18504 html.append('<th class="dow">' + weekdaysMin[i] + '</th>'); 18505 } 18506 } 18507 } 18508 picker.widget.find('.datepicker-days thead').append(html); 18509 }, 18510 18511 fillMonths = function () { 18512 moment.locale(picker.options.language); 18513 var html = '', i, monthsShort = moment.monthsShort(); 18514 for (i = 0; i < 12; i++) { 18515 html += '<span class="month">' + monthsShort[i] + '</span>'; 18516 } 18517 picker.widget.find('.datepicker-months td').append(html); 18518 }, 18519 18520 fillDate = function () { 18521 if (!picker.options.pickDate) { 18522 return; 18523 } 18524 moment.locale(picker.options.language); 18525 var year = picker.viewDate.year(),
18526 month = picker.viewDate.month(), 18527 startYear = picker.options.minDate.year(), 18528 startMonth = picker.options.minDate.month(), 18529 endYear = picker.options.maxDate.year(), 18530 endMonth = picker.options.maxDate.month(), 18531 currentDate, 18532 prevMonth, nextMonth, html = [], row, clsName, i, days, yearCont, currentYear, months = moment.months(); 18533 18534 picker.widget.find('.datepicker-days').find('.disabled').removeClass('disabled'); 18535 picker.widget.find('.datepicker-months').find('.disabled').removeClass('disabled'); 18536 picker.widget.find('.datepicker-years').find('.disabled').removeClass('disabled'); 18537 18538 picker.widget.find('.datepicker-days th:eq(1)').text( 18539 months[month] + ' ' + year); 18540 18541 prevMonth = moment(picker.viewDate, picker.format, picker.options.useStrict).subtract(1, 'months'); 18542 days = prevMonth.daysInMonth(); 18543 prevMonth.date(days).startOf('week'); 18544 if ((year === startYear && month <= startMonth) || year < startYear) { 18545 picker.widget.find('.datepicker-days th:eq(0)').addClass('disabled'); 18546 } 18547 if ((year === endYear && month >= endMonth) || year > endYear) { 18548 picker.widget.find('.datepicker-days th:eq(2)').addClass('disabled'); 18549 } 18550 18551 nextMonth = moment(prevMonth).add(42, 'd'); 18552 while (prevMonth.isBefore(nextMonth)) { 18553 if (prevMonth.weekday() === moment().startOf('week').weekday()) { 18554 row = $('<tr>'); 18555 html.push(row); 18556 } 18557 clsName = ''; 18558 if (prevMonth.year() < year || (prevMonth.year() === year && prevMonth.month() < month)) { 18559 clsName += ' old'; 18560 } else if (prevMonth.year() > year || (prevMonth.year() === year && prevMonth.month() > month)) { 18561 clsName += ' new'; 18562 } 18563 if (prevMonth.isSame(moment({y: picker.date.year(), M: picker.date.month(), d: picker.date.date()}))) { 18564 clsName += ' active'; 18565 } 18566 if (isInDisableDates(prevMonth, 'day') || !isInEnableDates(prevMonth)) { 18567 clsName += ' disabled'; 18568 } 18569 if (picker.options.showToday === true) { 18570 if (prevMonth.isSame(moment(), 'day')) { 18571 clsName += ' today'; 18572 } 18573 } 18574 if (picker.options.daysOfWeekDisabled) { 18575 for (i = 0; i < picker.options.daysOfWeekDisabled.length; i++) { 18576 if (prevMonth.day() === picker.options.daysOfWeekDisabled[i]) { 18577 clsName += ' disabled'; 18578 break; 18579 } 18580 } 18581 } 18582 row.append('<td class="day' + clsName + '">' + prevMonth.date() + '</td>'); 18583 18584 currentDate = prevMonth.date(); 18585 prevMonth.add(1, 'd'); 18586 18587 if (currentDate === prevMonth.date()) { 18588 prevMonth.add(1, 'd'); 18589 } 18590 } 18591 picker.widget.find('.datepicker-days tbody').empty().append(html); 18592 currentYear = picker.date.year(); 18593 months = picker.widget.find('.datepicker-months').find('th:eq(1)').text(year).end().find('span').removeClass('active'); 18594 if (currentYear === year) { 18595 months.eq(picker.date.month()).addClass('active'); 18596 } 18597 if (year - 1 < startYear) { 18598 picker.widget.find('.datepicker-months th:eq(0)').addClass('disabled'); 18599 } 18600 if (year + 1 > endYear) { 18601 picker.widget.find('.datepicker-months th:eq(2)').addClass('disabled'); 18602 } 18603 for (i = 0; i < 12; i++) { 18604 if ((year === startYear && startMonth > i) || (year < startYear)) { 18605 $(months[i]).addClass('disabled'); 18606 } else if ((year === endYear && endMonth < i) || (year > endYear)) { 18607 $(months[i]).addClass('disabled'); 18608 } 18609 } 18610 18611 html = ''; 18612 year = parseInt(year / 10, 10) * 10; 18613 yearCont = picker.widget.find('.datepicker-years').find( 18614 'th:eq(1)').text(year + '-' + (year + 9)).parents('table').find('td'); 18615 picker.widget.find('.datepicker-years').find('th').removeClass('disabled'); 18616 if (startYear > year) { 18617 picker.widget.find('.datepicker-years').find('th:eq(0)').addClass('disabled'); 18618 } 18619 if (endYear < year + 9) { 18620 picker.widget.find('.datepicker-years').find('th:eq(2)').addClass('disabled'); 18621 } 18622 year -= 1; 18623 for (i = -1; i < 11; i++) { 18624 html += '<span class="year' + (i === -1 || i === 10 ? ' old' : '') + (currentYear === year ? ' active' : '') + ((year < startYear || year > endYear) ? ' disabled' : '') + '">' + year + '</span>'; 18625 year += 1; 18626 } 18627 yearCont.html(html); 18628 }, 18629 18630 fillHours = function () { 18631 moment.locale(picker.options.language); 18632 var table = picker.widget.find('.timepicker .timepicker-hours table'), html = '', current, i, j; 18633 table.parent().hide(); 18634 if (picker.use24hours) { 18635 current = 0; 18636 for (i = 0; i < 6; i += 1) { 18637 html += '<tr>'; 18638 for (j = 0; j < 4; j += 1) { 18639 html += '<td class="hour">' + padLeft(current.toString()) + '</td>'; 18640 current++; 18641 } 18642 html += '</tr>'; 18643 } 18644 } 18645 else { 18646 current = 1; 18647 for (i = 0; i < 3; i += 1) { 18648 html += '<tr>'; 18649 for (j = 0; j < 4; j += 1) { 18650 html += '<td class="hour">' + padLeft(current.toString()) + '</td>'; 18651 current++; 18652 } 18653 html += '</tr>'; 18654 } 18655 } 18656 table.html(html); 18657 }, 18658 18659 fillMinutes = function () { 18660 var table = picker.widget.find('.timepicker .timepicker-minutes table'), html = '', current = 0, i, j, step = picker.options.minuteStepping; 18661 table.parent().hide(); 18662 if (step === 1) { 18663 step = 5; 18664 } 18665 for (i = 0;
18665 i < Math.ceil(60 / step / 4) ; i++) { 18666 html += '<tr>'; 18667 for (j = 0; j < 4; j += 1) { 18668 if (current < 60) { 18669 html += '<td class="minute">' + padLeft(current.toString()) + '</td>'; 18670 current += step; 18671 } else { 18672 html += '<td></td>'; 18673 } 18674 } 18675 html += '</tr>'; 18676 } 18677 table.html(html); 18678 }, 18679 18680 fillSeconds = function () { 18681 var table = picker.widget.find('.timepicker .timepicker-seconds table'), html = '', current = 0, i, j; 18682 table.parent().hide(); 18683 for (i = 0; i < 3; i++) { 18684 html += '<tr>'; 18685 for (j = 0; j < 4; j += 1) { 18686 html += '<td class="second">' + padLeft(current.toString()) + '</td>'; 18687 current += 5; 18688 } 18689 html += '</tr>'; 18690 } 18691 table.html(html); 18692 }, 18693 18694 fillTime = function () { 18695 if (!picker.date) { 18696 return; 18697 } 18698 var timeComponents = picker.widget.find('.timepicker span[data-time-component]'), 18699 hour = picker.date.hours(), 18700 period = picker.date.format('A'); 18701 if (!picker.use24hours) { 18702 if (hour === 0) { 18703 hour = 12; 18704 } else if (hour !== 12) { 18705 hour = hour % 12; 18706 } 18707 picker.widget.find('.timepicker [data-action=togglePeriod]').text(period); 18708 } 18709 timeComponents.filter('[data-time-component=hours]').text(padLeft(hour)); 18710 timeComponents.filter('[data-time-component=minutes]').text(padLeft(picker.date.minutes())); 18711 timeComponents.filter('[data-time-component=seconds]').text(padLeft(picker.date.second())); 18712 }, 18713 18714 click = function (e) { 18715 e.stopPropagation(); 18716 e.preventDefault(); 18717 picker.unset = false; 18718 var target = $(e.target).closest('span, td, th'), month, year, step, day, oldDate = moment(picker.date); 18719 if (target.length === 1) { 18720 if (!target.is('.disabled')) { 18721 switch (target[0].nodeName.toLowerCase()) { 18722 case 'th': 18723 switch (target[0].className) { 18724 case 'picker-switch': 18725 showMode(1); 18726 break; 18727 case 'prev': 18728 case 'next': 18729 step = dpGlobal.modes[picker.viewMode].navStep; 18730 if (target[0].className === 'prev') { 18731 step = step * -1; 18732 } 18733 picker.viewDate.add(step, dpGlobal.modes[picker.viewMode].navFnc); 18734 fillDate(); 18735 break; 18736 } 18737 break; 18738 case 'span': 18739 if (target.is('.month')) { 18740 month = target.parent().find('span').index(target); 18741 picker.viewDate.month(month); 18742 } else { 18743 year = parseInt(target.text(), 10) || 0; 18744 picker.viewDate.year(year); 18745 } 18746 if (picker.viewMode === picker.minViewMode) { 18747 picker.date = moment({ 18748 y: picker.viewDate.year(), 18749 M: picker.viewDate.month(), 18750 d: picker.viewDate.date(), 18751 h: picker.date.hours(), 18752 m: picker.date.minutes(), 18753 s: picker.date.seconds() 18754 }); 18755 set(); 18756 notifyChange(oldDate, e.type); 18757 } 18758 showMode(-1); 18759 fillDate(); 18760 break; 18761 case 'td': 18762 if (target.is('.day')) { 18763 day = parseInt(target.text(), 10) || 1;
18764 month = picker.viewDate.month(); 18765 year = picker.viewDate.year(); 18766 if (target.is('.old')) { 18767 if (month === 0) { 18768 month = 11; 18769 year -= 1; 18770 } else { 18771 month -= 1; 18772 } 18773 } else if (target.is('.new')) { 18774 if (month === 11) { 18775 month = 0; 18776 year += 1; 18777 } else { 18778 month += 1; 18779 } 18780 } 18781 picker.date = moment({ 18782 y: year, 18783 M: month, 18784 d: day, 18785 h: picker.date.hours(), 18786 m: picker.date.minutes(), 18787 s: picker.date.seconds() 18788 } 18789 ); 18790 picker.viewDate = moment({ 18791 y: year, M: month, d: Math.min(28, day) 18792 }); 18793 fillDate(); 18794 set(); 18795 notifyChange(oldDate, e.type); 18796 } 18797 break; 18798 } 18799 } 18800 } 18801 }, 18802 18803 actions = { 18804 incrementHours: function () { 18805 checkDate('add', 'hours', 1); 18806 }, 18807 18808 incrementMinutes: function () { 18809 checkDate('add', 'minutes', picker.options.minuteStepping); 18810 }, 18811 18812 incrementSeconds: function () { 18813 checkDate('add', 'seconds', 1); 18814 }, 18815 18816 decrementHours: function () { 18817 checkDate('subtract', 'hours', 1); 18818 }, 18819 18820 decrementMinutes: function () { 18821 checkDate('subtract', 'minutes', picker.options.minuteStepping); 18822 }, 18823 18824 decrementSeconds: function () { 18825 checkDate('subtract', 'seconds', 1); 18826 }, 18827 18828 togglePeriod: function () { 18829 var hour = picker.date.hours(); 18830 if (hour >= 12) { 18831 hour -= 12; 18832 } else { 18833 hour += 12; 18834 } 18835 picker.date.hours(hour); 18836 }, 18837 18838 showPicker: function () { 18839 picker.widget.find('.timepicker > div:not(.timepicker-picker)').hide(); 18840 picker.widget.find('.timepicker .timepicker-picker').show(); 18841 }, 18842 18843 showHours: function () { 18844 picker.widget.find('.timepicker .timepicker-picker').hide(); 18845 picker.widget.find('.timepicker .timepicker-hours').show(); 18846 }, 18847 18848 showMinutes: function () { 18849 picker.widget.find('.timepicker .timepicker-picker').hide(); 18850 picker.widget.find('.timepicker .timepicker-minutes').show(); 18851 }, 18852 18853 showSeconds: function () { 18854 picker.widget.find('.timepicker .timepicker-picker').hide(); 18855 picker.widget.find('.timepicker .timepicker-seconds').show(); 18856 }, 18857 18858 selectHour: function (e) { 18859 var hour = parseInt($(e.target).text(), 10); 18860 if (!picker.use24hours) { 18861 if (picker.date.hours() >= 12) { 18862 if (hour !== 12) { 18863 hour += 12; 18864 } 18865 } else { 18866 if (hour === 12) { 18867 hour = 0; 18868 } 18869 } 18870 } 18871 picker.date.hours(hour); 18872 actions.showPicker.call(picker); 18873 }, 18874 18875 selectMinute: function (e) { 18876 picker.date.minutes(parseInt($(e.target).text(), 10)); 18877 actions.showPicker.call(picker); 18878 }, 18879 18880 selectSecond: function (e) { 18881 picker.date.seconds(parseInt($(e.target).text(), 10)); 18882 actions.showPicker.call(picker); 18883 } 18884 }, 18885 18886 doAction = function (e) { 18887 var oldDate = moment(picker.date), 18888 action = $(e.currentTarget).data('action'),
18889 rv = actions[action].apply(picker, arguments); 18890 stopEvent(e); 18891 if (!picker.date) { 18892 picker.date = moment({y: 1970}); 18893 } 18894 set(); 18895 fillTime(); 18896 notifyChange(oldDate, e.type); 18897 return rv; 18898 }, 18899 18900 stopEvent = function (e) { 18901 e.stopPropagation(); 18902 e.preventDefault(); 18903 }, 18904 18905 keydown = function (e) { 18906 if (e.keyCode === 27) { // allow escape to hide picker 18907 picker.hide(); 18908 } 18909 }, 18910 18911 change = function (e) { 18912 moment.locale(picker.options.language); 18913 var input = $(e.target), oldDate = moment(picker.date), newDate = moment(input.val(), picker.format, picker.options.useStrict); 18914 if (newDate.isValid() && !isInDisableDates(newDate) && isInEnableDates(newDate)) { 18915 update(); 18916 picker.setValue(newDate); 18917 notifyChange(oldDate, e.type); 18918 set(); 18919 } 18920 else { 18921 picker.viewDate = oldDate; 18922 picker.unset = true; 18923 notifyChange(oldDate, e.type); 18924 notifyError(newDate); 18925 } 18926 }, 18927 18928 showMode = function (dir) { 18929 if (dir) { 18930 picker.viewMode = Math.max(picker.minViewMode, Math.min(2, picker.viewMode + dir)); 18931 } 18932 picker.widget.find('.datepicker > div').hide().filter('.datepicker-' + dpGlobal.modes[picker.viewMode].clsName).show(); 18933 }, 18934 18935 attachDatePickerEvents = function () { 18936 var $this, $parent, expanded, closed, collapseData; 18937 picker.widget.on('click', '.datepicker *', $.proxy(click, this)); // this handles date picker clicks 18938 picker.widget.on('click', '[data-action]', $.proxy(doAction, this)); // this handles time picker clicks 18939 picker.widget.on('mousedown', $.proxy(stopEvent, this)); 18940 picker.element.on('keydown', $.proxy(keydown, this)); 18941 if (picker.options.pickDate && picker.options.pickTime) { 18942 picker.widget.on('click.togglePicker', '.accordion-toggle', function (e) { 18943 e.stopPropagation(); 18944 $this = $(this); 18945 $parent = $this.closest('ul'); 18946 expanded = $parent.find('.in'); 18947 closed = $parent.find('.collapse:not(.in)'); 18948 18949 if (expanded && expanded.length) { 18950 collapseData = expanded.data('collapse'); 18951 if (collapseData && collapseData.transitioning) { 18952 return; 18953 } 18954 expanded.collapse('hide'); 18955 closed.collapse('show'); 18956 $this.find('span').toggleClass(picker.options.icons.time + ' ' + picker.options.icons.date); 18957 if (picker.component) { 18958 picker.component.find('span').toggleClass(picker.options.icons.time + ' ' + picker.options.icons.date); 18959 } 18960 } 18961 }); 18962 } 18963 if (picker.isInput) { 18964 picker.element.on({ 18965 'click': $.proxy(picker.show, this), 18966 'focus': $.proxy(picker.show, this), 18967 'change': $.proxy(change, this), 18968 'blur': $.proxy(picker.hide, this) 18969 }); 18970 } else { 18971 picker.element.on({ 18972 'change': $.proxy(change, this) 18973 }, 'input'); 18974 if (picker.component) { 18975 picker.component.on('click', $.proxy(picker.show, this)); 18976 picker.component.on('mousedown', $.proxy(stopEvent, this)); 18977 } else { 18978 picker.element.on('click', $.proxy(picker.show, this)); 18979 } 18980 } 18981 }, 18982 18983 attachDatePickerGlobalEvents = function () { 18984 $(window).on( 18985 'resize.datetimepicker' + picker.id, $.proxy(place, this)); 18986 if (!picker.isInput) { 18987 $(document).on( 18988 'mousedown.datetimepicker' + picker.id, $.proxy(picker.hide, this)); 18989 } 18990 }, 18991 18992 detachDatePickerEvents = function () { 18993 picker.widget.off('click', '.datepicker *', picker.click); 18994 picker.widget.off('click', '[data-action]'); 18995 picker.widget.off('mousedown', picker.stopEvent); 18996 if (picker.options.pickDate && picker.options.pickTime) { 18997 picker.widget.off('click.togglePicker'); 18998 } 18999 if (picker.isInput) { 19000 picker.element.off({
19001 'focus': picker.show, 19002 'change': picker.change, 19003 'click': picker.show, 19004 'blur' : picker.hide 19005 }); 19006 } else { 19007 picker.element.off({ 19008 'change': picker.change 19009 }, 'input'); 19010 if (picker.component) { 19011 picker.component.off('click', picker.show); 19012 picker.component.off('mousedown', picker.stopEvent); 19013 } else { 19014 picker.element.off('click', picker.show); 19015 } 19016 } 19017 }, 19018 19019 detachDatePickerGlobalEvents = function () { 19020 $(window).off('resize.datetimepicker' + picker.id); 19021 if (!picker.isInput) { 19022 $(document).off('mousedown.datetimepicker' + picker.id); 19023 } 19024 }, 19025 19026 isInFixed = function () { 19027 if (picker.element) { 19028 var parents = picker.element.parents(), inFixed = false, i; 19029 for (i = 0; i < parents.length; i++) { 19030 if ($(parents[i]).css('position') === 'fixed') { 19031 inFixed = true; 19032 break; 19033 } 19034 } 19035 return inFixed; 19036 } else { 19037 return false; 19038 } 19039 }, 19040 19041 set = function () { 19042 moment.locale(picker.options.language); 19043 var formatted = ''; 19044 if (!picker.unset) { 19045 formatted = moment(picker.date).format(picker.format); 19046 } 19047 getPickerInput().val(formatted); 19048 picker.element.data('date', formatted); 19049 if (!picker.options.pickTime) { 19050 picker.hide(); 19051 } 19052 }, 19053 19054 checkDate = function (direction, unit, amount) { 19055 moment.locale(picker.options.language); 19056 var newDate; 19057 if (direction === 'add') { 19058 newDate = moment(picker.date); 19059 if (newDate.hours() === 23) { 19060 newDate.add(amount, unit); 19061 } 19062 newDate.add(amount, unit); 19063 } 19064 else { 19065 newDate = moment(picker.date).subtract(amount, unit); 19066 } 19067 if (isInDisableDates(moment(newDate.subtract(amount, unit))) || isInDisableDates(newDate)) { 19068 notifyError(newDate.format(picker.format)); 19069 return; 19070 } 19071 19072 if (direction === 'add') { 19073 picker.date.add(amount, unit); 19074 } 19075 else { 19076 picker.date.subtract(amount, unit); 19077 } 19078 picker.unset = false; 19079 }, 19080 19081 isInDisableDates = function (date, timeUnit) { 19082 moment.locale(picker.options.language); 19083 var maxDate = moment(picker.options.maxDate, picker.format, picker.options.useStrict), 19084 minDate = moment(picker.options.minDate, picker.format, picker.options.useStrict); 19085 19086 if (timeUnit) { 19087 maxDate = maxDate.endOf(timeUnit); 19088 minDate = minDate.startOf(timeUnit); 19089 } 19090 19091 if (date.isAfter(maxDate) || date.isBefore(minDate)) { 19092 return true; 19093 } 19094 if (picker.options.disabledDates === false) { 19095 return false; 19096 } 19097 return picker.options.disabledDates[date.format('YYYY-MM-DD')] === true; 19098 }, 19099 isInEnableDates = function (date) { 19100 moment.locale(picker.options.language); 19101 if (picker.options.enabledDates === false) { 19102 return true; 19103 } 19104 return picker.options.enabledDates[date.format('YYYY-MM-DD')] === true; 19105 }, 19106 19107 indexGivenDates = function (givenDatesArray) { 19108 // Store given enabledDates and disabledDates as keys. 19109 // This way we can check their existence in O(1) time instead of looping through whole array. 19110 // (for example: picker.options.enabledDates['2014-02-27'] === true) 19111 var givenDatesIndexed = {}, givenDatesCount = 0, i; 19112 for (i = 0; i < givenDatesArray.length; i++) { 19113 if (moment.isMoment(givenDatesArray[i]) || givenDatesArray[i] instanceof Date) { 19114 dDate = moment(givenDatesArray[i]); 19115 } else { 19116 dDate = moment(givenDatesArray[i], picker.format, picker.options.useStrict); 19117 } 19118 if (dDate.isValid()) { 19119 givenDatesIndexed[dDate.format('YYYY-MM-DD')] = true; 19120 givenDatesCount++; 19121 } 19122 } 19123 if (givenDatesCount > 0) {
19124 return givenDatesIndexed; 19125 } 19126 return false; 19127 }, 19128 19129 padLeft = function (string) { 19130 string = string.toString(); 19131 if (string.length >= 2) { 19132 return string; 19133 } 19134 return '0' + string; 19135 }, 19136 19137 getTemplate = function () { 19138 if (picker.options.pickDate && picker.options.pickTime) { 19139 var ret = ''; 19140 ret = '<div class="bootstrap-datetimepicker-widget' + (picker.options.sideBySide ? ' timepicker-sbs' : '') + (picker.use24hours ? ' usetwentyfour' : '') + ' dropdown-menu" style="z-index:9999 !important;">'; 19141 if (picker.options.sideBySide) { 19142 ret += '<div class="row">' + 19143 '<div class="col-sm-6 datepicker">' + dpGlobal.template + '</div>' + 19144 '<div class="col-sm-6 timepicker">' + tpGlobal.getTemplate() + '</div>' + 19145 '</div>'; 19146 } else { 19147 ret += '<ul class="list-unstyled">' + 19148 '<li' + (picker.options.collapse ? ' class="collapse in"' : '') + '>' + 19149 '<div class="datepicker">' + dpGlobal.template + '</div>' + 19150 '</li>' + 19151 '<li class="picker-switch accordion-toggle"><a class="btn" style="width:100%"><span class="' + picker.options.icons.time + '"></span></a></li>' + 19152 '<li' + (picker.options.collapse ? ' class="collapse"' : '') + '>' + 19153 '<div class="timepicker">' + tpGlobal.getTemplate() + '</div>' + 19154 '</li>' + 19155 '</ul>'; 19156 } 19157 ret += '</div>'; 19158 return ret; 19159 } 19160 if (picker.options.pickTime) { 19161 return ( 19162 '<div class="bootstrap-datetimepicker-widget dropdown-menu">' + 19163 '<div class="timepicker">' + tpGlobal.getTemplate() + '</div>' + 19164 '</div>' 19165 ); 19166 } 19167 return ( 19168 '<div class="bootstrap-datetimepicker-widget dropdown-menu">' + 19169 '<div class="datepicker">' + dpGlobal.template + '</div>' + 19170 '</div>' 19171 ); 19172 }, 19173 19174 dpGlobal = { 19175 modes: [ 19176 { 19177 clsName: 'days', 19178 navFnc: 'month', 19179 navStep: 1 19180 }, 19181 { 19182 clsName: 'months', 19183 navFnc: 'year', 19184 navStep: 1 19185 }, 19186 { 19187 clsName: 'years', 19188 navFnc: 'year', 19189 navStep: 10 19190 } 19191 ], 19192 headTemplate: 19193 '<thead>' + 19194 '<tr>' + 19195 '<th class="prev">‹</th><th colspan="5" class="picker-switch"></th><th class="next">›</th>' + 19196 '</tr>' + 19197 '</thead>', 19198 contTemplate: 19199 '<tbody><tr><td colspan="7"></td></tr></tbody>' 19200 }, 19201 19202 tpGlobal = { 19203 hourTemplate: '<span data-action="showHours" data-time-component="hours" class="timepicker-hour"></span>', 19204 minuteTemplate: '<span data-action="showMinutes" data-time-component="minutes" class="timepicker-minute"></span>', 19205 secondTemplate: '<span data-action="showSeconds" data-time-component="seconds" class="timepicker-second"></span>' 19206 }; 19207 19208 dpGlobal.template = 19209 '<div class="datepicker-days">' + 19210 '<table class="table-condensed">' + dpGlobal.headTemplate + '<tbody></tbody></table>' + 19211 '</div>' + 19212 '<div class="datepicker-months">' + 19213 '<table class="table-condensed">' + dpGlobal.headTemplate + dpGlobal.contTemplate + '</table>' + 19214 '</div>' + 19215 '<div class="datepicker-years">' + 19216 '<table class="table-condensed">' + dpGlobal.headTemplate + dpGlobal.contTemplate + '</table>' + 19217 '</div>'; 19218 19219 tpGlobal.getTemplate = function () { 19220 return ( 19221 '<div class="timepicker-picker">' + 19222 '<table class="table-condensed">' + 19223 '<tr>' + 19224 '<td><a href="#" class="btn" data-action="incrementHours"><span class="' + picker.options.icons.up + '"></span></a></td>' + 19225 '<td class="separator"></td>' + 19226 '<td>' + (picker.options.useMinutes ? '<a href="#" class="btn" data-action="incrementMinutes"><span class="' + picker.options.icons.up + '"></span></a>' : '') + '</td>' + 19227 (picker.options.useSeconds ? 19228 '<td class="separator"></td><td><a href="#" class="btn" data-action="incrementSeconds"><span class="' + picker.options.icons.up + '"></span></a></td>' : '') + 19229 (picker.use24hours ? '' : '<td class="separator"></td>') + 19230 '</tr>' + 19231 '<tr>' + 19232 '<td>' + tpGlobal.hourTemplate + '</td> ' + 19233 '<td class="separator">:</td>' + 19234 '<td>' + (picker.options.useMinutes ? tpGlobal.minuteTemplate : '<span class="timepicker-minute">00</span>') + '</td> ' + 19235 (picker.options.useSeconds ? 19236 '<td class="separator">:</td><td>' + tpGlobal.secondTemplate + '</td>' : '') + 19237 (picker.use24hours ? '' : '<td class="separator"></td>' + 19238 '<td><button type="button" class="btn btn-primary" data-action="togglePeriod"></button></td>') + 19239 '</tr>' + 19240 '<tr>' + 19241 '<td><a href="#" class="btn" data-action="decrementHours"><span class="' + picker.options.icons.down + '"></span></a></td>' + 19242 '<td class="separator"></td>' + 19243 '<td>' + (picker.options.useMinutes ? '<a href="#" class="btn" data-action="decrementMinutes"><span class="' + picker.options.icons.down + '"></span></a>' : '') + '</td>' + 19244 (picker.options.useSeconds ? 19245 '<td class="separator"></td><td><a href="#" class="btn" data-action="decrementSeconds"><span class="' + picker.options.icons.down + '"></span></a></td>' : '') + 19246 (picker.use24hours ? '' : '<td class="separator"></td>') + 19247 '</tr>' + 19248 '</table>' + 19249 '</div>' + 19250 '<div class="timepicker-hours" data-action="selectHour">' + 19251 '<table class="table-condensed"></table>' + 19252 '</div>' + 19253 '<div class="timepicker-minutes" data-action="selectMinute">' + 19254 '<table class="table-condensed"></table>' + 19255 '</div>' + 19256 (picker.options.useSeconds ? 19257 '<div class="timepicker-seconds" data-action="selectSecond"><table class="table-condensed"></table></div>' : '') 19258 ); 19259 }; 19260 19261 picker.destroy = function () { 19262 detachDatePickerEvents(); 19263 detachDatePickerGlobalEvents(); 19264 picker.widget.remove(); 19265 picker.element.removeData('DateTimePicker'); 19266 if (picker.component) { 19267 picker.component.removeData('DateTimePicker'); 19268 } 19269 }; 19270 19271 picker.show = function (e) { 19272 if (picker.options.useCurrent) { 19273 if (getPickerInput().val() === '') { 19274 if (picker.options.minuteStepping !== 1) { 19275 var mDate = moment(), 19276 rInterval = picker.options.minuteStepping; 19277 mDate.minutes((Math.round(mDate.minutes() / rInterval) * rInterval) % 60).seconds(0); 19278 picker.setValue(mDate.format(picker.format)); 19279 } else { 19280 picker.setValue(moment().format(picker.format)); 19281 } 19282 notifyChange('', e.type); 19283 } 19284 } 19285 // if this is a click event on the input field and picker is already open don't hide it 19286 if (e && e.type === 'click' && picker.isInput && picker.widget.hasClass('picker-open')) { 19287 return; 19288 } 19289 if (picker.widget.hasClass('picker-open')) { 19290 picker.widget.hide(); 19291 picker.widget.removeClass('picker-open'); 19292 } 19293 else { 19294 picker.widget.show(); 19295 picker.widget.addClass('picker-open'); 19296 } 19297 picker.height = picker.component ? picker.component.outerHeight() : picker.element.outerHeight(); 19298 place(); 19299 picker.element.trigger({ 19300 type: 'dp.show', 19301 date: moment(picker.date) 19302 }); 19303 attachDatePickerGlobalEvents(); 19304 if (e) { 19305 stopEvent(e); 19306 } 19307 }; 19308 19309 picker.disable = function () { 19310 var input = picker.element.find('input'); 19311 if (input.prop('disabled')) { 19312 return; 19313 } 19314 input.prop('disabled', true); 19315 detachDatePickerEvents(); 19316 }; 19317 19318 picker.enable = function () { 19319 var input = picker.element.find('input'); 19320 if (!input.prop('disabled')) { 19321 return; 19322 } 19323 input.prop('disabled', false); 19324 attachDatePickerEvents(); 19325 }; 19326 19327 picker.hide = function () { 19328 // Ignore event if in the middle of a picker transition 19329 var collapse = picker.widget.find('.collapse'), i, collapseData; 19330 for (i = 0; i < collapse.length; i++) { 19331 collapseData = collapse.eq(i).data('collapse'); 19332 if (collapseData && collapseData.transitioning) { 19333 return; 19334 } 19335 } 19336 picker.widget.hide(); 19337 picker.widget.removeClass('picker-open'); 19338 picker.viewMode = picker.startViewMode; 19339 showMode(); 19340 picker.element.trigger({ 19341 type: 'dp.hide', 19342 date: moment(picker.date) 19343 }); 19344 detachDatePickerGlobalEvents(); 19345 }; 19346 19347 picker.setValue = function (newDate) { 19348 moment.locale(picker.options.language); 19349 if (!newDate) { 19350 picker.unset = true; 19351 set(); 19352 } else { 19353 picker.unset = false;
19354 } 19355 if (!moment.isMoment(newDate)) { 19356 newDate = (newDate instanceof Date) ? moment(newDate) : moment(newDate, picker.format, picker.options.useStrict); 19357 } else { 19358 newDate = newDate.locale(picker.options.language); 19359 } 19360 if (newDate.isValid()) { 19361 picker.date = newDate; 19362 set(); 19363 picker.viewDate = moment({y: picker.date.year(), M: picker.date.month()}); 19364 fillDate(); 19365 fillTime(); 19366 } 19367 else { 19368 notifyError(newDate); 19369 } 19370 }; 19371 19372 picker.getDate = function () { 19373 if (picker.unset) { 19374 return null; 19375 } 19376 return moment(picker.date); 19377 }; 19378 19379 picker.setDate = function (date) { 19380 var oldDate = moment(picker.date); 19381 if (!date) { 19382 picker.setValue(null); 19383 } else { 19384 picker.setValue(date); 19385 } 19386 notifyChange(oldDate, 'function'); 19387 }; 19388 19389 picker.setDisabledDates = function (dates) { 19390 picker.options.disabledDates = indexGivenDates(dates); 19391 if (picker.viewDate) { 19392 update(); 19393 } 19394 }; 19395 19396 picker.setEnabledDates = function (dates) { 19397 picker.options.enabledDates = indexGivenDates(dates); 19398 if (picker.viewDate) { 19399 update(); 19400 } 19401 }; 19402 19403 picker.setMaxDate = function (date) { 19404 if (date === undefined) { 19405 return; 19406 } 19407 if (moment.isMoment(date) || date instanceof Date) { 19408 picker.options.maxDate = moment(date); 19409 } else { 19410 picker.options.maxDate = moment(date, picker.format, picker.options.useStrict); 19411 } 19412 if (picker.viewDate) { 19413 update(); 19414 } 19415 }; 19416 19417 picker.setMinDate = function (date) { 19418 if (date === undefined) { 19419 return; 19420 } 19421 if (moment.isMoment(date) || date instanceof Date) { 19422 picker.options.minDate = moment(date); 19423 } else { 19424 picker.options.minDate = moment(date, picker.format, picker.options.useStrict); 19425 } 19426 if (picker.viewDate) { 19427 update(); 19428 } 19429 }; 19430 19431 init(); 19432 }; 19433 19434 $.fn.datetimepicker = function (options) { 19435 return this.each(function () { 19436 var $this = $(this), 19437 data = $this.data('DateTimePicker'); 19438 if (!data) { 19439 $this.data('DateTimePicker', new DateTimePicker(this, options)); 19440 } 19441 }); 19442 }; 19443 19444 $.fn.datetimepicker.defaults = { 19445 format: false, 19446 pickDate: true, 19447 pickTime: true, 19448 useMinutes: true, 19449 useSeconds: false, 19450 useCurrent: true, 19451 minuteStepping: 1, 19452 minDate: moment({y: 1900}), 19453 maxDate: moment().add(100, 'y'), 19454 showToday: true, 19455 collapse: true, 19456 language: moment.locale(), 19457 defaultDate: '', 19458 disabledDates: false, 19459 enabledDates: false, 19460 icons: {}, 19461 useStrict: false, 19462 direction: 'auto', 19463 sideBySide: false, 19464 daysOfWeekDisabled: [], 19465 widgetParent: false 19466 }; 19467})); 19468 19469/* =========================================================== 19470# bootstrap-tour - v0.9.3 19471# http://bootstraptour.com 19472# ============================================================== 19473# Copyright 2012-2013 Ulrich Sossou 19474# 19475# Licensed under the Apache License, Version 2.0 (the "License"); 19476# you may not use this file except in compliance with the License. 19477# You may obtain a copy of the License at 19478# 19479# http://www.apache.org/licenses/LICENSE-2.0 19480# 19481# Unless required by applicable law or agreed to in writing, software 19482# distributed under the License is distributed on an "AS IS" BASIS, 19483# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19484# See the License for the specific language governing permissions and 19485# limitations under the License. 19486*/ 19487(function($, window) { 19488 var Tour, document; 19489 document = window.document; 19490 Tour = (function() { 19491 function Tour(options) { 19492 var storage;
vendor: 19,485 bytes, lines 19493-20051
19493 try { 19494 storage = window.localStorage; 19495 } catch (_error) { 19496 storage = false; 19497 } 19498 this._options = $.extend({ 19499 name: "tour", 19500 steps: [], 19501 container: "body", 19502 keyboard: true, 19503 storage: storage, 19504 debug: false, 19505 backdrop: false, 19506 redirect: true, 19507 orphan: false, 19508 duration: false, 19509 basePath: "", 19510 template: "<div class='popover'> <div class='arrow'></div> <h3 class='popover-title'></h3> <div class='popover-content'></div> <div class='popover-navigation'> <div class='btn-group'> <button class='btn btn-sm btn-default' data-role='prev'>« Prev</button> <button class='btn btn-sm btn-default' data-role='next'>Next »</button> <button class='btn btn-sm btn-default' data-role='pause-resume' data-pause-text='Pause' data-resume-text='Resume'>Pause</button> </div> <button class='btn btn-sm btn-default' data-role='end'>End tour</button> </div> </div>", 19511 afterSetState: function(key, value) {}, 19512 afterGetState: function(key, value) {}, 19513 afterRemoveState: function(key) {}, 19514 onStart: function(tour) {}, 19515 onEnd: function(tour) {}, 19516 onShow: function(tour) {}, 19517 onShown: function(tour) {}, 19518 onHide: function(tour) {}, 19519 onHidden: function(tour) {}, 19520 onNext: function(tour) {}, 19521 onPrev: function(tour) {}, 19522 onPause: function(tour, duration) {}, 19523 onResume: function(tour, duration) {} 19524 }, options); 19525 this._force = false; 19526 this._inited = false; 19527 this.backdrop = { 19528 overlay: null, 19529 $element: null, 19530 $background: null, 19531 backgroundShown: false, 19532 overlayElementShown: false 19533 }; 19534 this; 19535 } 19536 19537 Tour.prototype.addSteps = function(steps) { 19538 var step, _i, _len; 19539 for (_i = 0, _len = steps.length; _i < _len; _i++) { 19540 step = steps[_i]; 19541 this.addStep(step); 19542 } 19543 return this; 19544 }; 19545 19546 Tour.prototype.addStep = function(step) { 19547 this._options.steps.push(step); 19548 return this; 19549 }; 19550 19551 Tour.prototype.getStep = function(i) { 19552 if (this._options.steps[i] != null) { 19553 return $.extend({ 19554 id: "step-" + i, 19555 path: "", 19556 placement: "right", 19557 title: "", 19558 content: "<p></p>", 19559 next: i === this._options.steps.length - 1 ? -1 : i + 1, 19560 prev: i - 1, 19561 animation: true, 19562 container: this._options.container, 19563 backdrop: this._options.backdrop, 19564 redirect: this._options.redirect, 19565 orphan: this._options.orphan, 19566 duration: this._options.duration, 19567 template: this._options.template, 19568 onShow: this._options.onShow, 19569 onShown: this._options.onShown, 19570 onHide: this._options.onHide, 19571 onHidden: this._options.onHidden, 19572 onNext: this._options.onNext, 19573 onPrev: this._options.onPrev, 19574 onPause: this._options.onPause, 19575 onResume: this._options.onResume 19576 }, this._options.steps[i]); 19577 } 19578 }; 19579 19580 Tour.prototype.init = function(force) { 19581 this._force = force; 19582 if (this.ended()) { 19583 this._debug("Tour ended, init prevented."); 19584 return this; 19585 } 19586 this.setCurrentStep(); 19587 this._initMouseNavigation(); 19588 this._initKeyboardNavigation(); 19589 this._onResize((function(_this) { 19590 return function() { 19591 return _this.showStep(_this._current); 19592 }; 19593 })(this)); 19594 if (this._current !== null) { 19595 this.showStep(this._current); 19596 } 19597 this._inited = true; 19598 return this; 19599 }; 19600 19601 Tour.prototype.start = function(force) { 19602 var promise; 19603 if (force == null) { 19604 force = false; 19605 } 19606 if (!this._inited) { 19607 this.init(force); 19608 } 19609 if (this._current === null) { 19610 promise = this._makePromise(this._options.onStart != null ? this._options.onStart(this) : void 0); 19611 this._callOnPromiseDone(promise, this.showStep, 0); 19612 } 19613 return this; 19614 }; 19615 19616 Tour.prototype.next = function() { 19617 var promise; 19618 promise = this.hideStep(this._current); 19619 return this._callOnPromiseDone(promise, this._showNextStep); 19620 }; 19621 19622 Tour.prototype.prev = function() { 19623 var promise; 19624 promise = this.hideStep(this._current); 19625 return this._callOnPromiseDone(promise, this._showPrevStep); 19626 }; 19627 19628 Tour.prototype.goTo = function(i) { 19629 var promise; 19630 promise = this.hideStep(this._current); 19631 return this._callOnPromiseDone(promise, this.showStep, i); 19632 }; 19633 19634 Tour.prototype.end = function() { 19635 var endHelper, promise; 19636 endHelper = (function(_this) { 19637 return function(e) { 19638 $(document).off("click.tour-" + _this._options.name); 19639 $(document).off("keyup.tour-" + _this._options.name); 19640 $(window).off("resize.tour-" + _this._options.name); 19641 _this._setState("end", "yes"); 19642 _this._inited = false; 19643 _this._force = false; 19644 _this._clearTimer(); 19645 if (_this._options.onEnd != null) { 19646 return _this._options.onEnd(_this); 19647 } 19648 }; 19649 })(this); 19650 promise = this.hideStep(this._current); 19651 return this._callOnPromiseDone(promise, endHelper); 19652 }; 19653 19654 Tour.prototype.ended = function() { 19655 return !this._force && !!this._getState("end"); 19656 }; 19657 19658 Tour.prototype.restart = function() { 19659 this._removeState("current_step"); 19660 this._removeState("end"); 19661 return this.start(); 19662 }; 19663 19664 Tour.prototype.pause = function() { 19665 var step; 19666 step = this.getStep(this._current); 19667 if (!(step && step.duration)) { 19668 return this; 19669 } 19670 this._paused = true; 19671 this._duration -= new Date().getTime() - this._start; 19672 window.clearTimeout(this._timer); 19673 this._debug("Paused/Stopped step " + (this._current + 1) + " timer (" + this._duration + " remaining)."); 19674 if (step.onPause != null) { 19675 return step.onPause(this, this._duration); 19676 } 19677 }; 19678 19679 Tour.prototype.resume = function() { 19680 var step; 19681 step = this.getStep(this._current); 19682 if (!(step && step.duration)) { 19683 return this; 19684 } 19685 this._paused = false; 19686 this._start = new Date().getTime(); 19687 this._duration = this._duration || step.duration; 19688 this._timer = window.setTimeout((function(_this) { 19689 return function() { 19690 if (_this._isLast()) { 19691 return _this.next(); 19692 } else { 19693 return _this.end(); 19694 } 19695 }; 19696 })(this), this._duration); 19697 this._debug("Started step " + (this._current + 1) + " timer with duration " + this._duration); 19698 if ((step.onResume != null) && this._duration !== step.duration) { 19699 return step.onResume(this, this._duration); 19700 } 19701 }; 19702 19703 Tour.prototype.hideStep = function(i) { 19704 var hideStepHelper, promise, step; 19705 step = this.getStep(i); 19706 if (!step) { 19707 return; 19708 } 19709 this._clearTimer(); 19710 promise = this._makePromise(step.onHide != null ? step.onHide(this, i) : void 0); 19711 hideStepHelper = (function(_this) { 19712 return function(e) { 19713 var $element; 19714 $element = $(step.element); 19715 if (!($element.data("bs.popover") || $element.data("popover"))) { 19716 $element = $("body"); 19717 } 19718 $element.popover("destroy").removeClass("tour-" + _this._options.name + "-element tour-" + _this._options.name + "-" + i + "-element"); 19719 if (step.reflex) { 19720 $element.css("cursor", "").off("click.tour-" + _this._options.name); 19721 } 19722 if (step.backdrop) { 19723 _this._hideBackdrop(); 19724 } 19725 if (step.onHidden != null) { 19726 return step.onHidden(_this); 19727 } 19728 }; 19729 })(this); 19730 this._callOnPromiseDone(promise, hideStepHelper); 19731 return promise; 19732 }; 19733 19734 Tour.prototype.showStep = function(i) { 19735 var promise, showStepHelper, skipToPrevious, step; 19736 if (this.ended()) { 19737 this._debug("Tour ended, showStep prevented."); 19738 return this; 19739 } 19740 step = this.getStep(i); 19741 if (!step) { 19742 return; 19743 } 19744 skipToPrevious = i < this._current; 19745 promise = this._makePromise(step.onShow != null ? step.onShow(this, i) : void 0); 19746 showStepHelper = (function(_this) { 19747 return function(e) { 19748 var current_path, path; 19749 _this.setCurrentStep(i); 19750 path = (function() { 19751 switch ({}.toString.call(step.path)) { 19752 case "[object Function]": 19753 return step.path(); 19754 case "[object String]": 19755 return this._options.basePath + step.path; 19756 default: 19757 return step.path; 19758 } 19759 }).call(_this); 19760 current_path = [document.location.pathname, document.location.hash].join(""); 19761 if (_this._isRedirect(path, current_path)) { 19762 _this._redirect(step, path); 19763 return; 19764 } 19765 if (_this._isOrphan(step)) { 19766 if (!step.orphan) { 19767 _this._debug("Skip the orphan step " + (_this._current + 1) + ". Orphan option is false and the element doesn't exist or is hidden."); 19768 if (skipToPrevious) { 19769 _this._showPrevStep(); 19770 } else { 19771 _this._showNextStep(); 19772 } 19773 return; 19774 } 19775 _this._debug("Show the orphan step " + (_this._current + 1) + ". Orphans option is true."); 19776 } 19777 if (step.backdrop) { 19778 _this._showBackdrop(!_this._isOrphan(step) ? step.element : void 0); 19779 } 19780 _this._scrollIntoView(step.element, function() { 19781 if (_this.getCurrentStep() !== i) { 19782 return; 19783 } 19784 if ((step.element != null) && step.backdrop) { 19785 _this._showOverlayElement(step.element); 19786 } 19787 _this._showPopover(step, i); 19788 if (step.onShown != null) { 19789 step.onShown(_this); 19790 } 19791 return _this._debug("Step " + (_this._current + 1) + " of " + _this._options.steps.length); 19792 }); 19793 if (step.duration) { 19794 return _this.resume(); 19795 } 19796 }; 19797 })(this); 19798 this._callOnPromiseDone(promise, showStepHelper); 19799 return promise; 19800 }; 19801 19802 Tour.prototype.getCurrentStep = function() { 19803 return this._current; 19804 }; 19805 19806 Tour.prototype.setCurrentStep = function(value) { 19807 if (value != null) { 19808 this._current = value; 19809 this._setState("current_step", value); 19810 } else { 19811 this._current = this._getState("current_step"); 19812 this._current = this._current === null ? null : parseInt(this._current, 10); 19813 } 19814 return this; 19815 }; 19816 19817 Tour.prototype._setState = function(key, value) { 19818 var e, keyName; 19819 if (this._options.storage) { 19820 keyName = "" + this._options.name + "_" + key; 19821 try { 19822 this._options.storage.setItem(keyName, value); 19823 } catch (_error) { 19824 e = _error; 19825 if (e.code === DOMException.QUOTA_EXCEEDED_ERR) { 19826 this.debug("LocalStorage quota exceeded. State storage failed."); 19827 } 19828 } 19829 return this._options.afterSetState(keyName, value); 19830 } else { 19831 if (this._state == null) { 19832 this._state = {}; 19833 } 19834 return this._state[key] = value; 19835 } 19836 }; 19837 19838 Tour.prototype._removeState = function(key) { 19839 var keyName; 19840 if (this._options.storage) { 19841 keyName = "" + this._options.name + "_" + key; 19842 this._options.storage.removeItem(keyName); 19843 return this._options.afterRemoveState(keyName); 19844 } else { 19845 if (this._state != null) { 19846 return delete this._state[key]; 19847 } 19848 } 19849 }; 19850 19851 Tour.prototype._getState = function(key) { 19852 var keyName, value; 19853 if (this._options.storage) { 19854 keyName = "" + this._options.name + "_" + key; 19855 value = this._options.storage.getItem(keyName); 19856 } else { 19857 if (this._state != null) { 19858 value = this._state[key]; 19859 } 19860 } 19861 if (value === void 0 || value === "null") { 19862 value = null; 19863 } 19864 this._options.afterGetState(key, value); 19865 return value; 19866 }; 19867 19868 Tour.prototype._showNextStep = function() { 19869 var promise, showNextStepHelper, step; 19870 step = this.getStep(this._current); 19871 showNextStepHelper = (function(_this) { 19872 return function(e) { 19873 return _this.showStep(step.next); 19874 }; 19875 })(this); 19876 promise = this._makePromise(step.onNext != null ? step.onNext(this) : void 0); 19877 return this._callOnPromiseDone(promise, showNextStepHelper); 19878 }; 19879 19880 Tour.prototype._showPrevStep = function() { 19881 var promise, showPrevStepHelper, step; 19882 step = this.getStep(this._current); 19883 showPrevStepHelper = (function(_this) { 19884 return function(e) { 19885 return _this.showStep(step.prev); 19886 }; 19887 })(this); 19888 promise = this._makePromise(step.onPrev != null ? step.onPrev(this) : void 0); 19889 return this._callOnPromiseDone(promise, showPrevStepHelper); 19890 }; 19891 19892 Tour.prototype._debug = function(text) { 19893 if (this._options.debug) { 19894 return window.console.log("Bootstrap Tour '" + this._options.name + "' | " + text); 19895 } 19896 }; 19897 19898 Tour.prototype._isRedirect = function(path, currentPath) { 19899 return (path != null) && path !== "" && (({}.toString.call(path) === "[object RegExp]" && !path.test(currentPath)) || ({}.toString.call(path) === "[object String]" && path.replace(/\?.*$/, "").replace(/\/?$/, "") !== currentPath.replace(/\/?$/, ""))); 19900 }; 19901 19902 Tour.prototype._redirect = function(step, path) { 19903 if ($.isFunction(step.redirect)) { 19904 return step.redirect.call(this, path); 19905 } else if (step.redirect === true) { 19906 this._debug("Redirect to " + path); 19907 return document.location.href = path; 19908 } 19909 }; 19910 19911 Tour.prototype._isOrphan = function(step) { 19912 return (step.element == null) || !$(step.element).length || $(step.element).is(":hidden") && ($(step.element)[0].namespaceURI !== "http://www.w3.org/2000/svg"); 19913 }; 19914 19915 Tour.prototype._isLast = function() { 19916 return this._current < this._options.steps.length - 1; 19917 }; 19918 19919 Tour.prototype._showPopover = function(step, i) { 19920 var $element, $navigation, $template, $tip, isOrphan, options; 19921 $(".tour-" + this._options.name).remove(); 19922 options = $.extend({}, this._options); 19923 $template = $.isFunction(step.template) ? $(step.template(i, step)) : $(step.template); 19924 $navigation = $template.find(".popover-navigation"); 19925 isOrphan = this._isOrphan(step); 19926 if (isOrphan) { 19927 step.element = "body"; 19928 step.placement = "top"; 19929 $template = $template.addClass("orphan"); 19930 } 19931 $element = $(step.element); 19932 $template.addClass("tour-" + this._options.name + " tour-" + this._options.name + "-" + i); 19933 $element.addClass("tour-" + this._options.name + "-element tour-" + this._options.name + "-" + i + "-element"); 19934 if (step.options) { 19935 $.extend(options, step.options); 19936 } 19937 if (step.reflex && !isOrphan) { 19938 $element.css("cursor", "pointer").on("click.tour-" + this._options.name, (function(_this) { 19939 return function() { 19940 if (_this._isLast()) { 19941 return _this.next(); 19942 } else { 19943 return _this.end(); 19944 } 19945 }; 19946 })(this)); 19947 } 19948 if (step.prev < 0) { 19949 $navigation.find("[data-role='prev']").addClass("disabled"); 19950 } 19951 if (step.next < 0) { 19952 $navigation.find("[data-role='next']").addClass("disabled"); 19953 } 19954 if (!step.duration) { 19955 $navigation.find("[data-role='pause-resume']").remove(); 19956 } 19957 step.template = $template.clone().wrap("<div>").parent().html(); 19958 $element.popover({ 19959 placement: step.placement, 19960 trigger: "manual", 19961 title: step.title, 19962 content: step.content, 19963 html: true, 19964 animation: step.animation, 19965 container: step.container, 19966 template: step.template, 19967 selector: step.element 19968 }).popover("show"); 19969 $tip = $element.data("bs.popover") ? $element.data("bs.popover").tip() : $element.data("popover").tip(); 19970 $tip.attr("id", step.id); 19971 this._reposition($tip, step); 19972 if (isOrphan) { 19973 return this._center($tip); 19974 } 19975 }; 19976 19977 Tour.prototype._reposition = function($tip, step) { 19978 var offsetBottom, offsetHeight, offsetRight, offsetWidth, originalLeft, originalTop, tipOffset; 19979 offsetWidth = $tip[0].offsetWidth; 19980 offsetHeight = $tip[0].offsetHeight; 19981 tipOffset = $tip.offset(); 19982 originalLeft = tipOffset.left; 19983 originalTop = tipOffset.top; 19984 offsetBottom = $(document).outerHeight() - tipOffset.top - $tip.outerHeight(); 19985 if (offsetBottom < 0) { 19986 tipOffset.top = tipOffset.top + offsetBottom; 19987 } 19988 offsetRight = $("html").outerWidth() - tipOffset.left - $tip.outerWidth(); 19989 if (offsetRight < 0) { 19990 tipOffset.left = tipOffset.left + offsetRight; 19991 } 19992 if (tipOffset.top < 0) { 19993 tipOffset.top = 0; 19994 } 19995 if (tipOffset.left < 0) { 19996 tipOffset.left = 0; 19997 } 19998 $tip.offset(tipOffset); 19999 if (step.placement === "bottom" || step.placement === "top") { 20000 if (originalLeft !== tipOffset.left) { 20001 return this._replaceArrow($tip, (tipOffset.left - originalLeft) * 2, offsetWidth, "left"); 20002 } 20003 } else { 20004 if (originalTop !== tipOffset.top) { 20005 return this._replaceArrow($tip, (tipOffset.top - originalTop) * 2, offsetHeight, "top"); 20006 } 20007 } 20008 }; 20009 20010 Tour.prototype._center = function($tip) { 20011 return $tip.css("top", $(window).outerHeight() / 2 - $tip.outerHeight() / 2); 20012 }; 20013 20014 Tour.prototype._replaceArrow = function($tip, delta, dimension, position) { 20015 return $tip.find(".arrow").css(position, delta ? 50 * (1 - delta / dimension) + "%" : ""); 20016 }; 20017 20018 Tour.prototype._scrollIntoView = function(element, callback) { 20019 var $element, $window, counter, offsetTop, scrollTop, windowHeight; 20020 $element = $(element); 20021 if (!$element.length) { 20022 return callback(); 20023 } 20024 $window = $(window); 20025 offsetTop = $element.offset().top; 20026 windowHeight = $window.height(); 20027 scrollTop = Math.max(0, offsetTop - (windowHeight / 2)); 20028 this._debug("Scroll into view. ScrollTop: " + scrollTop + ". Element offset: " + offsetTop + ". Window height: " + windowHeight + "."); 20029 counter = 0; 20030 return $("body,html").stop(true, true).animate({ 20031 scrollTop: Math.ceil(scrollTop) 20032 }, (function(_this) { 20033 return function() { 20034 if (++counter === 2) { 20035 callback(); 20036 return _this._debug("Scroll into view. Animation end element offset: " + ($element.offset().top) + ". Window height: " + ($window.height()) + "."); 20037 } 20038 }; 20039 })(this)); 20040 }; 20041 20042 Tour.prototype._onResize = function(callback, timeout) { 20043 return $(window).on("resize.tour-" + this._options.name, function() { 20044 clearTimeout(timeout); 20045 return timeout = setTimeout(callback, 100); 20046 }); 20047 }; 20048 20049 Tour.prototype._initMouseNavigation = function() { 20050 var _this; 20051 _this = this;
20052 return $(document).off("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='prev']:not(.disabled)").off("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='next']:not(.disabled)").off("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='end']").off("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='pause-resume']").on("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='next']:not(.disabled)", (function(_this) { 20053 return function(e) { 20054 e.preventDefault(); 20055 return _this.next(); 20056 }; 20057 })(this)).on("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='prev']:not(.disabled)", (function(_this) { 20058 return function(e) { 20059 e.preventDefault(); 20060 return _this.prev(); 20061 }; 20062 })(this)).on("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='end']", (function(_this) { 20063 return function(e) { 20064 e.preventDefault(); 20065 return _this.end(); 20066 }; 20067 })(this)).on("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='pause-resume']", function(e) { 20068 var $this; 20069 e.preventDefault(); 20070 $this = $(this); 20071 $this.text(_this._paused ? $this.data("pause-text") : $this.data("resume-text")); 20072 if (_this._paused) { 20073 return _this.resume(); 20074 } else { 20075 return _this.pause(); 20076 } 20077 }); 20078 }; 20079 20080 Tour.prototype._initKeyboardNavigation = function() { 20081 if (!this._options.keyboard) { 20082 return; 20083 } 20084 return $(document).on("keyup.tour-" + this._options.name, (function(_this) { 20085 return function(e) { 20086 if (!e.which) { 20087 return; 20088 } 20089 switch (e.which) { 20090 case 39: 20091 e.preventDefault(); 20092 if (_this._isLast()) { 20093 return _this.next(); 20094 } else { 20095 return _this.end(); 20096 } 20097 break; 20098 case 37: 20099 e.preventDefault(); 20100 if (_this._current > 0) { 20101 return _this.prev(); 20102 } 20103 break; 20104 case 27: 20105 e.preventDefault(); 20106 return _this.end(); 20107 } 20108 }; 20109 })(this)); 20110 }; 20111 20112 Tour.prototype._makePromise = function(result) { 20113 if (result && $.isFunction(result.then)) { 20114 return result; 20115 } else { 20116 return null; 20117 } 20118 }; 20119 20120 Tour.prototype._callOnPromiseDone = function(promise, cb, arg) { 20121 if (promise) { 20122 return promise.then((function(_this) { 20123 return function(e) { 20124 return cb.call(_this, arg); 20125 }; 20126 })(this)); 20127 } else { 20128 return cb.call(this, arg); 20129 } 20130 }; 20131 20132 Tour.prototype._showBackdrop = function(element) { 20133 if (this.backdrop.backgroundShown) { 20134 return; 20135 } 20136 this.backdrop = $("<div/>", { 20137 "class": "tour-backdrop" 20138 }); 20139 this.backdrop.backgroundShown = true; 20140 return $("body").append(this.backdrop); 20141 }; 20142 20143 Tour.prototype._hideBackdrop = function() { 20144 this._hideOverlayElement(); 20145 return this._hideBackground(); 20146 }; 20147 20148 Tour.prototype._hideBackground = function() { 20149 if (this.backdrop) { 20150 this.backdrop.remove(); 20151 this.backdrop.overlay = null; 20152 return this.backdrop.backgroundShown = false; 20153 } 20154 }; 20155 20156 Tour.prototype._showOverlayElement = function(element) { 20157 var $background, $element, offset; 20158 $element = $(element); 20159 if (!$element || $element.length === 0 || this.backdrop.overlayElementShown) { 20160 return; 20161 } 20162 this.backdrop.overlayElementShown = true; 20163 $background = $("<div/>"); 20164 offset = $element.offset(); 20165 offset.top = offset.top; 20166 offset.left = offset.left; 20167 $background.width($element.innerWidth()).height($element.innerHe
20167ight()).addClass("tour-step-background").offset(offset); 20168 $element.addClass("tour-step-backdrop"); 20169 $("body").append($background); 20170 this.backdrop.$element = $element; 20171 return this.backdrop.$background = $background; 20172 }; 20173 20174 Tour.prototype._hideOverlayElement = function() { 20175 if (!this.backdrop.overlayElementShown) { 20176 return; 20177 } 20178 this.backdrop.$element.removeClass("tour-step-backdrop"); 20179 this.backdrop.$background.remove(); 20180 this.backdrop.$element = null; 20181 this.backdrop.$background = null; 20182 return this.backdrop.overlayElementShown = false; 20183 }; 20184 20185 Tour.prototype._clearTimer = function() { 20186 window.clearTimeout(this._timer); 20187 this._timer = null; 20188 return this._duration = null; 20189 }; 20190 20191 return Tour; 20192 20193 })(); 20194 return window.Tour = Tour; 20195})(jQuery, window); 20196 20197define("bootstrapTour", ["jquery","bootstrapTooltip","bootstrapPopover"], (function (global) { 20198 return function () { 20199 var ret, fn; 20200 return ret || global.$; 20201 }; 20202}(this))); 20203 20204!function() { 20205 var d3 = { 20206 version: "3.4.13" 20207 }; 20208 if (!Date.now) Date.now = function() { 20209 return +new Date(); 20210 }; 20211 var d3_arraySlice = [].slice, d3_array = function(list) { 20212 return d3_arraySlice.call(list); 20213 }; 20214 var d3_document = document, d3_documentElement = d3_document.documentElement, d3_window = window; 20215 try { 20216 d3_array(d3_documentElement.childNodes)[0].nodeType; 20217 } catch (e) { 20218 d3_array = function(list) { 20219 var i = list.length, array = new Array(i); 20220 while (i--) array[i] = list[i]; 20221 return array; 20222 }; 20223 } 20224 try { 20225 d3_document.createElement("div").style.setProperty("opacity", 0, ""); 20226 } catch (error) { 20227 var d3_element_prototype = d3_window.Element.prototype, d3_element_setAttribute = d3_element_prototype.setAttribute, d3_element_setAttributeNS = d3_element_prototype.setAttributeNS, d3_style_prototype = d3_window.CSSStyleDeclaration.prototype, d3_style_setProperty = d3_style_prototype.setProperty; 20228 d3_element_prototype.setAttribute = function(name, value) { 20229 d3_element_setAttribute.call(this, name, value + ""); 20230 }; 20231 d3_element_prototype.setAttributeNS = function(space, local, value) { 20232 d3_element_setAttributeNS.call(this, space, local, value + ""); 20233 }; 20234 d3_style_prototype.setProperty = function(name, value, priority) { 20235 d3_style_setProperty.call(this, name, value + "", priority); 20236 }; 20237 } 20238 d3.ascending = d3_ascending; 20239 function d3_ascending(a, b) { 20240 return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN; 20241 }
vendor: 4,435 bytes, lines 20242-20368
20242 d3.descending = function(a, b) { 20243 return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN; 20244 }; 20245 d3.min = function(array, f) { 20246 var i = -1, n = array.length, a, b; 20247 if (arguments.length === 1) { 20248 while (++i < n && !((a = array[i]) != null && a <= a)) a = undefined; 20249 while (++i < n) if ((b = array[i]) != null && a > b) a = b; 20250 } else { 20251 while (++i < n && !((a = f.call(array, array[i], i)) != null && a <= a)) a = undefined; 20252 while (++i < n) if ((b = f.call(array, array[i], i)) != null && a > b) a = b; 20253 } 20254 return a; 20255 }; 20256 d3.max = function(array, f) { 20257 var i = -1, n = array.length, a, b; 20258 if (arguments.length === 1) { 20259 while (++i < n && !((a = array[i]) != null && a <= a)) a = undefined; 20260 while (++i < n) if ((b = array[i]) != null && b > a) a = b; 20261 } else { 20262 while (++i < n && !((a = f.call(array, array[i], i)) != null && a <= a)) a = undefined; 20263 while (++i < n) if ((b = f.call(array, array[i], i)) != null && b > a) a = b; 20264 } 20265 return a; 20266 }; 20267 d3.extent = function(array, f) { 20268 var i = -1, n = array.length, a, b, c; 20269 if (arguments.length === 1) { 20270 while (++i < n && !((a = c = array[i]) != null && a <= a)) a = c = undefined; 20271 while (++i < n) if ((b = array[i]) != null) { 20272 if (a > b) a = b; 20273 if (c < b) c = b; 20274 } 20275 } else { 20276 while (++i < n && !((a = c = f.call(array, array[i], i)) != null && a <= a)) a = undefined; 20277 while (++i < n) if ((b = f.call(array, array[i], i)) != null) { 20278 if (a > b) a = b; 20279 if (c < b) c = b; 20280 } 20281 } 20282 return [ a, c ]; 20283 }; 20284 function d3_number(x) { 20285 return x === null ? NaN : +x; 20286 } 20287 function d3_numeric(x) { 20288 return !isNaN(x); 20289 } 20290 d3.sum = function(array, f) { 20291 var s = 0, n = array.length, a, i = -1; 20292 if (arguments.length === 1) { 20293 while (++i < n) if (d3_numeric(a = +array[i])) s += a; 20294 } else { 20295 while (++i < n) if (d3_numeric(a = +f.call(array, array[i], i))) s += a; 20296 } 20297 return s; 20298 }; 20299 d3.mean = function(array, f) { 20300 var s = 0, n = array.length, a, i = -1, j = n; 20301 if (arguments.length === 1) { 20302 while (++i < n) if (d3_numeric(a = d3_number(array[i]))) s += a; else --j; 20303 } else { 20304 while (++i < n) if (d3_numeric(a = d3_number(f.call(array, array[i], i)))) s += a; else --j; 20305 } 20306 return j ? s / j : undefined; 20307 }; 20308 d3.quantile = function(values, p) { 20309 var H = (values.length - 1) * p + 1, h = Math.floor(H), v = +values[h - 1], e = H - h; 20310 return e ? v + e * (values[h] - v) : v; 20311 }; 20312 d3.median = function(array, f) { 20313 var numbers = [], n = array.length, a, i = -1; 20314 if (arguments.length === 1) { 20315 while (++i < n) if (d3_numeric(a = d3_number(array[i]))) numbers.push(a); 20316 } else { 20317 while (++i < n) if (d3_numeric(a = d3_number(f.call(array, array[i], i)))) numbers.push(a); 20318 } 20319 return numbers.length ? d3.quantile(numbers.sort(d3_ascending), .5) : undefined; 20320 }; 20321 function d3_bisector(compare) { 20322 return { 20323 left: function(a, x, lo, hi) { 20324 if (arguments.length < 3) lo = 0; 20325 if (arguments.length < 4) hi = a.length; 20326 while (lo < hi) { 20327 var mid = lo + hi >>> 1; 20328 if (compare(a[mid], x) < 0) lo = mid + 1; else hi = mid; 20329 } 20330 return lo; 20331 }, 20332 right: function(a, x, lo, hi) { 20333 if (arguments.length < 3) lo = 0; 20334 if (arguments.length < 4) hi = a.length; 20335 while (lo < hi) { 20336 var mid = lo + hi >>> 1; 20337 if (compare(a[mid], x) > 0) hi = mid; else lo = mid + 1; 20338 } 20339 return lo; 20340 } 20341 }; 20342 } 20343 var d3_bisect = d3_bisector(d3_ascending); 20344 d3.bisectLeft = d3_bisect.left; 20345 d3.bisect = d3.bisectRight = d3_bisect.right; 20346 d3.bisector = function(f) { 20347 return d3_bisector(f.length === 1 ? function(d, x) { 20348 return d3_ascending(f(d), x); 20349 } : f); 20350 }; 20351 d3.shuffle = function(array) { 20352 var m = array.length, t, i; 20353 while (m) { 20354 i = Math.random() * m-- | 0; 20355 t = array[m], array[m] = array[i], array[i] = t; 20356 } 20357 return array; 20358 }; 20359 d3.permute = function(array, indexes) { 20360 var i = indexes.length, permutes = new Array(i); 20361 while (i--) permutes[i] = array[indexes[i]]; 20362 return permutes; 20363 }; 20364 d3.pairs = function(array) { 20365 var i = 0, n = array.length - 1, p0, p1 = array[0], pairs = new Array(n < 0 ? 0 : n); 20366 while (i < n) pairs[i] = [ p0 = p1, p1 = array[++i] ]; 20367 return pairs; 20368 };
vendor: 27,908 bytes, lines 20369-21203
20369 d3.zip = function() { 20370 if (!(n = arguments.length)) return []; 20371 for (var i = -1, m = d3.min(arguments, d3_zipLength), zips = new Array(m); ++i < m; ) { 20372 for (var j = -1, n, zip = zips[i] = new Array(n); ++j < n; ) { 20373 zip[j] = arguments[j][i]; 20374 } 20375 } 20376 return zips; 20377 }; 20378 function d3_zipLength(d) { 20379 return d.length; 20380 } 20381 d3.transpose = function(matrix) { 20382 return d3.zip.apply(d3, matrix); 20383 }; 20384 d3.keys = function(map) { 20385 var keys = []; 20386 for (var key in map) keys.push(key); 20387 return keys; 20388 }; 20389 d3.values = function(map) { 20390 var values = []; 20391 for (var key in map) values.push(map[key]); 20392 return values; 20393 }; 20394 d3.entries = function(map) { 20395 var entries = []; 20396 for (var key in map) entries.push({ 20397 key: key, 20398 value: map[key] 20399 }); 20400 return entries; 20401 }; 20402 d3.merge = function(arrays) { 20403 var n = arrays.length, m, i = -1, j = 0, merged, array; 20404 while (++i < n) j += arrays[i].length; 20405 merged = new Array(j); 20406 while (--n >= 0) { 20407 array = arrays[n]; 20408 m = array.length; 20409 while (--m >= 0) { 20410 merged[--j] = array[m]; 20411 } 20412 } 20413 return merged; 20414 }; 20415 var abs = Math.abs; 20416 d3.range = function(start, stop, step) { 20417 if (arguments.length < 3) { 20418 step = 1; 20419 if (arguments.length < 2) { 20420 stop = start; 20421 start = 0; 20422 } 20423 } 20424 if ((stop - start) / step === Infinity) throw new Error("infinite range"); 20425 var range = [], k = d3_range_integerScale(abs(step)), i = -1, j; 20426 start *= k, stop *= k, step *= k; 20427 if (step < 0) while ((j = start + step * ++i) > stop) range.push(j / k); else while ((j = start + step * ++i) < stop) range.push(j / k); 20428 return range; 20429 }; 20430 function d3_range_integerScale(x) { 20431 var k = 1; 20432 while (x * k % 1) k *= 10; 20433 return k; 20434 } 20435 function d3_class(ctor, properties) { 20436 for (var key in properties) { 20437 Object.defineProperty(ctor.prototype, key, { 20438 value: properties[key], 20439 enumerable: false 20440 }); 20441 } 20442 } 20443 d3.map = function(object) { 20444 var map = new d3_Map(); 20445 if (object instanceof d3_Map) object.forEach(function(key, value) { 20446 map.set(key, value); 20447 }); else for (var key in object) map.set(key, object[key]); 20448 return map; 20449 }; 20450 function d3_Map() { 20451 this._ = Object.create(null); 20452 } 20453 var d3_map_proto = "__proto__", d3_map_zero = "\x00"; 20454 d3_class(d3_Map, { 20455 has: d3_map_has, 20456 get: function(key) { 20457 return this._[d3_map_escape(key)]; 20458 }, 20459 set: function(key, value) { 20460 return this._[d3_map_escape(key)] = value; 20461 }, 20462 remove: d3_map_remove, 20463 keys: d3_map_keys, 20464 values: function() { 20465 var values = []; 20466 for (var key in this._) values.push(this._[key]); 20467 return values; 20468 }, 20469 entries: function() { 20470 var entries = []; 20471 for (var key in this._) entries.push({ 20472 key: d3_map_unescape(key), 20473 value: this._[key] 20474 }); 20475 return entries; 20476 }, 20477 size: d3_map_size, 20478 empty: d3_map_empty, 20479 forEach: function(f) { 20480 for (var key in this._) f.call(this, d3_map_unescape(key), this._[key]); 20481 } 20482 }); 20483 function d3_map_escape(key) { 20484 return (key += "") === d3_map_proto || key[0] === d3_map_zero ? d3_map_zero + key : key; 20485 } 20486 function d3_map_unescape(key) { 20487 return (key += "")[0] === d3_map_zero ? key.slice(1) : key; 20488 } 20489 function d3_map_has(key) { 20490 return d3_map_escape(key) in this._; 20491 } 20492 function d3_map_remove(key) { 20493 return (key = d3_map_escape(key)) in this._ && delete this._[key]; 20494 } 20495 function d3_map_keys() { 20496 var keys = []; 20497 for (var key in this._) keys.push(d3_map_unescape(key)); 20498 return keys; 20499 } 20500 function d3_map_size() { 20501 var size = 0; 20502 for (var key in this._) ++size; 20503 return size; 20504 } 20505 function d3_map_empty() { 20506 for (var key in this._) return false; 20507 return true; 20508 } 20509 d3.nest = function() { 20510 var nest = {}, keys = [], sortKeys = [], sortValues, rollup; 20511 function map(mapType, array, depth) { 20512 if (depth >= keys.length) return rollup ? rollup.call(nest, array) : sortValues ? array.sort(sortValues) : array; 20513 var i = -1, n = array.length, key = keys[depth++], keyValue, object, setter, valuesByKey = new d3_Map(), values; 20514 while (++i < n) { 20515 if (values = valuesByKey.get(keyValue = key(object = array[i]))) { 20516 values.push(object); 20517 } else { 20518 valuesByKey.set(keyValue, [ object ]); 20519 } 20520 } 20521 if (mapType) { 20522 object = mapType(); 20523 setter = function(keyValue, values) { 20524 object.set(keyValue, map(mapType, values, depth)); 20525 }; 20526 } else { 20527 object = {}; 20528 setter = function(keyValue, values) { 20529 object[keyValue] = map(mapType, values, depth); 20530 }; 20531 } 20532 valuesByKey.forEach(setter); 20533 return object; 20534 } 20535 function entries(map, depth) { 20536 if (depth >= keys.length) return map; 20537 var array = [], sortKey = sortKeys[depth++]; 20538 map.forEach(function(key, keyMap) { 20539 array.push({ 20540 key: key, 20541 values: entries(keyMap, depth) 20542 }); 20543 }); 20544 return sortKey ? array.sort(function(a, b) { 20545 return sortKey(a.key, b.key); 20546 }) : array; 20547 } 20548 nest.map = function(array, mapType) { 20549 return map(mapType, array, 0); 20550 }; 20551 nest.entries = function(array) { 20552 return entries(map(d3.map, array, 0), 0); 20553 }; 20554 nest.key = function(d) { 20555 keys.push(d); 20556 return nest; 20557 }; 20558 nest.sortKeys = function(order) { 20559 sortKeys[keys.length - 1] = order; 20560 return nest; 20561 }; 20562 nest.sortValues = function(order) { 20563 sortValues = order; 20564 return nest; 20565 }; 20566 nest.rollup = function(f) { 20567 rollup = f; 20568 return nest; 20569 }; 20570 return nest; 20571 }; 20572 d3.set = function(array) { 20573 var set = new d3_Set(); 20574 if (array) for (var i = 0, n = array.length; i < n; ++i) set.add(array[i]); 20575 return set; 20576 }; 20577 function d3_Set() { 20578 this._ = Object.create(null); 20579 } 20580 d3_class(d3_Set, { 20581 has: d3_map_has, 20582 add: function(key) { 20583 this._[d3_map_escape(key += "")] = true; 20584 return key; 20585 }, 20586 remove: d3_map_remove, 20587 values: d3_map_keys, 20588 size: d3_map_size, 20589 empty: d3_map_empty, 20590 forEach: function(f) { 20591 for (var key in this._) f.call(this, d3_map_unescape(key)); 20592 } 20593 }); 20594 d3.behavior = {}; 20595 d3.rebind = function(target, source) { 20596 var i = 1, n = arguments.length, method; 20597 while (++i < n) target[method = arguments[i]] = d3_rebind(target, source, source[method]); 20598 return target; 20599 }; 20600 function d3_rebind(target, source, method) { 20601 return function() { 20602 var value = method.apply(source, arguments); 20603 return value === source ? target : value; 20604 }; 20605 } 20606 function d3_vendorSymbol(object, name) { 20607 if (name in object) return name; 20608 name = name.charAt(0).toUpperCase() + name.slice(1); 20609 for (var i = 0, n = d3_vendorPrefixes.length; i < n; ++i) { 20610 var prefixName = d3_vendorPrefixes[i] + name; 20611 if (prefixName in object) return prefixName; 20612 } 20613 } 20614 var d3_vendorPrefixes = [ "webkit", "ms", "moz", "Moz", "o", "O" ]; 20615 function d3_noop() {} 20616 d3.dispatch = function() { 20617 var dispatch = new d3_dispatch(), i = -1, n = arguments.length; 20618 while (++i < n) dispatch[arguments[i]] = d3_dispatch_event(dispatch); 20619 return dispatch; 20620 }; 20621 function d3_dispatch() {} 20622 d3_dispatch.prototype.on = function(type, listener) { 20623 var i = type.indexOf("."), name = ""; 20624 if (i >= 0) { 20625 name = type.slice(i + 1); 20626 type = type.slice(0, i); 20627 } 20628 if (type) return arguments.length < 2 ? this[type].on(name) : this[type].on(name, listener); 20629 if (arguments.length === 2) { 20630 if (listener == null) for (type in this) { 20631 if (this.hasOwnProperty(type)) this[type].on(name, null); 20632 } 20633 return this; 20634 } 20635 }; 20636 function d3_dispatch_event(dispatch) { 20637 var listeners = [], listenerByName = new d3_Map(); 20638 function event() { 20639 var z = listeners, i = -1, n = z.length, l; 20640 while (++i < n) if (l = z[i].on) l.apply(this, arguments); 20641 return dispatch; 20642 } 20643 event.on = function(name, listener) { 20644 var l = listenerByName.get(name), i; 20645 if (arguments.length < 2) return l && l.on; 20646 if (l) { 20647 l.on = null; 20648 listeners = listeners.slice(0, i = listeners.indexOf(l)).concat(listeners.slice(i + 1)); 20649 listenerByName.remove(name); 20650 } 20651 if (listener) listeners.push(listenerByName.set(name, { 20652 on: listener 20653 })); 20654 return dispatch; 20655 }; 20656 return event; 20657 } 20658 d3.event = null; 20659 function d3_eventPreventDefault() { 20660 d3.event.preventDefault(); 20661 } 20662 function d3_eventSource() { 20663 var e = d3.event, s; 20664 while (s = e.sourceEvent) e = s; 20665 return e; 20666 } 20667 function d3_eventDispatch(target) { 20668 var dispatch = new d3_dispatch(), i = 0, n = arguments.length; 20669 while (++i < n) dispatch[arguments[i]] = d3_dispatch_event(dispatch); 20670 dispatch.of = function(thiz, argumentz) { 20671 return function(e1) { 20672 try { 20673 var e0 = e1.sourceEvent = d3.event; 20674 e1.target = target; 20675 d3.event = e1; 20676 dispatch[e1.type].apply(thiz, argumentz); 20677 } finally { 20678 d3.event = e0; 20679 } 20680 }; 20681 }; 20682 return dispatch; 20683 } 20684 d3.requote = function(s) { 20685 return s.replace(d3_requote_re, "\\$&"); 20686 }; 20687 var d3_requote_re = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g; 20688 var d3_subclass = {}.__proto__ ? function(object, prototype) { 20689 object.__proto__ = prototype; 20690 } : function(object, prototype) { 20691 for (var property in prototype) object[property] = prototype[property]; 20692 }; 20693 function d3_selection(groups) { 20694 d3_subclass(groups, d3_selectionPrototype); 20695 return groups; 20696 } 20697 var d3_select = function(s, n) { 20698 return n.querySelector(s); 20699 }, d3_selectAll = function(s, n) { 20700 return n.querySelectorAll(s); 20701 }, d3_selectMatcher = d3_documentElement.matches || d3_documentElement[d3_vendorSymbol(d3_documentElement, "matchesSelector")], d3_selectMatches = function(n, s) { 20702 return d3_selectMatcher.call(n, s); 20703 }; 20704 if (typeof Sizzle === "function") { 20705 d3_select = function(s, n) { 20706 return Sizzle(s, n)[0] || null; 20707 }; 20708 d3_selectAll = Sizzle; 20709 d3_selectMatches = Sizzle.matchesSelector; 20710 } 20711 d3.selection = function() { 20712 return d3_selectionRoot; 20713 }; 20714 var d3_selectionPrototype = d3.selection.prototype = []; 20715 d3_selectionPrototype.select = function(selector) { 20716 var subgroups = [], subgroup, subnode, group, node; 20717 selector = d3_selection_selector(selector); 20718 for (var j = -1, m = this.length; ++j < m; ) { 20719 subgroups.push(subgroup = []); 20720 subgroup.parentNode = (group = this[j]).parentNode; 20721 for (var i = -1, n = group.length; ++i < n; ) { 20722 if (node = group[i]) { 20723 subgroup.push(subnode = selector.call(node, node.__data__, i, j)); 20724 if (subnode && "__data__" in node) subnode.__data__ = node.__data__; 20725 } else { 20726 subgroup.push(null); 20727 } 20728 } 20729 } 20730 return d3_selection(subgroups); 20731 }; 20732 function d3_selection_selector(selector) { 20733 return typeof selector === "function" ? selector : function() { 20734 return d3_select(selector, this); 20735 }; 20736 } 20737 d3_selectionPrototype.selectAll = function(selector) { 20738 var subgroups = [], subgroup, node; 20739 selector = d3_selection_selectorAll(selector); 20740 for (var j = -1, m = this.length; ++j < m; ) { 20741 for (var group = this[j], i = -1, n = group.length; ++i < n; ) { 20742 if (node = group[i]) { 20743 subgroups.push(subgroup = d3_array(selector.call(node, node.__data__, i, j))); 20744 subgroup.parentNode = node; 20745 } 20746 } 20747 } 20748 return d3_selection(subgroups); 20749 }; 20750 function d3_selection_selectorAll(selector) { 20751 return typeof selector === "function" ? selector : function() { 20752 return d3_selectAll(selector, this); 20753 }; 20754 } 20755 var d3_nsPrefix = { 20756 svg: "http://www.w3.org/2000/svg", 20757 xhtml: "http://www.w3.org/1999/xhtml", 20758 xlink: "http://www.w3.org/1999/xlink", 20759 xml: "http://www.w3.org/XML/1998/namespace", 20760 xmlns: "http://www.w3.org/2000/xmlns/" 20761 }; 20762 d3.ns = { 20763 prefix: d3_nsPrefix, 20764 qualify: function(name) { 20765 var i = name.indexOf(":"), prefix = name; 20766 if (i >= 0) { 20767 prefix = name.slice(0, i); 20768 name = name.slice(i + 1); 20769 } 20770 return d3_nsPrefix.hasOwnProperty(prefix) ? { 20771 space: d3_nsPrefix[prefix], 20772 local: name 20773 } : name; 20774 } 20775 }; 20776 d3_selectionPrototype.attr = function(name, value) { 20777 if (arguments.length < 2) { 20778 if (typeof name === "string") { 20779 var node = this.node(); 20780 name = d3.ns.qualify(name); 20781 return name.local ? node.getAttributeNS(name.space, name.local) : node.getAttribute(name); 20782 } 20783 for (value in name) this.each(d3_selection_attr(value, name[value])); 20784 return this; 20785 } 20786 return this.each(d3_selection_attr(name, value)); 20787 }; 20788 function d3_selection_attr(name, value) { 20789 name = d3.ns.qualify(name); 20790 function attrNull() { 20791 this.removeAttribute(name); 20792 } 20793 function attrNullNS() { 20794 this.removeAttributeNS(name.space, name.local); 20795 } 20796 function attrConstant() { 20797 this.setAttribute(name, value); 20798 } 20799 function attrConstantNS() { 20800 this.setAttributeNS(name.space, name.local, value); 20801 } 20802 function attrFunction() { 20803 var x = value.apply(this, arguments); 20804 if (x == null) this.removeAttribute(name); else this.setAttribute(name, x); 20805 } 20806 function attrFunctionNS() { 20807 var x = value.apply(this, arguments); 20808 if (x == null) this.removeAttributeNS(name.space, name.local); else this.setAttributeNS(name.space, name.local, x); 20809 } 20810 return value == null ? name.local ? attrNullNS : attrNull : typeof value === "function" ? name.local ? attrFunctionNS : attrFunction : name.local ? attrConstantNS : attrConstant; 20811 } 20812 function d3_collapse(s) { 20813 return s.trim().replace(/\s+/g, " "); 20814 } 20815 d3_selectionPrototype.classed = function(name, value) { 20816 if (arguments.length < 2) { 20817 if (typeof name === "string") { 20818 var node = this.node(), n = (name = d3_selection_classes(name)).length, i = -1; 20819 if (value = node.classList) { 20820 while (++i < n) if (!value.contains(name[i])) return false; 20821 } else { 20822 value = node.getAttribute("class"); 20823 while (++i < n) if (!d3_selection_classedRe(name[i]).test(value)) return false; 20824 } 20825 return true; 20826 } 20827 for (value in name) this.each(d3_selection_classed(value, name[value])); 20828 return this; 20829 } 20830 return this.each(d3_selection_classed(name, value)); 20831 }; 20832 function d3_selection_classedRe(name) { 20833 return new RegExp("(?:^|\\s+)" + d3.requote(name) + "(?:\\s+|$)", "g"); 20834 } 20835 function d3_selection_classes(name) { 20836 return (name + "").trim().split(/^|\s+/); 20837 } 20838 function d3_selection_classed(name, value) { 20839 name = d3_selection_classes(name).map(d3_selection_classedName); 20840 var n = name.length; 20841 function classedConstant() { 20842 var i = -1; 20843 while (++i < n) name[i](this, value); 20844 } 20845 function classedFunction() { 20846 var i = -1, x = value.apply(this, arguments); 20847 while (++i < n) name[i](this, x); 20848 } 20849 return typeof value === "function" ? classedFunction : classedConstant; 20850 } 20851 function d3_selection_classedName(name) { 20852 var re = d3_selection_classedRe(name); 20853 return function(node, value) { 20854 if (c = node.classList) return value ? c.add(name) : c.remove(name); 20855 var c = node.getAttribute("class") || ""; 20856 if (value) { 20857 re.lastIndex = 0; 20858 if (!re.test(c)) node.setAttribute("class", d3_collapse(c + " " + name)); 20859 } else { 20860 node.setAttribute("class", d3_collapse(c.replace(re, " "))); 20861 } 20862 }; 20863 } 20864 d3_selectionPrototype.style = function(name, value, priority) { 20865 var n = arguments.length; 20866 if (n < 3) { 20867 if (typeof name !== "string") { 20868 if (n < 2) value = ""; 20869 for (priority in name) this.each(d3_selection_style(priority, name[priority], value)); 20870 return this; 20871 } 20872 if (n < 2) return d3_window.getComputedStyle(this.node(), null).getPropertyValue(name); 20873 priority = ""; 20874 } 20875 return this.each(d3_selection_style(name, value, priority)); 20876 }; 20877 function d3_selection_style(name, value, priority) { 20878 function styleNull() { 20879 this.style.removeProperty(name); 20880 } 20881 function styleConstant() { 20882 this.style.setProperty(name, value, priority); 20883 } 20884 function styleFunction() { 20885 var x = value.apply(this, arguments); 20886 if (x == null) this.style.removeProperty(name); else this.style.setProperty(name, x, priority); 20887 } 20888 return value == null ? styleNull : typeof value === "function" ? styleFunction : styleConstant; 20889 } 20890 d3_selectionPrototype.property = function(name, value) { 20891 if (arguments.length < 2) { 20892 if (typeof name === "string") return this.node()[name]; 20893 for (value in name) this.each(d3_selection_property(value, name[value])); 20894 return this; 20895 } 20896 return this.each(d3_selection_property(name, value)); 20897 }; 20898 function d3_selection_property(name, value) { 20899 function propertyNull() { 20900 delete this[name]; 20901 } 20902 function propertyConstant() { 20903 this[name] = value; 20904 } 20905 function propertyFunction() { 20906 var x = value.apply(this, arguments); 20907 if (x == null) delete this[name]; else this[name] = x; 20908 } 20909 return value == null ? propertyNull : typeof value === "function" ? propertyFunction : propertyConstant; 20910 } 20911 d3_selectionPrototype.text = function(value) { 20912 return arguments.length ? this.each(typeof value === "function" ? function() { 20913 var v = value.apply(this, arguments); 20914 this.textContent = v == null ? "" : v; 20915 } : value == null ? function() { 20916 this.textContent = ""; 20917 } : function() { 20918 this.textContent = value; 20919 }) : this.node().textContent; 20920 }; 20921 d3_selectionPrototype.html = function(value) { 20922 return arguments.length ? this.each(typeof value === "function" ? function() { 20923 var v = value.apply(this, arguments); 20924 this.innerHTML = v == null ? "" : v; 20925 } : value == null ? function() { 20926 this.innerHTML = ""; 20927 } : function() { 20928 this.innerHTML = value; 20929 }) : this.node().innerHTML; 20930 }; 20931 d3_selectionPrototype.append = function(name) { 20932 name = d3_selection_creator(name); 20933 return this.select(function() { 20934 return this.appendChild(name.apply(this, arguments)); 20935 }); 20936 }; 20937 function d3_selection_creator(name) { 20938 return typeof name === "function" ? name : (name = d3.ns.qualify(name)).local ? function() { 20939 return this.ownerDocument.createElementNS(name.space, name.local); 20940 } : function() { 20941 return this.ownerDocument.createElementNS(this.namespaceURI, name); 20942 }; 20943 } 20944 d3_selectionPrototype.insert = function(name, before) { 20945 name = d3_selection_creator(name); 20946 before = d3_selection_selector(before); 20947 return this.select(function() { 20948 return this.insertBefore(name.apply(this, arguments), before.apply(this, arguments) || null); 20949 }); 20950 }; 20951 d3_selectionPrototype.remove = function() { 20952 return this.each(function() { 20953 var parent = this.parentNode; 20954 if (parent) parent.removeChild(this); 20955 }); 20956 }; 20957 d3_selectionPrototype.data = function(value, key) { 20958 var i = -1, n = this.length, group, node; 20959 if (!arguments.length) { 20960 value = new Array(n = (group = this[0]).length); 20961 while (++i < n) { 20962 if (node = group[i]) { 20963 value[i] = node.__data__; 20964 } 20965 } 20966 return value; 20967 } 20968 function bind(group, groupData) { 20969 var i, n = group.length, m = groupData.length, n0 = Math.min(n, m), updateNodes = new Array(m), enterNodes = new Array(m), exitNodes = new Array(n), node, nodeData; 20970 if (key) { 20971 var nodeByKeyValue = new d3_Map(), keyValues = new Array(n), keyValue; 20972 for (i = -1; ++i < n; ) { 20973 if (nodeByKeyValue.has(keyValue = key.call(node = group[i], node.__data__, i))) { 20974 exitNodes[i] = node; 20975 } else { 20976 nodeByKeyValue.set(keyValue, node); 20977 } 20978 keyValues[i] = keyValue; 20979 } 20980 for (i = -1; ++i < m; ) { 20981 if (!(node = nodeByKeyValue.get(keyValue = key.call(groupData, nodeData = groupData[i], i)))) { 20982 enterNodes[i] = d3_selection_dataNode(nodeData); 20983 } else if (node !== true) { 20984 updateNodes[i] = node; 20985 node.__data__ = nodeData; 20986 } 20987 nodeByKeyValue.set(keyValue, true); 20988 } 20989 for (i = -1; ++i < n; ) { 20990 if (nodeByKeyValue.get(keyValues[i]) !== true) { 20991 exitNodes[i] = group[i]; 20992 } 20993 } 20994 } else { 20995 for (i = -1; ++i < n0; ) { 20996 node = group[i]; 20997 nodeData = groupData[i]; 20998 if (node) { 20999 node.__data__ = nodeData; 21000 updateNodes[i] = node; 21001 } else { 21002 enterNodes[i] = d3_selection_dataNode(nodeData); 21003 } 21004 } 21005 for (;i < m; ++i) { 21006 enterNodes[i] = d3_selection_dataNode(groupData[i]); 21007 } 21008 for (;i < n; ++i) { 21009 exitNodes[i] = group[i]; 21010 } 21011 } 21012 enterNodes.update = updateNodes; 21013 enterNodes.parentNode = updateNodes.parentNode = exitNodes.parentNode = group.parentNode; 21014 enter.push(enterNodes); 21015 update.push(updateNodes); 21016 exit.push(exitNodes); 21017 } 21018 var enter = d3_selection_enter([]), update = d3_selection([]), exit = d3_selection([]); 21019 if (typeof value === "function") { 21020 while (++i < n) { 21021 bind(group = this[i], value.call(group, group.parentNode.__data__, i)); 21022 } 21023 } else { 21024 while (++i < n) { 21025 bind(group = this[i], value); 21026 } 21027 } 21028 update.enter = function() { 21029 return enter; 21030 }; 21031 update.exit = function() { 21032 return exit; 21033 }; 21034 return update; 21035 }; 21036 function d3_selection_dataNode(data) { 21037 return { 21038 __data__: data 21039 }; 21040 } 21041 d3_selectionPrototype.datum = function(value) { 21042 return arguments.length ? this.property("__data__", value) : this.property("__data__"); 21043 }; 21044 d3_selectionPrototype.filter = function(filter) { 21045 var subgroups = [], subgroup, group, node; 21046 if (typeof filter !== "function") filter = d3_selection_filter(filter); 21047 for (var j = 0, m = this.length; j < m; j++) { 21048 subgroups.push(subgroup = []); 21049 subgroup.parentNode = (group = this[j]).parentNode; 21050 for (var i = 0, n = group.length; i < n; i++) { 21051 if ((node = group[i]) && filter.call(node, node.__data__, i, j)) { 21052 subgroup.push(node); 21053 } 21054 } 21055 } 21056 return d3_selection(subgroups); 21057 }; 21058 function d3_selection_filter(selector) { 21059 return function() { 21060 return d3_selectMatches(this, selector); 21061 }; 21062 } 21063 d3_selectionPrototype.order = function() { 21064 for (var j = -1, m = this.length; ++j < m; ) { 21065 for (var group = this[j], i = group.length - 1, next = group[i], node; --i >= 0; ) { 21066 if (node = group[i]) { 21067 if (next && next !== node.nextSibling) next.parentNode.insertBefore(node, next); 21068 next = node; 21069 } 21070 } 21071 } 21072 return this; 21073 }; 21074 d3_selectionPrototype.sort = function(comparator) { 21075 comparator = d3_selection_sortComparator.apply(this, arguments); 21076 for (var j = -1, m = this.length; ++j < m; ) this[j].sort(comparator); 21077 return this.order(); 21078 }; 21079 function d3_selection_sortComparator(comparator) { 21080 if (!arguments.length) comparator = d3_ascending; 21081 return function(a, b) { 21082 return a && b ? comparator(a.__data__, b.__data__) : !a - !b; 21083 }; 21084 } 21085 d3_selectionPrototype.each = function(callback) { 21086 return d3_selection_each(this, function(node, i, j) { 21087 callback.call(node, node.__data__, i, j); 21088 }); 21089 }; 21090 function d3_selection_each(groups, callback) { 21091 for (var j = 0, m = groups.length; j < m; j++) { 21092 for (var group = groups[j], i = 0, n = group.length, node; i < n; i++) { 21093 if (node = group[i]) callback(node, i, j); 21094 } 21095 } 21096 return groups; 21097 } 21098 d3_selectionPrototype.call = function(callback) { 21099 var args = d3_array(arguments); 21100 callback.apply(args[0] = this, args); 21101 return this; 21102 }; 21103 d3_selectionPrototype.empty = function() { 21104 return !this.node(); 21105 }; 21106 d3_selectionPrototype.node = function() { 21107 for (var j = 0, m = this.length; j < m; j++) { 21108 for (var group = this[j], i = 0, n = group.length; i < n; i++) { 21109 var node = group[i]; 21110 if (node) return node; 21111 } 21112 } 21113 return null; 21114 }; 21115 d3_selectionPrototype.size = function() { 21116 var n = 0; 21117 d3_selection_each(this, function() { 21118 ++n; 21119 }); 21120 return n; 21121 }; 21122 function d3_selection_enter(selection) { 21123 d3_subclass(selection, d3_selection_enterPrototype); 21124 return selection; 21125 } 21126 var d3_selection_enterPrototype = []; 21127 d3.selection.enter = d3_selection_enter; 21128 d3.selection.enter.prototype = d3_selection_enterPrototype; 21129 d3_selection_enterPrototype.append = d3_selectionPrototype.append; 21130 d3_selection_enterPrototype.empty = d3_selectionPrototype.empty; 21131 d3_selection_enterPrototype.node = d3_selectionPrototype.node; 21132 d3_selection_enterPrototype.call = d3_selectionPrototype.call; 21133 d3_selection_enterPrototype.size = d3_selectionPrototype.size; 21134 d3_selection_enterPrototype.select = function(selector) { 21135 var subgroups = [], subgroup, subnode, upgroup, group, node; 21136 for (var j = -1, m = this.length; ++j < m; ) { 21137 upgroup = (group = this[j]).update; 21138 subgroups.push(subgroup = []); 21139 subgroup.parentNode = group.parentNode; 21140 for (var i = -1, n = group.length; ++i < n; ) { 21141 if (node = group[i]) { 21142 subgroup.push(upgroup[i] = subnode = selector.call(group.parentNode, node.__data__, i, j)); 21143 subnode.__data__ = node.__data__; 21144 } else { 21145 subgroup.push(null); 21146 } 21147 } 21148 } 21149 return d3_selection(subgroups); 21150 }; 21151 d3_selection_enterPrototype.insert = function(name, before) { 21152 if (arguments.length < 2) before = d3_selection_enterInsertBefore(this); 21153 return d3_selectionPrototype.insert.call(this, name, before); 21154 }; 21155 function d3_selection_enterInsertBefore(enter) { 21156 var i0, j0; 21157 return function(d, i, j) { 21158 var group = enter[j].update, n = group.length, node; 21159 if (j != j0) j0 = j, i0 = 0; 21160 if (i >= i0) i0 = i + 1; 21161 while (!(node = group[i0]) && ++i0 < n) ; 21162 return node; 21163 }; 21164 } 21165 d3_selectionPrototype.transition = function() { 21166 var id = d3_transitionInheritId || ++d3_transitionId, subgroups = [], subgroup, node, transition = d3_transitionInherit || { 21167 time: Date.now(), 21168 ease: d3_ease_cubicInOut, 21169 delay: 0, 21170 duration: 250 21171 }; 21172 for (var j = -1, m = this.length; ++j < m; ) { 21173 subgroups.push(subgroup = []); 21174 for (var group = this[j], i = -1, n = group.length; ++i < n; ) { 21175 if (node = group[i]) d3_transitionNode(node, i, id, transition); 21176 subgroup.push(node); 21177 } 21178 } 21179 return d3_transition(subgroups, id); 21180 }; 21181 d3_selectionPrototype.interrupt = function() { 21182 return this.each(d3_selection_interrupt); 21183 }; 21184 function d3_selection_interrupt() { 21185 var lock = this.__transition__; 21186 if (lock) ++lock.active; 21187 } 21188 d3.select = function(node) { 21189 var group = [ typeof node === "string" ? d3_select(node, d3_document) : node ]; 21190 group.parentNode = d3_documentElement; 21191 return d3_selection([ group ]); 21192 }; 21193 d3.selectAll = function(nodes) { 21194 var group = d3_array(typeof nodes === "string" ? d3_selectAll(nodes, d3_document) : nodes); 21195 group.parentNode = d3_documentElement; 21196 return d3_selection([ group ]); 21197 }; 21198 var d3_selectionRoot = d3.select(d3_documentElement); 21199 d3_selectionPrototype.on = function(type, listener, capture) { 21200 var n = arguments.length; 21201 if (n < 3) { 21202 if (typeof type !== "string") { 21203 if (n < 2) listener = false;
vendor: 2,326 bytes, lines 21204-21271
21204 for (capture in type) this.each(d3_selection_on(capture, type[capture], listener)); 21205 return this; 21206 } 21207 if (n < 2) return (n = this.node()["__on" + type]) && n._; 21208 capture = false; 21209 } 21210 return this.each(d3_selection_on(type, listener, capture)); 21211 }; 21212 function d3_selection_on(type, listener, capture) { 21213 var name = "__on" + type, i = type.indexOf("."), wrap = d3_selection_onListener; 21214 if (i > 0) type = type.slice(0, i); 21215 var filter = d3_selection_onFilters.get(type); 21216 if (filter) type = filter, wrap = d3_selection_onFilter; 21217 function onRemove() { 21218 var l = this[name]; 21219 if (l) { 21220 this.removeEventListener(type, l, l.$); 21221 delete this[name]; 21222 } 21223 } 21224 function onAdd() { 21225 var l = wrap(listener, d3_array(arguments)); 21226 onRemove.call(this); 21227 this.addEventListener(type, this[name] = l, l.$ = capture); 21228 l._ = listener; 21229 } 21230 function removeAll() { 21231 var re = new RegExp("^__on([^.]+)" + d3.requote(type) + "$"), match; 21232 for (var name in this) { 21233 if (match = name.match(re)) { 21234 var l = this[name]; 21235 this.removeEventListener(match[1], l, l.$); 21236 delete this[name]; 21237 } 21238 } 21239 } 21240 return i ? listener ? onAdd : onRemove : listener ? d3_noop : removeAll; 21241 } 21242 var d3_selection_onFilters = d3.map({ 21243 mouseenter: "mouseover", 21244 mouseleave: "mouseout" 21245 }); 21246 d3_selection_onFilters.forEach(function(k) { 21247 if ("on" + k in d3_document) d3_selection_onFilters.remove(k); 21248 }); 21249 function d3_selection_onListener(listener, argumentz) { 21250 return function(e) { 21251 var o = d3.event; 21252 d3.event = e; 21253 argumentz[0] = this.__data__; 21254 try { 21255 listener.apply(this, argumentz); 21256 } finally { 21257 d3.event = o; 21258 } 21259 }; 21260 } 21261 function d3_selection_onFilter(listener, argumentz) { 21262 var l = d3_selection_onListener(listener, argumentz); 21263 return function(e) { 21264 var target = this, related = e.relatedTarget; 21265 if (!related || related !== target && !(related.compareDocumentPosition(target) & 8)) { 21266 l.call(target, e); 21267 } 21268 }; 21269 } 21270 var d3_event_dragSelect = "onselectstart" in d3_document ? null : d3_vendorSymbol(d3_documentElement.style, "userSelect"), d3_event_dragId = 0; 21271 function d3_event_dragSuppress() {
vendor: 23,103 bytes, lines 21272-21873
21272 var name = ".dragsuppress-" + ++d3_event_dragId, click = "click" + name, w = d3.select(d3_window).on("touchmove" + name, d3_eventPreventDefault).on("dragstart" + name, d3_eventPreventDefault).on("selectstart" + name, d3_eventPreventDefault); 21273 if (d3_event_dragSelect) { 21274 var style = d3_documentElement.style, select = style[d3_event_dragSelect]; 21275 style[d3_event_dragSelect] = "none"; 21276 } 21277 return function(suppressClick) { 21278 w.on(name, null); 21279 if (d3_event_dragSelect) style[d3_event_dragSelect] = select; 21280 if (suppressClick) { 21281 function off() { 21282 w.on(click, null); 21283 } 21284 w.on(click, function() { 21285 d3_eventPreventDefault(); 21286 off(); 21287 }, true); 21288 setTimeout(off, 0); 21289 } 21290 }; 21291 } 21292 d3.mouse = function(container) { 21293 return d3_mousePoint(container, d3_eventSource()); 21294 }; 21295 var d3_mouse_bug44083 = /WebKit/.test(d3_window.navigator.userAgent) ? -1 : 0; 21296 function d3_mousePoint(container, e) { 21297 if (e.changedTouches) e = e.changedTouches[0]; 21298 var svg = container.ownerSVGElement || container; 21299 if (svg.createSVGPoint) { 21300 var point = svg.createSVGPoint(); 21301 if (d3_mouse_bug44083 < 0 && (d3_window.scrollX || d3_window.scrollY)) { 21302 svg = d3.select("body").append("svg").style({ 21303 position: "absolute", 21304 top: 0, 21305 left: 0, 21306 margin: 0, 21307 padding: 0, 21308 border: "none" 21309 }, "important"); 21310 var ctm = svg[0][0].getScreenCTM(); 21311 d3_mouse_bug44083 = !(ctm.f || ctm.e); 21312 svg.remove(); 21313 } 21314 if (d3_mouse_bug44083) point.x = e.pageX, point.y = e.pageY; else point.x = e.clientX, 21315 point.y = e.clientY; 21316 point = point.matrixTransform(container.getScreenCTM().inverse()); 21317 return [ point.x, point.y ]; 21318 } 21319 var rect = container.getBoundingClientRect(); 21320 return [ e.clientX - rect.left - container.clientLeft, e.clientY - rect.top - container.clientTop ]; 21321 } 21322 d3.touch = function(container, touches, identifier) { 21323 if (arguments.length < 3) identifier = touches, touches = d3_eventSource().changedTouches; 21324 if (touches) for (var i = 0, n = touches.length, touch; i < n; ++i) { 21325 if ((touch = touches[i]).identifier === identifier) { 21326 return d3_mousePoint(container, touch); 21327 } 21328 } 21329 }; 21330 d3.behavior.drag = function() { 21331 var event = d3_eventDispatch(drag, "drag", "dragstart", "dragend"), origin = null, mousedown = dragstart(d3_noop, d3.mouse, d3_behavior_dragMouseSubject, "mousemove", "mouseup"), touchstart = dragstart(d3_behavior_dragTouchId, d3.touch, d3_behavior_dragTouchSubject, "touchmove", "touchend"); 21332 function drag() { 21333 this.on("mousedown.drag", mousedown).on("touchstart.drag", touchstart); 21334 } 21335 function dragstart(id, position, subject, move, end) { 21336 return function() { 21337 var that = this, target = d3.event.target, parent = that.parentNode, dispatch = event.of(that, arguments), dragged = 0, dragId = id(), dragName = ".drag" + (dragId == null ? "" : "-" + dragId), dragOffset, dragSubject = d3.select(subject()).on(move + dragName, moved).on(end + dragName, ended), dragRestore = d3_event_dragSuppress(), position0 = position(parent, dragId); 21338 if (origin) { 21339 dragOffset = origin.apply(that, arguments); 21340 dragOffset = [ dragOffset.x - position0[0], dragOffset.y - position0[1] ]; 21341 } else { 21342 dragOffset = [ 0, 0 ]; 21343 } 21344 dispatch({ 21345 type: "dragstart" 21346 }); 21347 function moved() { 21348 var position1 = position(parent, dragId), dx, dy; 21349 if (!position1) return; 21350 dx = position1[0] - position0[0]; 21351 dy = position1[1] - position0[1]; 21352 dragged |= dx | dy; 21353 position0 = position1; 21354 dispatch({ 21355 type: "drag", 21356 x: position1[0] + dragOffset[0], 21357 y: position1[1] + dragOffset[1], 21358 dx: dx, 21359 dy: dy 21360 }); 21361 } 21362 function ended() { 21363 if (!position(parent, dragId)) return; 21364 dragSubject.on(move + dragName, null).on(end + dragName, null); 21365 dragRestore(dragged && d3.event.target === target); 21366 dispatch({ 21367 type: "dragend" 21368 }); 21369 } 21370 }; 21371 } 21372 drag.origin = function(x) { 21373 if (!arguments.length) return origin; 21374 origin = x; 21375 return drag; 21376 }; 21377 return d3.rebind(drag, event, "on"); 21378 }; 21379 function d3_behavior_dragTouchId() { 21380 return d3.event.changedTouches[0].identifier; 21381 } 21382 function d3_behavior_dragTouchSubject() { 21383 return d3.event.target; 21384 } 21385 function d3_behavior_dragMouseSubject() { 21386 return d3_window; 21387 } 21388 d3.touches = function(container, touches) { 21389 if (arguments.length < 2) touches = d3_eventSource().touches; 21390 return touches ? d3_array(touches).map(function(touch) { 21391 var point = d3_mousePoint(container, touch); 21392 point.identifier = touch.identifier; 21393 return point; 21394 }) : []; 21395 }; 21396 var Ï = Math.PI, Ï = 2 * Ï, halfÏ = Ï / 2, ε = 1e-6, ε2 = ε * ε, d3_radians = Ï / 180, d3_degrees = 180 / Ï; 21397 function d3_sgn(x) { 21398 return x > 0 ? 1 : x < 0 ? -1 : 0; 21399 } 21400 function d3_cross2d(a, b, c) { 21401 return (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0]); 21402 } 21403 function d3_acos(x) { 21404 return x > 1 ? 0 : x < -1 ? Ï : Math.acos(x); 21405 } 21406 function d3_asin(x) { 21407 return x > 1 ? halfÏ : x < -1 ? -halfÏ : Math.asin(x); 21408 } 21409 function d3_sinh(x) { 21410 return ((x = Math.exp(x)) - 1 / x) / 2; 21411 } 21412 function d3_cosh(x) { 21413 return ((x = Math.exp(x)) + 1 / x) / 2; 21414 } 21415 function d3_tanh(x) { 21416 return ((x = Math.exp(2 * x)) - 1) / (x + 1); 21417 } 21418 function d3_haversin(x) { 21419 return (x = Math.sin(x / 2)) * x; 21420 } 21421 var Ï = Math.SQRT2, Ï2 = 2, Ï4 = 4; 21422 d3.interpolateZoom = function(p0, p1) { 21423 var ux0 = p0[0], uy0 = p0[1], w0 = p0[2], ux1 = p1[0], uy1 = p1[1], w1 = p1[2]; 21424 var dx = ux1 - ux0, dy = uy1 - uy0, d2 = dx * dx + dy * dy, d1 = Math.sqrt(d2), b0 = (w1 * w1 - w0 * w0 + Ï4 * d2) / (2 * w0 * Ï2 * d1), b1 = (w1 * w1 - w0 * w0 - Ï4 * d2) / (2 * w1 * Ï2 * d1), r0 = Math.log(Math.sqrt(b0 * b0 + 1) - b0), r1 = Math.log(Math.sqrt(b1 * b1 + 1) - b1), dr = r1 - r0, S = (dr || Math.log(w1 / w0)) / Ï; 21425 function interpolate(t) { 21426 var s = t * S; 21427 if (dr) { 21428 var coshr0 = d3_cosh(r0), u = w0 / (Ï2 * d1) * (coshr0 * d3_tanh(Ï * s + r0) - d3_sinh(r0)); 21429 return [ ux0 + u * dx, uy0 + u * dy, w0 * coshr0 / d3_cosh(Ï * s + r0) ]; 21430 } 21431 return [ ux0 + t * dx, uy0 + t * dy, w0 * Math.exp(Ï * s) ]; 21432 } 21433 interpolate.duration = S * 1e3; 21434 return interpolate; 21435 }; 21436 d3.behavior.zoom = function() { 21437 var view = { 21438 x: 0, 21439 y: 0, 21440 k: 1 21441 }, translate0, center0, center, size = [ 960, 500 ], scaleExtent = d3_behavior_zoomInfinity, mousedown = "mousedown.zoom", mousemove = "mousemove.zoom", mouseup = "mouseup.zoom", mousewheelTimer, touchstart = "touchstart.zoom", touchtime, event = d3_eventDispatch(zoom, "zoomstart", "zoom", "zoomend"), x0, x1, y0, y1; 21442 function zoom(g) { 21443 g.on(mousedown, mousedowned).on(d3_behavior_zoomWheel + ".zoom", mousewheeled).on("dblclick.zoom", dblclicked).on(touchstart, touchstarted); 21444 } 21445 zoom.event = function(g) { 21446 g.each(function() { 21447 var dispatch = event.of(this, arguments), view1 = view; 21448 if (d3_transitionInheritId) { 21449 d3.select(this).transition().each("start.zoom", function() { 21450 view = this.__chart__ || { 21451 x: 0, 21452 y: 0, 21453 k: 1 21454 }; 21455 zoomstarted(dispatch); 21456 }).tween("zoom:zoom", function() { 21457 var dx = size[0], dy = size[1], cx = dx / 2, cy = dy / 2, i = d3.interpolateZoom([ (cx - view.x) / view.k, (cy - view.y) / view.k, dx / view.k ], [ (cx - view1.x) / view1.k, (cy - view1.y) / view1.k, dx / view1.k ]); 21458 return function(t) { 21459 var l = i(t), k = dx / l[2]; 21460 this.__chart__ = view = { 21461 x: cx - l[0] * k, 21462 y: cy - l[1] * k, 21463 k: k 21464 }; 21465 zoomed(dispatch); 21466 }; 21467 }).each("end.zoom", function() { 21468 zoomended(dispatch); 21469 }); 21470 } else { 21471 this.__chart__ = view; 21472 zoomstarted(dispatch); 21473 zoomed(dispatch); 21474 zoomended(dispatch); 21475 } 21476 }); 21477 }; 21478 zoom.translate = function(_) { 21479 if (!arguments.length) return [ view.x, view.y ]; 21480 view = { 21481 x: +_[0], 21482 y: +_[1], 21483 k: view.k 21484 }; 21485 rescale(); 21486 return zoom; 21487 }; 21488 zoom.scale = function(_) { 21489 if (!arguments.length) return view.k; 21490 view = { 21491 x: view.x, 21492 y: view.y, 21493 k: +_ 21494 }; 21495 rescale(); 21496 return zoom; 21497 }; 21498 zoom.scaleExtent = function(_) { 21499 if (!arguments.length) return scaleExtent; 21500 scaleExtent = _ == null ? d3_behavior_zoomInfinity : [ +_[0], +_[1] ]; 21501 return zoom; 21502 }; 21503 zoom.center = function(_) { 21504 if (!arguments.length) return center; 21505 center = _ && [ +_[0], +_[1] ]; 21506 return zoom; 21507 }; 21508 zoom.size = function(_) { 21509 if (!arguments.length) return size; 21510 size = _ && [ +_[0], +_[1] ]; 21511 return zoom; 21512 }; 21513 zoom.x = function(z) { 21514 if (!arguments.length) return x1; 21515 x1 = z; 21516 x0 = z.copy(); 21517 view = { 21518 x: 0, 21519 y: 0, 21520 k: 1 21521 }; 21522 return zoom; 21523 }; 21524 zoom.y = function(z) { 21525 if (!arguments.length) return y1; 21526 y1 = z; 21527 y0 = z.copy(); 21528 view = { 21529 x: 0, 21530 y: 0, 21531 k: 1 21532 }; 21533 return zoom; 21534 }; 21535 function location(p) { 21536 return [ (p[0] - view.x) / view.k, (p[1] - view.y) / view.k ]; 21537 } 21538 function point(l) { 21539 return [ l[0] * view.k + view.x, l[1] * view.k + view.y ]; 21540 } 21541 function scaleTo(s) { 21542 view.k = Math.max(scaleExtent[0], Math.min(scaleExtent[1], s)); 21543 } 21544 function translateTo(p, l) { 21545 l = point(l); 21546 view.x += p[0] - l[0]; 21547 view.y += p[1] - l[1]; 21548 } 21549 function rescale() { 21550 if (x1) x1.domain(x0.range().map(function(x) { 21551 return (x - view.x) / view.k; 21552 }).map(x0.invert)); 21553 if (y1) y1.domain(y0.range().map(function(y) { 21554 return (y - view.y) / view.k; 21555 }).map(y0.invert)); 21556 } 21557 function zoomstarted(dispatch) { 21558 dispatch({ 21559 type: "zoomstart" 21560 }); 21561 } 21562 function zoomed(dispatch) { 21563 rescale(); 21564 dispatch({ 21565 type: "zoom", 21566 scale: view.k, 21567 translate: [ view.x, view.y ] 21568 }); 21569 } 21570 function zoomended(dispatch) { 21571 dispatch({ 21572 type: "zoomend" 21573 }); 21574 } 21575 function mousedowned() { 21576 var that = this, target = d3.event.target, dispatch = event.of(that, arguments), dragged = 0, subject = d3.select(d3_window).on(mousemove, moved).on(mouseup, ended), location0 = location(d3.mouse(that)), dragRestore = d3_event_dragSuppress(); 21577 d3_selection_interrupt.call(that); 21578 zoomstarted(dispatch); 21579 function moved() { 21580 dragged = 1; 21581 translateTo(d3.mouse(that), location0); 21582 zoomed(dispatch); 21583 } 21584 function ended() { 21585 subject.on(mousemove, null).on(mouseup, null); 21586 dragRestore(dragged && d3.event.target === target); 21587 zoomended(dispatch); 21588 } 21589 } 21590 function touchstarted() { 21591 var that = this, dispatch = event.of(that, arguments), locations0 = {}, distance0 = 0, scale0, zoomName = ".zoom-" + d3.event.changedTouches[0].identifier, touchmove = "touchmove" + zoomName, touchend = "touchend" + zoomName, targets = [], subject = d3.select(that), dragRestore = d3_event_dragSuppress(); 21592 d3_selection_interrupt.call(that); 21593 started(); 21594 zoomstarted(dispatch); 21595 subject.on(mousedown, null).on(touchstart, started); 21596 function relocate() { 21597 var touches = d3.touches(that); 21598 scale0 = view.k; 21599 touches.forEach(function(t) { 21600 if (t.identifier in locations0) locations0[t.identifier] = location(t); 21601 }); 21602 return touches; 21603 } 21604 function started() { 21605 var target = d3.event.target; 21606 d3.select(target).on(touchmove, moved).on(touchend, ended); 21607 targets.push(target); 21608 var changed = d3.event.changedTouches; 21609 for (var i = 0, n = changed.length; i < n; ++i) { 21610 locations0[changed[i].identifier] = null; 21611 } 21612 var touches = relocate(), now = Date.now(); 21613 if (touches.length === 1) { 21614 if (now - touchtime < 500) { 21615 var p = touches[0], l = locations0[p.identifier]; 21616 scaleTo(view.k * 2); 21617 translateTo(p, l); 21618 d3_eventPreventDefault(); 21619 zoomed(dispatch); 21620 } 21621 touchtime = now; 21622 } else if (touches.length > 1) { 21623 var p = touches[0], q = touches[1], dx = p[0] - q[0], dy = p[1] - q[1]; 21624 distance0 = dx * dx + dy * dy; 21625 } 21626 } 21627 function moved() { 21628 var touches = d3.touches(that), p0, l0, p1, l1; 21629 for (var i = 0, n = touches.length; i < n; ++i, l1 = null) { 21630 p1 = touches[i]; 21631 if (l1 = locations0[p1.identifier]) { 21632 if (l0) break; 21633 p0 = p1, l0 = l1; 21634 } 21635 } 21636 if (l1) { 21637 var distance1 = (distance1 = p1[0] - p0[0]) * distance1 + (distance1 = p1[1] - p0[1]) * distance1, scale1 = distance0 && Math.sqrt(distance1 / distance0); 21638 p0 = [ (p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2 ]; 21639 l0 = [ (l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2 ]; 21640 scaleTo(scale1 * scale0); 21641 } 21642 touchtime = null; 21643 translateTo(p0, l0); 21644 zoomed(dispatch); 21645 } 21646 function ended() { 21647 if (d3.event.touches.length) { 21648 var changed = d3.event.changedTouches; 21649 for (var i = 0, n = changed.length; i < n; ++i) { 21650 delete locations0[changed[i].identifier]; 21651 } 21652 for (var identifier in locations0) { 21653 return void relocate(); 21654 } 21655 } 21656 d3.selectAll(targets).on(zoomName, null); 21657 subject.on(mousedown, mousedowned).on(touchstart, touchstarted); 21658 dragRestore(); 21659 zoomended(dispatch); 21660 } 21661 } 21662 function mousewheeled() { 21663 var dispatch = event.of(this, arguments); 21664 if (mousewheelTimer) clearTimeout(mousewheelTimer); else translate0 = location(center0 = center || d3.mouse(this)), 21665 d3_selection_interrupt.call(this), zoomstarted(dispatch); 21666 mousewheelTimer = setTimeout(function() { 21667 mousewheelTimer = null; 21668 zoomended(dispatch); 21669 }, 50); 21670 d3_eventPreventDefault(); 21671 scaleTo(Math.pow(2, d3_behavior_zoomDelta() * .002) * view.k); 21672 translateTo(center0, translate0); 21673 zoomed(dispatch); 21674 } 21675 function dblclicked() { 21676 var dispatch = event.of(this, arguments), p = d3.mouse(this), l = location(p), k = Math.log(view.k) / Math.LN2; 21677 zoomstarted(dispatch); 21678 scaleTo(Math.pow(2, d3.event.shiftKey ? Math.ceil(k) - 1 : Math.floor(k) + 1)); 21679 translateTo(p, l); 21680 zoomed(dispatch); 21681 zoomended(dispatch); 21682 } 21683 return d3.rebind(zoom, event, "on"); 21684 }; 21685 var d3_behavior_zoomInfinity = [ 0, Infinity ]; 21686 var d3_behavior_zoomDelta, d3_behavior_zoomWheel = "onwheel" in d3_document ? (d3_behavior_zoomDelta = function() { 21687 return -d3.event.deltaY * (d3.event.deltaMode ? 120 : 1); 21688 }, "wheel") : "onmousewheel" in d3_document ? (d3_behavior_zoomDelta = function() { 21689 return d3.event.wheelDelta; 21690 }, "mousewheel") : (d3_behavior_zoomDelta = function() { 21691 return -d3.event.detail; 21692 }, "MozMousePixelScroll"); 21693 d3.color = d3_color; 21694 function d3_color() {} 21695 d3_color.prototype.toString = function() { 21696 return this.rgb() + ""; 21697 }; 21698 d3.hsl = d3_hsl; 21699 function d3_hsl(h, s, l) { 21700 return this instanceof d3_hsl ? void (this.h = +h, this.s = +s, this.l = +l) : arguments.length < 2 ? h instanceof d3_hsl ? new d3_hsl(h.h, h.s, h.l) : d3_rgb_parse("" + h, d3_rgb_hsl, d3_hsl) : new d3_hsl(h, s, l); 21701 } 21702 var d3_hslPrototype = d3_hsl.prototype = new d3_color(); 21703 d3_hslPrototype.brighter = function(k) { 21704 k = Math.pow(.7, arguments.length ? k : 1); 21705 return new d3_hsl(this.h, this.s, this.l / k); 21706 }; 21707 d3_hslPrototype.darker = function(k) { 21708 k = Math.pow(.7, arguments.length ? k : 1); 21709 return new d3_hsl(this.h, this.s, k * this.l); 21710 }; 21711 d3_hslPrototype.rgb = function() { 21712 return d3_hsl_rgb(this.h, this.s, this.l); 21713 }; 21714 function d3_hsl_rgb(h, s, l) { 21715 var m1, m2; 21716 h = isNaN(h) ? 0 : (h %= 360) < 0 ? h + 360 : h; 21717 s = isNaN(s) ? 0 : s < 0 ? 0 : s > 1 ? 1 : s; 21718 l = l < 0 ? 0 : l > 1 ? 1 : l; 21719 m2 = l <= .5 ? l * (1 + s) : l + s - l * s; 21720 m1 = 2 * l - m2; 21721 function v(h) { 21722 if (h > 360) h -= 360; else if (h < 0) h += 360; 21723 if (h < 60) return m1 + (m2 - m1) * h / 60; 21724 if (h < 180) return m2; 21725 if (h < 240) return m1 + (m2 - m1) * (240 - h) / 60; 21726 return m1; 21727 } 21728 function vv(h) { 21729 return Math.round(v(h) * 255); 21730 } 21731 return new d3_rgb(vv(h + 120), vv(h), vv(h - 120)); 21732 } 21733 d3.hcl = d3_hcl; 21734 function d3_hcl(h, c, l) { 21735 return this instanceof d3_hcl ? void (this.h = +h, this.c = +c, this.l = +l) : arguments.length < 2 ? h instanceof d3_hcl ? new d3_hcl(h.h, h.c, h.l) : h instanceof d3_lab ? d3_lab_hcl(h.l, h.a, h.b) : d3_lab_hcl((h = d3_rgb_lab((h = d3.rgb(h)).r, h.g, h.b)).l, h.a, h.b) : new d3_hcl(h, c, l); 21736 } 21737 var d3_hclPrototype = d3_hcl.prototype = new d3_color(); 21738 d3_hclPrototype.brighter = function(k) { 21739 return new d3_hcl(this.h, this.c, Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1))); 21740 }; 21741 d3_hclPrototype.darker = function(k) { 21742 return new d3_hcl(this.h, this.c, Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1))); 21743 }; 21744 d3_hclPrototype.rgb = function() { 21745 return d3_hcl_lab(this.h, this.c, this.l).rgb(); 21746 }; 21747 function d3_hcl_lab(h, c, l) { 21748 if (isNaN(h)) h = 0; 21749 if (isNaN(c)) c = 0; 21750 return new d3_lab(l, Math.cos(h *= d3_radians) * c, Math.sin(h) * c); 21751 } 21752 d3.lab = d3_lab; 21753 function d3_lab(l, a, b) { 21754 return this instanceof d3_lab ? void (this.l = +l, this.a = +a, this.b = +b) : arguments.length < 2 ? l instanceof d3_lab ? new d3_lab(l.l, l.a, l.b) : l instanceof d3_hcl ? d3_hcl_lab(l.h, l.c, l.l) : d3_rgb_lab((l = d3_rgb(l)).r, l.g, l.b) : new d3_lab(l, a, b); 21755 } 21756 var d3_lab_K = 18; 21757 var d3_lab_X = .95047, d3_lab_Y = 1, d3_lab_Z = 1.08883; 21758 var d3_labPrototype = d3_lab.prototype = new d3_color(); 21759 d3_labPrototype.brighter = function(k) { 21760 return new d3_lab(Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1)), this.a, this.b); 21761 }; 21762 d3_labPrototype.darker = function(k) { 21763 return new d3_lab(Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1)), this.a, this.b); 21764 }; 21765 d3_labPrototype.rgb = function() { 21766 return d3_lab_rgb(this.l, this.a, this.b); 21767 }; 21768 function d3_lab_rgb(l, a, b) { 21769 var y = (l + 16) / 116, x = y + a / 500, z = y - b / 200; 21770 x = d3_lab_xyz(x) * d3_lab_X; 21771 y = d3_lab_xyz(y) * d3_lab_Y; 21772 z = d3_lab_xyz(z) * d3_lab_Z; 21773 return new d3_rgb(d3_xyz_rgb(3.2404542 * x - 1.5371385 * y - .4985314 * z), d3_xyz_rgb(-.969266 * x + 1.8760108 * y + .041556 * z), d3_xyz_rgb(.0556434 * x - .2040259 * y + 1.0572252 * z)); 21774 } 21775 function d3_lab_hcl(l, a, b) { 21776 return l > 0 ? new d3_hcl(Math.atan2(b, a) * d3_degrees, Math.sqrt(a * a + b * b), l) : new d3_hcl(NaN, NaN, l); 21777 } 21778 function d3_lab_xyz(x) { 21779 return x > .206893034 ? x * x * x : (x - 4 / 29) / 7.787037; 21780 } 21781 function d3_xyz_lab(x) { 21782 return x > .008856 ? Math.pow(x, 1 / 3) : 7.787037 * x + 4 / 29; 21783 } 21784 function d3_xyz_rgb(r) { 21785 return Math.round(255 * (r <= .00304 ? 12.92 * r : 1.055 * Math.pow(r, 1 / 2.4) - .055)); 21786 } 21787 d3.rgb = d3_rgb; 21788 function d3_rgb(r, g, b) { 21789 return this instanceof d3_rgb ? void (this.r = ~~r, this.g = ~~g, this.b = ~~b) : arguments.length < 2 ? r instanceof d3_rgb ? new d3_rgb(r.r, r.g, r.b) : d3_rgb_parse("" + r, d3_rgb, d3_hsl_rgb) : new d3_rgb(r, g, b); 21790 } 21791 function d3_rgbNumber(value) { 21792 return new d3_rgb(value >> 16, value >> 8 & 255, value & 255); 21793 } 21794 function d3_rgbString(value) { 21795 return d3_rgbNumber(value) + ""; 21796 } 21797 var d3_rgbPrototype = d3_rgb.prototype = new d3_color(); 21798 d3_rgbPrototype.brighter = function(k) { 21799 k = Math.pow(.7, arguments.length ? k : 1); 21800 var r = this.r, g = this.g, b = this.b, i = 30; 21801 if (!r && !g && !b) return new d3_rgb(i, i, i); 21802 if (r && r < i) r = i; 21803 if (g && g < i) g = i; 21804 if (b && b < i) b = i; 21805 return new d3_rgb(Math.min(255, r / k), Math.min(255, g / k), Math.min(255, b / k)); 21806 }; 21807 d3_rgbPrototype.darker = function(k) { 21808 k = Math.pow(.7, arguments.length ? k : 1); 21809 return new d3_rgb(k * this.r, k * this.g, k * this.b); 21810 }; 21811 d3_rgbPrototype.hsl = function() { 21812 return d3_rgb_hsl(this.r, this.g, this.b); 21813 }; 21814 d3_rgbPrototype.toString = function() { 21815 return "#" + d3_rgb_hex(this.r) + d3_rgb_hex(this.g) + d3_rgb_hex(this.b); 21816 }; 21817 function d3_rgb_hex(v) { 21818 return v < 16 ? "0" + Math.max(0, v).toString(16) : Math.min(255, v).toString(16); 21819 } 21820 function d3_rgb_parse(format, rgb, hsl) { 21821 var r = 0, g = 0, b = 0, m1, m2, color; 21822 m1 = /([a-z]+)\((.*)\)/i.exec(format); 21823 if (m1) { 21824 m2 = m1[2].split(","); 21825 switch (m1[1]) { 21826 case "hsl": 21827 { 21828 return hsl(parseFloat(m2[0]), parseFloat(m2[1]) / 100, parseFloat(m2[2]) / 100); 21829 } 21830 21831 case "rgb": 21832 { 21833 return rgb(d3_rgb_parseNumber(m2[0]), d3_rgb_parseNumber(m2[1]), d3_rgb_parseNumber(m2[2])); 21834 } 21835 } 21836 } 21837 if (color = d3_rgb_names.get(format)) return rgb(color.r, color.g, color.b); 21838 if (format != null && format.charAt(0) === "#" && !isNaN(color = parseInt(format.slice(1), 16))) { 21839 if (format.length === 4) { 21840 r = (color & 3840) >> 4; 21841 r = r >> 4 | r; 21842 g = color & 240; 21843 g = g >> 4 | g; 21844 b = color & 15; 21845 b = b << 4 | b; 21846 } else if (format.length === 7) { 21847 r = (color & 16711680) >> 16; 21848 g = (color & 65280) >> 8; 21849 b = color & 255; 21850 } 21851 } 21852 return rgb(r, g, b); 21853 } 21854 function d3_rgb_hsl(r, g, b) { 21855 var min = Math.min(r /= 255, g /= 255, b /= 255), max = Math.max(r, g, b), d = max - min, h, s, l = (max + min) / 2; 21856 if (d) { 21857 s = l < .5 ? d / (max + min) : d / (2 - max - min); 21858 if (r == max) h = (g - b) / d + (g < b ? 6 : 0); else if (g == max) h = (b - r) / d + 2; else h = (r - g) / d + 4; 21859 h *= 60; 21860 } else { 21861 h = NaN; 21862 s = l > 0 && l < 1 ? 0 : h; 21863 } 21864 return new d3_hsl(h, s, l); 21865 } 21866 function d3_rgb_lab(r, g, b) { 21867 r = d3_rgb_xyz(r); 21868 g = d3_rgb_xyz(g); 21869 b = d3_rgb_xyz(b); 21870 var x = d3_xyz_lab((.4124564 * r + .3575761 * g + .1804375 * b) / d3_lab_X), y = d3_xyz_lab((.2126729 * r + .7151522 * g + .072175 * b) / d3_lab_Y), z = d3_xyz_lab((.0193339 * r + .119192 * g + .9503041 * b) / d3_lab_Z); 21871 return d3_lab(116 * y - 16, 500 * (x - y), 200 * (y - z)); 21872 } 21873 function d3_rgb_xyz(r) {
vendor: 5,418 bytes, lines 21874-22071
21874 return (r /= 255) <= .04045 ? r / 12.92 : Math.pow((r + .055) / 1.055, 2.4); 21875 } 21876 function d3_rgb_parseNumber(c) { 21877 var f = parseFloat(c); 21878 return c.charAt(c.length - 1) === "%" ? Math.round(f * 2.55) : f; 21879 } 21880 var d3_rgb_names = d3.map({ 21881 aliceblue: 15792383, 21882 antiquewhite: 16444375, 21883 aqua: 65535, 21884 aquamarine: 8388564, 21885 azure: 15794175, 21886 beige: 16119260, 21887 bisque: 16770244, 21888 black: 0, 21889 blanchedalmond: 16772045, 21890 blue: 255, 21891 blueviolet: 9055202, 21892 brown: 10824234, 21893 burlywood: 14596231, 21894 cadetblue: 6266528, 21895 chartreuse: 8388352, 21896 chocolate: 13789470, 21897 coral: 16744272, 21898 cornflowerblue: 6591981, 21899 cornsilk: 16775388, 21900 crimson: 14423100, 21901 cyan: 65535, 21902 darkblue: 139, 21903 darkcyan: 35723, 21904 darkgoldenrod: 12092939, 21905 darkgray: 11119017, 21906 darkgreen: 25600, 21907 darkgrey: 11119017, 21908 darkkhaki: 12433259, 21909 darkmagenta: 9109643, 21910 darkolivegreen: 5597999, 21911 darkorange: 16747520, 21912 darkorchid: 10040012, 21913 darkred: 9109504, 21914 darksalmon: 15308410, 21915 darkseagreen: 9419919, 21916 darkslateblue: 4734347, 21917 darkslategray: 3100495, 21918 darkslategrey: 3100495, 21919 darkturquoise: 52945, 21920 darkviolet: 9699539, 21921 deeppink: 16716947, 21922 deepskyblue: 49151, 21923 dimgray: 6908265, 21924 dimgrey: 6908265, 21925 dodgerblue: 2003199, 21926 firebrick: 11674146, 21927 floralwhite: 16775920, 21928 forestgreen: 2263842, 21929 fuchsia: 16711935, 21930 gainsboro: 14474460, 21931 ghostwhite: 16316671, 21932 gold: 16766720, 21933 goldenrod: 14329120, 21934 gray: 8421504, 21935 green: 32768, 21936 greenyellow: 11403055, 21937 grey: 8421504, 21938 honeydew: 15794160, 21939 hotpink: 16738740, 21940 indianred: 13458524, 21941 indigo: 4915330, 21942 ivory: 16777200, 21943 khaki: 15787660, 21944 lavender: 15132410, 21945 lavenderblush: 16773365, 21946 lawngreen: 8190976, 21947 lemonchiffon: 16775885, 21948 lightblue: 11393254, 21949 lightcoral: 15761536, 21950 lightcyan: 14745599, 21951 lightgoldenrodyellow: 16448210, 21952 lightgray: 13882323, 21953 lightgreen: 9498256, 21954 lightgrey: 13882323, 21955 lightpink: 16758465, 21956 lightsalmon: 16752762, 21957 lightseagreen: 2142890, 21958 lightskyblue: 8900346, 21959 lightslategray: 7833753, 21960 lightslategrey: 7833753, 21961 lightsteelblue: 11584734, 21962 lightyellow: 16777184, 21963 lime: 65280, 21964 limegreen: 3329330, 21965 linen: 16445670, 21966 magenta: 16711935, 21967 maroon: 8388608, 21968 mediumaquamarine: 6737322, 21969 mediumblue: 205, 21970 mediumorchid: 12211667, 21971 mediumpurple: 9662683, 21972 mediumseagreen: 3978097, 21973 mediumslateblue: 8087790, 21974 mediumspringgreen: 64154, 21975 mediumturquoise: 4772300, 21976 mediumvioletred: 13047173, 21977 midnightblue: 1644912, 21978 mintcream: 16121850, 21979 mistyrose: 16770273, 21980 moccasin: 16770229, 21981 navajowhite: 16768685, 21982 navy: 128, 21983 oldlace: 16643558, 21984 olive: 8421376, 21985 olivedrab: 7048739, 21986 orange: 16753920, 21987 orangered: 16729344, 21988 orchid: 14315734, 21989 palegoldenrod: 15657130, 21990 palegreen: 10025880, 21991 paleturquoise: 11529966, 21992 palevioletred: 14381203, 21993 papayawhip: 16773077, 21994 peachpuff: 16767673, 21995 peru: 13468991, 21996 pink: 16761035, 21997 plum: 14524637, 21998 powderblue: 11591910, 21999 purple: 8388736, 22000 red: 16711680, 22001 rosybrown: 12357519, 22002 royalblue: 4286945, 22003 saddlebrown: 9127187, 22004 salmon: 16416882, 22005 sandybrown: 16032864, 22006 seagreen: 3050327, 22007 seashell: 16774638, 22008 sienna: 10506797, 22009 silver: 12632256, 22010 skyblue: 8900331, 22011 slateblue: 6970061, 22012 slategray: 7372944, 22013 slategrey: 7372944, 22014 snow: 16775930, 22015 springgreen: 65407, 22016 steelblue: 4620980, 22017 tan: 13808780, 22018 teal: 32896, 22019 thistle: 14204888, 22020 tomato: 16737095, 22021 turquoise: 4251856, 22022 violet: 15631086, 22023 wheat: 16113331, 22024 white: 16777215, 22025 whitesmoke: 16119285, 22026 yellow: 16776960, 22027 yellowgreen: 10145074 22028 }); 22029 d3_rgb_names.forEach(function(key, value) { 22030 d3_rgb_names.set(key, d3_rgbNumber(value)); 22031 }); 22032 function d3_functor(v) { 22033 return typeof v === "function" ? v : function() { 22034 return v; 22035 }; 22036 } 22037 d3.functor = d3_functor; 22038 function d3_identity(d) { 22039 return d; 22040 } 22041 d3.xhr = d3_xhrType(d3_identity); 22042 function d3_xhrType(response) { 22043 return function(url, mimeType, callback) { 22044 if (arguments.length === 2 && typeof mimeType === "function") callback = mimeType, 22045 mimeType = null; 22046 return d3_xhr(url, mimeType, response, callback); 22047 }; 22048 } 22049 function d3_xhr(url, mimeType, response, callback) { 22050 var xhr = {}, dispatch = d3.dispatch("beforesend", "progress", "load", "error"), headers = {}, request = new XMLHttpRequest(), responseType = null; 22051 if (d3_window.XDomainRequest && !("withCredentials" in request) && /^(http(s)?:)?\/\//.test(url)) request = new XDomainRequest(); 22052 "onload" in request ? request.onload = request.onerror = respond : request.onreadystatechange = function() { 22053 request.readyState > 3 && respond(); 22054 }; 22055 function respond() { 22056 var status = request.status, result; 22057 if (!status && d3_xhrHasResponse(request) || status >= 200 && status < 300 || status === 304) { 22058 try { 22059 result = response.call(xhr, request); 22060 } catch (e) { 22061 dispatch.error.call(xhr, e); 22062 return; 22063 } 22064 dispatch.load.call(xhr, result); 22065 } else { 22066 dispatch.error.call(xhr, request); 22067 } 22068 } 22069 request.onprogress = function(event) { 22070 var o = d3.event; 22071 d3.event = event;
vendor: 6,502 bytes, lines 22072-22258
22072 try { 22073 dispatch.progress.call(xhr, request); 22074 } finally { 22075 d3.event = o; 22076 } 22077 }; 22078 xhr.header = function(name, value) { 22079 name = (name + "").toLowerCase(); 22080 if (arguments.length < 2) return headers[name]; 22081 if (value == null) delete headers[name]; else headers[name] = value + ""; 22082 return xhr; 22083 }; 22084 xhr.mimeType = function(value) { 22085 if (!arguments.length) return mimeType; 22086 mimeType = value == null ? null : value + ""; 22087 return xhr; 22088 }; 22089 xhr.responseType = function(value) { 22090 if (!arguments.length) return responseType; 22091 responseType = value; 22092 return xhr; 22093 }; 22094 xhr.response = function(value) { 22095 response = value; 22096 return xhr; 22097 }; 22098 [ "get", "post" ].forEach(function(method) { 22099 xhr[method] = function() { 22100 return xhr.send.apply(xhr, [ method ].concat(d3_array(arguments))); 22101 }; 22102 }); 22103 xhr.send = function(method, data, callback) { 22104 if (arguments.length === 2 && typeof data === "function") callback = data, data = null; 22105 request.open(method, url, true); 22106 if (mimeType != null && !("accept" in headers)) headers["accept"] = mimeType + ",*/*"; 22107 if (request.setRequestHeader) for (var name in headers) request.setRequestHeader(name, headers[name]); 22108 if (mimeType != null && request.overrideMimeType) request.overrideMimeType(mimeType); 22109 if (responseType != null) request.responseType = responseType; 22110 if (callback != null) xhr.on("error", callback).on("load", function(request) { 22111 callback(null, request); 22112 }); 22113 dispatch.beforesend.call(xhr, request); 22114 request.send(data == null ? null : data); 22115 return xhr; 22116 }; 22117 xhr.abort = function() { 22118 request.abort(); 22119 return xhr; 22120 }; 22121 d3.rebind(xhr, dispatch, "on"); 22122 return callback == null ? xhr : xhr.get(d3_xhr_fixCallback(callback)); 22123 } 22124 function d3_xhr_fixCallback(callback) { 22125 return callback.length === 1 ? function(error, request) { 22126 callback(error == null ? request : null); 22127 } : callback; 22128 } 22129 function d3_xhrHasResponse(request) { 22130 var type = request.responseType; 22131 return type && type !== "text" ? request.response : request.responseText; 22132 } 22133 d3.dsv = function(delimiter, mimeType) { 22134 var reFormat = new RegExp('["' + delimiter + "\n]"), delimiterCode = delimiter.charCodeAt(0); 22135 function dsv(url, row, callback) { 22136 if (arguments.length < 3) callback = row, row = null; 22137 var xhr = d3_xhr(url, mimeType, row == null ? response : typedResponse(row), callback); 22138 xhr.row = function(_) { 22139 return arguments.length ? xhr.response((row = _) == null ? response : typedResponse(_)) : row; 22140 }; 22141 return xhr; 22142 } 22143 function response(request) { 22144 return dsv.parse(request.responseText); 22145 } 22146 function typedResponse(f) { 22147 return function(request) { 22148 return dsv.parse(request.responseText, f); 22149 }; 22150 } 22151 dsv.parse = function(text, f) { 22152 var o; 22153 return dsv.parseRows(text, function(row, i) { 22154 if (o) return o(row, i - 1); 22155 var a = new Function("d", "return {" + row.map(function(name, i) { 22156 return JSON.stringify(name) + ": d[" + i + "]"; 22157 }).join(",") + "}"); 22158 o = f ? function(row, i) { 22159 return f(a(row), i); 22160 } : a; 22161 }); 22162 }; 22163 dsv.parseRows = function(text, f) { 22164 var EOL = {}, EOF = {}, rows = [], N = text.length, I = 0, n = 0, t, eol; 22165 function token() { 22166 if (I >= N) return EOF; 22167 if (eol) return eol = false, EOL; 22168 var j = I; 22169 if (text.charCodeAt(j) === 34) { 22170 var i = j; 22171 while (i++ < N) { 22172 if (text.charCodeAt(i) === 34) { 22173 if (text.charCodeAt(i + 1) !== 34) break; 22174 ++i; 22175 } 22176 } 22177 I = i + 2; 22178 var c = text.charCodeAt(i + 1); 22179 if (c === 13) { 22180 eol = true; 22181 if (text.charCodeAt(i + 2) === 10) ++I; 22182 } else if (c === 10) { 22183 eol = true; 22184 } 22185 return text.slice(j + 1, i).replace(/""/g, '"'); 22186 } 22187 while (I < N) { 22188 var c = text.charCodeAt(I++), k = 1; 22189 if (c === 10) eol = true; else if (c === 13) { 22190 eol = true; 22191 if (text.charCodeAt(I) === 10) ++I, ++k; 22192 } else if (c !== delimiterCode) continue; 22193 return text.slice(j, I - k); 22194 } 22195 return text.slice(j); 22196 } 22197 while ((t = token()) !== EOF) { 22198 var a = []; 22199 while (t !== EOL && t !== EOF) { 22200 a.push(t); 22201 t = token(); 22202 } 22203 if (f && (a = f(a, n++)) == null) continue; 22204 rows.push(a); 22205 } 22206 return rows; 22207 }; 22208 dsv.format = function(rows) { 22209 if (Array.isArray(rows[0])) return dsv.formatRows(rows); 22210 var fieldSet = new d3_Set(), fields = []; 22211 rows.forEach(function(row) { 22212 for (var field in row) { 22213 if (!fieldSet.has(field)) { 22214 fields.push(fieldSet.add(field)); 22215 } 22216 } 22217 }); 22218 return [ fields.map(formatValue).join(delimiter) ].concat(rows.map(function(row) { 22219 return fields.map(function(field) { 22220 return formatValue(row[field]); 22221 }).join(delimiter); 22222 })).join("\n"); 22223 }; 22224 dsv.formatRows = function(rows) { 22225 return rows.map(formatRow).join("\n"); 22226 }; 22227 function formatRow(row) { 22228 return row.map(formatValue).join(delimiter); 22229 } 22230 function formatValue(text) { 22231 return reFormat.test(text) ? '"' + text.replace(/\"/g, '""') + '"' : text; 22232 } 22233 return dsv; 22234 }; 22235 d3.csv = d3.dsv(",", "text/csv"); 22236 d3.tsv = d3.dsv(" ", "text/tab-separated-values"); 22237 var d3_timer_queueHead, d3_timer_queueTail, d3_timer_interval, d3_timer_timeout, d3_timer_active, d3_timer_frame = d3_window[d3_vendorSymbol(d3_window, "requestAnimationFrame")] || function(callback) { 22238 setTimeout(callback, 17); 22239 }; 22240 d3.timer = function(callback, delay, then) { 22241 var n = arguments.length; 22242 if (n < 2) delay = 0; 22243 if (n < 3) then = Date.now(); 22244 var time = then + delay, timer = { 22245 c: callback, 22246 t: time, 22247 f: false, 22248 n: null 22249 }; 22250 if (d3_timer_queueTail) d3_timer_queueTail.n = timer; else d3_timer_queueHead = timer; 22251 d3_timer_queueTail = timer; 22252 if (!d3_timer_interval) { 22253 d3_timer_timeout = clearTimeout(d3_timer_timeout); 22254 d3_timer_interval = 1; 22255 d3_timer_frame(d3_timer_step); 22256 } 22257 }; 22258 function d3_timer_step() {
22259 var now = d3_timer_mark(), delay = d3_timer_sweep() - now; 22260 if (delay > 24) { 22261 if (isFinite(delay)) { 22262 clearTimeout(d3_timer_timeout); 22263 d3_timer_timeout = setTimeout(d3_timer_step, delay); 22264 } 22265 d3_timer_interval = 0; 22266 } else { 22267 d3_timer_interval = 1; 22268 d3_timer_frame(d3_timer_step); 22269 } 22270 } 22271 d3.timer.flush = function() { 22272 d3_timer_mark(); 22273 d3_timer_sweep(); 22274 }; 22275 function d3_timer_mark() { 22276 var now = Date.now(); 22277 d3_timer_active = d3_timer_queueHead; 22278 while (d3_timer_active) { 22279 if (now >= d3_timer_active.t) d3_timer_active.f = d3_timer_active.c(now - d3_timer_active.t); 22280 d3_timer_active = d3_timer_active.n; 22281 } 22282 return now; 22283 } 22284 function d3_timer_sweep() { 22285 var t0, t1 = d3_timer_queueHead, time = Infinity; 22286 while (t1) { 22287 if (t1.f) { 22288 t1 = t0 ? t0.n = t1.n : d3_timer_queueHead = t1.n; 22289 } else { 22290 if (t1.t < time) time = t1.t; 22291 t1 = (t0 = t1).n; 22292 } 22293 } 22294 d3_timer_queueTail = t0; 22295 return time; 22296 } 22297 function d3_format_precision(x, p) { 22298 return p - (x ? Math.ceil(Math.log(x) / Math.LN10) : 1); 22299 } 22300 d3.round = function(x, n) { 22301 return n ? Math.round(x * (n = Math.pow(10, n))) / n : Math.round(x); 22302 }; 22303 var d3_formatPrefixes = [ "y", "z", "a", "f", "p", "n", "µ", "m", "", "k", "M", "G", "T", "P", "E", "Z", "Y" ].map(d3_formatPrefix); 22304 d3.formatPrefix = function(value, precision) { 22305 var i = 0; 22306 if (value) { 22307 if (value < 0) value *= -1; 22308 if (precision) value = d3.round(value, d3_format_precision(value, precision)); 22309 i = 1 + Math.floor(1e-12 + Math.log(value) / Math.LN10); 22310 i = Math.max(-24, Math.min(24, Math.floor((i - 1) / 3) * 3)); 22311 } 22312 return d3_formatPrefixes[8 + i / 3]; 22313 }; 22314 function d3_formatPrefix(d, i) { 22315 var k = Math.pow(10, abs(8 - i) * 3); 22316 return { 22317 scale: i > 8 ? function(d) { 22318 return d / k; 22319 } : function(d) { 22320 return d * k; 22321 }, 22322 symbol: d 22323 }; 22324 } 22325 function d3_locale_numberFormat(locale) { 22326 var locale_decimal = locale.decimal, locale_thousands = locale.thousands, locale_grouping = locale.grouping, locale_currency = locale.currency, formatGroup = locale_grouping && locale_thousands ? function(value, width) { 22327 var i = value.length, t = [], j = 0, g = locale_grouping[0], length = 0; 22328 while (i > 0 && g > 0) { 22329 if (length + g + 1 > width) g = Math.max(1, width - length); 22330 t.push(value.substring(i -= g, i + g)); 22331 if ((length += g + 1) > width) break; 22332 g = locale_grouping[j = (j + 1) % locale_grouping.length]; 22333 } 22334 return t.reverse().join(locale_thousands); 22335 } : d3_identity; 22336 return function(specifier) { 22337 var match = d3_format_re.exec(specifier), fill = match[1] || " ", align = match[2] || ">", sign = match[3] || "-", symbol = match[4] || "", zfill = match[5], width = +match[6], comma = match[7], precision = match[8], type = match[9], scale = 1, prefix = "", suffix = "", integer = false, exponent = true; 22338 if (precision) precision = +precision.substring(1); 22339 if (zfill || fill === "0" && align === "=") { 22340 zfill = fill = "0"; 22341 align = "="; 22342 } 22343 switch (type) { 22344 case "n": 22345 comma = true; 22346 type = "g"; 22347 break; 22348 22349 case "%": 22350 scale = 100; 22351 suffix = "%"; 22352 type = "f"; 22353 break; 22354 22355 case "p": 22356 scale = 100; 22357 suffix = "%"; 22358 type = "r"; 22359 break; 22360 22361 case "b": 22362 case "o": 22363 case "x": 22364 case "X": 22365 if (symbol === "#") prefix = "0" + type.toLowerCase(); 22366 22367 case "c": 22368 exponent = false; 22369 22370 case "d": 22371 integer = true; 22372 precision = 0; 22373 break; 22374 22375 case "s": 22376 scale = -1; 22377 type = "r"; 22378 break; 22379 } 22380 if (symbol === "$") prefix = locale_currency[0], suffix = locale_currency[1]; 22381 if (type == "r" && !precision) type = "g"; 22382 if (precision != null) { 22383 if (type == "g") precision = Math.max(1, Math.min(21, precision)); else if (type == "e" || type == "f") precision = Math.max(0, Math.min(20, precision)); 22384 } 22385 type = d3_format_types.get(type) || d3_format_typeDefault; 22386 var zcomma = zfill && comma; 22387 return function(value) { 22388 var fullSuffix = suffix; 22389 if (integer && value % 1) return ""; 22390 var negative = value < 0 || value === 0 && 1 / value < 0 ? (value = -value, "-") : sign === "-" ? "" : sign; 22391 if (scale < 0) { 22392 var unit = d3.formatPrefix(value, precision); 22393 value = unit.scale(value); 22394 fullSuffix = unit.symbol + suffix; 22395 } else { 22396 value *= scale; 22397 } 22398 value = type(value, precision); 22399 var i = value.lastIndexOf("."), before, after; 22400 if (i < 0) {
22401 var j = exponent ? value.lastIndexOf("e") : -1; 22402 if (j < 0) before = value, after = ""; else before = value.substring(0, j), after = value.substring(j); 22403 } else { 22404 before = value.substring(0, i); 22405 after = locale_decimal + value.substring(i + 1); 22406 } 22407 if (!zfill && comma) before = formatGroup(before, Infinity); 22408 var length = prefix.length + before.length + after.length + (zcomma ? 0 : negative.length), padding = length < width ? new Array(length = width - length + 1).join(fill) : ""; 22409 if (zcomma) before = formatGroup(padding + before, padding.length ? width - after.length : Infinity); 22410 negative += prefix; 22411 value = before + after; 22412 return (align === "<" ? negative + value + padding : align === ">" ? padding + negative + value : align === "^" ? padding.substring(0, length >>= 1) + negative + value + padding.substring(length) : negative + (zcomma ? value : padding + value)) + fullSuffix; 22413 }; 22414 }; 22415 } 22416 var d3_format_re = /(?:([^{])?([<>=^]))?([+\- ])?([$#])?(0)?(\d+)?(,)?(\.-?\d+)?([a-z%])?/i; 22417 var d3_format_types = d3.map({ 22418 b: function(x) { 22419 return x.toString(2); 22420 }, 22421 c: function(x) { 22422 return String.fromCharCode(x); 22423 }, 22424 o: function(x) { 22425 return x.toString(8); 22426 }, 22427 x: function(x) { 22428 return x.toString(16); 22429 }, 22430 X: function(x) { 22431 return x.toString(16).toUpperCase(); 22432 }, 22433 g: function(x, p) { 22434 return x.toPrecision(p); 22435 }, 22436 e: function(x, p) { 22437 return x.toExponential(p); 22438 }, 22439 f: function(x, p) { 22440 return x.toFixed(p); 22441 }, 22442 r: function(x, p) { 22443 return (x = d3.round(x, d3_format_precision(x, p))).toFixed(Math.max(0, Math.min(20, d3_format_precision(x * (1 + 1e-15), p)))); 22444 } 22445 }); 22446 function d3_format_typeDefault(x) { 22447 return x + ""; 22448 } 22449 var d3_time = d3.time = {}, d3_date = Date; 22450 function d3_date_utc() { 22451 this._ = new Date(arguments.length > 1 ? Date.UTC.apply(this, arguments) : arguments[0]); 22452 } 22453 d3_date_utc.prototype = { 22454 getDate: function() { 22455 return this._.getUTCDate(); 22456 }, 22457 getDay: function() { 22458 return this._.getUTCDay(); 22459 }, 22460 getFullYear: function() { 22461 return this._.getUTCFullYear(); 22462 }, 22463 getHours: function() { 22464 return this._.getUTCHours(); 22465 }, 22466 getMilliseconds: function() { 22467 return this._.getUTCMilliseconds(); 22468 }, 22469 getMinutes: function() { 22470 return this._.getUTCMinutes(); 22471 }, 22472 getMonth: function() { 22473 return this._.getUTCMonth(); 22474 }, 22475 getSeconds: function() { 22476 return this._.getUTCSeconds(); 22477 }, 22478 getTime: function() { 22479 return this._.getTime(); 22480 }, 22481 getTimezoneOffset: function() { 22482 return 0; 22483 }, 22484 valueOf: function() { 22485 return this._.valueOf(); 22486 }, 22487 setDate: function() { 22488 d3_time_prototype.setUTCDate.apply(this._, arguments); 22489 }, 22490 setDay: function() { 22491 d3_time_prototype.setUTCDay.apply(this._, arguments); 22492 }, 22493 setFullYear: function() { 22494 d3_time_prototype.setUTCFullYear.apply(this._, arguments); 22495 }, 22496 setHours: function() { 22497 d3_time_prototype.setUTCHours.apply(this._, arguments); 22498 }, 22499 setMilliseconds: function() { 22500 d3_time_prototype.setUTCMilliseconds.apply(this._, arguments); 22501 }, 22502 setMinutes: function() { 22503 d3_time_prototype.setUTCMinutes.apply(this._, arguments); 22504 }, 22505 setMonth: function() { 22506 d3_time_prototype.setUTCMonth.apply(this._, arguments); 22507 }, 22508 setSeconds: function() { 22509 d3_time_prototype.setUTCSeconds.apply(this._, arguments); 22510 }, 22511 setTime: function() { 22512 d3_time_prototype.setTime.apply(this._, arguments); 22513 } 22514 }; 22515 var d3_time_prototype = Date.prototype; 22516 function d3_time_interval(local, step, number) { 22517 function round(date) { 22518 var d0 = local(date), d1 = offset(d0, 1); 22519 return date - d0 < d1 - date ? d0 : d1; 22520 } 22521 function ceil(date) { 22522 step(date = local(new d3_date(date - 1)), 1); 22523 return date; 22524 } 22525 function offset(date, k) { 22526 step(date = new d3_date(+date), k); 22527 return date; 22528 } 22529 function range(t0, t1, dt) { 22530 var time = ceil(t0), times = []; 22531 if (dt > 1) { 22532 while (time < t1) { 22533 if (!(number(time) % dt)) times.push(new Date(+time)); 22534 step(time, 1); 22535 } 22536 } else { 22537 while (time < t1) times.push(new Date(+time)), step(time, 1); 22538 } 22539 return times; 22540 } 22541 function range_utc(t0, t1, dt) {
22542 try { 22543 d3_date = d3_date_utc; 22544 var utc = new d3_date_utc(); 22545 utc._ = t0; 22546 return range(utc, t1, dt); 22547 } finally { 22548 d3_date = Date; 22549 } 22550 } 22551 local.floor = local; 22552 local.round = round; 22553 local.ceil = ceil; 22554 local.offset = offset; 22555 local.range = range; 22556 var utc = local.utc = d3_time_interval_utc(local); 22557 utc.floor = utc; 22558 utc.round = d3_time_interval_utc(round); 22559 utc.ceil = d3_time_interval_utc(ceil); 22560 utc.offset = d3_time_interval_utc(offset); 22561 utc.range = range_utc; 22562 return local; 22563 } 22564 function d3_time_interval_utc(method) { 22565 return function(date, k) { 22566 try { 22567 d3_date = d3_date_utc; 22568 var utc = new d3_date_utc(); 22569 utc._ = date; 22570 return method(utc, k)._; 22571 } finally { 22572 d3_date = Date; 22573 } 22574 }; 22575 } 22576 d3_time.year = d3_time_interval(function(date) { 22577 date = d3_time.day(date); 22578 date.setMonth(0, 1); 22579 return date; 22580 }, function(date, offset) { 22581 date.setFullYear(date.getFullYear() + offset); 22582 }, function(date) { 22583 return date.getFullYear(); 22584 }); 22585 d3_time.years = d3_time.year.range; 22586 d3_time.years.utc = d3_time.year.utc.range; 22587 d3_time.day = d3_time_interval(function(date) { 22588 var day = new d3_date(2e3, 0); 22589 day.setFullYear(date.getFullYear(), date.getMonth(), date.getDate()); 22590 return day; 22591 }, function(date, offset) { 22592 date.setDate(date.getDate() + offset); 22593 }, function(date) { 22594 return date.getDate() - 1; 22595 }); 22596 d3_time.days = d3_time.day.range; 22597 d3_time.days.utc = d3_time.day.utc.range; 22598 d3_time.dayOfYear = function(date) { 22599 var year = d3_time.year(date); 22600 return Math.floor((date - year - (date.getTimezoneOffset() - year.getTimezoneOffset()) * 6e4) / 864e5); 22601 }; 22602 [ "sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday" ].forEach(function(day, i) { 22603 i = 7 - i; 22604 var interval = d3_time[day] = d3_time_interval(function(date) { 22605 (date = d3_time.day(date)).setDate(date.getDate() - (date.getDay() + i) % 7); 22606 return date; 22607 }, function(date, offset) { 22608 date.setDate(date.getDate() + Math.floor(offset) * 7); 22609 }, function(date) { 22610 var day = d3_time.year(date).getDay(); 22611 return Math.floor((d3_time.dayOfYear(date) + (day + i) % 7) / 7) - (day !== i); 22612 }); 22613 d3_time[day + "s"] = interval.range; 22614 d3_time[day + "s"].utc = interval.utc.range; 22615 d3_time[day + "OfYear"] = function(date) { 22616 var day = d3_time.year(date).getDay(); 22617 return Math.floor((d3_time.dayOfYear(date) + (day + i) % 7) / 7); 22618 }; 22619 }); 22620 d3_time.week = d3_time.sunday; 22621 d3_time.weeks = d3_time.sunday.range; 22622 d3_time.weeks.utc = d3_time.sunday.utc.range; 22623 d3_time.weekOfYear = d3_time.sundayOfYear; 22624 function d3_locale_timeFormat(locale) { 22625 var locale_dateTime = locale.dateTime, locale_date = locale.date, locale_time = locale.time, locale_periods = locale.periods, locale_days = locale.days, locale_shortDays = locale.shortDays, locale_months = locale.months, locale_shortMonths = locale.shortMonths; 22626 function d3_time_format(template) { 22627 var n = template.length; 22628 function format(date) { 22629 var string = [], i = -1, j = 0, c, p, f; 22630 while (++i < n) { 22631 if (template.charCodeAt(i) === 37) { 22632 string.push(template.slice(j, i)); 22633 if ((p = d3_time_formatPads[c = template.charAt(++i)]) != null) c = template.charAt(++i); 22634 if (f = d3_time_formats[c]) c = f(date, p == null ? c === "e" ? " " : "0" : p); 22635 string.push(c); 22636 j = i + 1; 22637 } 22638 } 22639 string.push(template.slice(j, i)); 22640 return string.join(""); 22641 } 22642 format.parse = function(string) { 22643 var d = { 22644 y: 1900, 22645 m: 0, 22646 d: 1, 22647 H: 0, 22648 M: 0, 22649 S: 0, 22650 L: 0, 22651 Z: null 22652 }, i = d3_time_parse(d, template, string, 0); 22653 if (i != string.length) return null; 22654 if ("p" in d) d.H = d.H % 12 + d.p * 12; 22655 var localZ = d.Z != null && d3_date !== d3_date_utc, date = new (localZ ? d3_date_utc : d3_date)(); 22656 if ("j" in d) date.setFullYear(d.y, 0, d.j); else if ("w" in d && ("W" in d || "U" in d)) { 22657 date.setFullYear(d.y, 0, 1); 22658 date.setFullYear(d.y, 0, "W" in d ? (d.w + 6) % 7 + d.W * 7 - (date.getDay() + 5) % 7 : d.w + d.U * 7 - (date.getDay() + 6) % 7); 22659 } else date.setFullYear(d.y, d.m, d.d); 22660 date.setHours(d.H + (d.Z / 100 | 0), d.M + d.Z % 100, d.S, d.L); 22661 return localZ ? date._ : date; 22662 }; 22663 format.toString = function() { 22664 return template; 22665 }; 22666 return format; 22667 } 22668 function d3_time_parse(date, template, string, j) { 22669 var c, p, t, i = 0, n = template.length, m = string.length; 22670 while (i < n) { 22671 if (j >= m) return -1; 22672 c = template.charCodeAt(i++); 22673 if (c === 37) { 22674 t = template.charAt(i++); 22675 p = d3_time_parsers[t in d3_time_formatPads ? template.charAt(i++) : t]; 22676 if (!p || (j = p(date, string, j)) < 0) return -1; 22677 } else if (c != string.charCodeAt(j++)) { 22678 return -1; 22679 } 22680 } 22681 return j; 22682 } 22683 d3_time_format.utc = function(template) { 22684 var local = d3_time_format(template); 22685 function format(date) { 22686 try { 22687 d3_date = d3_date_utc; 22688 var utc = new d3_date(); 22689 utc._ = date; 22690 return local(utc); 22691 } finally { 22692 d3_date = Date; 22693 } 22694 } 22695 format.parse = function(string) { 22696 try { 22697 d3_date = d3_date_utc; 22698 var date = local.parse(string); 22699 return date && date._; 22700 } finally { 22701 d3_date = Date; 22702 } 22703 }; 22704 format.toString = local.toString; 22705 return format; 22706 }; 22707 d3_time_format.multi = d3_time_format.utc.multi = d3_time_formatMulti; 22708 var d3_time_periodLookup = d3.map(), d3_time_dayRe = d3_time_formatRe(locale_days), d3_time_dayLookup = d3_time_formatLookup(locale_days), d3_time_dayAbbrevRe = d3_time_formatRe(locale_shortDays), d3_time_dayAbbrevLookup = d3_time_formatLookup(locale_shortDays), d3_time_monthRe = d3_time_formatRe(locale_months), d3_time_monthLookup = d3_time_formatLookup(locale_months), d3_time_monthAbbrevRe = d3_time_formatRe(locale_shortMonths), d3_time_monthAbbrevLookup = d3_time_formatLookup(locale_shortMonths); 22709 locale_periods.forEach(function(p, i) { 22710 d3_time_periodLookup.set(p.toLowerCase(), i); 22711 }); 22712 var d3_time_formats = { 22713 a: function(d) { 22714 return locale_shortDays[d.getDay()]; 22715 }, 22716 A: function(d) { 22717 return locale_days[d.getDay()]; 22718 }, 22719 b: function(d) { 22720 return locale_shortMonths[d.getMonth()]; 22721 }, 22722 B: function(d) { 22723 return locale_months[d.getMonth()]; 22724 }, 22725 c: d3_time_format(locale_dateTime), 22726 d: function(d, p) { 22727 return d3_time_formatPad(d.getDate(), p, 2); 22728 }, 22729 e: function(d, p) { 22730 return d3_time_formatPad(d.getDate(), p, 2); 22731 }, 22732 H: function(d, p) { 22733 return d3_time_formatPad(d.getHours(), p, 2); 22734 }, 22735 I: function(d, p) { 22736 return d3_time_formatPad(d.getHours() % 12 || 12, p, 2); 22737 }, 22738 j: function(d, p) { 22739 return d3_time_formatPad(1 + d3_time.dayOfYear(d), p, 3); 22740 }, 22741 L: function(d, p) { 22742 return d3_time_formatPad(d.getMilliseconds(), p, 3); 22743 }, 22744 m: function(d, p) { 22745 return d3_time_formatPad(d.getMonth() + 1, p, 2); 22746 }, 22747 M: function(d, p) { 22748 return d3_time_formatPad(d.getMinutes(), p, 2); 22749 }, 22750 p: function(d) { 22751 return locale_periods[+(d.getHours() >= 12)]; 22752 }, 22753 S: function(d, p) { 22754 return d3_time_formatPad(d.getSeconds(), p, 2); 22755 }, 22756 U: function(d, p) { 22757 return d3_time_formatPad(d3_time.sundayOfYear(d), p, 2); 22758 }, 22759 w: function(d) { 22760 return d.getDay(); 22761 }, 22762 W: function(d, p) { 22763 return d3_time_formatPad(d3_time.mondayOfYear(d), p, 2); 22764 }, 22765 x: d3_time_format(locale_date), 22766 X: d3_time_format(locale_time), 22767 y: function(d, p) { 22768 return d3_time_formatPad(d.getFullYear() % 100, p, 2); 22769 }, 22770 Y: function(d, p) { 22771 return d3_time_formatPad(d.getFullYear() % 1e4, p, 4); 22772 }, 22773 Z: d3_time_zone, 22774 "%": function() { 22775 return "%"; 22776 } 22777 }; 22778 var d3_time_parsers = { 22779 a: d3_time_parseWeekdayAbbrev, 22780 A: d3_time_parseWeekday, 22781 b: d3_time_parseMonthAbbrev, 22782 B: d3_time_parseMonth, 22783 c: d3_time_parseLocaleFull, 22784 d: d3_time_parseDay, 22785 e: d3_time_parseDay, 22786 H: d3_time_parseHour24, 22787 I: d3_time_parseHour24, 22788 j: d3_time_parseDayOfYear, 22789 L: d3_time_parseMilliseconds, 22790 m: d3_time_parseMonthNumber, 22791 M: d3_time_parseMinutes, 22792 p: d3_time_parseAmPm, 22793 S: d3_time_parseSeconds, 22794 U: d3_time_parseWeekNumberSunday, 22795 w: d3_time_parseWeekdayNumber, 22796 W: d3_time_parseWeekNumberMonday, 22797 x: d3_time_parseLocaleDate, 22798 X: d3_time_parseLocaleTime, 22799 y: d3_time_parseYear, 22800 Y: d3_time_parseFullYear, 22801 Z: d3_time_parseZone, 22802 "%": d3_time_parseLiteralPercent 22803 }; 22804 function d3_time_parseWeekdayAbbrev(date, string, i) { 22805 d3_time_dayAbbrevRe.lastIndex = 0; 22806 var n = d3_time_dayAbbrevRe.exec(string.slice(i)); 22807 return n ? (date.w = d3_time_dayAbbrevLookup.get(n[0].toLowerCase()), i + n[0].length) : -1; 22808 } 22809 function d3_time_parseWeekday(date, string, i) { 22810 d3_time_dayRe.lastIndex = 0; 22811 var n = d3_time_dayRe.exec(string.slice(i)); 22812 return n ? (date.w = d3_time_dayLookup.get(n[0].toLowerCase()), i + n[0].length) : -1; 22813 } 22814 function d3_time_parseMonthAbbrev(date, string, i) { 22815 d3_time_monthAbbrevRe.lastIndex = 0; 22816 var n = d3_time_monthAbbrevRe.exec(string.slice(i)); 22817 return n ? (date.m = d3_time_monthAbbrevLookup.get(n[0].toLowerCase()), i + n[0].length) : -1; 22818 } 22819 function d3_time_parseMonth(date, string, i) { 22820 d3_time_monthRe.lastIndex = 0; 22821 var n = d3_time_monthRe.exec(string.slice(i)); 22822 return n ? (date.m = d3_time_monthLookup.get(n[0].toLowerCase()), i + n[0].length) : -1; 22823 } 22824 function d3_time_parseLocaleFull(date, string, i) { 22825 return d3_time_parse(date, d3_time_formats.c.toString(), string, i); 22826 } 22827 function d3_time_parseLocaleDate(date, string, i) { 22828 return d3_time_parse(date, d3_time_formats.x.toString(), string, i); 22829 } 22830 function d3_time_parseLocaleTime(date, string, i) { 22831 return d3_time_parse(date, d3_time_formats.X.toString(), string, i); 22832 } 22833 function d3_time_parseAmPm(date, string, i) { 22834 var n = d3_time_periodLookup.get(string.slice(i, i += 2).toLowerCase()); 22835 return n == null ? -1 : (date.p = n, i); 22836 } 22837 return d3_time_format; 22838 } 22839 var d3_time_formatPads = { 22840 "-": "", 22841 _: " ", 22842 "0": "0" 22843 }, d3_time_numberRe = /^\s*\d+/, d3_time_percentRe = /^%/; 22844 function d3_time_formatPad(value, fill, width) { 22845 var sign = value < 0 ? "-" : "", string = (sign ? -value : value) + "", length = string.length; 22846 return sign + (length < width ? new Array(width - length + 1).join(fill) + string : string); 22847 } 22848 function d3_time_formatRe(names) { 22849 return new RegExp("^(?:" + names.map(d3.requote).join("|") + ")", "i"); 22850 } 22851 function d3_time_formatLookup(names) { 22852 var map = new d3_Map(), i = -1, n = names.length; 22853 while (++i < n) map.set(names[i].toLowerCase(), i); 22854 return map; 22855 } 22856 function d3_time_parseWeekdayNumber(date, string, i) { 22857 d3_time_numberRe.lastIndex = 0; 22858 var n = d3_time_numberRe.exec(string.slice(i, i + 1)); 22859 return n ? (date.w = +n[0], i + n[0].length) : -1; 22860 } 22861 function d3_time_parseWeekNumberSunday(date, string, i) { 22862 d3_time_numberRe.lastIndex = 0; 22863 var n = d3_time_numberRe.exec(string.slice(i)); 22864 return n ? (date.U = +n[0], i + n[0].length) : -1; 22865 } 22866 function d3_time_parseWeekNumberMonday(date, string, i) { 22867 d3_time_numberRe.lastIndex = 0; 22868 var n = d3_time_numberRe.exec(string.slice(i)); 22869 return n ? (date.W = +n[0], i + n[0].length) : -1; 22870 } 22871 function d3_time_parseFullYear(date, string, i) { 22872 d3_time_numberRe.lastIndex = 0; 22873 var n = d3_time_numberRe.exec(string.slice(i, i + 4)); 22874 return n ? (date.y = +n[0], i + n[0].length) : -1; 22875 } 22876 function d3_time_parseYear(date, string, i) { 22877 d3_time_numberRe.lastIndex = 0; 22878 var n = d3_time_numberRe.exec(string.slice(i, i + 2)); 22879 return n ? (date.y = d3_time_expandYear(+n[0]), i + n[0].length) : -1; 22880 } 22881 function d3_time_parseZone(date, string, i) { 22882 return /^[+-]\d{4}$/.test(string = string.slice(i, i + 5)) ? (date.Z = -string, 22883 i + 5) : -1; 22884 } 22885 function d3_time_expandYear(d) { 22886 return d + (d > 68 ? 1900 : 2e3); 22887 } 22888 function d3_time_parseMonthNumber(date, string, i) { 22889 d3_time_numberRe.lastIndex = 0; 22890 var n = d3_time_numberRe.exec(string.slice(i, i + 2)); 22891 return n ? (date.m = n[0] - 1, i + n[0].length) : -1; 22892 } 22893 function d3_time_parseDay(date, string, i) { 22894 d3_time_numberRe.lastIndex = 0; 22895 var n = d3_time_numberRe.exec(string.slice(i, i + 2)); 22896 return n ? (date.d = +n[0], i + n[0].length) : -1; 22897 } 22898 function d3_time_parseDayOfYear(date, string, i) { 22899 d3_time_numberRe.lastIndex = 0; 22900 var n = d3_time_numberRe.exec(string.slice(i, i + 3)); 22901 return n ? (date.j = +n[0], i + n[0].length) : -1; 22902 } 22903 function d3_time_parseHour24(date, string, i) { 22904 d3_time_numberRe.lastIndex = 0; 22905 var n = d3_time_numberRe.exec(string.slice(i, i + 2)); 22906 return n ? (date.H = +n[0], i + n[0].length) : -1; 22907 } 22908 function d3_time_parseMinutes(date, string, i) { 22909 d3_time_numberRe.lastIndex = 0; 22910 var n = d3_time_numberRe.exec(string.slice(i, i + 2)); 22911 return n ? (date.M = +n[0], i + n[0].length) : -1; 22912 } 22913 function d3_time_parseSeconds(date, string, i) { 22914 d3_time_numberRe.lastIndex = 0; 22915 var n = d3_time_numberRe.exec(string.slice(i, i + 2)); 22916 return n ? (date.S = +n[0], i + n[0].length) : -1; 22917 } 22918 function d3_time_parseMilliseconds(date, string, i) { 22919 d3_time_numberRe.lastIndex = 0; 22920 var n = d3_time_numberRe.exec(string.slice(i, i + 3)); 22921 return n ? (date.L = +n[0], i + n[0].length) : -1; 22922 } 22923 function d3_time_zone(d) { 22924 var z = d.getTimezoneOffset(), zs = z > 0 ? "-" : "+", zh = abs(z) / 60 | 0, zm = abs(z) % 60; 22925 return zs + d3_time_formatPad(zh, "0", 2) + d3_time_formatPad(zm, "0", 2); 22926 } 22927 function d3_time_parseLiteralPercent(date, string, i) { 22928 d3_time_percentRe.lastIndex = 0; 22929 var n = d3_time_percentRe.exec(string.slice(i, i + 1)); 22930 return n ? i + n[0].length : -1; 22931 } 22932 function d3_time_formatMulti(formats) { 22933 var n = formats.length, i = -1; 22934 while (++i < n) formats[i][0] = this(formats[i][0]); 22935 return function(date) { 22936 var i = 0, f = formats[i]; 22937 while (!f[1](date)) f = formats[++i]; 22938 return f[0](date); 22939 }; 22940 } 22941 d3.locale = function(locale) { 22942 return { 22943 numberFormat: d3_locale_numberFormat(locale), 22944 timeFormat: d3_locale_timeFormat(locale) 22945 }; 22946 };
22947 var d3_locale_enUS = d3.locale({ 22948 decimal: ".", 22949 thousands: ",", 22950 grouping: [ 3 ], 22951 currency: [ "$", "" ], 22952 dateTime: "%a %b %e %X %Y", 22953 date: "%m/%d/%Y", 22954 time: "%H:%M:%S", 22955 periods: [ "AM", "PM" ], 22956 days: [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ], 22957 shortDays: [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ], 22958 months: [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ], 22959 shortMonths: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ] 22960 }); 22961 d3.format = d3_locale_enUS.numberFormat; 22962 d3.geo = {}; 22963 function d3_adder() {} 22964 d3_adder.prototype = { 22965 s: 0, 22966 t: 0, 22967 add: function(y) { 22968 d3_adderSum(y, this.t, d3_adderTemp); 22969 d3_adderSum(d3_adderTemp.s, this.s, this); 22970 if (this.s) this.t += d3_adderTemp.t; else this.s = d3_adderTemp.t; 22971 }, 22972 reset: function() { 22973 this.s = this.t = 0; 22974 }, 22975 valueOf: function() { 22976 return this.s; 22977 } 22978 }; 22979 var d3_adderTemp = new d3_adder(); 22980 function d3_adderSum(a, b, o) { 22981 var x = o.s = a + b, bv = x - a, av = x - bv; 22982 o.t = a - av + (b - bv); 22983 } 22984 d3.geo.stream = function(object, listener) { 22985 if (object && d3_geo_streamObjectType.hasOwnProperty(object.type)) { 22986 d3_geo_streamObjectType[object.type](object, listener); 22987 } else { 22988 d3_geo_streamGeometry(object, listener); 22989 } 22990 }; 22991 function d3_geo_streamGeometry(geometry, listener) { 22992 if (geometry && d3_geo_streamGeometryType.hasOwnProperty(geometry.type)) { 22993 d3_geo_streamGeometryType[geometry.type](geometry, listener); 22994 } 22995 } 22996 var d3_geo_streamObjectType = { 22997 Feature: function(feature, listener) { 22998 d3_geo_streamGeometry(feature.geometry, listener); 22999 }, 23000 FeatureCollection: function(object, listener) { 23001 var features = object.features, i = -1, n = features.length; 23002 while (++i < n) d3_geo_streamGeometry(features[i].geometry, listener); 23003 } 23004 }; 23005 var d3_geo_streamGeometryType = { 23006 Sphere: function(object, listener) { 23007 listener.sphere(); 23008 }, 23009 Point: function(object, listener) { 23010 object = object.coordinates; 23011 listener.point(object[0], object[1], object[2]); 23012 }, 23013 MultiPoint: function(object, listener) { 23014 var coordinates = object.coordinates, i = -1, n = coordinates.length; 23015 while (++i < n) object = coordinates[i], listener.point(object[0], object[1], object[2]); 23016 }, 23017 LineString: function(object, listener) { 23018 d3_geo_streamLine(object.coordinates, listener, 0); 23019 }, 23020 MultiLineString: function(object, listener) { 23021 var coordinates = object.coordinates, i = -1, n = coordinates.length; 23022 while (++i < n) d3_geo_streamLine(coordinates[i], listener, 0); 23023 }, 23024 Polygon: function(object, listener) { 23025 d3_geo_streamPolygon(object.coordinates, listener); 23026 }, 23027 MultiPolygon: function(object, listener) { 23028 var coordinates = object.coordinates, i = -1, n = coordinates.length; 23029 while (++i < n) d3_geo_streamPolygon(coordinates[i], listener); 23030 }, 23031 GeometryCollection: function(object, listener) { 23032 var geometries = object.geometries, i = -1, n = geometries.length; 23033 while (++i < n) d3_geo_streamGeometry(geometries[i], listener); 23034 } 23035 }; 23036 function d3_geo_streamLine(coordinates, listener, closed) { 23037 var i = -1, n = coordinates.length - closed, coordinate; 23038 listener.lineStart(); 23039 while (++i < n) coordinate = coordinates[i], listener.point(coordinate[0], coordinate[1], coordinate[2]); 23040 listener.lineEnd(); 23041 } 23042 function d3_geo_streamPolygon(coordinates, listener) { 23043 var i = -1, n = coordinates.length; 23044 listener.polygonStart(); 23045 while (++i < n) d3_geo_streamLine(coordinates[i], listener, 1); 23046 listener.polygonEnd(); 23047 } 23048 d3.geo.area = function(object) { 23049 d3_geo_areaSum = 0; 23050 d3.geo.stream(object, d3_geo_area); 23051 return d3_geo_areaSum; 23052 }; 23053 var d3_geo_areaSum, d3_geo_areaRingSum = new d3_adder(); 23054 var d3_geo_area = { 23055 sphere: function() { 23056 d3_geo_areaSum += 4 * Ï; 23057 }, 23058 point: d3_noop, 23059 lineStart: d3_noop, 23060 lineEnd: d3_noop, 23061 polygonStart: function() { 23062 d3_geo_areaRingSum.reset(); 23063 d3_geo_area.lineStart = d3_geo_areaRingStart; 23064 }, 23065 polygonEnd: function() { 23066 var area = 2 * d3_geo_areaRingSum; 23067 d3_geo_areaSum += area < 0 ? 4 * Ï + area : area; 23068 d3_geo_area.lineStart = d3_geo_area.lineEnd = d3_geo_area.point = d3_noop; 23069 } 23070 }; 23071 function d3_geo_areaRingStart() { 23072 var λ00, Ï00, λ0, cosÏ0, sinÏ0; 23073 d3_geo_area.point = function(λ, Ï) { 23074 d3_geo_area.point = nextPoint; 23075 λ0 = (λ00 = λ) * d3_radians, cosÏ0 = Math.cos(Ï = (Ï00 = Ï) * d3_radians / 2 + Ï / 4),
vendor: 13,920 bytes, lines 23076-23446
23076 sinÏ0 = Math.sin(Ï); 23077 }; 23078 function nextPoint(λ, Ï) { 23079 λ *= d3_radians; 23080 Ï = Ï * d3_radians / 2 + Ï / 4; 23081 var dλ = λ - λ0, sdλ = dλ >= 0 ? 1 : -1, adλ = sdλ * dλ, cosÏ = Math.cos(Ï), sinÏ = Math.sin(Ï), k = sinÏ0 * sinÏ, u = cosÏ0 * cosÏ + k * Math.cos(adλ), v = k * sdλ * Math.sin(adλ); 23082 d3_geo_areaRingSum.add(Math.atan2(v, u)); 23083 λ0 = λ, cosÏ0 = cosÏ, sinÏ0 = sinÏ; 23084 } 23085 d3_geo_area.lineEnd = function() { 23086 nextPoint(λ00, Ï00); 23087 }; 23088 } 23089 function d3_geo_cartesian(spherical) { 23090 var λ = spherical[0], Ï = spherical[1], cosÏ = Math.cos(Ï); 23091 return [ cosÏ * Math.cos(λ), cosÏ * Math.sin(λ), Math.sin(Ï) ]; 23092 } 23093 function d3_geo_cartesianDot(a, b) { 23094 return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; 23095 } 23096 function d3_geo_cartesianCross(a, b) { 23097 return [ a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0] ]; 23098 } 23099 function d3_geo_cartesianAdd(a, b) { 23100 a[0] += b[0]; 23101 a[1] += b[1]; 23102 a[2] += b[2]; 23103 } 23104 function d3_geo_cartesianScale(vector, k) { 23105 return [ vector[0] * k, vector[1] * k, vector[2] * k ]; 23106 } 23107 function d3_geo_cartesianNormalize(d) { 23108 var l = Math.sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]); 23109 d[0] /= l; 23110 d[1] /= l; 23111 d[2] /= l; 23112 } 23113 function d3_geo_spherical(cartesian) { 23114 return [ Math.atan2(cartesian[1], cartesian[0]), d3_asin(cartesian[2]) ]; 23115 } 23116 function d3_geo_sphericalEqual(a, b) { 23117 return abs(a[0] - b[0]) < ε && abs(a[1] - b[1]) < ε; 23118 } 23119 d3.geo.bounds = function() { 23120 var λ0, Ï0, λ1, Ï1, λ_, λ__, Ï__, p0, dλSum, ranges, range; 23121 var bound = { 23122 point: point, 23123 lineStart: lineStart, 23124 lineEnd: lineEnd, 23125 polygonStart: function() { 23126 bound.point = ringPoint; 23127 bound.lineStart = ringStart; 23128 bound.lineEnd = ringEnd; 23129 dλSum = 0; 23130 d3_geo_area.polygonStart(); 23131 }, 23132 polygonEnd: function() { 23133 d3_geo_area.polygonEnd(); 23134 bound.point = point; 23135 bound.lineStart = lineStart; 23136 bound.lineEnd = lineEnd; 23137 if (d3_geo_areaRingSum < 0) λ0 = -(λ1 = 180), Ï0 = -(Ï1 = 90); else if (dλSum > ε) Ï1 = 90; else if (dλSum < -ε) Ï0 = -90; 23138 range[0] = λ0, range[1] = λ1; 23139 } 23140 }; 23141 function point(λ, Ï) { 23142 ranges.push(range = [ λ0 = λ, λ1 = λ ]); 23143 if (Ï < Ï0) Ï0 = Ï; 23144 if (Ï > Ï1) Ï1 = Ï; 23145 } 23146 function linePoint(λ, Ï) { 23147 var p = d3_geo_cartesian([ λ * d3_radians, Ï * d3_radians ]); 23148 if (p0) { 23149 var normal = d3_geo_cartesianCross(p0, p), equatorial = [ normal[1], -normal[0], 0 ], inflection = d3_geo_cartesianCross(equatorial, normal); 23150 d3_geo_cartesianNormalize(inflection); 23151 inflection = d3_geo_spherical(inflection); 23152 var dλ = λ - λ_, s = dλ > 0 ? 1 : -1, λi = inflection[0] * d3_degrees * s, antimeridian = abs(dλ) > 180; 23153 if (antimeridian ^ (s * λ_ < λi && λi < s * λ)) { 23154 var Ïi = inflection[1] * d3_degrees; 23155 if (Ïi > Ï1) Ï1 = Ïi; 23156 } else if (λi = (λi + 360) % 360 - 180, antimeridian ^ (s * λ_ < λi && λi < s * λ)) { 23157 var Ïi = -inflection[1] * d3_degrees; 23158 if (Ïi < Ï0) Ï0 = Ïi; 23159 } else { 23160 if (Ï < Ï0) Ï0 = Ï; 23161 if (Ï > Ï1) Ï1 = Ï; 23162 } 23163 if (antimeridian) { 23164 if (λ < λ_) { 23165 if (angle(λ0, λ) > angle(λ0, λ1)) λ1 = λ; 23166 } else { 23167 if (angle(λ, λ1) > angle(λ0, λ1)) λ0 = λ; 23168 } 23169 } else { 23170 if (λ1 >= λ0) { 23171 if (λ < λ0) λ0 = λ; 23172 if (λ > λ1) λ1 = λ; 23173 } else { 23174 if (λ > λ_) { 23175 if (angle(λ0, λ) > angle(λ0, λ1)) λ1 = λ; 23176 } else { 23177 if (angle(λ, λ1) > angle(λ0, λ1)) λ0 = λ; 23178 } 23179 } 23180 } 23181 } else { 23182 point(λ, Ï); 23183 } 23184 p0 = p, λ_ = λ; 23185 } 23186 function lineStart() { 23187 bound.point = linePoint; 23188 } 23189 function lineEnd() { 23190 range[0] = λ0, range[1] = λ1; 23191 bound.point = point; 23192 p0 = null; 23193 } 23194 function ringPoint(λ, Ï) { 23195 if (p0) { 23196 var dλ = λ - λ_; 23197 dλSum += abs(dλ) > 180 ? dλ + (dλ > 0 ? 360 : -360) : dλ; 23198 } else λ__ = λ, Ï__ = Ï; 23199 d3_geo_area.point(λ, Ï); 23200 linePoint(λ, Ï); 23201 } 23202 function ringStart() { 23203 d3_geo_area.lineStart(); 23204 } 23205 function ringEnd() { 23206 ringPoint(λ__, Ï__); 23207 d3_geo_area.lineEnd(); 23208 if (abs(dλSum) > ε) λ0 = -(λ1 = 180); 23209 range[0] = λ0, range[1] = λ1; 23210 p0 = null; 23211 } 23212 function angle(λ0, λ1) { 23213 return (λ1 -= λ0) < 0 ? λ1 + 360 : λ1; 23214 } 23215 function compareRanges(a, b) { 23216 return a[0] - b[0]; 23217 } 23218 function withinRange(x, range) { 23219 return range[0] <= range[1] ? range[0] <= x && x <= range[1] : x < range[0] || range[1] < x; 23220 } 23221 return function(feature) { 23222 Ï1 = λ1 = -(λ0 = Ï0 = Infinity); 23223 ranges = []; 23224 d3.geo.stream(feature, bound); 23225 var n = ranges.length; 23226 if (n) { 23227 ranges.sort(compareRanges); 23228 for (var i = 1, a = ranges[0], b, merged = [ a ]; i < n; ++i) { 23229 b = ranges[i]; 23230 if (withinRange(b[0], a) || withinRange(b[1], a)) { 23231 if (angle(a[0], b[1]) > angle(a[0], a[1])) a[1] = b[1]; 23232 if (angle(b[0], a[1]) > angle(a[0], a[1])) a[0] = b[0]; 23233 } else { 23234 merged.push(a = b); 23235 } 23236 } 23237 var best = -Infinity, dλ; 23238 for (var n = merged.length - 1, i = 0, a = merged[n], b; i <= n; a = b, ++i) { 23239 b = merged[i]; 23240 if ((dλ = angle(a[1], b[0])) > best) best = dλ, λ0 = b[0], λ1 = a[1]; 23241 } 23242 } 23243 ranges = range = null; 23244 return λ0 === Infinity || Ï0 === Infinity ? [ [ NaN, NaN ], [ NaN, NaN ] ] : [ [ λ0, Ï0 ], [ λ1, Ï1 ] ]; 23245 }; 23246 }(); 23247 d3.geo.centroid = function(object) { 23248 d3_geo_centroidW0 = d3_geo_centroidW1 = d3_geo_centroidX0 = d3_geo_centroidY0 = d3_geo_centroidZ0 = d3_geo_centroidX1 = d3_geo_centroidY1 = d3_geo_centroidZ1 = d3_geo_centroidX2 = d3_geo_centroidY2 = d3_geo_centroidZ2 = 0; 23249 d3.geo.stream(object, d3_geo_centroid); 23250 var x = d3_geo_centroidX2, y = d3_geo_centroidY2, z = d3_geo_centroidZ2, m = x * x + y * y + z * z; 23251 if (m < ε2) { 23252 x = d3_geo_centroidX1, y = d3_geo_centroidY1, z = d3_geo_centroidZ1; 23253 if (d3_geo_centroidW1 < ε) x = d3_geo_centroidX0, y = d3_geo_centroidY0, z = d3_geo_centroidZ0; 23254 m = x * x + y * y + z * z; 23255 if (m < ε2) return [ NaN, NaN ]; 23256 } 23257 return [ Math.atan2(y, x) * d3_degrees, d3_asin(z / Math.sqrt(m)) * d3_degrees ]; 23258 }; 23259 var d3_geo_centroidW0, d3_geo_centroidW1, d3_geo_centroidX0, d3_geo_centroidY0, d3_geo_centroidZ0, d3_geo_centroidX1, d3_geo_centroidY1, d3_geo_centroidZ1, d3_geo_centroidX2, d3_geo_centroidY2, d3_geo_centroidZ2; 23260 var d3_geo_centroid = { 23261 sphere: d3_noop, 23262 point: d3_geo_centroidPoint, 23263 lineStart: d3_geo_centroidLineStart, 23264 lineEnd: d3_geo_centroidLineEnd, 23265 polygonStart: function() { 23266 d3_geo_centroid.lineStart = d3_geo_centroidRingStart; 23267 }, 23268 polygonEnd: function() { 23269 d3_geo_centroid.lineStart = d3_geo_centroidLineStart; 23270 } 23271 }; 23272 function d3_geo_centroidPoint(λ, Ï) { 23273 λ *= d3_radians; 23274 var cosÏ = Math.cos(Ï *= d3_radians); 23275 d3_geo_centroidPointXYZ(cosÏ * Math.cos(λ), cosÏ * Math.sin(λ), Math.sin(Ï)); 23276 } 23277 function d3_geo_centroidPointXYZ(x, y, z) { 23278 ++d3_geo_centroidW0; 23279 d3_geo_centroidX0 += (x - d3_geo_centroidX0) / d3_geo_centroidW0; 23280 d3_geo_centroidY0 += (y - d3_geo_centroidY0) / d3_geo_centroidW0; 23281 d3_geo_centroidZ0 += (z - d3_geo_centroidZ0) / d3_geo_centroidW0; 23282 } 23283 function d3_geo_centroidLineStart() { 23284 var x0, y0, z0; 23285 d3_geo_centroid.point = function(λ, Ï) { 23286 λ *= d3_radians; 23287 var cosÏ = Math.cos(Ï *= d3_radians); 23288 x0 = cosÏ * Math.cos(λ); 23289 y0 = cosÏ * Math.sin(λ); 23290 z0 = Math.sin(Ï); 23291 d3_geo_centroid.point = nextPoint; 23292 d3_geo_centroidPointXYZ(x0, y0, z0); 23293 }; 23294 function nextPoint(λ, Ï) { 23295 λ *= d3_radians; 23296 var cosÏ = Math.cos(Ï *= d3_radians), x = cosÏ * Math.cos(λ), y = cosÏ * Math.sin(λ), z = Math.sin(Ï), w = Math.atan2(Math.sqrt((w = y0 * z - z0 * y) * w + (w = z0 * x - x0 * z) * w + (w = x0 * y - y0 * x) * w), x0 * x + y0 * y + z0 * z); 23297 d3_geo_centroidW1 += w; 23298 d3_geo_centroidX1 += w * (x0 + (x0 = x)); 23299 d3_geo_centroidY1 += w * (y0 + (y0 = y)); 23300 d3_geo_centroidZ1 += w * (z0 + (z0 = z)); 23301 d3_geo_centroidPointXYZ(x0, y0, z0); 23302 } 23303 } 23304 function d3_geo_centroidLineEnd() { 23305 d3_geo_centroid.point = d3_geo_centroidPoint; 23306 } 23307 function d3_geo_centroidRingStart() { 23308 var λ00, Ï00, x0, y0, z0; 23309 d3_geo_centroid.point = function(λ, Ï) { 23310 λ00 = λ, Ï00 = Ï; 23311 d3_geo_centroid.point = nextPoint; 23312 λ *= d3_radians; 23313 var cosÏ = Math.cos(Ï *= d3_radians); 23314 x0 = cosÏ * Math.cos(λ); 23315 y0 = cosÏ * Math.sin(λ); 23316 z0 = Math.sin(Ï); 23317 d3_geo_centroidPointXYZ(x0, y0, z0); 23318 }; 23319 d3_geo_centroid.lineEnd = function() { 23320 nextPoint(λ00, Ï00); 23321 d3_geo_centroid.lineEnd = d3_geo_centroidLineEnd; 23322 d3_geo_centroid.point = d3_geo_centroidPoint; 23323 }; 23324 function nextPoint(λ, Ï) { 23325 λ *= d3_radians; 23326 var cosÏ = Math.cos(Ï *= d3_radians), x = cosÏ * Math.cos(λ), y = cosÏ * Math.sin(λ), z = Math.sin(Ï), cx = y0 * z - z0 * y, cy = z0 * x - x0 * z, cz = x0 * y - y0 * x, m = Math.sqrt(cx * cx + cy * cy + cz * cz), u = x0 * x + y0 * y + z0 * z, v = m && -d3_acos(u) / m, w = Math.atan2(m, u); 23327 d3_geo_centroidX2 += v * cx; 23328 d3_geo_centroidY2 += v * cy; 23329 d3_geo_centroidZ2 += v * cz; 23330 d3_geo_centroidW1 += w; 23331 d3_geo_centroidX1 += w * (x0 + (x0 = x)); 23332 d3_geo_centroidY1 += w * (y0 + (y0 = y)); 23333 d3_geo_centroidZ1 += w * (z0 + (z0 = z)); 23334 d3_geo_centroidPointXYZ(x0, y0, z0); 23335 } 23336 } 23337 function d3_true() { 23338 return true; 23339 } 23340 function d3_geo_clipPolygon(segments, compare, clipStartInside, interpolate, listener) { 23341 var subject = [], clip = []; 23342 segments.forEach(function(segment) { 23343 if ((n = segment.length - 1) <= 0) return; 23344 var n, p0 = segment[0], p1 = segment[n]; 23345 if (d3_geo_sphericalEqual(p0, p1)) { 23346 listener.lineStart(); 23347 for (var i = 0; i < n; ++i) listener.point((p0 = segment[i])[0], p0[1]); 23348 listener.lineEnd(); 23349 return; 23350 } 23351 var a = new d3_geo_clipPolygonIntersection(p0, segment, null, true), b = new d3_geo_clipPolygonIntersection(p0, null, a, false); 23352 a.o = b; 23353 subject.push(a); 23354 clip.push(b); 23355 a = new d3_geo_clipPolygonIntersection(p1, segment, null, false); 23356 b = new d3_geo_clipPolygonIntersection(p1, null, a, true); 23357 a.o = b; 23358 subject.push(a); 23359 clip.push(b); 23360 }); 23361 clip.sort(compare); 23362 d3_geo_clipPolygonLinkCircular(subject); 23363 d3_geo_clipPolygonLinkCircular(clip); 23364 if (!subject.length) return; 23365 for (var i = 0, entry = clipStartInside, n = clip.length; i < n; ++i) { 23366 clip[i].e = entry = !entry; 23367 } 23368 var start = subject[0], points, point; 23369 while (1) { 23370 var current = start, isSubject = true; 23371 while (current.v) if ((current = current.n) === start) return; 23372 points = current.z; 23373 listener.lineStart(); 23374 do { 23375 current.v = current.o.v = true; 23376 if (current.e) { 23377 if (isSubject) { 23378 for (var i = 0, n = points.length; i < n; ++i) listener.point((point = points[i])[0], point[1]); 23379 } else { 23380 interpolate(current.x, current.n.x, 1, listener); 23381 } 23382 current = current.n; 23383 } else { 23384 if (isSubject) { 23385 points = current.p.z; 23386 for (var i = points.length - 1; i >= 0; --i) listener.point((point = points[i])[0], point[1]); 23387 } else { 23388 interpolate(current.x, current.p.x, -1, listener); 23389 } 23390 current = current.p; 23391 } 23392 current = current.o; 23393 points = current.z; 23394 isSubject = !isSubject; 23395 } while (!current.v); 23396 listener.lineEnd(); 23397 } 23398 } 23399 function d3_geo_clipPolygonLinkCircular(array) { 23400 if (!(n = array.length)) return; 23401 var n, i = 0, a = array[0], b; 23402 while (++i < n) { 23403 a.n = b = array[i]; 23404 b.p = a; 23405 a = b; 23406 } 23407 a.n = b = array[0]; 23408 b.p = a; 23409 } 23410 function d3_geo_clipPolygonIntersection(point, points, other, entry) { 23411 this.x = point; 23412 this.z = points; 23413 this.o = other; 23414 this.e = entry; 23415 this.v = false; 23416 this.n = this.p = null; 23417 } 23418 function d3_geo_clip(pointVisible, clipLine, interpolate, clipStart) { 23419 return function(rotate, listener) { 23420 var line = clipLine(listener), rotatedClipStart = rotate.invert(clipStart[0], clipStart[1]); 23421 var clip = { 23422 point: point, 23423 lineStart: lineStart, 23424 lineEnd: lineEnd, 23425 polygonStart: function() { 23426 clip.point = pointRing; 23427 clip.lineStart = ringStart; 23428 clip.lineEnd = ringEnd; 23429 segments = []; 23430 polygon = []; 23431 }, 23432 polygonEnd: function() { 23433 clip.point = point; 23434 clip.lineStart = lineStart; 23435 clip.lineEnd = lineEnd; 23436 segments = d3.merge(segments); 23437 var clipStartInside = d3_geo_pointInPolygon(rotatedClipStart, polygon); 23438 if (segments.length) { 23439 if (!polygonStarted) listener.polygonStart(), polygonStarted = true; 23440 d3_geo_clipPolygon(segments, d3_geo_clipSort, clipStartInside, interpolate, listener); 23441 } else if (clipStartInside) { 23442 if (!polygonStarted) listener.polygonStart(), polygonStarted = true; 23443 listener.lineStart(); 23444 interpolate(null, null, 1, listener); 23445 listener.lineEnd(); 23446 }
vendor: 5,682 bytes, lines 23447-23610
23447 if (polygonStarted) listener.polygonEnd(), polygonStarted = false; 23448 segments = polygon = null; 23449 }, 23450 sphere: function() { 23451 listener.polygonStart(); 23452 listener.lineStart(); 23453 interpolate(null, null, 1, listener); 23454 listener.lineEnd(); 23455 listener.polygonEnd(); 23456 } 23457 }; 23458 function point(λ, Ï) { 23459 var point = rotate(λ, Ï); 23460 if (pointVisible(λ = point[0], Ï = point[1])) listener.point(λ, Ï); 23461 } 23462 function pointLine(λ, Ï) { 23463 var point = rotate(λ, Ï); 23464 line.point(point[0], point[1]); 23465 } 23466 function lineStart() { 23467 clip.point = pointLine; 23468 line.lineStart(); 23469 } 23470 function lineEnd() { 23471 clip.point = point; 23472 line.lineEnd(); 23473 } 23474 var segments; 23475 var buffer = d3_geo_clipBufferListener(), ringListener = clipLine(buffer), polygonStarted = false, polygon, ring; 23476 function pointRing(λ, Ï) { 23477 ring.push([ λ, Ï ]); 23478 var point = rotate(λ, Ï); 23479 ringListener.point(point[0], point[1]); 23480 } 23481 function ringStart() { 23482 ringListener.lineStart(); 23483 ring = []; 23484 } 23485 function ringEnd() { 23486 pointRing(ring[0][0], ring[0][1]); 23487 ringListener.lineEnd(); 23488 var clean = ringListener.clean(), ringSegments = buffer.buffer(), segment, n = ringSegments.length; 23489 ring.pop(); 23490 polygon.push(ring); 23491 ring = null; 23492 if (!n) return; 23493 if (clean & 1) { 23494 segment = ringSegments[0]; 23495 var n = segment.length - 1, i = -1, point; 23496 if (n > 0) { 23497 if (!polygonStarted) listener.polygonStart(), polygonStarted = true; 23498 listener.lineStart(); 23499 while (++i < n) listener.point((point = segment[i])[0], point[1]); 23500 listener.lineEnd(); 23501 } 23502 return; 23503 } 23504 if (n > 1 && clean & 2) ringSegments.push(ringSegments.pop().concat(ringSegments.shift())); 23505 segments.push(ringSegments.filter(d3_geo_clipSegmentLength1)); 23506 } 23507 return clip; 23508 }; 23509 } 23510 function d3_geo_clipSegmentLength1(segment) { 23511 return segment.length > 1; 23512 } 23513 function d3_geo_clipBufferListener() { 23514 var lines = [], line; 23515 return { 23516 lineStart: function() { 23517 lines.push(line = []); 23518 }, 23519 point: function(λ, Ï) { 23520 line.push([ λ, Ï ]); 23521 }, 23522 lineEnd: d3_noop, 23523 buffer: function() { 23524 var buffer = lines; 23525 lines = []; 23526 line = null; 23527 return buffer; 23528 }, 23529 rejoin: function() { 23530 if (lines.length > 1) lines.push(lines.pop().concat(lines.shift())); 23531 } 23532 }; 23533 } 23534 function d3_geo_clipSort(a, b) { 23535 return ((a = a.x)[0] < 0 ? a[1] - halfÏ - ε : halfÏ - a[1]) - ((b = b.x)[0] < 0 ? b[1] - halfÏ - ε : halfÏ - b[1]); 23536 } 23537 var d3_geo_clipAntimeridian = d3_geo_clip(d3_true, d3_geo_clipAntimeridianLine, d3_geo_clipAntimeridianInterpolate, [ -Ï, -Ï / 2 ]); 23538 function d3_geo_clipAntimeridianLine(listener) { 23539 var λ0 = NaN, Ï0 = NaN, sλ0 = NaN, clean; 23540 return { 23541 lineStart: function() { 23542 listener.lineStart(); 23543 clean = 1; 23544 }, 23545 point: function(λ1, Ï1) { 23546 var sλ1 = λ1 > 0 ? Ï : -Ï, dλ = abs(λ1 - λ0); 23547 if (abs(dλ - Ï) < ε) { 23548 listener.point(λ0, Ï0 = (Ï0 + Ï1) / 2 > 0 ? halfÏ : -halfÏ); 23549 listener.point(sλ0, Ï0); 23550 listener.lineEnd(); 23551 listener.lineStart(); 23552 listener.point(sλ1, Ï0); 23553 listener.point(λ1, Ï0); 23554 clean = 0; 23555 } else if (sλ0 !== sλ1 && dλ >= Ï) { 23556 if (abs(λ0 - sλ0) < ε) λ0 -= sλ0 * ε; 23557 if (abs(λ1 - sλ1) < ε) λ1 -= sλ1 * ε; 23558 Ï0 = d3_geo_clipAntimeridianIntersect(λ0, Ï0, λ1, Ï1); 23559 listener.point(sλ0, Ï0); 23560 listener.lineEnd(); 23561 listener.lineStart(); 23562 listener.point(sλ1, Ï0); 23563 clean = 0; 23564 } 23565 listener.point(λ0 = λ1, Ï0 = Ï1); 23566 sλ0 = sλ1; 23567 }, 23568 lineEnd: function() { 23569 listener.lineEnd(); 23570 λ0 = Ï0 = NaN; 23571 }, 23572 clean: function() { 23573 return 2 - clean; 23574 } 23575 }; 23576 } 23577 function d3_geo_clipAntimeridianIntersect(λ0, Ï0, λ1, Ï1) { 23578 var cosÏ0, cosÏ1, sinλ0_λ1 = Math.sin(λ0 - λ1); 23579 return abs(sinλ0_λ1) > ε ? Math.atan((Math.sin(Ï0) * (cosÏ1 = Math.cos(Ï1)) * Math.sin(λ1) - Math.sin(Ï1) * (cosÏ0 = Math.cos(Ï0)) * Math.sin(λ0)) / (cosÏ0 * cosÏ1 * sinλ0_λ1)) : (Ï0 + Ï1) / 2; 23580 } 23581 function d3_geo_clipAntimeridianInterpolate(from, to, direction, listener) { 23582 var Ï; 23583 if (from == null) { 23584 Ï = direction * halfÏ; 23585 listener.point(-Ï, Ï); 23586 listener.point(0, Ï); 23587 listener.point(Ï, Ï); 23588 listener.point(Ï, 0); 23589 listener.point(Ï, -Ï); 23590 listener.point(0, -Ï); 23591 listener.point(-Ï, -Ï); 23592 listener.point(-Ï, 0); 23593 listener.point(-Ï, Ï); 23594 } else if (abs(from[0] - to[0]) > ε) { 23595 var s = from[0] < to[0] ? Ï : -Ï; 23596 Ï = direction * s / 2; 23597 listener.point(-s, Ï); 23598 listener.point(0, Ï); 23599 listener.point(s, Ï); 23600 } else { 23601 listener.point(to[0], to[1]); 23602 } 23603 } 23604 function d3_geo_pointInPolygon(point, polygon) { 23605 var meridian = point[0], parallel = point[1], meridianNormal = [ Math.sin(meridian), -Math.cos(meridian), 0 ], polarAngle = 0, winding = 0; 23606 d3_geo_areaRingSum.reset(); 23607 for (var i = 0, n = polygon.length; i < n; ++i) { 23608 var ring = polygon[i], m = ring.length; 23609 if (!m) continue; 23610 var point0 = ring[0], λ0 = point0[0], Ï0 = point0[1] / 2 + Ï / 4, sinÏ0
vendor: 6,958 bytes, lines 23610-23787
23610= Math.sin(Ï0), cosÏ0 = Math.cos(Ï0), j = 1; 23611 while (true) { 23612 if (j === m) j = 0; 23613 point = ring[j]; 23614 var λ = point[0], Ï = point[1] / 2 + Ï / 4, sinÏ = Math.sin(Ï), cosÏ = Math.cos(Ï), dλ = λ - λ0, sdλ = dλ >= 0 ? 1 : -1, adλ = sdλ * dλ, antimeridian = adλ > Ï, k = sinÏ0 * sinÏ; 23615 d3_geo_areaRingSum.add(Math.atan2(k * sdλ * Math.sin(adλ), cosÏ0 * cosÏ + k * Math.cos(adλ))); 23616 polarAngle += antimeridian ? dλ + sdλ * Ï : dλ; 23617 if (antimeridian ^ λ0 >= meridian ^ λ >= meridian) { 23618 var arc = d3_geo_cartesianCross(d3_geo_cartesian(point0), d3_geo_cartesian(point)); 23619 d3_geo_cartesianNormalize(arc); 23620 var intersection = d3_geo_cartesianCross(meridianNormal, arc); 23621 d3_geo_cartesianNormalize(intersection); 23622 var Ïarc = (antimeridian ^ dλ >= 0 ? -1 : 1) * d3_asin(intersection[2]); 23623 if (parallel > Ïarc || parallel === Ïarc && (arc[0] || arc[1])) { 23624 winding += antimeridian ^ dλ >= 0 ? 1 : -1; 23625 } 23626 } 23627 if (!j++) break; 23628 λ0 = λ, sinÏ0 = sinÏ, cosÏ0 = cosÏ, point0 = point; 23629 } 23630 } 23631 return (polarAngle < -ε || polarAngle < ε && d3_geo_areaRingSum < 0) ^ winding & 1; 23632 } 23633 function d3_geo_clipCircle(radius) { 23634 var cr = Math.cos(radius), smallRadius = cr > 0, notHemisphere = abs(cr) > ε, interpolate = d3_geo_circleInterpolate(radius, 6 * d3_radians); 23635 return d3_geo_clip(visible, clipLine, interpolate, smallRadius ? [ 0, -radius ] : [ -Ï, radius - Ï ]); 23636 function visible(λ, Ï) { 23637 return Math.cos(λ) * Math.cos(Ï) > cr; 23638 } 23639 function clipLine(listener) { 23640 var point0, c0, v0, v00, clean; 23641 return { 23642 lineStart: function() { 23643 v00 = v0 = false; 23644 clean = 1; 23645 }, 23646 point: function(λ, Ï) { 23647 var point1 = [ λ, Ï ], point2, v = visible(λ, Ï), c = smallRadius ? v ? 0 : code(λ, Ï) : v ? code(λ + (λ < 0 ? Ï : -Ï), Ï) : 0; 23648 if (!point0 && (v00 = v0 = v)) listener.lineStart(); 23649 if (v !== v0) { 23650 point2 = intersect(point0, point1); 23651 if (d3_geo_sphericalEqual(point0, point2) || d3_geo_sphericalEqual(point1, point2)) { 23652 point1[0] += ε; 23653 point1[1] += ε; 23654 v = visible(point1[0], point1[1]); 23655 } 23656 } 23657 if (v !== v0) { 23658 clean = 0; 23659 if (v) { 23660 listener.lineStart(); 23661 point2 = intersect(point1, point0); 23662 listener.point(point2[0], point2[1]); 23663 } else { 23664 point2 = intersect(point0, point1); 23665 listener.point(point2[0], point2[1]); 23666 listener.lineEnd(); 23667 } 23668 point0 = point2; 23669 } else if (notHemisphere && point0 && smallRadius ^ v) { 23670 var t; 23671 if (!(c & c0) && (t = intersect(point1, point0, true))) { 23672 clean = 0; 23673 if (smallRadius) { 23674 listener.lineStart(); 23675 listener.point(t[0][0], t[0][1]); 23676 listener.point(t[1][0], t[1][1]); 23677 listener.lineEnd(); 23678 } else { 23679 listener.point(t[1][0], t[1][1]); 23680 listener.lineEnd(); 23681 listener.lineStart(); 23682 listener.point(t[0][0], t[0][1]); 23683 } 23684 } 23685 } 23686 if (v && (!point0 || !d3_geo_sphericalEqual(point0, point1))) { 23687 listener.point(point1[0], point1[1]); 23688 } 23689 point0 = point1, v0 = v, c0 = c; 23690 }, 23691 lineEnd: function() { 23692 if (v0) listener.lineEnd(); 23693 point0 = null; 23694 }, 23695 clean: function() { 23696 return clean | (v00 && v0) << 1; 23697 } 23698 }; 23699 } 23700 function intersect(a, b, two) { 23701 var pa = d3_geo_cartesian(a), pb = d3_geo_cartesian(b); 23702 var n1 = [ 1, 0, 0 ], n2 = d3_geo_cartesianCross(pa, pb), n2n2 = d3_geo_cartesianDot(n2, n2), n1n2 = n2[0], determinant = n2n2 - n1n2 * n1n2; 23703 if (!determinant) return !two && a; 23704 var c1 = cr * n2n2 / determinant, c2 = -cr * n1n2 / determinant, n1xn2 = d3_geo_cartesianCross(n1, n2), A = d3_geo_cartesianScale(n1, c1), B = d3_geo_cartesianScale(n2, c2); 23705 d3_geo_cartesianAdd(A, B); 23706 var u = n1xn2, w = d3_geo_cartesianDot(A, u), uu = d3_geo_cartesianDot(u, u), t2 = w * w - uu * (d3_geo_cartesianDot(A, A) - 1); 23707 if (t2 < 0) return; 23708 var t = Math.sqrt(t2), q = d3_geo_cartesianScale(u, (-w - t) / uu); 23709 d3_geo_cartesianAdd(q, A); 23710 q = d3_geo_spherical(q); 23711 if (!two) return q; 23712 var λ0 = a[0], λ1 = b[0], Ï0 = a[1], Ï1 = b[1], z; 23713 if (λ1 < λ0) z = λ0, λ0 = λ1, λ1 = z; 23714 var δλ = λ1 - λ0, polar = abs(δλ - Ï) < ε, meridian = polar || δλ < ε; 23715 if (!polar && Ï1 < Ï0) z = Ï0, Ï0 = Ï1, Ï1 = z; 23716 if (meridian ? polar ? Ï0 + Ï1 > 0 ^ q[1] < (abs(q[0] - λ0) < ε ? Ï0 : Ï1) : Ï0 <= q[1] && q[1] <= Ï1 : δλ > Ï ^ (λ0 <= q[0] && q[0] <= λ1)) { 23717 var q1 = d3_geo_cartesianScale(u, (-w + t) / uu); 23718 d3_geo_cartesianAdd(q1, A); 23719 return [ q, d3_geo_spherical(q1) ]; 23720 } 23721 } 23722 function code(λ, Ï) { 23723 var r = smallRadius ? radius : Ï - radius, code = 0; 23724 if (λ < -r) code |= 1; else if (λ > r) code |= 2; 23725 if (Ï < -r) code |= 4; else if (Ï > r) code |= 8; 23726 return code; 23727 } 23728 } 23729 function d3_geom_clipLine(x0, y0, x1, y1) { 23730 return function(line) { 23731 var a = line.a, b = line.b, ax = a.x, ay = a.y, bx = b.x, by = b.y, t0 = 0, t1 = 1, dx = bx - ax, dy = by - ay, r; 23732 r = x0 - ax; 23733 if (!dx && r > 0) return; 23734 r /= dx; 23735 if (dx < 0) { 23736 if (r < t0) return; 23737 if (r < t1) t1 = r; 23738 } else if (dx > 0) { 23739 if (r > t1) return; 23740 if (r > t0) t0 = r; 23741 } 23742 r = x1 - ax; 23743 if (!dx && r < 0) return; 23744 r /= dx; 23745 if (dx < 0) { 23746 if (r > t1) return; 23747 if (r > t0) t0 = r; 23748 } else if (dx > 0) { 23749 if (r < t0) return; 23750 if (r < t1) t1 = r; 23751 } 23752 r = y0 - ay; 23753 if (!dy && r > 0) return; 23754 r /= dy; 23755 if (dy < 0) { 23756 if (r < t0) return; 23757 if (r < t1) t1 = r; 23758 } else if (dy > 0) { 23759 if (r > t1) return; 23760 if (r > t0) t0 = r; 23761 } 23762 r = y1 - ay; 23763 if (!dy && r < 0) return; 23764 r /= dy; 23765 if (dy < 0) { 23766 if (r > t1) return; 23767 if (r > t0) t0 = r; 23768 } else if (dy > 0) { 23769 if (r < t0) return; 23770 if (r < t1) t1 = r; 23771 } 23772 if (t0 > 0) line.a = { 23773 x: ax + t0 * dx, 23774 y: ay + t0 * dy 23775 }; 23776 if (t1 < 1) line.b = { 23777 x: ax + t1 * dx, 23778 y: ay + t1 * dy 23779 }; 23780 return line; 23781 }; 23782 } 23783 var d3_geo_clipExtentMAX = 1e9; 23784 d3.geo.clipExtent = function() { 23785 var x0, y0, x1, y1, stream, clip, clipExtent = { 23786 stream: function(output) { 23787 if (stream) stream.valid = false;
23788 stream = clip(output); 23789 stream.valid = true; 23790 return stream; 23791 }, 23792 extent: function(_) { 23793 if (!arguments.length) return [ [ x0, y0 ], [ x1, y1 ] ]; 23794 clip = d3_geo_clipExtent(x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1]); 23795 if (stream) stream.valid = false, stream = null; 23796 return clipExtent; 23797 } 23798 }; 23799 return clipExtent.extent([ [ 0, 0 ], [ 960, 500 ] ]); 23800 }; 23801 function d3_geo_clipExtent(x0, y0, x1, y1) { 23802 return function(listener) { 23803 var listener_ = listener, bufferListener = d3_geo_clipBufferListener(), clipLine = d3_geom_clipLine(x0, y0, x1, y1), segments, polygon, ring; 23804 var clip = { 23805 point: point, 23806 lineStart: lineStart, 23807 lineEnd: lineEnd, 23808 polygonStart: function() { 23809 listener = bufferListener; 23810 segments = []; 23811 polygon = []; 23812 clean = true; 23813 }, 23814 polygonEnd: function() { 23815 listener = listener_; 23816 segments = d3.merge(segments); 23817 var clipStartInside = insidePolygon([ x0, y1 ]), inside = clean && clipStartInside, visible = segments.length; 23818 if (inside || visible) { 23819 listener.polygonStart(); 23820 if (inside) { 23821 listener.lineStart(); 23822 interpolate(null, null, 1, listener); 23823 listener.lineEnd(); 23824 } 23825 if (visible) { 23826 d3_geo_clipPolygon(segments, compare, clipStartInside, interpolate, listener); 23827 } 23828 listener.polygonEnd(); 23829 } 23830 segments = polygon = ring = null; 23831 } 23832 }; 23833 function insidePolygon(p) { 23834 var wn = 0, n = polygon.length, y = p[1]; 23835 for (var i = 0; i < n; ++i) { 23836 for (var j = 1, v = polygon[i], m = v.length, a = v[0], b; j < m; ++j) { 23837 b = v[j]; 23838 if (a[1] <= y) { 23839 if (b[1] > y && d3_cross2d(a, b, p) > 0) ++wn; 23840 } else { 23841 if (b[1] <= y && d3_cross2d(a, b, p) < 0) --wn; 23842 } 23843 a = b; 23844 } 23845 } 23846 return wn !== 0; 23847 } 23848 function interpolate(from, to, direction, listener) { 23849 var a = 0, a1 = 0; 23850 if (from == null || (a = corner(from, direction)) !== (a1 = corner(to, direction)) || comparePoints(from, to) < 0 ^ direction > 0) { 23851 do { 23852 listener.point(a === 0 || a === 3 ? x0 : x1, a > 1 ? y1 : y0); 23853 } while ((a = (a + direction + 4) % 4) !== a1); 23854 } else { 23855 listener.point(to[0], to[1]); 23856 } 23857 } 23858 function pointVisible(x, y) { 23859 return x0 <= x && x <= x1 && y0 <= y && y <= y1; 23860 } 23861 function point(x, y) { 23862 if (pointVisible(x, y)) listener.point(x, y); 23863 } 23864 var x__, y__, v__, x_, y_, v_, first, clean; 23865 function lineStart() { 23866 clip.point = linePoint; 23867 if (polygon) polygon.push(ring = []); 23868 first = true; 23869 v_ = false; 23870 x_ = y_ = NaN; 23871 } 23872 function lineEnd() { 23873 if (segments) { 23874 linePoint(x__, y__); 23875 if (v__ && v_) bufferListener.rejoin(); 23876 segments.push(bufferListener.buffer()); 23877 } 23878 clip.point = point; 23879 if (v_) listener.lineEnd(); 23880 } 23881 function linePoint(x, y) { 23882 x = Math.max(-d3_geo_clipExtentMAX, Math.min(d3_geo_clipExtentMAX, x)); 23883 y = Math.max(-d3_geo_clipExtentMAX, Math.min(d3_geo_clipExtentMAX, y)); 23884 var v = pointVisible(x, y); 23885 if (polygon) ring.push([ x, y ]); 23886 if (first) { 23887 x__ = x, y__ = y, v__ = v; 23888 first = false; 23889 if (v) { 23890 listener.lineStart(); 23891 listener.point(x, y); 23892 } 23893 } else { 23894 if (v && v_) listener.point(x, y); else { 23895 var l = { 23896 a: { 23897 x: x_, 23898 y: y_ 23899 }, 23900 b: { 23901 x: x, 23902 y: y 23903 } 23904 }; 23905 if (clipLine(l)) { 23906 if (!v_) { 23907 listener.lineStart(); 23908 listener.point(l.a.x, l.a.y); 23909 } 23910 listener.point(l.b.x, l.b.y); 23911 if (!v) listener.lineEnd(); 23912 clean = false;
23913 } else if (v) { 23914 listener.lineStart(); 23915 listener.point(x, y); 23916 clean = false; 23917 } 23918 } 23919 } 23920 x_ = x, y_ = y, v_ = v; 23921 } 23922 return clip; 23923 }; 23924 function corner(p, direction) { 23925 return abs(p[0] - x0) < ε ? direction > 0 ? 0 : 3 : abs(p[0] - x1) < ε ? direction > 0 ? 2 : 1 : abs(p[1] - y0) < ε ? direction > 0 ? 1 : 0 : direction > 0 ? 3 : 2; 23926 } 23927 function compare(a, b) { 23928 return comparePoints(a.x, b.x); 23929 } 23930 function comparePoints(a, b) { 23931 var ca = corner(a, 1), cb = corner(b, 1); 23932 return ca !== cb ? ca - cb : ca === 0 ? b[1] - a[1] : ca === 1 ? a[0] - b[0] : ca === 2 ? a[1] - b[1] : b[0] - a[0]; 23933 } 23934 } 23935 function d3_geo_compose(a, b) { 23936 function compose(x, y) { 23937 return x = a(x, y), b(x[0], x[1]); 23938 } 23939 if (a.invert && b.invert) compose.invert = function(x, y) { 23940 return x = b.invert(x, y), x && a.invert(x[0], x[1]); 23941 }; 23942 return compose; 23943 } 23944 function d3_geo_conic(projectAt) { 23945 var Ï0 = 0, Ï1 = Ï / 3, m = d3_geo_projectionMutator(projectAt), p = m(Ï0, Ï1); 23946 p.parallels = function(_) { 23947 if (!arguments.length) return [ Ï0 / Ï * 180, Ï1 / Ï * 180 ]; 23948 return m(Ï0 = _[0] * Ï / 180, Ï1 = _[1] * Ï / 180); 23949 }; 23950 return p; 23951 } 23952 function d3_geo_conicEqualArea(Ï0, Ï1) { 23953 var sinÏ0 = Math.sin(Ï0), n = (sinÏ0 + Math.sin(Ï1)) / 2, C = 1 + sinÏ0 * (2 * n - sinÏ0), Ï0 = Math.sqrt(C) / n; 23954 function forward(λ, Ï) { 23955 var Ï = Math.sqrt(C - 2 * n * Math.sin(Ï)) / n; 23956 return [ Ï * Math.sin(λ *= n), Ï0 - Ï * Math.cos(λ) ]; 23957 } 23958 forward.invert = function(x, y) { 23959 var Ï0_y = Ï0 - y; 23960 return [ Math.atan2(x, Ï0_y) / n, d3_asin((C - (x * x + Ï0_y * Ï0_y) * n * n) / (2 * n)) ]; 23961 }; 23962 return forward; 23963 } 23964 (d3.geo.conicEqualArea = function() { 23965 return d3_geo_conic(d3_geo_conicEqualArea); 23966 }).raw = d3_geo_conicEqualArea; 23967 d3.geo.albers = function() { 23968 return d3.geo.conicEqualArea().rotate([ 96, 0 ]).center([ -.6, 38.7 ]).parallels([ 29.5, 45.5 ]).scale(1070); 23969 }; 23970 d3.geo.albersUsa = function() { 23971 var lower48 = d3.geo.albers(); 23972 var alaska = d3.geo.conicEqualArea().rotate([ 154, 0 ]).center([ -2, 58.5 ]).parallels([ 55, 65 ]); 23973 var hawaii = d3.geo.conicEqualArea().rotate([ 157, 0 ]).center([ -3, 19.9 ]).parallels([ 8, 18 ]); 23974 var point, pointStream = { 23975 point: function(x, y) { 23976 point = [ x, y ]; 23977 } 23978 }, lower48Point, alaskaPoint, hawaiiPoint; 23979 function albersUsa(coordinates) { 23980 var x = coordinates[0], y = coordinates[1]; 23981 point = null; 23982 (lower48Point(x, y), point) || (alaskaPoint(x, y), point) || hawaiiPoint(x, y); 23983 return point; 23984 } 23985 albersUsa.invert = function(coordinates) { 23986 var k = lower48.scale(), t = lower48.translate(), x = (coordinates[0] - t[0]) / k, y = (coordinates[1] - t[1]) / k; 23987 return (y >= .12 && y < .234 && x >= -.425 && x < -.214 ? alaska : y >= .166 && y < .234 && x >= -.214 && x < -.115 ? hawaii : lower48).invert(coordinates); 23988 }; 23989 albersUsa.stream = function(stream) { 23990 var lower48Stream = lower48.stream(stream), alaskaStream = alaska.stream(stream), hawaiiStream = hawaii.stream(stream); 23991 return { 23992 point: function(x, y) { 23993 lower48Stream.point(x, y); 23994 alaskaStream.point(x, y); 23995 hawaiiStream.point(x, y); 23996 }, 23997 sphere: function() { 23998 lower48Stream.sphere(); 23999 alaskaStream.sphere(); 24000 hawaiiStream.sphere(); 24001 }, 24002 lineStart: function() { 24003 lower48Stream.lineStart(); 24004 alaskaStream.lineStart(); 24005 hawaiiStream.lineStart(); 24006 }, 24007 lineEnd: function() { 24008 lower48Stream.lineEnd(); 24009 alaskaStream.lineEnd(); 24010 hawaiiStream.lineEnd(); 24011 }, 24012 polygonStart: function() { 24013 lower48Stream.polygonStart(); 24014 alaskaStream.polygonStart(); 24015 hawaiiStream.polygonStart(); 24016 }, 24017 polygonEnd: function() { 24018 lower48Stream.polygonEnd(); 24019 alaskaStream.polygonEnd(); 24020 hawaiiStream.polygonEnd(); 24021 } 24022 }; 24023 }; 24024 albersUsa.precision = function(_) { 24025 if (!arguments.length) return lower48.precision(); 24026 lower48.precision(_); 24027 alaska.precision(_); 24028 hawaii.precision(_); 24029 return albersUsa; 24030 }; 24031 albersUsa.scale = function(_) { 24032 if (!arguments.length) return lower48.scale(); 24033 lower48.scale(_); 24034 alaska.scale(_ * .35); 24035 hawaii.scale(_); 24036 return albersUsa.translate(lower48.translate()); 24037 }; 24038 albersUsa.translate = function(_) { 24039 if (!arguments.length) return lower48.translate(); 24040 var k = lower48.scale(), x = +_[0], y = +_[1]; 24041 lower48Point = lower48.translate(_).clipExtent([ [ x - .455 * k, y - .238 * k ], [ x + .455 * k, y + .238 * k ] ]).stream(pointStream).point; 24042 alaskaPoint = alaska.translate([ x - .307 * k, y + .201 * k ]).clipExtent([ [ x - .425 * k + ε, y + .12 * k + ε ], [ x - .214 * k - ε, y + .234 * k - ε ] ]).stream(pointStream).point; 24043 hawaiiPoint = hawaii.translate([ x - .205 * k, y + .212 * k ]).clipExtent([ [ x - .214 * k + ε, y + .166 * k + ε ], [ x - .115 * k - ε, y + .234 * k - ε ] ]).stream(pointStream).point; 24044 return albersUsa; 24045 }; 24046 return albersUsa.scale(1070); 24047 }; 24048 var d3_geo_pathAreaSum, d3_geo_pathAreaPolygon, d3_geo_pathArea = { 24049 point: d3_noop, 24050 lineStart: d3_noop, 24051 lineEnd: d3_noop, 24052 polygonStart: function() { 24053 d3_geo_pathAreaPolygon = 0; 24054 d3_geo_pathArea.lineStart = d3_geo_pathAreaRingStart; 24055 }, 24056 polygonEnd: function() { 24057 d3_geo_pathArea.lineStart = d3_geo_pathArea.lineEnd = d3_geo_pathArea.point = d3_noop; 24058 d3_geo_pathAreaSum += abs(d3_geo_pathAreaPolygon / 2); 24059 } 24060 }; 24061 function d3_geo_pathAreaRingStart() { 24062 var x00, y00, x0, y0; 24063 d3_geo_pathArea.point = function(x, y) { 24064 d3_geo_pathArea.point = nextPoint; 24065 x00 = x0 = x, y00 = y0 = y; 24066 }; 24067 function nextPoint(x, y) { 24068 d3_geo_pathAreaPolygon += y0 * x - x0 * y; 24069 x0 = x, y0 = y; 24070 } 24071 d3_geo_pathArea.lineEnd = function() { 24072 nextPoint(x00, y00); 24073 }; 24074 } 24075 var d3_geo_pathBoundsX0, d3_geo_pathBoundsY0, d3_geo_pathBoundsX1, d3_geo_pathBoundsY1; 24076 var d3_geo_pathBounds = { 24077 point: d3_geo_pathBoundsPoint, 24078 lineStart: d3_noop, 24079 lineEnd: d3_noop, 24080 polygonStart: d3_noop, 24081 polygonEnd: d3_noop 24082 }; 24083 function d3_geo_pathBoundsPoint(x, y) { 24084 if (x < d3_geo_pathBoundsX0) d3_geo_pathBoundsX0 = x; 24085 if (x > d3_geo_pathBoundsX1) d3_geo_pathBoundsX1 = x; 24086 if (y < d3_geo_pathBoundsY0) d3_geo_pathBoundsY0 = y; 24087 if (y > d3_geo_pathBoundsY1) d3_geo_pathBoundsY1 = y; 24088 } 24089 function d3_geo_pathBuffer() { 24090 var pointCircle = d3_geo_pathBufferCircle(4.5), buffer = []; 24091 var stream = { 24092 point: point, 24093 lineStart: function() { 24094 stream.point = pointLineStart; 24095 }, 24096 lineEnd: lineEnd, 24097 polygonStart: function() { 24098 stream.lineEnd = lineEndPolygon; 24099 }, 24100 polygonEnd: function() { 24101 stream.lineEnd = lineEnd; 24102 stream.point = point; 24103 }, 24104 pointRadius: function(_) { 24105 pointCircle = d3_geo_pathBufferCircle(_); 24106 return stream; 24107 }, 24108 result: function() { 24109 if (buffer.length) { 24110 var result = buffer.join(""); 24111 buffer = []; 24112 return result; 24113 } 24114 } 24115 }; 24116 function point(x, y) { 24117 buffer.push("M", x, ",", y, pointCircle); 24118 } 24119 function pointLineStart(x, y) { 24120 buffer.push("M", x, ",", y); 24121 stream.point = pointLine; 24122 } 24123 function pointLine(x, y) { 24124 buffer.push("L", x, ",", y); 24125 } 24126 function lineEnd() { 24127 stream.point = point; 24128 } 24129 function lineEndPolygon() { 24130 buffer.push("Z"); 24131 } 24132 return stream; 24133 } 24134 function d3_geo_pathBufferCircle(radius) {
24135 return "m0," + radius + "a" + radius + "," + radius + " 0 1,1 0," + -2 * radius + "a" + radius + "," + radius + " 0 1,1 0," + 2 * radius + "z"; 24136 } 24137 var d3_geo_pathCentroid = { 24138 point: d3_geo_pathCentroidPoint, 24139 lineStart: d3_geo_pathCentroidLineStart, 24140 lineEnd: d3_geo_pathCentroidLineEnd, 24141 polygonStart: function() { 24142 d3_geo_pathCentroid.lineStart = d3_geo_pathCentroidRingStart; 24143 }, 24144 polygonEnd: function() { 24145 d3_geo_pathCentroid.point = d3_geo_pathCentroidPoint; 24146 d3_geo_pathCentroid.lineStart = d3_geo_pathCentroidLineStart; 24147 d3_geo_pathCentroid.lineEnd = d3_geo_pathCentroidLineEnd; 24148 } 24149 }; 24150 function d3_geo_pathCentroidPoint(x, y) { 24151 d3_geo_centroidX0 += x; 24152 d3_geo_centroidY0 += y; 24153 ++d3_geo_centroidZ0; 24154 } 24155 function d3_geo_pathCentroidLineStart() { 24156 var x0, y0; 24157 d3_geo_pathCentroid.point = function(x, y) { 24158 d3_geo_pathCentroid.point = nextPoint; 24159 d3_geo_pathCentroidPoint(x0 = x, y0 = y); 24160 }; 24161 function nextPoint(x, y) { 24162 var dx = x - x0, dy = y - y0, z = Math.sqrt(dx * dx + dy * dy); 24163 d3_geo_centroidX1 += z * (x0 + x) / 2; 24164 d3_geo_centroidY1 += z * (y0 + y) / 2; 24165 d3_geo_centroidZ1 += z; 24166 d3_geo_pathCentroidPoint(x0 = x, y0 = y); 24167 } 24168 } 24169 function d3_geo_pathCentroidLineEnd() { 24170 d3_geo_pathCentroid.point = d3_geo_pathCentroidPoint; 24171 } 24172 function d3_geo_pathCentroidRingStart() { 24173 var x00, y00, x0, y0; 24174 d3_geo_pathCentroid.point = function(x, y) { 24175 d3_geo_pathCentroid.point = nextPoint; 24176 d3_geo_pathCentroidPoint(x00 = x0 = x, y00 = y0 = y); 24177 }; 24178 function nextPoint(x, y) { 24179 var dx = x - x0, dy = y - y0, z = Math.sqrt(dx * dx + dy * dy); 24180 d3_geo_centroidX1 += z * (x0 + x) / 2; 24181 d3_geo_centroidY1 += z * (y0 + y) / 2; 24182 d3_geo_centroidZ1 += z; 24183 z = y0 * x - x0 * y; 24184 d3_geo_centroidX2 += z * (x0 + x); 24185 d3_geo_centroidY2 += z * (y0 + y); 24186 d3_geo_centroidZ2 += z * 3; 24187 d3_geo_pathCentroidPoint(x0 = x, y0 = y); 24188 } 24189 d3_geo_pathCentroid.lineEnd = function() { 24190 nextPoint(x00, y00); 24191 }; 24192 } 24193 function d3_geo_pathContext(context) { 24194 var pointRadius = 4.5; 24195 var stream = { 24196 point: point, 24197 lineStart: function() { 24198 stream.point = pointLineStart; 24199 }, 24200 lineEnd: lineEnd, 24201 polygonStart: function() { 24202 stream.lineEnd = lineEndPolygon; 24203 }, 24204 polygonEnd: function() { 24205 stream.lineEnd = lineEnd; 24206 stream.point = point; 24207 }, 24208 pointRadius: function(_) { 24209 pointRadius = _; 24210 return stream; 24211 }, 24212 result: d3_noop 24213 }; 24214 function point(x, y) { 24215 context.moveTo(x, y); 24216 context.arc(x, y, pointRadius, 0, Ï); 24217 } 24218 function pointLineStart(x, y) { 24219 context.moveTo(x, y); 24220 stream.point = pointLine; 24221 } 24222 function pointLine(x, y) { 24223 context.lineTo(x, y); 24224 } 24225 function lineEnd() { 24226 stream.point = point; 24227 } 24228 function lineEndPolygon() { 24229 context.closePath(); 24230 } 24231 return stream; 24232 } 24233 function d3_geo_resample(project) { 24234 var δ2 = .5, cosMinDistance = Math.cos(30 * d3_radians), maxDepth = 16; 24235 function resample(stream) { 24236 return (maxDepth ? resampleRecursive : resampleNone)(stream); 24237 } 24238 function resampleNone(stream) { 24239 return d3_geo_transformPoint(stream, function(x, y) { 24240 x = project(x, y); 24241 stream.point(x[0], x[1]); 24242 }); 24243 } 24244 function resampleRecursive(stream) { 24245 var λ00, Ï00, x00, y00, a00, b00, c00, λ0, x0, y0, a0, b0, c0; 24246 var resample = { 24247 point: point, 24248 lineStart: lineStart, 24249 lineEnd: lineEnd, 24250 polygonStart: function() { 24251 stream.polygonStart(); 24252 resample.lineStart = ringStart; 24253 }, 24254 polygonEnd: function() { 24255 stream.polygonEnd(); 24256 resample.lineStart = lineStart; 24257 } 24258 }; 24259 function point(x, y) { 24260 x = project(x, y); 24261 stream.point(x[0], x[1]); 24262 } 24263 function lineStart() { 24264 x0 = NaN; 24265 resample.point = linePoint; 24266 stream.lineStart(); 24267 } 24268 function linePoint(λ, Ï) { 24269 var c = d3_geo_cartesian([ λ, Ï ]), p = project(λ, Ï); 24270 resampleLineTo(x0, y0, λ0, a0, b0, c0, x0 = p[0], y0 = p[1], λ0 = λ, a0 = c[0], b0 = c[1], c0 = c[2], maxDepth, stream); 24271 stream.point(x0, y0); 24272 } 24273 function lineEnd() { 24274 resample.point = point; 24275 stream.lineEnd(); 24276 } 24277 function ringStart() { 24278 lineStart(); 24279 resample.point = ringPoint; 24280 resample.lineEnd = ringEnd; 24281 } 24282 function ringPoint(λ, Ï) { 24283 linePoint(λ00 = λ, Ï00 = Ï), x00 = x0, y00 = y0, a00 = a0, b00 = b0, c00 = c0; 24284 resample.point = linePoint; 24285 } 24286 function ringEnd() { 24287 resampleLineTo(x0, y0, λ0, a0, b0, c0, x00, y00, λ00, a00, b00, c00, maxDepth, stream); 24288 resample.lineEnd = lineEnd; 24289 lineEnd(); 24290 } 24291 return resample; 24292 } 24293 function resampleLineTo(x0, y0, λ0, a0, b0, c0, x1, y1, λ1, a1, b1, c1, depth, stream) { 24294 var dx = x1 - x0, dy = y1 - y0, d2 = dx * dx + dy * dy; 24295 if (d2 > 4 * δ2 && depth--) { 24296 var a = a0 + a1, b = b0 + b1, c = c0 + c1, m = Math.sqrt(a * a + b * b + c * c), Ï2 = Math.asin(c /= m), λ2 = abs(abs(c) - 1) < ε || abs(λ0 - λ1) < ε ? (λ0 + λ1) / 2 : Math.atan2(b, a), p = project(λ2, Ï2), x2 = p[0], y2 = p[1], dx2 = x2 - x0, dy2 = y2 - y0, dz = dy * dx2 - dx * dy2; 24297 if (dz * dz / d2 > δ2 || abs((dx * dx2 + dy * dy2) / d2 - .5) > .3 || a0 * a1 + b0 * b1 + c0 * c1 < cosMinDistance) { 24298 resampleLineTo(x0, y0, λ0, a0, b0, c0, x2, y2, λ2, a /= m, b /= m, c, depth, stream); 24299 stream.point(x2, y2); 24300 resampleLineTo(x2, y2, λ2, a, b, c, x1, y1, λ1, a1, b1, c1, depth, stream); 24301 } 24302 } 24303 } 24304 resample.precision = function(_) { 24305 if (!arguments.length) return Math.sqrt(δ2); 24306 maxDepth = (δ2 = _ * _) > 0 && 16; 24307 return resample; 24308 }; 24309 return resample; 24310 } 24311 d3.geo.path = function() { 24312 var pointRadius = 4.5, projection, context, projectStream, contextStream, cacheStream; 24313 function path(object) { 24314 if (object) { 24315 if (typeof pointRadius === "function") contextStream.pointRadius(+pointRadius.apply(this, arguments)); 24316 if (!cacheStream || !cacheStream.valid) cacheStream = projectStream(contextStream); 24317 d3.geo.stream(object, cacheStream); 24318 } 24319 return contextStream.result(); 24320 } 24321 path.area = function(object) { 24322 d3_geo_pathAreaSum = 0; 24323 d3.geo.stream(object, projectStream(d3_geo_pathArea)); 24324 return d3_geo_pathAreaSum; 24325 };
24326 path.centroid = function(object) { 24327 d3_geo_centroidX0 = d3_geo_centroidY0 = d3_geo_centroidZ0 = d3_geo_centroidX1 = d3_geo_centroidY1 = d3_geo_centroidZ1 = d3_geo_centroidX2 = d3_geo_centroidY2 = d3_geo_centroidZ2 = 0; 24328 d3.geo.stream(object, projectStream(d3_geo_pathCentroid)); 24329 return d3_geo_centroidZ2 ? [ d3_geo_centroidX2 / d3_geo_centroidZ2, d3_geo_centroidY2 / d3_geo_centroidZ2 ] : d3_geo_centroidZ1 ? [ d3_geo_centroidX1 / d3_geo_centroidZ1, d3_geo_centroidY1 / d3_geo_centroidZ1 ] : d3_geo_centroidZ0 ? [ d3_geo_centroidX0 / d3_geo_centroidZ0, d3_geo_centroidY0 / d3_geo_centroidZ0 ] : [ NaN, NaN ]; 24330 }; 24331 path.bounds = function(object) { 24332 d3_geo_pathBoundsX1 = d3_geo_pathBoundsY1 = -(d3_geo_pathBoundsX0 = d3_geo_pathBoundsY0 = Infinity); 24333 d3.geo.stream(object, projectStream(d3_geo_pathBounds)); 24334 return [ [ d3_geo_pathBoundsX0, d3_geo_pathBoundsY0 ], [ d3_geo_pathBoundsX1, d3_geo_pathBoundsY1 ] ]; 24335 }; 24336 path.projection = function(_) { 24337 if (!arguments.length) return projection; 24338 projectStream = (projection = _) ? _.stream || d3_geo_pathProjectStream(_) : d3_identity; 24339 return reset(); 24340 }; 24341 path.context = function(_) { 24342 if (!arguments.length) return context; 24343 contextStream = (context = _) == null ? new d3_geo_pathBuffer() : new d3_geo_pathContext(_); 24344 if (typeof pointRadius !== "function") contextStream.pointRadius(pointRadius); 24345 return reset(); 24346 }; 24347 path.pointRadius = function(_) { 24348 if (!arguments.length) return pointRadius; 24349 pointRadius = typeof _ === "function" ? _ : (contextStream.pointRadius(+_), +_); 24350 return path; 24351 }; 24352 function reset() { 24353 cacheStream = null; 24354 return path; 24355 } 24356 return path.projection(d3.geo.albersUsa()).context(null); 24357 }; 24358 function d3_geo_pathProjectStream(project) { 24359 var resample = d3_geo_resample(function(x, y) { 24360 return project([ x * d3_degrees, y * d3_degrees ]); 24361 }); 24362 return function(stream) { 24363 return d3_geo_projectionRadians(resample(stream)); 24364 }; 24365 } 24366 d3.geo.transform = function(methods) { 24367 return { 24368 stream: function(stream) { 24369 var transform = new d3_geo_transform(stream); 24370 for (var k in methods) transform[k] = methods[k]; 24371 return transform; 24372 } 24373 }; 24374 }; 24375 function d3_geo_transform(stream) { 24376 this.stream = stream; 24377 } 24378 d3_geo_transform.prototype = { 24379 point: function(x, y) { 24380 this.stream.point(x, y); 24381 }, 24382 sphere: function() { 24383 this.stream.sphere(); 24384 }, 24385 lineStart: function() { 24386 this.stream.lineStart(); 24387 }, 24388 lineEnd: function() { 24389 this.stream.lineEnd(); 24390 }, 24391 polygonStart: function() { 24392 this.stream.polygonStart(); 24393 }, 24394 polygonEnd: function() { 24395 this.stream.polygonEnd(); 24396 } 24397 }; 24398 function d3_geo_transformPoint(stream, point) { 24399 return { 24400 point: point, 24401 sphere: function() { 24402 stream.sphere(); 24403 }, 24404 lineStart: function() { 24405 stream.lineStart(); 24406 }, 24407 lineEnd: function() { 24408 stream.lineEnd(); 24409 }, 24410 polygonStart: function() { 24411 stream.polygonStart(); 24412 }, 24413 polygonEnd: function() { 24414 stream.polygonEnd(); 24415 } 24416 }; 24417 } 24418 d3.geo.projection = d3_geo_projection; 24419 d3.geo.projectionMutator = d3_geo_projectionMutator; 24420 function d3_geo_projection(project) { 24421 return d3_geo_projectionMutator(function() { 24422 return project; 24423 })(); 24424 } 24425 function d3_geo_projectionMutator(projectAt) { 24426 var project, rotate, projectRotate, projectResample = d3_geo_resample(function(x, y) { 24427 x = project(x, y); 24428 return [ x[0] * k + δx, δy - x[1] * k ]; 24429 }), k = 150, x = 480, y = 250, λ = 0, Ï = 0, δλ = 0, Î´Ï = 0, δγ = 0, δx, δy, preclip = d3_geo_clipAntimeridian, postclip = d3_identity, clipAngle = null, clipExtent = null, stream; 24430 function projection(point) { 24431 point = projectRotate(point[0] * d3_radians, point[1] * d3_radians); 24432 return [ point[0] * k + δx, δy - point[1] * k ]; 24433 } 24434 function invert(point) { 24435 point = projectRotate.invert((point[0] - δx) / k, (δy - point[1]) / k); 24436 return point && [ point[0] * d3_degrees, point[1] * d3_degrees ]; 24437 } 24438 projection.stream = function(output) { 24439 if (stream) stream.valid = false;
24440 stream = d3_geo_projectionRadians(preclip(rotate, projectResample(postclip(output)))); 24441 stream.valid = true; 24442 return stream; 24443 }; 24444 projection.clipAngle = function(_) { 24445 if (!arguments.length) return clipAngle; 24446 preclip = _ == null ? (clipAngle = _, d3_geo_clipAntimeridian) : d3_geo_clipCircle((clipAngle = +_) * d3_radians); 24447 return invalidate(); 24448 }; 24449 projection.clipExtent = function(_) { 24450 if (!arguments.length) return clipExtent; 24451 clipExtent = _; 24452 postclip = _ ? d3_geo_clipExtent(_[0][0], _[0][1], _[1][0], _[1][1]) : d3_identity; 24453 return invalidate(); 24454 }; 24455 projection.scale = function(_) { 24456 if (!arguments.length) return k; 24457 k = +_; 24458 return reset(); 24459 }; 24460 projection.translate = function(_) { 24461 if (!arguments.length) return [ x, y ]; 24462 x = +_[0]; 24463 y = +_[1]; 24464 return reset(); 24465 }; 24466 projection.center = function(_) { 24467 if (!arguments.length) return [ λ * d3_degrees, Ï * d3_degrees ]; 24468 λ = _[0] % 360 * d3_radians; 24469 Ï = _[1] % 360 * d3_radians; 24470 return reset(); 24471 }; 24472 projection.rotate = function(_) { 24473 if (!arguments.length) return [ δλ * d3_degrees, Î´Ï * d3_degrees, δγ * d3_degrees ]; 24474 δλ = _[0] % 360 * d3_radians; 24475 Î´Ï = _[1] % 360 * d3_radians; 24476 δγ = _.length > 2 ? _[2] % 360 * d3_radians : 0; 24477 return reset(); 24478 }; 24479 d3.rebind(projection, projectResample, "precision"); 24480 function reset() { 24481 projectRotate = d3_geo_compose(rotate = d3_geo_rotation(δλ, δÏ, δγ), project); 24482 var center = project(λ, Ï); 24483 δx = x - center[0] * k; 24484 δy = y + center[1] * k; 24485 return invalidate(); 24486 }
24487 function invalidate() { 24488 if (stream) stream.valid = false, stream = null; 24489 return projection; 24490 } 24491 return function() { 24492 project = projectAt.apply(this, arguments); 24493 projection.invert = project.invert && invert; 24494 return reset(); 24495 }; 24496 } 24497 function d3_geo_projectionRadians(stream) { 24498 return d3_geo_transformPoint(stream, function(x, y) { 24499 stream.point(x * d3_radians, y * d3_radians); 24500 }); 24501 } 24502 function d3_geo_equirectangular(λ, Ï) { 24503 return [ λ, Ï ]; 24504 } 24505 (d3.geo.equirectangular = function() { 24506 return d3_geo_projection(d3_geo_equirectangular); 24507 }).raw = d3_geo_equirectangular.invert = d3_geo_equirectangular; 24508 d3.geo.rotation = function(rotate) { 24509 rotate = d3_geo_rotation(rotate[0] % 360 * d3_radians, rotate[1] * d3_radians, rotate.length > 2 ? rotate[2] * d3_radians : 0); 24510 function forward(coordinates) { 24511 coordinates = rotate(coordinates[0] * d3_radians, coordinates[1] * d3_radians); 24512 return coordinates[0] *= d3_degrees, coordinates[1] *= d3_degrees, coordinates; 24513 } 24514 forward.invert = function(coordinates) { 24515 coordinates = rotate.invert(coordinates[0] * d3_radians, coordinates[1] * d3_radians); 24516 return coordinates[0] *= d3_degrees, coordinates[1] *= d3_degrees, coordinates; 24517 }; 24518 return forward; 24519 }; 24520 function d3_geo_identityRotation(λ, Ï) { 24521 return [ λ > Ï ? λ - Ï : λ < -Ï ? λ + Ï : λ, Ï ]; 24522 } 24523 d3_geo_identityRotation.invert = d3_geo_equirectangular; 24524 function d3_geo_rotation(δλ, δÏ, δγ) { 24525 return δλ ? Î´Ï || δγ ? d3_geo_compose(d3_geo_rotationλ(δλ
24525), d3_geo_rotationÏγ(δÏ, δγ)) : d3_geo_rotationλ(δλ) : Î´Ï || δγ ? d3_geo_rotationÏγ(δÏ, δγ) : d3_geo_identityRotation; 24526 } 24527 function d3_geo_forwardRotationλ(δλ) { 24528 return function(λ, Ï) { 24529 return λ += δλ, [ λ > Ï ? λ - Ï : λ < -Ï ? λ + Ï : λ, Ï ]; 24530 }; 24531 } 24532 function d3_geo_rotationλ(δλ) { 24533 var rotation = d3_geo_forwardRotationλ(δλ); 24534 rotation.invert = d3_geo_forwardRotationλ(-δλ); 24535 return rotation; 24536 } 24537 function d3_geo_rotationÏγ(δÏ, δγ) { 24538 var cosÎ´Ï = Math.cos(δÏ), sinÎ´Ï = Math.sin(δÏ), cosδγ = Math.cos(δγ), sinδγ = Math.sin(δγ); 24539 function rotation(λ, Ï) { 24540 var cosÏ = Math.cos(Ï), x = Math.cos(λ) * cosÏ, y = Math.sin(λ) * cosÏ, z = Math.sin(Ï), k = z * cosÎ´Ï + x * sinδÏ; 24541 return [ Math.atan2(y * cosδγ - k * sinδγ, x * cosÎ´Ï - z * sinδÏ), d3_asin(k * cosδγ + y * sinδγ) ]; 24542 } 24543 rotation.invert = function(λ, Ï) { 24544 var cosÏ = Math.cos(Ï), x = Math.cos(λ) * cosÏ, y = Math.sin(λ) * cosÏ, z = Math.sin(Ï), k = z * cosδγ - y * sinδγ; 24545 return [ Math.atan2(y * cosδγ + z * sinδγ, x * cosÎ´Ï + k * sinδÏ), d3_asin(k * cosÎ´Ï - x * sinδÏ) ]; 24546 }; 24547 return rotation; 24548 } 24549 d3.geo.circle = function() { 24550 var origin = [ 0, 0 ], angle, precision = 6, interpolate; 24551 function circle() { 24552 var center = typeof origin === "function" ? origin.apply(this, arguments) : origin, rotate = d3_geo_rotation(-center[0] * d3_radians, -center[1] * d3_radians, 0).invert, ring = []; 24553 interpolate(null, null, 1, { 24554 point: function(x, y) { 24555 ring.push(x = rotate(x, y)); 24556 x[0] *= d3_degrees, x[1] *= d3_degrees; 24557 } 24558 }); 24559 return { 24560 type: "Polygon", 24561 coordinates: [ ring ] 24562 }; 24563 } 24564 circle.origin = function(x) { 24565 if (!arguments.length) return origin; 24566 origin = x; 24567 return circle; 24568 }; 24569 circle.angle = function(x) { 24570 if (!arguments.length) return angle; 24571 interpolate = d3_geo_circleInterpolate((angle = +x) * d3_radians, precision * d3_radians); 24572 return circle; 24573 }; 24574 circle.precision = function(_) { 24575 if (!arguments.length) return precision; 24576 interpolate = d3_geo_circleInterpolate(angle * d3_radians, (precision = +_) * d3_radians); 24577 return circle; 24578 }; 24579 return circle.angle(90); 24580 }; 24581 function d3_geo_circleInterpolate(radius, precision) { 24582 var cr = Math.cos(radius), sr = Math.sin(radius); 24583 return function(from, to, direction, listener) { 24584 var step = direction * precision; 24585 if (from != null) { 24586 from = d3_geo_circleAngle(cr, from); 24587 to = d3_geo_circleAngle(cr, to); 24588 if (direction > 0 ? from < to : from > to) from += direction * Ï; 24589 } else { 24590 from = radius + direction * Ï; 24591 to = radius - .5 * step; 24592 } 24593 for (var point, t = from; direction > 0 ? t > to : t < to; t -= step) { 24594 listener.point((point = d3_geo_spherical([ cr, -sr * Math.cos(t), -sr * Math.sin(t) ]))[0], point[1]); 24595 } 24596 }; 24597 } 24598 function d3_geo_circleAngle(cr, point) { 24599 var a = d3_geo_cartesian(point); 24600 a[0] -= cr; 24601 d3_geo_cartesianNormalize(a); 24602 var angle = d3_acos(-a[1]); 24603 return ((-a[2] < 0 ? -angle : angle) + 2 * Math.PI - ε) % (2 * Math.PI); 24604 } 24605 d3.geo.distance = function(a, b) { 24606 var Îλ = (b[0] - a[0]) * d3_radians, Ï0 = a[1] * d3_radians, Ï1 = b[1] * d3_radians, sinÎλ = Math.sin(Îλ), cosÎλ = Math.cos(Îλ), sinÏ0 = Math.sin(Ï0), cosÏ0 = Math.cos(Ï0), sinÏ1 = Math.sin(Ï1), cosÏ1 = Math.cos(Ï1), t; 24607 return Math.atan2(Math.sqrt((t = cosÏ1 * sinÎλ) * t + (t = cosÏ0 * sinÏ1 - sinÏ0 * cosÏ1 * cosÎλ) * t), sinÏ0 * sinÏ1 + cosÏ0 * cosÏ1 * cosÎλ); 24608 }; 24609 d3.geo.graticule = function() { 24610 var x1, x0, X1, X0, y1, y0, Y1, Y0, dx = 10, dy = dx, DX = 90, DY = 360, x, y, X, Y, precision = 2.5; 24611 function graticule() { 24612 return { 24613 type: "MultiLineString", 24614 coordinates: lines() 24615 }; 24616 } 24617 function lines() { 24618 return d3.range(Math.ceil(X0 / DX) * DX, X1, DX).map(X).concat(d3.range(Math.ceil(Y0 / DY) * DY, Y1, DY).map(Y)).concat(d3.range(Math.ceil(x0 / dx) * dx, x1, dx).filter(function(x) { 24619 return abs(x % DX) > ε; 24620 }).map(x)).concat(d3.range(Math.ceil(y0 / dy) * dy, y1, dy).filter(function(y) { 24621 return abs(y % DY) > ε; 24622 }).map(y)); 24623 } 24624 graticule.lines = function() { 24625 return lines().map(function(coordinates) { 24626 return { 24627 type: "LineString", 24628 coordinates: coordinates 24629 }; 24630 }); 24631 }; 24632 graticule.outline = function() { 24633 return { 24634 type: "Polygon", 24635 coordinates: [ X(X0).concat(Y(Y1).slice(1), X(X1).reverse().slice(1), Y(Y0).reverse().slice(1)) ] 24636 }; 24637 }; 24638 graticule.extent = function(_) { 24639 if (!arguments.length) return graticule.minorExtent(); 24640 return graticule.majorExtent(_).minorExtent(_); 24641 }; 24642 graticule.majorExtent = function(_) { 24643 if (!arguments.length) return [ [ X0, Y0 ], [ X1, Y1 ] ]; 24644 X0 = +_[0][0], X1 = +_[1][0]; 24645 Y0 = +_[0][1], Y1 = +_[1][1]; 24646 if (X0 > X1) _ = X0, X0 = X1, X1 = _; 24647 if (Y0 > Y1) _ = Y0, Y0 = Y1, Y1 = _; 24648 return graticule.precision(precision); 24649 }; 24650 graticule.minorExtent = function(_) { 24651 if (!arguments.length) return [ [ x0, y0 ], [ x1, y1 ] ]; 24652 x0 = +_[0][0], x1 = +_[1][0]; 24653 y0 = +_[0][1], y1 = +_[1][1]; 24654 if (x0 > x1) _ = x0, x0 = x1, x1 = _; 24655 if (y0 > y1) _ = y0, y0 = y1, y1 = _; 24656 return graticule.precision(precision); 24657 };
24658 graticule.step = function(_) { 24659 if (!arguments.length) return graticule.minorStep(); 24660 return graticule.majorStep(_).minorStep(_); 24661 }; 24662 graticule.majorStep = function(_) { 24663 if (!arguments.length) return [ DX, DY ]; 24664 DX = +_[0], DY = +_[1]; 24665 return graticule; 24666 }; 24667 graticule.minorStep = function(_) { 24668 if (!arguments.length) return [ dx, dy ]; 24669 dx = +_[0], dy = +_[1]; 24670 return graticule; 24671 }; 24672 graticule.precision = function(_) { 24673 if (!arguments.length) return precision; 24674 precision = +_; 24675 x = d3_geo_graticuleX(y0, y1, 90); 24676 y = d3_geo_graticuleY(x0, x1, precision); 24677 X = d3_geo_graticuleX(Y0, Y1, 90); 24678 Y = d3_geo_graticuleY(X0, X1, precision); 24679 return graticule; 24680 }; 24681 return graticule.majorExtent([ [ -180, -90 + ε ], [ 180, 90 - ε ] ]).minorExtent([ [ -180, -80 - ε ], [ 180, 80 + ε ] ]); 24682 }; 24683 function d3_geo_graticuleX(y0, y1, dy) { 24684 var y = d3.range(y0, y1 - ε, dy).concat(y1); 24685 return function(x) { 24686 return y.map(function(y) { 24687 return [ x, y ]; 24688 }); 24689 }; 24690 } 24691 function d3_geo_graticuleY(x0, x1, dx) { 24692 var x = d3.range(x0, x1 - ε, dx).concat(x1); 24693 return function(y) { 24694 return x.map(function(x) { 24695 return [ x, y ]; 24696 }); 24697 }; 24698 } 24699 function d3_source(d) { 24700 return d.source; 24701 } 24702 function d3_target(d) { 24703 return d.target; 24704 } 24705 d3.geo.greatArc = function() { 24706 var source = d3_source, source_, target = d3_target, target_; 24707 function greatArc() { 24708 return { 24709 type: "LineString", 24710 coordinates: [ source_ || source.apply(this, arguments), target_ || target.apply(this, arguments) ] 24711 }; 24712 } 24713 greatArc.distance = function() { 24714 return d3.geo.distance(source_ || source.apply(this, arguments), target_ || target.apply(this, arguments)); 24715 }; 24716 greatArc.source = function(_) { 24717 if (!arguments.length) return source; 24718 source = _, source_ = typeof _ === "function" ? null : _; 24719 return greatArc; 24720 }; 24721 greatArc.target = function(_) { 24722 if (!arguments.length) return target; 24723 target = _, target_ = typeof _ === "function" ? null : _; 24724 return greatArc; 24725 }; 24726 greatArc.precision = function() { 24727 return arguments.length ? greatArc : 0; 24728 }; 24729 return greatArc; 24730 }; 24731 d3.geo.interpolate = function(source, target) { 24732 return d3_geo_interpolate(source[0] * d3_radians, source[1] * d3_radians, target[0] * d3_radians, target[1] * d3_radians); 24733 }; 24734 function d3_geo_interpolate(x0, y0, x1, y1) { 24735 var cy0 = Math.cos(y0), sy0 = Math.sin(y0), cy1 = Math.cos(y1), sy1 = Math.sin(y1), kx0 = cy0 * Math.cos(x0), ky0 = cy0 * Math.sin(x0), kx1 = cy1 * Math.cos(x1), ky1 = cy1 * Math.sin(x1), d = 2 * Math.asin(Math.sqrt(d3_haversin(y1 - y0) + cy0 * cy1 * d3_haversin(x1 - x0))), k = 1 / Math.sin(d); 24736 var interpolate = d ? function(t) { 24737 var B = Math.sin(t *= d) * k, A = Math.sin(d - t) * k, x = A * kx0 + B * kx1, y = A * ky0 + B * ky1, z = A * sy0 + B * sy1; 24738 return [ Math.atan2(y, x) * d3_degrees, Math.atan2(z, Math.sqrt(x * x + y * y)) * d3_degrees ]; 24739 } : function() { 24740 return [ x0 * d3_degrees, y0 * d3_degrees ]; 24741 }; 24742 interpolate.distance = d; 24743 return interpolate; 24744 } 24745 d3.geo.length = function(object) { 24746 d3_geo_lengthSum = 0; 24747 d3.geo.stream(object, d3_geo_length); 24748 return d3_geo_lengthSum; 24749 }; 24750 var d3_geo_lengthSum; 24751 var d3_geo_length = { 24752 sphere: d3_noop, 24753 point: d3_noop, 24754 lineStart: d3_geo_lengthLineStart, 24755 lineEnd: d3_noop, 24756 polygonStart: d3_noop, 24757 polygonEnd: d3_noop 24758 }; 24759 function d3_geo_lengthLineStart() { 24760 var λ0, sinÏ0, cosÏ0; 24761 d3_geo_length.point = function(λ, Ï) { 24762 λ0 = λ * d3_radians, sinÏ0 = Math.sin(Ï *= d3_radians), cosÏ0 = Math.cos(Ï); 24763 d3_geo_length.point = nextPoint; 24764 }; 24765 d3_geo_length.lineEnd = function() { 24766 d3_geo_length.point = d3_geo_length.lineEnd = d3_noop; 24767 }; 24768 function nextPoint(λ, Ï) { 24769 var sinÏ = Math.sin(Ï *= d3_radians), cosÏ = Math.cos(Ï), t = abs((λ *= d3_radians) - λ0), cosÎλ = Math.cos(t); 24770 d3_geo_lengthSum += Math.atan2(Math.sqrt((t = cosÏ * Math.sin(t)) * t + (t = cosÏ0 * sinÏ - sinÏ0 * cosÏ * cosÎλ) * t), sinÏ0 * sinÏ + cosÏ0 * cosÏ * cosÎλ);
24771 λ0 = λ, sinÏ0 = sinÏ, cosÏ0 = cosÏ; 24772 } 24773 } 24774 function d3_geo_azimuthal(scale, angle) { 24775 function azimuthal(λ, Ï) { 24776 var cosλ = Math.cos(λ), cosÏ = Math.cos(Ï), k = scale(cosλ * cosÏ); 24777 return [ k * cosÏ * Math.sin(λ), k * Math.sin(Ï) ]; 24778 } 24779 azimuthal.invert = function(x, y) { 24780 var Ï = Math.sqrt(x * x + y * y), c = angle(Ï), sinc = Math.sin(c), cosc = Math.cos(c); 24781 return [ Math.atan2(x * sinc, Ï * cosc), Math.asin(Ï && y * sinc / Ï) ]; 24782 }; 24783 return azimuthal; 24784 } 24785 var d3_geo_azimuthalEqualArea = d3_geo_azimuthal(function(cosλcosÏ) { 24786 return Math.sqrt(2 / (1 + cosλcosÏ)); 24787 }, function(Ï) { 24788 return 2 * Math.asin(Ï / 2); 24789 }); 24790 (d3.geo.azimuthalEqualArea = function() { 24791 return d3_geo_projection(d3_geo_azimuthalEqualArea); 24792 }).raw = d3_geo_azimuthalEqualArea; 24793 var d3_geo_azimuthalEquidistant = d3_geo_azimuthal(function(cosλcosÏ) { 24794 var c = Math.acos(cosλcosÏ); 24795 return c && c / Math.sin(c); 24796 }, d3_identity); 24797 (d3.geo.azimuthalEquidistant = function() { 24798 return d3_geo_projection(d3_geo_azimuthalEquidistant); 24799 }).raw = d3_geo_azimuthalEquidistant; 24800 function d3_geo_conicConformal(Ï0, Ï1) { 24801 var cosÏ0 = Math.cos(Ï0), t = function(Ï) { 24802 return Math.tan(Ï / 4 + Ï / 2); 24803 }, n = Ï0 === Ï1 ? Math.sin(Ï0) : Math.log(cosÏ0 / Math.cos(Ï1)) / Math.log(t(Ï1) / t(Ï0)), F = cosÏ0 * Math.pow(t(Ï0), n) / n; 24804 if (!n) return d3_geo_mercator; 24805 function forward(λ, Ï) { 24806 if (F > 0) { 24807 if (Ï < -halfÏ + ε) Ï = -halfÏ + ε; 24808 } else { 24809 if (Ï > halfÏ - ε) Ï = halfÏ - ε; 24810 } 24811 var Ï = F / Math.pow(t(Ï), n); 24812 return [ Ï * Math.sin(n * λ), F - Ï * Math.cos(n * λ) ]; 24813 } 24814 forward.invert = function(x, y) { 24815 var Ï0_y = F - y, Ï = d3_sgn(n) * Math.sqrt(x * x + Ï0_y * Ï0_y); 24816 return [ Math.atan2(x, Ï0_y) / n, 2 * Math.atan(Math.pow(F / Ï, 1 / n)) - halfÏ ]; 24817 }; 24818 return forward; 24819 } 24820 (d3.geo.conicConformal = function() { 24821 return d3_geo_conic(d3_geo_conicConformal); 24822 }).raw = d3_geo_conicConformal; 24823 function d3_geo_conicEquidistant(Ï0, Ï1) { 24824 var cosÏ0 = Math.cos(Ï0), n = Ï0 === Ï1 ? Math.sin(Ï0) : (cosÏ0 - Math.cos(Ï1)) / (Ï1 - Ï0), G = cosÏ0 / n + Ï0; 24825 if (abs(n) < ε) return d3_geo_equirectangular; 24826 function forward(λ, Ï) { 24827 var Ï = G - Ï; 24828 return [ Ï * Math.sin(n * λ), G - Ï * Math.cos(n * λ) ]; 24829 } 24830 forward.invert = function(x, y) { 24831 var Ï0_y = G - y; 24832 return [ Math.atan2(x, Ï0_y) / n, G - d3_sgn(n) * Math.sqrt(x * x + Ï0_y * Ï0_y) ]; 24833 }; 24834 return forward; 24835 } 24836 (d3.geo.conicEquidistant = function() { 24837 return d3_geo_conic(d3_geo_conicEquidistant); 24838 }).raw = d3_geo_conicEquidistant; 24839 var d3_geo_gnomonic = d3_geo_azimuthal(function(cosλcosÏ) { 24840 return 1 / cosλcosÏ; 24841 }, Math.atan); 24842 (d3.geo.gnomonic = function() { 24843 return d3_geo_projection(d3_geo_gnomonic); 24844 }).raw = d3_geo_gnomonic; 24845 function d3_geo_mercator(λ, Ï) { 24846 return [ λ, Math.log(Math.tan(Ï / 4 + Ï / 2)) ]; 24847 } 24848 d3_geo_mercator.invert = function(x, y) { 24849 return [ x, 2 * Math.atan(Math.exp(y)) - halfÏ ]; 24850 }; 24851 function d3_geo_mercatorProjection(project) { 24852 var m = d3_geo_projection(project), scale = m.scale, translate = m.translate, clipExtent = m.clipExtent, clipAuto; 24853 m.scale = function() { 24854 var v = scale.apply(m, arguments); 24855 return v === m ? clipAuto ? m.clipExtent(null) : m : v; 24856 }; 24857 m.translate = function() { 24858 var v = translate.apply(m, arguments); 24859 return v === m ? clipAuto ? m.clipExtent(null) : m : v; 24860 }; 24861 m.clipExtent = function(_) { 24862 var v = clipExtent.apply(m, arguments); 24863 if (v === m) { 24864 if (clipAuto = _ == null) { 24865 var k = Ï * scale(), t = translate(); 24866 clipExtent([ [ t[0] - k, t[1] - k ], [ t[0] + k, t[1] + k ] ]); 24867 } 24868 } else if (clipAuto) { 24869 v = null; 24870 } 24871 return v; 24872 }; 24873 return m.clipExtent(null); 24874 } 24875 (d3.geo.mercator = function() { 24876 return d3_geo_mercatorProjection(d3_geo_mercator); 24877 }).raw = d3_geo_mercator; 24878 var d3_geo_orthographic = d3_geo_azimuthal(function() { 24879 return 1; 24880 }, Math.asin); 24881 (d3.geo.orthographic = function() { 24882 return d3_geo_projection(d3_geo_orthographic); 24883 }).raw = d3_geo_orthographic; 24884 var d3_geo_stereographic = d3_geo_azimuthal(function(cosλcosÏ) { 24885 return 1 / (1 + cosλcosÏ); 24886 }, function(Ï) { 24887 return 2 * Math.atan(Ï); 24888 }); 24889 (d3.geo.stereographic = function() { 24890 return d3_geo_projection(d3_geo_stereographic); 24891 }).raw = d3_geo_stereographic; 24892 function d3_geo_transverseMercator(λ, Ï) { 24893 return [ Math.log(Math.tan(Ï / 4 + Ï / 2)), -λ ]; 24894 } 24895 d3_geo_transverseMercator.invert = function(x, y) { 24896 return [ -y, 2 * Math.atan(Math.exp(x)) - halfÏ ]; 24897 }; 24898 (d3.geo.transverseMercator = function() { 24899 var projection = d3_geo_mercatorProjection(d3_geo_transverseMercator), center = projection.center, rotate = projection.rotate; 24900 projection.center = function(_) { 24901 return _ ? center([ -_[1], _[0] ]) : (_ = center(), [ _[1], -_[0] ]); 24902 }; 24903 projection.rotate = function(_) { 24904 return _ ? rotate([ _[0], _[1], _.length > 2 ? _[2] + 90 : 90 ]) : (_ = rotate(), 24905 [ _[0], _[1], _[2] - 90 ]); 24906 }; 24907 return rotate([ 0, 0, 90 ]); 24908 }).raw = d3_geo_transverseMercator; 24909 d3.geom = {}; 24910 function d3_geom_pointX(d) { 24911 return d[0]; 24912 } 24913 function d3_geom_pointY(d) { 24914 return d[1]; 24915 } 24916 d3.geom.hull = function(vertices) { 24917 var x = d3_geom_pointX, y = d3_geom_pointY; 24918 if (arguments.length) return hull(vertices); 24919 function hull(data) { 24920 if (data.length < 3) return []; 24921 var fx = d3_functor(x), fy = d3_functor(y), i, n = data.length, points = [], flippedPoints = []; 24922 for (i = 0; i < n; i++) { 24923 points.push([ +fx.call(this, data[i], i), +fy.call(this, data[i], i), i ]); 24924 } 24925 points.sort(d3_geom_hullOrder); 24926 for (i = 0; i < n; i++) flippedPoints.push([ points[i][0], -points[i][1] ]); 24927 var upper = d3_geom_hullUpper(points), lower = d3_geom_hullUpper(flippedPoints); 24928 var skipLeft = lower[0] === upper[0], skipRight = lower[lower.length - 1] === upper[upper.length - 1], pol
vendor: 23,510 bytes, lines 24928-25623
24928ygon = []; 24929 for (i = upper.length - 1; i >= 0; --i) polygon.push(data[points[upper[i]][2]]); 24930 for (i = +skipLeft; i < lower.length - skipRight; ++i) polygon.push(data[points[lower[i]][2]]); 24931 return polygon; 24932 } 24933 hull.x = function(_) { 24934 return arguments.length ? (x = _, hull) : x; 24935 }; 24936 hull.y = function(_) { 24937 return arguments.length ? (y = _, hull) : y; 24938 }; 24939 return hull; 24940 }; 24941 function d3_geom_hullUpper(points) { 24942 var n = points.length, hull = [ 0, 1 ], hs = 2; 24943 for (var i = 2; i < n; i++) { 24944 while (hs > 1 && d3_cross2d(points[hull[hs - 2]], points[hull[hs - 1]], points[i]) <= 0) --hs; 24945 hull[hs++] = i; 24946 } 24947 return hull.slice(0, hs); 24948 } 24949 function d3_geom_hullOrder(a, b) { 24950 return a[0] - b[0] || a[1] - b[1]; 24951 } 24952 d3.geom.polygon = function(coordinates) { 24953 d3_subclass(coordinates, d3_geom_polygonPrototype); 24954 return coordinates; 24955 }; 24956 var d3_geom_polygonPrototype = d3.geom.polygon.prototype = []; 24957 d3_geom_polygonPrototype.area = function() { 24958 var i = -1, n = this.length, a, b = this[n - 1], area = 0; 24959 while (++i < n) { 24960 a = b; 24961 b = this[i]; 24962 area += a[1] * b[0] - a[0] * b[1]; 24963 } 24964 return area * .5; 24965 }; 24966 d3_geom_polygonPrototype.centroid = function(k) { 24967 var i = -1, n = this.length, x = 0, y = 0, a, b = this[n - 1], c; 24968 if (!arguments.length) k = -1 / (6 * this.area()); 24969 while (++i < n) { 24970 a = b; 24971 b = this[i]; 24972 c = a[0] * b[1] - b[0] * a[1]; 24973 x += (a[0] + b[0]) * c; 24974 y += (a[1] + b[1]) * c; 24975 } 24976 return [ x * k, y * k ]; 24977 }; 24978 d3_geom_polygonPrototype.clip = function(subject) { 24979 var input, closed = d3_geom_polygonClosed(subject), i = -1, n = this.length - d3_geom_polygonClosed(this), j, m, a = this[n - 1], b, c, d; 24980 while (++i < n) { 24981 input = subject.slice(); 24982 subject.length = 0; 24983 b = this[i]; 24984 c = input[(m = input.length - closed) - 1]; 24985 j = -1; 24986 while (++j < m) { 24987 d = input[j]; 24988 if (d3_geom_polygonInside(d, a, b)) { 24989 if (!d3_geom_polygonInside(c, a, b)) { 24990 subject.push(d3_geom_polygonIntersect(c, d, a, b)); 24991 } 24992 subject.push(d); 24993 } else if (d3_geom_polygonInside(c, a, b)) { 24994 subject.push(d3_geom_polygonIntersect(c, d, a, b)); 24995 } 24996 c = d; 24997 } 24998 if (closed) subject.push(subject[0]); 24999 a = b; 25000 } 25001 return subject; 25002 }; 25003 function d3_geom_polygonInside(p, a, b) { 25004 return (b[0] - a[0]) * (p[1] - a[1]) < (b[1] - a[1]) * (p[0] - a[0]); 25005 } 25006 function d3_geom_polygonIntersect(c, d, a, b) { 25007 var x1 = c[0], x3 = a[0], x21 = d[0] - x1, x43 = b[0] - x3, y1 = c[1], y3 = a[1], y21 = d[1] - y1, y43 = b[1] - y3, ua = (x43 * (y1 - y3) - y43 * (x1 - x3)) / (y43 * x21 - x43 * y21); 25008 return [ x1 + ua * x21, y1 + ua * y21 ]; 25009 } 25010 function d3_geom_polygonClosed(coordinates) { 25011 var a = coordinates[0], b = coordinates[coordinates.length - 1]; 25012 return !(a[0] - b[0] || a[1] - b[1]); 25013 } 25014 var d3_geom_voronoiEdges, d3_geom_voronoiCells, d3_geom_voronoiBeaches, d3_geom_voronoiBeachPool = [], d3_geom_voronoiFirstCircle, d3_geom_voronoiCircles, d3_geom_voronoiCirclePool = []; 25015 function d3_geom_voronoiBeach() { 25016 d3_geom_voronoiRedBlackNode(this); 25017 this.edge = this.site = this.circle = null; 25018 } 25019 function d3_geom_voronoiCreateBeach(site) { 25020 var beach = d3_geom_voronoiBeachPool.pop() || new d3_geom_voronoiBeach(); 25021 beach.site = site; 25022 return beach; 25023 } 25024 function d3_geom_voronoiDetachBeach(beach) { 25025 d3_geom_voronoiDetachCircle(beach); 25026 d3_geom_voronoiBeaches.remove(beach); 25027 d3_geom_voronoiBeachPool.push(beach); 25028 d3_geom_voronoiRedBlackNode(beach); 25029 } 25030 function d3_geom_voronoiRemoveBeach(beach) { 25031 var circle = beach.circle, x = circle.x, y = circle.cy, vertex = { 25032 x: x, 25033 y: y 25034 }, previous = beach.P, next = beach.N, disappearing = [ beach ]; 25035 d3_geom_voronoiDetachBeach(beach); 25036 var lArc = previous; 25037 while (lArc.circle && abs(x - lArc.circle.x) < ε && abs(y - lArc.circle.cy) < ε) { 25038 previous = lArc.P; 25039 disappearing.unshift(lArc); 25040 d3_geom_voronoiDetachBeach(lArc); 25041 lArc = previous; 25042 } 25043 disappearing.unshift(lArc); 25044 d3_geom_voronoiDetachCircle(lArc); 25045 var rArc = next; 25046 while (rArc.circle && abs(x - rArc.circle.x) < ε && abs(y - rArc.circle.cy) < ε) { 25047 next = rArc.N; 25048 disappearing.push(rArc); 25049 d3_geom_voronoiDetachBeach(rArc); 25050 rArc = next; 25051 } 25052 disappearing.push(rArc); 25053 d3_geom_voronoiDetachCircle(rArc); 25054 var nArcs = disappearing.length, iArc; 25055 for (iArc = 1; iArc < nArcs; ++iArc) { 25056 rArc = disappearing[iArc]; 25057 lArc = disappearing[iArc - 1]; 25058 d3_geom_voronoiSetEdgeEnd(rArc.edge, lArc.site, rArc.site, vertex); 25059 } 25060 lArc = disappearing[0]; 25061 rArc = disappearing[nArcs - 1]; 25062 rArc.edge = d3_geom_voronoiCreateEdge(lArc.site, rArc.site, null, vertex); 25063 d3_geom_voronoiAttachCircle(lArc); 25064 d3_geom_voronoiAttachCircle(rArc); 25065 } 25066 function d3_geom_voronoiAddBeach(site) { 25067 var x = site.x, directrix = site.y, lArc, rArc, dxl, dxr, node = d3_geom_voronoiBeaches._; 25068 while (node) { 25069 dxl = d3_geom_voronoiLeftBreakPoint(node, directrix) - x; 25070 if (dxl > ε) node = node.L; else { 25071 dxr = x - d3_geom_voronoiRightBreakPoint(node, directrix); 25072 if (dxr > ε) { 25073 if (!node.R) { 25074 lArc = node; 25075 break; 25076 } 25077 node = node.R; 25078 } else { 25079 if (dxl > -ε) { 25080 lArc = node.P; 25081 rArc = node; 25082 } else if (dxr > -ε) { 25083 lArc = node; 25084 rArc = node.N; 25085 } else { 25086 lArc = rArc = node; 25087 } 25088 break; 25089 } 25090 } 25091 } 25092 var newArc = d3_geom_voronoiCreateBeach(site); 25093 d3_geom_voronoiBeaches.insert(lArc, newArc); 25094 if (!lArc && !rArc) return; 25095 if (lArc === rArc) { 25096 d3_geom_voronoiDetachCircle(lArc); 25097 rArc = d3_geom_voronoiCreateBeach(lArc.site); 25098 d3_geom_voronoiBeaches.insert(newArc, rArc); 25099 newArc.edge = rArc.edge = d3_geom_voronoiCreateEdge(lArc.site, newArc.site); 25100 d3_geom_voronoiAttachCircle(lArc); 25101 d3_geom_voronoiAttachCircle(rArc); 25102 return; 25103 } 25104 if (!rArc) { 25105 newArc.edge = d3_geom_voronoiCreateEdge(lArc.site, newArc.site); 25106 return; 25107 } 25108 d3_geom_voronoiDetachCircle(lArc); 25109 d3_geom_voronoiDetachCircle(rArc); 25110 var lSite = lArc.site, ax = lSite.x, ay = lSite.y, bx = site.x - ax, by = site.y - ay, rSite = rArc.site, cx = rSite.x - ax, cy = rSite.y - ay, d = 2 * (bx * cy - by * cx), hb = bx * bx + by * by, hc = cx * cx + cy * cy, vertex = { 25111 x: (cy * hb - by * hc) / d + ax, 25112 y: (bx * hc - cx * hb) / d + ay 25113 }; 25114 d3_geom_voronoiSetEdgeEnd(rArc.edge, lSite, rSite, vertex); 25115 newArc.edge = d3_geom_voronoiCreateEdge(lSite, site, null, vertex); 25116 rArc.edge = d3_geom_voronoiCreateEdge(site, rSite, null, vertex); 25117 d3_geom_voronoiAttachCircle(lArc); 25118 d3_geom_voronoiAttachCircle(rArc); 25119 } 25120 function d3_geom_voronoiLeftBreakPoint(arc, directrix) { 25121 var site = arc.site, rfocx = site.x, rfocy = site.y, pby2 = rfocy - directrix; 25122 if (!pby2) return rfocx; 25123 var lArc = arc.P; 25124 if (!lArc) return -Infinity; 25125 site = lArc.site; 25126 var lfocx = site.x, lfocy = site.y, plby2 = lfocy - directrix; 25127 if (!plby2) return lfocx; 25128 var hl = lfocx - rfocx, aby2 = 1 / pby2 - 1 / plby2, b = hl / plby2; 25129 if (aby2) return (-b + Math.sqrt(b * b - 2 * aby2 * (hl * hl / (-2 * plby2) - lfocy + plby2 / 2 + rfocy - pby2 / 2))) / aby2 + rfocx; 25130 return (rfocx + lfocx) / 2; 25131 } 25132 function d3_geom_voronoiRightBreakPoint(arc, directrix) { 25133 var rArc = arc.N; 25134 if (rArc) return d3_geom_voronoiLeftBreakPoint(rArc, directrix); 25135 var site = arc.site; 25136 return site.y === directrix ? site.x : Infinity; 25137 } 25138 function d3_geom_voronoiCell(site) { 25139 this.site = site; 25140 this.edges = []; 25141 } 25142 d3_geom_voronoiCell.prototype.prepare = function() { 25143 var halfEdges = this.edges, iHalfEdge = halfEdges.length, edge; 25144 while (iHalfEdge--) { 25145 edge = halfEdges[iHalfEdge].edge; 25146 if (!edge.b || !edge.a) halfEdges.splice(iHalfEdge, 1); 25147 } 25148 halfEdges.sort(d3_geom_voronoiHalfEdgeOrder); 25149 return halfEdges.length; 25150 }; 25151 function d3_geom_voronoiCloseCells(extent) { 25152 var x0 = extent[0][0], x1 = extent[1][0], y0 = extent[0][1], y1 = extent[1][1], x2, y2, x3, y3, cells = d3_geom_voronoiCells, iCell = cells.length, cell, iHalfEdge, halfEdges, nHalfEdges, start, end; 25153 while (iCell--) { 25154 cell = cells[iCell]; 25155 if (!cell || !cell.prepare()) continue; 25156 halfEdges = cell.edges; 25157 nHalfEdges = halfEdges.length; 25158 iHalfEdge = 0; 25159 while (iHalfEdge < nHalfEdges) { 25160 end = halfEdges[iHalfEdge].end(), x3 = end.x, y3 = end.y; 25161 start = halfEdges[++iHalfEdge % nHalfEdges].start(), x2 = start.x, y2 = start.y; 25162 if (abs(x3 - x2) > ε || abs(y3 - y2) > ε) { 25163 halfEdges.splice(iHalfEdge, 0, new d3_geom_voronoiHalfEdge(d3_geom_voronoiCreateBorderEdge(cell.site, end, abs(x3 - x0) < ε && y1 - y3 > ε ? { 25164 x: x0, 25165 y: abs(x2 - x0) < ε ? y2 : y1 25166 } : abs(y3 - y1) < ε && x1 - x3 > ε ? { 25167 x: abs(y2 - y1) < ε ? x2 : x1, 25168 y: y1 25169 } : abs(x3 - x1) < ε && y3 - y0 > ε ? { 25170 x: x1, 25171 y: abs(x2 - x1) < ε ? y2 : y0 25172 } : abs(y3 - y0) < ε && x3 - x0 > ε ? { 25173 x: abs(y2 - y0) < ε ? x2 : x0, 25174 y: y0 25175 } : null), cell.site, null)); 25176 ++nHalfEdges; 25177 } 25178 } 25179 } 25180 } 25181 function d3_geom_voronoiHalfEdgeOrder(a, b) { 25182 return b.angle - a.angle; 25183 } 25184 function d3_geom_voronoiCircle() { 25185 d3_geom_voronoiRedBlackNode(this); 25186 this.x = this.y = this.arc = this.site = this.cy = null; 25187 } 25188 function d3_geom_voronoiAttachCircle(arc) { 25189 var lArc = arc.P, rArc = arc.N; 25190 if (!lArc || !rArc) return; 25191 var lSite = lArc.site, cSite = arc.site, rSite = rArc.site; 25192 if (lSite === rSite) return; 25193 var bx = cSite.x, by = cSite.y, ax = lSite.x - bx, ay = lSite.y - by, cx = rSite.x - bx, cy = rSite.y - by; 25194 var d = 2 * (ax * cy - ay * cx); 25195 if (d >= -ε2) return; 25196 var ha = ax * ax + ay * ay, hc = cx * cx + cy * cy, x = (cy * ha - ay * hc) / d, y = (ax * hc - cx * ha) / d, cy = y + by; 25197 var circle = d3_geom_voronoiCirclePool.pop() || new d3_geom_voronoiCircle(); 25198 circle.arc = arc; 25199 circle.site = cSite; 25200 circle.x = x + bx; 25201 circle.y = cy + Math.sqrt(x * x + y * y); 25202 circle.cy = cy; 25203 arc.circle = circle; 25204 var before = null, node = d3_geom_voronoiCircles._; 25205 while (node) { 25206 if (circle.y < node.y || circle.y === node.y && circle.x <= node.x) { 25207 if (node.L) node = node.L; else { 25208 before = node.P; 25209 break; 25210 } 25211 } else { 25212 if (node.R) node = node.R; else { 25213 before = node; 25214 break; 25215 } 25216 } 25217 } 25218 d3_geom_voronoiCircles.insert(before, circle); 25219 if (!before) d3_geom_voronoiFirstCircle = circle; 25220 } 25221 function d3_geom_voronoiDetachCircle(arc) { 25222 var circle = arc.circle; 25223 if (circle) { 25224 if (!circle.P) d3_geom_voronoiFirstCircle = circle.N; 25225 d3_geom_voronoiCircles.remove(circle); 25226 d3_geom_voronoiCirclePool.push(circle); 25227 d3_geom_voronoiRedBlackNode(circle); 25228 arc.circle = null; 25229 } 25230 } 25231 function d3_geom_voronoiClipEdges(extent) { 25232 var edges = d3_geom_voronoiEdges, clip = d3_geom_clipLine(extent[0][0], extent[0][1], extent[1][0], extent[1][1]), i = edges.length, e; 25233 while (i--) { 25234 e = edges[i]; 25235 if (!d3_geom_voronoiConnectEdge(e, extent) || !clip(e) || abs(e.a.x - e.b.x) < ε && abs(e.a.y - e.b.y) < ε) { 25236 e.a = e.b = null; 25237 edges.splice(i, 1); 25238 } 25239 } 25240 } 25241 function d3_geom_voronoiConnectEdge(edge, extent) { 25242 var vb = edge.b; 25243 if (vb) return true; 25244 var va = edge.a, x0 = extent[0][0], x1 = extent[1][0], y0 = extent[0][1], y1 = extent[1][1], lSite = edge.l, rSite = edge.r, lx = lSite.x, ly = lSite.y, rx = rSite.x, ry = rSite.y, fx = (lx + rx) / 2, fy = (ly + ry) / 2, fm, fb; 25245 if (ry === ly) { 25246 if (fx < x0 || fx >= x1) return; 25247 if (lx > rx) { 25248 if (!va) va = { 25249 x: fx, 25250 y: y0 25251 }; else if (va.y >= y1) return; 25252 vb = { 25253 x: fx, 25254 y: y1 25255 }; 25256 } else { 25257 if (!va) va = { 25258 x: fx, 25259 y: y1 25260 }; else if (va.y < y0) return; 25261 vb = { 25262 x: fx, 25263 y: y0 25264 }; 25265 } 25266 } else { 25267 fm = (lx - rx) / (ry - ly); 25268 fb = fy - fm * fx; 25269 if (fm < -1 || fm > 1) { 25270 if (lx > rx) { 25271 if (!va) va = { 25272 x: (y0 - fb) / fm, 25273 y: y0 25274 }; else if (va.y >= y1) return; 25275 vb = { 25276 x: (y1 - fb) / fm, 25277 y: y1 25278 }; 25279 } else { 25280 if (!va) va = { 25281 x: (y1 - fb) / fm, 25282 y: y1 25283 }; else if (va.y < y0) return; 25284 vb = { 25285 x: (y0 - fb) / fm, 25286 y: y0 25287 }; 25288 } 25289 } else { 25290 if (ly < ry) { 25291 if (!va) va = { 25292 x: x0, 25293 y: fm * x0 + fb 25294 }; else if (va.x >= x1) return; 25295 vb = { 25296 x: x1, 25297 y: fm * x1 + fb 25298 }; 25299 } else { 25300 if (!va) va = { 25301 x: x1, 25302 y: fm * x1 + fb 25303 }; else if (va.x < x0) return; 25304 vb = { 25305 x: x0, 25306 y: fm * x0 + fb 25307 }; 25308 } 25309 } 25310 } 25311 edge.a = va; 25312 edge.b = vb; 25313 return true; 25314 } 25315 function d3_geom_voronoiEdge(lSite, rSite) { 25316 this.l = lSite; 25317 this.r = rSite; 25318 this.a = this.b = null; 25319 } 25320 function d3_geom_voronoiCreateEdge(lSite, rSite, va, vb) { 25321 var edge = new d3_geom_voronoiEdge(lSite, rSite); 25322 d3_geom_voronoiEdges.push(edge); 25323 if (va) d3_geom_voronoiSetEdgeEnd(edge, lSite, rSite, va); 25324 if (vb) d3_geom_voronoiSetEdgeEnd(edge, rSite, lSite, vb); 25325 d3_geom_voronoiCells[lSite.i].edges.push(new d3_geom_voronoiHalfEdge(edge, lSite, rSite)); 25326 d3_geom_voronoiCells[rSite.i].edges.push(new d3_geom_voronoiHalfEdge(edge, rSite, lSite)); 25327 return edge; 25328 } 25329 function d3_geom_voronoiCreateBorderEdge(lSite, va, vb) { 25330 var edge = new d3_geom_voronoiEdge(lSite, null); 25331 edge.a = va; 25332 edge.b = vb; 25333 d3_geom_voronoiEdges.push(edge); 25334 return edge; 25335 } 25336 function d3_geom_voronoiSetEdgeEnd(edge, lSite, rSite, vertex) { 25337 if (!edge.a && !edge.b) { 25338 edge.a = vertex; 25339 edge.l = lSite; 25340 edge.r = rSite; 25341 } else if (edge.l === rSite) { 25342 edge.b = vertex; 25343 } else { 25344 edge.a = vertex; 25345 } 25346 } 25347 function d3_geom_voronoiHalfEdge(edge, lSite, rSite) { 25348 var va = edge.a, vb = edge.b; 25349 this.edge = edge; 25350 this.site = lSite; 25351 this.angle = rSite ? Math.atan2(rSite.y - lSite.y, rSite.x - lSite.x) : edge.l === lSite ? Math.atan2(vb.x - va.x, va.y - vb.y) : Math.atan2(va.x - vb.x, vb.y - va.y); 25352 } 25353 d3_geom_voronoiHalfEdge.prototype = { 25354 start: function() { 25355 return this.edge.l === this.site ? this.edge.a : this.edge.b; 25356 }, 25357 end: function() { 25358 return this.edge.l === this.site ? this.edge.b : this.edge.a; 25359 } 25360 }; 25361 function d3_geom_voronoiRedBlackTree() { 25362 this._ = null; 25363 } 25364 function d3_geom_voronoiRedBlackNode(node) { 25365 node.U = node.C = node.L = node.R = node.P = node.N = null; 25366 } 25367 d3_geom_voronoiRedBlackTree.prototype = { 25368 insert: function(after, node) { 25369 var parent, grandpa, uncle; 25370 if (after) { 25371 node.P = after; 25372 node.N = after.N; 25373 if (after.N) after.N.P = node; 25374 after.N = node; 25375 if (after.R) { 25376 after = after.R; 25377 while (after.L) after = after.L; 25378 after.L = node; 25379 } else { 25380 after.R = node; 25381 } 25382 parent = after; 25383 } else if (this._) { 25384 after = d3_geom_voronoiRedBlackFirst(this._); 25385 node.P = null; 25386 node.N = after; 25387 after.P = after.L = node; 25388 parent = after; 25389 } else { 25390 node.P = node.N = null; 25391 this._ = node; 25392 parent = null; 25393 } 25394 node.L = node.R = null; 25395 node.U = parent; 25396 node.C = true; 25397 after = node; 25398 while (parent && parent.C) { 25399 grandpa = parent.U; 25400 if (parent === grandpa.L) { 25401 uncle = grandpa.R; 25402 if (uncle && uncle.C) { 25403 parent.C = uncle.C = false; 25404 grandpa.C = true; 25405 after = grandpa; 25406 } else { 25407 if (after === parent.R) { 25408 d3_geom_voronoiRedBlackRotateLeft(this, parent); 25409 after = parent; 25410 parent = after.U; 25411 } 25412 parent.C = false; 25413 grandpa.C = true; 25414 d3_geom_voronoiRedBlackRotateRight(this, grandpa); 25415 } 25416 } else { 25417 uncle = grandpa.L; 25418 if (uncle && uncle.C) { 25419 parent.C = uncle.C = false; 25420 grandpa.C = true; 25421 after = grandpa; 25422 } else { 25423 if (after === parent.L) { 25424 d3_geom_voronoiRedBlackRotateRight(this, parent); 25425 after = parent; 25426 parent = after.U; 25427 } 25428 parent.C = false; 25429 grandpa.C = true; 25430 d3_geom_voronoiRedBlackRotateLeft(this, grandpa); 25431 } 25432 } 25433 parent = after.U; 25434 } 25435 this._.C = false; 25436 }, 25437 remove: function(node) { 25438 if (node.N) node.N.P = node.P; 25439 if (node.P) node.P.N = node.N; 25440 node.N = node.P = null; 25441 var parent = node.U, sibling, left = node.L, right = node.R, next, red; 25442 if (!left) next = right; else if (!right) next = left; else next = d3_geom_voronoiRedBlackFirst(right); 25443 if (parent) { 25444 if (parent.L === node) parent.L = next; else parent.R = next; 25445 } else { 25446 this._ = next; 25447 } 25448 if (left && right) { 25449 red = next.C; 25450 next.C = node.C; 25451 next.L = left; 25452 left.U = next; 25453 if (next !== right) { 25454 parent = next.U; 25455 next.U = node.U; 25456 node = next.R; 25457 parent.L = node; 25458 next.R = right; 25459 right.U = next; 25460 } else { 25461 next.U = parent; 25462 parent = next; 25463 node = next.R; 25464 } 25465 } else { 25466 red = node.C; 25467 node = next; 25468 } 25469 if (node) node.U = parent; 25470 if (red) return; 25471 if (node && node.C) { 25472 node.C = false; 25473 return; 25474 } 25475 do { 25476 if (node === this._) break; 25477 if (node === parent.L) { 25478 sibling = parent.R; 25479 if (sibling.C) { 25480 sibling.C = false; 25481 parent.C = true; 25482 d3_geom_voronoiRedBlackRotateLeft(this, parent); 25483 sibling = parent.R; 25484 } 25485 if (sibling.L && sibling.L.C || sibling.R && sibling.R.C) { 25486 if (!sibling.R || !sibling.R.C) { 25487 sibling.L.C = false; 25488 sibling.C = true; 25489 d3_geom_voronoiRedBlackRotateRight(this, sibling); 25490 sibling = parent.R; 25491 } 25492 sibling.C = parent.C; 25493 parent.C = sibling.R.C = false; 25494 d3_geom_voronoiRedBlackRotateLeft(this, parent); 25495 node = this._; 25496 break; 25497 } 25498 } else { 25499 sibling = parent.L; 25500 if (sibling.C) { 25501 sibling.C = false; 25502 parent.C = true; 25503 d3_geom_voronoiRedBlackRotateRight(this, parent); 25504 sibling = parent.L; 25505 } 25506 if (sibling.L && sibling.L.C || sibling.R && sibling.R.C) { 25507 if (!sibling.L || !sibling.L.C) { 25508 sibling.R.C = false; 25509 sibling.C = true; 25510 d3_geom_voronoiRedBlackRotateLeft(this, sibling); 25511 sibling = parent.L; 25512 } 25513 sibling.C = parent.C; 25514 parent.C = sibling.L.C = false; 25515 d3_geom_voronoiRedBlackRotateRight(this, parent); 25516 node = this._; 25517 break; 25518 } 25519 } 25520 sibling.C = true; 25521 node = parent; 25522 parent = parent.U; 25523 } while (!node.C); 25524 if (node) node.C = false; 25525 } 25526 }; 25527 function d3_geom_voronoiRedBlackRotateLeft(tree, node) { 25528 var p = node, q = node.R, parent = p.U; 25529 if (parent) { 25530 if (parent.L === p) parent.L = q; else parent.R = q; 25531 } else { 25532 tree._ = q; 25533 } 25534 q.U = parent; 25535 p.U = q; 25536 p.R = q.L; 25537 if (p.R) p.R.U = p; 25538 q.L = p; 25539 } 25540 function d3_geom_voronoiRedBlackRotateRight(tree, node) { 25541 var p = node, q = node.L, parent = p.U; 25542 if (parent) { 25543 if (parent.L === p) parent.L = q; else parent.R = q; 25544 } else { 25545 tree._ = q; 25546 } 25547 q.U = parent; 25548 p.U = q; 25549 p.L = q.R; 25550 if (p.L) p.L.U = p; 25551 q.R = p; 25552 } 25553 function d3_geom_voronoiRedBlackFirst(node) { 25554 while (node.L) node = node.L; 25555 return node; 25556 } 25557 function d3_geom_voronoi(sites, bbox) { 25558 var site = sites.sort(d3_geom_voronoiVertexOrder).pop(), x0, y0, circle; 25559 d3_geom_voronoiEdges = []; 25560 d3_geom_voronoiCells = new Array(sites.length); 25561 d3_geom_voronoiBeaches = new d3_geom_voronoiRedBlackTree(); 25562 d3_geom_voronoiCircles = new d3_geom_voronoiRedBlackTree(); 25563 while (true) { 25564 circle = d3_geom_voronoiFirstCircle; 25565 if (site && (!circle || site.y < circle.y || site.y === circle.y && site.x < circle.x)) { 25566 if (site.x !== x0 || site.y !== y0) { 25567 d3_geom_voronoiCells[site.i] = new d3_geom_voronoiCell(site); 25568 d3_geom_voronoiAddBeach(site); 25569 x0 = site.x, y0 = site.y; 25570 } 25571 site = sites.pop(); 25572 } else if (circle) { 25573 d3_geom_voronoiRemoveBeach(circle.arc); 25574 } else { 25575 break; 25576 } 25577 } 25578 if (bbox) d3_geom_voronoiClipEdges(bbox), d3_geom_voronoiCloseCells(bbox); 25579 var diagram = { 25580 cells: d3_geom_voronoiCells, 25581 edges: d3_geom_voronoiEdges 25582 }; 25583 d3_geom_voronoiBeaches = d3_geom_voronoiCircles = d3_geom_voronoiEdges = d3_geom_voronoiCells = null; 25584 return diagram; 25585 } 25586 function d3_geom_voronoiVertexOrder(a, b) { 25587 return b.y - a.y || b.x - a.x; 25588 } 25589 d3.geom.voronoi = function(points) { 25590 var x = d3_geom_pointX, y = d3_geom_pointY, fx = x, fy = y, clipExtent = d3_geom_voronoiClipExtent; 25591 if (points) return voronoi(points); 25592 function voronoi(data) { 25593 var polygons = new Array(data.length), x0 = clipExtent[0][0], y0 = clipExtent[0][1], x1 = clipExtent[1][0], y1 = clipExtent[1][1]; 25594 d3_geom_voronoi(sites(data), clipExtent).cells.forEach(function(cell, i) { 25595 var edges = cell.edges, site = cell.site, polygon = polygons[i] = edges.length ? edges.map(function(e) { 25596 var s = e.start(); 25597 return [ s.x, s.y ]; 25598 }) : site.x >= x0 && site.x <= x1 && site.y >= y0 && site.y <= y1 ? [ [ x0, y1 ], [ x1, y1 ], [ x1, y0 ], [ x0, y0 ] ] : []; 25599 polygon.point = data[i]; 25600 }); 25601 return polygons; 25602 } 25603 function sites(data) { 25604 return data.map(function(d, i) { 25605 return { 25606 x: Math.round(fx(d, i) / ε) * ε, 25607 y: Math.round(fy(d, i) / ε) * ε, 25608 i: i 25609 }; 25610 }); 25611 } 25612 voronoi.links = function(data) { 25613 return d3_geom_voronoi(sites(data)).edges.filter(function(edge) { 25614 return edge.l && edge.r; 25615 }).map(function(edge) { 25616 return { 25617 source: data[edge.l.i], 25618 target: data[edge.r.i] 25619 }; 25620 }); 25621 }; 25622 voronoi.triangles = function(data) { 25623 var triangles = [];
vendor: 5,984 bytes, lines 25624-25791
25624 d3_geom_voronoi(sites(data)).cells.forEach(function(cell, i) { 25625 var site = cell.site, edges = cell.edges.sort(d3_geom_voronoiHalfEdgeOrder), j = -1, m = edges.length, e0, s0, e1 = edges[m - 1].edge, s1 = e1.l === site ? e1.r : e1.l; 25626 while (++j < m) { 25627 e0 = e1; 25628 s0 = s1; 25629 e1 = edges[j].edge; 25630 s1 = e1.l === site ? e1.r : e1.l; 25631 if (i < s0.i && i < s1.i && d3_geom_voronoiTriangleArea(site, s0, s1) < 0) { 25632 triangles.push([ data[i], data[s0.i], data[s1.i] ]); 25633 } 25634 } 25635 }); 25636 return triangles; 25637 }; 25638 voronoi.x = function(_) { 25639 return arguments.length ? (fx = d3_functor(x = _), voronoi) : x; 25640 }; 25641 voronoi.y = function(_) { 25642 return arguments.length ? (fy = d3_functor(y = _), voronoi) : y; 25643 }; 25644 voronoi.clipExtent = function(_) { 25645 if (!arguments.length) return clipExtent === d3_geom_voronoiClipExtent ? null : clipExtent; 25646 clipExtent = _ == null ? d3_geom_voronoiClipExtent : _; 25647 return voronoi; 25648 }; 25649 voronoi.size = function(_) { 25650 if (!arguments.length) return clipExtent === d3_geom_voronoiClipExtent ? null : clipExtent && clipExtent[1]; 25651 return voronoi.clipExtent(_ && [ [ 0, 0 ], _ ]); 25652 }; 25653 return voronoi; 25654 }; 25655 var d3_geom_voronoiClipExtent = [ [ -1e6, -1e6 ], [ 1e6, 1e6 ] ]; 25656 function d3_geom_voronoiTriangleArea(a, b, c) { 25657 return (a.x - c.x) * (b.y - a.y) - (a.x - b.x) * (c.y - a.y); 25658 } 25659 d3.geom.delaunay = function(vertices) { 25660 return d3.geom.voronoi().triangles(vertices); 25661 }; 25662 d3.geom.quadtree = function(points, x1, y1, x2, y2) { 25663 var x = d3_geom_pointX, y = d3_geom_pointY, compat; 25664 if (compat = arguments.length) { 25665 x = d3_geom_quadtreeCompatX; 25666 y = d3_geom_quadtreeCompatY; 25667 if (compat === 3) { 25668 y2 = y1; 25669 x2 = x1; 25670 y1 = x1 = 0; 25671 } 25672 return quadtree(points); 25673 } 25674 function quadtree(data) { 25675 var d, fx = d3_functor(x), fy = d3_functor(y), xs, ys, i, n, x1_, y1_, x2_, y2_; 25676 if (x1 != null) { 25677 x1_ = x1, y1_ = y1, x2_ = x2, y2_ = y2; 25678 } else { 25679 x2_ = y2_ = -(x1_ = y1_ = Infinity); 25680 xs = [], ys = []; 25681 n = data.length; 25682 if (compat) for (i = 0; i < n; ++i) { 25683 d = data[i]; 25684 if (d.x < x1_) x1_ = d.x; 25685 if (d.y < y1_) y1_ = d.y; 25686 if (d.x > x2_) x2_ = d.x; 25687 if (d.y > y2_) y2_ = d.y; 25688 xs.push(d.x); 25689 ys.push(d.y); 25690 } else for (i = 0; i < n; ++i) { 25691 var x_ = +fx(d = data[i], i), y_ = +fy(d, i); 25692 if (x_ < x1_) x1_ = x_; 25693 if (y_ < y1_) y1_ = y_; 25694 if (x_ > x2_) x2_ = x_; 25695 if (y_ > y2_) y2_ = y_; 25696 xs.push(x_); 25697 ys.push(y_); 25698 } 25699 } 25700 var dx = x2_ - x1_, dy = y2_ - y1_; 25701 if (dx > dy) y2_ = y1_ + dx; else x2_ = x1_ + dy; 25702 function insert(n, d, x, y, x1, y1, x2, y2) { 25703 if (isNaN(x) || isNaN(y)) return; 25704 if (n.leaf) { 25705 var nx = n.x, ny = n.y; 25706 if (nx != null) { 25707 if (abs(nx - x) + abs(ny - y) < .01) { 25708 insertChild(n, d, x, y, x1, y1, x2, y2); 25709 } else { 25710 var nPoint = n.point; 25711 n.x = n.y = n.point = null; 25712 insertChild(n, nPoint, nx, ny, x1, y1, x2, y2); 25713 insertChild(n, d, x, y, x1, y1, x2, y2); 25714 } 25715 } else { 25716 n.x = x, n.y = y, n.point = d; 25717 } 25718 } else { 25719 insertChild(n, d, x, y, x1, y1, x2, y2); 25720 } 25721 } 25722 function insertChild(n, d, x, y, x1, y1, x2, y2) { 25723 var sx = (x1 + x2) * .5, sy = (y1 + y2) * .5, right = x >= sx, bottom = y >= sy, i = (bottom << 1) + right; 25724 n.leaf = false; 25725 n = n.nodes[i] || (n.nodes[i] = d3_geom_quadtreeNode()); 25726 if (right) x1 = sx; else x2 = sx; 25727 if (bottom) y1 = sy; else y2 = sy; 25728 insert(n, d, x, y, x1, y1, x2, y2); 25729 } 25730 var root = d3_geom_quadtreeNode(); 25731 root.add = function(d) { 25732 insert(root, d, +fx(d, ++i), +fy(d, i), x1_, y1_, x2_, y2_); 25733 }; 25734 root.visit = function(f) { 25735 d3_geom_quadtreeVisit(f, root, x1_, y1_, x2_, y2_); 25736 }; 25737 i = -1; 25738 if (x1 == null) { 25739 while (++i < n) { 25740 insert(root, data[i], xs[i], ys[i], x1_, y1_, x2_, y2_); 25741 } 25742 --i; 25743 } else data.forEach(root.add); 25744 xs = ys = data = d = null; 25745 return root; 25746 } 25747 quadtree.x = function(_) { 25748 return arguments.length ? (x = _, quadtree) : x; 25749 }; 25750 quadtree.y = function(_) { 25751 return arguments.length ? (y = _, quadtree) : y; 25752 }; 25753 quadtree.extent = function(_) { 25754 if (!arguments.length) return x1 == null ? null : [ [ x1, y1 ], [ x2, y2 ] ]; 25755 if (_ == null) x1 = y1 = x2 = y2 = null; else x1 = +_[0][0], y1 = +_[0][1], x2 = +_[1][0], 25756 y2 = +_[1][1]; 25757 return quadtree; 25758 }; 25759 quadtree.size = function(_) { 25760 if (!arguments.length) return x1 == null ? null : [ x2 - x1, y2 - y1 ]; 25761 if (_ == null) x1 = y1 = x2 = y2 = null; else x1 = y1 = 0, x2 = +_[0], y2 = +_[1]; 25762 return quadtree; 25763 }; 25764 return quadtree; 25765 }; 25766 function d3_geom_quadtreeCompatX(d) { 25767 return d.x; 25768 } 25769 function d3_geom_quadtreeCompatY(d) { 25770 return d.y; 25771 } 25772 function d3_geom_quadtreeNode() { 25773 return { 25774 leaf: true, 25775 nodes: [], 25776 point: null, 25777 x: null, 25778 y: null 25779 }; 25780 } 25781 function d3_geom_quadtreeVisit(f, node, x1, y1, x2, y2) { 25782 if (!f(node, x1, y1, x2, y2)) { 25783 var sx = (x1 + x2) * .5, sy = (y1 + y2) * .5, children = node.nodes; 25784 if (children[0]) d3_geom_quadtreeVisit(f, children[0], x1, y1, sx, sy); 25785 if (children[1]) d3_geom_quadtreeVisit(f, children[1], sx, y1, x2, sy); 25786 if (children[2]) d3_geom_quadtreeVisit(f, children[2], x1, sy, sx, y2); 25787 if (children[3]) d3_geom_quadtreeVisit(f, children[3], sx, sy, x2, y2); 25788 } 25789 } 25790 d3.interpolateRgb = d3_interpolateRgb; 25791 function d3_interpolateRgb(a, b) {
vendor: 13,311 bytes, lines 25792-26225
25792 a = d3.rgb(a); 25793 b = d3.rgb(b); 25794 var ar = a.r, ag = a.g, ab = a.b, br = b.r - ar, bg = b.g - ag, bb = b.b - ab; 25795 return function(t) { 25796 return "#" + d3_rgb_hex(Math.round(ar + br * t)) + d3_rgb_hex(Math.round(ag + bg * t)) + d3_rgb_hex(Math.round(ab + bb * t)); 25797 }; 25798 } 25799 d3.interpolateObject = d3_interpolateObject; 25800 function d3_interpolateObject(a, b) { 25801 var i = {}, c = {}, k; 25802 for (k in a) { 25803 if (k in b) { 25804 i[k] = d3_interpolate(a[k], b[k]); 25805 } else { 25806 c[k] = a[k]; 25807 } 25808 } 25809 for (k in b) { 25810 if (!(k in a)) { 25811 c[k] = b[k]; 25812 } 25813 } 25814 return function(t) { 25815 for (k in i) c[k] = i[k](t); 25816 return c; 25817 }; 25818 } 25819 d3.interpolateNumber = d3_interpolateNumber; 25820 function d3_interpolateNumber(a, b) { 25821 a = +a, b = +b; 25822 return function(t) { 25823 return a * (1 - t) + b * t; 25824 }; 25825 } 25826 d3.interpolateString = d3_interpolateString; 25827 function d3_interpolateString(a, b) { 25828 var bi = d3_interpolate_numberA.lastIndex = d3_interpolate_numberB.lastIndex = 0, am, bm, bs, i = -1, s = [], q = []; 25829 a = a + "", b = b + ""; 25830 while ((am = d3_interpolate_numberA.exec(a)) && (bm = d3_interpolate_numberB.exec(b))) { 25831 if ((bs = bm.index) > bi) { 25832 bs = b.slice(bi, bs); 25833 if (s[i]) s[i] += bs; else s[++i] = bs; 25834 } 25835 if ((am = am[0]) === (bm = bm[0])) { 25836 if (s[i]) s[i] += bm; else s[++i] = bm; 25837 } else { 25838 s[++i] = null; 25839 q.push({ 25840 i: i, 25841 x: d3_interpolateNumber(am, bm) 25842 }); 25843 } 25844 bi = d3_interpolate_numberB.lastIndex; 25845 } 25846 if (bi < b.length) { 25847 bs = b.slice(bi); 25848 if (s[i]) s[i] += bs; else s[++i] = bs; 25849 } 25850 return s.length < 2 ? q[0] ? (b = q[0].x, function(t) { 25851 return b(t) + ""; 25852 }) : function() { 25853 return b; 25854 } : (b = q.length, function(t) { 25855 for (var i = 0, o; i < b; ++i) s[(o = q[i]).i] = o.x(t); 25856 return s.join(""); 25857 }); 25858 } 25859 var d3_interpolate_numberA = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g, d3_interpolate_numberB = new RegExp(d3_interpolate_numberA.source, "g"); 25860 d3.interpolate = d3_interpolate; 25861 function d3_interpolate(a, b) { 25862 var i = d3.interpolators.length, f; 25863 while (--i >= 0 && !(f = d3.interpolators[i](a, b))) ; 25864 return f; 25865 } 25866 d3.interpolators = [ function(a, b) { 25867 var t = typeof b; 25868 return (t === "string" ? d3_rgb_names.has(b) || /^(#|rgb\(|hsl\()/.test(b) ? d3_interpolateRgb : d3_interpolateString : b instanceof d3_color ? d3_interpolateRgb : Array.isArray(b) ? d3_interpolateArray : t === "object" && isNaN(b) ? d3_interpolateObject : d3_interpolateNumber)(a, b); 25869 } ]; 25870 d3.interpolateArray = d3_interpolateArray; 25871 function d3_interpolateArray(a, b) { 25872 var x = [], c = [], na = a.length, nb = b.length, n0 = Math.min(a.length, b.length), i; 25873 for (i = 0; i < n0; ++i) x.push(d3_interpolate(a[i], b[i])); 25874 for (;i < na; ++i) c[i] = a[i]; 25875 for (;i < nb; ++i) c[i] = b[i]; 25876 return function(t) { 25877 for (i = 0; i < n0; ++i) c[i] = x[i](t); 25878 return c; 25879 }; 25880 } 25881 var d3_ease_default = function() { 25882 return d3_identity; 25883 }; 25884 var d3_ease = d3.map({ 25885 linear: d3_ease_default, 25886 poly: d3_ease_poly, 25887 quad: function() { 25888 return d3_ease_quad; 25889 }, 25890 cubic: function() { 25891 return d3_ease_cubic; 25892 }, 25893 sin: function() { 25894 return d3_ease_sin; 25895 }, 25896 exp: function() { 25897 return d3_ease_exp; 25898 }, 25899 circle: function() { 25900 return d3_ease_circle; 25901 }, 25902 elastic: d3_ease_elastic, 25903 back: d3_ease_back, 25904 bounce: function() { 25905 return d3_ease_bounce; 25906 } 25907 }); 25908 var d3_ease_mode = d3.map({ 25909 "in": d3_identity, 25910 out: d3_ease_reverse, 25911 "in-out": d3_ease_reflect, 25912 "out-in": function(f) { 25913 return d3_ease_reflect(d3_ease_reverse(f)); 25914 } 25915 }); 25916 d3.ease = function(name) { 25917 var i = name.indexOf("-"), t = i >= 0 ? name.slice(0, i) : name, m = i >= 0 ? name.slice(i + 1) : "in"; 25918 t = d3_ease.get(t) || d3_ease_default; 25919 m = d3_ease_mode.get(m) || d3_identity; 25920 return d3_ease_clamp(m(t.apply(null, d3_arraySlice.call(arguments, 1)))); 25921 }; 25922 function d3_ease_clamp(f) { 25923 return function(t) { 25924 return t <= 0 ? 0 : t >= 1 ? 1 : f(t); 25925 }; 25926 } 25927 function d3_ease_reverse(f) { 25928 return function(t) { 25929 return 1 - f(1 - t); 25930 }; 25931 } 25932 function d3_ease_reflect(f) { 25933 return function(t) { 25934 return .5 * (t < .5 ? f(2 * t) : 2 - f(2 - 2 * t)); 25935 }; 25936 } 25937 function d3_ease_quad(t) { 25938 return t * t; 25939 } 25940 function d3_ease_cubic(t) { 25941 return t * t * t; 25942 } 25943 function d3_ease_cubicInOut(t) { 25944 if (t <= 0) return 0; 25945 if (t >= 1) return 1; 25946 var t2 = t * t, t3 = t2 * t; 25947 return 4 * (t < .5 ? t3 : 3 * (t - t2) + t3 - .75); 25948 } 25949 function d3_ease_poly(e) { 25950 return function(t) { 25951 return Math.pow(t, e); 25952 }; 25953 } 25954 function d3_ease_sin(t) { 25955 return 1 - Math.cos(t * halfÏ); 25956 } 25957 function d3_ease_exp(t) { 25958 return Math.pow(2, 10 * (t - 1)); 25959 } 25960 function d3_ease_circle(t) { 25961 return 1 - Math.sqrt(1 - t * t); 25962 } 25963 function d3_ease_elastic(a, p) { 25964 var s; 25965 if (arguments.length < 2) p = .45; 25966 if (arguments.length) s = p / Ï * Math.asin(1 / a); else a = 1, s = p / 4; 25967 return function(t) { 25968 return 1 + a * Math.pow(2, -10 * t) * Math.sin((t - s) * Ï / p); 25969 }; 25970 } 25971 function d3_ease_back(s) { 25972 if (!s) s = 1.70158; 25973 return function(t) { 25974 return t * t * ((s + 1) * t - s); 25975 }; 25976 } 25977 function d3_ease_bounce(t) { 25978 return t < 1 / 2.75 ? 7.5625 * t * t : t < 2 / 2.75 ? 7.5625 * (t -= 1.5 / 2.75) * t + .75 : t < 2.5 / 2.75 ? 7.5625 * (t -= 2.25 / 2.75) * t + .9375 : 7.5625 * (t -= 2.625 / 2.75) * t + .984375; 25979 } 25980 d3.interpolateHcl = d3_interpolateHcl; 25981 function d3_interpolateHcl(a, b) { 25982 a = d3.hcl(a); 25983 b = d3.hcl(b); 25984 var ah = a.h, ac = a.c, al = a.l, bh = b.h - ah, bc = b.c - ac, bl = b.l - al; 25985 if (isNaN(bc)) bc = 0, ac = isNaN(ac) ? b.c : ac; 25986 if (isNaN(bh)) bh = 0, ah = isNaN(ah) ? b.h : ah; else if (bh > 180) bh -= 360; else if (bh < -180) bh += 360; 25987 return function(t) { 25988 return d3_hcl_lab(ah + bh * t, ac + bc * t, al + bl * t) + ""; 25989 }; 25990 } 25991 d3.interpolateHsl = d3_interpolateHsl; 25992 function d3_interpolateHsl(a, b) { 25993 a = d3.hsl(a); 25994 b = d3.hsl(b); 25995 var ah = a.h, as = a.s, al = a.l, bh = b.h - ah, bs = b.s - as, bl = b.l - al; 25996 if (isNaN(bs)) bs = 0, as = isNaN(as) ? b.s : as; 25997 if (isNaN(bh)) bh = 0, ah = isNaN(ah) ? b.h : ah; else if (bh > 180) bh -= 360; else if (bh < -180) bh += 360; 25998 return function(t) { 25999 return d3_hsl_rgb(ah + bh * t, as + bs * t, al + bl * t) + ""; 26000 }; 26001 } 26002 d3.interpolateLab = d3_interpolateLab; 26003 function d3_interpolateLab(a, b) { 26004 a = d3.lab(a); 26005 b = d3.lab(b); 26006 var al = a.l, aa = a.a, ab = a.b, bl = b.l - al, ba = b.a - aa, bb = b.b - ab; 26007 return function(t) { 26008 return d3_lab_rgb(al + bl * t, aa + ba * t, ab + bb * t) + ""; 26009 }; 26010 } 26011 d3.interpolateRound = d3_interpolateRound; 26012 function d3_interpolateRound(a, b) { 26013 b -= a; 26014 return function(t) { 26015 return Math.round(a + b * t); 26016 }; 26017 } 26018 d3.transform = function(string) { 26019 var g = d3_document.createElementNS(d3.ns.prefix.svg, "g"); 26020 return (d3.transform = function(string) { 26021 if (string != null) { 26022 g.setAttribute("transform", string); 26023 var t = g.transform.baseVal.consolidate(); 26024 } 26025 return new d3_transform(t ? t.matrix : d3_transformIdentity); 26026 })(string); 26027 }; 26028 function d3_transform(m) { 26029 var r0 = [ m.a, m.b ], r1 = [ m.c, m.d ], kx = d3_transformNormalize(r0), kz = d3_transformDot(r0, r1), ky = d3_transformNormalize(d3_transformCombine(r1, r0, -kz)) || 0; 26030 if (r0[0] * r1[1] < r1[0] * r0[1]) { 26031 r0[0] *= -1; 26032 r0[1] *= -1; 26033 kx *= -1; 26034 kz *= -1; 26035 } 26036 this.rotate = (kx ? Math.atan2(r0[1], r0[0]) : Math.atan2(-r1[0], r1[1])) * d3_degrees; 26037 this.translate = [ m.e, m.f ]; 26038 this.scale = [ kx, ky ]; 26039 this.skew = ky ? Math.atan2(kz, ky) * d3_degrees : 0; 26040 } 26041 d3_transform.prototype.toString = function() { 26042 return "translate(" + this.translate + ")rotate(" + this.rotate + ")skewX(" + this.skew + ")scale(" + this.scale + ")"; 26043 }; 26044 function d3_transformDot(a, b) { 26045 return a[0] * b[0] + a[1] * b[1]; 26046 } 26047 function d3_transformNormalize(a) { 26048 var k = Math.sqrt(d3_transformDot(a, a)); 26049 if (k) { 26050 a[0] /= k; 26051 a[1] /= k; 26052 } 26053 return k; 26054 } 26055 function d3_transformCombine(a, b, k) { 26056 a[0] += k * b[0]; 26057 a[1] += k * b[1]; 26058 return a; 26059 } 26060 var d3_transformIdentity = { 26061 a: 1, 26062 b: 0, 26063 c: 0, 26064 d: 1, 26065 e: 0, 26066 f: 0 26067 }; 26068 d3.interpolateTransform = d3_interpolateTransform; 26069 function d3_interpolateTransform(a, b) { 26070 var s = [], q = [], n, A = d3.transform(a), B = d3.transform(b), ta = A.translate, tb = B.translate, ra = A.rotate, rb = B.rotate, wa = A.skew, wb = B.skew, ka = A.scale, kb = B.scale; 26071 if (ta[0] != tb[0] || ta[1] != tb[1]) { 26072 s.push("translate(", null, ",", null, ")"); 26073 q.push({ 26074 i: 1, 26075 x: d3_interpolateNumber(ta[0], tb[0]) 26076 }, { 26077 i: 3, 26078 x: d3_interpolateNumber(ta[1], tb[1]) 26079 }); 26080 } else if (tb[0] || tb[1]) { 26081 s.push("translate(" + tb + ")"); 26082 } else { 26083 s.push(""); 26084 } 26085 if (ra != rb) { 26086 if (ra - rb > 180) rb += 360; else if (rb - ra > 180) ra += 360; 26087 q.push({ 26088 i: s.push(s.pop() + "rotate(", null, ")") - 2, 26089 x: d3_interpolateNumber(ra, rb) 26090 }); 26091 } else if (rb) { 26092 s.push(s.pop() + "rotate(" + rb + ")"); 26093 } 26094 if (wa != wb) { 26095 q.push({ 26096 i: s.push(s.pop() + "skewX(", null, ")") - 2, 26097 x: d3_interpolateNumber(wa, wb) 26098 }); 26099 } else if (wb) { 26100 s.push(s.pop() + "skewX(" + wb + ")"); 26101 } 26102 if (ka[0] != kb[0] || ka[1] != kb[1]) { 26103 n = s.push(s.pop() + "scale(", null, ",", null, ")"); 26104 q.push({ 26105 i: n - 4, 26106 x: d3_interpolateNumber(ka[0], kb[0]) 26107 }, { 26108 i: n - 2, 26109 x: d3_interpolateNumber(ka[1], kb[1]) 26110 }); 26111 } else if (kb[0] != 1 || kb[1] != 1) { 26112 s.push(s.pop() + "scale(" + kb + ")"); 26113 } 26114 n = q.length; 26115 return function(t) { 26116 var i = -1, o; 26117 while (++i < n) s[(o = q[i]).i] = o.x(t); 26118 return s.join(""); 26119 }; 26120 } 26121 function d3_uninterpolateNumber(a, b) { 26122 b = (b -= a = +a) || 1 / b; 26123 return function(x) { 26124 return (x - a) / b; 26125 }; 26126 } 26127 function d3_uninterpolateClamp(a, b) { 26128 b = (b -= a = +a) || 1 / b; 26129 return function(x) { 26130 return Math.max(0, Math.min(1, (x - a) / b)); 26131 }; 26132 } 26133 d3.layout = {}; 26134 d3.layout.bundle = function() { 26135 return function(links) { 26136 var paths = [], i = -1, n = links.length; 26137 while (++i < n) paths.push(d3_layout_bundlePath(links[i])); 26138 return paths; 26139 }; 26140 }; 26141 function d3_layout_bundlePath(link) { 26142 var start = link.source, end = link.target, lca = d3_layout_bundleLeastCommonAncestor(start, end), points = [ start ]; 26143 while (start !== lca) { 26144 start = start.parent; 26145 points.push(start); 26146 } 26147 var k = points.length; 26148 while (end !== lca) { 26149 points.splice(k, 0, end); 26150 end = end.parent; 26151 } 26152 return points; 26153 } 26154 function d3_layout_bundleAncestors(node) { 26155 var ancestors = [], parent = node.parent; 26156 while (parent != null) { 26157 ancestors.push(node); 26158 node = parent; 26159 parent = parent.parent; 26160 } 26161 ancestors.push(node); 26162 return ancestors; 26163 } 26164 function d3_layout_bundleLeastCommonAncestor(a, b) { 26165 if (a === b) return a; 26166 var aNodes = d3_layout_bundleAncestors(a), bNodes = d3_layout_bundleAncestors(b), aNode = aNodes.pop(), bNode = bNodes.pop(), sharedNode = null; 26167 while (aNode === bNode) { 26168 sharedNode = aNode; 26169 aNode = aNodes.pop(); 26170 bNode = bNodes.pop(); 26171 } 26172 return sharedNode; 26173 } 26174 d3.layout.chord = function() { 26175 var chord = {}, chords, groups, matrix, n, padding = 0, sortGroups, sortSubgroups, sortChords; 26176 function relayout() { 26177 var subgroups = {}, groupSums = [], groupIndex = d3.range(n), subgroupIndex = [], k, x, x0, i, j; 26178 chords = []; 26179 groups = []; 26180 k = 0, i = -1; 26181 while (++i < n) { 26182 x = 0, j = -1; 26183 while (++j < n) { 26184 x += matrix[i][j]; 26185 } 26186 groupSums.push(x); 26187 subgroupIndex.push(d3.range(n)); 26188 k += x; 26189 } 26190 if (sortGroups) { 26191 groupIndex.sort(function(a, b) { 26192 return sortGroups(groupSums[a], groupSums[b]); 26193 }); 26194 } 26195 if (sortSubgroups) { 26196 subgroupIndex.forEach(function(d, i) { 26197 d.sort(function(a, b) { 26198 return sortSubgroups(matrix[i][a], matrix[i][b]); 26199 }); 26200 }); 26201 } 26202 k = (Ï - padding * n) / k; 26203 x = 0, i = -1; 26204 while (++i < n) { 26205 x0 = x, j = -1; 26206 while (++j < n) { 26207 var di = groupIndex[i], dj = subgroupIndex[di][j], v = matrix[di][dj], a0 = x, a1 = x += v * k; 26208 subgroups[di + "-" + dj] = { 26209 index: di, 26210 subindex: dj, 26211 startAngle: a0, 26212 endAngle: a1, 26213 value: v 26214 }; 26215 } 26216 groups[di] = { 26217 index: di, 26218 startAngle: x0, 26219 endAngle: x, 26220 value: (x - x0) / k 26221 }; 26222 x += padding; 26223 } 26224 i = -1; 26225 while (++i < n) {
vendor: 3,724 bytes, lines 26226-26346
26226 j = i - 1; 26227 while (++j < n) { 26228 var source = subgroups[i + "-" + j], target = subgroups[j + "-" + i]; 26229 if (source.value || target.value) { 26230 chords.push(source.value < target.value ? { 26231 source: target, 26232 target: source 26233 } : { 26234 source: source, 26235 target: target 26236 }); 26237 } 26238 } 26239 } 26240 if (sortChords) resort(); 26241 } 26242 function resort() { 26243 chords.sort(function(a, b) { 26244 return sortChords((a.source.value + a.target.value) / 2, (b.source.value + b.target.value) / 2); 26245 }); 26246 } 26247 chord.matrix = function(x) { 26248 if (!arguments.length) return matrix; 26249 n = (matrix = x) && matrix.length; 26250 chords = groups = null; 26251 return chord; 26252 }; 26253 chord.padding = function(x) { 26254 if (!arguments.length) return padding; 26255 padding = x; 26256 chords = groups = null; 26257 return chord; 26258 }; 26259 chord.sortGroups = function(x) { 26260 if (!arguments.length) return sortGroups; 26261 sortGroups = x; 26262 chords = groups = null; 26263 return chord; 26264 }; 26265 chord.sortSubgroups = function(x) { 26266 if (!arguments.length) return sortSubgroups; 26267 sortSubgroups = x; 26268 chords = null; 26269 return chord; 26270 }; 26271 chord.sortChords = function(x) { 26272 if (!arguments.length) return sortChords; 26273 sortChords = x; 26274 if (chords) resort(); 26275 return chord; 26276 }; 26277 chord.chords = function() { 26278 if (!chords) relayout(); 26279 return chords; 26280 }; 26281 chord.groups = function() { 26282 if (!groups) relayout(); 26283 return groups; 26284 }; 26285 return chord; 26286 }; 26287 d3.layout.force = function() { 26288 var force = {}, event = d3.dispatch("start", "tick", "end"), size = [ 1, 1 ], drag, alpha, friction = .9, linkDistance = d3_layout_forceLinkDistance, linkStrength = d3_layout_forceLinkStrength, charge = -30, chargeDistance2 = d3_layout_forceChargeDistance2, gravity = .1, theta2 = .64, nodes = [], links = [], distances, strengths, charges; 26289 function repulse(node) { 26290 return function(quad, x1, _, x2) { 26291 if (quad.point !== node) { 26292 var dx = quad.cx - node.x, dy = quad.cy - node.y, dw = x2 - x1, dn = dx * dx + dy * dy; 26293 if (dw * dw / theta2 < dn) { 26294 if (dn < chargeDistance2) { 26295 var k = quad.charge / dn; 26296 node.px -= dx * k; 26297 node.py -= dy * k; 26298 } 26299 return true; 26300 } 26301 if (quad.point && dn && dn < chargeDistance2) { 26302 var k = quad.pointCharge / dn; 26303 node.px -= dx * k; 26304 node.py -= dy * k; 26305 } 26306 } 26307 return !quad.charge; 26308 }; 26309 } 26310 force.tick = function() { 26311 if ((alpha *= .99) < .005) { 26312 event.end({ 26313 type: "end", 26314 alpha: alpha = 0 26315 }); 26316 return true; 26317 } 26318 var n = nodes.length, m = links.length, q, i, o, s, t, l, k, x, y; 26319 for (i = 0; i < m; ++i) { 26320 o = links[i]; 26321 s = o.source; 26322 t = o.target; 26323 x = t.x - s.x; 26324 y = t.y - s.y; 26325 if (l = x * x + y * y) { 26326 l = alpha * strengths[i] * ((l = Math.sqrt(l)) - distances[i]) / l; 26327 x *= l; 26328 y *= l; 26329 t.x -= x * (k = s.weight / (t.weight + s.weight)); 26330 t.y -= y * k; 26331 s.x += x * (k = 1 - k); 26332 s.y += y * k; 26333 } 26334 } 26335 if (k = alpha * gravity) { 26336 x = size[0] / 2; 26337 y = size[1] / 2; 26338 i = -1; 26339 if (k) while (++i < n) { 26340 o = nodes[i]; 26341 o.x += (x - o.x) * k; 26342 o.y += (y - o.y) * k; 26343 } 26344 } 26345 if (charge) { 26346 d3_layout_forceAccumulate(q = d3.geom.quadtree(nodes), alph
vendor: 14,132 bytes, lines 26346-26796
26346a, charges); 26347 i = -1; 26348 while (++i < n) { 26349 if (!(o = nodes[i]).fixed) { 26350 q.visit(repulse(o)); 26351 } 26352 } 26353 } 26354 i = -1; 26355 while (++i < n) { 26356 o = nodes[i]; 26357 if (o.fixed) { 26358 o.x = o.px; 26359 o.y = o.py; 26360 } else { 26361 o.x -= (o.px - (o.px = o.x)) * friction; 26362 o.y -= (o.py - (o.py = o.y)) * friction; 26363 } 26364 } 26365 event.tick({ 26366 type: "tick", 26367 alpha: alpha 26368 }); 26369 }; 26370 force.nodes = function(x) { 26371 if (!arguments.length) return nodes; 26372 nodes = x; 26373 return force; 26374 }; 26375 force.links = function(x) { 26376 if (!arguments.length) return links; 26377 links = x; 26378 return force; 26379 }; 26380 force.size = function(x) { 26381 if (!arguments.length) return size; 26382 size = x; 26383 return force; 26384 }; 26385 force.linkDistance = function(x) { 26386 if (!arguments.length) return linkDistance; 26387 linkDistance = typeof x === "function" ? x : +x; 26388 return force; 26389 }; 26390 force.distance = force.linkDistance; 26391 force.linkStrength = function(x) { 26392 if (!arguments.length) return linkStrength; 26393 linkStrength = typeof x === "function" ? x : +x; 26394 return force; 26395 }; 26396 force.friction = function(x) { 26397 if (!arguments.length) return friction; 26398 friction = +x; 26399 return force; 26400 }; 26401 force.charge = function(x) { 26402 if (!arguments.length) return charge; 26403 charge = typeof x === "function" ? x : +x; 26404 return force; 26405 }; 26406 force.chargeDistance = function(x) { 26407 if (!arguments.length) return Math.sqrt(chargeDistance2); 26408 chargeDistance2 = x * x; 26409 return force; 26410 }; 26411 force.gravity = function(x) { 26412 if (!arguments.length) return gravity; 26413 gravity = +x; 26414 return force; 26415 }; 26416 force.theta = function(x) { 26417 if (!arguments.length) return Math.sqrt(theta2); 26418 theta2 = x * x; 26419 return force; 26420 }; 26421 force.alpha = function(x) { 26422 if (!arguments.length) return alpha; 26423 x = +x; 26424 if (alpha) { 26425 if (x > 0) alpha = x; else alpha = 0; 26426 } else if (x > 0) { 26427 event.start({ 26428 type: "start", 26429 alpha: alpha = x 26430 }); 26431 d3.timer(force.tick); 26432 } 26433 return force; 26434 }; 26435 force.start = function() { 26436 var i, n = nodes.length, m = links.length, w = size[0], h = size[1], neighbors, o; 26437 for (i = 0; i < n; ++i) { 26438 (o = nodes[i]).index = i; 26439 o.weight = 0; 26440 } 26441 for (i = 0; i < m; ++i) { 26442 o = links[i]; 26443 if (typeof o.source == "number") o.source = nodes[o.source]; 26444 if (typeof o.target == "number") o.target = nodes[o.target]; 26445 ++o.source.weight; 26446 ++o.target.weight; 26447 } 26448 for (i = 0; i < n; ++i) { 26449 o = nodes[i]; 26450 if (isNaN(o.x)) o.x = position("x", w); 26451 if (isNaN(o.y)) o.y = position("y", h); 26452 if (isNaN(o.px)) o.px = o.x; 26453 if (isNaN(o.py)) o.py = o.y; 26454 } 26455 distances = []; 26456 if (typeof linkDistance === "function") for (i = 0; i < m; ++i) distances[i] = +linkDistance.call(this, links[i], i); else for (i = 0; i < m; ++i) distances[i] = linkDistance; 26457 strengths = []; 26458 if (typeof linkStrength === "function") for (i = 0; i < m; ++i) strengths[i] = +linkStrength.call(this, links[i], i); else for (i = 0; i < m; ++i) strengths[i] = linkStrength; 26459 charges = []; 26460 if (typeof charge === "function") for (i = 0; i < n; ++i) charges[i] = +charge.call(this, nodes[i], i); else for (i = 0; i < n; ++i) charges[i] = charge; 26461 function position(dimension, size) { 26462 if (!neighbors) { 26463 neighbors = new Array(n); 26464 for (j = 0; j < n; ++j) { 26465 neighbors[j] = []; 26466 } 26467 for (j = 0; j < m; ++j) { 26468 var o = links[j]; 26469 neighbors[o.source.index].push(o.target); 26470 neighbors[o.target.index].push(o.source); 26471 } 26472 } 26473 var candidates = neighbors[i], j = -1, m = candidates.length, x; 26474 while (++j < m) if (!isNaN(x = candidates[j][dimension])) return x; 26475 return Math.random() * size; 26476 } 26477 return force.resume(); 26478 }; 26479 force.resume = function() { 26480 return force.alpha(.1); 26481 }; 26482 force.stop = function() { 26483 return force.alpha(0); 26484 }; 26485 force.drag = function() { 26486 if (!drag) drag = d3.behavior.drag().origin(d3_identity).on("dragstart.force", d3_layout_forceDragstart).on("drag.force", dragmove).on("dragend.force", d3_layout_forceDragend); 26487 if (!arguments.length) return drag; 26488 this.on("mouseover.force", d3_layout_forceMouseover).on("mouseout.force", d3_layout_forceMouseout).call(drag); 26489 }; 26490 function dragmove(d) { 26491 d.px = d3.event.x, d.py = d3.event.y; 26492 force.resume(); 26493 } 26494 return d3.rebind(force, event, "on"); 26495 }; 26496 function d3_layout_forceDragstart(d) { 26497 d.fixed |= 2; 26498 } 26499 function d3_layout_forceDragend(d) { 26500 d.fixed &= ~6; 26501 } 26502 function d3_layout_forceMouseover(d) { 26503 d.fixed |= 4; 26504 d.px = d.x, d.py = d.y; 26505 } 26506 function d3_layout_forceMouseout(d) { 26507 d.fixed &= ~4; 26508 } 26509 function d3_layout_forceAccumulate(quad, alpha, charges) { 26510 var cx = 0, cy = 0; 26511 quad.charge = 0; 26512 if (!quad.leaf) { 26513 var nodes = quad.nodes, n = nodes.length, i = -1, c; 26514 while (++i < n) { 26515 c = nodes[i]; 26516 if (c == null) continue; 26517 d3_layout_forceAccumulate(c, alpha, charges); 26518 quad.charge += c.charge; 26519 cx += c.charge * c.cx; 26520 cy += c.charge * c.cy; 26521 } 26522 } 26523 if (quad.point) { 26524 if (!quad.leaf) { 26525 quad.point.x += Math.random() - .5; 26526 quad.point.y += Math.random() - .5; 26527 } 26528 var k = alpha * charges[quad.point.index]; 26529 quad.charge += quad.pointCharge = k; 26530 cx += k * quad.point.x; 26531 cy += k * quad.point.y; 26532 } 26533 quad.cx = cx / quad.charge; 26534 quad.cy = cy / quad.charge; 26535 } 26536 var d3_layout_forceLinkDistance = 20, d3_layout_forceLinkStrength = 1, d3_layout_forceChargeDistance2 = Infinity; 26537 d3.layout.hierarchy = function() { 26538 var sort = d3_layout_hierarchySort, children = d3_layout_hierarchyChildren, value = d3_layout_hierarchyValue; 26539 function hierarchy(root) { 26540 var stack = [ root ], nodes = [], node; 26541 root.depth = 0; 26542 while ((node = stack.pop()) != null) { 26543 nodes.push(node); 26544 if ((childs = children.call(hierarchy, node, node.depth)) && (n = childs.length)) { 26545 var n, childs, child; 26546 while (--n >= 0) { 26547 stack.push(child = childs[n]); 26548 child.parent = node; 26549 child.depth = node.depth + 1; 26550 } 26551 if (value) node.value = 0; 26552 node.children = childs; 26553 } else { 26554 if (value) node.value = +value.call(hierarchy, node, node.depth) || 0; 26555 delete node.children; 26556 } 26557 } 26558 d3_layout_hierarchyVisitAfter(root, function(node) { 26559 var childs, parent; 26560 if (sort && (childs = node.children)) childs.sort(sort); 26561 if (value && (parent = node.parent)) parent.value += node.value; 26562 }); 26563 return nodes; 26564 } 26565 hierarchy.sort = function(x) { 26566 if (!arguments.length) return sort; 26567 sort = x; 26568 return hierarchy; 26569 }; 26570 hierarchy.children = function(x) { 26571 if (!arguments.length) return children; 26572 children = x; 26573 return hierarchy; 26574 }; 26575 hierarchy.value = function(x) { 26576 if (!arguments.length) return value; 26577 value = x; 26578 return hierarchy; 26579 }; 26580 hierarchy.revalue = function(root) { 26581 if (value) { 26582 d3_layout_hierarchyVisitBefore(root, function(node) { 26583 if (node.children) node.value = 0; 26584 }); 26585 d3_layout_hierarchyVisitAfter(root, function(node) { 26586 var parent; 26587 if (!node.children) node.value = +value.call(hierarchy, node, node.depth) || 0; 26588 if (parent = node.parent) parent.value += node.value; 26589 }); 26590 } 26591 return root; 26592 }; 26593 return hierarchy; 26594 }; 26595 function d3_layout_hierarchyRebind(object, hierarchy) { 26596 d3.rebind(object, hierarchy, "sort", "children", "value"); 26597 object.nodes = object; 26598 object.links = d3_layout_hierarchyLinks; 26599 return object; 26600 } 26601 function d3_layout_hierarchyVisitBefore(node, callback) { 26602 var nodes = [ node ]; 26603 while ((node = nodes.pop()) != null) { 26604 callback(node); 26605 if ((children = node.children) && (n = children.length)) { 26606 var n, children; 26607 while (--n >= 0) nodes.push(children[n]); 26608 } 26609 } 26610 } 26611 function d3_layout_hierarchyVisitAfter(node, callback) { 26612 var nodes = [ node ], nodes2 = []; 26613 while ((node = nodes.pop()) != null) { 26614 nodes2.push(node); 26615 if ((children = node.children) && (n = children.length)) { 26616 var i = -1, n, children; 26617 while (++i < n) nodes.push(children[i]); 26618 } 26619 } 26620 while ((node = nodes2.pop()) != null) { 26621 callback(node); 26622 } 26623 } 26624 function d3_layout_hierarchyChildren(d) { 26625 return d.children; 26626 } 26627 function d3_layout_hierarchyValue(d) { 26628 return d.value; 26629 } 26630 function d3_layout_hierarchySort(a, b) { 26631 return b.value - a.value; 26632 } 26633 function d3_layout_hierarchyLinks(nodes) { 26634 return d3.merge(nodes.map(function(parent) { 26635 return (parent.children || []).map(function(child) { 26636 return { 26637 source: parent, 26638 target: child 26639 }; 26640 }); 26641 })); 26642 } 26643 d3.layout.partition = function() { 26644 var hierarchy = d3.layout.hierarchy(), size = [ 1, 1 ]; 26645 function position(node, x, dx, dy) { 26646 var children = node.children; 26647 node.x = x; 26648 node.y = node.depth * dy; 26649 node.dx = dx; 26650 node.dy = dy; 26651 if (children && (n = children.length)) { 26652 var i = -1, n, c, d; 26653 dx = node.value ? dx / node.value : 0; 26654 while (++i < n) { 26655 position(c = children[i], x, d = c.value * dx, dy); 26656 x += d; 26657 } 26658 } 26659 } 26660 function depth(node) { 26661 var children = node.children, d = 0; 26662 if (children && (n = children.length)) { 26663 var i = -1, n; 26664 while (++i < n) d = Math.max(d, depth(children[i])); 26665 } 26666 return 1 + d; 26667 } 26668 function partition(d, i) { 26669 var nodes = hierarchy.call(this, d, i); 26670 position(nodes[0], 0, size[0], size[1] / depth(nodes[0])); 26671 return nodes; 26672 } 26673 partition.size = function(x) { 26674 if (!arguments.length) return size; 26675 size = x; 26676 return partition; 26677 }; 26678 return d3_layout_hierarchyRebind(partition, hierarchy); 26679 }; 26680 d3.layout.pie = function() { 26681 var value = Number, sort = d3_layout_pieSortByValue, startAngle = 0, endAngle = Ï; 26682 function pie(data) { 26683 var values = data.map(function(d, i) { 26684 return +value.call(pie, d, i); 26685 }); 26686 var a = +(typeof startAngle === "function" ? startAngle.apply(this, arguments) : startAngle); 26687 var k = ((typeof endAngle === "function" ? endAngle.apply(this, arguments) : endAngle) - a) / d3.sum(values); 26688 var index = d3.range(data.length); 26689 if (sort != null) index.sort(sort === d3_layout_pieSortByValue ? function(i, j) { 26690 return values[j] - values[i]; 26691 } : function(i, j) { 26692 return sort(data[i], data[j]); 26693 }); 26694 var arcs = []; 26695 index.forEach(function(i) { 26696 var d; 26697 arcs[i] = { 26698 data: data[i], 26699 value: d = values[i], 26700 startAngle: a, 26701 endAngle: a += d * k 26702 }; 26703 }); 26704 return arcs; 26705 } 26706 pie.value = function(x) { 26707 if (!arguments.length) return value; 26708 value = x; 26709 return pie; 26710 }; 26711 pie.sort = function(x) { 26712 if (!arguments.length) return sort; 26713 sort = x; 26714 return pie; 26715 }; 26716 pie.startAngle = function(x) { 26717 if (!arguments.length) return startAngle; 26718 startAngle = x; 26719 return pie; 26720 }; 26721 pie.endAngle = function(x) { 26722 if (!arguments.length) return endAngle; 26723 endAngle = x; 26724 return pie; 26725 }; 26726 return pie; 26727 }; 26728 var d3_layout_pieSortByValue = {}; 26729 d3.layout.stack = function() { 26730 var values = d3_identity, order = d3_layout_stackOrderDefault, offset = d3_layout_stackOffsetZero, out = d3_layout_stackOut, x = d3_layout_stackX, y = d3_layout_stackY; 26731 function stack(data, index) { 26732 if (!(n = data.length)) return data; 26733 var series = data.map(function(d, i) { 26734 return values.call(stack, d, i); 26735 }); 26736 var points = series.map(function(d) { 26737 return d.map(function(v, i) { 26738 return [ x.call(stack, v, i), y.call(stack, v, i) ]; 26739 }); 26740 }); 26741 var orders = order.call(stack, points, index); 26742 series = d3.permute(series, orders); 26743 points = d3.permute(points, orders); 26744 var offsets = offset.call(stack, points, index); 26745 var m = series[0].length, n, i, j, o; 26746 for (j = 0; j < m; ++j) { 26747 out.call(stack, series[0][j], o = offsets[j], points[0][j][1]); 26748 for (i = 1; i < n; ++i) { 26749 out.call(stack, series[i][j], o += points[i - 1][j][1], points[i][j][1]); 26750 } 26751 } 26752 return data; 26753 } 26754 stack.values = function(x) { 26755 if (!arguments.length) return values; 26756 values = x; 26757 return stack; 26758 }; 26759 stack.order = function(x) { 26760 if (!arguments.length) return order; 26761 order = typeof x === "function" ? x : d3_layout_stackOrders.get(x) || d3_layout_stackOrderDefault; 26762 return stack; 26763 }; 26764 stack.offset = function(x) { 26765 if (!arguments.length) return offset; 26766 offset = typeof x === "function" ? x : d3_layout_stackOffsets.get(x) || d3_layout_stackOffsetZero; 26767 return stack; 26768 }; 26769 stack.x = function(z) { 26770 if (!arguments.length) return x; 26771 x = z; 26772 return stack; 26773 }; 26774 stack.y = function(z) { 26775 if (!arguments.length) return y; 26776 y = z; 26777 return stack; 26778 }; 26779 stack.out = function(z) { 26780 if (!arguments.length) return out; 26781 out = z; 26782 return stack; 26783 }; 26784 return stack; 26785 }; 26786 function d3_layout_stackX(d) { 26787 return d.x; 26788 } 26789 function d3_layout_stackY(d) { 26790 return d.y; 26791 } 26792 function d3_layout_stackOut(d, y0, y) { 26793 d.y0 = y0; 26794 d.y = y; 26795 } 26796 var d3_layout_stackOrders = d3.map({
vendor: 19,113 bytes, lines 26797-27350
26797 "inside-out": function(data) { 26798 var n = data.length, i, j, max = data.map(d3_layout_stackMaxIndex), sums = data.map(d3_layout_stackReduceSum), index = d3.range(n).sort(function(a, b) { 26799 return max[a] - max[b]; 26800 }), top = 0, bottom = 0, tops = [], bottoms = []; 26801 for (i = 0; i < n; ++i) { 26802 j = index[i]; 26803 if (top < bottom) { 26804 top += sums[j]; 26805 tops.push(j); 26806 } else { 26807 bottom += sums[j]; 26808 bottoms.push(j); 26809 } 26810 } 26811 return bottoms.reverse().concat(tops); 26812 }, 26813 reverse: function(data) { 26814 return d3.range(data.length).reverse(); 26815 }, 26816 "default": d3_layout_stackOrderDefault 26817 }); 26818 var d3_layout_stackOffsets = d3.map({ 26819 silhouette: function(data) { 26820 var n = data.length, m = data[0].length, sums = [], max = 0, i, j, o, y0 = []; 26821 for (j = 0; j < m; ++j) { 26822 for (i = 0, o = 0; i < n; i++) o += data[i][j][1]; 26823 if (o > max) max = o; 26824 sums.push(o); 26825 } 26826 for (j = 0; j < m; ++j) { 26827 y0[j] = (max - sums[j]) / 2; 26828 } 26829 return y0; 26830 }, 26831 wiggle: function(data) { 26832 var n = data.length, x = data[0], m = x.length, i, j, k, s1, s2, s3, dx, o, o0, y0 = []; 26833 y0[0] = o = o0 = 0; 26834 for (j = 1; j < m; ++j) { 26835 for (i = 0, s1 = 0; i < n; ++i) s1 += data[i][j][1]; 26836 for (i = 0, s2 = 0, dx = x[j][0] - x[j - 1][0]; i < n; ++i) { 26837 for (k = 0, s3 = (data[i][j][1] - data[i][j - 1][1]) / (2 * dx); k < i; ++k) { 26838 s3 += (data[k][j][1] - data[k][j - 1][1]) / dx; 26839 } 26840 s2 += s3 * data[i][j][1]; 26841 } 26842 y0[j] = o -= s1 ? s2 / s1 * dx : 0; 26843 if (o < o0) o0 = o; 26844 } 26845 for (j = 0; j < m; ++j) y0[j] -= o0; 26846 return y0; 26847 }, 26848 expand: function(data) { 26849 var n = data.length, m = data[0].length, k = 1 / n, i, j, o, y0 = []; 26850 for (j = 0; j < m; ++j) { 26851 for (i = 0, o = 0; i < n; i++) o += data[i][j][1]; 26852 if (o) for (i = 0; i < n; i++) data[i][j][1] /= o; else for (i = 0; i < n; i++) data[i][j][1] = k; 26853 } 26854 for (j = 0; j < m; ++j) y0[j] = 0; 26855 return y0; 26856 }, 26857 zero: d3_layout_stackOffsetZero 26858 }); 26859 function d3_layout_stackOrderDefault(data) { 26860 return d3.range(data.length); 26861 } 26862 function d3_layout_stackOffsetZero(data) { 26863 var j = -1, m = data[0].length, y0 = []; 26864 while (++j < m) y0[j] = 0; 26865 return y0; 26866 } 26867 function d3_layout_stackMaxIndex(array) { 26868 var i = 1, j = 0, v = array[0][1], k, n = array.length; 26869 for (;i < n; ++i) { 26870 if ((k = array[i][1]) > v) { 26871 j = i; 26872 v = k; 26873 } 26874 } 26875 return j; 26876 } 26877 function d3_layout_stackReduceSum(d) { 26878 return d.reduce(d3_layout_stackSum, 0); 26879 } 26880 function d3_layout_stackSum(p, d) { 26881 return p + d[1]; 26882 } 26883 d3.layout.histogram = function() { 26884 var frequency = true, valuer = Number, ranger = d3_layout_histogramRange, binner = d3_layout_histogramBinSturges; 26885 function histogram(data, i) { 26886 var bins = [], values = data.map(valuer, this), range = ranger.call(this, values, i), thresholds = binner.call(this, range, values, i), bin, i = -1, n = values.length, m = thresholds.length - 1, k = frequency ? 1 : 1 / n, x; 26887 while (++i < m) { 26888 bin = bins[i] = []; 26889 bin.dx = thresholds[i + 1] - (bin.x = thresholds[i]); 26890 bin.y = 0; 26891 } 26892 if (m > 0) { 26893 i = -1; 26894 while (++i < n) { 26895 x = values[i]; 26896 if (x >= range[0] && x <= range[1]) { 26897 bin = bins[d3.bisect(thresholds, x, 1, m) - 1]; 26898 bin.y += k; 26899 bin.push(data[i]); 26900 } 26901 } 26902 } 26903 return bins; 26904 } 26905 histogram.value = function(x) { 26906 if (!arguments.length) return valuer; 26907 valuer = x; 26908 return histogram; 26909 }; 26910 histogram.range = function(x) { 26911 if (!arguments.length) return ranger; 26912 ranger = d3_functor(x); 26913 return histogram; 26914 }; 26915 histogram.bins = function(x) { 26916 if (!arguments.length) return binner; 26917 binner = typeof x === "number" ? function(range) { 26918 return d3_layout_histogramBinFixed(range, x); 26919 } : d3_functor(x); 26920 return histogram; 26921 }; 26922 histogram.frequency = function(x) { 26923 if (!arguments.length) return frequency; 26924 frequency = !!x; 26925 return histogram; 26926 }; 26927 return histogram; 26928 }; 26929 function d3_layout_histogramBinSturges(range, values) { 26930 return d3_layout_histogramBinFixed(range, Math.ceil(Math.log(values.length) / Math.LN2 + 1)); 26931 } 26932 function d3_layout_histogramBinFixed(range, n) { 26933 var x = -1, b = +range[0], m = (range[1] - b) / n, f = []; 26934 while (++x <= n) f[x] = m * x + b; 26935 return f; 26936 } 26937 function d3_layout_histogramRange(values) { 26938 return [ d3.min(values), d3.max(values) ]; 26939 } 26940 d3.layout.pack = function() { 26941 var hierarchy = d3.layout.hierarchy().sort(d3_layout_packSort), padding = 0, size = [ 1, 1 ], radius; 26942 function pack(d, i) { 26943 var nodes = hierarchy.call(this, d, i), root = nodes[0], w = size[0], h = size[1], r = radius == null ? Math.sqrt : typeof radius === "function" ? radius : function() { 26944 return radius; 26945 }; 26946 root.x = root.y = 0; 26947 d3_layout_hierarchyVisitAfter(root, function(d) { 26948 d.r = +r(d.value); 26949 }); 26950 d3_layout_hierarchyVisitAfter(root, d3_layout_packSiblings); 26951 if (padding) { 26952 var dr = padding * (radius ? 1 : Math.max(2 * root.r / w, 2 * root.r / h)) / 2; 26953 d3_layout_hierarchyVisitAfter(root, function(d) { 26954 d.r += dr; 26955 }); 26956 d3_layout_hierarchyVisitAfter(root, d3_layout_packSiblings); 26957 d3_layout_hierarchyVisitAfter(root, function(d) { 26958 d.r -= dr; 26959 }); 26960 } 26961 d3_layout_packTransform(root, w / 2, h / 2, radius ? 1 : 1 / Math.max(2 * root.r / w, 2 * root.r / h)); 26962 return nodes; 26963 } 26964 pack.size = function(_) { 26965 if (!arguments.length) return size; 26966 size = _; 26967 return pack; 26968 }; 26969 pack.radius = function(_) { 26970 if (!arguments.length) return radius; 26971 radius = _ == null || typeof _ === "function" ? _ : +_; 26972 return pack; 26973 }; 26974 pack.padding = function(_) { 26975 if (!arguments.length) return padding; 26976 padding = +_; 26977 return pack; 26978 }; 26979 return d3_layout_hierarchyRebind(pack, hierarchy); 26980 }; 26981 function d3_layout_packSort(a, b) { 26982 return a.value - b.value; 26983 } 26984 function d3_layout_packInsert(a, b) { 26985 var c = a._pack_next; 26986 a._pack_next = b; 26987 b._pack_prev = a; 26988 b._pack_next = c; 26989 c._pack_prev = b; 26990 } 26991 function d3_layout_packSplice(a, b) { 26992 a._pack_next = b; 26993 b._pack_prev = a; 26994 } 26995 function d3_layout_packIntersects(a, b) { 26996 var dx = b.x - a.x, dy = b.y - a.y, dr = a.r + b.r; 26997 return .999 * dr * dr > dx * dx + dy * dy; 26998 } 26999 function d3_layout_packSiblings(node) { 27000 if (!(nodes = node.children) || !(n = nodes.length)) return; 27001 var nodes, xMin = Infinity, xMax = -Infinity, yMin = Infinity, yMax = -Infinity, a, b, c, i, j, k, n; 27002 function bound(node) { 27003 xMin = Math.min(node.x - node.r, xMin); 27004 xMax = Math.max(node.x + node.r, xMax); 27005 yMin = Math.min(node.y - node.r, yMin); 27006 yMax = Math.max(node.y + node.r, yMax); 27007 } 27008 nodes.forEach(d3_layout_packLink); 27009 a = nodes[0]; 27010 a.x = -a.r; 27011 a.y = 0; 27012 bound(a); 27013 if (n > 1) { 27014 b = nodes[1]; 27015 b.x = b.r; 27016 b.y = 0; 27017 bound(b); 27018 if (n > 2) { 27019 c = nodes[2]; 27020 d3_layout_packPlace(a, b, c); 27021 bound(c); 27022 d3_layout_packInsert(a, c); 27023 a._pack_prev = c; 27024 d3_layout_packInsert(c, b); 27025 b = a._pack_next; 27026 for (i = 3; i < n; i++) { 27027 d3_layout_packPlace(a, b, c = nodes[i]); 27028 var isect = 0, s1 = 1, s2 = 1; 27029 for (j = b._pack_next; j !== b; j = j._pack_next, s1++) { 27030 if (d3_layout_packIntersects(j, c)) { 27031 isect = 1; 27032 break; 27033 } 27034 } 27035 if (isect == 1) { 27036 for (k = a._pack_prev; k !== j._pack_prev; k = k._pack_prev, s2++) { 27037 if (d3_layout_packIntersects(k, c)) { 27038 break; 27039 } 27040 } 27041 } 27042 if (isect) { 27043 if (s1 < s2 || s1 == s2 && b.r < a.r) d3_layout_packSplice(a, b = j); else d3_layout_packSplice(a = k, b); 27044 i--; 27045 } else { 27046 d3_layout_packInsert(a, c); 27047 b = c; 27048 bound(c); 27049 } 27050 } 27051 } 27052 } 27053 var cx = (xMin + xMax) / 2, cy = (yMin + yMax) / 2, cr = 0; 27054 for (i = 0; i < n; i++) { 27055 c = nodes[i]; 27056 c.x -= cx; 27057 c.y -= cy; 27058 cr = Math.max(cr, c.r + Math.sqrt(c.x * c.x + c.y * c.y)); 27059 } 27060 node.r = cr; 27061 nodes.forEach(d3_layout_packUnlink); 27062 } 27063 function d3_layout_packLink(node) { 27064 node._pack_next = node._pack_prev = node; 27065 } 27066 function d3_layout_packUnlink(node) { 27067 delete node._pack_next; 27068 delete node._pack_prev; 27069 } 27070 function d3_layout_packTransform(node, x, y, k) { 27071 var children = node.children; 27072 node.x = x += k * node.x; 27073 node.y = y += k * node.y; 27074 node.r *= k; 27075 if (children) { 27076 var i = -1, n = children.length; 27077 while (++i < n) d3_layout_packTransform(children[i], x, y, k); 27078 } 27079 } 27080 function d3_layout_packPlace(a, b, c) { 27081 var db = a.r + c.r, dx = b.x - a.x, dy = b.y - a.y; 27082 if (db && (dx || dy)) { 27083 var da = b.r + c.r, dc = dx * dx + dy * dy; 27084 da *= da; 27085 db *= db; 27086 var x = .5 + (db - da) / (2 * dc), y = Math.sqrt(Math.max(0, 2 * da * (db + dc) - (db -= dc) * db - da * da)) / (2 * dc); 27087 c.x = a.x + x * dx + y * dy; 27088 c.y = a.y + x * dy - y * dx; 27089 } else { 27090 c.x = a.x + db; 27091 c.y = a.y; 27092 } 27093 } 27094 d3.layout.tree = function() { 27095 var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ], nodeSize = null; 27096 function tree(d, i) { 27097 var nodes = hierarchy.call(this, d, i), root0 = nodes[0], root1 = wrapTree(root0); 27098 d3_layout_hierarchyVisitAfter(root1, firstWalk), root1.parent.m = -root1.z; 27099 d3_layout_hierarchyVisitBefore(root1, secondWalk); 27100 if (nodeSize) d3_layout_hierarchyVisitBefore(root0, sizeNode); else { 27101 var left = root0, right = root0, bottom = root0; 27102 d3_layout_hierarchyVisitBefore(root0, function(node) { 27103 if (node.x < left.x) left = node; 27104 if (node.x > right.x) right = node; 27105 if (node.depth > bottom.depth) bottom = node; 27106 }); 27107 var tx = separation(left, right) / 2 - left.x, kx = size[0] / (right.x + separation(right, left) / 2 + tx), ky = size[1] / (bottom.depth || 1); 27108 d3_layout_hierarchyVisitBefore(root0, function(node) { 27109 node.x = (node.x + tx) * kx; 27110 node.y = node.depth * ky; 27111 }); 27112 } 27113 return nodes; 27114 } 27115 function wrapTree(root0) { 27116 var root1 = { 27117 A: null, 27118 children: [ root0 ] 27119 }, queue = [ root1 ], node1; 27120 while ((node1 = queue.pop()) != null) { 27121 for (var children = node1.children, child, i = 0, n = children.length; i < n; ++i) { 27122 queue.push((children[i] = child = { 27123 _: children[i], 27124 parent: node1, 27125 children: (child = children[i].children) && child.slice() || [], 27126 A: null, 27127 a: null, 27128 z: 0, 27129 m: 0, 27130 c: 0, 27131 s: 0, 27132 t: null, 27133 i: i 27134 }).a = child); 27135 } 27136 } 27137 return root1.children[0]; 27138 } 27139 function firstWalk(v) { 27140 var children = v.children, siblings = v.parent.children, w = v.i ? siblings[v.i - 1] : null; 27141 if (children.length) { 27142 d3_layout_treeShift(v); 27143 var midpoint = (children[0].z + children[children.length - 1].z) / 2; 27144 if (w) { 27145 v.z = w.z + separation(v._, w._); 27146 v.m = v.z - midpoint; 27147 } else { 27148 v.z = midpoint; 27149 } 27150 } else if (w) { 27151 v.z = w.z + separation(v._, w._); 27152 } 27153 v.parent.A = apportion(v, w, v.parent.A || siblings[0]); 27154 } 27155 function secondWalk(v) { 27156 v._.x = v.z + v.parent.m; 27157 v.m += v.parent.m; 27158 } 27159 function apportion(v, w, ancestor) { 27160 if (w) { 27161 var vip = v, vop = v, vim = w, vom = vip.parent.children[0], sip = vip.m, sop = vop.m, sim = vim.m, som = vom.m, shift; 27162 while (vim = d3_layout_treeRight(vim), vip = d3_layout_treeLeft(vip), vim && vip) { 27163 vom = d3_layout_treeLeft(vom); 27164 vop = d3_layout_treeRight(vop); 27165 vop.a = v; 27166 shift = vim.z + sim - vip.z - sip + separation(vim._, vip._); 27167 if (shift > 0) { 27168 d3_layout_treeMove(d3_layout_treeAncestor(vim, v, ancestor), v, shift); 27169 sip += shift; 27170 sop += shift; 27171 } 27172 sim += vim.m; 27173 sip += vip.m; 27174 som += vom.m; 27175 sop += vop.m; 27176 } 27177 if (vim && !d3_layout_treeRight(vop)) { 27178 vop.t = vim; 27179 vop.m += sim - sop; 27180 } 27181 if (vip && !d3_layout_treeLeft(vom)) { 27182 vom.t = vip; 27183 vom.m += sip - som; 27184 ancestor = v; 27185 } 27186 } 27187 return ancestor; 27188 } 27189 function sizeNode(node) { 27190 node.x *= size[0]; 27191 node.y = node.depth * size[1]; 27192 } 27193 tree.separation = function(x) { 27194 if (!arguments.length) return separation; 27195 separation = x; 27196 return tree; 27197 }; 27198 tree.size = function(x) { 27199 if (!arguments.length) return nodeSize ? null : size; 27200 nodeSize = (size = x) == null ? sizeNode : null; 27201 return tree; 27202 }; 27203 tree.nodeSize = function(x) { 27204 if (!arguments.length) return nodeSize ? size : null; 27205 nodeSize = (size = x) == null ? null : sizeNode; 27206 return tree; 27207 }; 27208 return d3_layout_hierarchyRebind(tree, hierarchy); 27209 }; 27210 function d3_layout_treeSeparation(a, b) { 27211 return a.parent == b.parent ? 1 : 2; 27212 } 27213 function d3_layout_treeLeft(v) { 27214 var children = v.children; 27215 return children.length ? children[0] : v.t; 27216 } 27217 function d3_layout_treeRight(v) { 27218 var children = v.children, n; 27219 return (n = children.length) ? children[n - 1] : v.t; 27220 } 27221 function d3_layout_treeMove(wm, wp, shift) { 27222 var change = shift / (wp.i - wm.i); 27223 wp.c -= change; 27224 wp.s += shift; 27225 wm.c += change; 27226 wp.z += shift; 27227 wp.m += shift; 27228 } 27229 function d3_layout_treeShift(v) { 27230 var shift = 0, change = 0, children = v.children, i = children.length, w; 27231 while (--i >= 0) { 27232 w = children[i]; 27233 w.z += shift; 27234 w.m += shift; 27235 shift += w.s + (change += w.c); 27236 } 27237 } 27238 function d3_layout_treeAncestor(vim, v, ancestor) { 27239 return vim.a.parent === v.parent ? vim.a : ancestor; 27240 } 27241 d3.layout.cluster = function() { 27242 var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ], nodeSize = false; 27243 function cluster(d, i) { 27244 var nodes = hierarchy.call(this, d, i), root = nodes[0], previousNode, x = 0; 27245 d3_layout_hierarchyVisitAfter(root, function(node) { 27246 var children = node.children; 27247 if (children && children.length) { 27248 node.x = d3_layout_clusterX(children); 27249 node.y = d3_layout_clusterY(children); 27250 } else { 27251 node.x = previousNode ? x += separation(node, previousNode) : 0; 27252 node.y = 0; 27253 previousNode = node; 27254 } 27255 }); 27256 var left = d3_layout_clusterLeft(root), right = d3_layout_clusterRight(root), x0 = left.x - separation(left, right) / 2, x1 = right.x + separation(right, left) / 2; 27257 d3_layout_hierarchyVisitAfter(root, nodeSize ? function(node) { 27258 node.x = (node.x - root.x) * size[0]; 27259 node.y = (root.y - node.y) * size[1]; 27260 } : function(node) { 27261 node.x = (node.x - x0) / (x1 - x0) * size[0]; 27262 node.y = (1 - (root.y ? node.y / root.y : 1)) * size[1]; 27263 }); 27264 return nodes; 27265 } 27266 cluster.separation = function(x) { 27267 if (!arguments.length) return separation; 27268 separation = x; 27269 return cluster; 27270 }; 27271 cluster.size = function(x) { 27272 if (!arguments.length) return nodeSize ? null : size; 27273 nodeSize = (size = x) == null; 27274 return cluster; 27275 }; 27276 cluster.nodeSize = function(x) { 27277 if (!arguments.length) return nodeSize ? size : null; 27278 nodeSize = (size = x) != null; 27279 return cluster; 27280 }; 27281 return d3_layout_hierarchyRebind(cluster, hierarchy); 27282 }; 27283 function d3_layout_clusterY(children) { 27284 return 1 + d3.max(children, function(child) { 27285 return child.y; 27286 }); 27287 } 27288 function d3_layout_clusterX(children) { 27289 return children.reduce(function(x, child) { 27290 return x + child.x; 27291 }, 0) / children.length; 27292 } 27293 function d3_layout_clusterLeft(node) { 27294 var children = node.children; 27295 return children && children.length ? d3_layout_clusterLeft(children[0]) : node; 27296 } 27297 function d3_layout_clusterRight(node) { 27298 var children = node.children, n; 27299 return children && (n = children.length) ? d3_layout_clusterRight(children[n - 1]) : node; 27300 } 27301 d3.layout.treemap = function() { 27302 var hierarchy = d3.layout.hierarchy(), round = Math.round, size = [ 1, 1 ], padding = null, pad = d3_layout_treemapPadNull, sticky = false, stickies, mode = "squarify", ratio = .5 * (1 + Math.sqrt(5)); 27303 function scale(children, k) { 27304 var i = -1, n = children.length, child, area; 27305 while (++i < n) { 27306 area = (child = children[i]).value * (k < 0 ? 0 : k); 27307 child.area = isNaN(area) || area <= 0 ? 0 : area; 27308 } 27309 } 27310 function squarify(node) { 27311 var children = node.children; 27312 if (children && children.length) { 27313 var rect = pad(node), row = [], remaining = children.slice(), child, best = Infinity, score, u = mode === "slice" ? rect.dx : mode === "dice" ? rect.dy : mode === "slice-dice" ? node.depth & 1 ? rect.dy : rect.dx : Math.min(rect.dx, rect.dy), n; 27314 scale(remaining, rect.dx * rect.dy / node.value); 27315 row.area = 0; 27316 while ((n = remaining.length) > 0) { 27317 row.push(child = remaining[n - 1]); 27318 row.area += child.area; 27319 if (mode !== "squarify" || (score = worst(row, u)) <= best) { 27320 remaining.pop(); 27321 best = score; 27322 } else { 27323 row.area -= row.pop().area; 27324 position(row, u, rect, false); 27325 u = Math.min(rect.dx, rect.dy); 27326 row.length = row.area = 0; 27327 best = Infinity; 27328 } 27329 } 27330 if (row.length) { 27331 position(row, u, rect, true); 27332 row.length = row.area = 0; 27333 } 27334 children.forEach(squarify); 27335 } 27336 } 27337 function stickify(node) { 27338 var children = node.children; 27339 if (children && children.length) { 27340 var rect = pad(node), remaining = children.slice(), child, row = []; 27341 scale(remaining, rect.dx * rect.dy / node.value); 27342 row.area = 0; 27343 while (child = remaining.pop()) { 27344 row.push(child); 27345 row.area += child.area; 27346 if (child.z != null) { 27347 position(row, child.z ? rect.dx : rect.dy, rect, !remaining.length); 27348 row.length = row.area = 0; 27349 } 27350 }
vendor: 12,778 bytes, lines 27351-27745
27351 children.forEach(stickify); 27352 } 27353 } 27354 function worst(row, u) { 27355 var s = row.area, r, rmax = 0, rmin = Infinity, i = -1, n = row.length; 27356 while (++i < n) { 27357 if (!(r = row[i].area)) continue; 27358 if (r < rmin) rmin = r; 27359 if (r > rmax) rmax = r; 27360 } 27361 s *= s; 27362 u *= u; 27363 return s ? Math.max(u * rmax * ratio / s, s / (u * rmin * ratio)) : Infinity; 27364 } 27365 function position(row, u, rect, flush) { 27366 var i = -1, n = row.length, x = rect.x, y = rect.y, v = u ? round(row.area / u) : 0, o; 27367 if (u == rect.dx) { 27368 if (flush || v > rect.dy) v = rect.dy; 27369 while (++i < n) { 27370 o = row[i]; 27371 o.x = x; 27372 o.y = y; 27373 o.dy = v; 27374 x += o.dx = Math.min(rect.x + rect.dx - x, v ? round(o.area / v) : 0); 27375 } 27376 o.z = true; 27377 o.dx += rect.x + rect.dx - x; 27378 rect.y += v; 27379 rect.dy -= v; 27380 } else { 27381 if (flush || v > rect.dx) v = rect.dx; 27382 while (++i < n) { 27383 o = row[i]; 27384 o.x = x; 27385 o.y = y; 27386 o.dx = v; 27387 y += o.dy = Math.min(rect.y + rect.dy - y, v ? round(o.area / v) : 0); 27388 } 27389 o.z = false; 27390 o.dy += rect.y + rect.dy - y; 27391 rect.x += v; 27392 rect.dx -= v; 27393 } 27394 } 27395 function treemap(d) { 27396 var nodes = stickies || hierarchy(d), root = nodes[0]; 27397 root.x = 0; 27398 root.y = 0; 27399 root.dx = size[0]; 27400 root.dy = size[1]; 27401 if (stickies) hierarchy.revalue(root); 27402 scale([ root ], root.dx * root.dy / root.value); 27403 (stickies ? stickify : squarify)(root); 27404 if (sticky) stickies = nodes; 27405 return nodes; 27406 } 27407 treemap.size = function(x) { 27408 if (!arguments.length) return size; 27409 size = x; 27410 return treemap; 27411 }; 27412 treemap.padding = function(x) { 27413 if (!arguments.length) return padding; 27414 function padFunction(node) { 27415 var p = x.call(treemap, node, node.depth); 27416 return p == null ? d3_layout_treemapPadNull(node) : d3_layout_treemapPad(node, typeof p === "number" ? [ p, p, p, p ] : p); 27417 } 27418 function padConstant(node) { 27419 return d3_layout_treemapPad(node, x); 27420 } 27421 var type; 27422 pad = (padding = x) == null ? d3_layout_treemapPadNull : (type = typeof x) === "function" ? padFunction : type === "number" ? (x = [ x, x, x, x ], 27423 padConstant) : padConstant; 27424 return treemap; 27425 }; 27426 treemap.round = function(x) { 27427 if (!arguments.length) return round != Number; 27428 round = x ? Math.round : Number; 27429 return treemap; 27430 }; 27431 treemap.sticky = function(x) { 27432 if (!arguments.length) return sticky; 27433 sticky = x; 27434 stickies = null; 27435 return treemap; 27436 }; 27437 treemap.ratio = function(x) { 27438 if (!arguments.length) return ratio; 27439 ratio = x; 27440 return treemap; 27441 }; 27442 treemap.mode = function(x) { 27443 if (!arguments.length) return mode; 27444 mode = x + ""; 27445 return treemap; 27446 }; 27447 return d3_layout_hierarchyRebind(treemap, hierarchy); 27448 }; 27449 function d3_layout_treemapPadNull(node) { 27450 return { 27451 x: node.x, 27452 y: node.y, 27453 dx: node.dx, 27454 dy: node.dy 27455 }; 27456 } 27457 function d3_layout_treemapPad(node, padding) { 27458 var x = node.x + padding[3], y = node.y + padding[0], dx = node.dx - padding[1] - padding[3], dy = node.dy - padding[0] - padding[2]; 27459 if (dx < 0) { 27460 x += dx / 2; 27461 dx = 0; 27462 } 27463 if (dy < 0) { 27464 y += dy / 2; 27465 dy = 0; 27466 } 27467 return { 27468 x: x, 27469 y: y, 27470 dx: dx, 27471 dy: dy 27472 }; 27473 } 27474 d3.random = { 27475 normal: function(µ, Ï) { 27476 var n = arguments.length; 27477 if (n < 2) Ï = 1; 27478 if (n < 1) µ = 0; 27479 return function() { 27480 var x, y, r; 27481 do { 27482 x = Math.random() * 2 - 1; 27483 y = Math.random() * 2 - 1; 27484 r = x * x + y * y; 27485 } while (!r || r > 1); 27486 return µ + Ï * x * Math.sqrt(-2 * Math.log(r) / r); 27487 }; 27488 }, 27489 logNormal: function() { 27490 var random = d3.random.normal.apply(d3, arguments); 27491 return function() { 27492 return Math.exp(random()); 27493 }; 27494 }, 27495 bates: function(m) { 27496 var random = d3.random.irwinHall(m); 27497 return function() { 27498 return random() / m; 27499 }; 27500 }, 27501 irwinHall: function(m) { 27502 return function() { 27503 for (var s = 0, j = 0; j < m; j++) s += Math.random(); 27504 return s; 27505 }; 27506 } 27507 }; 27508 d3.scale = {}; 27509 function d3_scaleExtent(domain) { 27510 var start = domain[0], stop = domain[domain.length - 1]; 27511 return start < stop ? [ start, stop ] : [ stop, start ]; 27512 } 27513 function d3_scaleRange(scale) { 27514 return scale.rangeExtent ? scale.rangeExtent() : d3_scaleExtent(scale.range()); 27515 } 27516 function d3_scale_bilinear(domain, range, uninterpolate, interpolate) { 27517 var u = uninterpolate(domain[0], domain[1]), i = interpolate(range[0], range[1]); 27518 return function(x) { 27519 return i(u(x)); 27520 }; 27521 } 27522 function d3_scale_nice(domain, nice) { 27523 var i0 = 0, i1 = domain.length - 1, x0 = domain[i0], x1 = domain[i1], dx; 27524 if (x1 < x0) { 27525 dx = i0, i0 = i1, i1 = dx; 27526 dx = x0, x0 = x1, x1 = dx; 27527 } 27528 domain[i0] = nice.floor(x0); 27529 domain[i1] = nice.ceil(x1); 27530 return domain; 27531 } 27532 function d3_scale_niceStep(step) { 27533 return step ? { 27534 floor: function(x) { 27535 return Math.floor(x / step) * step; 27536 }, 27537 ceil: function(x) { 27538 return Math.ceil(x / step) * step; 27539 } 27540 } : d3_scale_niceIdentity; 27541 } 27542 var d3_scale_niceIdentity = { 27543 floor: d3_identity, 27544 ceil: d3_identity 27545 }; 27546 function d3_scale_polylinear(domain, range, uninterpolate, interpolate) { 27547 var u = [], i = [], j = 0, k = Math.min(domain.length, range.length) - 1; 27548 if (domain[k] < domain[0]) { 27549 domain = domain.slice().reverse(); 27550 range = range.slice().reverse(); 27551 } 27552 while (++j <= k) { 27553 u.push(uninterpolate(domain[j - 1], domain[j])); 27554 i.push(interpolate(range[j - 1], range[j])); 27555 } 27556 return function(x) { 27557 var j = d3.bisect(domain, x, 1, k) - 1; 27558 return i[j](u[j](x)); 27559 }; 27560 } 27561 d3.scale.linear = function() { 27562 return d3_scale_linear([ 0, 1 ], [ 0, 1 ], d3_interpolate, false); 27563 }; 27564 function d3_scale_linear(domain, range, interpolate, clamp) { 27565 var output, input; 27566 function rescale() { 27567 var linear = Math.min(domain.length, range.length) > 2 ? d3_scale_polylinear : d3_scale_bilinear, uninterpolate = clamp ? d3_uninterpolateClamp : d3_uninterpolateNumber; 27568 output = linear(domain, range, uninterpolate, interpolate); 27569 input = linear(range, domain, uninterpolate, d3_interpolate); 27570 return scale; 27571 } 27572 function scale(x) { 27573 return output(x); 27574 } 27575 scale.invert = function(y) { 27576 return input(y); 27577 }; 27578 scale.domain = function(x) { 27579 if (!arguments.length) return domain; 27580 domain = x.map(Number); 27581 return rescale(); 27582 }; 27583 scale.range = function(x) { 27584 if (!arguments.length) return range; 27585 range = x; 27586 return rescale(); 27587 }; 27588 scale.rangeRound = function(x) { 27589 return scale.range(x).interpolate(d3_interpolateRound); 27590 }; 27591 scale.clamp = function(x) { 27592 if (!arguments.length) return clamp; 27593 clamp = x; 27594 return rescale(); 27595 }; 27596 scale.interpolate = function(x) { 27597 if (!arguments.length) return interpolate; 27598 interpolate = x; 27599 return rescale(); 27600 }; 27601 scale.ticks = function(m) { 27602 return d3_scale_linearTicks(domain, m); 27603 }; 27604 scale.tickFormat = function(m, format) { 27605 return d3_scale_linearTickFormat(domain, m, format); 27606 }; 27607 scale.nice = function(m) { 27608 d3_scale_linearNice(domain, m); 27609 return rescale(); 27610 }; 27611 scale.copy = function() { 27612 return d3_scale_linear(domain, range, interpolate, clamp); 27613 }; 27614 return rescale(); 27615 } 27616 function d3_scale_linearRebind(scale, linear) { 27617 return d3.rebind(scale, linear, "range", "rangeRound", "interpolate", "clamp"); 27618 } 27619 function d3_scale_linearNice(domain, m) { 27620 return d3_scale_nice(domain, d3_scale_niceStep(d3_scale_linearTickRange(domain, m)[2])); 27621 } 27622 function d3_scale_linearTickRange(domain, m) { 27623 if (m == null) m = 10; 27624 var extent = d3_scaleExtent(domain), span = extent[1] - extent[0], step = Math.pow(10, Math.floor(Math.log(span / m) / Math.LN10)), err = m / span * step; 27625 if (err <= .15) step *= 10; else if (err <= .35) step *= 5; else if (err <= .75) step *= 2; 27626 extent[0] = Math.ceil(extent[0] / step) * step; 27627 extent[1] = Math.floor(extent[1] / step) * step + step * .5; 27628 extent[2] = step; 27629 return extent; 27630 } 27631 function d3_scale_linearTicks(domain, m) { 27632 return d3.range.apply(d3, d3_scale_linearTickRange(domain, m)); 27633 } 27634 function d3_scale_linearTickFormat(domain, m, format) { 27635 var range = d3_scale_linearTickRange(domain, m); 27636 if (format) { 27637 var match = d3_format_re.exec(format); 27638 match.shift(); 27639 if (match[8] === "s") { 27640 var prefix = d3.formatPrefix(Math.max(abs(range[0]), abs(range[1]))); 27641 if (!match[7]) match[7] = "." + d3_scale_linearPrecision(prefix.scale(range[2])); 27642 match[8] = "f"; 27643 format = d3.format(match.join("")); 27644 return function(d) { 27645 return format(prefix.scale(d)) + prefix.symbol; 27646 }; 27647 } 27648 if (!match[7]) match[7] = "." + d3_scale_linearFormatPrecision(match[8], range); 27649 format = match.join(""); 27650 } else { 27651 format = ",." + d3_scale_linearPrecision(range[2]) + "f"; 27652 } 27653 return d3.format(format); 27654 } 27655 var d3_scale_linearFormatSignificant = { 27656 s: 1, 27657 g: 1, 27658 p: 1, 27659 r: 1, 27660 e: 1 27661 }; 27662 function d3_scale_linearPrecision(value) { 27663 return -Math.floor(Math.log(value) / Math.LN10 + .01); 27664 } 27665 function d3_scale_linearFormatPrecision(type, range) { 27666 var p = d3_scale_linearPrecision(range[2]); 27667 return type in d3_scale_linearFormatSignificant ? Math.abs(p - d3_scale_linearPrecision(Math.max(abs(range[0]), abs(range[1])))) + +(type !== "e") : p - (type === "%") * 2; 27668 } 27669 d3.scale.log = function() { 27670 return d3_scale_log(d3.scale.linear().domain([ 0, 1 ]), 10, true, [ 1, 10 ]); 27671 }; 27672 function d3_scale_log(linear, base, positive, domain) { 27673 function log(x) { 27674 return (positive ? Math.log(x < 0 ? 0 : x) : -Math.log(x > 0 ? 0 : -x)) / Math.log(base); 27675 } 27676 function pow(x) { 27677 return positive ? Math.pow(base, x) : -Math.pow(base, -x); 27678 } 27679 function scale(x) { 27680 return linear(log(x)); 27681 } 27682 scale.invert = function(x) { 27683 return pow(linear.invert(x)); 27684 }; 27685 scale.domain = function(x) { 27686 if (!arguments.length) return domain; 27687 positive = x[0] >= 0; 27688 linear.domain((domain = x.map(Number)).map(log)); 27689 return scale; 27690 }; 27691 scale.base = function(_) { 27692 if (!arguments.length) return base; 27693 base = +_; 27694 linear.domain(domain.map(log)); 27695 return scale; 27696 }; 27697 scale.nice = function() { 27698 var niced = d3_scale_nice(domain.map(log), positive ? Math : d3_scale_logNiceNegative); 27699 linear.domain(niced); 27700 domain = niced.map(pow); 27701 return scale; 27702 }; 27703 scale.ticks = function() { 27704 var extent = d3_scaleExtent(domain), ticks = [], u = extent[0], v = extent[1], i = Math.floor(log(u)), j = Math.ceil(log(v)), n = base % 1 ? 2 : base; 27705 if (isFinite(j - i)) { 27706 if (positive) { 27707 for (;i < j; i++) for (var k = 1; k < n; k++) ticks.push(pow(i) * k); 27708 ticks.push(pow(i)); 27709 } else { 27710 ticks.push(pow(i)); 27711 for (;i++ < j; ) for (var k = n - 1; k > 0; k--) ticks.push(pow(i) * k); 27712 } 27713 for (i = 0; ticks[i] < u; i++) {} 27714 for (j = ticks.length; ticks[j - 1] > v; j--) {} 27715 ticks = ticks.slice(i, j); 27716 } 27717 return ticks; 27718 }; 27719 scale.tickFormat = function(n, format) { 27720 if (!arguments.length) return d3_scale_logFormat; 27721 if (arguments.length < 2) format = d3_scale_logFormat; else if (typeof format !== "function") format = d3.format(format); 27722 var k = Math.max(.1, n / scale.ticks().length), f = positive ? (e = 1e-12, Math.ceil) : (e = -1e-12, 27723 Math.floor), e; 27724 return function(d) { 27725 return d / pow(f(log(d) + e)) <= k ? format(d) : ""; 27726 }; 27727 }; 27728 scale.copy = function() { 27729 return d3_scale_log(linear.copy(), base, positive, domain); 27730 }; 27731 return d3_scale_linearRebind(scale, linear); 27732 } 27733 var d3_scale_logFormat = d3.format(".0e"), d3_scale_logNiceNegative = { 27734 floor: function(x) { 27735 return -Math.ceil(-x); 27736 }, 27737 ceil: function(x) { 27738 return -Math.floor(-x); 27739 } 27740 }; 27741 d3.scale.pow = function() { 27742 return d3_scale_pow(d3.scale.linear(), 1, [ 0, 1 ]); 27743 }; 27744 function d3_scale_pow(linear, exponent, domain) { 27745 var powp = d3_scale_powPow(exponent), powb = d3_scale_powPow(1 / exponent);
vendor: 8,414 bytes, lines 27746-27995
27746 function scale(x) { 27747 return linear(powp(x)); 27748 } 27749 scale.invert = function(x) { 27750 return powb(linear.invert(x)); 27751 }; 27752 scale.domain = function(x) { 27753 if (!arguments.length) return domain; 27754 linear.domain((domain = x.map(Number)).map(powp)); 27755 return scale; 27756 }; 27757 scale.ticks = function(m) { 27758 return d3_scale_linearTicks(domain, m); 27759 }; 27760 scale.tickFormat = function(m, format) { 27761 return d3_scale_linearTickFormat(domain, m, format); 27762 }; 27763 scale.nice = function(m) { 27764 return scale.domain(d3_scale_linearNice(domain, m)); 27765 }; 27766 scale.exponent = function(x) { 27767 if (!arguments.length) return exponent; 27768 powp = d3_scale_powPow(exponent = x); 27769 powb = d3_scale_powPow(1 / exponent); 27770 linear.domain(domain.map(powp)); 27771 return scale; 27772 }; 27773 scale.copy = function() { 27774 return d3_scale_pow(linear.copy(), exponent, domain); 27775 }; 27776 return d3_scale_linearRebind(scale, linear); 27777 } 27778 function d3_scale_powPow(e) { 27779 return function(x) { 27780 return x < 0 ? -Math.pow(-x, e) : Math.pow(x, e); 27781 }; 27782 } 27783 d3.scale.sqrt = function() { 27784 return d3.scale.pow().exponent(.5); 27785 }; 27786 d3.scale.ordinal = function() { 27787 return d3_scale_ordinal([], { 27788 t: "range", 27789 a: [ [] ] 27790 }); 27791 }; 27792 function d3_scale_ordinal(domain, ranger) { 27793 var index, range, rangeBand; 27794 function scale(x) { 27795 return range[((index.get(x) || (ranger.t === "range" ? index.set(x, domain.push(x)) : NaN)) - 1) % range.length]; 27796 } 27797 function steps(start, step) { 27798 return d3.range(domain.length).map(function(i) { 27799 return start + step * i; 27800 }); 27801 } 27802 scale.domain = function(x) { 27803 if (!arguments.length) return domain; 27804 domain = []; 27805 index = new d3_Map(); 27806 var i = -1, n = x.length, xi; 27807 while (++i < n) if (!index.has(xi = x[i])) index.set(xi, domain.push(xi)); 27808 return scale[ranger.t].apply(scale, ranger.a); 27809 }; 27810 scale.range = function(x) { 27811 if (!arguments.length) return range; 27812 range = x; 27813 rangeBand = 0; 27814 ranger = { 27815 t: "range", 27816 a: arguments 27817 }; 27818 return scale; 27819 }; 27820 scale.rangePoints = function(x, padding) { 27821 if (arguments.length < 2) padding = 0; 27822 var start = x[0], stop = x[1], step = (stop - start) / (Math.max(1, domain.length - 1) + padding); 27823 range = steps(domain.length < 2 ? (start + stop) / 2 : start + step * padding / 2, step); 27824 rangeBand = 0; 27825 ranger = { 27826 t: "rangePoints", 27827 a: arguments 27828 }; 27829 return scale; 27830 }; 27831 scale.rangeBands = function(x, padding, outerPadding) { 27832 if (arguments.length < 2) padding = 0; 27833 if (arguments.length < 3) outerPadding = padding; 27834 var reverse = x[1] < x[0], start = x[reverse - 0], stop = x[1 - reverse], step = (stop - start) / (domain.length - padding + 2 * outerPadding); 27835 range = steps(start + step * outerPadding, step); 27836 if (reverse) range.reverse(); 27837 rangeBand = step * (1 - padding); 27838 ranger = { 27839 t: "rangeBands", 27840 a: arguments 27841 }; 27842 return scale; 27843 }; 27844 scale.rangeRoundBands = function(x, padding, outerPadding) { 27845 if (arguments.length < 2) padding = 0; 27846 if (arguments.length < 3) outerPadding = padding; 27847 var reverse = x[1] < x[0], start = x[reverse - 0], stop = x[1 - reverse], step = Math.floor((stop - start) / (domain.length - padding + 2 * outerPadding)), error = stop - start - (domain.length - padding) * step; 27848 range = steps(start + Math.round(error / 2), step); 27849 if (reverse) range.reverse(); 27850 rangeBand = Math.round(step * (1 - padding)); 27851 ranger = { 27852 t: "rangeRoundBands", 27853 a: arguments 27854 }; 27855 return scale; 27856 }; 27857 scale.rangeBand = function() { 27858 return rangeBand; 27859 }; 27860 scale.rangeExtent = function() { 27861 return d3_scaleExtent(ranger.a[0]); 27862 }; 27863 scale.copy = function() { 27864 return d3_scale_ordinal(domain, ranger); 27865 }; 27866 return scale.domain(domain); 27867 } 27868 d3.scale.category10 = function() { 27869 return d3.scale.ordinal().range(d3_category10); 27870 }; 27871 d3.scale.category20 = function() { 27872 return d3.scale.ordinal().range(d3_category20); 27873 }; 27874 d3.scale.category20b = function() { 27875 return d3.scale.ordinal().range(d3_category20b); 27876 }; 27877 d3.scale.category20c = function() { 27878 return d3.scale.ordinal().range(d3_category20c); 27879 }; 27880 var d3_category10 = [ 2062260, 16744206, 2924588, 14034728, 9725885, 9197131, 14907330, 8355711, 12369186, 1556175 ].map(d3_rgbString); 27881 var d3_category20 = [ 2062260, 11454440, 16744206, 16759672, 2924588, 10018698, 14034728, 16750742, 9725885, 12955861, 9197131, 12885140, 14907330, 16234194, 8355711, 13092807, 12369186, 14408589, 1556175, 10410725 ].map(d3_rgbString); 27882 var d3_category20b = [ 3750777, 5395619, 7040719, 10264286, 6519097, 9216594, 11915115, 13556636, 9202993, 12426809, 15186514, 15190932, 8666169, 11356490, 14049643, 15177372, 8077683, 10834324, 13528509, 14589654 ].map(d3_rgbString); 27883 var d3_category20c = [ 3244733, 7057110, 10406625, 13032431, 15095053, 16616764, 16625259, 16634018, 3253076, 7652470, 10607003, 13101504, 7695281, 10394312, 12369372, 14342891, 6513507, 9868950, 12434877, 14277081 ].map(d3_rgbString); 27884 d3.scale.quantile = function() { 27885 return d3_scale_quantile([], []); 27886 }; 27887 function d3_scale_quantile(domain, range) { 27888 var thresholds; 27889 function rescale() { 27890 var k = 0, q = range.length; 27891 thresholds = []; 27892 while (++k < q) thresholds[k - 1] = d3.quantile(domain, k / q); 27893 return scale; 27894 } 27895 function scale(x) { 27896 if (!isNaN(x = +x)) return range[d3.bisect(thresholds, x)]; 27897 } 27898 scale.domain = function(x) { 27899 if (!arguments.length) return domain; 27900 domain = x.map(d3_number).filter(d3_numeric).sort(d3_ascending); 27901 return rescale(); 27902 }; 27903 scale.range = function(x) { 27904 if (!arguments.length) return range; 27905 range = x; 27906 return rescale(); 27907 }; 27908 scale.quantiles = function() { 27909 return thresholds; 27910 }; 27911 scale.invertExtent = function(y) { 27912 y = range.indexOf(y); 27913 return y < 0 ? [ NaN, NaN ] : [ y > 0 ? thresholds[y - 1] : domain[0], y < thresholds.length ? thresholds[y] : domain[domain.length - 1] ]; 27914 }; 27915 scale.copy = function() { 27916 return d3_scale_quantile(domain, range); 27917 }; 27918 return rescale(); 27919 } 27920 d3.scale.quantize = function() { 27921 return d3_scale_quantize(0, 1, [ 0, 1 ]); 27922 }; 27923 function d3_scale_quantize(x0, x1, range) { 27924 var kx, i; 27925 function scale(x) { 27926 return range[Math.max(0, Math.min(i, Math.floor(kx * (x - x0))))]; 27927 } 27928 function rescale() { 27929 kx = range.length / (x1 - x0); 27930 i = range.length - 1; 27931 return scale; 27932 } 27933 scale.domain = function(x) { 27934 if (!arguments.length) return [ x0, x1 ]; 27935 x0 = +x[0]; 27936 x1 = +x[x.length - 1]; 27937 return rescale(); 27938 }; 27939 scale.range = function(x) { 27940 if (!arguments.length) return range; 27941 range = x; 27942 return rescale(); 27943 }; 27944 scale.invertExtent = function(y) { 27945 y = range.indexOf(y); 27946 y = y < 0 ? NaN : y / kx + x0; 27947 return [ y, y + 1 / kx ]; 27948 }; 27949 scale.copy = function() { 27950 return d3_scale_quantize(x0, x1, range); 27951 }; 27952 return rescale(); 27953 } 27954 d3.scale.threshold = function() { 27955 return d3_scale_threshold([ .5 ], [ 0, 1 ]); 27956 }; 27957 function d3_scale_threshold(domain, range) { 27958 function scale(x) { 27959 if (x <= x) return range[d3.bisect(domain, x)]; 27960 } 27961 scale.domain = function(_) { 27962 if (!arguments.length) return domain; 27963 domain = _; 27964 return scale; 27965 }; 27966 scale.range = function(_) { 27967 if (!arguments.length) return range; 27968 range = _; 27969 return scale; 27970 }; 27971 scale.invertExtent = function(y) { 27972 y = range.indexOf(y); 27973 return [ domain[y - 1], domain[y] ]; 27974 }; 27975 scale.copy = function() { 27976 return d3_scale_threshold(domain, range); 27977 }; 27978 return scale; 27979 } 27980 d3.scale.identity = function() { 27981 return d3_scale_identity([ 0, 1 ]); 27982 }; 27983 function d3_scale_identity(domain) { 27984 function identity(x) { 27985 return +x; 27986 } 27987 identity.invert = identity; 27988 identity.domain = identity.range = function(x) { 27989 if (!arguments.length) return domain; 27990 domain = x.map(identity); 27991 return identity; 27992 }; 27993 identity.ticks = function(m) { 27994 return d3_scale_linearTicks(domain, m); 27995 };
27996 identity.tickFormat = function(m, format) { 27997 return d3_scale_linearTickFormat(domain, m, format); 27998 }; 27999 identity.copy = function() { 28000 return d3_scale_identity(domain); 28001 }; 28002 return identity; 28003 } 28004 d3.svg = {}; 28005 d3.svg.arc = function() { 28006 var innerRadius = d3_svg_arcInnerRadius, outerRadius = d3_svg_arcOuterRadius, startAngle = d3_svg_arcStartAngle, endAngle = d3_svg_arcEndAngle; 28007 function arc() { 28008 var r0 = innerRadius.apply(this, arguments), r1 = outerRadius.apply(this, arguments), a0 = startAngle.apply(this, arguments) + d3_svg_arcOffset, a1 = endAngle.apply(this, arguments) + d3_svg_arcOffset, da = (a1 < a0 && (da = a0, 28009 a0 = a1, a1 = da), a1 - a0), df = da < Ï ? "0" : "1", c0 = Math.cos(a0), s0 = Math.sin(a0), c1 = Math.cos(a1), s1 = Math.sin(a1); 28010 return da >= d3_svg_arcMax ? r0 ? "M0," + r1 + "A" + r1 + "," + r1 + " 0 1,1 0," + -r1 + "A" + r1 + "," + r1 + " 0 1,1 0," + r1 + "M0," + r0 + "A" + r0 + "," + r0 + " 0 1,0 0," + -r0 + "A" + r0 + "," + r0 + " 0 1,0 0," + r0 + "Z" : "M0," + r1 + "A" + r1 + "," + r1 + " 0 1,1 0," + -r1 + "A" + r1 + "," + r1 + " 0 1,1 0," + r1 + "Z" : r0 ? "M" + r1 * c0 + "," + r1 * s0 + "A" + r1 + "," + r1 + " 0 " + df + ",1 " + r1 * c1 + "," + r1 * s1 + "L" + r0 * c1 + "," + r0 * s1 + "A" + r0 + "," + r0 + " 0 " + df + ",0 " + r0 * c0 + "," + r0 * s0 + "Z" : "M" + r1 * c0 + "," + r1 * s0 + "A" + r1 + "," + r1 + " 0 " + df + ",1 " + r1 * c1 + "," + r1 * s1 + "L0,0" + "Z"; 28011 } 28012 arc.innerRadius = function(v) { 28013 if (!arguments.length) return innerRadius; 28014 innerRadius = d3_functor(v); 28015 return arc; 28016 }; 28017 arc.outerRadius = function(v) { 28018 if (!arguments.length) return outerRadius; 28019 outerRadius = d3_functor(v); 28020 return arc; 28021 }; 28022 arc.startAngle = function(v) { 28023 if (!arguments.length) return startAngle; 28024 startAngle = d3_functor(v); 28025 return arc; 28026 }; 28027 arc.endAngle = function(v) { 28028 if (!arguments.length) return endAngle; 28029 endAngle = d3_functor(v); 28030 return arc; 28031 }; 28032 arc.centroid = function() { 28033 var r = (innerRadius.apply(this, arguments) + outerRadius.apply(this, arguments)) / 2, a = (startAngle.apply(this, arguments) + endAngle.apply(this, arguments)) / 2 + d3_svg_arcOffset; 28034 return [ Math.cos(a) * r, Math.sin(a) * r ]; 28035 }; 28036 return arc; 28037 }; 28038 var d3_svg_arcOffset = -halfÏ, d3_svg_arcMax = Ï - ε; 28039 function d3_svg_arcInnerRadius(d) { 28040 return d.innerRadius; 28041 } 28042 function d3_svg_arcOuterRadius(d) { 28043 return d.outerRadius; 28044 } 28045 function d3_svg_arcStartAngle(d) { 28046 return d.startAngle; 28047 } 28048 function d3_svg_arcEndAngle(d) { 28049 return d.endAngle; 28050 } 28051 function d3_svg_line(projection) { 28052 var x = d3_geom_pointX, y = d3_geom_pointY, defined = d3_true, interpolate = d3_svg_lineLinear, interpolateKey = interpolate.key, tension = .7; 28053 function line(data) { 28054 var segments = [], points = [], i = -1, n = data.length, d, fx = d3_functor(x), fy = d3_functor(y); 28055 function segment() { 28056 segments.push("M", interpolate(projection(points), tension)); 28057 } 28058 while (++i < n) { 28059 if (defined.call(this, d = data[i], i)) { 28060 points.push([ +fx.call(this, d, i), +fy.call(this, d, i) ]); 28061 } else if (points.length) { 28062 segment(); 28063 points = []; 28064 } 28065 } 28066 if (points.length) segment(); 28067 return segments.length ? segments.join("") : null; 28068 } 28069 line.x = function(_) { 28070 if (!arguments.length) return x; 28071 x = _; 28072 return line; 28073 }; 28074 line.y = function(_) { 28075 if (!arguments.length) return y; 28076 y = _; 28077 return line; 28078 }; 28079 line.defined = function(_) { 28080 if (!arguments.length) return defined; 28081 defined = _; 28082 return line; 28083 }; 28084 line.interpolate = function(_) { 28085 if (!arguments.length) return interpolateKey; 28086 if (typeof _ === "function") interpolateKey = interpolate = _; else interpolateKey = (interpolate = d3_svg_lineInterpolators.get(_) || d3_svg_lineLinear).key; 28087 return line; 28088 }; 28089 line.tension = function(_) { 28090 if (!arguments.length) return tension; 28091 tension = _; 28092 return line; 28093 }; 28094 return line; 28095 } 28096 d3.svg.line = function() { 28097 return d3_svg_line(d3_identity); 28098 }; 28099 var d3_svg_lineInterpolators = d3.map({ 28100 linear: d3_svg_lineLinear, 28101 "linear-closed": d3_svg_lineLinearClosed, 28102 step: d3_svg_lineStep, 28103 "step-before": d3_svg_lineStepBefore, 28104 "step-after": d3_svg_lineStepAfter, 28105 basis: d3_svg_lineBasis, 28106 "basis-open": d3_svg_lineBasisOpen, 28107 "basis-closed": d3_svg_lineBasisClosed, 28108 bundle: d3_svg_lineBundle, 28109 cardinal: d3_svg_lineCardinal, 28110 "cardinal-open": d3_svg_lineCardinalOpen, 28111 "cardinal-closed": d3_svg_lineCardinalClosed, 28112 monotone: d3_svg_lineMonotone 28113 });
vendor: 12,000 bytes, lines 28114-28430
28114 d3_svg_lineInterpolators.forEach(function(key, value) { 28115 value.key = key; 28116 value.closed = /-closed$/.test(key); 28117 }); 28118 function d3_svg_lineLinear(points) { 28119 return points.join("L"); 28120 } 28121 function d3_svg_lineLinearClosed(points) { 28122 return d3_svg_lineLinear(points) + "Z"; 28123 } 28124 function d3_svg_lineStep(points) { 28125 var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ]; 28126 while (++i < n) path.push("H", (p[0] + (p = points[i])[0]) / 2, "V", p[1]); 28127 if (n > 1) path.push("H", p[0]); 28128 return path.join(""); 28129 } 28130 function d3_svg_lineStepBefore(points) { 28131 var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ]; 28132 while (++i < n) path.push("V", (p = points[i])[1], "H", p[0]); 28133 return path.join(""); 28134 } 28135 function d3_svg_lineStepAfter(points) { 28136 var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ]; 28137 while (++i < n) path.push("H", (p = points[i])[0], "V", p[1]); 28138 return path.join(""); 28139 } 28140 function d3_svg_lineCardinalOpen(points, tension) { 28141 return points.length < 4 ? d3_svg_lineLinear(points) : points[1] + d3_svg_lineHermite(points.slice(1, points.length - 1), d3_svg_lineCardinalTangents(points, tension)); 28142 } 28143 function d3_svg_lineCardinalClosed(points, tension) { 28144 return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite((points.push(points[0]), 28145 points), d3_svg_lineCardinalTangents([ points[points.length - 2] ].concat(points, [ points[1] ]), tension)); 28146 } 28147 function d3_svg_lineCardinal(points, tension) { 28148 return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite(points, d3_svg_lineCardinalTangents(points, tension)); 28149 } 28150 function d3_svg_lineHermite(points, tangents) { 28151 if (tangents.length < 1 || points.length != tangents.length && points.length != tangents.length + 2) { 28152 return d3_svg_lineLinear(points); 28153 } 28154 var quad = points.length != tangents.length, path = "", p0 = points[0], p = points[1], t0 = tangents[0], t = t0, pi = 1; 28155 if (quad) { 28156 path += "Q" + (p[0] - t0[0] * 2 / 3) + "," + (p[1] - t0[1] * 2 / 3) + "," + p[0] + "," + p[1]; 28157 p0 = points[1]; 28158 pi = 2; 28159 } 28160 if (tangents.length > 1) { 28161 t = tangents[1]; 28162 p = points[pi]; 28163 pi++; 28164 path += "C" + (p0[0] + t0[0]) + "," + (p0[1] + t0[1]) + "," + (p[0] - t[0]) + "," + (p[1] - t[1]) + "," + p[0] + "," + p[1]; 28165 for (var i = 2; i < tangents.length; i++, pi++) { 28166 p = points[pi]; 28167 t = tangents[i]; 28168 path += "S" + (p[0] - t[0]) + "," + (p[1] - t[1]) + "," + p[0] + "," + p[1]; 28169 } 28170 } 28171 if (quad) { 28172 var lp = points[pi]; 28173 path += "Q" + (p[0] + t[0] * 2 / 3) + "," + (p[1] + t[1] * 2 / 3) + "," + lp[0] + "," + lp[1]; 28174 } 28175 return path; 28176 } 28177 function d3_svg_lineCardinalTangents(points, tension) { 28178 var tangents = [], a = (1 - tension) / 2, p0, p1 = points[0], p2 = points[1], i = 1, n = points.length; 28179 while (++i < n) { 28180 p0 = p1; 28181 p1 = p2; 28182 p2 = points[i]; 28183 tangents.push([ a * (p2[0] - p0[0]), a * (p2[1] - p0[1]) ]); 28184 } 28185 return tangents; 28186 } 28187 function d3_svg_lineBasis(points) { 28188 if (points.length < 3) return d3_svg_lineLinear(points); 28189 var i = 1, n = points.length, pi = points[0], x0 = pi[0], y0 = pi[1], px = [ x0, x0, x0, (pi = points[1])[0] ], py = [ y0, y0, y0, pi[1] ], path = [ x0, ",", y0, "L", d3_svg_lineDot4(d3_svg_lineBasisBezier3, px), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, py) ]; 28190 points.push(points[n - 1]); 28191 while (++i <= n) { 28192 pi = points[i]; 28193 px.shift(); 28194 px.push(pi[0]); 28195 py.shift(); 28196 py.push(pi[1]); 28197 d3_svg_lineBasisBezier(path, px, py); 28198 } 28199 points.pop(); 28200 path.push("L", pi); 28201 return path.join(""); 28202 } 28203 function d3_svg_lineBasisOpen(points) { 28204 if (points.length < 4) return d3_svg_lineLinear(points); 28205 var path = [], i = -1, n = points.length, pi, px = [ 0 ], py = [ 0 ]; 28206 while (++i < 3) { 28207 pi = points[i]; 28208 px.push(pi[0]); 28209 py.push(pi[1]); 28210 } 28211 path.push(d3_svg_lineDot4(d3_svg_lineBasisBezier3, px) + "," + d3_svg_lineDot4(d3_svg_lineBasisBezier3, py)); 28212 --i; 28213 while (++i < n) { 28214 pi = points[i]; 28215 px.shift(); 28216 px.push(pi[0]); 28217 py.shift(); 28218 py.push(pi[1]); 28219 d3_svg_lineBasisBezier(path, px, py); 28220 } 28221 return path.join(""); 28222 } 28223 function d3_svg_lineBasisClosed(points) { 28224 var path, i = -1, n = points.length, m = n + 4, pi, px = [], py = []; 28225 while (++i < 4) { 28226 pi = points[i % n]; 28227 px.push(pi[0]); 28228 py.push(pi[1]); 28229 } 28230 path = [ d3_svg_lineDot4(d3_svg_lineBasisBezier3, px), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, py) ]; 28231 --i; 28232 while (++i < m) { 28233 pi = points[i % n]; 28234 px.shift(); 28235 px.push(pi[0]); 28236 py.shift(); 28237 py.push(pi[1]); 28238 d3_svg_lineBasisBezier(path, px, py); 28239 } 28240 return path.join(""); 28241 } 28242 function d3_svg_lineBundle(points, tension) { 28243 var n = points.length - 1; 28244 if (n) { 28245 var x0 = points[0][0], y0 = points[0][1], dx = points[n][0] - x0, dy = points[n][1] - y0, i = -1, p, t; 28246 while (++i <= n) { 28247 p = points[i]; 28248 t = i / n; 28249 p[0] = tension * p[0] + (1 - tension) * (x0 + t * dx); 28250 p[1] = tension * p[1] + (1 - tension) * (y0 + t * dy); 28251 } 28252 } 28253 return d3_svg_lineBasis(points); 28254 } 28255 function d3_svg_lineDot4(a, b) { 28256 return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3]; 28257 } 28258 var d3_svg_lineBasisBezier1 = [ 0, 2 / 3, 1 / 3, 0 ], d3_svg_lineBasisBezier2 = [ 0, 1 / 3, 2 / 3, 0 ], d3_svg_lineBasisBezier3 = [ 0, 1 / 6, 2 / 3, 1 / 6 ]; 28259 function d3_svg_lineBasisBezier(path, x, y) { 28260 path.push("C", d3_svg_lineDot4(d3_svg_lineBasisBezier1, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier1, y), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier2, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier2, y), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, y)); 28261 } 28262 function d3_svg_lineSlope(p0, p1) { 28263 return (p1[1] - p0[1]) / (p1[0] - p0[0]); 28264 } 28265 function d3_svg_lineFiniteDifferences(points) { 28266 var i = 0, j = points.length - 1, m = [], p0 = points[0], p1 = points[1], d = m[0] = d3_svg_lineSlope(p0, p1); 28267 while (++i < j) { 28268 m[i] = (d + (d = d3_svg_lineSlope(p0 = p1, p1 = points[i + 1]))) / 2; 28269 } 28270 m[i] = d; 28271 return m; 28272 } 28273 function d3_svg_lineMonotoneTangents(points) { 28274 var tangents = [], d, a, b, s, m = d3_svg_lineFiniteDifferences(points), i = -1, j = points.length - 1; 28275 while (++i < j) { 28276 d = d3_svg_lineSlope(points[i], points[i + 1]); 28277 if (abs(d) < ε) { 28278 m[i] = m[i + 1] = 0; 28279 } else { 28280 a = m[i] / d; 28281 b = m[i + 1] / d; 28282 s = a * a + b * b; 28283 if (s > 9) { 28284 s = d * 3 / Math.sqrt(s); 28285 m[i] = s * a; 28286 m[i + 1] = s * b; 28287 } 28288 } 28289 } 28290 i = -1; 28291 while (++i <= j) { 28292 s = (points[Math.min(j, i + 1)][0] - points[Math.max(0, i - 1)][0]) / (6 * (1 + m[i] * m[i])); 28293 tangents.push([ s || 0, m[i] * s || 0 ]); 28294 } 28295 return tangents; 28296 } 28297 function d3_svg_lineMonotone(points) { 28298 return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite(points, d3_svg_lineMonotoneTangents(points)); 28299 } 28300 d3.svg.line.radial = function() { 28301 var line = d3_svg_line(d3_svg_lineRadial); 28302 line.radius = line.x, delete line.x; 28303 line.angle = line.y, delete line.y; 28304 return line; 28305 }; 28306 function d3_svg_lineRadial(points) { 28307 var point, i = -1, n = points.length, r, a; 28308 while (++i < n) { 28309 point = points[i]; 28310 r = point[0]; 28311 a = point[1] + d3_svg_arcOffset; 28312 point[0] = r * Math.cos(a); 28313 point[1] = r * Math.sin(a); 28314 } 28315 return points; 28316 } 28317 function d3_svg_area(projection) { 28318 var x0 = d3_geom_pointX, x1 = d3_geom_pointX, y0 = 0, y1 = d3_geom_pointY, defined = d3_true, interpolate = d3_svg_lineLinear, interpolateKey = interpolate.key, interpolateReverse = interpolate, L = "L", tension = .7; 28319 function area(data) { 28320 var segments = [], points0 = [], points1 = [], i = -1, n = data.length, d, fx0 = d3_functor(x0), fy0 = d3_functor(y0), fx1 = x0 === x1 ? function() { 28321 return x; 28322 } : d3_functor(x1), fy1 = y0 === y1 ? function() { 28323 return y; 28324 } : d3_functor(y1), x, y; 28325 function segment() { 28326 segments.push("M", interpolate(projection(points1), tension), L, interpolateReverse(projection(points0.reverse()), tension), "Z"); 28327 } 28328 while (++i < n) { 28329 if (defined.call(this, d = data[i], i)) { 28330 points0.push([ x = +fx0.call(this, d, i), y = +fy0.call(this, d, i) ]); 28331 points1.push([ +fx1.call(this, d, i), +fy1.call(this, d, i) ]); 28332 } else if (points0.length) { 28333 segment(); 28334 points0 = []; 28335 points1 = []; 28336 } 28337 } 28338 if (points0.length) segment(); 28339 return segments.length ? segments.join("") : null; 28340 } 28341 area.x = function(_) { 28342 if (!arguments.length) return x1; 28343 x0 = x1 = _; 28344 return area; 28345 }; 28346 area.x0 = function(_) { 28347 if (!arguments.length) return x0; 28348 x0 = _; 28349 return area; 28350 }; 28351 area.x1 = function(_) { 28352 if (!arguments.length) return x1; 28353 x1 = _; 28354 return area; 28355 }; 28356 area.y = function(_) { 28357 if (!arguments.length) return y1; 28358 y0 = y1 = _; 28359 return area; 28360 }; 28361 area.y0 = function(_) { 28362 if (!arguments.length) return y0; 28363 y0 = _; 28364 return area; 28365 }; 28366 area.y1 = function(_) { 28367 if (!arguments.length) return y1; 28368 y1 = _; 28369 return area; 28370 }; 28371 area.defined = function(_) { 28372 if (!arguments.length) return defined; 28373 defined = _; 28374 return area; 28375 }; 28376 area.interpolate = function(_) { 28377 if (!arguments.length) return interpolateKey; 28378 if (typeof _ === "function") interpolateKey = interpolate = _; else interpolateKey = (interpolate = d3_svg_lineInterpolators.get(_) || d3_svg_lineLinear).key; 28379 interpolateReverse = interpolate.reverse || interpolate; 28380 L = interpolate.closed ? "M" : "L"; 28381 return area; 28382 }; 28383 area.tension = function(_) { 28384 if (!arguments.length) return tension; 28385 tension = _; 28386 return area; 28387 }; 28388 return area; 28389 } 28390 d3_svg_lineStepBefore.reverse = d3_svg_lineStepAfter; 28391 d3_svg_lineStepAfter.reverse = d3_svg_lineStepBefore; 28392 d3.svg.area = function() { 28393 return d3_svg_area(d3_identity); 28394 }; 28395 d3.svg.area.radial = function() { 28396 var area = d3_svg_area(d3_svg_lineRadial); 28397 area.radius = area.x, delete area.x; 28398 area.innerRadius = area.x0, delete area.x0; 28399 area.outerRadius = area.x1, delete area.x1; 28400 area.angle = area.y, delete area.y; 28401 area.startAngle = area.y0, delete area.y0; 28402 area.endAngle = area.y1, delete area.y1; 28403 return area; 28404 }; 28405 d3.svg.chord = function() { 28406 var source = d3_source, target = d3_target, radius = d3_svg_chordRadius, startAngle = d3_svg_arcStartAngle, endAngle = d3_svg_arcEndAngle; 28407 function chord(d, i) { 28408 var s = subgroup(this, source, d, i), t = subgroup(this, target, d, i); 28409 return "M" + s.p0 + arc(s.r, s.p1, s.a1 - s.a0) + (equals(s, t) ? curve(s.r, s.p1, s.r, s.p0) : curve(s.r, s.p1, t.r, t.p0) + arc(t.r, t.p1, t.a1 - t.a0) + curve(t.r, t.p1, s.r, s.p0)) + "Z"; 28410 } 28411 function subgroup(self, f, d, i) { 28412 var subgroup = f.call(self, d, i), r = radius.call(self, subgroup, i), a0 = startAngle.call(self, subgroup, i) + d3_svg_arcOffset, a1 = endAngle.call(self, subgroup, i) + d3_svg_arcOffset; 28413 return { 28414 r: r, 28415 a0: a0, 28416 a1: a1, 28417 p0: [ r * Math.cos(a0), r * Math.sin(a0) ], 28418 p1: [ r * Math.cos(a1), r * Math.sin(a1) ] 28419 }; 28420 } 28421 function equals(a, b) { 28422 return a.a0 == b.a0 && a.a1 == b.a1; 28423 } 28424 function arc(r, p, a) { 28425 return "A" + r + "," + r + " 0 " + +(a > Ï) + ",1 " + p; 28426 } 28427 function curve(r0, p0, r1, p1) { 28428 return "Q 0,0 " + p1; 28429 } 28430 chord.radius = function(v) {
vendor: 5,564 bytes, lines 28431-28580
28431 if (!arguments.length) return radius; 28432 radius = d3_functor(v); 28433 return chord; 28434 }; 28435 chord.source = function(v) { 28436 if (!arguments.length) return source; 28437 source = d3_functor(v); 28438 return chord; 28439 }; 28440 chord.target = function(v) { 28441 if (!arguments.length) return target; 28442 target = d3_functor(v); 28443 return chord; 28444 }; 28445 chord.startAngle = function(v) { 28446 if (!arguments.length) return startAngle; 28447 startAngle = d3_functor(v); 28448 return chord; 28449 }; 28450 chord.endAngle = function(v) { 28451 if (!arguments.length) return endAngle; 28452 endAngle = d3_functor(v); 28453 return chord; 28454 }; 28455 return chord; 28456 }; 28457 function d3_svg_chordRadius(d) { 28458 return d.radius; 28459 } 28460 d3.svg.diagonal = function() { 28461 var source = d3_source, target = d3_target, projection = d3_svg_diagonalProjection; 28462 function diagonal(d, i) { 28463 var p0 = source.call(this, d, i), p3 = target.call(this, d, i), m = (p0.y + p3.y) / 2, p = [ p0, { 28464 x: p0.x, 28465 y: m 28466 }, { 28467 x: p3.x, 28468 y: m 28469 }, p3 ]; 28470 p = p.map(projection); 28471 return "M" + p[0] + "C" + p[1] + " " + p[2] + " " + p[3]; 28472 } 28473 diagonal.source = function(x) { 28474 if (!arguments.length) return source; 28475 source = d3_functor(x); 28476 return diagonal; 28477 }; 28478 diagonal.target = function(x) { 28479 if (!arguments.length) return target; 28480 target = d3_functor(x); 28481 return diagonal; 28482 }; 28483 diagonal.projection = function(x) { 28484 if (!arguments.length) return projection; 28485 projection = x; 28486 return diagonal; 28487 }; 28488 return diagonal; 28489 }; 28490 function d3_svg_diagonalProjection(d) { 28491 return [ d.x, d.y ]; 28492 } 28493 d3.svg.diagonal.radial = function() { 28494 var diagonal = d3.svg.diagonal(), projection = d3_svg_diagonalProjection, projection_ = diagonal.projection; 28495 diagonal.projection = function(x) { 28496 return arguments.length ? projection_(d3_svg_diagonalRadialProjection(projection = x)) : projection; 28497 }; 28498 return diagonal; 28499 }; 28500 function d3_svg_diagonalRadialProjection(projection) { 28501 return function() { 28502 var d = projection.apply(this, arguments), r = d[0], a = d[1] + d3_svg_arcOffset; 28503 return [ r * Math.cos(a), r * Math.sin(a) ]; 28504 }; 28505 } 28506 d3.svg.symbol = function() { 28507 var type = d3_svg_symbolType, size = d3_svg_symbolSize; 28508 function symbol(d, i) { 28509 return (d3_svg_symbols.get(type.call(this, d, i)) || d3_svg_symbolCircle)(size.call(this, d, i)); 28510 } 28511 symbol.type = function(x) { 28512 if (!arguments.length) return type; 28513 type = d3_functor(x); 28514 return symbol; 28515 }; 28516 symbol.size = function(x) { 28517 if (!arguments.length) return size; 28518 size = d3_functor(x); 28519 return symbol; 28520 }; 28521 return symbol; 28522 }; 28523 function d3_svg_symbolSize() { 28524 return 64; 28525 } 28526 function d3_svg_symbolType() { 28527 return "circle"; 28528 } 28529 function d3_svg_symbolCircle(size) { 28530 var r = Math.sqrt(size / Ï); 28531 return "M0," + r + "A" + r + "," + r + " 0 1,1 0," + -r + "A" + r + "," + r + " 0 1,1 0," + r + "Z"; 28532 } 28533 var d3_svg_symbols = d3.map({ 28534 circle: d3_svg_symbolCircle, 28535 cross: function(size) { 28536 var r = Math.sqrt(size / 5) / 2; 28537 return "M" + -3 * r + "," + -r + "H" + -r + "V" + -3 * r + "H" + r + "V" + -r + "H" + 3 * r + "V" + r + "H" + r + "V" + 3 * r + "H" + -r + "V" + r + "H" + -3 * r + "Z"; 28538 }, 28539 diamond: function(size) { 28540 var ry = Math.sqrt(size / (2 * d3_svg_symbolTan30)), rx = ry * d3_svg_symbolTan30; 28541 return "M0," + -ry + "L" + rx + ",0" + " 0," + ry + " " + -rx + ",0" + "Z"; 28542 }, 28543 square: function(size) { 28544 var r = Math.sqrt(size) / 2; 28545 return "M" + -r + "," + -r + "L" + r + "," + -r + " " + r + "," + r + " " + -r + "," + r + "Z"; 28546 }, 28547 "triangle-down": function(size) { 28548 var rx = Math.sqrt(size / d3_svg_symbolSqrt3), ry = rx * d3_svg_symbolSqrt3 / 2; 28549 return "M0," + ry + "L" + rx + "," + -ry + " " + -rx + "," + -ry + "Z"; 28550 }, 28551 "triangle-up": function(size) { 28552 var rx = Math.sqrt(size / d3_svg_symbolSqrt3), ry = rx * d3_svg_symbolSqrt3 / 2; 28553 return "M0," + -ry + "L" + rx + "," + ry + " " + -rx + "," + ry + "Z"; 28554 } 28555 }); 28556 d3.svg.symbolTypes = d3_svg_symbols.keys(); 28557 var d3_svg_symbolSqrt3 = Math.sqrt(3), d3_svg_symbolTan30 = Math.tan(30 * d3_radians); 28558 function d3_transition(groups, id) { 28559 d3_subclass(groups, d3_transitionPrototype); 28560 groups.id = id; 28561 return groups; 28562 } 28563 var d3_transitionPrototype = [], d3_transitionId = 0, d3_transitionInheritId, d3_transitionInherit; 28564 d3_transitionPrototype.call = d3_selectionPrototype.call; 28565 d3_transitionPrototype.empty = d3_selectionPrototype.empty; 28566 d3_transitionPrototype.node = d3_selectionPrototype.node; 28567 d3_transitionPrototype.size = d3_selectionPrototype.size; 28568 d3.transition = function(selection) { 28569 return arguments.length ? d3_transitionInheritId ? selection.transition() : selection : d3_selectionRoot.transition(); 28570 }; 28571 d3.transition.prototype = d3_transitionPrototype; 28572 d3_transitionPrototype.select = function(selector) { 28573 var id = this.id, subgroups = [], subgroup, subnode, node; 28574 selector = d3_selection_selector(selector); 28575 for (var j = -1, m = this.length; ++j < m; ) { 28576 subgroups.push(subgroup = []); 28577 for (var group = this[j], i = -1, n = group.length; ++i < n; ) { 28578 if ((node = group[i]) && (subnode = selector.call(node, node.__data__, i, j))) { 28579 if ("__data__" in node) subnode.__data__ = node.__data__; 28580 d3_transitionNode(subnode, i, id, node.__transition__[id]);
vendor: 4,289 bytes, lines 28581-28695
28581 subgroup.push(subnode); 28582 } else { 28583 subgroup.push(null); 28584 } 28585 } 28586 } 28587 return d3_transition(subgroups, id); 28588 }; 28589 d3_transitionPrototype.selectAll = function(selector) { 28590 var id = this.id, subgroups = [], subgroup, subnodes, node, subnode, transition; 28591 selector = d3_selection_selectorAll(selector); 28592 for (var j = -1, m = this.length; ++j < m; ) { 28593 for (var group = this[j], i = -1, n = group.length; ++i < n; ) { 28594 if (node = group[i]) { 28595 transition = node.__transition__[id]; 28596 subnodes = selector.call(node, node.__data__, i, j); 28597 subgroups.push(subgroup = []); 28598 for (var k = -1, o = subnodes.length; ++k < o; ) { 28599 if (subnode = subnodes[k]) d3_transitionNode(subnode, k, id, transition); 28600 subgroup.push(subnode); 28601 } 28602 } 28603 } 28604 } 28605 return d3_transition(subgroups, id); 28606 }; 28607 d3_transitionPrototype.filter = function(filter) { 28608 var subgroups = [], subgroup, group, node; 28609 if (typeof filter !== "function") filter = d3_selection_filter(filter); 28610 for (var j = 0, m = this.length; j < m; j++) { 28611 subgroups.push(subgroup = []); 28612 for (var group = this[j], i = 0, n = group.length; i < n; i++) { 28613 if ((node = group[i]) && filter.call(node, node.__data__, i, j)) { 28614 subgroup.push(node); 28615 } 28616 } 28617 } 28618 return d3_transition(subgroups, this.id); 28619 }; 28620 d3_transitionPrototype.tween = function(name, tween) { 28621 var id = this.id; 28622 if (arguments.length < 2) return this.node().__transition__[id].tween.get(name); 28623 return d3_selection_each(this, tween == null ? function(node) { 28624 node.__transition__[id].tween.remove(name); 28625 } : function(node) { 28626 node.__transition__[id].tween.set(name, tween); 28627 }); 28628 }; 28629 function d3_transition_tween(groups, name, value, tween) { 28630 var id = groups.id; 28631 return d3_selection_each(groups, typeof value === "function" ? function(node, i, j) { 28632 node.__transition__[id].tween.set(name, tween(value.call(node, node.__data__, i, j))); 28633 } : (value = tween(value), function(node) { 28634 node.__transition__[id].tween.set(name, value); 28635 })); 28636 } 28637 d3_transitionPrototype.attr = function(nameNS, value) { 28638 if (arguments.length < 2) { 28639 for (value in nameNS) this.attr(value, nameNS[value]); 28640 return this; 28641 } 28642 var interpolate = nameNS == "transform" ? d3_interpolateTransform : d3_interpolate, name = d3.ns.qualify(nameNS); 28643 function attrNull() { 28644 this.removeAttribute(name); 28645 } 28646 function attrNullNS() { 28647 this.removeAttributeNS(name.space, name.local); 28648 } 28649 function attrTween(b) { 28650 return b == null ? attrNull : (b += "", function() { 28651 var a = this.getAttribute(name), i; 28652 return a !== b && (i = interpolate(a, b), function(t) { 28653 this.setAttribute(name, i(t)); 28654 }); 28655 }); 28656 } 28657 function attrTweenNS(b) { 28658 return b == null ? attrNullNS : (b += "", function() { 28659 var a = this.getAttributeNS(name.space, name.local), i; 28660 return a !== b && (i = interpolate(a, b), function(t) { 28661 this.setAttributeNS(name.space, name.local, i(t)); 28662 }); 28663 }); 28664 } 28665 return d3_transition_tween(this, "attr." + nameNS, value, name.local ? attrTweenNS : attrTween); 28666 }; 28667 d3_transitionPrototype.attrTween = function(nameNS, tween) { 28668 var name = d3.ns.qualify(nameNS); 28669 function attrTween(d, i) { 28670 var f = tween.call(this, d, i, this.getAttribute(name)); 28671 return f && function(t) { 28672 this.setAttribute(name, f(t)); 28673 }; 28674 } 28675 function attrTweenNS(d, i) { 28676 var f = tween.call(this, d, i, this.getAttributeNS(name.space, name.local)); 28677 return f && function(t) { 28678 this.setAttributeNS(name.space, name.local, f(t)); 28679 }; 28680 } 28681 return this.tween("attr." + nameNS, name.local ? attrTweenNS : attrTween); 28682 }; 28683 d3_transitionPrototype.style = function(name, value, priority) { 28684 var n = arguments.length; 28685 if (n < 3) { 28686 if (typeof name !== "string") { 28687 if (n < 2) value = ""; 28688 for (priority in name) this.style(priority, name[priority], value); 28689 return this; 28690 } 28691 priority = ""; 28692 } 28693 function styleNull() { 28694 this.style.removeProperty(name); 28695 }
28696 function styleString(b) { 28697 return b == null ? styleNull : (b += "", function() { 28698 var a = d3_window.getComputedStyle(this, null).getPropertyValue(name), i; 28699 return a !== b && (i = d3_interpolate(a, b), function(t) { 28700 this.style.setProperty(name, i(t), priority); 28701 }); 28702 }); 28703 } 28704 return d3_transition_tween(this, "style." + name, value, styleString); 28705 }; 28706 d3_transitionPrototype.styleTween = function(name, tween, priority) { 28707 if (arguments.length < 3) priority = ""; 28708 function styleTween(d, i) { 28709 var f = tween.call(this, d, i, d3_window.getComputedStyle(this, null).getPropertyValue(name)); 28710 return f && function(t) { 28711 this.style.setProperty(name, f(t), priority); 28712 }; 28713 } 28714 return this.tween("style." + name, styleTween); 28715 }; 28716 d3_transitionPrototype.text = function(value) { 28717 return d3_transition_tween(this, "text", value, d3_transition_text); 28718 }; 28719 function d3_transition_text(b) { 28720 if (b == null) b = ""; 28721 return function() { 28722 this.textContent = b; 28723 }; 28724 } 28725 d3_transitionPrototype.remove = function() { 28726 return this.each("end.transition", function() { 28727 var p; 28728 if (this.__transition__.count < 2 && (p = this.parentNode)) p.removeChild(this); 28729 }); 28730 }; 28731 d3_transitionPrototype.ease = function(value) { 28732 var id = this.id; 28733 if (arguments.length < 1) return this.node().__transition__[id].ease; 28734 if (typeof value !== "function") value = d3.ease.apply(d3, arguments); 28735 return d3_selection_each(this, function(node) { 28736 node.__transition__[id].ease = value; 28737 }); 28738 }; 28739 d3_transitionPrototype.delay = function(value) { 28740 var id = this.id; 28741 if (arguments.length < 1) return this.node().__transition__[id].delay; 28742 return d3_selection_each(this, typeof value === "function" ? function(node, i, j) { 28743 node.__transition__[id].delay = +value.call(node, node.__data__, i, j); 28744 } : (value = +value, function(node) { 28745 node.__transition__[id].delay = value; 28746 })); 28747 }; 28748 d3_transitionPrototype.duration = function(value) { 28749 var id = this.id; 28750 if (arguments.length < 1) return this.node().__transition__[id].duration; 28751 return d3_selection_each(this, typeof value === "function" ? function(node, i, j) { 28752 node.__transition__[id].duration = Math.max(1, value.call(node, node.__data__, i, j)); 28753 } : (value = Math.max(1, value), function(node) { 28754 node.__transition__[id].duration = value; 28755 })); 28756 }; 28757 d3_transitionPrototype.each = function(type, listener) { 28758 var id = this.id; 28759 if (arguments.length < 2) { 28760 var inherit = d3_transitionInherit, inheritId = d3_transitionInheritId; 28761 d3_transitionInheritId = id; 28762 d3_selection_each(this, function(node, i, j) { 28763 d3_transitionInherit = node.__transition__[id]; 28764 type.call(node, node.__data__, i, j); 28765 }); 28766 d3_transitionInherit = inherit; 28767 d3_transitionInheritId = inheritId; 28768 } else { 28769 d3_selection_each(this, function(node) { 28770 var transition = node.__transition__[id]; 28771 (transition.event || (transition.event = d3.dispatch("start", "end"))).on(type, listener); 28772 }); 28773 } 28774 return this; 28775 }; 28776 d3_transitionPrototype.transition = function() { 28777 var id0 = this.id, id1 = ++d3_transitionId, subgroups = [], subgroup, group, node, transition; 28778 for (var j = 0, m = this.length; j < m; j++) { 28779 subgroups.push(subgroup = []); 28780 for (var group = this[j], i = 0, n = group.length; i < n; i++) { 28781 if (node = group[i]) { 28782 transition = Object.create(node.__transition__[id0]); 28783 transition.delay += transition.duration; 28784 d3_transitionNode(node, i, id1, transition); 28785 } 28786 subgroup.push(node); 28787 } 28788 } 28789 return d3_transition(subgroups, id1); 28790 }; 28791 function d3_transitionNode(node, i, id, inherit) { 28792 var lock = node.__transition__ || (node.__transition__ = { 28793 active: 0, 28794 count: 0 28795 }), transition = lock[id]; 28796 if (!transition) { 28797 var time = inherit.time; 28798 transition = lock[id] = { 28799 tween: new d3_Map(), 28800 time: time, 28801 ease: inherit.ease, 28802 delay: inherit.delay, 28803 duration: inherit.duration 28804 }; 28805 ++lock.count; 28806 d3.timer(function(elapsed) { 28807 var d = node.__data__, ease = transition.ease, delay = transition.delay, duration = transition.duration, timer = d3_timer_active, tweened = []; 28808 timer.t = delay + time; 28809 if (delay <= elapsed) return start(elapsed - delay); 28810 timer.c = start; 28811 function start(elapsed) { 28812 if (lock.active > id) return stop(); 28813 lock.active = id; 28814 transition.event && transition.event.start.call(node, d, i);
vendor: 11,648 bytes, lines 28815-29097
28815 transition.tween.forEach(function(key, value) { 28816 if (value = value.call(node, d, i)) { 28817 tweened.push(value); 28818 } 28819 }); 28820 d3.timer(function() { 28821 timer.c = tick(elapsed || 1) ? d3_true : tick; 28822 return 1; 28823 }, 0, time); 28824 } 28825 function tick(elapsed) { 28826 if (lock.active !== id) return stop(); 28827 var t = elapsed / duration, e = ease(t), n = tweened.length; 28828 while (n > 0) { 28829 tweened[--n].call(node, e); 28830 } 28831 if (t >= 1) { 28832 transition.event && transition.event.end.call(node, d, i); 28833 return stop(); 28834 } 28835 } 28836 function stop() { 28837 if (--lock.count) delete lock[id]; else delete node.__transition__; 28838 return 1; 28839 } 28840 }, 0, time); 28841 } 28842 } 28843 d3.svg.axis = function() { 28844 var scale = d3.scale.linear(), orient = d3_svg_axisDefaultOrient, innerTickSize = 6, outerTickSize = 6, tickPadding = 3, tickArguments_ = [ 10 ], tickValues = null, tickFormat_; 28845 function axis(g) { 28846 g.each(function() { 28847 var g = d3.select(this); 28848 var scale0 = this.__chart__ || scale, scale1 = this.__chart__ = scale.copy(); 28849 var ticks = tickValues == null ? scale1.ticks ? scale1.ticks.apply(scale1, tickArguments_) : scale1.domain() : tickValues, tickFormat = tickFormat_ == null ? scale1.tickFormat ? scale1.tickFormat.apply(scale1, tickArguments_) : d3_identity : tickFormat_, tick = g.selectAll(".tick").data(ticks, scale1), tickEnter = tick.enter().insert("g", ".domain").attr("class", "tick").style("opacity", ε), tickExit = d3.transition(tick.exit()).style("opacity", ε).remove(), tickUpdate = d3.transition(tick.order()).style("opacity", 1), tickSpacing = Math.max(innerTickSize, 0) + tickPadding, tickTransform; 28850 var range = d3_scaleRange(scale1), path = g.selectAll(".domain").data([ 0 ]), pathUpdate = (path.enter().append("path").attr("class", "domain"), 28851 d3.transition(path)); 28852 tickEnter.append("line"); 28853 tickEnter.append("text"); 28854 var lineEnter = tickEnter.select("line"), lineUpdate = tickUpdate.select("line"), text = tick.select("text").text(tickFormat), textEnter = tickEnter.select("text"), textUpdate = tickUpdate.select("text"), sign = orient === "top" || orient === "left" ? -1 : 1, x1, x2, y1, y2; 28855 if (orient === "bottom" || orient === "top") { 28856 tickTransform = d3_svg_axisX, x1 = "x", y1 = "y", x2 = "x2", y2 = "y2"; 28857 text.attr("dy", sign < 0 ? "0em" : ".71em").style("text-anchor", "middle"); 28858 pathUpdate.attr("d", "M" + range[0] + "," + sign * outerTickSize + "V0H" + range[1] + "V" + sign * outerTickSize); 28859 } else { 28860 tickTransform = d3_svg_axisY, x1 = "y", y1 = "x", x2 = "y2", y2 = "x2"; 28861 text.attr("dy", ".32em").style("text-anchor", sign < 0 ? "end" : "start"); 28862 pathUpdate.attr("d", "M" + sign * outerTickSize + "," + range[0] + "H0V" + range[1] + "H" + sign * outerTickSize); 28863 } 28864 lineEnter.attr(y2, sign * innerTickSize); 28865 textEnter.attr(y1, sign * tickSpacing); 28866 lineUpdate.attr(x2, 0).attr(y2, sign * innerTickSize); 28867 textUpdate.attr(x1, 0).attr(y1, sign * tickSpacing); 28868 if (scale1.rangeBand) { 28869 var x = scale1, dx = x.rangeBand() / 2; 28870 scale0 = scale1 = function(d) { 28871 return x(d) + dx; 28872 }; 28873 } else if (scale0.rangeBand) { 28874 scale0 = scale1; 28875 } else { 28876 tickExit.call(tickTransform, scale1, scale0); 28877 } 28878 tickEnter.call(tickTransform, scale0, scale1); 28879 tickUpdate.call(tickTransform, scale1, scale1); 28880 }); 28881 } 28882 axis.scale = function(x) { 28883 if (!arguments.length) return scale; 28884 scale = x; 28885 return axis; 28886 }; 28887 axis.orient = function(x) { 28888 if (!arguments.length) return orient; 28889 orient = x in d3_svg_axisOrients ? x + "" : d3_svg_axisDefaultOrient; 28890 return axis; 28891 }; 28892 axis.ticks = function() { 28893 if (!arguments.length) return tickArguments_; 28894 tickArguments_ = arguments; 28895 return axis; 28896 }; 28897 axis.tickValues = function(x) { 28898 if (!arguments.length) return tickValues; 28899 tickValues = x; 28900 return axis; 28901 }; 28902 axis.tickFormat = function(x) { 28903 if (!arguments.length) return tickFormat_; 28904 tickFormat_ = x; 28905 return axis; 28906 }; 28907 axis.tickSize = function(x) { 28908 var n = arguments.length; 28909 if (!n) return innerTickSize; 28910 innerTickSize = +x; 28911 outerTickSize = +arguments[n - 1]; 28912 return axis; 28913 }; 28914 axis.innerTickSize = function(x) { 28915 if (!arguments.length) return innerTickSize; 28916 innerTickSize = +x; 28917 return axis; 28918 }; 28919 axis.outerTickSize = function(x) { 28920 if (!arguments.length) return outerTickSize; 28921 outerTickSize = +x; 28922 return axis; 28923 }; 28924 axis.tickPadding = function(x) { 28925 if (!arguments.length) return tickPadding; 28926 tickPadding = +x; 28927 return axis; 28928 }; 28929 axis.tickSubdivide = function() { 28930 return arguments.length && axis; 28931 }; 28932 return axis; 28933 }; 28934 var d3_svg_axisDefaultOrient = "bottom", d3_svg_axisOrients = { 28935 top: 1, 28936 right: 1, 28937 bottom: 1, 28938 left: 1 28939 }; 28940 function d3_svg_axisX(selection, x0, x1) { 28941 selection.attr("transform", function(d) { 28942 var v0 = x0(d); 28943 return "translate(" + (isFinite(v0) ? v0 : x1(d)) + ",0)"; 28944 }); 28945 } 28946 function d3_svg_axisY(selection, y0, y1) { 28947 selection.attr("transform", function(d) { 28948 var v0 = y0(d); 28949 return "translate(0," + (isFinite(v0) ? v0 : y1(d)) + ")"; 28950 }); 28951 } 28952 d3.svg.brush = function() { 28953 var event = d3_eventDispatch(brush, "brushstart", "brush", "brushend"), x = null, y = null, xExtent = [ 0, 0 ], yExtent = [ 0, 0 ], xExtentDomain, yExtentDomain, xClamp = true, yClamp = true, resizes = d3_svg_brushResizes[0]; 28954 function brush(g) { 28955 g.each(function() { 28956 var g = d3.select(this).style("pointer-events", "all").style("-webkit-tap-highlight-color", "rgba(0,0,0,0)").on("mousedown.brush", brushstart).on("touchstart.brush", brushstart); 28957 var background = g.selectAll(".background").data([ 0 ]); 28958 background.enter().append("rect").attr("class", "background").style("visibility", "hidden").style("cursor", "crosshair"); 28959 g.selectAll(".extent").data([ 0 ]).enter().append("rect").attr("class", "extent").style("cursor", "move"); 28960 var resize = g.selectAll(".resize").data(resizes, d3_identity); 28961 resize.exit().remove(); 28962 resize.enter().append("g").attr("class", function(d) { 28963 return "resize " + d; 28964 }).style("cursor", function(d) { 28965 return d3_svg_brushCursor[d]; 28966 }).append("rect").attr("x", function(d) { 28967 return /[ew]$/.test(d) ? -3 : null; 28968 }).attr("y", function(d) { 28969 return /^[ns]/.test(d) ? -3 : null; 28970 }).attr("width", 6).attr("height", 6).style("visibility", "hidden"); 28971 resize.style("display", brush.empty() ? "none" : null); 28972 var gUpdate = d3.transition(g), backgroundUpdate = d3.transition(background), range; 28973 if (x) { 28974 range = d3_scaleRange(x); 28975 backgroundUpdate.attr("x", range[0]).attr("width", range[1] - range[0]); 28976 redrawX(gUpdate); 28977 } 28978 if (y) { 28979 range = d3_scaleRange(y); 28980 backgroundUpdate.attr("y", range[0]).attr("height", range[1] - range[0]); 28981 redrawY(gUpdate); 28982 } 28983 redraw(gUpdate); 28984 }); 28985 } 28986 brush.event = function(g) { 28987 g.each(function() { 28988 var event_ = event.of(this, arguments), extent1 = { 28989 x: xExtent, 28990 y: yExtent, 28991 i: xExtentDomain, 28992 j: yExtentDomain 28993 }, extent0 = this.__chart__ || extent1; 28994 this.__chart__ = extent1; 28995 if (d3_transitionInheritId) { 28996 d3.select(this).transition().each("start.brush", function() { 28997 xExtentDomain = extent0.i; 28998 yExtentDomain = extent0.j; 28999 xExtent = extent0.x; 29000 yExtent = extent0.y; 29001 event_({ 29002 type: "brushstart" 29003 }); 29004 }).tween("brush:brush", function() { 29005 var xi = d3_interpolateArray(xExtent, extent1.x), yi = d3_interpolateArray(yExtent, extent1.y); 29006 xExtentDomain = yExtentDomain = null; 29007 return function(t) { 29008 xExtent = extent1.x = xi(t); 29009 yExtent = extent1.y = yi(t); 29010 event_({ 29011 type: "brush", 29012 mode: "resize" 29013 }); 29014 }; 29015 }).each("end.brush", function() { 29016 xExtentDomain = extent1.i; 29017 yExtentDomain = extent1.j; 29018 event_({ 29019 type: "brush", 29020 mode: "resize" 29021 }); 29022 event_({ 29023 type: "brushend" 29024 }); 29025 }); 29026 } else { 29027 event_({ 29028 type: "brushstart" 29029 }); 29030 event_({ 29031 type: "brush", 29032 mode: "resize" 29033 }); 29034 event_({ 29035 type: "brushend" 29036 }); 29037 } 29038 }); 29039 }; 29040 function redraw(g) { 29041 g.selectAll(".resize").attr("transform", function(d) { 29042 return "translate(" + xExtent[+/e$/.test(d)] + "," + yExtent[+/^s/.test(d)] + ")"; 29043 }); 29044 } 29045 function redrawX(g) { 29046 g.select(".extent").attr("x", xExtent[0]); 29047 g.selectAll(".extent,.n>rect,.s>rect").attr("width", xExtent[1] - xExtent[0]); 29048 } 29049 function redrawY(g) { 29050 g.select(".extent").attr("y", yExtent[0]); 29051 g.selectAll(".extent,.e>rect,.w>rect").attr("height", yExtent[1] - yExtent[0]); 29052 } 29053 function brushstart() { 29054 var target = this, eventTarget = d3.select(d3.event.target), event_ = event.of(target, arguments), g = d3.select(target), resizing = eventTarget.datum(), resizingX = !/^(n|s)$/.test(resizing) && x, resizingY = !/^(e|w)$/.test(resizing) && y, dragging = eventTarget.classed("extent"), dragRestore = d3_event_dragSuppress(), center, origin = d3.mouse(target), offset; 29055 var w = d3.select(d3_window).on("keydown.brush", keydown).on("keyup.brush", keyup); 29056 if (d3.event.changedTouches) { 29057 w.on("touchmove.brush", brushmove).on("touchend.brush", brushend); 29058 } else { 29059 w.on("mousemove.brush", brushmove).on("mouseup.brush", brushend); 29060 } 29061 g.interrupt().selectAll("*").interrupt(); 29062 if (dragging) { 29063 origin[0] = xExtent[0] - origin[0]; 29064 origin[1] = yExtent[0] - origin[1]; 29065 } else if (resizing) { 29066 var ex = +/w$/.test(resizing), ey = +/^n/.test(resizing); 29067 offset = [ xExtent[1 - ex] - origin[0], yExtent[1 - ey] - origin[1] ]; 29068 origin[0] = xExtent[ex]; 29069 origin[1] = yExtent[ey]; 29070 } else if (d3.event.altKey) center = origin.slice(); 29071 g.style("pointer-events", "none").selectAll(".resize").style("display", null); 29072 d3.select("body").style("cursor", eventTarget.style("cursor")); 29073 event_({ 29074 type: "brushstart" 29075 }); 29076 brushmove(); 29077 function keydown() { 29078 if (d3.event.keyCode == 32) { 29079 if (!dragging) { 29080 center = null; 29081 origin[0] -= xExtent[1]; 29082 origin[1] -= yExtent[1]; 29083 dragging = 2; 29084 } 29085 d3_eventPreventDefault(); 29086 } 29087 } 29088 function keyup() { 29089 if (d3.event.keyCode == 32 && dragging == 2) { 29090 origin[0] += xExtent[1]; 29091 origin[1] += yExtent[1]; 29092 dragging = 0; 29093 d3_eventPreventDefault(); 29094 } 29095 } 29096 function brushmove() { 29097 var point = d3.mouse(target), moved = false;
vendor: 6,929 bytes, lines 29098-29293
29098 if (offset) { 29099 point[0] += offset[0]; 29100 point[1] += offset[1]; 29101 } 29102 if (!dragging) { 29103 if (d3.event.altKey) { 29104 if (!center) center = [ (xExtent[0] + xExtent[1]) / 2, (yExtent[0] + yExtent[1]) / 2 ]; 29105 origin[0] = xExtent[+(point[0] < center[0])]; 29106 origin[1] = yExtent[+(point[1] < center[1])]; 29107 } else center = null; 29108 } 29109 if (resizingX && move1(point, x, 0)) { 29110 redrawX(g); 29111 moved = true; 29112 } 29113 if (resizingY && move1(point, y, 1)) { 29114 redrawY(g); 29115 moved = true; 29116 } 29117 if (moved) { 29118 redraw(g); 29119 event_({ 29120 type: "brush", 29121 mode: dragging ? "move" : "resize" 29122 }); 29123 } 29124 } 29125 function move1(point, scale, i) { 29126 var range = d3_scaleRange(scale), r0 = range[0], r1 = range[1], position = origin[i], extent = i ? yExtent : xExtent, size = extent[1] - extent[0], min, max; 29127 if (dragging) { 29128 r0 -= position; 29129 r1 -= size + position; 29130 } 29131 min = (i ? yClamp : xClamp) ? Math.max(r0, Math.min(r1, point[i])) : point[i]; 29132 if (dragging) { 29133 max = (min += position) + size; 29134 } else { 29135 if (center) position = Math.max(r0, Math.min(r1, 2 * center[i] - min)); 29136 if (position < min) { 29137 max = min; 29138 min = position; 29139 } else { 29140 max = position; 29141 } 29142 } 29143 if (extent[0] != min || extent[1] != max) { 29144 if (i) yExtentDomain = null; else xExtentDomain = null; 29145 extent[0] = min; 29146 extent[1] = max; 29147 return true; 29148 } 29149 } 29150 function brushend() { 29151 brushmove(); 29152 g.style("pointer-events", "all").selectAll(".resize").style("display", brush.empty() ? "none" : null); 29153 d3.select("body").style("cursor", null); 29154 w.on("mousemove.brush", null).on("mouseup.brush", null).on("touchmove.brush", null).on("touchend.brush", null).on("keydown.brush", null).on("keyup.brush", null); 29155 dragRestore(); 29156 event_({ 29157 type: "brushend" 29158 }); 29159 } 29160 } 29161 brush.x = function(z) { 29162 if (!arguments.length) return x; 29163 x = z; 29164 resizes = d3_svg_brushResizes[!x << 1 | !y]; 29165 return brush; 29166 }; 29167 brush.y = function(z) { 29168 if (!arguments.length) return y; 29169 y = z; 29170 resizes = d3_svg_brushResizes[!x << 1 | !y]; 29171 return brush; 29172 }; 29173 brush.clamp = function(z) { 29174 if (!arguments.length) return x && y ? [ xClamp, yClamp ] : x ? xClamp : y ? yClamp : null; 29175 if (x && y) xClamp = !!z[0], yClamp = !!z[1]; else if (x) xClamp = !!z; else if (y) yClamp = !!z; 29176 return brush; 29177 }; 29178 brush.extent = function(z) { 29179 var x0, x1, y0, y1, t; 29180 if (!arguments.length) { 29181 if (x) { 29182 if (xExtentDomain) { 29183 x0 = xExtentDomain[0], x1 = xExtentDomain[1]; 29184 } else { 29185 x0 = xExtent[0], x1 = xExtent[1]; 29186 if (x.invert) x0 = x.invert(x0), x1 = x.invert(x1); 29187 if (x1 < x0) t = x0, x0 = x1, x1 = t; 29188 } 29189 } 29190 if (y) { 29191 if (yExtentDomain) { 29192 y0 = yExtentDomain[0], y1 = yExtentDomain[1]; 29193 } else { 29194 y0 = yExtent[0], y1 = yExtent[1]; 29195 if (y.invert) y0 = y.invert(y0), y1 = y.invert(y1); 29196 if (y1 < y0) t = y0, y0 = y1, y1 = t; 29197 } 29198 } 29199 return x && y ? [ [ x0, y0 ], [ x1, y1 ] ] : x ? [ x0, x1 ] : y && [ y0, y1 ]; 29200 } 29201 if (x) { 29202 x0 = z[0], x1 = z[1]; 29203 if (y) x0 = x0[0], x1 = x1[0]; 29204 xExtentDomain = [ x0, x1 ]; 29205 if (x.invert) x0 = x(x0), x1 = x(x1); 29206 if (x1 < x0) t = x0, x0 = x1, x1 = t; 29207 if (x0 != xExtent[0] || x1 != xExtent[1]) xExtent = [ x0, x1 ]; 29208 } 29209 if (y) { 29210 y0 = z[0], y1 = z[1]; 29211 if (x) y0 = y0[1], y1 = y1[1]; 29212 yExtentDomain = [ y0, y1 ]; 29213 if (y.invert) y0 = y(y0), y1 = y(y1); 29214 if (y1 < y0) t = y0, y0 = y1, y1 = t; 29215 if (y0 != yExtent[0] || y1 != yExtent[1]) yExtent = [ y0, y1 ]; 29216 } 29217 return brush; 29218 }; 29219 brush.clear = function() { 29220 if (!brush.empty()) { 29221 xExtent = [ 0, 0 ], yExtent = [ 0, 0 ]; 29222 xExtentDomain = yExtentDomain = null; 29223 } 29224 return brush; 29225 }; 29226 brush.empty = function() { 29227 return !!x && xExtent[0] == xExtent[1] || !!y && yExtent[0] == yExtent[1]; 29228 }; 29229 return d3.rebind(brush, event, "on"); 29230 }; 29231 var d3_svg_brushCursor = { 29232 n: "ns-resize", 29233 e: "ew-resize", 29234 s: "ns-resize", 29235 w: "ew-resize", 29236 nw: "nwse-resize", 29237 ne: "nesw-resize", 29238 se: "nwse-resize", 29239 sw: "nesw-resize" 29240 }; 29241 var d3_svg_brushResizes = [ [ "n", "e", "s", "w", "nw", "ne", "se", "sw" ], [ "e", "w" ], [ "n", "s" ], [] ]; 29242 var d3_time_format = d3_time.format = d3_locale_enUS.timeFormat; 29243 var d3_time_formatUtc = d3_time_format.utc; 29244 var d3_time_formatIso = d3_time_formatUtc("%Y-%m-%dT%H:%M:%S.%LZ"); 29245 d3_time_format.iso = Date.prototype.toISOString && +new Date("2000-01-01T00:00:00.000Z") ? d3_time_formatIsoNative : d3_time_formatIso; 29246 function d3_time_formatIsoNative(date) { 29247 return date.toISOString(); 29248 } 29249 d3_time_formatIsoNative.parse = function(string) { 29250 var date = new Date(string); 29251 return isNaN(date) ? null : date; 29252 }; 29253 d3_time_formatIsoNative.toString = d3_time_formatIso.toString; 29254 d3_time.second = d3_time_interval(function(date) { 29255 return new d3_date(Math.floor(date / 1e3) * 1e3); 29256 }, function(date, offset) { 29257 date.setTime(date.getTime() + Math.floor(offset) * 1e3); 29258 }, function(date) { 29259 return date.getSeconds(); 29260 }); 29261 d3_time.seconds = d3_time.second.range; 29262 d3_time.seconds.utc = d3_time.second.utc.range; 29263 d3_time.minute = d3_time_interval(function(date) { 29264 return new d3_date(Math.floor(date / 6e4) * 6e4); 29265 }, function(date, offset) { 29266 date.setTime(date.getTime() + Math.floor(offset) * 6e4); 29267 }, function(date) { 29268 return date.getMinutes(); 29269 }); 29270 d3_time.minutes = d3_time.minute.range; 29271 d3_time.minutes.utc = d3_time.minute.utc.range; 29272 d3_time.hour = d3_time_interval(function(date) { 29273 var timezone = date.getTimezoneOffset() / 60; 29274 return new d3_date((Math.floor(date / 36e5 - timezone) + timezone) * 36e5); 29275 }, function(date, offset) { 29276 date.setTime(date.getTime() + Math.floor(offset) * 36e5); 29277 }, function(date) { 29278 return date.getHours(); 29279 }); 29280 d3_time.hours = d3_time.hour.range; 29281 d3_time.hours.utc = d3_time.hour.utc.range; 29282 d3_time.month = d3_time_interval(function(date) { 29283 date = d3_time.day(date); 29284 date.setDate(1); 29285 return date; 29286 }, function(date, offset) { 29287 date.setMonth(date.getMonth() + offset); 29288 }, function(date) { 29289 return date.getMonth(); 29290 }); 29291 d3_time.months = d3_time.month.range; 29292 d3_time.months.utc = d3_time.month.utc.range; 29293 function d3_time_scale(linear, methods, format) {
29294 function scale(x) { 29295 return linear(x); 29296 } 29297 scale.invert = function(x) { 29298 return d3_time_scaleDate(linear.invert(x)); 29299 }; 29300 scale.domain = function(x) { 29301 if (!arguments.length) return linear.domain().map(d3_time_scaleDate); 29302 linear.domain(x); 29303 return scale; 29304 }; 29305 function tickMethod(extent, count) { 29306 var span = extent[1] - extent[0], target = span / count, i = d3.bisect(d3_time_scaleSteps, target); 29307 return i == d3_time_scaleSteps.length ? [ methods.year, d3_scale_linearTickRange(extent.map(function(d) { 29308 return d / 31536e6; 29309 }), count)[2] ] : !i ? [ d3_time_scaleMilliseconds, d3_scale_linearTickRange(extent, count)[2] ] : methods[target / d3_time_scaleSteps[i - 1] < d3_time_scaleSteps[i] / target ? i - 1 : i]; 29310 } 29311 scale.nice = function(interval, skip) { 29312 var domain = scale.domain(), extent = d3_scaleExtent(domain), method = interval == null ? tickMethod(extent, 10) : typeof interval === "number" && tickMethod(extent, interval); 29313 if (method) interval = method[0], skip = method[1]; 29314 function skipped(date) { 29315 return !isNaN(date) && !interval.range(date, d3_time_scaleDate(+date + 1), skip).length; 29316 } 29317 return scale.domain(d3_scale_nice(domain, skip > 1 ? { 29318 floor: function(date) { 29319 while (skipped(date = interval.floor(date))) date = d3_time_scaleDate(date - 1); 29320 return date; 29321 }, 29322 ceil: function(date) { 29323 while (skipped(date = interval.ceil(date))) date = d3_time_scaleDate(+date + 1); 29324 return date; 29325 } 29326 } : interval)); 29327 }; 29328 scale.ticks = function(interval, skip) { 29329 var extent = d3_scaleExtent(scale.domain()), method = interval == null ? tickMethod(extent, 10) : typeof interval === "number" ? tickMethod(extent, interval) : !interval.range && [ { 29330 range: interval 29331 }, skip ]; 29332 if (method) interval = method[0], skip = method[1]; 29333 return interval.range(extent[0], d3_time_scaleDate(+extent[1] + 1), skip < 1 ? 1 : skip); 29334 }; 29335 scale.tickFormat = function() { 29336 return format; 29337 }; 29338 scale.copy = function() { 29339 return d3_time_scale(linear.copy(), methods, format); 29340 }; 29341 return d3_scale_linearRebind(scale, linear); 29342 } 29343 function d3_time_scaleDate(t) { 29344 return new Date(t); 29345 } 29346 var d3_time_scaleSteps = [ 1e3, 5e3, 15e3, 3e4, 6e4, 3e5, 9e5, 18e5, 36e5, 108e5, 216e5, 432e5, 864e5, 1728e5, 6048e5, 2592e6, 7776e6, 31536e6 ]; 29347 var d3_time_scaleLocalMethods = [ [ d3_time.second, 1 ], [ d3_time.second, 5 ], [ d3_time.second, 15 ], [ d3_time.second, 30 ], [ d3_time.minute, 1 ], [ d3_time.minute, 5 ], [ d3_time.minute, 15 ], [ d3_time.minute, 30 ], [ d3_time.hour, 1 ], [ d3_time.hour, 3 ], [ d3_time.hour, 6 ], [ d3_time.hour, 12 ], [ d3_time.day, 1 ], [ d3_time.day, 2 ], [ d3_time.week, 1 ], [ d3_time.month, 1 ], [ d3_time.month, 3 ], [ d3_time.year, 1 ] ]; 29348 var d3_time_scaleLocalFormat = d3_time_format.multi([ [ ".%L", function(d) { 29349 return d.getMilliseconds(); 29350 } ], [ ":%S", function(d) { 29351 return d.getSeconds(); 29352 } ], [ "%I:%M", function(d) { 29353 return d.getMinutes(); 29354 } ], [ "%I %p", function(d) { 29355 return d.getHours(); 29356 } ], [ "%a %d", function(d) { 29357 return d.getDay() && d.getDate() != 1; 29358 } ], [ "%b %d", function(d) { 29359 return d.getDate() != 1; 29360 } ], [ "%B", function(d) { 29361 return d.getMonth(); 29362 } ], [ "%Y", d3_true ] ]); 29363 var d3_time_scaleMilliseconds = { 29364 range: function(start, stop, step) { 29365 return d3.range(Math.ceil(start / step) * step, +stop, step).map(d3_time_scaleDate); 29366 }, 29367 floor: d3_identity, 29368 ceil: d3_identity 29369 }; 29370 d3_time_scaleLocalMethods.year = d3_time.year; 29371 d3_time.scale = function() { 29372 return d3_time_scale(d3.scale.linear(), d3_time_scaleLocalMethods, d3_time_scaleLocalFormat); 29373 }; 29374 var d3_time_scaleUtcMethods = d3_time_scaleLocalMethods.map(function(m) { 29375 return [ m[0].utc, m[1] ]; 29376 }); 29377 var d3_time_scaleUtcFormat = d3_time_formatUtc.multi([ [ ".%L", function(d) { 29378 return d.getUTCMilliseconds(); 29379 } ], [ ":%S", function(d) { 29380 return d.getUTCSeconds(); 29381 } ], [ "%I:%M", function(d) { 29382 return d.getUTCMinutes(); 29383 } ], [ "%I %p", function(d) { 29384 return d.getUTCHours(); 29385 } ], [ "%a %d", function(d) { 29386 return d.getUTCDay() && d.getUTCDate() != 1; 29387 } ], [ "%b %d", function(d) { 29388 return d.getUTCDate() != 1; 29389 } ], [ "%B", function(d) { 29390 return d.getUTCMonth(); 29391 } ], [ "%Y", d3_true ] ]); 29392 d3_time_scaleUtcMethods.year = d3_time.year.utc; 29393 d3_time.scale.utc = function() { 29394 return d3_time_scale(d3.scale.linear(), d3_time_scaleUtcMethods, d3_time_scaleUtcFormat); 29395 }; 29396 d3.text = d3_xhrType(function(request) { 29397 return request.responseText; 29398 }); 29399 d3.json = function(url, callback) { 29400 return d3_xhr(url, "application/json", d3_json, callback); 29401 }; 29402 function d3_json(request) { 29403 return JSON.parse(request.responseText); 29404 } 29405 d3.html = function(url, callback) { 29406 return d3_xhr(url, "text/html", d3_html, callback); 29407 }; 29408 function d3_html(request) { 29409 var range = d3_document.createRange(); 29410 range.selectNode(d3_document.body); 29411 return range.createContextualFragment(request.responseText); 29412 } 29413 d3.xml = d3_xhrType(function(request) { 29414 return request.responseXML; 29415 }); 29416 if (typeof define === "function" && define.amd) define('d3',d3); else if (typeof module === "object" && module.exports) module.exports = d3; 29417 this.d3 = d3; 29418}(); 29419(function (window) { 29420 'use strict'; 29421 29422 /*global define, module, exports, require */ 29423 29424 var c3 = { version: "0.3.0" }; 29425 29426 var c3_chart_fn, c3_chart_internal_fn; 29427 29428 function Chart(config) { 29429 var $$ = this.internal = new ChartInternal(this); 29430 $$.loadConfig(config); 29431 $$.init(); 29432 29433 // bind "this" to nested API 29434 (function bindThis(fn, target, argThis) { 29435 for (var key in fn) { 29436 target[key] = fn[key].bind(argThis); 29437 if (Object.keys(fn[key]).length > 0) { 29438 bindThis(fn[key], target[key], argThis); 29439 } 29440 } 29441 })(c3_chart_fn, this, this); 29442 } 29443 29444 function ChartInternal(api) { 29445 var $$ = this; 29446 $$.d3 = window.d3 ? window.d3 : typeof require !== 'undefined' ? require("d3") : undefined; 29447 $$.api = api; 29448 $$.config = $$.getDefaultConfig(); 29449 $$.data = {}; 29450 $$.cache = {}; 29451 $$.axes = {}; 29452 } 29453 29454 c3.generate = function (config) { 29455 return new Chart(config); 29456 }; 29457 29458 c3.chart = { 29459 fn: Chart.prototype, 29460 internal: { 29461 fn: ChartInternal.prototype 29462 } 29463 }; 29464 c3_chart_fn = c3.chart.fn; 29465 c3_chart_internal_fn = c3.chart.internal.fn; 29466 29467 29468 c3_chart_internal_fn.init = function () {
29469 var $$ = this, config = $$.config; 29470 29471 $$.initParams(); 29472 29473 if (config.data_url) { 29474 $$.convertUrlToData(config.data_url, config.data_mimeType, config.data_keys, $$.initWithData); 29475 } 29476 else if (config.data_json) { 29477 $$.initWithData($$.convertJsonToData(config.data_json, config.data_keys)); 29478 } 29479 else if (config.data_rows) { 29480 $$.initWithData($$.convertRowsToData(config.data_rows)); 29481 } 29482 else if (config.data_columns) { 29483 $$.initWithData($$.convertColumnsToData(config.data_columns)); 29484 } 29485 else { 29486 throw Error('url or json or rows or columns is required.'); 29487 } 29488 }; 29489 29490 c3_chart_internal_fn.initParams = function () { 29491 var $$ = this, d3 = $$.d3, config = $$.config; 29492 29493 // MEMO: clipId needs to be unique because it conflicts when multiple charts exist 29494 $$.clipId = "c3-" + (+new Date()) + '-clip', 29495 $$.clipIdForXAxis = $$.clipId + '-xaxis', 29496 $$.clipIdForYAxis = $$.clipId + '-yaxis', 29497 $$.clipPath = $$.getClipPath($$.clipId), 29498 $$.clipPathForXAxis = $$.getClipPath($$.clipIdForXAxis), 29499 $$.clipPathForYAxis = $$.getClipPath($$.clipIdForYAxis); 29500 29501 $$.dragStart = null; 29502 $$.dragging = false; 29503 $$.cancelClick = false; 29504 $$.mouseover = false; 29505 $$.transiting = false; 29506 29507 $$.color = $$.generateColor(); 29508 $$.levelColor = $$.generateLevelColor(); 29509 29510 $$.dataTimeFormat = config.data_xLocaltime ? d3.time.format : d3.time.format.utc; 29511 $$.axisTimeFormat = config.axis_x_localtime ? d3.time.format : d3.time.format.utc; 29512 $$.defaultAxisTimeFormat = $$.axisTimeFormat.multi([ 29513 [".%L", function (d) { return d.getMilliseconds(); }], 29514 [":%S", function (d) { return d.getSeconds(); }], 29515 ["%I:%M", function (d) { return d.getMinutes(); }], 29516 ["%I %p", function (d) { return d.getHours(); }], 29517 ["%-m/%-d", function (d) { return d.getDay() && d.getDate() !== 1; }], 29518 ["%-m/%-d", function (d) { return d.getDate() !== 1; }], 29519 ["%-m/%-d", function (d) { return d.getMonth(); }], 29520 ["%Y/%-m/%-d", function () { return true; }] 29521 ]); 29522 29523 $$.hiddenTargetIds = []; 29524 $$.hiddenLegendIds = []; 29525 29526 $$.xOrient = config.axis_rotated ? "left" : "bottom"; 29527 $$.yOrient = config.axis_rotated ? "bottom" : "left"; 29528 $$.y2Orient = config.axis_rotated ? "top" : "right"; 29529 $$.subXOrient = config.axis_rotated ? "left" : "bottom"; 29530 29531 $$.isLegendRight = config.legend_position === 'right'; 29532 $$.isLegendInset = config.legend_position === 'inset'; 29533 $$.isLegendTop = config.legend_inset_anchor === 'top-left' || config.legend_inset_anchor === 'top-right'; 29534 $$.isLegendLeft = config.legend_inset_anchor === 'top-left' || config.legend_inset_anchor === 'bottom-left'; 29535 $$.legendStep = 0; 29536 $$.legendItemWidth = 0; 29537 $$.legendItemHeight = 0; 29538 $$.legendOpacityForHidden = 0.15; 29539 29540 $$.currentMaxTickWidth = 0; 29541 29542 $$.rotated_padding_left = 30; 29543 $$.rotated_padding_right = config.axis_rotated && !config.axis_x_show ? 0 : 30; 29544 $$.rotated_padding_top = 5; 29545 29546 $$.withoutFadeIn = {}; 29547 29548 $$.axes.subx = d3.selectAll([]); // needs when excluding subchart.js 29549 }; 29550 29551 c3_chart_internal_fn.initWithData = function (data) { 29552 var $$ = this, d3 = $$.d3, config = $$.config; 29553 var main, binding = true; 29554 29555 if ($$.initPie) { $$.initPie(); } 29556 if ($$.initBrush) { $$.initBrush(); } 29557 if ($$.initZoom) { $$.initZoom(); } 29558 29559 $$.selectChart = d3.select(config.bindto); 29560 if ($$.selectChart.empty()) { 29561 $$.selectChart = d3.select(document.createElement('div')).style('opacity', 0); 29562 $$.observeInserted($$.selectChart); 29563 binding = false; 29564 } 29565 $$.selectChart.html("").classed("c3", true); 29566 29567 // Init data as targets 29568 $$.data.xs = {}; 29569 $$.data.targets = $$.convertDataToTargets(data); 29570 29571 if (config.data_filter) { 29572 $$.data.targets = $$.data.targets.filter(config.data_filter); 29573 } 29574 29575 // Set targets to hide if needed 29576 if (config.data_hide) { 29577 $$.addHiddenTargetIds(config.data_hide === true ? $$.mapToIds($$.data.targets) : config.data_hide); 29578 } 29579
29580 // when gauge, hide legend // TODO: fix 29581 if ($$.hasType('gauge')) { 29582 config.legend_show = false; 29583 } 29584 29585 // Init sizes and scales 29586 $$.updateSizes(); 29587 $$.updateScales(); 29588 29589 // Set domains for each scale 29590 $$.x.domain(d3.extent($$.getXDomain($$.data.targets))); 29591 $$.y.domain($$.getYDomain($$.data.targets, 'y')); 29592 $$.y2.domain($$.getYDomain($$.data.targets, 'y2')); 29593 $$.subX.domain($$.x.domain()); 29594 $$.subY.domain($$.y.domain()); 29595 $$.subY2.domain($$.y2.domain()); 29596 29597 // Save original x domain for zoom update 29598 $$.orgXDomain = $$.x.domain(); 29599 29600 // Set initialized scales to brush and zoom 29601 if ($$.brush) { $$.brush.scale($$.subX); } 29602 if (config.zoom_enabled) { $$.zoom.scale($$.x); } 29603 29604 /*-- Basic Elements --*/ 29605 29606 // Define svgs 29607 $$.svg = $$.selectChart.append("svg") 29608 .style("overflow", "hidden") 29609 .on('mouseenter', function () { return config.onmouseover.call($$); }) 29610 .on('mouseleave', function () { return config.onmouseout.call($$); }); 29611 29612 // Define defs 29613 $$.defs = $$.svg.append("defs"); 29614 $$.defs.append("clipPath").attr("id", $$.clipId).append("rect"); 29615 $$.defs.append("clipPath").attr("id", $$.clipIdForXAxis).append("rect"); 29616 $$.defs.append("clipPath").attr("id", $$.clipIdForYAxis).append("rect"); 29617 $$.updateSvgSize(); 29618 29619 // Define regions 29620 main = $$.main = $$.svg.append("g").attr("transform", $$.getTranslate('main')); 29621 29622 if ($$.initSubchart) { $$.initSubchart(); } 29623 if ($$.initTooltip) { $$.initTooltip(); } 29624 if ($$.initLegend) { $$.initLegend(); } 29625 29626 /*-- Main Region --*/ 29627 29628 // text when empty 29629 main.append("text") 29630 .attr("class", CLASS.text + ' ' + CLASS.empty) 29631 .attr("text-anchor", "middle") // horizontal centering of text at x position in all browsers. 29632 .attr("dominant-baseline", "middle"); // vertical centering of text at y position in all browsers, except IE. 29633 29634 // Regions 29635 $$.initRegion(); 29636 29637 // Grids 29638 $$.initGrid(); 29639 29640 // Define g for chart area 29641 main.append('g') 29642 .attr("clip-path", $$.clipPath) 29643 .attr('class', CLASS.chart); 29644 29645 // Cover whole with rects for events 29646 $$.initEventRect(); 29647 29648 // Define g for bar chart area 29649 if ($$.initBar) { $$.initBar(); } 29650 29651 // Define g for line chart area 29652 if ($$.initLine) { $$.initLine(); } 29653 29654 // Define g for arc chart area 29655 if ($$.initArc) { $$.initArc(); } 29656 if ($$.initGauge) { $$.initGauge(); } 29657 29658 // Define g for text area 29659 if ($$.initText) { $$.initText(); } 29660 29661 // if zoom privileged, insert rect to forefront 29662 // TODO: is this needed? 29663 main.insert('rect', config.zoom_privileged ? null : 'g.' + CLASS.regions) 29664 .attr('class', CLASS.zoomRect) 29665 .attr('width', $$.width) 29666 .attr('height', $$.height) 29667 .style('opacity', 0) 29668 .on("dblclick.zoom", null); 29669 29670 // Set default extent if defined 29671 if (config.axis_x_default) { 29672 $$.brush.extent(isFunction(config.axis_x_default) ? config.axis_x_default($$.getXDomain()) : config.axis_x_default); 29673 } 29674 29675 // Add Axis 29676 $$.initAxis(); 29677 29678 // Set targets 29679 $$.updateTargets($$.data.targets); 29680 29681 // Draw with targets 29682 if (binding) { 29683 $$.updateDimension(); 29684 $$.redraw({ 29685 withTransform: true, 29686 withUpdateXDomain: true, 29687 withUpdateOrgXDomain: true, 29688 withTransitionForAxis: false 29689 }); 29690 } 29691 29692 // Bind resize event 29693 if (window.onresize == null) { 29694 window.onresize = $$.generateResize(); 29695 } 29696 if (window.onresize.add) { 29697 window.onresize.add(function () { 29698 config.onresize.call($$); 29699 }); 29700 window.onresize.add(function () { 29701 $$.api.flush(); 29702 }); 29703 window.onresize.add(function () { 29704 config.onresized.call($$); 29705 }); 29706 } 29707 29708 // export element of the chart 29709 $$.api.element = $$.selectChart.node(); 29710 }; 29711 29712 c3_chart_internal_fn.smoothLines = function (el, type) { 29713 var $$ = this; 29714 if (type === 'grid') { 29715 el.each(function () { 29716 var g = $$.d3.select(this), 29717 x1 = g.attr('x1'), 29718 x2 = g.attr('x2'), 29719 y1 = g.attr('y1'), 29720 y2 = g.attr('y2'); 29721 g.attr({
vendor: 9,211 bytes, lines 29722-29937
29722 'x1': Math.ceil(x1), 29723 'x2': Math.ceil(x2), 29724 'y1': Math.ceil(y1), 29725 'y2': Math.ceil(y2) 29726 }); 29727 }); 29728 } 29729 }; 29730 29731 29732 c3_chart_internal_fn.updateSizes = function () { 29733 var $$ = this, config = $$.config; 29734 var legendHeight = $$.legend ? $$.getLegendHeight() : 0, 29735 legendWidth = $$.legend ? $$.getLegendWidth() : 0, 29736 legendHeightForBottom = $$.isLegendRight || $$.isLegendInset ? 0 : legendHeight, 29737 hasArc = $$.hasArcType(), 29738 xAxisHeight = config.axis_rotated || hasArc ? 0 : $$.getHorizontalAxisHeight('x'), 29739 subchartHeight = config.subchart_show && !hasArc ? (config.subchart_size_height + xAxisHeight) : 0; 29740 29741 $$.currentWidth = $$.getCurrentWidth(); 29742 $$.currentHeight = $$.getCurrentHeight(); 29743 29744 // for main 29745 $$.margin = config.axis_rotated ? { 29746 top: $$.getHorizontalAxisHeight('y2') + $$.getCurrentPaddingTop(), 29747 right: hasArc ? 0 : $$.getCurrentPaddingRight(), 29748 bottom: $$.getHorizontalAxisHeight('y') + legendHeightForBottom + $$.getCurrentPaddingBottom(), 29749 left: subchartHeight + (hasArc ? 0 : $$.getCurrentPaddingLeft()) 29750 } : { 29751 top: 4 + $$.getCurrentPaddingTop(), // for top tick text 29752 right: hasArc ? 0 : $$.getCurrentPaddingRight(), 29753 bottom: xAxisHeight + subchartHeight + legendHeightForBottom + $$.getCurrentPaddingBottom(), 29754 left: hasArc ? 0 : $$.getCurrentPaddingLeft() 29755 }; 29756 29757 // for subchart 29758 $$.margin2 = config.axis_rotated ? { 29759 top: $$.margin.top, 29760 right: NaN, 29761 bottom: 20 + legendHeightForBottom, 29762 left: $$.rotated_padding_left 29763 } : { 29764 top: $$.currentHeight - subchartHeight - legendHeightForBottom, 29765 right: NaN, 29766 bottom: xAxisHeight + legendHeightForBottom, 29767 left: $$.margin.left 29768 }; 29769 29770 // for legend 29771 $$.margin3 = { 29772 top: 0, 29773 right: NaN, 29774 bottom: 0, 29775 left: 0 29776 }; 29777 if ($$.updateSizeForLegend) { $$.updateSizeForLegend(legendHeight, legendWidth); } 29778 29779 $$.width = $$.currentWidth - $$.margin.left - $$.margin.right; 29780 $$.height = $$.currentHeight - $$.margin.top - $$.margin.bottom; 29781 if ($$.width < 0) { $$.width = 0; } 29782 if ($$.height < 0) { $$.height = 0; } 29783 29784 $$.width2 = config.axis_rotated ? $$.margin.left - $$.rotated_padding_left - $$.rotated_padding_right : $$.width; 29785 $$.height2 = config.axis_rotated ? $$.height : $$.currentHeight - $$.margin2.top - $$.margin2.bottom; 29786 if ($$.width2 < 0) { $$.width2 = 0; } 29787 if ($$.height2 < 0) { $$.height2 = 0; } 29788 29789 // for arc 29790 $$.arcWidth = $$.width - ($$.isLegendRight ? legendWidth + 10 : 0); 29791 $$.arcHeight = $$.height - ($$.isLegendRight ? 0 : 10); 29792 if ($$.updateRadius) { $$.updateRadius(); } 29793 29794 if ($$.isLegendRight && hasArc) { 29795 $$.margin3.left = $$.arcWidth / 2 + $$.radiusExpanded * 1.1; 29796 } 29797 }; 29798 29799 c3_chart_internal_fn.updateTargets = function (targets) { 29800 var $$ = this, config = $$.config; 29801 29802 /*-- Main --*/ 29803 29804 //-- Text --// 29805 $$.updateTargetsForText(targets); 29806 29807 //-- Bar --// 29808 $$.updateTargetsForBar(targets); 29809 29810 //-- Line --// 29811 $$.updateTargetsForLine(targets); 29812 29813 //-- Arc --// 29814 if ($$.updateTargetsForArc) { $$.updateTargetsForArc(targets); } 29815 if ($$.updateTargetsForSubchart) { $$.updateTargetsForSubchart(targets); } 29816 29817 /*-- Show --*/ 29818 29819 // Fade-in each chart 29820 $$.svg.selectAll('.' + CLASS.target).filter(function (d) { return $$.isTargetToShow(d.id); }) 29821 .transition().duration(config.transition_duration) 29822 .style("opacity", 1); 29823 }; 29824 29825 c3_chart_internal_fn.redraw = function (options, transitions) { 29826 var $$ = this, main = $$.main, d3 = $$.d3, config = $$.config; 29827 var areaIndices = $$.getShapeIndices($$.isAreaType), barIndices = $$.getShapeIndices($$.isBarType), lineIndices = $$.getShapeIndices($$.isLineType); 29828 var withY, withSubchart, withTransition, withTransitionForExit, withTransitionForAxis, withTransform, withUpdateXDomain, withUpdateOrgXDomain, withLegend; 29829 var hideAxis = $$.hasArcType(); 29830 var drawArea, drawBar, drawLine, xForText, yForText; 29831 var duration, durationForExit, durationForAxis; 29832 var waitForDraw, flow; 29833 var targetsToShow = $$.filterTargetsToShow($$.data.targets), tickValues, i, intervalForCulling; 29834 var xv = $$.xv.bind($$), 29835 cx = ($$.config.axis_rotated ? $$.circleY : $$.circleX).bind($$), 29836 cy = ($$.config.axis_rotated ? $$.circleX : $$.circleY).bind($$); 29837 29838 options = options || {}; 29839 withY = getOption(options, "withY", true); 29840 withSubchart = getOption(options, "withSubchart", true); 29841 withTransition = getOption(options, "withTransition", true); 29842 withTransform = getOption(options, "withTransform", false); 29843 withUpdateXDomain = getOption(options, "withUpdateXDomain", false); 29844 withUpdateOrgXDomain = getOption(options, "withUpdateOrgXDomain", false); 29845 withLegend = getOption(options, "withLegend", false); 29846 withTransitionForExit = getOption(options, "withTransitionForExit", withTransition); 29847 withTransitionForAxis = getOption(options, "withTransitionForAxis", withTransition); 29848 29849 duration = withTransition ? config.transition_duration : 0; 29850 durationForExit = withTransitionForExit ? duration : 0; 29851 durationForAxis = withTransitionForAxis ? duration : 0; 29852 29853 transitions = transitions || $$.generateAxisTransitions(durationForAxis); 29854 29855 // update legend and transform each g 29856 if (withLegend && config.legend_show) { 29857 $$.updateLegend($$.mapToIds($$.data.targets), options, transitions); 29858 } 29859 29860 // MEMO: needed for grids calculation 29861 if ($$.isCategorized() && targetsToShow.length === 0) { 29862 $$.x.domain([0, $$.axes.x.selectAll('.tick').size()]); 29863 } 29864 29865 if (targetsToShow.length) { 29866 $$.updateXDomain(targetsToShow, withUpdateXDomain, withUpdateOrgXDomain); 29867 // update axis tick values according to options 29868 if (!config.axis_x_tick_values && (config.axis_x_tick_fit || config.axis_x_tick_count)) { 29869 tickValues = $$.generateTickValues($$.mapTargetsToUniqueXs(targetsToShow), config.axis_x_tick_count); 29870 $$.xAxis.tickValues(tickValues); 29871 $$.subXAxis.tickValues(tickValues); 29872 } 29873 } else { 29874 $$.xAxis.tickValues([]); 29875 $$.subXAxis.tickValues([]); 29876 } 29877 29878 $$.y.domain($$.getYDomain(targetsToShow, 'y')); 29879 $$.y2.domain($$.getYDomain(targetsToShow, 'y2')); 29880 29881 // axes 29882 $$.redrawAxis(transitions, hideAxis); 29883 29884 // Update axis label 29885 $$.updateAxisLabels(withTransition); 29886 29887 // show/hide if manual culling needed 29888 if (withUpdateXDomain && targetsToShow.length) { 29889 if (config.axis_x_tick_culling && tickValues) { 29890 for (i = 1; i < tickValues.length; i++) { 29891 if (tickValues.length / i < config.axis_x_tick_culling_max) { 29892 intervalForCulling = i; 29893 break; 29894 } 29895 } 29896 $$.svg.selectAll('.' + CLASS.axisX + ' .tick text').each(function (e) { 29897 var index = tickValues.indexOf(e); 29898 if (index >= 0) { 29899 d3.select(this).style('display', index % intervalForCulling ? 'none' : 'block'); 29900 } 29901 }); 29902 } else { 29903 $$.svg.selectAll('.' + CLASS.axisX + ' .tick text').style('display', 'block'); 29904 } 29905 } 29906 29907 // rotate tick text if needed 29908 if (!config.axis_rotated && config.axis_x_tick_rotate) { 29909 $$.rotateTickText($$.axes.x, transitions.axisX, config.axis_x_tick_rotate); 29910 } 29911 29912 // setup drawer - MEMO: these must be called after axis updated 29913 drawArea = $$.generateDrawArea ? $$.generateDrawArea(areaIndices, false) : undefined; 29914 drawBar = $$.generateDrawBar ? $$.generateDrawBar(barIndices) : undefined; 29915 drawLine = $$.generateDrawLine ? $$.generateDrawLine(lineIndices, false) : undefined; 29916 xForText = $$.generateXYForText(barIndices, true); 29917 yForText = $$.generateXYForText(barIndices, false); 29918 29919 // Update sub domain 29920 $$.subY.domain($$.y.domain()); 29921 $$.subY2.domain($$.y2.domain()); 29922 29923 // tooltip 29924 $$.tooltip.style("display", "none"); 29925 29926 // xgrid focus 29927 $$.updateXgridFocus(); 29928 29929 // Data empty label positioning and text. 29930 main.select("text." + CLASS.text + '.' + CLASS.empty) 29931 .attr("x", $$.width / 2) 29932 .attr("y", $$.height / 2) 29933 .text(config.data_empty_label_text) 29934 .transition() 29935 .style('opacity', targetsToShow.length ? 0 : 1); 29936 29937 // grid
29938 $$.redrawGrid(duration, withY); 29939 29940 // rect for regions 29941 $$.redrawRegion(duration); 29942 29943 // bars 29944 $$.redrawBar(durationForExit); 29945 29946 // lines, areas and cricles 29947 $$.redrawLine(durationForExit); 29948 $$.redrawArea(durationForExit); 29949 if (config.point_show) { $$.redrawCircle(); } 29950 29951 // text 29952 if ($$.hasDataLabel()) { 29953 $$.redrawText(durationForExit); 29954 } 29955 29956 // arc 29957 if ($$.redrawArc) { $$.redrawArc(duration, durationForExit, withTransform); } 29958 29959 // subchart 29960 if ($$.redrawSubchart) { 29961 $$.redrawSubchart(withSubchart, transitions, duration, durationForExit, areaIndices, barIndices, lineIndices); 29962 } 29963 29964 // circles for select 29965 main.selectAll('.' + CLASS.selectedCircles) 29966 .filter($$.isBarType.bind($$)) 29967 .selectAll('circle') 29968 .remove(); 29969 29970 // event rect 29971 if (config.interaction_enabled) { 29972 $$.redrawEventRect(); 29973 } 29974 29975 // transition should be derived from one transition 29976 d3.transition().duration(duration).each(function () { 29977 var transitions = []; 29978 29979 $$.addTransitionForBar(transitions, drawBar); 29980 $$.addTransitionForLine(transitions, drawLine); 29981 $$.addTransitionForArea(transitions, drawArea); 29982 if (config.point_show) { $$.addTransitionForCircle(transitions, cx, cy); } 29983 $$.addTransitionForText(transitions, xForText, yForText, options.flow); 29984 $$.addTransitionForRegion(transitions); 29985 $$.addTransitionForGrid(transitions); 29986 29987 // Wait for end of transitions if called from flow API 29988 if (options.flow) { 29989 waitForDraw = $$.generateWait(); 29990 transitions.forEach(function (t) { 29991 waitForDraw.add(t); 29992 }); 29993 flow = $$.generateFlow({ 29994 targets: targetsToShow, 29995 flow: options.flow, 29996 duration: duration, 29997 drawBar: drawBar, 29998 drawLine: drawLine, 29999 drawArea: drawArea, 30000 cx: cx, 30001 cy: cy, 30002 xv: xv, 30003 xForText: xForText, 30004 yForText: yForText 30005 }); 30006 } 30007 }) 30008 .call(waitForDraw || function () {}, flow || function () {}); 30009 30010 // update fadein condition 30011 $$.mapToIds($$.data.targets).forEach(function (id) { 30012 $$.withoutFadeIn[id] = true; 30013 }); 30014 30015 if ($$.updateZoom) { $$.updateZoom(); } 30016 }; 30017 30018 c3_chart_internal_fn.updateAndRedraw = function (options) { 30019 var $$ = this, config = $$.config, transitions; 30020 options = options || {}; 30021 // same with redraw 30022 options.withTransition = getOption(options, "withTransition", true); 30023 options.withTransform = getOption(options, "withTransform", false); 30024 options.withLegend = getOption(options, "withLegend", false); 30025 // NOT same with redraw 30026 options.withUpdateXDomain = true; 30027 options.withUpdateOrgXDomain = true; 30028 options.withTransitionForExit = false; 30029 options.withTransitionForTransform = getOption(options, "withTransitionForTransform", options.withTransition); 30030 // MEMO: this needs to be called before updateLegend and it means this ALWAYS needs to be called) 30031 $$.updateSizes(); 30032 // MEMO: called in updateLegend in redraw if withLegend 30033 if (!(options.withLegend && config.legend_show)) { 30034 transitions = $$.generateAxisTransitions(options.withTransitionForAxis ? config.transition_duration : 0); 30035 // Update scales 30036 $$.updateScales(); 30037 $$.updateSvgSize(); 30038 // Update g positions 30039 $$.transformAll(options.withTransitionForTransform, transitions); 30040 } 30041 // Draw with new sizes & scales 30042 $$.redraw(options, transitions); 30043 }; 30044 30045 c3_chart_internal_fn.isTimeSeries = function () { 30046 return this.config.axis_x_type === 'timeseries'; 30047 }; 30048 c3_chart_internal_fn.isCategorized = function () { 30049 return this.config.axis_x_type.indexOf('categor') >= 0; 30050 }; 30051 c3_chart_internal_fn.isCustomX = function () {
vendor: 25,170 bytes, lines 30052-30667
30052 var $$ = this, config = $$.config; 30053 return !$$.isTimeSeries() && (config.data_x || notEmpty(config.data_xs)); 30054 }; 30055 30056 c3_chart_internal_fn.getTranslate = function (target) { 30057 var $$ = this, config = $$.config, x, y; 30058 if (target === 'main') { 30059 x = asHalfPixel($$.margin.left); 30060 y = asHalfPixel($$.margin.top); 30061 } else if (target === 'context') { 30062 x = asHalfPixel($$.margin2.left); 30063 y = asHalfPixel($$.margin2.top); 30064 } else if (target === 'legend') { 30065 x = $$.margin3.left; 30066 y = $$.margin3.top; 30067 } else if (target === 'x') { 30068 x = 0; 30069 y = config.axis_rotated ? 0 : $$.height; 30070 } else if (target === 'y') { 30071 x = 0; 30072 y = config.axis_rotated ? $$.height : 0; 30073 } else if (target === 'y2') { 30074 x = config.axis_rotated ? 0 : $$.width; 30075 y = config.axis_rotated ? 1 : 0; 30076 } else if (target === 'subx') { 30077 x = 0; 30078 y = config.axis_rotated ? 0 : $$.height2; 30079 } else if (target === 'arc') { 30080 x = $$.arcWidth / 2; 30081 y = $$.arcHeight / 2; 30082 } 30083 return "translate(" + x + "," + y + ")"; 30084 }; 30085 c3_chart_internal_fn.initialOpacity = function (d) { 30086 return d.value !== null && this.withoutFadeIn[d.id] ? 1 : 0; 30087 }; 30088 c3_chart_internal_fn.opacityForCircle = function (d) { 30089 var $$ = this; 30090 return isValue(d.value) ? $$.isScatterType(d) ? 0.5 : 1 : 0; 30091 }; 30092 c3_chart_internal_fn.opacityForText = function () { 30093 return this.hasDataLabel() ? 1 : 0; 30094 }; 30095 c3_chart_internal_fn.xx = function (d) { 30096 return d ? this.x(d.x) : null; 30097 }; 30098 c3_chart_internal_fn.xv = function (d) { 30099 var $$ = this; 30100 return Math.ceil($$.x($$.isTimeSeries() ? $$.parseDate(d.value) : d.value)); 30101 }; 30102 c3_chart_internal_fn.yv = function (d) { 30103 var $$ = this, 30104 yScale = d.axis && d.axis === 'y2' ? $$.y2 : $$.y; 30105 return Math.ceil(yScale(d.value)); 30106 }; 30107 c3_chart_internal_fn.subxx = function (d) { 30108 return d ? this.subX(d.x) : null; 30109 }; 30110 30111 c3_chart_internal_fn.transformMain = function (withTransition, transitions) { 30112 var $$ = this, 30113 xAxis, yAxis, y2Axis; 30114 if (transitions && transitions.axisX) { 30115 xAxis = transitions.axisX; 30116 } else { 30117 xAxis = $$.main.select('.' + CLASS.axisX); 30118 if (withTransition) { xAxis = xAxis.transition(); } 30119 } 30120 if (transitions && transitions.axisY) { 30121 yAxis = transitions.axisY; 30122 } else { 30123 yAxis = $$.main.select('.' + CLASS.axisY); 30124 if (withTransition) { yAxis = yAxis.transition(); } 30125 } 30126 if (transitions && transitions.axisY2) { 30127 y2Axis = transitions.axisY2; 30128 } else { 30129 y2Axis = $$.main.select('.' + CLASS.axisY2); 30130 if (withTransition) { y2Axis = y2Axis.transition(); } 30131 } 30132 (withTransition ? $$.main.transition() : $$.main).attr("transform", $$.getTranslate('main')); 30133 xAxis.attr("transform", $$.getTranslate('x')); 30134 yAxis.attr("transform", $$.getTranslate('y')); 30135 y2Axis.attr("transform", $$.getTranslate('y2')); 30136 $$.main.select('.' + CLASS.chartArcs).attr("transform", $$.getTranslate('arc')); 30137 }; 30138 c3_chart_internal_fn.transformAll = function (withTransition, transitions) { 30139 var $$ = this; 30140 $$.transformMain(withTransition, transitions); 30141 if ($$.config.subchart_show) { $$.transformContext(withTransition, transitions); } 30142 if ($$.legend) { $$.transformLegend(withTransition); } 30143 }; 30144 30145 c3_chart_internal_fn.updateSvgSize = function () { 30146 var $$ = this; 30147 $$.svg.attr('width', $$.currentWidth).attr('height', $$.currentHeight); 30148 $$.svg.select('#' + $$.clipId).select('rect') 30149 .attr('width', $$.width) 30150 .attr('height', $$.height); 30151 $$.svg.select('#' + $$.clipIdForXAxis).select('rect') 30152 .attr('x', $$.getXAxisClipX.bind($$)) 30153 .attr('y', $$.getXAxisClipY.bind($$)) 30154 .attr('width', $$.getXAxisClipWidth.bind($$)) 30155 .attr('height', $$.getXAxisClipHeight.bind($$)); 30156 $$.svg.select('#' + $$.clipIdForYAxis).select('rect') 30157 .attr('x', $$.getYAxisClipX.bind($$)) 30158 .attr('y', $$.getYAxisClipY.bind($$)) 30159 .attr('width', $$.getYAxisClipWidth.bind($$)) 30160 .attr('height', $$.getYAxisClipHeight.bind($$)); 30161 $$.svg.select('.' + CLASS.zoomRect) 30162 .attr('width', $$.width) 30163 .attr('height', $$.height); 30164 // MEMO: parent div's height will be bigger than svg when <!DOCTYPE html> 30165 $$.selectChart.style('max-height', $$.currentHeight + "px"); 30166 }; 30167 30168 30169 c3_chart_internal_fn.updateDimension = function () { 30170 var $$ = this; 30171 if ($$.config.axis_rotated) { 30172 $$.axes.x.call($$.xAxis); 30173 $$.axes.subx.call($$.subXAxis); 30174 } else { 30175 $$.axes.y.call($$.yAxis); 30176 $$.axes.y2.call($$.y2Axis); 30177 } 30178 $$.updateSizes(); 30179 $$.updateScales(); 30180 $$.updateSvgSize(); 30181 $$.transformAll(false); 30182 }; 30183 30184 c3_chart_internal_fn.observeInserted = function (selection) { 30185 var $$ = this, observer = new MutationObserver(function (mutations) { 30186 mutations.forEach(function (mutation) { 30187 if (mutation.type === 'childList' && mutation.previousSibling) { 30188 observer.disconnect(); 30189 // need to wait for completion of load because size calculation requires the actual sizes determined after that completion 30190 var interval = window.setInterval(function () { 30191 // parentNode will NOT be null when completed 30192 if (selection.node().parentNode) { 30193 window.clearInterval(interval); 30194 $$.updateDimension(); 30195 $$.redraw({ 30196 withTransform: true, 30197 withUpdateXDomain: true, 30198 withUpdateOrgXDomain: true, 30199 withTransition: false, 30200 withTransitionForTransform: false, 30201 withLegend: true 30202 }); 30203 selection.transition().style('opacity', 1); 30204 } 30205 }, 10); 30206 } 30207 }); 30208 }); 30209 observer.observe(selection.node(), {attributes: true, childList: true, characterData: true}); 30210 }; 30211 30212 30213 c3_chart_internal_fn.generateResize = function () { 30214 var resizeFunctions = []; 30215 function callResizeFunctions() { 30216 resizeFunctions.forEach(function (f) { 30217 f(); 30218 }); 30219 } 30220 callResizeFunctions.add = function (f) { 30221 resizeFunctions.push(f); 30222 }; 30223 return callResizeFunctions; 30224 }; 30225 30226 c3_chart_internal_fn.endall = function (transition, callback) { 30227 var n = 0; 30228 transition 30229 .each(function () { ++n; }) 30230 .each("end", function () { 30231 if (!--n) { callback.apply(this, arguments); } 30232 }); 30233 }; 30234 c3_chart_internal_fn.generateWait = function () { 30235 var transitionsToWait = [], 30236 f = function (transition, callback) { 30237 var timer = setInterval(function () { 30238 var done = 0; 30239 transitionsToWait.forEach(function (t) { 30240 if (t.empty()) { 30241 done += 1; 30242 return; 30243 } 30244 try { 30245 t.transition(); 30246 } catch (e) { 30247 done += 1; 30248 } 30249 }); 30250 if (done === transitionsToWait.length) { 30251 clearInterval(timer); 30252 if (callback) { callback(); } 30253 } 30254 }, 10); 30255 }; 30256 f.add = function (transition) { 30257 transitionsToWait.push(transition); 30258 }; 30259 return f; 30260 }; 30261 30262 c3_chart_internal_fn.parseDate = function (date) { 30263 var $$ = this, parsedDate; 30264 if (date instanceof Date) { 30265 parsedDate = date; 30266 } else if (typeof date === 'number') { 30267 parsedDate = new Date(date); 30268 } else { 30269 parsedDate = $$.dataTimeFormat($$.config.data_xFormat).parse(date); 30270 } 30271 if (!parsedDate || isNaN(+parsedDate)) { 30272 window.console.error("Failed to parse x '" + date + "' to Date object"); 30273 } 30274 return parsedDate; 30275 }; 30276 30277 c3_chart_internal_fn.getDefaultConfig = function () { 30278 var config = { 30279 bindto: '#chart', 30280 size_width: undefined, 30281 size_height: undefined, 30282 padding_left: undefined, 30283 padding_right: undefined, 30284 padding_top: undefined, 30285 padding_bottom: undefined, 30286 zoom_enabled: false, 30287 zoom_extent: undefined, 30288 zoom_privileged: false, 30289 zoom_onzoom: function () {}, 30290 interaction_enabled: true, 30291 onmouseover: function () {}, 30292 onmouseout: function () {}, 30293 onresize: function () {}, 30294 onresized: function () {}, 30295 transition_duration: 350, 30296 data_x: undefined, 30297 data_xs: {}, 30298 data_xFormat: '%Y-%m-%d', 30299 data_xLocaltime: true, 30300 data_idConverter: function (id) { return id; }, 30301 data_names: {}, 30302 data_classes: {}, 30303 data_groups: [], 30304 data_axes: {}, 30305 data_type: undefined, 30306 data_types: {}, 30307 data_labels: {}, 30308 data_order: 'desc', 30309 data_regions: {}, 30310 data_color: undefined, 30311 data_colors: {}, 30312 data_hide: false, 30313 data_filter: undefined, 30314 data_selection_enabled: false, 30315 data_selection_grouped: false, 30316 data_selection_isselectable: function () { return true; }, 30317 data_selection_multiple: true, 30318 data_onclick: function () {}, 30319 data_onmouseover: function () {}, 30320 data_onmouseout: function () {}, 30321 data_onselected: function () {}, 30322 data_onunselected: function () {}, 30323 data_ondragstart: function () {}, 30324 data_ondragend: function () {}, 30325 data_url: undefined, 30326 data_json: undefined, 30327 data_rows: undefined, 30328 data_columns: undefined, 30329 data_mimeType: undefined, 30330 data_keys: undefined, 30331 // configuration for no plot-able data supplied. 30332 data_empty_label_text: "", 30333 // subchart 30334 subchart_show: false, 30335 subchart_size_height: 60, 30336 subchart_onbrush: function () {}, 30337 // color 30338 color_pattern: [], 30339 color_threshold: {}, 30340 // legend 30341 legend_show: true, 30342 legend_position: 'bottom', 30343 legend_inset_anchor: 'top-left', 30344 legend_inset_x: 10, 30345 legend_inset_y: 0, 30346 legend_inset_step: undefined, 30347 legend_item_onclick: undefined, 30348 legend_item_onmouseover: undefined, 30349 legend_item_onmouseout: undefined, 30350 legend_equally: false, 30351 // axis 30352 axis_rotated: false, 30353 axis_x_show: true, 30354 axis_x_type: 'indexed', 30355 axis_x_localtime: true, 30356 axis_x_categories: [], 30357 axis_x_tick_centered: false, 30358 axis_x_tick_format: undefined, 30359 axis_x_tick_culling: {}, 30360 axis_x_tick_culling_max: 10, 30361 axis_x_tick_count: undefined, 30362 axis_x_tick_fit: true, 30363 axis_x_tick_values: null, 30364 axis_x_tick_rotate: undefined, 30365 axis_x_tick_outer: true, 30366 axis_x_max: null, 30367 axis_x_min: null, 30368 axis_x_padding: {}, 30369 axis_x_height: undefined, 30370 axis_x_default: undefined, 30371 axis_x_label: {}, 30372 axis_y_show: true, 30373 axis_y_max: undefined, 30374 axis_y_min: undefined, 30375 axis_y_center: undefined, 30376 axis_y_label: {}, 30377 axis_y_tick_format: undefined, 30378 axis_y_tick_outer: true, 30379 axis_y_padding: undefined, 30380 axis_y_ticks: 10, 30381 axis_y2_show: false, 30382 axis_y2_max: undefined, 30383 axis_y2_min: undefined, 30384 axis_y2_center: undefined, 30385 axis_y2_label: {}, 30386 axis_y2_tick_format: undefined, 30387 axis_y2_tick_outer: true, 30388 axis_y2_padding: undefined, 30389 axis_y2_ticks: 10, 30390 // grid 30391 grid_x_show: false, 30392 grid_x_type: 'tick', 30393 grid_x_lines: [], 30394 grid_y_show: false, 30395 // not used 30396 // grid_y_type: 'tick', 30397 grid_y_lines: [], 30398 grid_y_ticks: 10, 30399 grid_focus_show: true, 30400 // point - point of each data 30401 point_show: true, 30402 point_r: 2.5, 30403 point_focus_expand_enabled: true, 30404 point_focus_expand_r: undefined, 30405 point_select_r: undefined, 30406 line_connect_null: false, 30407 // bar 30408 bar_width: undefined, 30409 bar_width_ratio: 0.6, 30410 bar_width_max: undefined, 30411 bar_zerobased: true, 30412 // area 30413 area_zerobased: true, 30414 // pie 30415 pie_label_show: true, 30416 pie_label_format: undefined, 30417 pie_label_threshold: 0.05, 30418 pie_sort: true, 30419 pie_expand: true, 30420 // gauge 30421 gauge_label_show: true, 30422 gauge_label_format: undefined, 30423 gauge_expand: true, 30424 gauge_min: 0, 30425 gauge_max: 100, 30426 gauge_units: undefined, 30427 gauge_width: undefined, 30428 // donut 30429 donut_label_show: true, 30430 donut_label_format: undefined, 30431 donut_label_threshold: 0.05, 30432 donut_width: undefined, 30433 donut_sort: true, 30434 donut_expand: true, 30435 donut_title: "", 30436 // region - region to change style 30437 regions: [], 30438 // tooltip - show when mouseover on each data 30439 tooltip_show: true, 30440 tooltip_grouped: true, 30441 tooltip_format_title: undefined, 30442 tooltip_format_name: undefined, 30443 tooltip_format_value: undefined, 30444 tooltip_contents: function (d, defaultTitleFormat, defaultValueFormat, color) { 30445 return this.getTooltipContent ? this.getTooltipContent(d, defaultTitleFormat, defaultValueFormat, color) : ''; 30446 }, 30447 tooltip_init_show: false, 30448 tooltip_init_x: 0, 30449 tooltip_init_position: {top: '0px', left: '50px'} 30450 }; 30451 30452 Object.keys(this.additionalConfig).forEach(function (key) { 30453 config[key] = this.additionalConfig[key]; 30454 }, this); 30455 30456 return config; 30457 }; 30458 c3_chart_internal_fn.additionalConfig = {}; 30459 30460 c3_chart_internal_fn.loadConfig = function (config) { 30461 var this_config = this.config, target, keys, read; 30462 function find() { 30463 var key = keys.shift(); 30464 // console.log("key =>", key, ", target =>", target); 30465 if (key && target && typeof target === 'object' && key in target) { 30466 target = target[key]; 30467 return find(); 30468 } 30469 else if (!key) { 30470 return target; 30471 } 30472 else { 30473 return undefined; 30474 } 30475 } 30476 Object.keys(this_config).forEach(function (key) { 30477 target = config; 30478 keys = key.split('_'); 30479 read = find(); 30480 // console.log("CONFIG : ", key, read); 30481 if (isDefined(read)) { 30482 this_config[key] = read; 30483 } 30484 }); 30485 }; 30486 30487 c3_chart_internal_fn.getScale = function (min, max, forTimeseries) { 30488 return (forTimeseries ? this.d3.time.scale() : this.d3.scale.linear()).range([min, max]); 30489 }; 30490 c3_chart_internal_fn.getX = function (min, max, domain, offset) { 30491 var $$ = this, 30492 scale = $$.getScale(min, max, $$.isTimeSeries()), 30493 _scale = domain ? scale.domain(domain) : scale, key; 30494 // Define customized scale if categorized axis 30495 if ($$.isCategorized()) { 30496 offset = offset || function () { return 0; }; 30497 scale = function (d, raw) { 30498 var v = _scale(d) + offset(d); 30499 return raw ? v : Math.ceil(v); 30500 }; 30501 } else { 30502 scale = function (d, raw) { 30503 var v = _scale(d); 30504 return raw ? v : Math.ceil(v); 30505 }; 30506 } 30507 // define functions 30508 for (key in _scale) { 30509 scale[key] = _scale[key]; 30510 } 30511 scale.orgDomain = function () { 30512 return _scale.domain(); 30513 }; 30514 // define custom domain() for categorized axis 30515 if ($$.isCategorized()) { 30516 scale.domain = function (domain) { 30517 if (!arguments.length) { 30518 domain = this.orgDomain(); 30519 return [domain[0], domain[1] + 1]; 30520 } 30521 _scale.domain(domain); 30522 return scale; 30523 }; 30524 } 30525 return scale; 30526 }; 30527 c3_chart_internal_fn.getY = function (min, max, domain) { 30528 var scale = this.getScale(min, max); 30529 if (domain) { scale.domain(domain); } 30530 return scale; 30531 }; 30532 c3_chart_internal_fn.getYScale = function (id) { 30533 return this.getAxisId(id) === 'y2' ? this.y2 : this.y; 30534 }; 30535 c3_chart_internal_fn.getSubYScale = function (id) { 30536 return this.getAxisId(id) === 'y2' ? this.subY2 : this.subY; 30537 }; 30538 c3_chart_internal_fn.updateScales = function () { 30539 var $$ = this, config = $$.config, 30540 forInit = !$$.x; 30541 // update edges 30542 $$.xMin = config.axis_rotated ? 1 : 0; 30543 $$.xMax = config.axis_rotated ? $$.height : $$.width; 30544 $$.yMin = config.axis_rotated ? 0 : $$.height; 30545 $$.yMax = config.axis_rotated ? $$.width : 1; 30546 $$.subXMin = $$.xMin; 30547 $$.subXMax = $$.xMax; 30548 $$.subYMin = config.axis_rotated ? 0 : $$.height2; 30549 $$.subYMax = config.axis_rotated ? $$.width2 : 1; 30550 // update scales 30551 $$.x = $$.getX($$.xMin, $$.xMax, forInit ? undefined : $$.x.orgDomain(), function () { return $$.xAxis.tickOffset(); }); 30552 $$.y = $$.getY($$.yMin, $$.yMax, forInit ? undefined : $$.y.domain()); 30553 $$.y2 = $$.getY($$.yMin, $$.yMax, forInit ? undefined : $$.y2.domain()); 30554 $$.subX = $$.getX($$.xMin, $$.xMax, $$.orgXDomain, function (d) { return d % 1 ? 0 : $$.subXAxis.tickOffset(); }); 30555 $$.subY = $$.getY($$.subYMin, $$.subYMax, forInit ? undefined : $$.subY.domain()); 30556 $$.subY2 = $$.getY($$.subYMin, $$.subYMax, forInit ? undefined : $$.subY2.domain()); 30557 // update axes 30558 $$.xAxisTickFormat = $$.getXAxisTickFormat(); 30559 $$.xAxisTickValues = config.axis_x_tick_values ? config.axis_x_tick_values : (forInit ? undefined : $$.xAxis.tickValues()); 30560 $$.xAxis = $$.getXAxis($$.x, $$.xOrient, $$.xAxisTickFormat, $$.xAxisTickValues); 30561 $$.subXAxis = $$.getXAxis($$.subX, $$.subXOrient, $$.xAxisTickFormat, $$.xAxisTickValues); 30562 $$.yAxis = $$.getYAxis($$.y, $$.yOrient, config.axis_y_tick_format, config.axis_y_ticks); 30563 $$.y2Axis = $$.getYAxis($$.y2, $$.y2Orient, config.axis_y2_tick_format, config.axis_y2_ticks); 30564 // Set initialized scales to brush and zoom 30565 if (!forInit) { 30566 if ($$.brush) { $$.brush.scale($$.subX); } 30567 if (config.zoom_enabled) { $$.zoom.scale($$.x); } 30568 } 30569 // update for arc 30570 if ($$.updateArc) { $$.updateArc(); } 30571 }; 30572 30573 c3_chart_internal_fn.getYDomainMin = function (targets) { 30574 var $$ = this, config = $$.config, 30575 ids = $$.mapToIds(targets), ys = $$.getValuesAsIdKeyed(targets), 30576 j, k, baseId, idsInGroup, id, hasNegativeValue; 30577 if (config.data_groups.length > 0) { 30578 hasNegativeValue = $$.hasNegativeValueInTargets(targets); 30579 for (j = 0; j < config.data_groups.length; j++) { 30580 // Determine baseId 30581 idsInGroup = config.data_groups[j].filter(function (id) { return ids.indexOf(id) >= 0; }); 30582 if (idsInGroup.length === 0) { continue; } 30583 baseId = idsInGroup[0]; 30584 // Consider negative values 30585 if (hasNegativeValue && ys[baseId]) { 30586 ys[baseId].forEach(function (v, i) { 30587 ys[baseId][i] = v < 0 ? v : 0; 30588 }); 30589 } 30590 // Compute min 30591 for (k = 1; k < idsInGroup.length; k++) { 30592 id = idsInGroup[k]; 30593 if (! ys[id]) { continue; } 30594 ys[id].forEach(function (v, i) { 30595 if ($$.getAxisId(id) === $$.getAxisId(baseId) && ys[baseId] && !(hasNegativeValue && +v > 0)) { 30596 ys[baseId][i] += +v; 30597 } 30598 }); 30599 } 30600 } 30601 } 30602 return $$.d3.min(Object.keys(ys).map(function (key) { return $$.d3.min(ys[key]); })); 30603 }; 30604 c3_chart_internal_fn.getYDomainMax = function (targets) { 30605 var $$ = this, config = $$.config, 30606 ids = $$.mapToIds(targets), ys = $$.getValuesAsIdKeyed(targets), 30607 j, k, baseId, idsInGroup, id, hasPositiveValue; 30608 if (config.data_groups.length > 0) { 30609 hasPositiveValue = $$.hasPositiveValueInTargets(targets); 30610 for (j = 0; j < config.data_groups.length; j++) { 30611 // Determine baseId 30612 idsInGroup = config.data_groups[j].filter(function (id) { return ids.indexOf(id) >= 0; }); 30613 if (idsInGroup.length === 0) { continue; } 30614 baseId = idsInGroup[0]; 30615 // Consider positive values 30616 if (hasPositiveValue && ys[baseId]) { 30617 ys[baseId].forEach(function (v, i) { 30618 ys[baseId][i] = v > 0 ? v : 0; 30619 }); 30620 } 30621 // Compute max 30622 for (k = 1; k < idsInGroup.length; k++) { 30623 id = idsInGroup[k]; 30624 if (! ys[id]) { continue; } 30625 ys[id].forEach(function (v, i) { 30626 if ($$.getAxisId(id) === $$.getAxisId(baseId) && ys[baseId] && !(hasPositiveValue && +v < 0)) { 30627 ys[baseId][i] += +v; 30628 } 30629 }); 30630 } 30631 } 30632 } 30633 return $$.d3.max(Object.keys(ys).map(function (key) { return $$.d3.max(ys[key]); })); 30634 }; 30635 c3_chart_internal_fn.getYDomain = function (targets, axisId) { 30636 var $$ = this, config = $$.config, 30637 yTargets = targets.filter(function (d) { return $$.getAxisId(d.id) === axisId; }), 30638 yMin = axisId === 'y2' ? config.axis_y2_min : config.axis_y_min, 30639 yMax = axisId === 'y2' ? config.axis_y2_max : config.axis_y_max, 30640 yDomainMin = isValue(yMin) ? yMin : $$.getYDomainMin(yTargets), 30641 yDomainMax = isValue(yMax) ? yMax : $$.getYDomainMax(yTargets), 30642 domainLength, padding, padding_top, padding_bottom, 30643 center = axisId === 'y2' ? config.axis_y2_center : config.axis_y_center, 30644 yDomainAbs, lengths, diff, ratio, isAllPositive, isAllNegative, 30645 isZeroBased = ($$.hasType('bar', yTargets) && config.bar_zerobased) || ($$.hasType('area', yTargets) && config.area_zerobased), 30646 showHorizontalDataLabel = $$.hasDataLabel() && config.axis_rotated, 30647 showVerticalDataLabel = $$.hasDataLabel() && !config.axis_rotated; 30648 if (yTargets.length === 0) { // use current domain if target of axisId is none 30649 return axisId === 'y2' ? $$.y2.domain() : $$.y.domain(); 30650 } 30651 if (yDomainMin === yDomainMax) { 30652 yDomainMin < 0 ? yDomainMax = 0 : yDomainMin = 0; 30653 } 30654 isAllPositive = yDomainMin >= 0 && yDomainMax >= 0; 30655 isAllNegative = yDomainMin <= 0 && yDomainMax <= 0; 30656 30657 // Bar/Area chart should be 0-based if all positive|negative 30658 if (isZeroBased) { 30659 if (isAllPositive) { yDomainMin = 0; } 30660 if (isAllNegative) { yDomainMax = 0; } 30661 } 30662 30663 domainLength = Math.abs(yDomainMax - yDomainMin); 30664 padding = padding_top = padding_bottom = domainLength * 0.1; 30665 30666 if (center) { 30667 yDomainAbs = Math.max(Math.abs(yDomainMin), Math.abs(yDomainMax));
30668 yDomainMax = yDomainAbs - center; 30669 yDomainMin = center - yDomainAbs; 30670 } 30671 // add padding for data label 30672 if (showHorizontalDataLabel) { 30673 lengths = $$.getDataLabelLength(yDomainMin, yDomainMax, axisId, 'width'); 30674 diff = diffDomain($$.y.range()); 30675 ratio = [lengths[0] / diff, lengths[1] / diff]; 30676 padding_top += domainLength * (ratio[1] / (1 - ratio[0] - ratio[1])); 30677 padding_bottom += domainLength * (ratio[0] / (1 - ratio[0] - ratio[1])); 30678 } else if (showVerticalDataLabel) { 30679 lengths = $$.getDataLabelLength(yDomainMin, yDomainMax, axisId, 'height'); 30680 padding_top += lengths[1]; 30681 padding_bottom += lengths[0]; 30682 } 30683 if (axisId === 'y' && config.axis_y_padding) { 30684 padding_top = $$.getAxisPadding(config.axis_y_padding, 'top', padding, domainLength); 30685 padding_bottom = $$.getAxisPadding(config.axis_y_padding, 'bottom', padding, domainLength); 30686 } 30687 if (axisId === 'y2' && config.axis_y2_padding) { 30688 padding_top = $$.getAxisPadding(config.axis_y2_padding, 'top', padding, domainLength); 30689 padding_bottom = $$.getAxisPadding(config.axis_y2_padding, 'bottom', padding, domainLength); 30690 } 30691 // Bar/Area chart should be 0-based if all positive|negative 30692 if (isZeroBased) { 30693 if (isAllPositive) { padding_bottom = yDomainMin; } 30694 if (isAllNegative) { padding_top = -yDomainMax; } 30695 } 30696 return [yDomainMin - padding_bottom, yDomainMax + padding_top]; 30697 }; 30698 c3_chart_internal_fn.getXDomainMin = function (targets) { 30699 var $$ = this, config = $$.config; 30700 return config.axis_x_min ? 30701 ($$.isTimeSeries() ? this.parseDate(config.axis_x_min) : config.axis_x_min) : 30702 $$.d3.min(targets, function (t) { return $$.d3.min(t.values, function (v) { return v.x; }); }); 30703 }; 30704 c3_chart_internal_fn.getXDomainMax = function (targets) { 30705 var $$ = this, config = $$.config; 30706 return config.axis_x_max ? 30707 ($$.isTimeSeries() ? this.parseDate(config.axis_x_max) : config.axis_x_max) : 30708 $$.d3.max(targets, function (t) { return $$.d3.max(t.values, function (v) { return v.x; }); }); 30709 }; 30710 c3_chart_internal_fn.getXDomainPadding = function (targets) { 30711 var $$ = this, config = $$.config, 30712 edgeX = this.getEdgeX(targets), diff = edgeX[1] - edgeX[0], 30713 maxDataCount, padding, paddingLeft, paddingRight; 30714 if ($$.isCategorized()) { 30715 padding = 0; 30716 } else if ($$.hasType('bar', targets)) { 30717 maxDataCount = $$.getMaxDataCount(); 30718 padding = maxDataCount > 1 ? (diff / (maxDataCount - 1)) / 2 : 0.5; 30719 } else { 30720 padding = diff * 0.01; 30721 } 30722 if (typeof config.axis_x_padding === 'object' && notEmpty(config.axis_x_padding)) { 30723 paddingLeft = isValue(config.axis_x_padding.left) ? config.axis_x_padding.left : padding; 30724 paddingRight = isValue(config.axis_x_padding.right) ? config.axis_x_padding.right : padding; 30725 } else if (typeof config.axis_x_padding === 'number') { 30726 paddingLeft = paddingRight = config.axis_x_padding; 30727 } else { 30728 paddingLeft = paddingRight = padding; 30729 } 30730 return {left: paddingLeft, right: paddingRight}; 30731 }; 30732 c3_chart_internal_fn.getXDomain = function (targets) { 30733 var $$ = this, 30734 xDomain = [$$.getXDomainMin(targets), $$.getXDomainMax(targets)], 30735 firstX = xDomain[0], lastX = xDomain[1], 30736 padding = $$.getXDomainPadding(targets), 30737 min = 0, max = 0; 30738 // show center of x domain if min and max are the same 30739 if ((firstX - lastX) === 0 && !$$.isCategorized()) { 30740 firstX = $$.isTimeSeries() ? new Date(firstX.getTime() * 0.5) : -0.5; 30741 lastX = $$.isTimeSeries() ? new Date(lastX.getTime() * 1.5) : 0.5; 30742 } 30743 if (firstX || firstX === 0) { 30744 min = $$.isTimeSeries() ? new Date(firstX.getTime() - padding.left) : firstX - padding.left; 30745 } 30746 if (lastX || lastX === 0) { 30747 max = $$.isTimeSeries() ? new Date(lastX.getTime() + padding.right) : lastX + padding.right; 30748 } 30749 return [min, max]; 30750 }; 30751 c3_chart_internal_fn.updateXDomain = function (targets, withUpdateXDomain, withUpdateOrgXDomain, domain) {
30752 var $$ = this, config = $$.config; 30753 if (withUpdateOrgXDomain) { 30754 $$.x.domain(domain ? domain : $$.d3.extent($$.getXDomain(targets))); 30755 $$.orgXDomain = $$.x.domain(); 30756 if (config.zoom_enabled) { $$.zoom.scale($$.x).updateScaleExtent(); } 30757 $$.subX.domain($$.x.domain()); 30758 if ($$.brush) { $$.brush.scale($$.subX); } 30759 } 30760 if (withUpdateXDomain) { 30761 $$.x.domain(domain ? domain : (!$$.brush || $$.brush.empty()) ? $$.orgXDomain : $$.brush.extent()); 30762 if (config.zoom_enabled) { $$.zoom.scale($$.x).updateScaleExtent(); } 30763 } 30764 return $$.x.domain(); 30765 }; 30766 30767 c3_chart_internal_fn.isX = function (key) { 30768 var $$ = this, config = $$.config; 30769 return (config.data_x && key === config.data_x) || (notEmpty(config.data_xs) && hasValue(config.data_xs, key)); 30770 }; 30771 c3_chart_internal_fn.isNotX = function (key) { 30772 return !this.isX(key); 30773 }; 30774 c3_chart_internal_fn.getXKey = function (id) { 30775 var $$ = this, config = $$.config; 30776 return config.data_x ? config.data_x : notEmpty(config.data_xs) ? config.data_xs[id] : null; 30777 }; 30778 c3_chart_internal_fn.getXValuesOfXKey = function (key, targets) { 30779 var $$ = this, 30780 xValues, ids = targets && notEmpty(targets) ? $$.mapToIds(targets) : []; 30781 ids.forEach(function (id) { 30782 if ($$.getXKey(id) === key) { 30783 xValues = $$.data.xs[id]; 30784 } 30785 }); 30786 return xValues; 30787 }; 30788 c3_chart_internal_fn.getXValue = function (id, i) { 30789 var $$ = this; 30790 return id in $$.data.xs && $$.data.xs[id] && isValue($$.data.xs[id][i]) ? $$.data.xs[id][i] : i; 30791 }; 30792 c3_chart_internal_fn.getOtherTargetXs = function () { 30793 var $$ = this, 30794 idsForX = Object.keys($$.data.xs); 30795 return idsForX.length ? $$.data.xs[idsForX[0]] : null; 30796 }; 30797 c3_chart_internal_fn.getOtherTargetX = function (index) { 30798 var xs = this.getOtherTargetXs(); 30799 return xs && index < xs.length ? xs[index] : null; 30800 }; 30801 c3_chart_internal_fn.addXs = function (xs) { 30802 var $$ = this; 30803 Object.keys(xs).forEach(function (id) { 30804 $$.config.data_xs[id] = xs[id]; 30805 }); 30806 }; 30807 c3_chart_internal_fn.hasMultipleX = function (xs) { 30808 return this.d3.set(Object.keys(xs).map(function (id) { return xs[id]; })).size() > 1; 30809 }; 30810 c3_chart_internal_fn.isMultipleX = function () { 30811 var $$ = this, config = $$.config; 30812 return notEmpty(config.data_xs) && $$.hasMultipleX(config.data_xs); 30813 }; 30814 c3_chart_internal_fn.addName = function (data) { 30815 var $$ = this, name; 30816 if (data) { 30817 name = $$.config.data_names[data.id]; 30818 data.name = name ? name : data.id; 30819 } 30820 return data; 30821 }; 30822 c3_chart_internal_fn.getValueOnIndex = function (values, index) { 30823 var valueOnIndex = values.filter(function (v) { return v.index === index; }); 30824 return valueOnIndex.length ? valueOnIndex[0] : null; 30825 }; 30826 c3_chart_internal_fn.updateTargetX = function (targets, x) { 30827 var $$ = this; 30828 targets.forEach(function (t) { 30829 t.values.forEach(function (v, i) { 30830 v.x = $$.generateTargetX(x[i], t.id, i); 30831 }); 30832 $$.data.xs[t.id] = x; 30833 }); 30834 }; 30835 c3_chart_internal_fn.updateTargetXs = function (targets, xs) { 30836 var $$ = this; 30837 targets.forEach(function (t) { 30838 if (xs[t.id]) { 30839 $$.updateTargetX([t], xs[t.id]); 30840 } 30841 }); 30842 }; 30843 c3_chart_internal_fn.generateTargetX = function (rawX, id, index) { 30844 var $$ = this, x; 30845 if ($$.isTimeSeries()) { 30846 x = rawX ? $$.parseDate(rawX) : $$.parseDate($$.getXValue(id, index)); 30847 } 30848 else if ($$.isCustomX() && !$$.isCategorized()) { 30849 x = isValue(rawX) ? +rawX : $$.getXValue(id, index); 30850 } 30851 else { 30852 x = index; 30853 } 30854 return x; 30855 }; 30856 c3_chart_internal_fn.cloneTarget = function (target) { 30857 return { 30858 id : target.id, 30859 id_org : target.id_org, 30860 values : target.values.map(function (d) { 30861 return {x: d.x, value: d.value, id: d.id}; 30862 }) 30863 }; 30864 }; 30865 c3_chart_internal_fn.getPrevX = function (i) { 30866 var $$ = this, value = $$.getValueOnIndex($$.data.targets[0].values, i - 1); 30867 return value ? value.x : null; 30868 }; 30869 c3_chart_internal_fn.getNextX = function (i) { 30870 var $$ = this, value = $$.getValueOnIndex($$.data.targets[0].values, i + 1); 30871 return value ? value.x : null; 30872 }; 30873 c3_chart_internal_fn.getMaxDataCount = function () { 30874 var $$ = this; 30875 return $$.d3.max($$.data.targets, function (t) { return t.values.length; }); 30876 }; 30877 c3_chart_internal_fn.getMaxDataCountTarget = function (targets) { 30878 var length = targets.length, max = 0, maxTarget; 30879 if (length > 1) {
30880 targets.forEach(function (t) { 30881 if (t.values.length > max) { 30882 maxTarget = t; 30883 max = t.values.length; 30884 } 30885 }); 30886 } else { 30887 maxTarget = length ? targets[0] : null; 30888 } 30889 return maxTarget; 30890 }; 30891 c3_chart_internal_fn.getEdgeX = function (targets) { 30892 var target = this.getMaxDataCountTarget(targets), firstData, lastData; 30893 if (!target) { 30894 return [0, 0]; 30895 } 30896 firstData = target.values[0], lastData = target.values[target.values.length - 1]; 30897 return [firstData.x, lastData.x]; 30898 }; 30899 c3_chart_internal_fn.mapToIds = function (targets) { 30900 return targets.map(function (d) { return d.id; }); 30901 }; 30902 c3_chart_internal_fn.mapToTargetIds = function (ids) { 30903 var $$ = this; 30904 return ids ? (isString(ids) ? [ids] : ids) : $$.mapToIds($$.data.targets); 30905 }; 30906 c3_chart_internal_fn.hasTarget = function (targets, id) { 30907 var ids = this.mapToIds(targets), i; 30908 for (i = 0; i < ids.length; i++) { 30909 if (ids[i] === id) { 30910 return true; 30911 } 30912 } 30913 return false; 30914 }; 30915 c3_chart_internal_fn.isTargetToShow = function (targetId) { 30916 return this.hiddenTargetIds.indexOf(targetId) < 0; 30917 }; 30918 c3_chart_internal_fn.isLegendToShow = function (targetId) { 30919 return this.hiddenLegendIds.indexOf(targetId) < 0; 30920 }; 30921 c3_chart_internal_fn.filterTargetsToShow = function (targets) { 30922 var $$ = this; 30923 return targets.filter(function (t) { return $$.isTargetToShow(t.id); }); 30924 }; 30925 c3_chart_internal_fn.mapTargetsToUniqueXs = function (targets) { 30926 var $$ = this; 30927 var xs = $$.d3.set($$.d3.merge(targets.map(function (t) { return t.values.map(function (v) { return v.x; }); }))).values(); 30928 return $$.isTimeSeries() ? xs.map(function (x) { return new Date(x); }) : xs.map(function (x) { return +x; }); 30929 }; 30930 c3_chart_internal_fn.addHiddenTargetIds = function (targetIds) { 30931 this.hiddenTargetIds = this.hiddenTargetIds.concat(targetIds); 30932 }; 30933 c3_chart_internal_fn.removeHiddenTargetIds = function (targetIds) { 30934 this.hiddenTargetIds = this.hiddenTargetIds.filter(function (id) { return targetIds.indexOf(id) < 0; }); 30935 }; 30936 c3_chart_internal_fn.addHiddenLegendIds = function (targetIds) { 30937 this.hiddenLegendIds = this.hiddenLegendIds.concat(targetIds); 30938 }; 30939 c3_chart_internal_fn.removeHiddenLegendIds = function (targetIds) { 30940 this.hiddenLegendIds = this.hiddenLegendIds.filter(function (id) { return targetIds.indexOf(id) < 0; }); 30941 }; 30942 c3_chart_internal_fn.getValuesAsIdKeyed = function (targets) { 30943 var ys = {}; 30944 targets.forEach(function (t) { 30945 ys[t.id] = []; 30946 t.values.forEach(function (v) { 30947 ys[t.id].push(v.value); 30948 }); 30949 }); 30950 return ys; 30951 }; 30952 c3_chart_internal_fn.checkValueInTargets = function (targets, checker) { 30953 var ids = Object.keys(targets), i, j, values; 30954 for (i = 0; i < ids.length; i++) { 30955 values = targets[ids[i]].values; 30956 for (j = 0; j < values.length; j++) { 30957 if (checker(values[j].value)) { 30958 return true; 30959 } 30960 } 30961 } 30962 return false; 30963 }; 30964 c3_chart_internal_fn.hasNegativeValueInTargets = function (targets) { 30965 return this.checkValueInTargets(targets, function (v) { return v < 0; }); 30966 }; 30967 c3_chart_internal_fn.hasPositiveValueInTargets = function (targets) { 30968 return this.checkValueInTargets(targets, function (v) { return v > 0; }); 30969 }; 30970 c3_chart_internal_fn.isOrderDesc = function () { 30971 var config = this.config; 30972 return config.data_order && config.data_order.toLowerCase() === 'desc'; 30973 }; 30974 c3_chart_internal_fn.isOrderAsc = function () { 30975 var config = this.config; 30976 return config.data_order && config.data_order.toLowerCase() === 'asc'; 30977 }; 30978 c3_chart_internal_fn.orderTargets = function (targets) {
30979 var $$ = this, config = $$.config, orderAsc = $$.isOrderAsc(), orderDesc = $$.isOrderDesc(); 30980 if (orderAsc || orderDesc) { 30981 targets.sort(function (t1, t2) { 30982 var reducer = function (p, c) { return p + Math.abs(c.value); }; 30983 var t1Sum = t1.values.reduce(reducer, 0), 30984 t2Sum = t2.values.reduce(reducer, 0); 30985 return orderAsc ? t2Sum - t1Sum : t1Sum - t2Sum; 30986 }); 30987 } else if (isFunction(config.data_order)) { 30988 targets.sort(config.data_order); 30989 } // TODO: accept name array for order 30990 return targets; 30991 }; 30992 c3_chart_internal_fn.filterSameX = function (targets, x) { 30993 return this.d3.merge(targets.map(function (t) { return t.values; })).filter(function (v) { return v.x - x === 0; }); 30994 }; 30995 c3_chart_internal_fn.filterRemoveNull = function (data) { 30996 return data.filter(function (d) { return isValue(d.value); }); 30997 }; 30998 c3_chart_internal_fn.hasDataLabel = function () { 30999 var config = this.config; 31000 if (typeof config.data_labels === 'boolean' && config.data_labels) { 31001 return true; 31002 } else if (typeof config.data_labels === 'object' && notEmpty(config.data_labels)) { 31003 return true; 31004 } 31005 return false; 31006 }; 31007 c3_chart_internal_fn.getDataLabelLength = function (min, max, axisId, key) { 31008 var $$ = this, 31009 lengths = [0, 0], paddingCoef = 1.3; 31010 $$.selectChart.select('svg').selectAll('.dummy') 31011 .data([min, max]) 31012 .enter().append('text') 31013 .text(function (d) { return $$.formatByAxisId(axisId)(d); }) 31014 .each(function (d, i) { 31015 lengths[i] = this.getBoundingClientRect()[key] * paddingCoef; 31016 }) 31017 .remove(); 31018 return lengths; 31019 }; 31020 c3_chart_internal_fn.isNoneArc = function (d) { 31021 return this.hasTarget(this.data.targets, d.id); 31022 }, 31023 c3_chart_internal_fn.isArc = function (d) { 31024 return 'data' in d && this.hasTarget(this.data.targets, d.data.id); 31025 }; 31026 c3_chart_internal_fn.findSameXOfValues = function (values, index) { 31027 var i, targetX = values[index].x, sames = []; 31028 for (i = index - 1; i >= 0; i--) { 31029 if (targetX !== values[i].x) { break; } 31030 sames.push(values[i]); 31031 } 31032 for (i = index; i < values.length; i++) { 31033 if (targetX !== values[i].x) { break; } 31034 sames.push(values[i]); 31035 } 31036 return sames; 31037 }; 31038 31039 c3_chart_internal_fn.findClosestOfValues = function (values, pos, _min, _max) { // MEMO: values must be sorted by x 31040 var $$ = this, 31041 min = _min ? _min : 0, 31042 max = _max ? _max : values.length - 1, 31043 med = Math.floor((max - min) / 2) + min, 31044 value = values[med], 31045 diff = $$.x(value.x) - pos[$$.config.axis_rotated ? 1 : 0], 31046 candidates; 31047 31048 // Update range for search 31049 diff > 0 ? max = med : min = med; 31050 31051 // if candidates are two closest min and max, stop recursive call 31052 if ((max - min) === 1 || (min === 0 && max === 0)) { 31053 31054 // Get candidates that has same min and max index 31055 candidates = []; 31056 if (values[min].x || values[min].x === 0) { 31057 candidates = candidates.concat($$.findSameXOfValues(values, min)); 31058 } 31059 if (values[max].x || values[max].x === 0) { 31060 candidates = candidates.concat($$.findSameXOfValues(values, max)); 31061 } 31062 31063 // Determine the closest and return 31064 return $$.findClosest(candidates, pos); 31065 } 31066 31067 return $$.findClosestOfValues(values, pos, min, max); 31068 }; 31069 c3_chart_internal_fn.findClosestFromTargets = function (targets, pos) { 31070 var $$ = this, candidates; 31071 31072 // map to array of closest points of each target 31073 candidates = targets.map(function (target) { 31074 return $$.findClosestOfValues(target.values, pos); 31075 }); 31076 31077 // decide closest point and return
31078 return $$.findClosest(candidates, pos); 31079 }; 31080 c3_chart_internal_fn.findClosest = function (values, pos) { 31081 var $$ = this, minDist, closest; 31082 values.forEach(function (v) { 31083 var d = $$.dist(v, pos); 31084 if (d < minDist || ! minDist) { 31085 minDist = d; 31086 closest = v; 31087 } 31088 }); 31089 return closest; 31090 }; 31091 c3_chart_internal_fn.dist = function (data, pos) { 31092 var $$ = this, config = $$.config, 31093 yScale = $$.getAxisId(data.id) === 'y' ? $$.y : $$.y2, 31094 xIndex = config.axis_rotated ? 1 : 0, 31095 yIndex = config.axis_rotated ? 0 : 1; 31096 return Math.pow($$.x(data.x) - pos[xIndex], 2) + Math.pow(yScale(data.value) - pos[yIndex], 2); 31097 }; 31098 31099 c3_chart_internal_fn.convertUrlToData = function (url, mimeType, keys, done) { 31100 var $$ = this, type = mimeType ? mimeType : 'csv'; 31101 $$.d3.xhr(url, function (error, data) { 31102 var d; 31103 if (type === 'json') { 31104 d = $$.convertJsonToData(JSON.parse(data.response), keys); 31105 } else { 31106 d = $$.convertCsvToData(data.response); 31107 } 31108 done.call($$, d); 31109 }); 31110 }; 31111 c3_chart_internal_fn.convertCsvToData = function (csv) { 31112 var d3 = this.d3, rows = d3.csv.parseRows(csv), d; 31113 if (rows.length === 1) { 31114 d = [{}]; 31115 rows[0].forEach(function (id) { 31116 d[0][id] = null; 31117 }); 31118 } else { 31119 d = d3.csv.parse(csv); 31120 } 31121 return d; 31122 }; 31123 c3_chart_internal_fn.convertJsonToData = function (json, keys) { 31124 var $$ = this, 31125 new_rows = [], targetKeys, data; 31126 if (keys) { // when keys specified, json would be an array that includes objects 31127 targetKeys = keys.value; 31128 if (keys.x) { 31129 targetKeys.push(keys.x); 31130 $$.config.data_x = keys.x; 31131 } 31132 new_rows.push(targetKeys); 31133 json.forEach(function (o) { 31134 var new_row = []; 31135 targetKeys.forEach(function (key) { 31136 // convert undefined to null because undefined data will be removed in convertDataToTargets() 31137 var v = isUndefined(o[key]) ? null : o[key]; 31138 new_row.push(v); 31139 }); 31140 new_rows.push(new_row); 31141 }); 31142 data = $$.convertRowsToData(new_rows); 31143 } else { 31144 Object.keys(json).forEach(function (key) { 31145 new_rows.push([key].concat(json[key])); 31146 }); 31147 data = $$.convertColumnsToData(new_rows); 31148 } 31149 return data; 31150 }; 31151 c3_chart_internal_fn.convertRowsToData = function (rows) { 31152 var keys = rows[0], new_row = {}, new_rows = [], i, j; 31153 for (i = 1; i < rows.length; i++) { 31154 new_row = {}; 31155 for (j = 0; j < rows[i].length; j++) { 31156 if (isUndefined(rows[i][j])) { 31157 throw new Error("Source data is missing a component at (" + i + "," + j + ")!"); 31158 } 31159 new_row[keys[j]] = rows[i][j]; 31160 } 31161 new_rows.push(new_row); 31162 } 31163 return new_rows; 31164 }; 31165 c3_chart_internal_fn.convertColumnsToData = function (columns) { 31166 var new_rows = [], i, j, key; 31167 for (i = 0; i < columns.length; i++) { 31168 key = columns[i][0]; 31169 for (j = 1; j < columns[i].length; j++) { 31170 if (isUndefined(new_rows[j - 1])) { 31171 new_rows[j - 1] = {}; 31172 } 31173 if (isUndefined(columns[i][j])) { 31174 throw new Error("Source data is missing a component at (" + i + "," + j + ")!"); 31175 } 31176 new_rows[j - 1][key] = columns[i][j]; 31177 } 31178 } 31179 return new_rows; 31180 }; 31181 c3_chart_internal_fn.convertDataToTargets = function (data, appendXs) { 31182 var $$ = this, config = $$.config, 31183 ids = $$.d3.keys(data[0]).filter($$.isNotX, $$), 31184 xs = $$.d3.keys(data[0]).filter($$.isX, $$), 31185 targets; 31186 31187 // save x for update data by load when custom x and c3.x API 31188 ids.forEach(function (id) { 31189 var xKey = $$.getXKey(id); 31190 31191 if ($$.isCustomX() || $$.isTimeSeries()) { 31192 // if included in input data 31193 if (xs.indexOf(xKey) >= 0) { 31194 $$.data.xs[id] = (appendXs && $$.data.xs[id] ? $$.data.xs[id] : []).c
vendor: 4,344 bytes, lines 31194-31305
31194oncat( 31195 data.map(function (d) { return d[xKey]; }) 31196 .filter(isValue) 31197 .map(function (rawX, i) { return $$.generateTargetX(rawX, id, i); }) 31198 ); 31199 } 31200 // if not included in input data, find from preloaded data of other id's x 31201 else if (config.data_x) { 31202 $$.data.xs[id] = $$.getOtherTargetXs(); 31203 } 31204 // if not included in input data, find from preloaded data 31205 else if (notEmpty(config.data_xs)) { 31206 $$.data.xs[id] = $$.getXValuesOfXKey(xKey, $$.data.targets); 31207 } 31208 // MEMO: if no x included, use same x of current will be used 31209 } else { 31210 $$.data.xs[id] = data.map(function (d, i) { return i; }); 31211 } 31212 }); 31213 31214 31215 // check x is defined 31216 ids.forEach(function (id) { 31217 if (!$$.data.xs[id]) { 31218 throw new Error('x is not defined for id = "' + id + '".'); 31219 } 31220 }); 31221 31222 // convert to target 31223 targets = ids.map(function (id, index) { 31224 var convertedId = config.data_idConverter(id); 31225 return { 31226 id: convertedId, 31227 id_org: id, 31228 values: data.map(function (d, i) { 31229 var xKey = $$.getXKey(id), rawX = d[xKey], x = $$.generateTargetX(rawX, id, i); 31230 // use x as categories if custom x and categorized 31231 if ($$.isCustomX() && $$.isCategorized() && index === 0 && rawX) { 31232 if (i === 0) { config.axis_x_categories = []; } 31233 config.axis_x_categories.push(rawX); 31234 } 31235 // mark as x = undefined if value is undefined and filter to remove after mapped 31236 if (isUndefined(d[id]) || $$.data.xs[id].length <= i) { 31237 x = undefined; 31238 } 31239 return {x: x, value: d[id] !== null && !isNaN(d[id]) ? +d[id] : null, id: convertedId}; 31240 }).filter(function (v) { return isDefined(v.x); }) 31241 }; 31242 }); 31243 31244 // finish targets 31245 targets.forEach(function (t) { 31246 var i; 31247 // sort values by its x 31248 t.values = t.values.sort(function (v1, v2) { 31249 var x1 = v1.x || v1.x === 0 ? v1.x : Infinity, 31250 x2 = v2.x || v2.x === 0 ? v2.x : Infinity; 31251 return x1 - x2; 31252 }); 31253 // indexing each value 31254 i = 0; 31255 t.values.forEach(function (v) { 31256 v.index = i++; 31257 }); 31258 // this needs to be sorted because its index and value.index is identical 31259 $$.data.xs[t.id].sort(function (v1, v2) { 31260 return v1 - v2; 31261 }); 31262 }); 31263 31264 // set target types 31265 if (config.data_type) { 31266 $$.setTargetType($$.mapToIds(targets).filter(function (id) { return ! (id in config.data_types); }), config.data_type); 31267 } 31268 31269 // cache as original id keyed 31270 targets.forEach(function (d) { 31271 $$.addCache(d.id_org, d); 31272 }); 31273 31274 return targets; 31275 }; 31276 31277 c3_chart_internal_fn.load = function (targets, args) { 31278 var $$ = this; 31279 if (targets) { 31280 // filter loading targets if needed 31281 if (args.filter) { 31282 targets = targets.filter(args.filter); 31283 } 31284 // set type if args.types || args.type specified 31285 if (args.type || args.types) { 31286 targets.forEach(function (t) { 31287 $$.setTargetType(t.id, args.types ? args.types[t.id] : args.type); 31288 }); 31289 } 31290 // Update/Add data 31291 $$.data.targets.forEach(function (d) { 31292 for (var i = 0; i < targets.length; i++) { 31293 if (d.id === targets[i].id) { 31294 d.values = targets[i].values; 31295 targets.splice(i, 1); 31296 break; 31297 } 31298 } 31299 }); 31300 $$.data.targets = $$.data.targets.concat(targets); // add remained 31301 } 31302 31303 // Set targets 31304 $$.updateTargets($$.data.targets); 31305
31306 // Redraw with new targets 31307 $$.redraw({withUpdateOrgXDomain: true, withUpdateXDomain: true, withLegend: true}); 31308 31309 if (args.done) { args.done(); } 31310 }; 31311 c3_chart_internal_fn.loadFromArgs = function (args) { 31312 var $$ = this; 31313 if (args.data) { 31314 $$.load($$.convertDataToTargets(args.data), args); 31315 } 31316 else if (args.url) { 31317 $$.convertUrlToData(args.url, args.mimeType, args.keys, function (data) { 31318 $$.load($$.convertDataToTargets(data), args); 31319 }); 31320 } 31321 else if (args.json) { 31322 $$.load($$.convertDataToTargets($$.convertJsonToData(args.json, args.keys)), args); 31323 } 31324 else if (args.rows) { 31325 $$.load($$.convertDataToTargets($$.convertRowsToData(args.rows)), args); 31326 } 31327 else if (args.columns) { 31328 $$.load($$.convertDataToTargets($$.convertColumnsToData(args.columns)), args); 31329 } 31330 else { 31331 $$.load(null, args); 31332 } 31333 }; 31334 c3_chart_internal_fn.unload = function (targetIds, done) { 31335 var $$ = this; 31336 if (!done) { 31337 done = function () {}; 31338 } 31339 // filter existing target 31340 targetIds = targetIds.filter(function (id) { return $$.hasTarget($$.data.targets, id); }); 31341 // If no target, call done and return 31342 if (!targetIds || targetIds.length === 0) { 31343 done(); 31344 return; 31345 } 31346 $$.svg.selectAll(targetIds.map(function (id) { return $$.selectorTarget(id); })) 31347 .transition() 31348 .style('opacity', 0) 31349 .remove() 31350 .call($$.endall, done); 31351 targetIds.forEach(function (id) { 31352 // Reset fadein for future load 31353 $$.withoutFadeIn[id] = false; 31354 // Remove target's elements 31355 if ($$.legend) { 31356 $$.legend.selectAll('.' + CLASS.legendItem + $$.getTargetSelectorSuffix(id)).remove(); 31357 } 31358 // Remove target 31359 $$.data.targets = $$.data.targets.filter(function (t) { 31360 return t.id !== id; 31361 }); 31362 }); 31363 }; 31364 31365 c3_chart_internal_fn.categoryName = function (i) { 31366 var config = this.config; 31367 return i < config.axis_x_categories.length ? config.axis_x_categories[i] : i; 31368 }; 31369 31370 c3_chart_internal_fn.initEventRect = function () { 31371 var $$ = this; 31372 $$.main.select('.' + CLASS.chart).append("g") 31373 .attr("class", CLASS.eventRects) 31374 .style('fill-opacity', 0); 31375 }; 31376 c3_chart_internal_fn.redrawEventRect = function () { 31377 var $$ = this, config = $$.config, 31378 eventRectUpdate, maxDataCountTarget, 31379 isMultipleX = $$.isMultipleX(); 31380 31381 // rects for mouseover 31382 var eventRects = $$.main.select('.' + CLASS.eventRects) 31383 .style('cursor', config.zoom_enabled ? config.axis_rotated ? 'ns-resize' : 'ew-resize' : null) 31384 .classed(CLASS.eventRectsMultiple, isMultipleX) 31385 .classed(CLASS.eventRectsSingle, !isMultipleX); 31386 31387 // clear old rects 31388 eventRects.selectAll('.' + CLASS.eventRect).remove(); 31389 31390 // open as public variable 31391 $$.eventRect = eventRects.selectAll('.' + CLASS.eventRect); 31392 31393 if (isMultipleX) { 31394 eventRectUpdate = $$.eventRect.data([0]); 31395 // enter : only one rect will be added 31396 $$.generateEventRectsForMultipleXs(eventRectUpdate.enter()); 31397 // update 31398 $$.updateEventRect(eventRectUpdate); 31399 // exit : not needed because always only one rect exists 31400 } 31401 else { 31402 // Set data and update $$.eventRect 31403 maxDataCountTarget = $$.getMaxDataCountTarget($$.data.targets); 31404 eventRects.datum(maxDataCountTarget ? maxDataCountTarget.values : []); 31405 $$.eventRect = eventRects.selectAll('.' + CLASS.eventRect); 31406 eventRectUpdate = $$.eventRect.data(function (d) { return d; }); 31407 // enter 31408 $$.generateEventRectsForSingleX(eventRectUpdate.enter()); 31409 // update 31410 $$.updateEventRect(eventRectUpdate); 31411 // exit 31412 eventRectUpdate.exit().remove(); 31413 } 31414 }; 31415 c3_chart_internal_fn.updateEventRect = function (eventRectUpdate) {
31416 var $$ = this, config = $$.config, 31417 x, y, w, h, rectW, rectX; 31418 31419 // set update selection if null 31420 eventRectUpdate = eventRectUpdate || $$.eventRect.data(function (d) { return d; }); 31421 31422 if ($$.isMultipleX()) { 31423 // TODO: rotated not supported yet 31424 x = 0; 31425 y = 0; 31426 w = $$.width; 31427 h = $$.height; 31428 } 31429 else { 31430 if (($$.isCustomX() || $$.isTimeSeries()) && !$$.isCategorized()) { 31431 rectW = function (d) { 31432 var prevX = $$.getPrevX(d.index), nextX = $$.getNextX(d.index), dx = $$.data.xs[d.id][d.index], 31433 w = ($$.x(nextX ? nextX : dx) - $$.x(prevX ? prevX : dx)) / 2; 31434 return w < 0 ? 0 : w; 31435 }; 31436 rectX = function (d) { 31437 var prevX = $$.getPrevX(d.index), dx = $$.data.xs[d.id][d.index]; 31438 return ($$.x(dx) + $$.x(prevX ? prevX : dx)) / 2; 31439 }; 31440 } else { 31441 rectW = $$.getEventRectWidth(); 31442 rectX = function (d) { 31443 return $$.x(d.x) - (rectW / 2); 31444 }; 31445 } 31446 x = config.axis_rotated ? 0 : rectX; 31447 y = config.axis_rotated ? rectX : 0; 31448 w = config.axis_rotated ? $$.width : rectW; 31449 h = config.axis_rotated ? rectW : $$.height; 31450 } 31451 31452 eventRectUpdate 31453 .attr('class', $$.classEvent.bind($$)) 31454 .attr("x", x) 31455 .attr("y", y) 31456 .attr("width", w) 31457 .attr("height", h); 31458 }; 31459 c3_chart_internal_fn.generateEventRectsForSingleX = function (eventRectEnter) { 31460 var $$ = this, d3 = $$.d3, config = $$.config; 31461 eventRectEnter.append("rect") 31462 .attr("class", $$.classEvent.bind($$)) 31463 .style("cursor", config.data_selection_enabled && config.data_selection_grouped ? "pointer" : null) 31464 .on('mouseover', function (d) { 31465 var index = d.index, selectedData, newData; 31466 31467 if ($$.dragging) { return; } // do nothing if dragging 31468 if ($$.hasArcType()) { return; } 31469 31470 selectedData = $$.data.targets.map(function (t) { 31471 return $$.addName($$.getValueOnIndex(t.values, index)); 31472 }); 31473 31474 // Sort selectedData as names order 31475 newData = []; 31476 Object.keys(config.data_names).forEach(function (id) { 31477 for (var j = 0; j < selectedData.length; j++) { 31478 if (selectedData[j] && selectedData[j].id === id) { 31479 newData.push(selectedData[j]); 31480 selectedData.shift(j); 31481 break; 31482 } 31483 } 31484 }); 31485 selectedData = newData.concat(selectedData); // Add remained 31486 31487 // Expand shapes for selection 31488 if (config.point_focus_expand_enabled) { $$.expandCircles(index); } 31489 $$.expandBars(index); 31490 31491 // Call event handler 31492 $$.main.selectAll('.' + CLASS.shape + '-' + index).each(function (d) { 31493 config.data_onmouseover.call($$, d); 31494 }); 31495 }) 31496 .on('mouseout', function (d) { 31497 var index = d.index; 31498 if ($$.hasArcType()) { return; } 31499 $$.hideXGridFocus(); 31500 $$.hideTooltip(); 31501 // Undo expanded shapes 31502 $$.unexpandCircles(index); 31503 $$.unexpandBars(); 31504 // Call event handler 31505 $$.main.selectAll('.' + CLASS.shape + '-' + index).each(function (d) { 31506 config.data_onmouseout.call($$, d); 31507 }); 31508 }) 31509 .on('mousemove', function (d) { 31510 var selectedData, index = d.index, 31511 eventRect = $$.svg.select('.' + CLASS.eventRect + '-' + index); 31512 31513 if ($$.dragging) { return; } // do nothing when dragging 31514 if ($$.hasArcType()) { return; } 31515 31516 // Show tooltip
31517 selectedData = $$.filterTargetsToShow($$.data.targets).map(function (t) { 31518 return $$.addName($$.getValueOnIndex(t.values, index)); 31519 }); 31520 31521 if (config.tooltip_grouped) { 31522 $$.showTooltip(selectedData, d3.mouse(this)); 31523 $$.showXGridFocus(selectedData); 31524 } 31525 31526 if (config.tooltip_grouped && (!config.data_selection_enabled || config.data_selection_grouped)) { 31527 return; 31528 } 31529 31530 $$.main.selectAll('.' + CLASS.shape + '-' + index) 31531 .each(function () { 31532 d3.select(this).classed(CLASS.EXPANDED, true); 31533 if (config.data_selection_enabled) { 31534 eventRect.style('cursor', config.data_selection_grouped ? 'pointer' : null); 31535 } 31536 if (!config.tooltip_grouped) { 31537 $$.hideXGridFocus(); 31538 $$.hideTooltip(); 31539 if (!config.data_selection_grouped) { 31540 $$.unexpandCircles(index); 31541 $$.unexpandBars(); 31542 } 31543 } 31544 }) 31545 .filter(function (d) { 31546 if (this.nodeName === 'circle') { 31547 return $$.isWithinCircle(this, $$.pointSelectR(d)); 31548 } 31549 else if (this.nodeName === 'path') { 31550 return $$.isWithinBar(this); 31551 } 31552 }) 31553 .each(function (d) { 31554 if (config.data_selection_enabled && (config.data_selection_grouped || config.data_selection_isselectable(d))) { 31555 eventRect.style('cursor', 'pointer'); 31556 } 31557 if (!config.tooltip_grouped) { 31558 $$.showTooltip([d], d3.mouse(this)); 31559 $$.showXGridFocus([d]); 31560 if (config.point_focus_expand_enabled) { $$.expandCircles(index, d.id); } 31561 $$.expandBars(index, d.id); 31562 } 31563 }); 31564 }) 31565 .on('click', function (d) { 31566 var index = d.index; 31567 if ($$.hasArcType() || !$$.toggleShape) { return; } 31568 if ($$.cancelClick) { 31569 $$.cancelClick = false; 31570 return; 31571 } 31572 $$.main.selectAll('.' + CLASS.shape + '-' + index).each(function (d) { 31573 $$.toggleShape(this, d, index); 31574 }); 31575 }) 31576 .call( 31577 d3.behavior.drag().origin(Object) 31578 .on('drag', function () { $$.drag(d3.mouse(this)); }) 31579 .on('dragstart', function () { $$.dragstart(d3.mouse(this)); }) 31580 .on('dragend', function () { $$.dragend(); }) 31581 ) 31582 .on("dblclick.zoom", null); 31583 }; 31584 31585 c3_chart_internal_fn.generateEventRectsForMultipleXs = function (eventRectEnter) { 31586 var $$ = this, d3 = $$.d3, config = $$.config; 31587 eventRectEnter.append('rect') 31588 .attr('x', 0) 31589 .attr('y', 0) 31590 .attr('width', $$.width) 31591 .attr('height', $$.height) 31592 .attr('class', CLASS.eventRect) 31593 .on('mouseout', function () { 31594 if ($$.hasArcType()) { return; } 31595 $$.hideXGridFocus(); 31596 $$.hideTooltip(); 31597 $$.unexpandCircles(); 31598 }) 31599 .on('mousemove', function () { 31600 var targetsToShow = $$.filterTargetsToShow($$.data.targets); 31601 var mouse, closest, sameXData, selectedData; 31602 31603 if ($$.dragging) { return; } // do nothing when dragging 31604 if ($$.hasArcType(targetsToShow)) { return; } 31605 31606 mouse = d3.mouse(this); 31607 closest = $$.findClosestFromTargets(targetsToShow, mouse); 31608 31609 if (! closest) { return; } 31610 31611 if ($$.isScatterType(closest)) { 31612 sameXData = [closest]; 31613 } else {
31614 sameXData = $$.filterSameX(targetsToShow, closest.x); 31615 } 31616 31617 // show tooltip when cursor is close to some point 31618 selectedData = sameXData.map(function (d) { 31619 return $$.addName(d); 31620 }); 31621 $$.showTooltip(selectedData, mouse); 31622 31623 // expand points 31624 if (config.point_focus_expand_enabled) { 31625 $$.unexpandCircles(); 31626 $$.expandCircles(closest.index, closest.id); 31627 } 31628 31629 // Show xgrid focus line 31630 $$.showXGridFocus(selectedData); 31631 31632 // Show cursor as pointer if point is close to mouse position 31633 if ($$.dist(closest, mouse) < 100) { 31634 $$.svg.select('.' + CLASS.eventRect).style('cursor', 'pointer'); 31635 if (!$$.mouseover) { 31636 config.data_onmouseover.call($$, closest); 31637 $$.mouseover = true; 31638 } 31639 } else if ($$.mouseover) { 31640 $$.svg.select('.' + CLASS.eventRect).style('cursor', null); 31641 config.data_onmouseout.call($$, closest); 31642 $$.mouseover = false; 31643 } 31644 }) 31645 .on('click', function () { 31646 var targetsToShow = $$.filterTargetsToShow($$.data.targets); 31647 var mouse, closest; 31648 31649 if ($$.hasArcType(targetsToShow)) { return; } 31650 31651 mouse = d3.mouse(this); 31652 closest = $$.findClosestFromTargets(targetsToShow, mouse); 31653 31654 if (! closest) { return; } 31655 31656 // select if selection enabled 31657 if ($$.dist(closest, mouse) < 100 && $$.toggleShape) { 31658 $$.main.select('.' + CLASS.circles + $$.getTargetSelectorSuffix(closest.id)).select('.' + CLASS.circle + '-' + closest.index).each(function () { 31659 $$.toggleShape(this, closest, closest.index); 31660 }); 31661 } 31662 }) 31663 .call( 31664 d3.behavior.drag().origin(Object) 31665 .on('drag', function () { $$.drag(d3.mouse(this)); }) 31666 .on('dragstart', function () { $$.dragstart(d3.mouse(this)); }) 31667 .on('dragend', function () { $$.dragend(); }) 31668 ) 31669 .on("dblclick.zoom", null); 31670 }; 31671 31672 c3_chart_internal_fn.getCurrentWidth = function () { 31673 var $$ = this, config = $$.config; 31674 return config.size_width ? config.size_width : $$.getParentWidth(); 31675 }; 31676 c3_chart_internal_fn.getCurrentHeight = function () { 31677 var $$ = this, config = $$.config, 31678 h = config.size_height ? config.size_height : $$.getParentHeight(); 31679 return h > 0 ? h : 320; 31680 }; 31681 c3_chart_internal_fn.getCurrentPaddingTop = function () { 31682 var config = this.config; 31683 return isValue(config.padding_top) ? config.padding_top : 0; 31684 }; 31685 c3_chart_internal_fn.getCurrentPaddingBottom = function () { 31686 var config = this.config; 31687 return isValue(config.padding_bottom) ? config.padding_bottom : 0; 31688 }; 31689 c3_chart_internal_fn.getCurrentPaddingLeft = function () { 31690 var $$ = this, config = $$.config; 31691 if (isValue(config.padding_left)) { 31692 return config.padding_left; 31693 } else if (config.axis_rotated) { 31694 return !config.axis_x_show ? 1 : Math.max(ceil10($$.getAxisWidthByAxisId('x')), 40); 31695 } else { 31696 return !config.axis_y_show ? 1 : ceil10($$.getAxisWidthByAxisId('y')); 31697 } 31698 }; 31699 c3_chart_internal_fn.getCurrentPaddingRight = function () { 31700 var $$ = this, config = $$.config, 31701 defaultPadding = 10, legendWidthOnRight = $$.isLegendRight ? $$.getLegendWidth() + 20 : 0; 31702 if (isValue(config.padding_right)) { 31703 return config.padding_right + 1; // 1 is needed not to hide tick line 31704 } else if (config.axis_rotated) { 31705 return defaultPadding + legendWidthOnRight; 31706 } else { 31707 return (!config.axis_y2_show ? defaultPadding : ceil10($$.getAxisWidthByAxisId('y2'))) + legendWidthOnRight; 31708 } 31709 }; 31710 31711 c3_chart_internal_fn.getParentRectValue = function (key) { 31712 var parent = this.selectChart.node(), v; 31713 while (parent && parent.tagName !== 'BODY') { 31714 v = parent.getBoundingClientRect()[key]; 31715 if (v) { 31716 break; 31717 } 31718 parent = parent.parentNode; 31719 } 31720 return v; 31721 }; 31722 c3_chart_internal_fn.getParentWidth = function () { 31723 return this.getParentRectValue('width'); 31724 }; 31725 c3_chart_internal_fn.getParentHeight = function () { 31726 var h = this.selectChart.style('height'); 31727 return h.indexOf('px') >
31727 0 ? +h.replace('px', '') : 0; 31728 }; 31729 31730 31731 c3_chart_internal_fn.getSvgLeft = function () { 31732 var $$ = this, config = $$.config, 31733 leftAxisClass = config.axis_rotated ? CLASS.axisX : CLASS.axisY, 31734 leftAxis = $$.main.select('.' + leftAxisClass).node(), 31735 svgRect = leftAxis ? leftAxis.getBoundingClientRect() : {right: 0}, 31736 chartRect = $$.selectChart.node().getBoundingClientRect(), 31737 hasArc = $$.hasArcType(), 31738 svgLeft = svgRect.right - chartRect.left - (hasArc ? 0 : $$.getCurrentPaddingLeft()); 31739 return svgLeft > 0 ? svgLeft : 0; 31740 }; 31741 31742 31743 c3_chart_internal_fn.getAxisWidthByAxisId = function (id) { 31744 var $$ = this, position = $$.getAxisLabelPositionById(id); 31745 return position.isInner ? 20 + $$.getMaxTickWidth(id) : 40 + $$.getMaxTickWidth(id); 31746 }; 31747 c3_chart_internal_fn.getHorizontalAxisHeight = function (axisId) { 31748 var $$ = this, config = $$.config; 31749 if (axisId === 'x' && !config.axis_x_show) { return 0; } 31750 if (axisId === 'x' && config.axis_x_height) { return config.axis_x_height; } 31751 if (axisId === 'y' && !config.axis_y_show) { return config.legend_show && !$$.isLegendRight && !$$.isLegendInset ? 10 : 1; } 31752 if (axisId === 'y2' && !config.axis_y2_show) { return $$.rotated_padding_top; } 31753 return ($$.getAxisLabelPositionById(axisId).isInner ? 30 : 40) + (axisId === 'y2' ? -10 : 0); 31754 }; 31755 31756 c3_chart_internal_fn.getEventRectWidth = function () { 31757 var $$ = this; 31758 var target = $$.getMaxDataCountTarget($$.data.targets), 31759 firstData, lastData, base, maxDataCount, ratio, w; 31760 if (!target) { 31761 return 0; 31762 } 31763 firstData = target.values[0], lastData = target.values[target.values.length - 1]; 31764 base = $$.x(lastData.x) - $$.x(firstData.x); 31765 if (base === 0) { 31766 return $$.config.axis_rotated ? $$.height : $$.width; 31767 } 31768 maxDataCount = $$.getMaxDataCount(); 31769 ratio = ($$.hasType('bar') ? (maxDataCount - ($$.isCategorized() ? 0.25 : 1)) / maxDataCount : 1); 31770 w = maxDataCount > 1 ? (base * ratio) / (maxDataCount - 1) : base; 31771 return w < 1 ? 1 : w; 31772 }; 31773 31774 c3_chart_internal_fn.getShapeIndices = function (typeFilter) { 31775 var $$ = this, config = $$.config, 31776 indices = {}, i = 0, j, k; 31777 $$.filterTargetsToShow($$.data.targets.filter(typeFilter, $$)).forEach(function (d) { 31778 for (j = 0; j < config.data_groups.length; j++) { 31779 if (config.data_groups[j].indexOf(d.id) < 0) { continue; } 31780 for (k = 0; k < config.data_groups[j].length; k++) { 31781 if (config.data_groups[j][k] in indices) { 31782 indices[d.id] = indices[config.data_groups[j][k]]; 31783 break; 31784 } 31785 } 31786 } 31787 if (isUndefined(indices[d.id])) { indices[d.id] = i++; } 31788 }); 31789 indices.__max__ = i - 1; 31790 return indices; 31791 }; 31792 c3_chart_internal_fn.getShapeX = function (offset, targetsNum, indices, isSub) { 31793 var $$ = this, scale = isSub ? $$.subX : $$.x; 31794 return function (d) { 31795 var index = d.id in indices ? indices[d.id] : 0; 31796 return d.x || d.x === 0 ? scale(d.x) - offset * (targetsNum / 2 - index) : 0; 31797 }; 31798 }; 31799 c3_chart_internal_fn.getShapeY = function (isSub) { 31800 var $$ = this; 31801 return function (d) { 31802 var scale = isSub ? $$.getSubYScale(d.id) : $$.getYScale(d.id); 31803 return scale(d.value); 31804 }; 31805 }; 31806 c3_chart_internal_fn.getShapeOffset = function (typeFilter, indices, isSub) { 31807 var $$ = this, 31808 targets = $$.orderTargets($$.filterTargetsToShow($$.data.targets.filter(typeFilter, $$))), 31809 targetIds = targets.map(function (t) { return t.id; }); 31810 return function (d, i) { 31811 var scale = isSub ? $$.getSubYScale(d.id) : $$.getYScale(d.id), 31812 y0 = scale(0), offset = y0; 31813 targets.forEach(function (t) { 31814 if (t.id === d.id || indices[t.id] !== indices[d.id]) { return; } 31815 if (targetIds.indexOf(t.id) < targetIds.indexOf(d.id) && t.values[i].value * d.value >= 0) { 31816 offset += scale(t.values[i].value) - y0; 31817 } 31818 }); 31819 return offset; 31820 }; 31821 }; 31822 31823 c3_chart_internal_fn.getInterpolate = function (d) { 31824 var $$ = this; 31825 return $$.isSplineType(d) ? "cardinal" : $$.isStepType(d) ? "step-after" : "linear"; 31826 }; 31827 31828 c3_chart_internal_fn.initLine = function () { 31829 var $$ = this; 31830 $$.main.select('.' + CLASS.chart).append("g") 31831 .attr("class", CLASS.chartLines); 31832 }; 31833 c3_chart_internal_fn.updateTargetsForLine = function (targets) {
vendor: 14,068 bytes, lines 31834-32150
31834 var $$ = this, config = $$.config, 31835 mainLineUpdate, mainLineEnter, 31836 classChartLine = $$.classChartLine.bind($$), 31837 classLines = $$.classLines.bind($$), 31838 classAreas = $$.classAreas.bind($$), 31839 classCircles = $$.classCircles.bind($$); 31840 mainLineUpdate = $$.main.select('.' + CLASS.chartLines).selectAll('.' + CLASS.chartLine) 31841 .data(targets) 31842 .attr('class', classChartLine); 31843 mainLineEnter = mainLineUpdate.enter().append('g') 31844 .attr('class', classChartLine) 31845 .style('opacity', 0) 31846 .style("pointer-events", "none"); 31847 // Lines for each data 31848 mainLineEnter.append('g') 31849 .attr("class", classLines); 31850 // Areas 31851 mainLineEnter.append('g') 31852 .attr('class', classAreas); 31853 // Circles for each data point on lines 31854 mainLineEnter.append('g') 31855 .attr("class", function (d) { return $$.generateClass(CLASS.selectedCircles, d.id); }); 31856 mainLineEnter.append('g') 31857 .attr("class", classCircles) 31858 .style("cursor", function (d) { return config.data_selection_isselectable(d) ? "pointer" : null; }); 31859 // Update date for selected circles 31860 targets.forEach(function (t) { 31861 $$.main.selectAll('.' + CLASS.selectedCircles + $$.getTargetSelectorSuffix(t.id)).selectAll('.' + CLASS.selectedCircle).each(function (d) { 31862 d.value = t.values[d.index].value; 31863 }); 31864 }); 31865 // MEMO: can not keep same color... 31866 //mainLineUpdate.exit().remove(); 31867 }; 31868 c3_chart_internal_fn.redrawLine = function (durationForExit) { 31869 var $$ = this; 31870 $$.mainLine = $$.main.selectAll('.' + CLASS.lines).selectAll('.' + CLASS.line) 31871 .data($$.lineData.bind($$)); 31872 $$.mainLine.enter().append('path') 31873 .attr('class', $$.classLine.bind($$)) 31874 .style("stroke", $$.color); 31875 $$.mainLine 31876 .style("opacity", $$.initialOpacity.bind($$)) 31877 .attr('transform', null); 31878 $$.mainLine.exit().transition().duration(durationForExit) 31879 .style('opacity', 0) 31880 .remove(); 31881 }; 31882 c3_chart_internal_fn.addTransitionForLine = function (transitions, drawLine) { 31883 var $$ = this; 31884 transitions.push($$.mainLine.transition() 31885 .attr("d", drawLine) 31886 .style("stroke", $$.color) 31887 .style("opacity", 1)); 31888 }; 31889 c3_chart_internal_fn.generateDrawLine = function (lineIndices, isSub) { 31890 var $$ = this, config = $$.config, 31891 line = $$.d3.svg.line(), 31892 getPoint = $$.generateGetLinePoint(lineIndices, isSub), 31893 yScaleGetter = isSub ? $$.getSubYScale : $$.getYScale, 31894 xValue = function (d) { return (isSub ? $$.subxx : $$.xx).call($$, d); }, 31895 yValue = function (d, i) { 31896 return config.data_groups.length > 0 ? getPoint(d, i)[0][1] : yScaleGetter.call($$, d.id)(d.value); 31897 }; 31898 31899 line = config.axis_rotated ? line.x(yValue).y(xValue) : line.x(xValue).y(yValue); 31900 if (!config.line_connect_null) { line = line.defined(function (d) { return d.value != null; }); } 31901 return function (d) { 31902 var data = config.line_connect_null ? $$.filterRemoveNull(d.values) : d.values, 31903 x = isSub ? $$.x : $$.subX, y = yScaleGetter.call($$, d.id), x0 = 0, y0 = 0, path; 31904 if ($$.isLineType(d)) { 31905 if (config.data_regions[d.id]) { 31906 path = $$.lineWithRegions(data, x, y, config.data_regions[d.id]); 31907 } else { 31908 path = line.interpolate($$.getInterpolate(d))(data); 31909 } 31910 } else { 31911 if (data[0]) { 31912 x0 = x(data[0].x); 31913 y0 = y(data[0].value); 31914 } 31915 path = config.axis_rotated ? "M " + y0 + " " + x0 : "M " + x0 + " " + y0; 31916 } 31917 return path ? path : "M 0 0"; 31918 }; 31919 }; 31920 c3_chart_internal_fn.generateGetLinePoint = function (lineIndices, isSub) { // partial duplication of generateGetBarPoints 31921 var $$ = this, config = $$.config, 31922 lineTargetsNum = lineIndices.__max__ + 1, 31923 x = $$.getShapeX(0, lineTargetsNum, lineIndices, !!isSub), 31924 y = $$.getShapeY(!!isSub), 31925 lineOffset = $$.getShapeOffset($$.isLineType, lineIndices, !!isSub), 31926 yScale = isSub ? $$.getSubYScale : $$.getYScale; 31927 return function (d, i) { 31928 var y0 = yScale.call($$, d.id)(0), 31929 offset = lineOffset(d, i) || y0, // offset is for stacked area chart 31930 posX = x(d), posY = y(d); 31931 // fix posY not to overflow opposite quadrant 31932 if (config.axis_rotated) { 31933 if ((0 < d.value && posY < y0) || (d.value < 0 && y0 < posY)) { posY = y0; } 31934 } 31935 // 1 point that marks the line position 31936 return [ 31937 [posX, posY - (y0 - offset)] 31938 ]; 31939 }; 31940 }; 31941 31942 31943 c3_chart_internal_fn.lineWithRegions = function (d, x, y, _regions) { 31944 var $$ = this, config = $$.config, 31945 prev = -1, i, j, 31946 s = "M", sWithRegion, 31947 xp, yp, dx, dy, dd, diff, diffx2, 31948 xValue, yValue, 31949 regions = []; 31950 31951 function isWithinRegions(x, regions) { 31952 var i; 31953 for (i = 0; i < regions.length; i++) { 31954 if (regions[i].start < x && x <= regions[i].end) { return true; } 31955 } 31956 return false; 31957 } 31958 31959 // Check start/end of regions 31960 if (isDefined(_regions)) { 31961 for (i = 0; i < _regions.length; i++) { 31962 regions[i] = {}; 31963 if (isUndefined(_regions[i].start)) { 31964 regions[i].start = d[0].x; 31965 } else { 31966 regions[i].start = $$.isTimeSeries() ? $$.parseDate(_regions[i].start) : _regions[i].start; 31967 } 31968 if (isUndefined(_regions[i].end)) { 31969 regions[i].end = d[d.length - 1].x; 31970 } else { 31971 regions[i].end = $$.isTimeSeries() ? $$.parseDate(_regions[i].end) : _regions[i].end; 31972 } 31973 } 31974 } 31975 31976 // Set scales 31977 xValue = config.axis_rotated ? function (d) { return y(d.value); } : function (d) { return x(d.x); }; 31978 yValue = config.axis_rotated ? function (d) { return x(d.x); } : function (d) { return y(d.value); }; 31979 31980 // Define svg generator function for region 31981 if ($$.isTimeSeries()) { 31982 sWithRegion = function (d0, d1, j, diff) { 31983 var x0 = d0.x.getTime(), x_diff = d1.x - d0.x, 31984 xv0 = new Date(x0 + x_diff * j), 31985 xv1 = new Date(x0 + x_diff * (j + diff)); 31986 return "M" + x(xv0) + " " + y(yp(j)) + " " + x(xv1) + " " + y(yp(j + diff)); 31987 }; 31988 } else { 31989 sWithRegion = function (d0, d1, j, diff) { 31990 return "M" + x(xp(j), true) + " " + y(yp(j)) + " " + x(xp(j + diff), true) + " " + y(yp(j + diff)); 31991 }; 31992 } 31993 31994 // Generate 31995 for (i = 0; i < d.length; i++) { 31996 31997 // Draw as normal 31998 if (isUndefined(regions) || ! isWithinRegions(d[i].x, regions)) { 31999 s += " " + xValue(d[i]) + " " + yValue(d[i]); 32000 } 32001 // Draw with region // TODO: Fix for horizotal charts 32002 else { 32003 xp = $$.getScale(d[i - 1].x, d[i].x, $$.isTimeSeries()); 32004 yp = $$.getScale(d[i - 1].value, d[i].value); 32005 32006 dx = x(d[i].x) - x(d[i - 1].x); 32007 dy = y(d[i].value) - y(d[i - 1].value); 32008 dd = Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2)); 32009 diff = 2 / dd; 32010 diffx2 = diff * 2; 32011 32012 for (j = diff; j <= 1; j += diffx2) { 32013 s += sWithRegion(d[i - 1], d[i], j, diff); 32014 } 32015 } 32016 prev = d[i].x; 32017 } 32018 32019 return s; 32020 }; 32021 32022 32023 c3_chart_internal_fn.redrawArea = function (durationForExit) { 32024 var $$ = this, d3 = $$.d3; 32025 $$.mainArea = $$.main.selectAll('.' + CLASS.areas).selectAll('.' + CLASS.area) 32026 .data($$.lineData.bind($$)); 32027 $$.mainArea.enter().append('path') 32028 .attr("class", $$.classArea.bind($$)) 32029 .style("fill", $$.color) 32030 .style("opacity", function () { $$.orgAreaOpacity = +d3.select(this).style('opacity'); return 0; }); 32031 $$.mainArea 32032 .style("opacity", $$.orgAreaOpacity); 32033 $$.mainArea.exit().transition().duration(durationForExit) 32034 .style('opacity', 0) 32035 .remove(); 32036 }; 32037 c3_chart_internal_fn.addTransitionForArea = function (transitions, drawArea) { 32038 var $$ = this; 32039 transitions.push($$.mainArea.transition() 32040 .attr("d", drawArea) 32041 .style("fill", $$.color) 32042 .style("opacity", $$.orgAreaOpacity)); 32043 }; 32044 c3_chart_internal_fn.generateDrawArea = function (areaIndices, isSub) { 32045 var $$ = this, config = $$.config, area = $$.d3.svg.area(), 32046 getPoint = $$.generateGetAreaPoint(areaIndices, isSub), 32047 yScaleGetter = isSub ? $$.getSubYScale : $$.getYScale, 32048 xValue = function (d) { return (isSub ? $$.subxx : $$.xx).call($$, d); }, 32049 value0 = function (d, i) { 32050 return config.data_groups.length > 0 ? getPoint(d, i)[0][1] : yScaleGetter.call($$, d.id)(0); 32051 }, 32052 value1 = function (d, i) { 32053 return config.data_groups.length > 0 ? getPoint(d, i)[1][1] : yScaleGetter.call($$, d.id)(d.value); 32054 }; 32055 32056 area = config.axis_rotated ? area.x0(value0).x1(value1).y(xValue) : area.x(xValue).y0(value0).y1(value1); 32057 if (!config.line_connect_null) { 32058 area = area.defined(function (d) { return d.value !== null; }); 32059 } 32060 32061 return function (d) { 32062 var data = config.line_connect_null ? $$.filterRemoveNull(d.values) : d.values, x0 = 0, y0 = 0, path; 32063 if ($$.isAreaType(d)) { 32064 path = area.interpolate($$.getInterpolate(d))(data); 32065 } else { 32066 if (data[0]) { 32067 x0 = $$.x(data[0].x); 32068 y0 = $$.getYScale(d.id)(data[0].value); 32069 } 32070 path = config.axis_rotated ? "M " + y0 + " " + x0 : "M " + x0 + " " + y0; 32071 } 32072 return path ? path : "M 0 0"; 32073 }; 32074 }; 32075 32076 c3_chart_internal_fn.generateGetAreaPoint = function (areaIndices, isSub) { // partial duplication of generateGetBarPoints 32077 var $$ = this, config = $$.config, 32078 areaTargetsNum = areaIndices.__max__ + 1, 32079 x = $$.getShapeX(0, areaTargetsNum, areaIndices, !!isSub), 32080 y = $$.getShapeY(!!isSub), 32081 areaOffset = $$.getShapeOffset($$.isAreaType, areaIndices, !!isSub), 32082 yScale = isSub ? $$.getSubYScale : $$.getYScale; 32083 return function (d, i) { 32084 var y0 = yScale.call($$, d.id)(0), 32085 offset = areaOffset(d, i) || y0, // offset is for stacked area chart 32086 posX = x(d), posY = y(d); 32087 // fix posY not to overflow opposite quadrant 32088 if (config.axis_rotated) { 32089 if ((0 < d.value && posY < y0) || (d.value < 0 && y0 < posY)) { posY = y0; } 32090 } 32091 // 1 point that marks the area position 32092 return [ 32093 [posX, offset], 32094 [posX, posY - (y0 - offset)] 32095 ]; 32096 }; 32097 }; 32098 32099 32100 c3_chart_internal_fn.redrawCircle = function () { 32101 var $$ = this; 32102 $$.mainCircle = $$.main.selectAll('.' + CLASS.circles).selectAll('.' + CLASS.circle) 32103 .data($$.lineOrScatterData.bind($$)); 32104 $$.mainCircle.enter().append("circle") 32105 .attr("class", $$.classCircle.bind($$)) 32106 .attr("r", $$.pointR.bind($$)) 32107 .style("fill", $$.color); 32108 $$.mainCircle 32109 .style("opacity", $$.initialOpacity.bind($$)); 32110 $$.mainCircle.exit().remove(); 32111 }; 32112 c3_chart_internal_fn.addTransitionForCircle = function (transitions, cx, cy) { 32113 var $$ = this; 32114 transitions.push($$.mainCircle.transition() 32115 .style('opacity', $$.opacityForCircle.bind($$)) 32116 .style("fill", $$.color) 32117 .attr("cx", cx) 32118 .attr("cy", cy)); 32119 transitions.push($$.main.selectAll('.' + CLASS.selectedCircle).transition() 32120 .attr("cx", cx) 32121 .attr("cy", cy)); 32122 }; 32123 c3_chart_internal_fn.circleX = function (d) { 32124 return d.x || d.x === 0 ? this.x(d.x) : null; 32125 }; 32126 c3_chart_internal_fn.circleY = function (d, i) { 32127 var $$ = this, 32128 lineIndices = $$.getShapeIndices($$.isLineType), getPoint = $$.generateGetLinePoint(lineIndices); 32129 return $$.config.data_groups.length > 0 ? getPoint(d, i)[0][1] : $$.getYScale(d.id)(d.value); 32130 }; 32131 c3_chart_internal_fn.getCircles = function (i, id) { 32132 var $$ = this; 32133 return (id ? $$.main.selectAll('.' + CLASS.circles + $$.getTargetSelectorSuffix(id)) : $$.main).selectAll('.' + CLASS.circle + (isValue(i) ? '-' + i : '')); 32134 }; 32135 c3_chart_internal_fn.expandCircles = function (i, id) { 32136 var $$ = this, 32137 r = $$.pointExpandedR.bind($$); 32138 $$.getCircles(i, id) 32139 .classed(CLASS.EXPANDED, true) 32140 .attr('r', r); 32141 }; 32142 c3_chart_internal_fn.unexpandCircles = function (i) { 32143 var $$ = this, 32144 r = $$.pointR.bind($$); 32145 $$.getCircles(i) 32146 .filter(function () { return $$.d3.select(this).classed(CLASS.EXPANDED); }) 32147 .classed(CLASS.EXPANDED, false) 32148 .attr('r', r); 32149 }; 32150 c3_chart_internal_fn.pointR = function (d) {
32151 var $$ = this, config = $$.config; 32152 return config.point_show && !$$.isStepType(d) ? (isFunction(config.point_r) ? config.point_r(d) : config.point_r) : 0; 32153 }; 32154 c3_chart_internal_fn.pointExpandedR = function (d) { 32155 var $$ = this, config = $$.config; 32156 return config.point_focus_expand_enabled ? (config.point_focus_expand_r ? config.point_focus_expand_r : $$.pointR(d) * 1.75) : $$.pointR(d); 32157 }; 32158 c3_chart_internal_fn.pointSelectR = function (d) { 32159 var $$ = this, config = $$.config; 32160 return config.point_select_r ? config.point_select_r : $$.pointR(d) * 4; 32161 }; 32162 c3_chart_internal_fn.isWithinCircle = function (_this, _r) { 32163 var d3 = this.d3, 32164 mouse = d3.mouse(_this), d3_this = d3.select(_this), 32165 cx = d3_this.attr("cx") * 1, cy = d3_this.attr("cy") * 1; 32166 return Math.sqrt(Math.pow(cx - mouse[0], 2) + Math.pow(cy - mouse[1], 2)) < _r; 32167 }; 32168 32169 c3_chart_internal_fn.initBar = function () { 32170 var $$ = this; 32171 $$.main.select('.' + CLASS.chart).append("g") 32172 .attr("class", CLASS.chartBars); 32173 }; 32174 c3_chart_internal_fn.updateTargetsForBar = function (targets) { 32175 var $$ = this, config = $$.config, 32176 mainBarUpdate, mainBarEnter, 32177 classChartBar = $$.classChartBar.bind($$), 32178 classBars = $$.classBars.bind($$); 32179 mainBarUpdate = $$.main.select('.' + CLASS.chartBars).selectAll('.' + CLASS.chartBar) 32180 .data(targets) 32181 .attr('class', classChartBar); 32182 mainBarEnter = mainBarUpdate.enter().append('g') 32183 .attr('class', classChartBar) 32184 .style('opacity', 0) 32185 .style("pointer-events", "none"); 32186 // Bars for each data 32187 mainBarEnter.append('g') 32188 .attr("class", classBars) 32189 .style("cursor", function (d) { return config.data_selection_isselectable(d) ? "pointer" : null; }); 32190 32191 }; 32192 c3_chart_internal_fn.redrawBar = function (durationForExit) { 32193 var $$ = this, 32194 barData = $$.barData.bind($$), 32195 classBar = $$.classBar.bind($$), 32196 initialOpacity = $$.initialOpacity.bind($$), 32197 color = function (d) { return $$.color(d.id); }; 32198 $$.mainBar = $$.main.selectAll('.' + CLASS.bars).selectAll('.' + CLASS.bar) 32199 .data(barData); 32200 $$.mainBar.enter().append('path') 32201 .attr("class", classBar) 32202 .style("stroke", color) 32203 .style("fill", color); 32204 $$.mainBar 32205 .style("opacity", initialOpacity); 32206 $$.mainBar.exit().transition().duration(durationForExit) 32207 .style('opacity', 0) 32208 .remove(); 32209 }; 32210 c3_chart_internal_fn.addTransitionForBar = function (transitions, drawBar) { 32211 var $$ = this; 32212 transitions.push($$.mainBar.transition() 32213 .attr('d', drawBar) 32214 .style("fill", $$.color) 32215 .style("opacity", 1)); 32216 }; 32217 c3_chart_internal_fn.getBarW = function (axis, barTargetsNum) { 32218 var $$ = this, config = $$.config, 32219 w = typeof config.bar_width === 'number' ? config.bar_width : barTargetsNum ? (axis.tickOffset() * 2 * config.bar_width_ratio) / barTargetsNum : 0; 32220 return config.bar_width_max && w > config.bar_width_max ? config.bar_width_max : w; 32221 }; 32222 c3_chart_internal_fn.getBars = function (i) { 32223 var $$ = this; 32224 return $$.main.selectAll('.' + CLASS.bar + (isValue(i) ? '-' + i : '')); 32225 }; 32226 c3_chart_internal_fn.expandBars = function (i) { 32227 var $$ = this; 32228 $$.getBars(i).classed(CLASS.EXPANDED, true); 32229 }; 32230 c3_chart_internal_fn.unexpandBars = function (i) { 32231 var $$ = this; 32232 $$.getBars(i).classed(CLASS.EXPANDED, false); 32233 }; 32234 c3_chart_internal_fn.generateDrawBar = function (barIndices, isSub) { 32235 var $$ = this, config = $$.config, 32236 getPoints = $$.generateGetBarPoints(barIndices, isSub); 32237 return function (d, i) { 32238 // 4 points that make a bar 32239 var points = getPoints(d, i); 32240 32241 // switch points if axis is rotated, not applicable for sub chart 32242 var indexX = config.axis_rotated ? 1 : 0; 32243 var indexY = config.axis_rotated ? 0 : 1; 32244 32245 var path = 'M ' + points[0][indexX] + ',' + points[0][indexY] + ' ' + 32246 'L' + points[1][indexX] + ',' + points[1][indexY] + ' ' + 32247 'L' + points[2][indexX] + ',' + points[2][indexY] + ' ' + 32248 'L' + points[3][indexX] + ',' + points[3][indexY] + ' ' + 32249 'z'; 32250 32251 return path; 32252 }; 32253 }; 32254 c3_chart_internal_fn.generateGetBarPoints = function (barIndices, isSub) { 32255 var $$ = this, 32256 barTargetsNum = barIndices.__max__ + 1, 32257 barW = $$.getBarW($$.xAxis, barTargetsNum), 32258 barX = $$.getShapeX(barW, barTargetsNum, barIndices, !!isSub), 32259 barY = $$.getShapeY(!!isSub), 32260 barOffset = $$.getShapeOffset($$.isBarType, barIndices, !!isSub), 32261 yScale = isSub ? $$.getSubYScale : $$.getYScale; 32262 return function (d, i) { 32263 var y0 = yScale.call($$, d.id)(0), 32264 offset = barOffset(d, i) || y0, // offset is for stacked bar chart 32265 posX = barX(d), posY = barY(d); 32266 // fix posY not to overflow opposite quadrant 32267 if ($$.config.axis_rotated) { 32268 if ((0 < d.value && posY < y0) || (d.value < 0 && y0 < posY)) { posY = y0; } 32269 } 32270 // 4 points that make a bar 32271 return [ 32272 [posX, offset], 32273 [posX, posY - (y0 - offset)], 32274 [posX + barW, posY - (y0 - offset)], 32275 [posX + barW, offset] 32276 ]; 32277 }; 32278 }; 32279 c3_chart_internal_fn.isWithinBar = function (_this) { 32280 var d3 = this.d3, 32281 mouse = d3.mouse(_this), box = _this.getBoundingClientRect(), 32282 seg0 = _this.pathSegList.getItem(0), seg1 = _this.pathSegList.getItem(1), 32283 x = seg0.x, y = Math.min(seg0.y, seg1.y), w = box.width, h = box.height, offset = 2, 32284 sx = x - offset, ex = x + w + offset, sy = y + h + offset, ey = y - offset; 32285 return sx < mouse[0] && mouse[0] < ex && ey < mouse[1] && mouse[1] < sy; 32286 }; 32287 32288 c3_chart_internal_fn.initText = function () { 32289 var $$ = this; 32290 $$.main.select('.' + CLASS.chart).append("g") 32291 .attr("class", CLASS.chartTexts); 32292 $$.mainText = $$.d3.selectAll([]); 32293 }; 32294 c3_chart_internal_fn.updateTargetsForText = function (targets) { 32295 var $$ = this, mainTextUpdate, mainTextEnter, 32296 classChartText = $$.classChartText.bind($$), 32297 classTexts = $$.classTexts.bind($$); 32298 mainTextUpdate = $$.main.select('.' + CLASS.chartTexts).selectAll('.' + CLASS.chartText) 32299 .data(targets) 32300 .attr('class', classChartText); 32301 mainTextEnter = mainTextUpdate.enter().append('g') 32302 .attr('class', classChartText) 32303 .style('opacity', 0) 32304 .style("pointer-events", "none"); 32305 mainTextEnter.append('g') 32306 .attr('class', classTexts); 32307 }; 32308 c3_chart_internal_fn.redrawText = function (durationForExit) {
32309 var $$ = this, config = $$.config, 32310 barOrLineData = $$.barOrLineData.bind($$), 32311 classText = $$.classText.bind($$); 32312 $$.mainText = $$.main.selectAll('.' + CLASS.texts).selectAll('.' + CLASS.text) 32313 .data(barOrLineData); 32314 $$.mainText.enter().append('text') 32315 .attr("class", classText) 32316 .attr('text-anchor', function (d) { return config.axis_rotated ? (d.value < 0 ? 'end' : 'start') : 'middle'; }) 32317 .style("stroke", 'none') 32318 .style("fill", function (d) { return $$.color(d); }) 32319 .style("fill-opacity", 0); 32320 $$.mainText 32321 .text(function (d) { return $$.formatByAxisId($$.getAxisId(d.id))(d.value, d.id); }); 32322 $$.mainText.exit() 32323 .transition().duration(durationForExit) 32324 .style('fill-opacity', 0) 32325 .remove(); 32326 }; 32327 c3_chart_internal_fn.addTransitionForText = function (transitions, xForText, yForText, forFlow) { 32328 var $$ = this, 32329 opacityForText = forFlow ? 0 : $$.opacityForText.bind($$); 32330 transitions.push($$.mainText.transition() 32331 .attr('x', xForText) 32332 .attr('y', yForText) 32333 .style("fill", $$.color) 32334 .style("fill-opacity", opacityForText)); 32335 }; 32336 c3_chart_internal_fn.getTextRect = function (text, cls) { 32337 var rect; 32338 this.d3.select('body').selectAll('.dummy') 32339 .data([text]) 32340 .enter().append('text') 32341 .classed(cls ? cls : "", true) 32342 .text(text) 32343 .each(function () { rect = this.getBoundingClientRect(); }) 32344 .remove(); 32345 return rect; 32346 }; 32347 c3_chart_internal_fn.generateXYForText = function (barIndices, forX) { 32348 var $$ = this, 32349 getPoints = $$.generateGetBarPoints(barIndices, false), 32350 getter = forX ? $$.getXForText : $$.getYForText; 32351 return function (d, i) { 32352 return getter.call($$, getPoints(d, i), d, this); 32353 }; 32354 }; 32355 c3_chart_internal_fn.getXForText = function (points, d, textElement) { 32356 var $$ = this, 32357 box = textElement.getBoundingClientRect(), xPos, padding; 32358 if ($$.config.axis_rotated) { 32359 padding = $$.isBarType(d) ? 4 : 6; 32360 xPos = points[2][1] + padding * (d.value < 0 ? -1 : 1); 32361 } else { 32362 xPos = $$.hasType('bar') ? (points[2][0] + points[0][0]) / 2 : points[0][0]; 32363 } 32364 return xPos > $$.width ? $$.width - box.width : xPos; 32365 }; 32366 c3_chart_internal_fn.getYForText = function (points, d, textElement) { 32367 var $$ = this, 32368 box = textElement.getBoundingClientRect(), yPos; 32369 if ($$.config.axis_rotated) { 32370 yPos = (points[0][0] + points[2][0] + box.height * 0.6) / 2; 32371 } else { 32372 yPos = points[2][1] + (d.value < 0 ? box.height : $$.isBarType(d) ? -3 : -6); 32373 } 32374 return yPos < box.height ? box.height : yPos; 32375 }; 32376 32377 c3_chart_internal_fn.setTargetType = function (targetIds, type) { 32378 var $$ = this, config = $$.config; 32379 $$.mapToTargetIds(targetIds).forEach(function (id) { 32380 $$.withoutFadeIn[id] = (type === config.data_types[id]); 32381 config.data_types[id] = type; 32382 }); 32383 if (!targetIds) { 32384 config.data_type = type; 32385 } 32386 }; 32387 c3_chart_internal_fn.hasType = function (type, targets) { 32388 var $$ = this, types = $$.config.data_types, has = false; 32389 (targets || $$.data.targets).forEach(function (t) { 32390 if ((types[t.id] && types[t.id].indexOf(type) >= 0) || (!(t.id in types) && type === 'line')) { 32391 has = true; 32392 } 32393 }); 32394 return has; 32395 }; 32396 c3_chart_internal_fn.hasArcType = function (targets) { 32397 return this.hasType('pie', targets) || this.hasType('donut', targets) || this.hasType('gauge', targets); 32398 }; 32399 c3_chart_internal_fn.isLineType = function (d) { 32400 var config = this.config, id = isString(d) ? d : d.id; 32401 return !config.data_types[id] || ['line', 'spline', 'area', 'area-spline', 'step', 'area-step'].indexOf(config.data_types[id]) >= 0; 32402 }; 32403 c3_chart_internal_fn.isStepType = function (d) { 32404 var id = isString(d) ? d : d.id; 32405 return ['step', 'area-step'].indexOf(this.config.data_types[id]) >= 0; 32406 }; 32407 c3_chart_internal_fn.isSplineType = function (d) { 32408 var id = isString(d) ? d : d.id; 32409 return ['spline', 'area-spline'].indexOf(this.config.data_types[id]) >= 0; 32410 }; 32411 c3_chart_internal_fn.isAreaType = function (d) { 32412 var id = isString(d) ? d : d.id; 32413 return ['area', 'area-spline', 'area-step'].indexOf(this.config.data_types[id]) >= 0; 32414 }; 32415 c3_chart_internal_fn.isBarType = function (d) { 32416 var id = isString(d) ? d : d.id; 32417 return this.config.data_types[id] === 'bar'; 32418 }; 32419 c3_chart_internal_fn.isScatterType = function (d) { 32420 var id = isString(d) ? d : d.id; 32421 return this.config.data_types[id] === 'scatter'; 32422 }; 32423 c3_chart_internal_fn.isPieType = function (d) { 32424 var id = isString(d) ? d : d.id; 32425 return this.config.data_types[id] === 'pie'; 32426 }; 32427 c3_chart_internal_fn.isGaugeType = function (d) { 32428 var id = isString(d) ? d : d.id; 32429 return this.config.data_types[id] === 'gauge'; 32430 }; 32431 c3_chart_internal_fn.isDonutType = function (d) { 32432 var id = isString(d) ? d : d.id; 32433 return this.config.data_types[id] === 'donut'; 32434 }; 32435 c3_chart_internal_fn.isArcType = function (d) { 32436 return this.isPieType(d) || this.isDonutType(d) || this.isGaugeType(d); 32437 }; 32438 c3_chart_internal_fn.lineData = function (d) { 32439 return this.isLineType(d) ? [d] : []; 32440 }; 32441 c3_chart_internal_fn.arcData = function (d) { 32442 return this.isArcType(d.data) ? [d] : []; 32443 }; 32444 /* not used 32445 function scatterData(d) { 32446 return isScatterType(d) ? d.values : []; 32447 } 32448 */ 32449 c3_chart_internal_fn.barData = function (d) { 32450 return this.isBarType(d) ? d.values : []; 32451 }; 32452 c3_chart_internal_fn.lineOrScatterData = function (d) { 32453 return this.isLineType(d) || this.isScatterType(d) ? d.values : []; 32454 }; 32455 c3_chart_internal_fn.barOrLineData = function (d) { 32456 return this.isBarType(d) || this.isLineType(d) ? d.values : []; 32457 }; 32458 32459 c3_chart_internal_fn.initGrid = function () {
32460 var $$ = this, config = $$.config, d3 = $$.d3; 32461 $$.grid = $$.main.append('g') 32462 .attr("clip-path", $$.clipPath) 32463 .attr('class', CLASS.grid); 32464 if (config.grid_x_show) { 32465 $$.grid.append("g").attr("class", CLASS.xgrids); 32466 } 32467 if (config.grid_y_show) { 32468 $$.grid.append('g').attr('class', CLASS.ygrids); 32469 } 32470 $$.grid.append('g').attr("class", CLASS.xgridLines); 32471 $$.grid.append('g').attr('class', CLASS.ygridLines); 32472 if (config.grid_focus_show) { 32473 $$.grid.append('g') 32474 .attr("class", CLASS.xgridFocus) 32475 .append('line') 32476 .attr('class', CLASS.xgridFocus); 32477 } 32478 $$.xgrid = d3.selectAll([]); 32479 $$.xgridLines = d3.selectAll([]); 32480 }; 32481 32482 c3_chart_internal_fn.updateXGrid = function (withoutUpdate) { 32483 var $$ = this, config = $$.config, d3 = $$.d3, 32484 xgridData = $$.generateGridData(config.grid_x_type, $$.x), 32485 tickOffset = $$.isCategorized() ? $$.xAxis.tickOffset() : 0; 32486 32487 $$.xgridAttr = config.axis_rotated ? { 32488 'x1': 0, 32489 'x2': $$.width, 32490 'y1': function (d) { return $$.x(d) - tickOffset; }, 32491 'y2': function (d) { return $$.x(d) - tickOffset; } 32492 } : { 32493 'x1': function (d) { return $$.x(d) + tickOffset; }, 32494 'x2': function (d) { return $$.x(d) + tickOffset; }, 32495 'y1': 0, 32496 'y2': $$.height 32497 }; 32498 32499 $$.xgrid = $$.main.select('.' + CLASS.xgrids).selectAll('.' + CLASS.xgrid) 32500 .data(xgridData); 32501 $$.xgrid.enter().append('line').attr("class", CLASS.xgrid); 32502 if (!withoutUpdate) { 32503 $$.xgrid.attr($$.xgridAttr) 32504 .style("opacity", function () { return +d3.select(this).attr(config.axis_rotated ? 'y1' : 'x1') === (config.axis_rotated ? $$.height : 0) ? 0 : 1; }); 32505 } 32506 $$.xgrid.exit().remove(); 32507 }; 32508 32509 c3_chart_internal_fn.updateYGrid = function () { 32510 var $$ = this, config = $$.config; 32511 $$.ygrid = $$.main.select('.' + CLASS.ygrids).selectAll('.' + CLASS.ygrid) 32512 .data($$.y.ticks(config.grid_y_ticks)); 32513 $$.ygrid.enter().append('line') 32514 .attr('class', CLASS.ygrid); 32515 $$.ygrid.attr("x1", config.axis_rotated ? $$.y : 0) 32516 .attr("x2", config.axis_rotated ? $$.y : $$.width) 32517 .attr("y1", config.axis_rotated ? 0 : $$.y) 32518 .attr("y2", config.axis_rotated ? $$.height : $$.y); 32519 $$.ygrid.exit().remove(); 32520 $$.smoothLines($$.ygrid, 'grid'); 32521 }; 32522 32523 32524 c3_chart_internal_fn.redrawGrid = function (duration, withY) { 32525 var $$ = this, main = $$.main, config = $$.config, 32526 xgridLine, ygridLine, yv; 32527 main.select('line.' + CLASS.xgridFocus).style("visibility", "hidden"); 32528 if (config.grid_x_show) { 32529 $$.updateXGrid(); 32530 } 32531 $$.xgridLines = main.select('.' + CLASS.xgridLines).selectAll('.' + CLASS.xgridLine) 32532 .data(config.grid_x_lines); 32533 // enter 32534 xgridLine = $$.xgridLines.enter().append('g') 32535 .attr("class", function (d) { return CLASS.xgridLine + (d.class ? ' ' + d.class : ''); }); 32536 xgridLine.append('line') 32537 .style("opacity", 0); 32538 xgridLine.append('text') 32539 .attr("text-anchor", "end") 32540 .attr("transform", config.axis_rotated ? "" : "rotate(-90)") 32541 .attr('dx', config.axis_rotated ? 0 : -$$.margin.top) 32542 .attr('dy', -5) 32543 .style("opacity", 0); 32544 // udpate 32545 // done in d3.transition() of the end of this function 32546 // exit 32547 $$.xgridLines.exit().transition().duration(duration) 32548 .style("opacity", 0) 32549 .remove(); 32550 32551 // Y-Grid 32552 if (withY && config.grid_y_show) { 32553 $$.updateYGrid(); 32554 } 32555 if (withY) { 32556 $$.ygridLines = main.select('.' + CLASS.ygridLines).selectAll('.' + CLASS.ygridLine) 32557 .data(config.grid_y_lines); 32558 // enter
vendor: 4,461 bytes, lines 32559-32651
32559 ygridLine = $$.ygridLines.enter().append('g') 32560 .attr("class", function (d) { return CLASS.ygridLine + (d.class ? ' ' + d.class : ''); }); 32561 ygridLine.append('line') 32562 .style("opacity", 0); 32563 ygridLine.append('text') 32564 .attr("text-anchor", "end") 32565 .attr("transform", config.axis_rotated ? "rotate(-90)" : "") 32566 .attr('dx', config.axis_rotated ? 0 : -$$.margin.top) 32567 .attr('dy', -5) 32568 .style("opacity", 0); 32569 // update 32570 yv = $$.yv.bind($$); 32571 $$.ygridLines.select('line') 32572 .transition().duration(duration) 32573 .attr("x1", config.axis_rotated ? yv : 0) 32574 .attr("x2", config.axis_rotated ? yv : $$.width) 32575 .attr("y1", config.axis_rotated ? 0 : yv) 32576 .attr("y2", config.axis_rotated ? $$.height : yv) 32577 .style("opacity", 1); 32578 $$.ygridLines.select('text') 32579 .transition().duration(duration) 32580 .attr("x", config.axis_rotated ? 0 : $$.width) 32581 .attr("y", yv) 32582 .text(function (d) { return d.text; }) 32583 .style("opacity", 1); 32584 // exit 32585 $$.ygridLines.exit().transition().duration(duration) 32586 .style("opacity", 0) 32587 .remove(); 32588 } 32589 }; 32590 c3_chart_internal_fn.addTransitionForGrid = function (transitions) { 32591 var $$ = this, config = $$.config, xv = $$.xv.bind($$); 32592 transitions.push($$.xgridLines.select('line').transition() 32593 .attr("x1", config.axis_rotated ? 0 : xv) 32594 .attr("x2", config.axis_rotated ? $$.width : xv) 32595 .attr("y1", config.axis_rotated ? xv : $$.margin.top) 32596 .attr("y2", config.axis_rotated ? xv : $$.height) 32597 .style("opacity", 1)); 32598 transitions.push($$.xgridLines.select('text').transition() 32599 .attr("x", config.axis_rotated ? $$.width : 0) 32600 .attr("y", xv) 32601 .text(function (d) { return d.text; }) 32602 .style("opacity", 1)); 32603 }; 32604 c3_chart_internal_fn.showXGridFocus = function (selectedData) { 32605 var $$ = this, config = $$.config, 32606 dataToShow = selectedData.filter(function (d) { return d && isValue(d.value); }), 32607 focusEl = $$.main.selectAll('line.' + CLASS.xgridFocus), 32608 xx = $$.xx.bind($$); 32609 if (! config.tooltip_show) { return; } 32610 // Hide when scatter plot exists 32611 if ($$.hasType('scatter') || $$.hasArcType()) { return; } 32612 focusEl 32613 .style("visibility", "visible") 32614 .data([dataToShow[0]]) 32615 .attr(config.axis_rotated ? 'y1' : 'x1', xx) 32616 .attr(config.axis_rotated ? 'y2' : 'x2', xx); 32617 $$.smoothLines(focusEl, 'grid'); 32618 }; 32619 c3_chart_internal_fn.hideXGridFocus = function () { 32620 this.main.select('line.' + CLASS.xgridFocus).style("visibility", "hidden"); 32621 }; 32622 c3_chart_internal_fn.updateXgridFocus = function () { 32623 var $$ = this, config = $$.config; 32624 $$.main.select('line.' + CLASS.xgridFocus) 32625 .attr("x1", config.axis_rotated ? 0 : -10) 32626 .attr("x2", config.axis_rotated ? $$.width : -10) 32627 .attr("y1", config.axis_rotated ? -10 : 0) 32628 .attr("y2", config.axis_rotated ? -10 : $$.height); 32629 }; 32630 c3_chart_internal_fn.generateGridData = function (type, scale) { 32631 var $$ = this, 32632 gridData = [], xDomain, firstYear, lastYear, i, 32633 tickNum = $$.main.select("." + CLASS.axisX).selectAll('.tick').size(); 32634 if (type === 'year') { 32635 xDomain = $$.getXDomain(); 32636 firstYear = xDomain[0].getFullYear(); 32637 lastYear = xDomain[1].getFullYear(); 32638 for (i = firstYear; i <= lastYear; i++) { 32639 gridData.push(new Date(i + '-01-01 00:00:00')); 32640 } 32641 } else { 32642 gridData = scale.ticks(10); 32643 if (gridData.length > tickNum) { // use only int 32644 gridData = gridData.filter(function (d) { return ("" + d).indexOf('.') < 0; }); 32645 } 32646 } 32647 return gridData; 32648 }; 32649 c3_chart_internal_fn.getGridFilterToRemove = function (params) { 32650 return params ? function (line) { 32651 var found = false;
32652 [].concat(params).forEach(function (param) { 32653 if ((('value' in param && line.value === params.value) || ('class' in param && line.class === params.class))) { 32654 found = true; 32655 } 32656 }); 32657 return found; 32658 } : function () { return true; }; 32659 }; 32660 c3_chart_internal_fn.removeGridLines = function (params, forX) { 32661 var $$ = this, config = $$.config, 32662 toRemove = $$.getGridFilterToRemove(params), 32663 toShow = function (line) { return !toRemove(line); }, 32664 classLines = forX ? CLASS.xgridLines : CLASS.ygridLines, 32665 classLine = forX ? CLASS.xgridLine : CLASS.ygridLine; 32666 $$.main.select('.' + classLines).selectAll('.' + classLine).filter(toRemove) 32667 .transition().duration(config.transition_duration) 32668 .style('opacity', 0).remove(); 32669 if (forX) { 32670 config.grid_x_lines = config.grid_x_lines.filter(toShow); 32671 } else { 32672 config.grid_y_lines = config.grid_y_lines.filter(toShow); 32673 } 32674 }; 32675 32676 c3_chart_internal_fn.initTooltip = function () { 32677 var $$ = this, config = $$.config, i; 32678 $$.tooltip = $$.selectChart 32679 .style("position", "relative") 32680 .append("div") 32681 .style("position", "absolute") 32682 .style("pointer-events", "none") 32683 .style("z-index", "10") 32684 .style("display", "none"); 32685 // Show tooltip if needed 32686 if (config.tooltip_init_show) { 32687 if ($$.isTimeSeries() && isString(config.tooltip_init_x)) { 32688 config.tooltip_init_x = $$.parseDate(config.tooltip_init_x); 32689 for (i = 0; i < $$.data.targets[0].values.length; i++) { 32690 if (($$.data.targets[0].values[i].x - config.tooltip_init_x) === 0) { break; } 32691 } 32692 config.tooltip_init_x = i; 32693 } 32694 $$.tooltip.html(config.tooltip_contents.call($$, $$.data.targets.map(function (d) { 32695 return $$.addName(d.values[config.tooltip_init_x]); 32696 }), $$.getXAxisTickFormat(), $$.getYFormat($$.hasArcType()), $$.color)); 32697 $$.tooltip.style("top", config.tooltip_init_position.top) 32698 .style("left", config.tooltip_init_position.left) 32699 .style("display", "block"); 32700 } 32701 }; 32702 c3_chart_internal_fn.getTooltipContent = function (d, defaultTitleFormat, defaultValueFormat, color) { 32703 var $$ = this, config = $$.config, 32704 titleFormat = config.tooltip_format_title || defaultTitleFormat, 32705 nameFormat = config.tooltip_format_name || function (name) { return name; }, 32706 valueFormat = config.tooltip_format_value || defaultValueFormat, 32707 text, i, title, value, name, bgcolor; 32708 for (i = 0; i < d.length; i++) { 32709 if (! (d[i] && (d[i].value || d[i].value === 0))) { continue; } 32710 32711 if (! text) { 32712 title = titleFormat ? titleFormat(d[i].x) : d[i].x; 32713 text = "<table class='" + CLASS.tooltip + "'>" + (title || title === 0 ? "<tr><th colspan='2'>" + title + "</th></tr>" : ""); 32714 } 32715 32716 name = nameFormat(d[i].name); 32717 value = valueFormat(d[i].value, d[i].ratio, d[i].id, d[i].index); 32718 bgcolor = $$.levelColor ? $$.levelColor(d[i].value) : color(d[i].id); 32719 32720 text += "<tr class='" + CLASS.tooltipName + "-" + d[i].id + "'>"; 32721 text += "<td class='name'><span style='background-color:" + bgcolor + "'></span>" + name + "</td>"; 32722 text += "<td class='value'>" + value + "</td>"; 32723 text += "</tr>"; 32724 } 32725 return text + "</table>"; 32726 }; 32727 c3_chart_internal_fn.showTooltip = function (selectedData, mouse) { 32728 var $$ = this, config = $$.config; 32729 var tWidth, tHeight, svgLeft, tooltipLeft, tooltipRight, tooltipTop, chartRight; 32730 var forArc = $$.hasArcType(), 32731 dataToShow = selectedData.filter(function (d) { return d && isValue(d.value); }); 32732 if (dataToShow.length === 0 || !config.tooltip_show) { 32733 return; 32734 } 32735 $$.tooltip.html(config.tooltip_contents.call($$, selectedData, $$.getXAxisTickFormat(), $$.getYFormat(forArc), $$.color)).style("display", "block"); 32736 32737 // Get tooltip dimensions 32738 tWidth = $$.tooltip.property('offsetWidth'); 32739 tHeight = $$.tooltip.property('offsetHeight'); 32740 // Determin tooltip position 32741 if (forArc) { 32742 tooltipLeft = ($$.width / 2) + mouse[0]; 32743 tooltipTop = ($$.height / 2) + mouse[1] + 20; 32744 } else { 32745 if (config.axis_rotated) { 32746 svgLeft = $$.getSvgLeft(); 32747 tooltipLeft = svgLeft + mouse[0] + 100; 32748 tooltipRight = tooltipLeft + tWidth; 32749 chartRight = $$.getCurrentWidth() - $$.getCurrentPaddingRight(); 32750 tooltipTop = $$.x(dataToShow[0].x) + 20; 32751 } else { 32752 svgLeft = $$.getSvgLeft(); 32753 tooltipLeft = svgLeft + $$.getCurrentPaddingLeft() + $$.x(dataToShow[0].x) + 20; 32754 tooltipRight = tooltipLeft + tWidth; 32755 chartRight = svgLeft + $$.getCurrentWidth() - $$.getCurrentPaddingRight(); 32756 tooltipTop = mouse[1] + 15; 32757 } 32758 32759 if (tooltipRight > chartRight) { 32760 tooltipLeft -= tooltipRight - chartRight; 32761 } 32762 if (tooltipTop + tHeight > $$.getCurrentHeight() && tooltipTop > tHeight + 30) { 32763 tooltipTop -= tHeight + 30; 32764 } 32765 } 32766 // Set tooltip 32767 $$.tooltip 32768 .style("top", tooltipTop + "px") 32769 .style("left", tooltipLeft + 'px'); 32770 }; 32771 c3_chart_internal_fn.hideTooltip = function () { 32772 this.tooltip.style("display", "none"); 32773 }; 32774 32775 c3_chart_internal_fn.initLegend = function () { 32776 var $$ = this; 32777 $$.legend = $$.svg.append("g").attr("transform", $$.getTranslate('legend')); 32778 if (!$$.config.legend_show) { 32779 $$.legend.style('visibility', 'hidden'); 32780 $$.hiddenLegendIds = $$.mapToIds($$.data.targets); 32781 } 32782 // MEMO: call here to update legend box and tranlate for all 32783 // MEMO: translate will be upated by this, so transform not needed in updateLegend() 32784 $$.updateLegend($$.mapToIds($$.data.targets), {withTransform: false, withTransitionForTransform: false, withTransition: false}); 32785 }; 32786 c3_chart_internal_fn.updateSizeForLegend = function (legendHeight, legendWidth) {
vendor: 15,326 bytes, lines 32787-33111
32787 var $$ = this, config = $$.config, insetLegendPosition = { 32788 top: $$.isLegendTop ? $$.getCurrentPaddingTop() + config.legend_inset_y + 5.5 : $$.currentHeight - legendHeight - $$.getCurrentPaddingBottom() - config.legend_inset_y, 32789 left: $$.isLegendLeft ? $$.getCurrentPaddingLeft() + config.legend_inset_x + 0.5 : $$.currentWidth - legendWidth - $$.getCurrentPaddingRight() - config.legend_inset_x + 0.5 32790 }; 32791 $$.margin3 = { 32792 top: $$.isLegendRight ? 0 : $$.isLegendInset ? insetLegendPosition.top : $$.currentHeight - legendHeight, 32793 right: NaN, 32794 bottom: 0, 32795 left: $$.isLegendRight ? $$.currentWidth - legendWidth : $$.isLegendInset ? insetLegendPosition.left : 0 32796 }; 32797 }; 32798 c3_chart_internal_fn.transformLegend = function (withTransition) { 32799 var $$ = this; 32800 (withTransition ? $$.legend.transition() : $$.legend).attr("transform", $$.getTranslate('legend')); 32801 }; 32802 c3_chart_internal_fn.updateLegendStep = function (step) { 32803 this.legendStep = step; 32804 }; 32805 c3_chart_internal_fn.updateLegendItemWidth = function (w) { 32806 this.legendItemWidth = w; 32807 }; 32808 c3_chart_internal_fn.updateLegendItemHeight = function (h) { 32809 this.legendItemHeight = h; 32810 }; 32811 c3_chart_internal_fn.getLegendWidth = function () { 32812 var $$ = this; 32813 return $$.config.legend_show ? $$.isLegendRight || $$.isLegendInset ? $$.legendItemWidth * ($$.legendStep + 1) : $$.currentWidth : 0; 32814 }; 32815 c3_chart_internal_fn.getLegendHeight = function () { 32816 var $$ = this, config = $$.config, h = 0; 32817 if (config.legend_show) { 32818 if ($$.isLegendRight) { 32819 h = $$.currentHeight; 32820 } else if ($$.isLegendInset) { 32821 h = config.legend_inset_step ? Math.max(20, $$.legendItemHeight) * (config.legend_inset_step + 1) : $$.height; 32822 } else { 32823 h = Math.max(20, $$.legendItemHeight) * ($$.legendStep + 1); 32824 } 32825 } 32826 return h; 32827 }; 32828 c3_chart_internal_fn.opacityForLegend = function (legendItem) { 32829 var $$ = this; 32830 return legendItem.classed(CLASS.legendItemHidden) ? $$.legendOpacityForHidden : 1; 32831 }; 32832 c3_chart_internal_fn.opacityForUnfocusedLegend = function (legendItem) { 32833 var $$ = this; 32834 return legendItem.classed(CLASS.legendItemHidden) ? $$.legendOpacityForHidden : 0.3; 32835 }; 32836 c3_chart_internal_fn.toggleFocusLegend = function (id, focus) { 32837 var $$ = this; 32838 $$.legend.selectAll('.' + CLASS.legendItem) 32839 .transition().duration(100) 32840 .style('opacity', function (_id) { 32841 var This = $$.d3.select(this); 32842 if (id && _id !== id) { 32843 return focus ? $$.opacityForUnfocusedLegend(This) : $$.opacityForLegend(This); 32844 } else { 32845 return focus ? $$.opacityForLegend(This) : $$.opacityForUnfocusedLegend(This); 32846 } 32847 }); 32848 }; 32849 c3_chart_internal_fn.revertLegend = function () { 32850 var $$ = this, d3 = $$.d3; 32851 $$.legend.selectAll('.' + CLASS.legendItem) 32852 .transition().duration(100) 32853 .style('opacity', function () { return $$.opacityForLegend(d3.select(this)); }); 32854 }; 32855 c3_chart_internal_fn.showLegend = function (targetIds) { 32856 var $$ = this, config = $$.config; 32857 if (!config.legend_show) { 32858 config.legend_show = true; 32859 $$.legend.style('visibility', 'visible'); 32860 } 32861 $$.removeHiddenLegendIds(targetIds); 32862 $$.legend.selectAll($$.selectorLegends(targetIds)) 32863 .style('visibility', 'visible') 32864 .transition() 32865 .style('opacity', function () { return $$.opacityForLegend($$.d3.select(this)); }); 32866 }; 32867 c3_chart_internal_fn.hideLegend = function (targetIds) { 32868 var $$ = this, config = $$.config; 32869 if (config.legend_show && isEmpty(targetIds)) { 32870 config.legend_show = false; 32871 $$.legend.style('visibility', 'hidden'); 32872 } 32873 $$.addHiddenLegendIds(targetIds); 32874 $$.legend.selectAll($$.selectorLegends(targetIds)) 32875 .style('opacity', 0) 32876 .style('visibility', 'hidden'); 32877 }; 32878 c3_chart_internal_fn.updateLegend = function (targetIds, options, transitions) { 32879 var $$ = this, config = $$.config; 32880 var xForLegend, xForLegendText, xForLegendRect, yForLegend, yForLegendText, yForLegendRect; 32881 var paddingTop = 4, paddingRight = 36, maxWidth = 0, maxHeight = 0, posMin = 10; 32882 var l, totalLength = 0, offsets = {}, widths = {}, heights = {}, margins = [0], steps = {}, step = 0; 32883 var withTransition, withTransitionForTransform; 32884 var hasFocused = $$.legend.selectAll('.' + CLASS.legendItemFocused).size(); 32885 var texts, rects, tiles; 32886 32887 options = options || {}; 32888 withTransition = getOption(options, "withTransition", true); 32889 withTransitionForTransform = getOption(options, "withTransitionForTransform", true); 32890 32891 function updatePositions(textElement, id, reset) { 32892 var box = $$.getTextRect(textElement.textContent, CLASS.legendItem), 32893 itemWidth = Math.ceil((box.width + paddingRight) / 10) * 10, 32894 itemHeight = Math.ceil((box.height + paddingTop) / 10) * 10, 32895 itemLength = $$.isLegendRight || $$.isLegendInset ? itemHeight : itemWidth, 32896 areaLength = $$.isLegendRight || $$.isLegendInset ? $$.getLegendHeight() : $$.getLegendWidth(), 32897 margin, maxLength; 32898 32899 // MEMO: care about condifion of step, totalLength 32900 function updateValues(id, withoutStep) { 32901 if (!withoutStep) { 32902 margin = (areaLength - totalLength - itemLength) / 2; 32903 if (margin < posMin) { 32904 margin = (areaLength - itemLength) / 2; 32905 totalLength = 0; 32906 step++; 32907 } 32908 } 32909 steps[id] = step; 32910 margins[step] = $$.isLegendInset ? 10 : margin; 32911 offsets[id] = totalLength; 32912 totalLength += itemLength; 32913 } 32914 32915 if (reset) { 32916 totalLength = 0; 32917 step = 0; 32918 maxWidth = 0; 32919 maxHeight = 0; 32920 } 32921 32922 if (config.legend_show && !$$.isLegendToShow(id)) { 32923 widths[id] = heights[id] = steps[id] = offsets[id] = 0; 32924 return; 32925 } 32926 32927 widths[id] = itemWidth; 32928 heights[id] = itemHeight; 32929 32930 if (!maxWidth || itemWidth >= maxWidth) { maxWidth = itemWidth; } 32931 if (!maxHeight || itemHeight >= maxHeight) { maxHeight = itemHeight; } 32932 maxLength = $$.isLegendRight || $$.isLegendInset ? maxHeight : maxWidth; 32933 32934 if (config.legend_equally) { 32935 Object.keys(widths).forEach(function (id) { widths[id] = maxWidth; }); 32936 Object.keys(heights).forEach(function (id) { heights[id] = maxHeight; }); 32937 margin = (areaLength - maxLength * targetIds.length) / 2; 32938 if (margin < posMin) { 32939 totalLength = 0; 32940 step = 0; 32941 targetIds.forEach(function (id) { updateValues(id); }); 32942 } 32943 else { 32944 updateValues(id, true); 32945 } 32946 } else { 32947 updateValues(id); 32948 } 32949 } 32950 32951 if ($$.isLegendRight) { 32952 xForLegend = function (id) { return maxWidth * steps[id]; }; 32953 yForLegend = function (id) { return margins[steps[id]] + offsets[id]; }; 32954 } else if ($$.isLegendInset) { 32955 xForLegend = function (id) { return maxWidth * steps[id] + 10; }; 32956 yForLegend = function (id) { return margins[steps[id]] + offsets[id]; }; 32957 } else { 32958 xForLegend = function (id) { return margins[steps[id]] + offsets[id]; }; 32959 yForLegend = function (id) { return maxHeight * steps[id]; }; 32960 } 32961 xForLegendText = function (id, i) { return xForLegend(id, i) + 14; }; 32962 yForLegendText = function (id, i) { return yForLegend(id, i) + 9; }; 32963 xForLegendRect = function (id, i) { return xForLegend(id, i) - 4; }; 32964 yForLegendRect = function (id, i) { return yForLegend(id, i) - 7; }; 32965 32966 // Define g for legend area 32967 l = $$.legend.selectAll('.' + CLASS.legendItem) 32968 .data(targetIds) 32969 .enter().append('g') 32970 .attr('class', function (id) { return $$.generateClass(CLASS.legendItem, id); }) 32971 .style('visibility', function (id) { return $$.isLegendToShow(id) ? 'visible' : 'hidden'; }) 32972 .style('cursor', 'pointer') 32973 .on('click', function (id) { 32974 config.legend_item_onclick ? config.legend_item_onclick.call($$, id) : $$.api.toggle(id); 32975 }) 32976 .on('mouseover', function (id) { 32977 $$.d3.select(this).classed(CLASS.legendItemFocused, true); 32978 if (!$$.transiting) { 32979 $$.api.focus(id); 32980 } 32981 if (config.legend_item_onmouseover) { 32982 config.legend_item_onmouseover.call($$, id); 32983 } 32984 }) 32985 .on('mouseout', function (id) { 32986 $$.d3.select(this).classed(CLASS.legendItemFocused, false); 32987 if (!$$.transiting) { 32988 $$.api.revert(); 32989 } 32990 if (config.legend_item_onmouseout) { 32991 config.legend_item_onmouseout.call($$, id); 32992 } 32993 }); 32994 l.append('text') 32995 .text(function (id) { return isDefined(config.data_names[id]) ? config.data_names[id] : id; }) 32996 .each(function (id, i) { updatePositions(this, id, i === 0); }) 32997 .style("pointer-events", "none") 32998 .attr('x', $$.isLegendRight || $$.isLegendInset ? xForLegendText : -200) 32999 .attr('y', $$.isLegendRight || $$.isLegendInset ? -200 : yForLegendText); 33000 l.append('rect') 33001 .attr("class", CLASS.legendItemEvent) 33002 .style('fill-opacity', 0) 33003 .attr('x', $$.isLegendRight || $$.isLegendInset ? xForLegendRect : -200) 33004 .attr('y', $$.isLegendRight || $$.isLegendInset ? -200 : yForLegendRect); 33005 l.append('rect') 33006 .attr("class", CLASS.legendItemTile) 33007 .style("pointer-events", "none") 33008 .style('fill', $$.color) 33009 .attr('x', $$.isLegendRight || $$.isLegendInset ? xForLegendText : -200) 33010 .attr('y', $$.isLegendRight || $$.isLegendInset ? -200 : yForLegend) 33011 .attr('width', 10) 33012 .attr('height', 10); 33013 // Set background for inset legend 33014 if ($$.isLegendInset && maxWidth !== 0) { 33015 $$.legend.insert('g', '.' + CLASS.legendItem) 33016 .attr("class", CLASS.legendBackground) 33017 .append('rect') 33018 .attr('height', $$.getLegendHeight() - 10) 33019 .attr('width', maxWidth * (step + 1) + 10); 33020 } 33021 33022 texts = $$.legend.selectAll('text') 33023 .data(targetIds) 33024 .text(function (id) { return isDefined(config.data_names[id]) ? config.data_names[id] : id; }) // MEMO: needed for update 33025 .each(function (id, i) { updatePositions(this, id, i === 0); }); 33026 (withTransition ? texts.transition() : texts) 33027 .attr('x', xForLegendText) 33028 .attr('y', yForLegendText); 33029 33030 rects = $$.legend.selectAll('rect.' + CLASS.legendItemEvent) 33031 .data(targetIds); 33032 (withTransition ? rects.transition() : rects) 33033 .attr('width', function (id) { return widths[id]; }) 33034 .attr('height', function (id) { return heights[id]; }) 33035 .attr('x', xForLegendRect) 33036 .attr('y', yForLegendRect); 33037 33038 tiles = $$.legend.selectAll('rect.' + CLASS.legendItemTile) 33039 .data(targetIds); 33040 (withTransition ? tiles.transition() : tiles) 33041 .style('fill', $$.color) 33042 .attr('x', xForLegend) 33043 .attr('y', yForLegend); 33044 33045 // toggle legend state 33046 $$.legend.selectAll('.' + CLASS.legendItem) 33047 .classed(CLASS.legendItemHidden, function (id) { return !$$.isTargetToShow(id); }) 33048 .transition() 33049 .style('opacity', function (id) { 33050 var This = $$.d3.select(this); 33051 if ($$.isTargetToShow(id)) { 33052 return !hasFocused || This.classed(CLASS.legendItemFocused) ? $$.opacityForLegend(This) : $$.opacityForUnfocusedLegend(This); 33053 } else { 33054 return $$.legendOpacityForHidden; 33055 } 33056 }); 33057 33058 // Update all to reflect change of legend 33059 $$.updateLegendItemWidth(maxWidth); 33060 $$.updateLegendItemHeight(maxHeight); 33061 $$.updateLegendStep(step); 33062 // Update size and scale 33063 $$.updateSizes(); 33064 $$.updateScales(); 33065 $$.updateSvgSize(); 33066 // Update g positions 33067 $$.transformAll(withTransitionForTransform, transitions); 33068 }; 33069 33070 c3_chart_internal_fn.initAxis = function () { 33071 var $$ = this, config = $$.config, main = $$.main; 33072 $$.axes.x = main.append("g") 33073 .attr("class", CLASS.axis + ' ' + CLASS.axisX) 33074 .attr("clip-path", $$.clipPathForXAxis) 33075 .attr("transform", $$.getTranslate('x')) 33076 .style("visibility", config.axis_x_show ? 'visible' : 'hidden'); 33077 $$.axes.x.append("text") 33078 .attr("class", CLASS.axisXLabel) 33079 .attr("transform", config.axis_rotated ? "rotate(-90)" : "") 33080 .style("text-anchor", $$.textAnchorForXAxisLabel.bind($$)); 33081 33082 $$.axes.y = main.append("g") 33083 .attr("class", CLASS.axis + ' ' + CLASS.axisY) 33084 .attr("clip-path", $$.clipPathForYAxis) 33085 .attr("transform", $$.getTranslate('y')) 33086 .style("visibility", config.axis_y_show ? 'visible' : 'hidden'); 33087 $$.axes.y.append("text") 33088 .attr("class", CLASS.axisYLabel) 33089 .attr("transform", config.axis_rotated ? "" : "rotate(-90)") 33090 .style("text-anchor", $$.textAnchorForYAxisLabel.bind($$)); 33091 33092 $$.axes.y2 = main.append("g") 33093 .attr("class", CLASS.axis + ' ' + CLASS.axisY2) 33094 // clip-path? 33095 .attr("transform", $$.getTranslate('y2')) 33096 .style("visibility", config.axis_y2_show ? 'visible' : 'hidden'); 33097 $$.axes.y2.append("text") 33098 .attr("class", CLASS.axisY2Label) 33099 .attr("transform", config.axis_rotated ? "" : "rotate(-90)") 33100 .style("text-anchor", $$.textAnchorForY2AxisLabel.bind($$)); 33101 }; 33102 c3_chart_internal_fn.getXAxis = function (scale, orient, tickFormat, tickValues) { 33103 var $$ = this, config = $$.config, 33104 axis = c3_axis($$.d3, $$.isCategorized()).scale(scale).orient(orient); 33105 33106 // Set tick 33107 axis.tickFormat(tickFormat).tickValues(tickValues); 33108 if ($$.isCategorized()) { 33109 axis.tickCentered(config.axis_x_tick_centered); 33110 if (isEmpty(config.axis_x_tick_culling)) { 33111 config.axis_x_tick_culling = false;
33112 } 33113 } else { 33114 // TODO: move this to c3_axis 33115 axis.tickOffset = function () { 33116 var edgeX = $$.getEdgeX($$.data.targets), diff = $$.x(edgeX[1]) - $$.x(edgeX[0]), 33117 base = diff ? diff : (config.axis_rotated ? $$.height : $$.width); 33118 return (base / $$.getMaxDataCount()) / 2; 33119 }; 33120 } 33121 33122 return axis; 33123 }; 33124 c3_chart_internal_fn.getYAxis = function (scale, orient, tickFormat, ticks) { 33125 return c3_axis(this.d3).scale(scale).orient(orient).tickFormat(tickFormat).ticks(ticks); 33126 }; 33127 c3_chart_internal_fn.getAxisId = function (id) { 33128 var config = this.config; 33129 return id in config.data_axes ? config.data_axes[id] : 'y'; 33130 }; 33131 c3_chart_internal_fn.getXAxisTickFormat = function () { 33132 var $$ = this, config = $$.config, 33133 format = $$.isTimeSeries() ? $$.defaultAxisTimeFormat : $$.isCategorized() ? $$.categoryName : function (v) { return v < 0 ? v.toFixed(0) : v; }; 33134 if (config.axis_x_tick_format) { 33135 if (isFunction(config.axis_x_tick_format)) { 33136 format = config.axis_x_tick_format; 33137 } else if ($$.isTimeSeries()) { 33138 format = function (date) { 33139 return date ? $$.axisTimeFormat(config.axis_x_tick_format)(date) : ""; 33140 }; 33141 } 33142 } 33143 return isFunction(format) ? function (v) { return format.call($$, v); } : format; 33144 }; 33145 c3_chart_internal_fn.getAxisLabelOptionByAxisId = function (axisId) { 33146 var $$ = this, config = $$.config, option; 33147 if (axisId === 'y') { 33148 option = config.axis_y_label; 33149 } else if (axisId === 'y2') { 33150 option = config.axis_y2_label; 33151 } else if (axisId === 'x') { 33152 option = config.axis_x_label; 33153 } 33154 return option; 33155 }; 33156 c3_chart_internal_fn.getAxisLabelText = function (axisId) { 33157 var option = this.getAxisLabelOptionByAxisId(axisId); 33158 return isString(option) ? option : option ? option.text : null; 33159 }; 33160 c3_chart_internal_fn.setAxisLabelText = function (axisId, text) { 33161 var $$ = this, config = $$.config, 33162 option = $$.getAxisLabelOptionByAxisId(axisId); 33163 if (isString(option)) { 33164 if (axisId === 'y') { 33165 config.axis_y_label = text; 33166 } else if (axisId === 'y2') { 33167 config.axis_y2_label = text; 33168 } else if (axisId === 'x') { 33169 config.axis_x_label = text; 33170 } 33171 } else if (option) { 33172 option.text = text; 33173 } 33174 }; 33175 c3_chart_internal_fn.getAxisLabelPosition = function (axisId, defaultPosition) { 33176 var option = this.getAxisLabelOptionByAxisId(axisId), 33177 position = (option && typeof option === 'object' && option.position) ? option.position : defaultPosition; 33178 return { 33179 isInner: position.indexOf('inner') >= 0, 33180 isOuter: position.indexOf('outer') >= 0, 33181 isLeft: position.indexOf('left') >= 0, 33182 isCenter: position.indexOf('center') >= 0, 33183 isRight: position.indexOf('right') >= 0, 33184 isTop: position.indexOf('top') >= 0, 33185 isMiddle: position.indexOf('middle') >= 0, 33186 isBottom: position.indexOf('bottom') >= 0 33187 }; 33188 }; 33189 c3_chart_internal_fn.getXAxisLabelPosition = function () { 33190 return this.getAxisLabelPosition('x', this.config.axis_rotated ? 'inner-top' : 'inner-right'); 33191 }; 33192 c3_chart_internal_fn.getYAxisLabelPosition = function () { 33193 return this.getAxisLabelPosition('y', this.config.axis_rotated ? 'inner-right' : 'inner-top'); 33194 }; 33195 c3_chart_internal_fn.getY2AxisLabelPosition = function () { 33196 return this.getAxisLabelPosition('y2', this.config.axis_rotated ? 'inner-right' : 'inner-top'); 33197 }; 33198 c3_chart_internal_fn.getAxisLabelPositionById = function (id) { 33199 return id === 'y2' ? this.getY2AxisLabelPosition() : id === 'y' ? this.getYAxisLabelPosition() : this.getXAxisLabelPosition(); 33200 }; 33201 c3_chart_internal_fn.textForXAxisLabel = function () { 33202 return this.getAxisLabelText('x'); 33203 }; 33204 c3_chart_internal_fn.textForYAxisLabel = function () { 33205 return this.getAxisLabelText('y'); 33206 }; 33207 c3_chart_internal_fn.textForY2AxisLabel = function () { 33208 return this.getAxisLabelText('y2'); 33209 }; 33210 c3_chart_internal_fn.xForAxisLabel = function (forHorizontal, position) { 33211 var $$ = this; 33212 if (forHorizontal) { 33213 return position.isLeft ? 0 : position.isCenter ? $$.width / 2 : $$.width; 33214 } else { 33215 return position.isBottom ? -$$.height : position.isMiddle ? -$$.height / 2 : 0; 33216 } 33217 }; 33218 c3_chart_internal_fn.dxForAxisLabel = function (forHorizontal, position) { 33219 if (forHorizontal) { 33220 return position.isLeft ? "0.5em" : position.isRight ? "-0.5em" : "0"; 33221 } else { 33222 return position.isTop ? "-0.5em" : position.isBottom ? "0.5em" : "0"; 33223 } 33224 }; 33225 c3_chart_internal_fn.textAnchorForAxisLabel = function (forHorizontal, position) { 33226 if (forHorizontal) { 33227 return position.isLeft ? 'start' : position.isCenter ? 'middle' : 'end'; 33228 } else { 33229 return position.isBottom ? 'start' : position.isMiddle ? 'middle' : 'end'; 33230 } 33231 }; 33232 c3_chart_internal_fn.xForXAxisLabel = function () { 33233 return this.xForAxisLabel(!this.config.axis_rotated, this.getXAxisLabelPosition()); 33234 }; 33235 c3_chart_internal_fn.xForYAxisLabel = function () { 33236 return this.xForAxisLabel(this.config.axis_rotated, this.getYAxisLabelPosition()); 33237 }; 33238 c3_chart_internal_fn.xForY2AxisLabel = function () { 33239 return this.xForAxisLabel(this.config.axis_rotated, this.getY2AxisLabelPosition()); 33240 }; 33241 c3_chart_internal_fn.dxForXAxisLabel = function () { 33242 return this.dxForAxisLabel(!this.config.axis_rotated, this.getXAxisLabelPosition()); 33243 }; 33244 c3_chart_internal_fn.dxForYAxisLabel = function () { 33245 return this.dxForAxisLabel(this.config.axis_rotated, this.getYAxisLabelPosition()); 33246 }; 33247 c3_chart_internal_fn.dxForY2AxisLabel = function () { 33248 return this.dxForAxisLabel(this.config.axis_rotated, this.getY2AxisLabelPosition()); 33249 }; 33250 c3_chart_internal_fn.dyForXAxisLabel = function () {
33251 var $$ = this, config = $$.config, 33252 position = $$.getXAxisLabelPosition(); 33253 if (config.axis_rotated) { 33254 return position.isInner ? "1.2em" : -25 - $$.getMaxTickWidth('x'); 33255 } else { 33256 return position.isInner ? "-0.5em" : config.axis_x_height ? config.axis_x_height - 10 : "3em"; 33257 } 33258 }; 33259 c3_chart_internal_fn.dyForYAxisLabel = function () { 33260 var $$ = this, 33261 position = $$.getYAxisLabelPosition(); 33262 if ($$.config.axis_rotated) { 33263 return position.isInner ? "-0.5em" : "3em"; 33264 } else { 33265 return position.isInner ? "1.2em" : -20 - $$.getMaxTickWidth('y'); 33266 } 33267 }; 33268 c3_chart_internal_fn.dyForY2AxisLabel = function () { 33269 var $$ = this, 33270 position = $$.getY2AxisLabelPosition(); 33271 if ($$.config.axis_rotated) { 33272 return position.isInner ? "1.2em" : "-2.2em"; 33273 } else { 33274 return position.isInner ? "-0.5em" : 30 + this.getMaxTickWidth('y2'); 33275 } 33276 }; 33277 c3_chart_internal_fn.textAnchorForXAxisLabel = function () { 33278 var $$ = this; 33279 return $$.textAnchorForAxisLabel(!$$.config.axis_rotated, $$.getXAxisLabelPosition()); 33280 }; 33281 c3_chart_internal_fn.textAnchorForYAxisLabel = function () { 33282 var $$ = this; 33283 return $$.textAnchorForAxisLabel($$.config.axis_rotated, $$.getYAxisLabelPosition()); 33284 }; 33285 c3_chart_internal_fn.textAnchorForY2AxisLabel = function () { 33286 var $$ = this; 33287 return $$.textAnchorForAxisLabel($$.config.axis_rotated, $$.getY2AxisLabelPosition()); 33288 }; 33289 33290 c3_chart_internal_fn.xForRotatedTickText = function (r) { 33291 return 10 * Math.sin(Math.PI * (r / 180)); 33292 }; 33293 c3_chart_internal_fn.yForRotatedTickText = function (r) { 33294 return 11.5 - 2.5 * (r / 15); 33295 }; 33296 c3_chart_internal_fn.rotateTickText = function (axis, transition, rotate) { 33297 axis.selectAll('.tick text') 33298 .style("text-anchor", "start"); 33299 transition.selectAll('.tick text') 33300 .attr("y", this.yForRotatedTickText(rotate)) 33301 .attr("x", this.xForRotatedTickText(rotate)) 33302 .attr("transform", "rotate(" + rotate + ")"); 33303 }; 33304 33305 c3_chart_internal_fn.getMaxTickWidth = function (id) { 33306 var $$ = this, config = $$.config, 33307 maxWidth = 0, targetsToShow, scale, axis; 33308 if ($$.svg) { 33309 targetsToShow = $$.filterTargetsToShow($$.data.targets); 33310 if (id === 'y') { 33311 scale = $$.y.copy().domain($$.getYDomain(targetsToShow, 'y')); 33312 axis = $$.getYAxis(scale, $$.yOrient, config.axis_y_tick_format, config.axis_y_ticks); 33313 } else if (id === 'y2') { 33314 scale = $$.y2.copy().domain($$.getYDomain(targetsToShow, 'y2')); 33315 axis = $$.getYAxis(scale, $$.y2Orient, config.axis_y2_tick_format, config.axis_y2_ticks); 33316 } else { 33317 scale = $$.x.copy().domain($$.getXDomain(targetsToShow)); 33318 axis = $$.getXAxis(scale, $$.xOrient, $$.getXAxisTickFormat(), config.axis_x_tick_values ? config.axis_x_tick_values : $$.xAxis.tickValues()); 33319 } 33320 $$.main.append("g").call(axis).each(function () { 33321 $$.d3.select(this).selectAll('text').each(function () { 33322 var box = this.getBoundingClientRect(); 33323 if (maxWidth < box.width) { maxWidth = box.width; } 33324 }); 33325 }).remove(); 33326 } 33327 $$.currentMaxTickWidth = maxWidth <= 0 ? $$.currentMaxTickWidth : maxWidth; 33328 return $$.currentMaxTickWidth; 33329 }; 33330 33331 c3_chart_internal_fn.updateAxisLabels = function (withTransition) { 33332 var $$ = this; 33333 var axisXLabel = $$.main.select('.' + CLASS.axisX + ' .' + CLASS.axisXLabel), 33334 axisYLabel = $$.main.select('.' + CLASS.axisY + ' .' + CLASS.axisYLabel), 33335 axisY2Label = $$.main.select('.' + CLASS.axisY2 + ' .' + CLASS.axisY2Label); 33336 (withTransition ? axisXLabel.transition() : axisXLabel) 33337 .attr("x", $$.xForXAxisLabel.bind($$)) 33338 .attr("dx", $$.dxForXAxisLabel.bind($$)) 33339 .attr("dy", $$.dyForXAxisLabel.bind($$)) 33340 .text($$.textForXAxisLabel.bind($$)); 33341 (withTransition ? axisYLabel.transition() : axisYLabel) 33342 .attr("x", $$.xForYAxisLabel.bind($$)) 33343 .attr("dx", $$.dxForYAxisLabel.bind($$)) 33344 .attr("dy", $$.dyForYAxisLabel.bind($$)) 33345 .text($$.textForYAxisLabel.bind($$)); 33346 (withTransition ? axisY2Label.transition() : axisY2Label) 33347 .attr("x", $$.xForY2AxisLabel.bind($$)) 33348 .attr("dx", $$.dxForY2AxisLabel.bind($$)) 33349 .attr("dy", $$.dyForY2AxisLabel.bind($$)) 33350 .text($$.textForY2AxisLabel.bind($$)); 33351 }; 33352 33353 c3_chart_internal_fn.getAxisPadding = function (padding, key, defaultValue, all) { 33354 var ratio = padding.unit === 'ratio' ? all : 1; 33355 return isValue(padding[key]) ? padding[key] * ratio : defaultValue; 33356 }; 33357 33358 c3_chart_internal_fn.generateTickValues = function (xs, tickCount) { 33359 var $$ = this; 33360 var tickValues = xs, targetCount, start, end, count, interval, i, tickValue; 33361 if (tickCount) { 33362 targetCount = isFunction(tickCount) ? tickCount() : tickCount; 33363 // compute ticks according to $$.config.axis_x_tick_count 33364 if (targetCount === 1) { 33365 tickValues = [xs[0]]; 33366 } else if (targetCount === 2) { 33367 tickValues = [xs[0], xs[xs.length - 1]]; 33368 } else if (targetCount > 2) { 33369 count = targetCount - 2; 33370 start = xs[0]; 33371 end = xs[xs.length - 1]; 33372 interval = (end - start) / (count + 1); 33373 // re-construct uniqueXs 33374 tickValues = [start]; 33375 for (i = 0; i < count; i++) { 33376 tickValue = +start + interval * (i + 1); 33377 tickValues.push($$.isTimeSeries() ? new Date(tickValue) : tickValue); 33378 } 33379 tickValues.push(end); 33380 } 33381 } 33382 if (!$$.isTimeSeries()) { tickValues = tickValues.sort(function (a, b) { return a - b; }); } 33383 return tickValues; 33384 }; 33385 c3_chart_internal_fn.generateAxisTransitions = function (duration) { 33386 var $$ = this, axes = $$.axes; 33387 return { 33388 axisX: duration ? axes.x.transition().duration(duration) : axes.x, 33389 axisY: duration ? axes.y.transition().duration(duration) : axes.y, 33390 axisY2: duration ? axes.y2.transition().duration(duration) : axes.y2, 33391 axisSubX: duration ? axes.subx.transition().duration(duration) : axes.subx 33392 }; 33393 }; 33394 c3_chart_internal_fn.redrawAxis = function (transitions, isHidden) { 33395 var $$ = this; 33396 $$.axes.x.style("opacity", isHidden ? 0 : 1); 33397 $$.axes.y.style("opacity", isHidden ? 0 : 1); 33398 $$.axes.y2.style("opacity", isHidden ? 0 : 1); 33399 $$.axes.subx.style("opacity", isHidden ? 0 : 1); 33400 transitions.axisX.call($$.xAxis); 33401 transitions.axisY.call($$.yAxis); 33402 transitions.axisY2.call($$.y2Axis); 33403 transitions.axisSubX.call($$.subXAxis); 33404 }; 33405 33406 c3_chart_internal_fn.getClipPath = function (id) { 33407 var isIE9 = window.navigator.appVersion.toLowerCase().indexOf("msie 9.") >= 0; 33408 return "url(" + (isIE9 ? "" : document.URL.split('#')[0]) + "#" + id + ")"; 33409 }; 33410 c3_chart_internal_fn.getAxisClipX = function (forHorizontal) { 33411 // axis line width + padding for left 33412 return forHorizontal ? -(1 + 30) : -(this.margin.left - 1); 33413 }; 33414 c3_chart_internal_fn.getAxisClipY = function (forHorizontal) { 33415 return forHorizontal ? -20 : -4; 33416 }; 33417 c3_chart_internal_fn.getXAxisClipX = function () { 33418 var $$ = this; 33419 return $$.getAxisClipX(!$$.config.axis_rotated); 33420 }; 33421 c3_chart_internal_fn.getXAxisClipY = function () { 33422 var $$ = this; 33423 return $$.getAxisClipY(!$$.config.axis_rotated); 33424 }; 33425 c3_chart_internal_fn.getYAxisClipX = function () { 33426 var $$ = this; 33427 return $$.getAxisClipX($$.config.axis_rotated); 33428 }; 33429 c3_chart_internal_fn.getYAxisClipY = function () { 33430 var $$ = this; 33431 return $$.getAxisClipY($$.config.axis_rotated); 33432 }; 33433 c3_chart_internal_fn.getAxisClipWidth = function (forHorizontal) { 33434 var $$ = this; 33435 // width + axis line width + padding for left/right 33436 return forHorizontal ? $$.width + 2 + 30 + 30 : $$.margin.left + 20; 33437 }; 33438 c3_chart_internal_fn.getAxisClipHeight = function (forHorizontal) {
33439 var $$ = this, config = $$.config; 33440 return forHorizontal ? (config.axis_x_height ? config.axis_x_height : 0) + 80 : $$.height + 8; 33441 }; 33442 c3_chart_internal_fn.getXAxisClipWidth = function () { 33443 var $$ = this; 33444 return $$.getAxisClipWidth(!$$.config.axis_rotated); 33445 }; 33446 c3_chart_internal_fn.getXAxisClipHeight = function () { 33447 var $$ = this; 33448 return $$.getAxisClipHeight(!$$.config.axis_rotated); 33449 }; 33450 c3_chart_internal_fn.getYAxisClipWidth = function () { 33451 var $$ = this; 33452 return $$.getAxisClipWidth($$.config.axis_rotated); 33453 }; 33454 c3_chart_internal_fn.getYAxisClipHeight = function () { 33455 var $$ = this; 33456 return $$.getAxisClipHeight($$.config.axis_rotated); 33457 }; 33458 33459 c3_chart_internal_fn.initPie = function () { 33460 var $$ = this, d3 = $$.d3, config = $$.config; 33461 $$.pie = d3.layout.pie().value(function (d) { 33462 return d.values.reduce(function (a, b) { return a + b.value; }, 0); 33463 }); 33464 if (!config.data_order || !config.pie_sort || !config.donut_sort) { 33465 $$.pie.sort(null); 33466 } 33467 }; 33468 33469 c3_chart_internal_fn.updateRadius = function () { 33470 var $$ = this, config = $$.config, 33471 w = config.gauge_width || config.donut_width; 33472 $$.radiusExpanded = Math.min($$.arcWidth, $$.arcHeight) / 2; 33473 $$.radius = $$.radiusExpanded * 0.95; 33474 $$.innerRadiusRatio = w ? ($$.radius - w) / $$.radius : 0.6; 33475 $$.innerRadius = $$.hasType('donut') || $$.hasType('gauge') ? $$.radius * $$.innerRadiusRatio : 0; 33476 }; 33477 33478 c3_chart_internal_fn.updateArc = function () { 33479 var $$ = this; 33480 $$.svgArc = $$.getSvgArc(); 33481 $$.svgArcExpanded = $$.getSvgArcExpanded(); 33482 $$.svgArcExpandedSub = $$.getSvgArcExpanded(0.98); 33483 }; 33484 33485 c3_chart_internal_fn.updateAngle = function (d) { 33486 var $$ = this, config = $$.config, 33487 found = false, index = 0; 33488 $$.pie($$.filterTargetsToShow($$.data.targets)).sort($$.descByStartAngle).forEach(function (t) { 33489 if (! found && t.data.id === d.data.id) { 33490 found = true; 33491 d = t; 33492 d.index = index; 33493 } 33494 index++; 33495 }); 33496 if (isNaN(d.endAngle)) { 33497 d.endAngle = d.startAngle; 33498 } 33499 if ($$.isGaugeType(d.data)) { 33500 var gMin = config.gauge_min, gMax = config.gauge_max, 33501 gF = Math.abs(gMin) + gMax, 33502 aTic = (Math.PI) / gF; 33503 d.startAngle = (-1 * (Math.PI / 2)) + (aTic * Math.abs(gMin)); 33504 d.endAngle = d.startAngle + (aTic * ((d.value > gMax) ? gMax : d.value)); 33505 } 33506 return found ? d : null; 33507 }; 33508 33509 c3_chart_internal_fn.getSvgArc = function () { 33510 var $$ = this,
33511 arc = $$.d3.svg.arc().outerRadius($$.radius).innerRadius($$.innerRadius), 33512 newArc = function (d, withoutUpdate) { 33513 var updated; 33514 if (withoutUpdate) { return arc(d); } // for interpolate 33515 updated = $$.updateAngle(d); 33516 return updated ? arc(updated) : "M 0 0"; 33517 }; 33518 // TODO: extends all function 33519 newArc.centroid = arc.centroid; 33520 return newArc; 33521 }; 33522 33523 c3_chart_internal_fn.getSvgArcExpanded = function (rate) { 33524 var $$ = this, 33525 arc = $$.d3.svg.arc().outerRadius($$.radiusExpanded * (rate ? rate : 1)).innerRadius($$.innerRadius); 33526 return function (d) { 33527 var updated = $$.updateAngle(d); 33528 return updated ? arc(updated) : "M 0 0"; 33529 }; 33530 }; 33531 33532 c3_chart_internal_fn.getArc = function (d, withoutUpdate, force) { 33533 return force || this.isArcType(d.data) ? this.svgArc(d, withoutUpdate) : "M 0 0"; 33534 }; 33535 33536 33537 c3_chart_internal_fn.transformForArcLabel = function (d) { 33538 var $$ = this, 33539 updated = $$.updateAngle(d), c, x, y, h, ratio, translate = ""; 33540 if (updated && !$$.hasType('gauge')) { 33541 c = this.svgArc.centroid(updated); 33542 x = isNaN(c[0]) ? 0 : c[0]; 33543 y = isNaN(c[1]) ? 0 : c[1]; 33544 h = Math.sqrt(x * x + y * y); 33545 // TODO: ratio should be an option? 33546 ratio = $$.radius && h ? (36 / $$.radius > 0.375 ? 1.175 - 36 / $$.radius : 0.8) * $$.radius / h : 0; 33547 translate = "translate(" + (x * ratio) + ',' + (y * ratio) + ")"; 33548 } 33549 return translate; 33550 }; 33551 33552 c3_chart_internal_fn.getArcRatio = function (d) { 33553 var $$ = this, 33554 whole = $$.hasType('gauge') ? Math.PI : (Math.PI * 2); 33555 return d ? (d.endAngle - d.startAngle) / whole : null; 33556 }; 33557 33558 c3_chart_internal_fn.convertToArcData = function (d) { 33559 return this.addName({ 33560 id: d.data.id, 33561 value: d.value, 33562 ratio: this.getArcRatio(d), 33563 index: d.index 33564 }); 33565 }; 33566 33567 c3_chart_internal_fn.textForArcLabel = function (d) { 33568 var $$ = this, 33569 updated, value, ratio, format; 33570 if (! $$.shouldShowArcLabel()) { return ""; } 33571 updated = $$.updateAngle(d); 33572 value = updated ? updated.value : null; 33573 ratio = $$.getArcRatio(updated); 33574 if (! $$.hasType('gauge') && ! $$.meetsArcLabelThreshold(ratio)) { return ""; } 33575 format = $$.getArcLabelFormat(); 33576 return format ? format(value, ratio) : $$.defaultArcValueFormat(value, ratio); 33577 }; 33578 33579 c3_chart_internal_fn.expandArc = function (id, withoutFadeOut) { 33580 var $$ = this, 33581 target = $$.svg.selectAll('.' + CLASS.chartArc + $$.selectorTarget(id)), 33582 noneTargets = $$.svg.selectAll('.' + CLASS.arc).filter(function (data) { return data.data.id !== id; }); 33583 33584 if ($$.shouldExpand(id)) { 33585 target.selectAll('path') 33586 .transition().duration(50) 33587 .attr("d", $$.svgArcExpanded) 33588 .transition().duration(100) 33589 .attr("d", $$.svgArcExpandedSub) 33590 .each(function (d) { 33591 if ($$.isDonutType(d.data)) { 33592 // callback here 33593 } 33594 }); 33595 } 33596 if (!withoutFadeOut) { 33597 noneTargets.style("opacity", 0.3); 33598 } 33599 }; 33600 33601 c3_chart_internal_fn.unexpandArc = function (id) { 33602 var $$ = this, 33603 target = $$.svg.selectAll('.' + CLASS.chartArc + $$.selectorTarget(id)); 33604 target.selectAll('path.' + CLASS.arc) 33605 .transition().duration(50) 33606 .attr("d", $$.svgArc); 33607 $$.svg.selectAll('.' + CLASS.arc) 33608 .style("opacity", 1); 33609 }; 33610 33611 c3_chart_internal_fn.shouldExpand = function (id) { 33612 var $$ = this, config = $$.config; 33613 return ($$.isDonutType(id) && config.donut_expand) || ($$.isGaugeType(id) && config.gauge_expand) || ($$.isPieType(id) && config.pie_expand); 33614 }; 33615 33616 c3_chart_internal_fn.shouldShowArcLabel = function () {
33617 var $$ = this, config = $$.config, shouldShow = true; 33618 if ($$.hasType('donut')) { 33619 shouldShow = config.donut_label_show; 33620 } else if ($$.hasType('pie')) { 33621 shouldShow = config.pie_label_show; 33622 } 33623 // when gauge, always true 33624 return shouldShow; 33625 }; 33626 33627 c3_chart_internal_fn.meetsArcLabelThreshold = function (ratio) { 33628 var $$ = this, config = $$.config, 33629 threshold = $$.hasType('donut') ? config.donut_label_threshold : config.pie_label_threshold; 33630 return ratio >= threshold; 33631 }; 33632 33633 c3_chart_internal_fn.getArcLabelFormat = function () { 33634 var $$ = this, config = $$.config, 33635 format = config.pie_label_format; 33636 if ($$.hasType('gauge')) { 33637 format = config.gauge_label_format; 33638 } else if ($$.hasType('donut')) { 33639 format = config.donut_label_format; 33640 } 33641 return format; 33642 }; 33643 33644 c3_chart_internal_fn.getArcTitle = function () { 33645 var $$ = this; 33646 return $$.hasType('donut') ? $$.config.donut_title : ""; 33647 }; 33648 33649 c3_chart_internal_fn.descByStartAngle = function (a, b) { 33650 return a.startAngle - b.startAngle; 33651 }; 33652 33653 c3_chart_internal_fn.updateTargetsForArc = function (targets) { 33654 var $$ = this, main = $$.main,
33655 mainPieUpdate, mainPieEnter, 33656 classChartArc = $$.classChartArc.bind($$), 33657 classArcs = $$.classArcs.bind($$); 33658 mainPieUpdate = main.select('.' + CLASS.chartArcs).selectAll('.' + CLASS.chartArc) 33659 .data($$.pie(targets)) 33660 .attr("class", classChartArc); 33661 mainPieEnter = mainPieUpdate.enter().append("g") 33662 .attr("class", classChartArc); 33663 mainPieEnter.append('g') 33664 .attr('class', classArcs); 33665 mainPieEnter.append("text") 33666 .attr("dy", $$.hasType('gauge') ? "-0.35em" : ".35em") 33667 .style("opacity", 0) 33668 .style("text-anchor", "middle") 33669 .style("pointer-events", "none"); 33670 // MEMO: can not keep same color..., but not bad to update color in redraw 33671 //mainPieUpdate.exit().remove(); 33672 }; 33673 33674 c3_chart_internal_fn.initArc = function () { 33675 var $$ = this; 33676 $$.arcs = $$.main.select('.' + CLASS.chart).append("g") 33677 .attr("class", CLASS.chartArcs) 33678 .attr("transform", $$.getTranslate('arc')); 33679 $$.arcs.append('text') 33680 .attr('class', CLASS.chartArcsTitle) 33681 .style("text-anchor", "middle") 33682 .text($$.getArcTitle()); 33683 }; 33684 33685 c3_chart_internal_fn.redrawArc = function (duration, durationForExit, withTransform) { 33686 var $$ = this, d3 = $$.d3, config = $$.config, main = $$.main, 33687 mainArc; 33688 mainArc = main.selectAll('.' + CLASS.arcs).selectAll('.' + CLASS.arc) 33689 .data($$.arcData.bind($$)); 33690 mainArc.enter().append('path') 33691 .attr("class", $$.classArc.bind($$)) 33692 .style("fill", function (d) { return $$.color(d.data); }) 33693 .style("cursor", function (d) { return config.data_selection_isselectable(d) ? "pointer" : null; }) 33694 .style("opacity", 0) 33695 .each(function (d) { 33696 if ($$.isGaugeType(d.data)) { 33697 d.startAngle = d.endAngle = -1 * (Math.PI / 2); 33698 } 33699 this._current = d; 33700 }) 33701 .on('mouseover', function (d) { 33702 var updated, arcData; 33703 if ($$.transiting) { // skip while transiting 33704 return; 33705 } 33706 updated = $$.updateAngle(d); 33707 arcData = $$.convertToArcData(updated); 33708 // transitions 33709 $$.expandArc(updated.data.id); 33710 $$.toggleFocusLegend(updated.data.id, true); 33711 $$.config.data_onmouseover(arcData, this); 33712 }) 33713 .on('mousemove', function (d) { 33714 var updated = $$.updateAngle(d), 33715 arcData = $$.convertToArcData(updated), 33716 selectedData = [arcData]; 33717 $$.showTooltip(selectedData, d3.mouse(this)); 33718 }) 33719 .on('mouseout', function (d) { 33720 var updated, arcData; 33721 if ($$.transiting) { // skip while transiting 33722 return; 33723 } 33724 updated = $$.updateAngle(d); 33725 arcData = $$.convertToArcData(updated); 33726 // transitions 33727 $$.unexpandArc(updated.data.id); 33728 $$.revertLegend(); 33729 $$.hideTooltip(); 33730 $$.config.data_onmouseout(arcData, this); 33731 }) 33732 .on('click', function (d, i) { 33733 var updated, arcData; 33734 if (!$$.toggleShape) { 33735 return; 33736 } 33737 updated = $$.updateAngle(d); 33738 arcData = $$.convertToArcData(updated); 33739 $$.toggleShape(this, arcData, i); // onclick called in toogleShape() 33740 }); 33741 mainArc 33742 .attr("transform", function (d) { return !$$.isGaugeType(d.data) && withTransform ? "scale(0)" : ""; }) 33743 .style("opacity", function (d) { return d === this._current ? 0 : 1; }) 33744 .each(function () { $$.transiting = true; }) 33745 .transition().duration(duration) 33746 .attrTween("d", function (d) { 33747 var updated = $$.updateAngle(d), interpolate; 33748 if (! updated) { 33749 return function () { return "M 0 0"; }; 33750 } 33751 // if (this._current === d) { 33752 // this._current = { 33753 // startAngle: Math.PI*2, 33754 // endAngle: Math.PI*2, 33755 // }; 33756 // } 33757 if (isNaN(this._current.endAngle)) { 33758 this._current.endAngle = this._current.startAngle; 33759 } 33760 interpolate = d3.interpolate(this._current, updated); 33761 this._current = interpolate(0); 33762 return function (t) { return $$.getArc(interpolate(t), true); }; 33763 }) 33764 .attr("transform", withTransform ? "scale(1)" : "") 33765 .style("fill", function (d) { 33766 return $$.levelColor ? $$.levelColor(d.data.values[0].value) : $$.color(d.data.id); 33767 }) // Where gauge reading color would receive customization. 33768 .style("opacity", 1) 33769 .call($$.endall, function () { 33770 $$.transiting = false;
33771 }); 33772 mainArc.exit().transition().duration(durationForExit) 33773 .style('opacity', 0) 33774 .remove(); 33775 main.selectAll('.' + CLASS.chartArc).select('text') 33776 .style("opacity", 0) 33777 .attr('class', function (d) { return $$.isGaugeType(d.data) ? CLASS.gaugeValue : ''; }) 33778 .text($$.textForArcLabel.bind($$)) 33779 .attr("transform", $$.transformForArcLabel.bind($$)) 33780 .transition().duration(duration) 33781 .style("opacity", function (d) { return $$.isTargetToShow(d.data.id) && $$.isArcType(d.data) ? 1 : 0; }); 33782 main.select('.' + CLASS.chartArcsTitle) 33783 .style("opacity", $$.hasType('donut') || $$.hasType('gauge') ? 1 : 0); 33784 33785 }; 33786 c3_chart_internal_fn.initGauge = function () { 33787 var $$ = this, config = $$.config, arcs = $$.arcs; 33788 if ($$.hasType('gauge')) { 33789 arcs.append('path') 33790 .attr("class", CLASS.chartArcsBackground) 33791 .attr("d", function () { 33792 var d = { 33793 data: [{value: config.gauge_max}], 33794 startAngle: -1 * (Math.PI / 2), 33795 endAngle: Math.PI / 2 33796 }; 33797 return $$.getArc(d, true, true); 33798 }); 33799 arcs.append("text") 33800 .attr("dy", ".75em") 33801 .attr("class", CLASS.chartArcsGaugeUnit) 33802 .style("text-anchor", "middle") 33803 .style("pointer-events", "none") 33804 .text(config.gauge_label_show ? config.gauge_units : ''); 33805 arcs.append("text") 33806 .attr("dx", -1 * ($$.innerRadius + (($$.radius - $$.innerRadius) / 2)) + "px") 33807 .attr("dy", "1.2em") 33808 .attr("class", CLASS.chartArcsGaugeMin) 33809 .style("text-anchor", "middle") 33810 .style("pointer-events", "none") 33811 .text(config.gauge_label_show ? config.gauge_min : ''); 33812 arcs.append("text") 33813 .attr("dx", $$.innerRadius + (($$.radius - $$.innerRadius) / 2) + "px") 33814 .attr("dy", "1.2em") 33815 .attr("class", CLASS.chartArcsGaugeMax) 33816 .style("text-anchor", "middle") 33817 .style("pointer-events", "none") 33818 .text(config.gauge_label_show ? config.gauge_max : ''); 33819 } 33820 }; 33821 33822 c3_chart_internal_fn.initRegion = function () { 33823 var $$ = this; 33824 $$.main.append('g') 33825 .attr("clip-path", $$.clipPath) 33826 .attr("class", CLASS.regions); 33827 }; 33828 c3_chart_internal_fn.redrawRegion = function (duration) { 33829 var $$ = this, config = $$.config; 33830 $$.mainRegion = $$.main.select('.' + CLASS.regions).selectAll('.' + CLASS.region) 33831 .data(config.regions); 33832 $$.mainRegion.enter().append('g') 33833 .attr('class', $$.classRegion.bind($$)) 33834 .append('rect') 33835 .style("fill-opacity", 0); 33836 $$.mainRegion.exit().transition().duration(duration) 33837 .style("opacity", 0) 33838 .remove(); 33839 }; 33840 c3_chart_internal_fn.addTransitionForRegion = function (transitions) { 33841 var $$ = this, 33842 x = $$.regionX.bind($$), 33843 y = $$.regionY.bind($$), 33844 w = $$.regionWidth.bind($$), 33845 h = $$.regionHeight.bind($$); 33846 transitions.push($$.mainRegion.selectAll('rect').transition() 33847 .attr("x", x) 33848 .attr("y", y) 33849 .attr("width", w) 33850 .attr("height", h) 33851 .style("fill-opacity", function (d) { return isValue(d.opacity) ? d.opacity : 0.1; })); 33852 }; 33853 c3_chart_internal_fn.regionX = function (d) { 33854 var $$ = this, config = $$.config, 33855 xPos, yScale = d.axis === 'y' ? $$.y : $$.y2; 33856 if (d.axis === 'y' || d.axis === 'y2') { 33857 xPos = config.axis_rotated ? ('start' in d ? yScale(d.start) : 0) : 0; 33858 } else { 33859 xPos = config.axis_rotated ? 0 : ('start' in d ? $$.x($$.isTimeSeries() ? $$.parseDate(d.start) : d.start) : 0); 33860 } 33861 return xPos; 33862 }; 33863 c3_chart_internal_fn.regionY = function (d) {
33864 var $$ = this, config = $$.config, 33865 yPos, yScale = d.axis === 'y' ? $$.y : $$.y2; 33866 if (d.axis === 'y' || d.axis === 'y2') { 33867 yPos = config.axis_rotated ? 0 : ('end' in d ? yScale(d.end) : 0); 33868 } else { 33869 yPos = config.axis_rotated ? ('start' in d ? $$.x($$.isTimeSeries() ? $$.parseDate(d.start) : d.start) : 0) : 0; 33870 } 33871 return yPos; 33872 }; 33873 c3_chart_internal_fn.regionWidth = function (d) { 33874 var $$ = this, config = $$.config, 33875 start = $$.regionX(d), end, yScale = d.axis === 'y' ? $$.y : $$.y2; 33876 if (d.axis === 'y' || d.axis === 'y2') { 33877 end = config.axis_rotated ? ('end' in d ? yScale(d.end) : $$.width) : $$.width; 33878 } else { 33879 end = config.axis_rotated ? $$.width : ('end' in d ? $$.x($$.isTimeSeries() ? $$.parseDate(d.end) : d.end) : $$.width); 33880 } 33881 return end < start ? 0 : end - start; 33882 }; 33883 c3_chart_internal_fn.regionHeight = function (d) { 33884 var $$ = this, config = $$.config, 33885 start = this.regionY(d), end, yScale = d.axis === 'y' ? $$.y : $$.y2; 33886 if (d.axis === 'y' || d.axis === 'y2') { 33887 end = config.axis_rotated ? $$.height : ('start' in d ? yScale(d.start) : $$.height); 33888 } else { 33889 end = config.axis_rotated ? ('end' in d ? $$.x($$.isTimeSeries() ? $$.parseDate(d.end) : d.end) : $$.height) : $$.height; 33890 } 33891 return end < start ? 0 : end - start; 33892 }; 33893 c3_chart_internal_fn.isRegionOnX = function (d) { 33894 return !d.axis || d.axis === 'x'; 33895 }; 33896 33897 c3_chart_internal_fn.drag = function (mouse) { 33898 var $$ = this, config = $$.config, main = $$.main, d3 = $$.d3; 33899 var sx, sy, mx, my, minX, maxX, minY, maxY; 33900 33901 if ($$.hasArcType()) { return; } 33902 if (! config.data_selection_enabled) { return; } // do nothing if not selectable 33903 if (config.zoom_enabled && ! $$.zoom.altDomain) { return; } // skip if zoomable because of conflict drag dehavior 33904 if (!config.data_selection_multiple) { return; } // skip when single selection because drag is used for multiple selection 33905 33906 sx = $$.dragStart[0]; 33907 sy = $$.dragStart[1]; 33908 mx = mouse[0]; 33909 my = mouse[1]; 33910 minX = Math.min(sx, mx); 33911 maxX = Math.max(sx, mx); 33912 minY = (config.data_selection_grouped) ? $$.margin.top : Math.min(sy, my); 33913 maxY = (config.data_selection_grouped) ? $$.height : Math.max(sy, my); 33914 33915 main.select('.' + CLASS.dragarea) 33916 .attr('x', minX) 33917 .attr('y', minY) 33918 .attr('width', maxX - minX) 33919 .attr('height', maxY - minY); 33920 // TODO: binary search when multiple xs 33921 main.selectAll('.' + CLASS.shapes).selectAll('.' + CLASS.shape) 33922 .filter(function (d) { return config.data_selection_isselectable(d); }) 33923 .each(function (d, i) { 33924 var shape = d3.select(this), 33925 isSelected = shape.classed(CLASS.SELECTED), 33926 isIncluded = shape.classed(CLASS.INCLUDED), 33927 _x, _y, _w, _h, toggle, isWithin = false, box; 33928 if (shape.classed(CLASS.circle)) { 33929 _x = shape.attr("cx") * 1; 33930 _y = shape.attr("cy") * 1; 33931 toggle = $$.togglePoint; 33932 isWithin = minX < _x && _x < maxX && minY < _y && _y < maxY; 33933 } 33934 else if (shape.classed(CLASS.bar)) { 33935 box = getPathBox(this); 33936 _x = box.x; 33937 _y = box.y; 33938 _w = box.width; 33939 _h = box.height; 33940 toggle = $$.toggleBar; 33941 isWithin = !(maxX < _x || _x + _w < minX) && !(maxY < _y || _y + _h < minY); 33942 } else { 33943 // line/area selection not supported yet 33944 return; 33945 } 33946 if (isWithin ^ isIncluded) { 33947 shape.classed(CLASS.INCLUDED, !isIncluded); 33948 // TODO: included/unincluded callback here 33949 shape.classed(CLASS.SELECTED, !isSelected); 33950 toggle.call($$, !isSelected, shape, d, i); 33951 } 33952 }); 33953 }; 33954 33955 c3_chart_internal_fn.dragstart = function (mouse) {
33956 var $$ = this, config = $$.config; 33957 if ($$.hasArcType()) { return; } 33958 if (! config.data_selection_enabled) { return; } // do nothing if not selectable 33959 $$.dragStart = mouse; 33960 $$.main.select('.' + CLASS.chart).append('rect') 33961 .attr('class', CLASS.dragarea) 33962 .style('opacity', 0.1); 33963 $$.dragging = true; 33964 $$.config.data_ondragstart(); 33965 }; 33966 33967 c3_chart_internal_fn.dragend = function () { 33968 var $$ = this, config = $$.config; 33969 if ($$.hasArcType()) { return; } 33970 if (! config.data_selection_enabled) { return; } // do nothing if not selectable 33971 $$.main.select('.' + CLASS.dragarea) 33972 .transition().duration(100) 33973 .style('opacity', 0) 33974 .remove(); 33975 $$.main.selectAll('.' + CLASS.shape) 33976 .classed(CLASS.INCLUDED, false); 33977 $$.dragging = false; 33978 $$.config.data_ondragend(); 33979 }; 33980 33981 33982 c3_chart_internal_fn.selectPoint = function (target, d, i) { 33983 var $$ = this, config = $$.config, 33984 cx = (config.axis_rotated ? $$.circleY : $$.circleX).bind($$), 33985 cy = (config.axis_rotated ? $$.circleX : $$.circleY).bind($$), 33986 r = $$.pointSelectR.bind($$); 33987 config.data_onselected.call($$.api, d, target.node()); 33988 // add selected-circle on low layer g 33989 $$.main.select('.' + CLASS.selectedCircles + $$.getTargetSelectorSuffix(d.id)).selectAll('.' + CLASS.selectedCircle + '-' + i) 33990 .data([d]) 33991 .enter().append('circle') 33992 .attr("class", function () { return $$.generateClass(CLASS.selectedCircle, i); }) 33993 .attr("cx", cx) 33994 .attr("cy", cy) 33995 .attr("stroke", function () { return $$.color(d); }) 33996 .attr("r", function (d) { return $$.pointSelectR(d) * 1.4; }) 33997 .transition().duration(100) 33998 .attr("r", r); 33999 }; 34000 c3_chart_internal_fn.unselectPoint = function (target, d, i) { 34001 var $$ = this; 34002 $$.config.data_onunselected(d, target.node()); 34003 // remove selected-circle from low layer g 34004 $$.main.select('.' + CLASS.selectedCircles + $$.getTargetSelectorSuffix(d.id)).selectAll('.' + CLASS.selectedCircle + '-' + i) 34005 .transition().duration(100).attr('r', 0) 34006 .remove(); 34007 }; 34008 c3_chart_internal_fn.togglePoint = function (selected, target, d, i) { 34009 selected ? this.selectPoint(target, d, i) : this.unselectPoint(target, d, i); 34010 }; 34011 c3_chart_internal_fn.selectBar = function (target, d) { 34012 var $$ = this; 34013 $$.config.data_onselected.call($$, d, target.node()); 34014 target.transition().duration(100) 34015 .style("fill", function () { return $$.d3.rgb($$.color(d)).brighter(0.75); }); 34016 }; 34017 c3_chart_internal_fn.unselectBar = function (target, d) { 34018 var $$ = this; 34019 $$.config.data_onunselected.call($$, d, target.node()); 34020 target.transition().duration(100) 34021 .style("fill", function () { return $$.color(d); }); 34022 }; 34023 c3_chart_internal_fn.toggleBar = function (selected, target, d, i) { 34024 selected ? this.selectBar(target, d, i) : this.unselectBar(target, d, i); 34025 }; 34026 c3_chart_internal_fn.toggleArc = function (selected, target, d, i) { 34027 this.toggleBar(selected, target, d.data, i); 34028 }; 34029 c3_chart_internal_fn.getToggle = function (that) { 34030 var $$ = this; 34031 // path selection not supported yet 34032 return that.nodeName === 'circle' ? $$.togglePoint : ($$.d3.select(that).classed(CLASS.bar) ? $$.toggleBar : $$.toggleArc); 34033 }; 34034 c3_chart_internal_fn.toggleShape = function (that, d, i) { 34035 var $$ = this, d3 = $$.d3, config = $$.config, 34036 shape = d3.select(that), isSelected = shape.classed(CLASS.SELECTED), isWithin, toggle; 34037 if (that.nodeName === 'circle') { 34038 isWithin = $$.isWithinCircle(that, $$.pointSelectR(d) * 1.5); 34039 toggle = $$.togglePoint; 34040 } 34041 else if (that.nodeName === 'path') { 34042 if (shape.classed(CLASS.bar)) { 34043 isWithin = $$.isWithinBar(that); 34044 toggle = $$.toggleBar; 34045 } else { // would be arc 34046 isWithin = true; 34047 toggle = $$.toggleArc; 34048 } 34049 } 34050 if (config.data_selection_grouped || isWithin) { 34051 if (config.data_selection_enabled && config.data_selection_isselectable(d)) { 34052 if (!config.data_selection_multiple) { 34053 $$.main.selectAll('.' + CLASS.shapes + (config.data_selection_grouped ? $$.getTargetSelectorSuffix(d.id) : "")).selectAll('.' + CLASS.shape).each(function (d, i) { 34054 var shape = d3.select(this); 34055 if (shape.classed(CLASS.SELECTED)) { toggle.call($$, false, shape.classed(CLASS.SELECTED, false), d, i); } 34056 }); 34057 } 34058 shape.classed(CLASS.SELECTED, !isSelected); 34059 toggle.call($$, !isSelected, shape, d, i); 34060 } 34061 $$.config.data_onclick.call($$.api, d, that); 34062 } 34063 }; 34064 34065 c3_chart_internal_fn.initBrush = function () { 34066 var $$ = this, d3 = $$.d3; 34067 $$.brush = d3.svg.brush().on("brush", function () { $$.redrawForBrush(); }); 34068 $$.brush.update = function () { 34069 if ($$.context) { $$.context.select('.' + CLASS.brush).call(this); } 34070 return this; 34071 }; 34072 $$.brush.scale = function (scale) { 34073 return $$.config.axis_rotated ? this.y(scale) : this.x(scale); 34074 }; 34075 }; 34076 c3_chart_internal_fn.initSubchart = function () {
34077 var $$ = this, config = $$.config, 34078 context = $$.context = $$.svg.append("g").attr("transform", $$.getTranslate('context')); 34079 34080 if (!config.subchart_show) { 34081 context.style('visibility', 'hidden'); 34082 } 34083 34084 // Define g for chart area 34085 context.append('g') 34086 .attr("clip-path", $$.clipPath) 34087 .attr('class', CLASS.chart); 34088 34089 // Define g for bar chart area 34090 context.select('.' + CLASS.chart).append("g") 34091 .attr("class", CLASS.chartBars); 34092 34093 // Define g for line chart area 34094 context.select('.' + CLASS.chart).append("g") 34095 .attr("class", CLASS.chartLines); 34096 34097 // Add extent rect for Brush 34098 context.append("g") 34099 .attr("clip-path", $$.clipPath) 34100 .attr("class", CLASS.brush) 34101 .call($$.brush) 34102 .selectAll("rect") 34103 .attr(config.axis_rotated ? "width" : "height", config.axis_rotated ? $$.width2 : $$.height2); 34104 34105 // ATTENTION: This must be called AFTER chart added 34106 // Add Axis 34107 $$.axes.subx = context.append("g") 34108 .attr("class", CLASS.axisX) 34109 .attr("transform", $$.getTranslate('subx')) 34110 .attr("clip-path", config.axis_rotated ? "" : $$.clipPathForXAxis); 34111 }; 34112 c3_chart_internal_fn.updateTargetsForSubchart = function (targets) { 34113 var $$ = this, context = $$.context, config = $$.config, 34114 contextLineEnter, contextLineUpdate, contextBarEnter, contextBarUpdate, 34115 classChartBar = $$.classChartBar.bind($$), 34116 classBars = $$.classBars.bind($$), 34117 classChartLine = $$.classChartLine.bind($$), 34118 classLines = $$.classLines.bind($$), 34119 classAreas = $$.classAreas.bind($$); 34120 34121 if (config.subchart_show) { 34122 contextBarUpdate = context.select('.' + CLASS.chartBars).selectAll('.' + CLASS.chartBar) 34123 .data(targets) 34124 .attr('class', classChartBar); 34125 contextBarEnter = contextBarUpdate.enter().append('g') 34126 .style('opacity', 0) 34127 .attr('class', classChartBar); 34128 // Bars for each data 34129 contextBarEnter.append('g') 34130 .attr("class", classBars); 34131 34132 //-- Line --// 34133 contextLineUpdate = context.select('.' + CLASS.chartLines).selectAll('.' + CLASS.chartLine) 34134 .data(targets) 34135 .attr('class', classChartLine); 34136 contextLineEnter = contextLineUpdate.enter().append('g') 34137 .style('opacity', 0) 34138 .attr('class', classChartLine); 34139 // Lines for each data 34140 contextLineEnter.append("g") 34141 .attr("class", classLines); 34142 // Area 34143 contextLineEnter.append("g") 34144 .attr("class", classAreas); 34145 } 34146 }; 34147 c3_chart_internal_fn.redrawSubchart = function (withSubchart, transitions, duration, durationForExit, areaIndices, barIndices, lineIndices) { 34148 var $$ = this, d3 = $$.d3, context = $$.context, config = $$.config, 34149 contextLine, contextArea, contextBar, drawAreaOnSub, drawBarOnSub, drawLineOnSub, 34150 barData = $$.barData.bind($$), 34151 lineData = $$.lineData.bind($$), 34152 classBar = $$.classBar.bind($$), 34153 classLine = $$.classLine.bind($$), 34154 classArea = $$.classArea.bind($$), 34155 initialOpacity = $$.initialOpacity.bind($$); 34156 34157 // subchart 34158 if (config.subchart_show) { 34159 // reflect main chart to extent on subchart if zoomed 34160 if (d3.event && d3.event.type === 'zoom') { 34161 $$.brush.extent($$.x.orgDomain()).update(); 34162 } 34163 // update subchart elements if needed 34164 if (withSubchart) { 34165 34166 // rotate tick text if needed 34167 if (!config.axis_rotated && config.axis_x_tick_rotate) { 34168 $$.rotateTickText($$.axes.subx, transitions.axisSubX, config.axis_x_tick_rotate); 34169 } 34170 34171 // extent rect 34172 if (!$$.brush.empty()) { 34173 $$.brush.extent($$.x.orgDomain()).update(); 34174 } 34175 // setup drawer - MEMO: this must be called after axis updated 34176 drawAreaOnSub = $$.generateDrawArea(areaIndices, true); 34177 drawBarOnSub = $$.generateDrawBar(barIndices, true); 34178 drawLineOnSub = $$.generateDrawLine(lineIndices, true); 34179 // bars 34180 contextBar = context.selectAll('.' + CLASS.bars).selectAll('.' + CLASS.bar) 34181 .data(barData); 34182 contextBar.enter().append('path') 34183 .attr("class", classBar) 34184 .style("stroke", 'none') 34185 .style("fill", $$.color); 34186 contextBar 34187 .style("opacity", initialOpacity) 34188 .transition().duration(duration) 34189 .attr('d', drawBarOnSub) 34190 .style('opacity', 1); 34191 contextBar.exit().transition().duration(duration) 34192 .style('opacity', 0) 34193 .remove(); 34194 // lines 34195 contextLine = context.selectAll('.' + CLASS.lines).selectAll('.' + CLASS.line) 34196 .data(lineData); 34197 contextLine.enter().append('path') 34198 .attr('class', classLine) 34199 .style('stroke', $$.color); 34200 contextLine 34201 .style("opacity", initialOpacity) 34202 .transition().duration(duration) 34203 .attr("d", drawLineOnSub) 34204 .style('opacity', 1); 34205 contextLine.exit().transition().duration(duration) 34206 .style('opacity', 0) 34207 .remove(); 34208 // area 34209 contextArea = context.selectAll('.' + CLASS.areas).selectAll('.' + CLASS.area) 34210 .data(lineData); 34211 contextArea.enter().append('path') 34212 .attr("class", classArea) 34213 .style("fill", $$.color) 34214 .style("opacity", function () { $$.orgAreaOpacity = +d3.select(this).style('opacity'); return 0; }); 34215 contextArea 34216 .style("opacity", 0) 34217 .transition().duration(duration) 34218 .attr("d", drawAreaOnSub) 34219 .style("fill", $$.color) 34220 .style("opacity", $$.orgAreaOpacity); 34221 contextArea.exit().transition().duration(durationForExit) 34222 .style('opacity', 0) 34223 .remove(); 34224 } 34225 } 34226 }; 34227 c3_chart_internal_fn.redrawForBrush = function () { 34228 var $$ = this, x = $$.x; 34229 $$.redraw({ 34230 withTransition: false, 34231 withY: false, 34232 withSubchart: false, 34233 withUpdateXDomain: true 34234 }); 34235 $$.config.subchart_onbrush.call($$.api, x.orgDomain()); 34236 }; 34237 c3_chart_internal_fn.transformContext = function (withTransition, transitions) { 34238 var $$ = this, subXAxis; 34239 if (transitions && transitions.axisSubX) { 34240 subXAxis = transitions.axisSubX; 34241 } else { 34242 subXAxis = $$.context.select('.' + CLASS.axisX); 34243 if (withTransition) { subXAxis = subXAxis.transition(); } 34244 } 34245 $$.context.attr("transform", $$.getTranslate('context')); 34246 subXAxis.attr("transform", $$.getTranslate('subx')); 34247 }; 34248 34249 c3_chart_internal_fn.initZoom = function () { 34250 var $$ = this, d3 = $$.d3, config = $$.config; 34251 $$.zoom = d3.behavior.zoom() 34252 .on("zoomstart", function () { 34253 $$.zoom.altDomain = d3.event.sourceEvent.altKey ? $$.x.orgDomain() : null; 34254 }) 34255 .on("zoom", function () { $$.redrawForZoom.call($$); }); 34256 $$.zoom.scale = function (scale) { 34257 return config.axis_rotated ? this.y(scale) : this.x(scale); 34258 }; 34259 $$.zoom.orgScaleExtent = function () { 34260 var extent = config.zoom_extent ? config.zoom_extent : [1, 10]; 34261 return [extent[0], Math.max($$.getMaxDataCount() / extent[1], extent[1])]; 34262 }; 34263 $$.zoom.updateScaleExtent = function () { 34264 var ratio = diffDomain($$.x.orgDomain()) / diffDomain($$.orgXDomain), 34265 extent = this.orgScaleExtent(); 34266 this.scaleExtent([extent[0] * ratio, extent[1] * ratio]); 34267 return this; 34268 }; 34269 }; 34270 c3_chart_internal_fn.updateZoom = function () { 34271 var $$ = this, z = $$.config.zoom_enabled ? $$.zoom : function () {}; 34272 $$.main.select('.' + CLASS.zoomRect).call(z); 34273 $$.main.selectAll('.' + CLASS.eventRect).call(z); 34274 }; 34275 c3_chart_internal_fn.redrawForZoom = function () { 34276 var $$ = this, d3 = $$.d3, config = $$.config, zoom = $$.zoom, x = $$.x, orgXDomain = $$.orgXDomain; 34277 if (!config.zoom_enabled) { 34278 return; 34279 } 34280 if ($$.filterTargetsToShow($$.data.targets).length === 0) { 34281 return; 34282 } 34283 if (d3.event.sourceEvent.type === 'mousemove' && zoom.altDomain) { 34284 x.domain(zoom.altDomain);
34285 zoom.scale(x).updateScaleExtent(); 34286 return; 34287 } 34288 if ($$.isCategorized() && x.orgDomain()[0] === orgXDomain[0]) { 34289 x.domain([orgXDomain[0] - 1e-10, x.orgDomain()[1]]); 34290 } 34291 $$.redraw({ 34292 withTransition: false, 34293 withY: false, 34294 withSubchart: false 34295 }); 34296 if (d3.event.sourceEvent.type === 'mousemove') { 34297 $$.cancelClick = true; 34298 } 34299 config.zoom_onzoom.call($$.api, x.orgDomain()); 34300 }; 34301 34302 c3_chart_internal_fn.generateColor = function () { 34303 var $$ = this, config = $$.config, d3 = $$.d3, 34304 colors = config.data_colors, 34305 pattern = notEmpty(config.color_pattern) ? config.color_pattern : d3.scale.category10().range(), 34306 callback = config.data_color, 34307 ids = []; 34308 34309 return function (d) { 34310 var id = d.id || d, color; 34311 34312 // if callback function is provided 34313 if (colors[id] instanceof Function) { 34314 color = colors[id](d); 34315 } 34316 // if specified, choose that color 34317 else if (colors[id]) { 34318 color = colors[id]; 34319 } 34320 // if not specified, choose from pattern 34321 else { 34322 if (ids.indexOf(id) < 0) { ids.push(id); } 34323 color = pattern[ids.indexOf(id) % pattern.length]; 34324 colors[id] = color; 34325 } 34326 return callback instanceof Function ? callback(color, d) : color; 34327 }; 34328 }; 34329 c3_chart_internal_fn.generateLevelColor = function () { 34330 var $$ = this, config = $$.config, 34331 colors = config.color_pattern, 34332 threshold = config.color_threshold, 34333 asValue = threshold.unit === 'value', 34334 values = threshold.values && threshold.values.length ? threshold.values : [], 34335 max = threshold.max || 100; 34336 return notEmpty(config.color_threshold) ? function (value) { 34337 var i, v, color = colors[colors.length - 1]; 34338 for (i = 0; i < values.length; i++) { 34339 v = asValue ? value : (value * 100 / max); 34340 if (v < values[i]) { 34341 color = colors[i]; 34342 break; 34343 } 34344 } 34345 return color; 34346 } : null; 34347 }; 34348 34349 c3_chart_internal_fn.getYFormat = function (forArc) { 34350 var $$ = this, 34351 formatForY = forArc && !$$.hasType('gauge') ? $$.defaultArcValueFormat : $$.yFormat, 34352 formatForY2 = forArc && !$$.hasType('gauge') ? $$.defaultArcValueFormat : $$.y2Format; 34353 return function (v, ratio, id) { 34354 var format = $$.getAxisId(id) === 'y2' ? formatForY2 : formatForY; 34355 return format.call($$, v, ratio); 34356 }; 34357 }; 34358 c3_chart_internal_fn.yFormat = function (v) { 34359 var $$ = this, config = $$.config, 34360 format = config.axis_y_tick_format ? config.axis_y_tick_format : $$.defaultValueFormat; 34361 return format(v); 34362 }; 34363 c3_chart_internal_fn.y2Format = function (v) { 34364 var $$ = this, config = $$.config, 34365 format = config.axis_y2_tick_format ? config.axis_y2_tick_format : $$.defaultValueFormat; 34366 return format(v); 34367 }; 34368 c3_chart_internal_fn.defaultValueFormat = function (v) { 34369 return isValue(v) ? +v : ""; 34370 }; 34371 c3_chart_internal_fn.defaultArcValueFormat = function (v, ratio) { 34372 return (ratio * 100).toFixed(1) + '%'; 34373 }; 34374 c3_chart_internal_fn.formatByAxisId = function (axisId) { 34375 var $$ = this, data_labels = $$.config.data_labels, 34376 format = function (v) { return isValue(v) ? +v : ""; }; 34377 // find format according to axis id 34378 if (typeof data_labels.format === 'function') { 34379 format = data_labels.format; 34380 } else if (typeof data_labels.format === 'object') { 34381 if (data_labels.format[axisId]) { 34382 format = data_labels.format[axisId]; 34383 } 34384 } 34385 return format; 34386 }; 34387 34388 c3_chart_internal_fn.hasCaches = function (ids) { 34389 for (var i = 0; i < ids.length; i++) { 34390 if (! (ids[i] in this.cache)) { return false; } 34391 } 34392 return true; 34393 }; 34394 c3_chart_internal_fn.addCache = function (id, target) { 34395 this.cache[id] = this.cloneTarget(target); 34396 }; 34397 c3_chart_internal_fn.getCaches = function (ids) { 34398 var targets = [], i; 34399 for (i = 0; i < ids.length; i++) { 34400 if (ids[i] in this.cache) { targets.push(this.cloneTarget(this.cache[ids[i]])); } 34401 } 34402 return targets; 34403 }; 34404 34405 var CLASS = c3_chart_internal_fn.CLASS = { 34406 target: 'c3-target', 34407 chart: 'c3-chart', 34408 chartLine: 'c3-chart-line', 34409 chartLines: 'c3-chart-lines', 34410 chartBar: 'c3-chart-bar', 34411 chartBars: 'c3-chart-bars', 34412 chartText: 'c3-chart-text', 34413 chartTexts: 'c3-chart-texts', 34414 chartArc: 'c3-chart-arc', 34415 chartArcs: 'c3-chart-arcs', 34416 chartArcsTitle: 'c3-chart-arcs-title',
34417 chartArcsBackground: 'c3-chart-arcs-background', 34418 chartArcsGaugeUnit: 'c3-chart-arcs-gauge-unit', 34419 chartArcsGaugeMax: 'c3-chart-arcs-gauge-max', 34420 chartArcsGaugeMin: 'c3-chart-arcs-gauge-min', 34421 selectedCircle: 'c3-selected-circle', 34422 selectedCircles: 'c3-selected-circles', 34423 eventRect: 'c3-event-rect', 34424 eventRects: 'c3-event-rects', 34425 eventRectsSingle: 'c3-event-rects-single', 34426 eventRectsMultiple: 'c3-event-rects-multiple', 34427 zoomRect: 'c3-zoom-rect', 34428 brush: 'c3-brush', 34429 focused: 'c3-focused', 34430 region: 'c3-region', 34431 regions: 'c3-regions', 34432 tooltip: 'c3-tooltip', 34433 tooltipName: 'c3-tooltip-name', 34434 shape: 'c3-shape', 34435 shapes: 'c3-shapes', 34436 line: 'c3-line', 34437 lines: 'c3-lines', 34438 bar: 'c3-bar', 34439 bars: 'c3-bars', 34440 circle: 'c3-circle', 34441 circles: 'c3-circles', 34442 arc: 'c3-arc', 34443 arcs: 'c3-arcs', 34444 area: 'c3-area', 34445 areas: 'c3-areas', 34446 empty: 'c3-empty', 34447 text: 'c3-text', 34448 texts: 'c3-texts', 34449 gaugeValue: 'c3-gauge-value', 34450 grid: 'c3-grid', 34451 xgrid: 'c3-xgrid', 34452 xgrids: 'c3-xgrids', 34453 xgridLine: 'c3-xgrid-line', 34454 xgridLines: 'c3-xgrid-lines', 34455 xgridFocus: 'c3-xgrid-focus', 34456 ygrid: 'c3-ygrid', 34457 ygrids: 'c3-ygrids', 34458 ygridLine: 'c3-ygrid-line', 34459 ygridLines: 'c3-ygrid-lines', 34460 axis: 'c3-axis', 34461 axisX: 'c3-axis-x', 34462 axisXLabel: 'c3-axis-x-label', 34463 axisY: 'c3-axis-y', 34464 axisYLabel: 'c3-axis-y-label', 34465 axisY2: 'c3-axis-y2', 34466 axisY2Label: 'c3-axis-y2-label', 34467 legendBackground: 'c3-legend-background', 34468 legendItem: 'c3-legend-item', 34469 legendItemEvent: 'c3-legend-item-event', 34470 legendItemTile: 'c3-legend-item-tile', 34471 legendItemHidden: 'c3-legend-item-hidden', 34472 legendItemFocused: 'c3-legend-item-focused', 34473 dragarea: 'c3-dragarea', 34474 EXPANDED: '_expanded_', 34475 SELECTED: '_selected_', 34476 INCLUDED: '_included_' 34477 }; 34478 c3_chart_internal_fn.generateClass = function (prefix, targetId) { 34479 return " " + prefix + " " + prefix + this.getTargetSelectorSuffix(targetId); 34480 }; 34481 c3_chart_internal_fn.classText = function (d) { 34482 return this.generateClass(CLASS.text, d.index); 34483 }; 34484 c3_chart_internal_fn.classTexts = function (d) { 34485 return this.generateClass(CLASS.texts, d.id); 34486 }; 34487 c3_chart_internal_fn.classShape = function (d) { 34488 return this.generateClass(CLASS.shape, d.index); 34489 }; 34490 c3_chart_internal_fn.classShapes = function (d) { 34491 return this.generateClass(CLASS.shapes, d.id); 34492 }; 34493 c3_chart_internal_fn.classLine = function (d) { 34494 return this.classShape(d) + this.generateClass(CLASS.line, d.id); 34495 }; 34496 c3_chart_internal_fn.classLines = function (d) { 34497 return this.classShapes(d) + this.generateClass(CLASS.lines, d.id); 34498 }; 34499 c3_chart_internal_fn.classCircle = function (d) { 34500 return this.classShape(d) + this.generateClass(CLASS.circle, d.index); 34501 }; 34502 c3_chart_internal_fn.classCircles = function (d) { 34503 return this.classShapes(d) + this.generateClass(CLASS.circles, d.id); 34504 }; 34505 c3_chart_internal_fn.classBar = function (d) { 34506 return this.classShape(d) + this.generateClass(CLASS.bar, d.index); 34507 }; 34508 c3_chart_internal_fn.classBars = function (d) { 34509 return this.classShapes(d) + this.generateClass(CLASS.bars, d.id); 34510 }; 34511 c3_chart_internal_fn.classArc = function (d) { 34512 return this.classShape(d.data) + this.generateClass(CLASS.arc, d.data.id); 34513 }; 34514 c3_chart_internal_fn.classArcs = function (d) { 34515 return this.classShapes(d.data) + this.generateClass(CLASS.arcs, d.data.id); 34516 }; 34517 c3_chart_internal_fn.classArea = function (d) { 34518 return this.classShape(d) + this.generateClass(CLASS.area, d.id); 34519 }; 34520 c3_chart_internal_fn.classAreas = function (d) { 34521 return this.classShapes(d) + this.generateClass(CLASS.areas, d.id); 34522 }; 34523 c3_chart_internal_fn.classRegion = function (d, i) { 34524 return this.generateClass(CLASS.region, i) + ' ' + ('class' in d ? d.class : ''); 34525 }; 34526 c3_chart_internal_fn.classEvent = function (d) { 34527 return this.generateClass(CLASS.eventRect, d.index); 34528 }; 34529 c3_chart_internal_fn.classTarget = function (id) { 34530 var $$ = this; 34531 var additionalClassSuffix = $$.config.data_classes[id], additionalClass = ''; 34532 if (additionalClassSuffix) { 34533 additionalClass = ' ' + CLASS.target + '-' + additionalClassSuffix; 34534 } 34535 return $$.generateClass(CLASS.target, id) + additionalClass; 34536 }; 34537 c3_chart_internal_fn.classChartText = function (d) { 34538 return CLASS.chartText + this.classTarget(d.id); 34539 }; 34540 c3_chart_internal_fn.classChartLine = function (d) { 34541 return CLASS.chartLine + this.classTarget(d.id); 34542 }; 34543 c3_chart_internal_fn.classChartBar = function (d) { 34544 return CLASS.chartBar + this.classTarget(d.id); 34545 }; 34546 c3_chart_internal_fn.classChartArc = function (d) { 34547 return CLASS.chartArc + this.classTarget(d.data.id); 34548 }; 34549 c3_chart_internal_fn.getTargetSelectorSuffix = function (targetId) { 34550 return targetId || targetId === 0 ? '-' + (targetId.replace ? targetId.replace(/([^a-zA-Z0-9-_])/g, '-') : targetId) : ''; 34551 }; 34552 c3_chart_internal_fn.selectorTarget = function (id) { 34553 return '.' + CLASS.target + this.getTargetSelectorSuffix(id); 34554 }; 34555 c3_chart_internal_fn.selectorTargets = function (ids) { 34556 var $$ = this; 34557 return ids.length ? ids.map(function (id) { return $$.selectorTarget(id); }) : null; 34558 }; 34559 c3_chart_internal_fn.selectorLegend = function (id) { 34560 return '.' + CLASS.legendItem + this.getTargetSelectorSuffix(id); 34561 }; 34562 c3_chart_internal_fn.selectorLegends = function (ids) { 34563 var $$ = this; 34564 return ids.length ? ids.map(function (id) { return $$.selectorLegend(id); }) : null; 34565 }; 34566 34567 var isValue = c3_chart_internal_fn.isValue = function (v) { 34568 return v || v === 0; 34569 }, 34570 isFunction = c3_chart_internal_fn.isFunction = function (o) { 34571 return typeof o === 'function'; 34572 }, 34573 isString = c3_chart_internal_fn.isString = function (o) { 34574 return typeof o === 'string'; 34575 }, 34576 isUndefined = c3_chart_internal_fn.isUndefined = function (v) { 34577 return typeof v === 'undefined'; 34578 }, 34579 isDefined = c3_chart_internal_fn.isDefined = function (v) { 34580 return typeof v !== 'undefined'; 34581 }, 34582 ceil10 = c3_chart_internal_fn.ceil10 = function (v) { 34583 return Math.ceil(v / 10) * 10; 34584 }, 34585 asHalfPixel = c3_chart_internal_fn.asHalfPixel = function (n) { 34586 return Math.ceil(n) + 0.5; 34587 }, 34588 diffDomain = c3_chart_internal_fn.diffDomain = function (d) { 34589 return d[1] - d[0]; 34590 }, 34591 isEmpty = c3_chart_internal_fn.isEmpty = function (o) { 34592 return !o || (isString(o) && o.length === 0) || (typeof o === 'object' && Object.keys(o).length === 0); 34593 }, 34594 notEmpty = c3_chart_internal_fn.notEmpty = function (o) { 34595 return Object.keys(o).length > 0; 34596 }, 34597 getOption = c3_chart_internal_fn.getOption = function (options, key, defaultValue) { 34598 return isDefined(options[key]) ? options[key] : defaultValue; 34599 }, 34600 hasValue = c3_chart_internal_fn.hasValue = function (dict, value) { 34601 var found = false;
34602 Object.keys(dict).forEach(function (key) { 34603 if (dict[key] === value) { found = true; } 34604 }); 34605 return found; 34606 }, 34607 getPathBox = c3_chart_internal_fn.getPathBox = function (path) { 34608 var box = path.getBoundingClientRect(), 34609 items = [path.pathSegList.getItem(0), path.pathSegList.getItem(1)], 34610 minX = items[0].x, minY = Math.min(items[0].y, items[1].y); 34611 return {x: minX, y: minY, width: box.width, height: box.height}; 34612 }; 34613 34614 c3_chart_fn.focus = function (targetId) { 34615 var $$ = this.internal, 34616 candidates = $$.svg.selectAll($$.selectorTarget(targetId)), 34617 candidatesForNoneArc = candidates.filter($$.isNoneArc.bind($$)), 34618 candidatesForArc = candidates.filter($$.isArc.bind($$)); 34619 function focus(targets) { 34620 $$.filterTargetsToShow(targets).transition().duration(100).style('opacity', 1); 34621 } 34622 this.revert(); 34623 this.defocus(); 34624 focus(candidatesForNoneArc.classed(CLASS.focused, true)); 34625 focus(candidatesForArc); 34626 if ($$.hasArcType()) { 34627 $$.expandArc(targetId, true); 34628 } 34629 $$.toggleFocusLegend(targetId, true); 34630 }; 34631 34632 c3_chart_fn.defocus = function (targetId) { 34633 var $$ = this.internal, 34634 candidates = $$.svg.selectAll($$.selectorTarget(targetId)), 34635 candidatesForNoneArc = candidates.filter($$.isNoneArc.bind($$)), 34636 candidatesForArc = candidates.filter($$.isArc.bind($$)); 34637 function defocus(targets) { 34638 $$.filterTargetsToShow(targets).transition().duration(100).style('opacity', 0.3); 34639 } 34640 this.revert(); 34641 defocus(candidatesForNoneArc.classed(CLASS.focused, false)); 34642 defocus(candidatesForArc); 34643 if ($$.hasArcType()) { 34644 $$.unexpandArc(targetId); 34645 } 34646 $$.toggleFocusLegend(targetId, false); 34647 }; 34648 34649 c3_chart_fn.revert = function (targetId) { 34650 var $$ = this.internal, 34651 candidates = $$.svg.selectAll($$.selectorTarget(targetId)), 34652 candidatesForNoneArc = candidates.filter($$.isNoneArc.bind($$)), 34653 candidatesForArc = candidates.filter($$.isArc.bind($$)); 34654 function revert(targets) { 34655 $$.filterTargetsToShow(targets).transition().duration(100).style('opacity', 1); 34656 } 34657 revert(candidatesForNoneArc.classed(CLASS.focused, false)); 34658 revert(candidatesForArc); 34659 if ($$.hasArcType()) { 34660 $$.unexpandArc(targetId); 34661 } 34662 $$.revertLegend(); 34663 }; 34664 34665 c3_chart_fn.show = function (targetIds, options) { 34666 var $$ = this.internal; 34667 34668 targetIds = $$.mapToTargetIds(targetIds); 34669 options = options || {}; 34670 34671 $$.removeHiddenTargetIds(targetIds); 34672 $$.svg.selectAll($$.selectorTargets(targetIds)) 34673 .transition() 34674 .style('opacity', 1); 34675 34676 if (options.withLegend) { 34677 $$.showLegend(targetIds); 34678 } 34679 34680 $$.redraw({withUpdateOrgXDomain: true, withUpdateXDomain: true, withLegend: true}); 34681 }; 34682 34683 c3_chart_fn.hide = function (targetIds, options) { 34684 var $$ = this.internal; 34685 34686 targetIds = $$.mapToTargetIds(targetIds); 34687 options = options || {}; 34688 34689 $$.addHiddenTargetIds(targetIds); 34690 $$.svg.selectAll($$.selectorTargets(targetIds)) 34691 .transition() 34692 .style('opacity', 0); 34693 34694 if (options.withLegend) { 34695 $$.hideLegend(targetIds); 34696 } 34697 34698 $$.redraw({withUpdateOrgXDomain: true, withUpdateXDomain: true, withLegend: true}); 34699 }; 34700 34701 c3_chart_fn.toggle = function (targetId) { 34702 var $$ = this.internal; 34703 $$.isTargetToShow(targetId) ? this.hide(targetId) : this.show(targetId); 34704 }; 34705 34706 c3_chart_fn.zoom = function () { 34707 }; 34708 c3_chart_fn.zoom.enable = function (enabled) { 34709 var $$ = this.internal; 34710 $$.config.zoom_enabled = enabled; 34711 $$.updateAndRedraw(); 34712 }; 34713 c3_chart_fn.unzoom = function () { 34714 var $$ = this.internal; 34715 $$.brush.clear().update(); 34716 $$.redraw({withUpdateXDomain: true}); 34717 }; 34718 34719 c3_chart_fn.load = function (args) { 34720 var $$ = this.internal, config = $$.config; 34721 // update xs if specified 34722 if (args.xs) { 34723 $$.addXs(args.xs); 34724 } 34725 // update classes if exists
vendor: 4,770 bytes, lines 34726-34855
34726 if ('classes' in args) { 34727 Object.keys(args.classes).forEach(function (id) { 34728 config.data_classes[id] = args.classes[id]; 34729 }); 34730 } 34731 // update categories if exists 34732 if ('categories' in args && $$.isCategorized()) { 34733 config.axis_x_categories = args.categories; 34734 } 34735 // use cache if exists 34736 if ('cacheIds' in args && $$.hasCaches(args.cacheIds)) { 34737 $$.load($$.getCaches(args.cacheIds), args.done); 34738 return; 34739 } 34740 // unload if needed 34741 if ('unload' in args) { 34742 // TODO: do not unload if target will load (included in url/rows/columns) 34743 $$.unload($$.mapToTargetIds((typeof args.unload === 'boolean' && args.unload) ? null : args.unload), function () { 34744 $$.loadFromArgs(args); 34745 }); 34746 } else { 34747 $$.loadFromArgs(args); 34748 } 34749 }; 34750 34751 c3_chart_fn.unload = function (args) { 34752 var $$ = this.internal; 34753 args = args || {}; 34754 $$.unload($$.mapToTargetIds(args.ids), function () { 34755 $$.redraw({withUpdateOrgXDomain: true, withUpdateXDomain: true, withLegend: true}); 34756 if (args.done) { args.done(); } 34757 }); 34758 }; 34759 34760 c3_chart_fn.flow = function (args) { 34761 var $$ = this.internal, 34762 targets, data, notfoundIds = [], orgDataCount = $$.getMaxDataCount(), 34763 dataCount, domain, baseTarget, baseValue, length = 0, tail = 0, diff, to; 34764 34765 if (args.json) { 34766 data = $$.convertJsonToData(args.json, args.keys); 34767 } 34768 else if (args.rows) { 34769 data = $$.convertRowsToData(args.rows); 34770 } 34771 else if (args.columns) { 34772 data = $$.convertColumnsToData(args.columns); 34773 } 34774 else { 34775 return; 34776 } 34777 targets = $$.convertDataToTargets(data, true); 34778 34779 // Update/Add data 34780 $$.data.targets.forEach(function (t) { 34781 var found = false, i, j; 34782 for (i = 0; i < targets.length; i++) { 34783 if (t.id === targets[i].id) { 34784 found = true; 34785 34786 if (t.values[t.values.length - 1]) { 34787 tail = t.values[t.values.length - 1].index + 1; 34788 } 34789 length = targets[i].values.length; 34790 34791 for (j = 0; j < length; j++) { 34792 targets[i].values[j].index = tail + j; 34793 if (!$$.isTimeSeries()) { 34794 targets[i].values[j].x = tail + j; 34795 } 34796 } 34797 t.values = t.values.concat(targets[i].values); 34798 34799 targets.splice(i, 1); 34800 break; 34801 } 34802 } 34803 if (!found) { notfoundIds.push(t.id); } 34804 }); 34805 34806 // Append null for not found targets 34807 $$.data.targets.forEach(function (t) { 34808 var i, j; 34809 for (i = 0; i < notfoundIds.length; i++) { 34810 if (t.id === notfoundIds[i]) { 34811 tail = t.values[t.values.length - 1].index + 1; 34812 for (j = 0; j < length; j++) { 34813 t.values.push({ 34814 id: t.id, 34815 index: tail + j, 34816 x: $$.isTimeSeries() ? $$.getOtherTargetX(tail + j) : tail + j, 34817 value: null 34818 }); 34819 } 34820 } 34821 } 34822 }); 34823 34824 // Generate null values for new target 34825 if ($$.data.targets.length) { 34826 targets.forEach(function (t) { 34827 var i, missing = []; 34828 for (i = $$.data.targets[0].values[0].index; i < tail; i++) { 34829 missing.push({ 34830 id: t.id, 34831 index: i, 34832 x: $$.isTimeSeries() ? $$.getOtherTargetX(i) : i, 34833 value: null 34834 }); 34835 } 34836 t.values.forEach(function (v) { 34837 v.index += tail; 34838 if (!$$.isTimeSeries()) { 34839 v.x += tail; 34840 } 34841 }); 34842 t.values = missing.concat(t.values); 34843 }); 34844 } 34845 $$.data.targets = $$.data.targets.concat(targets); // add remained 34846 34847 // check data count because behavior needs to change when it's only one 34848 dataCount = $$.getMaxDataCount(); 34849 baseTarget = $$.data.targets[0]; 34850 baseValue = baseTarget.values[0]; 34851 34852 // Update length to flow if needed 34853 if (isDefined(args.to)) { 34854 length = 0; 34855 to = $$.isTimeSeries() ? $$.parseDate(args.to) : args.to;
34856 baseTarget.values.forEach(function (v) { 34857 if (v.x < to) { length++; } 34858 }); 34859 } else if (isDefined(args.length)) { 34860 length = args.length; 34861 } 34862 34863 // If only one data, update the domain to flow from left edge of the chart 34864 if (!orgDataCount) { 34865 if ($$.isTimeSeries()) { 34866 if (baseTarget.values.length > 1) { 34867 diff = baseTarget.values[baseTarget.values.length - 1].x - baseValue.x; 34868 } else { 34869 diff = baseValue.x - $$.getXDomain($$.data.targets)[0]; 34870 } 34871 } else { 34872 diff = 1; 34873 } 34874 domain = [baseValue.x - diff, baseValue.x]; 34875 $$.updateXDomain(null, true, true, domain); 34876 } else if (orgDataCount === 1) { 34877 if ($$.isTimeSeries()) { 34878 diff = (baseTarget.values[baseTarget.values.length - 1].x - baseValue.x) / 2; 34879 domain = [new Date(+baseValue.x - diff), new Date(+baseValue.x + diff)]; 34880 $$.updateXDomain(null, true, true, domain); 34881 } 34882 } 34883 34884 // Set targets 34885 $$.updateTargets($$.data.targets); 34886 34887 // Redraw with new targets 34888 $$.redraw({ 34889 flow: { 34890 index: baseValue.index, 34891 length: length, 34892 duration: isValue(args.duration) ? args.duration : $$.config.transition_duration, 34893 done: args.done, 34894 orgDataCount: orgDataCount, 34895 }, 34896 withLegend: true, 34897 withTransition: orgDataCount > 1, 34898 }); 34899 }; 34900 34901 c3_chart_internal_fn.generateFlow = function (args) { 34902 var $$ = this, config = $$.config, d3 = $$.d3; 34903 34904 return function () { 34905 var targets = args.targets, 34906 flow = args.flow, 34907 drawBar = args.drawBar, 34908 drawLine = args.drawLine, 34909 drawArea = args.drawArea, 34910 cx = args.cx, 34911 cy = args.cy, 34912 xv = args.xv, 34913 xForText = args.xForText, 34914 yForText = args.yForText, 34915 duration = args.duration; 34916 34917 var translateX, scaleX = 1, transform, 34918 flowIndex = flow.index, 34919 flowLength = flow.length, 34920 flowStart = $$.getValueOnIndex($$.data.targets[0].values, flowIndex), 34921 flowEnd = $$.getValueOnIndex($$.data.targets[0].values, flowIndex + flowLength), 34922 orgDomain = $$.x.domain(), domain, 34923 durationForFlow = flow.duration || duration, 34924 done = flow.done || function () {}, 34925 wait = $$.generateWait(); 34926 34927 var xgrid = $$.xgrid || d3.selectAll([]), 34928 xgridLines = $$.xgridLines || d3.selectAll([]), 34929 mainRegion = $$.mainRegion || d3.selectAll([]), 34930 mainText = $$.mainText || d3.selectAll([]), 34931 mainBar = $$.mainBar || d3.selectAll([]), 34932 mainLine = $$.mainLine || d3.selectAll([]), 34933 mainArea = $$.mainArea || d3.selectAll([]), 34934 mainCircle = $$.mainCircle || d3.selectAll([]); 34935 34936 // remove head data after rendered 34937 $$.data.targets.forEach(function (d) { 34938 d.values.splice(0, flowLength); 34939 }); 34940 34941 // update x domain to generate axis elements for flow 34942 domain = $$.updateXDomain(targets, true, true); 34943 // update elements related to x scale 34944 if ($$.updateXGrid) { $$.updateXGrid(true); } 34945 34946 // generate transform to flow 34947 if (!flow.orgDataCount) { // if empty 34948 if ($$.data.targets[0].values.length !== 1) { 34949 translateX = $$.x(orgDomain[0]) - $$.x(domain[0]); 34950 } else { 34951 if ($$.isTimeSeries()) { 34952 flowStart = $$.getValueOnIndex($$.data.targets[0].values, 0); 34953 flowEnd = $$.getValueOnIndex($$.data.targets[0].values, $$.data.targets[0].values.length - 1); 34954 translateX = $$.x(flowStart.x) - $$.x(flowEnd.x); 34955 } else { 34956 translateX = diffDomain(domain) / 2; 34957 } 34958 } 34959 } else if (flow.orgDataCount === 1 || flowStart.x === flowEnd.x) { 34960 translateX = $$.x(orgDomain[0]) - $$.x(domain[0]); 34961 } else { 34962 if ($$.isTimeSeries()) { 34963 translateX = ($$.x(orgDomain[0]) - $$.x(domain[0])); 34964 } else { 34965 translateX = ($$.x(flowStart.x) - $$.x(flowEnd.x)); 34966 } 34967 } 34968 scaleX = (diffDomain(orgDomain) / diffDomain(domain)); 34969 transform = 'translate(' + translateX + ',0) scale(' + scaleX + ',1)'; 34970 34971 d3.transition().ease('linear').duration(durationForFlow).each(function () { 34972 wait.add($$.axes.x.transition().call($$.xAxis)); 34973 wait.add(mainBar.transition().attr('transform', transform)); 34974 wait.add(mainLine.transition().attr('transform', transform)); 34975 wait.add(mainArea.transition().attr('transform', transform)); 34976 wait.add(mainCircle.transition().attr('transform', transform)); 34977 wait.add(mainText.transition().attr('transform', transform)); 34978 wait.add(mainRegion.filter($$.isRegionOnX).transition().attr('transform', transform)); 34979 wait.add(xgrid.transition().attr('transform', transform)); 34980 wait.add(xgridLines.transition().attr('transform', transform)); 34981 }) 34982 .call(wait, function () { 34983 var i, shapes = [], texts = [], eventRects = []; 34984 34985 // remove flowed elements 34986 if (flowLength) { 34987 for (i = 0;
vendor: 5,652 bytes, lines 34987-35106
34987 i < flowLength; i++) { 34988 shapes.push('.' + CLASS.shape + '-' + (flowIndex + i)); 34989 texts.push('.' + CLASS.text + '-' + (flowIndex + i)); 34990 eventRects.push('.' + CLASS.eventRect + '-' + (flowIndex + i)); 34991 } 34992 $$.svg.selectAll('.' + CLASS.shapes).selectAll(shapes).remove(); 34993 $$.svg.selectAll('.' + CLASS.texts).selectAll(texts).remove(); 34994 $$.svg.selectAll('.' + CLASS.eventRects).selectAll(eventRects).remove(); 34995 $$.svg.select('.' + CLASS.xgrid).remove(); 34996 } 34997 34998 // draw again for removing flowed elements and reverting attr 34999 xgrid 35000 .attr('transform', null) 35001 .attr($$.xgridAttr); 35002 xgridLines 35003 .attr('transform', null); 35004 xgridLines.select('line') 35005 .attr("x1", config.axis_rotated ? 0 : xv) 35006 .attr("x2", config.axis_rotated ? $$.width : xv); 35007 xgridLines.select('text') 35008 .attr("x", config.axis_rotated ? $$.width : 0) 35009 .attr("y", xv); 35010 mainBar 35011 .attr('transform', null) 35012 .attr("d", drawBar); 35013 mainLine 35014 .attr('transform', null) 35015 .attr("d", drawLine); 35016 mainArea 35017 .attr('transform', null) 35018 .attr("d", drawArea); 35019 mainCircle 35020 .attr('transform', null) 35021 .attr("cx", cx) 35022 .attr("cy", cy); 35023 mainText 35024 .attr('transform', null) 35025 .attr('x', xForText) 35026 .attr('y', yForText) 35027 .style('fill-opacity', $$.opacityForText.bind($$)); 35028 mainRegion 35029 .attr('transform', null); 35030 mainRegion.select('rect').filter($$.isRegionOnX) 35031 .attr("x", $$.regionX.bind($$)) 35032 .attr("width", $$.regionWidth.bind($$)); 35033 $$.updateEventRect(); 35034 35035 // callback for end of flow 35036 done(); 35037 }); 35038 }; 35039 }; 35040 35041 c3_chart_fn.selected = function (targetId) { 35042 var $$ = this.internal, d3 = $$.d3; 35043 return d3.merge( 35044 $$.main.selectAll('.' + CLASS.shapes + $$.getTargetSelectorSuffix(targetId)).selectAll('.' + CLASS.shape) 35045 .filter(function () { return d3.select(this).classed(CLASS.SELECTED); }) 35046 .map(function (d) { return d.map(function (d) { var data = d.__data__; return data.data ? data.data : data; }); }) 35047 ); 35048 }; 35049 c3_chart_fn.select = function (ids, indices, resetOther) { 35050 var $$ = this.internal, d3 = $$.d3, config = $$.config; 35051 if (! config.data_selection_enabled) { return; } 35052 $$.main.selectAll('.' + CLASS.shapes).selectAll('.' + CLASS.shape).each(function (d, i) { 35053 var shape = d3.select(this), id = d.data ? d.data.id : d.id, 35054 toggle = $$.getToggle(this).bind($$), 35055 isTargetId = config.data_selection_grouped || !ids || ids.indexOf(id) >= 0, 35056 isTargetIndex = !indices || indices.indexOf(i) >= 0, 35057 isSelected = shape.classed(CLASS.SELECTED); 35058 // line/area selection not supported yet 35059 if (shape.classed(CLASS.line) || shape.classed(CLASS.area)) { 35060 return; 35061 } 35062 if (isTargetId && isTargetIndex) { 35063 if (config.data_selection_isselectable(d) && !isSelected) { 35064 toggle(true, shape.classed(CLASS.SELECTED, true), d, i); 35065 } 35066 } else if (isDefined(resetOther) && resetOther) { 35067 if (isSelected) { 35068 toggle(false, shape.classed(CLASS.SELECTED, false), d, i); 35069 } 35070 } 35071 }); 35072 }; 35073 c3_chart_fn.unselect = function (ids, indices) { 35074 var $$ = this.internal, d3 = $$.d3, config = $$.config; 35075 if (! config.data_selection_enabled) { return; } 35076 $$.main.selectAll('.' + CLASS.shapes).selectAll('.' + CLASS.shape).each(function (d, i) { 35077 var shape = d3.select(this), id = d.data ? d.data.id : d.id, 35078 toggle = $$.getToggle(this).bind($$), 35079 isTargetId = config.data_selection_grouped || !ids || ids.indexOf(id) >= 0, 35080 isTargetIndex = !indices || indices.indexOf(i) >= 0, 35081 isSelected = shape.classed(CLASS.SELECTED); 35082 // line/area selection not supported yet 35083 if (shape.classed(CLASS.line) || shape.classed(CLASS.area)) { 35084 return; 35085 } 35086 if (isTargetId && isTargetIndex) { 35087 if (config.data_selection_isselectable(d)) { 35088 if (isSelected) { 35089 toggle(false, shape.classed(CLASS.SELECTED, false), d, i); 35090 } 35091 } 35092 } 35093 }); 35094 }; 35095 35096 c3_chart_fn.transform = function (type, targetIds) { 35097 var $$ = this.internal, 35098 options = ['pie', 'donut'].indexOf(type) >= 0 ? {withTransform: true} : null; 35099 $$.transformTo(targetIds, type, options); 35100 }; 35101 35102 c3_chart_internal_fn.transformTo = function (targetIds, type, optionsForRedraw) { 35103 var $$ = this, 35104 withTransitionForAxis = !$$.hasArcType(), 35105 options = optionsForRedraw || {withTransitionForAxis: withTransitionForAxis}; 35106 options.withTransitionForTransform = false;
35107 $$.transiting = false; 35108 $$.setTargetType(targetIds, type); 35109 $$.updateAndRedraw(options); 35110 }; 35111 35112 c3_chart_fn.groups = function (groups) { 35113 var $$ = this.internal, config = $$.config; 35114 if (isUndefined(groups)) { return config.data_groups; } 35115 config.data_groups = groups; 35116 $$.redraw(); 35117 return config.data_groups; 35118 }; 35119 35120 c3_chart_fn.xgrids = function (grids) { 35121 var $$ = this.internal, config = $$.config; 35122 if (! grids) { return config.grid_x_lines; } 35123 config.grid_x_lines = grids; 35124 $$.redraw(); 35125 return config.grid_x_lines; 35126 }; 35127 c3_chart_fn.xgrids.add = function (grids) { 35128 var $$ = this.internal; 35129 return this.xgrids($$.config.grid_x_lines.concat(grids ? grids : [])); 35130 }; 35131 c3_chart_fn.xgrids.remove = function (params) { // TODO: multiple 35132 var $$ = this.internal; 35133 $$.removeGridLines(params, true); 35134 }; 35135 35136 c3_chart_fn.ygrids = function (grids) { 35137 var $$ = this.internal, config = $$.config; 35138 if (! grids) { return config.grid_y_lines; } 35139 config.grid_y_lines = grids; 35140 $$.redraw(); 35141 return config.grid_y_lines; 35142 }; 35143 c3_chart_fn.ygrids.add = function (grids) { 35144 var $$ = this.internal; 35145 return this.ygrids($$.config.grid_y_lines.concat(grids ? grids : [])); 35146 }; 35147 c3_chart_fn.ygrids.remove = function (params) { // TODO: multiple 35148 var $$ = this.internal; 35149 $$.removeGridLines(params, false); 35150 }; 35151 35152 c3_chart_fn.regions = function (regions) { 35153 var $$ = this.internal, config = $$.config; 35154 if (!regions) { return config.regions; } 35155 config.regions = regions; 35156 $$.redraw(); 35157 return config.regions; 35158 }; 35159 c3_chart_fn.regions.add = function (regions) { 35160 var $$ = this.internal, config = $$.config; 35161 if (!regions) { return config.regions; } 35162 config.regions = config.regions.concat(regions); 35163 $$.redraw(); 35164 return config.regions; 35165 }; 35166 c3_chart_fn.regions.remove = function (options) { 35167 var $$ = this.internal, config = $$.config, 35168 duration, classes, regions; 35169 35170 options = options || {}; 35171 duration = $$.getOption(options, "duration", config.transition_duration); 35172 classes = $$.getOption(options, "classes", [CLASS.region]); 35173 35174 regions = $$.main.select('.' + CLASS.regions).selectAll(classes.map(function (c) { return '.' + c; })); 35175 (duration ? regions.transition().duration(duration) : regions) 35176 .style('opacity', 0) 35177 .remove(); 35178 35179 config.regions = config.regions.filter(function (region) { 35180 var found = false; 35181 if (!region.class) { 35182 return true; 35183 } 35184 region.class.split(' ').forEach(function (c) { 35185 if (classes.indexOf(c) >= 0) { found = true; } 35186 }); 35187 return !found; 35188 }); 35189 35190 return config.regions; 35191 }; 35192 35193 c3_chart_fn.data = function () {}; 35194 c3_chart_fn.data.get = function (targetId) { 35195 var target = this.data.getAsTarget(targetId); 35196 return isDefined(target) ? target.values.map(function (d) { return d.value; }) : undefined; 35197 }; 35198 c3_chart_fn.data.getAsTarget = function (targetId) { 35199 var targets = this.data.targets.filter(function (t) { return t.id === targetId; }); 35200 return targets.length > 0 ? targets[0] : undefined; 35201 }; 35202 c3_chart_fn.data.names = function (names) { 35203 var $$ = this.internal, config = $$.config; 35204 if (!arguments.length) { return config.data_names; } 35205 Object.keys(names).forEach(function (id) { 35206 config.data_names[id] = names[id]; 35207 }); 35208 $$.redraw({withLegend: true}); 35209 return config.data_names; 35210 }; 35211 c3_chart_fn.data.colors = function (colors) { 35212 var $$ = this.internal, config = $$.config; 35213 if (!arguments.length) { return config.data_colors; } 35214 Object.keys(colors).forEach(function (id) { 35215 config.data_colors[id] = colors[id]; 35216 }); 35217 $$.redraw({withLegend: true}); 35218 return config.data_colors; 35219 }; 35220 35221 c3_chart_fn.category = function (i, category) { 35222 var $$ = this.internal, config = $$.config; 35223 if (arguments.length > 1) { 35224 config.axis_x_categories[i] = category; 35225 $$.redraw(); 35226 } 35227 return config.axis_x_categories[i]; 35228 }; 35229 c3_chart_fn.categories = function (categories) { 35230 var $$ = this.internal, config = $$.config; 35231 if (!arguments.length) { return config.axis_x_categories; } 35232 config.axis_x_categories = categories; 35233 $$.redraw(); 35234 return config.axis_x_categories; 35235 }; 35236
35237 // TODO: fix 35238 c3_chart_fn.color = function (id) { 35239 var $$ = this.internal; 35240 return $$.color(id); // more patterns 35241 }; 35242 35243 c3_chart_fn.x = function (x) { 35244 var $$ = this.internal; 35245 if (arguments.length) { 35246 $$.updateTargetX($$.data.targets, x); 35247 $$.redraw({withUpdateOrgXDomain: true, withUpdateXDomain: true}); 35248 } 35249 return $$.data.xs; 35250 }; 35251 c3_chart_fn.xs = function (xs) { 35252 var $$ = this.internal; 35253 if (arguments.length) { 35254 $$.updateTargetXs($$.data.targets, xs); 35255 $$.redraw({withUpdateOrgXDomain: true, withUpdateXDomain: true}); 35256 } 35257 return $$.data.xs; 35258 }; 35259 35260 c3_chart_fn.axis = function () {}; 35261 c3_chart_fn.axis.labels = function (labels) { 35262 var $$ = this.internal; 35263 if (arguments.length) { 35264 Object.keys(labels).forEach(function (axisId) { 35265 $$.setAxisLabelText(axisId, labels[axisId]); 35266 }); 35267 $$.updateAxisLabels(); 35268 } 35269 // TODO: return some values? 35270 }; 35271 c3_chart_fn.axis.max = function (max) { 35272 var $$ = this.internal, config = $$.config; 35273 if (arguments.length) { 35274 if (typeof max === 'object') { 35275 if (isValue(max.x)) { config.axis_x_max = max.x; } 35276 if (isValue(max.y)) { config.axis_y_max = max.y; } 35277 if (isValue(max.y2)) { config.axis_y2_max = max.y2; } 35278 } else { 35279 config.axis_y_max = config.axis_y2_max = max; 35280 } 35281 $$.redraw({withUpdateOrgXDomain: true, withUpdateXDomain: true}); 35282 } 35283 }; 35284 c3_chart_fn.axis.min = function (min) { 35285 var $$ = this.internal, config = $$.config; 35286 if (arguments.length) { 35287 if (typeof min === 'object') { 35288 if (isValue(min.x)) { config.axis_x_min = min.x; } 35289 if (isValue(min.y)) { config.axis_y_min = min.y; } 35290 if (isValue(min.y2)) { config.axis_y2_min = min.y2; } 35291 } else { 35292 config.axis_y_min = config.axis_y2_min = min; 35293 } 35294 $$.redraw({withUpdateOrgXDomain: true, withUpdateXDomain: true}); 35295 } 35296 }; 35297 c3_chart_fn.axis.range = function (range) { 35298 if (arguments.length) { 35299 if (isDefined(range.max)) { this.axis.max(range.max); } 35300 if (isDefined(range.min)) { this.axis.min(range.min); } 35301 } 35302 }; 35303 35304 c3_chart_fn.legend = function () {}; 35305 c3_chart_fn.legend.show = function (targetIds) { 35306 var $$ = this.internal; 35307 $$.showLegend($$.mapToTargetIds(targetIds)); 35308 $$.updateAndRedraw({withLegend: true}); 35309 }; 35310 c3_chart_fn.legend.hide = function (targetIds) { 35311 var $$ = this.internal; 35312 $$.hideLegend($$.mapToTargetIds(targetIds)); 35313 $$.updateAndRedraw({withLegend: true}); 35314 }; 35315 35316 c3_chart_fn.resize = function (size) { 35317 var $$ = this.internal, config = $$.config; 35318 config.size_width = size ? size.width : null; 35319 config.size_height = size ? size.height : null; 35320 this.flush(); 35321 }; 35322 35323 c3_chart_fn.flush = function () { 35324 var $$ = this.internal; 35325 $$.updateAndRedraw({withLegend: true, withTransition: false, withTransitionForTransform: false}); 35326 }; 35327 35328 c3_chart_fn.destroy = function () { 35329 var $$ = this.internal; 35330 $$.data.targets = undefined; 35331 $$.data.xs = {}; 35332 $$.selectChart.classed('c3', false).html(""); 35333 window.onresize = null; 35334 }; 35335 35336 // Features: 35337 // 1. category axis 35338 // 2. ceil values of translate/x/y to int for half pixel antialiasing 35339 function c3_axis(d3, isCategory) { 35340 var scale = d3.scale.linear(), orient = "bottom", innerTickSize = 6, outerTickSize = 6, tickPadding = 3, tickValues = null, tickFormat, tickArguments; 35341 35342 var tickOffset = 0, tickCulling = true, tickCentered; 35343 35344 function axisX(selection, x) { 35345 selection.attr("transform", function (d) { 35346 return "translate(" + Math.ceil(x(d) + tickOffset) + ", 0)"; 35347 }); 35348 } 35349 function axisY(selection, y) { 35350 selection.attr("transform", function (d) { 35351 return "translate(0," + Math.ceil(y(d)) + ")"; 35352 }); 35353 } 35354 function scaleExtent(domain) { 35355 var start = domain[0], stop = domain[domain.length - 1]; 35356 return start < stop ? [ start, stop ] : [ stop, start ]; 35357 } 35358 function generateTicks(scale) { 35359 var i, domain, ticks = []; 35360 if (scale.ticks) { 35361 return scale.ticks.apply(scale, tickArguments); 35362 } 35363 domain = scale.domain(); 35364 for (i = Math.ceil(domain[0]); i < domain[1]; i++) { 35365 ticks.push(i); 35366 } 35367 if (ticks.length > 0 && ticks[0] > 0) { 35368 ticks.unshift(ticks[0] - (ticks[1] - ticks[0])); 35369 } 35370 return ticks; 35371 } 35372 function copyScale() { 35373 var newScale = scale.copy(), domain; 35374 if (isCategory) { 35375 domain = scale.domain(); 35376 newScale.domain([domain[0], domain[1] - 1]); 35377 } 35378 return newScale; 35379 } 35380 function textFormatted(v) { 35381 return tickFormat ? tickFormat(v) : v; 35382 } 35383 function axis(g) { 35384 g.each(function () { 35385 var g = d3.select(this); 35386 var scale0 = this.__chart__ || scale, scale1 = this.__chart__ = copyScale(); 35387 35388 var ticks = tickValues ? tickValues : generateTicks(scale1), 35389 tick = g.selectAll(".tick").data(ticks, scale1), 35390 tickEnter = tick.enter().insert("g", ".domain").attr("class", "tick").style("opacity", 1e-6), 35391 // MEMO: No exit transition. The reason is this transition affects max tick width calculation because old tick will be included in the ticks. 35392 tickExit = tick.exit().remove(), 35393 tickUpdate = d3.transition(tick).style("opacity", 1), 35394 tickTransform, tickX; 35395 35396 var range = scale.rangeExtent ? scale.rangeExtent() : scaleExtent(scale.range()), 35397 path = g.selectAll(".domain").data([ 0 ]), 35398 pathUpdate = (path.enter().append("path").attr("class", "domain"), d3.transition(path)); 35399 tickEnter.append("line"); 35400 tickEnter.append("text"); 35401 35402 var lineEnter = tickEnter.select("line"), 35403 lineUpdate = tickUpdate.select("line"), 35404 text = tick.select("text").text(textFormatted), 35405 textEnter = tickEnter.select("text"), 35406 textUpdate = tickUpdate.select("text"); 35407 35408 if (isCategory) {
35409 tickOffset = Math.ceil((scale1(1) - scale1(0)) / 2); 35410 tickX = tickCentered ? 0 : tickOffset; 35411 } else { 35412 tickOffset = tickX = 0; 35413 } 35414 35415 function tickSize(d) { 35416 var tickPosition = scale(d) + tickOffset; 35417 return range[0] < tickPosition && tickPosition < range[1] ? innerTickSize : 0; 35418 } 35419 35420 switch (orient) { 35421 case "bottom": 35422 { 35423 tickTransform = axisX; 35424 lineEnter.attr("y2", innerTickSize); 35425 textEnter.attr("y", Math.max(innerTickSize, 0) + tickPadding); 35426 lineUpdate.attr("x1", tickX).attr("x2", tickX).attr("y2", tickSize); 35427 textUpdate.attr("x", 0).attr("y", Math.max(innerTickSize, 0) + tickPadding); 35428 text.attr("dy", ".71em").style("text-anchor", "middle"); 35429 pathUpdate.attr("d", "M" + range[0] + "," + outerTickSize + "V0H" + range[1] + "V" + outerTickSize); 35430 break; 35431 } 35432 case "top": 35433 { 35434 tickTransform = axisX; 35435 lineEnter.attr("y2", -innerTickSize); 35436 textEnter.attr("y", -(Math.max(innerTickSize, 0) + tickPadding)); 35437 lineUpdate.attr("x2", 0).attr("y2", -innerTickSize); 35438 textUpdate.attr("x", 0).attr("y", -(Math.max(innerTickSize, 0) + tickPadding)); 35439 text.attr("dy", "0em").style("text-anchor", "middle"); 35440 pathUpdate.attr("d", "M" + range[0] + "," + -outerTickSize + "V0H" + range[1] + "V" + -outerTickSize); 35441 break; 35442 } 35443 case "left": 35444 { 35445 tickTransform = axisY; 35446 lineEnter.attr("x2", -innerTickSize); 35447 textEnter.attr("x", -(Math.max(innerTickSize, 0) + tickPadding)); 35448 lineUpdate.attr("x2", -innerTickSize).attr("y2", 0); 35449 textUpdate.attr("x", -(Math.max(innerTickSize, 0) + tickPadding)).attr("y", tickOffset); 35450 text.attr("dy", ".32em").style("text-anchor", "end"); 35451 pathUpdate.attr("d", "M" + -outerTickSize + "," + range[0] + "H0V" + range[1] + "H" + -outerTickSize); 35452 break; 35453 } 35454 case "right": 35455 { 35456 tickTransform = axisY; 35457 lineEnter.attr("x2", innerTickSize); 35458 textEnter.attr("x", Math.max(innerTickSize, 0) + tickPadding); 35459 lineUpdate.attr("x2", innerTickSize).attr("y2", 0); 35460 textUpdate.attr("x", Math.max(innerTickSize, 0) + tickPadding).attr("y", 0); 35461 text.attr("dy", ".32em").style("text-anchor", "start"); 35462 pathUpdate.attr("d", "M" + outerTickSize + "," + range[0] + "H0V" + range[1] + "H" + outerTickSize); 35463 break; 35464 } 35465 } 35466 if (scale1.rangeBand) { 35467 var x = scale1, dx = x.rangeBand() / 2; 35468 scale0 = scale1 = function (d) { 35469 return x(d) + dx; 35470 }; 35471 } else if (scale0.rangeBand) { 35472 scale0 = scale1; 35473 } else { 35474 tickExit.call(tickTransform, scale1); 35475 } 35476 tickEnter.call(tickTransform, scale0); 35477 tickUpdate.call(tickTransform, scale1); 35478 }); 35479 } 35480 axis.scale = function (x) { 35481 if (!arguments.length) { return scale; } 35482 scale = x; 35483 return axis; 35484 }; 35485 axis.orient = function (x) { 35486 if (!arguments.length) { return orient; } 35487 orient = x in {top: 1, right: 1, bottom: 1, left: 1} ? x + "" : "bottom"; 35488 return axis; 35489 }; 35490 axis.tickFormat = function (format) { 35491 if (!arguments.length) { return tickFormat; } 35492 tickFormat = format; 35493 return axis; 35494 }; 35495 axis.tickCentered = function (isCentered) { 35496 if (!arguments.length) { return tickCentered; } 35497 tickCentered = isCentered; 35498 return axis; 35499 }; 35500 axis.tickOffset = function () { // This will be overwritten when normal x axis 35501 return tickOffset; 35502 }; 35503 axis.ticks = function () { 35504 if (!arguments.length) { return tickArguments; } 35505 tickArguments = arguments; 35506 return axis; 35507 }; 35508 axis.tickCulling = function (culling) { 35509 if (!arguments.length) { return tickCulling; } 35510 tickCulling = culling; 35511 return axis; 35512 }; 35513 axis.tickValues = function (x) { 35514 if (typeof x === 'function') { 35515 tickValues = function () { 35516 return x(scale.domain()); 35517 }; 35518 } 35519 else { 35520 if (!arguments.length) { return tickValues; } 35521 tickValues = x; 35522 } 35523 return axis; 35524 }; 35525 return axis; 35526 } 35527 35528 if (typeof define === 'function' && define.amd) { 35529 define("c3", ["d3"], c3); 35530 } else if ('undefined' !== typeof exports && 'undefined' !== typeof module) { 35531 module.exports = c3; 35532 } else { 35533 window.c3 = c3; 35534 } 35535 35536})(window); 35537 35538/* 35539 * JavaScript Canvas to Blob 35540 * https://github.com/blueimp/JavaScript-Canvas-to-Blob 35541 * 35542 * Copyright 2012, Sebastian Tschan 35543 * https://blueimp.net 35544 * 35545 * Licensed under the MIT license: 35546 * https://opensource.org/licenses/MIT 35547 * 35548 * Based on stackoverflow user Stoive's code snippet: 35549 * http://stackoverflow.com/q/4998908 35550 */ 35551 35552/* global define, Uint8Array, ArrayBuffer, module */ 35553 35554;(function (window) { 35555 'use strict' 35556 35557 var CanvasPrototype = 35558 window.HTMLCanvasElement && window.HTMLCanvasElement.prototype 35559 var hasBlobConstructor = 35560 window.Blob && 35561 (function () {
35562 try { 35563 return Boolean(new Blob()) 35564 } catch (e) { 35565 return false 35566 } 35567 })() 35568 var hasArrayBufferViewSupport = 35569 hasBlobConstructor && 35570 window.Uint8Array && 35571 (function () { 35572 try { 35573 return new Blob([new Uint8Array(100)]).size === 100 35574 } catch (e) { 35575 return false 35576 } 35577 })() 35578 var BlobBuilder = 35579 window.BlobBuilder || 35580 window.WebKitBlobBuilder || 35581 window.MozBlobBuilder || 35582 window.MSBlobBuilder 35583 var dataURIPattern = /^data:((.*?)(;charset=.*?)?)(;base64)?,/ 35584 var dataURLtoBlob = 35585 (hasBlobConstructor || BlobBuilder) && 35586 window.atob && 35587 window.ArrayBuffer && 35588 window.Uint8Array && 35589 function (dataURI) { 35590 var matches, 35591 mediaType, 35592 isBase64, 35593 dataString, 35594 byteString, 35595 arrayBuffer, 35596 intArray, 35597 i, 35598 bb 35599 // Parse the dataURI components as per RFC 2397 35600 matches = dataURI.match(dataURIPattern) 35601 if (!matches) { 35602 throw new Error('invalid data URI') 35603 } 35604 // Default to text/plain;charset=US-ASCII 35605 mediaType = matches[2] 35606 ? matches[1] 35607 : 'text/plain' + (matches[3] || ';charset=US-ASCII') 35608 isBase64 = !!matches[4] 35609 dataString = dataURI.slice(matches[0].length) 35610 if (isBase64) { 35611 // Convert base64 to raw binary data held in a string: 35612 byteString = atob(dataString) 35613 } else { 35614 // Convert base64/URLEncoded data component to raw binary: 35615 byteString = decodeURIComponent(dataString) 35616 } 35617 // Write the bytes of the string to an ArrayBuffer: 35618 arrayBuffer = new ArrayBuffer(byteString.length) 35619 intArray = new Uint8Array(arrayBuffer) 35620 for (i = 0; i < byteString.length; i += 1) { 35621 intArray[i] = byteString.charCodeAt(i) 35622 } 35623 // Write the ArrayBuffer (or ArrayBufferView) to a blob: 35624 if (hasBlobConstructor) { 35625 return new Blob([hasArrayBufferViewSupport ? intArray : arrayBuffer], { 35626 type: mediaType 35627 }) 35628 } 35629 bb = new BlobBuilder() 35630 bb.append(arrayBuffer) 35631 return bb.getBlob(mediaType) 35632 } 35633 if (window.HTMLCanvasElement && !CanvasPrototype.toBlob) { 35634 if (CanvasPrototype.mozGetAsFile) { 35635 CanvasPrototype.toBlob = function (callback, type, quality) { 35636 var self = this 35637 setTimeout(function () { 35638 if (quality && CanvasPrototype.toDataURL && dataURLtoBlob) { 35639 callback(dataURLtoBlob(self.toDataURL(type, quality))) 35640 } else { 35641 callback(self.mozGetAsFile('blob', type)) 35642 } 35643 }) 35644 } 35645 } else if (CanvasPrototype.toDataURL && dataURLtoBlob) { 35646 if (CanvasPrototype.msToBlob) { 35647 CanvasPrototype.toBlob = function (callback, type, quality) { 35648 var self = this 35649 setTimeout(function () { 35650 if ( 35651 ((type && type !== 'image/png') || quality) && 35652 CanvasPrototype.toDataURL && 35653 dataURLtoBlob 35654 ) { 35655 callback(dataURLtoBlob(self.toDataURL(type, quality))) 35656 } else { 35657 callback(self.msToBlob(type)) 35658 } 35659 }) 35660 } 35661 } else { 35662 CanvasPrototype.toBlob = function (callback, type, quality) { 35663 var self = this 35664 setTimeout(function () { 35665 callback(dataURLtoBlob(self.toDataURL(type, quality))) 35666 }) 35667 } 35668 } 35669 } 35670 } 35671 if (typeof define === 'function' && define.amd) { 35672 define('canvas-to-blob',[],function () { 35673 return dataURLtoBlob 35674 }) 35675 } else if (typeof module === 'object' && module.exports) { 35676 module.exports = dataURLtoBlob 35677 } else { 35678 window.dataURLtoBlob = dataURLtoBlob 35679 } 35680})(window) 35681; 35682(function() { 35683 var $, AbstractChosen, Chosen, SelectParser, _ref, 35684 __hasProp = {}.hasOwnProperty, 35685 __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; }; 35686 35687 SelectParser = (function() { 35688 function SelectParser() { 35689 this.options_index = 0; 35690 this.parsed = []; 35691 } 35692 35693 SelectParser.prototype.add_node = function(child) { 35694 if (child.nodeName.toUpperCase() === "OPTGROUP") { 35695 return this.add_group(child); 35696 } else { 35697 return this.add_option(child); 35698 } 35699 }; 35700 35701 SelectParser.prototype.add_group = function(group) { 35702 var group_position, option, _i, _len, _ref, _results; 35703 group_position = this.parsed.length; 35704 this.parsed.push({ 35705 array_index: group_position, 35706 group: true, 35707 label: this.escapeExpression(group.label), 35708 title: group.title ? group.title : void 0, 35709 children: 0, 35710 disabled: group.disabled, 35711 classes: group.className 35712 }); 35713 _ref = group.childNodes; 35714 _results = []; 35715 for (_i = 0, _len = _ref.length; _i < _len; _i++) { 35716 option = _ref[_i]; 35717 _results.push(this.add_option(option, group_position, group.disabled)); 35718 } 35719 return _results; 35720 }; 35721 35722 SelectParser.prototype.add_option = function(option, group_position, group_disabled) { 35723 if (option.nodeName.toUpperCase() === "OPTION") { 35724 if (option.text !== "") { 35725 if (group_position != null) { 35726 this.parsed[group_position].children += 1; 35727 } 35728 this.parsed.push({ 35729 array_index: this.parsed.length, 35730 options_index: this.options_index, 35731 value: option.value, 35732 text: option.text, 35733 html: option.innerHTML, 35734 title: option.title ? option.title : void 0, 35735 selected: option.selected, 35736 disabled: group_disabled === true ? group_disabled : option.disabled, 35737 group_array_index: group_position, 35738 group_label: group_position != null ? this.parsed[group_position].label : null, 35739 classes: option.className, 35740 style: option.style.cssText 35741 }); 35742 } else { 35743 this.parsed.push({ 35744 array_index: this.parsed.length, 35745 options_index: this.options_index, 35746 empty: true 35747 }); 35748 } 35749 return this.options_index += 1; 35750 } 35751 }; 35752 35753 SelectParser.prototype.escapeExpression = function(text) { 35754 var map, unsafe_chars; 35755 if ((text == null) || text === false) { 35756 return ""; 35757 } 35758 if (!/[\&\<\>\"\'\`]/.test(text)) { 35759 return text; 35760 } 35761 map = { 35762 "<": "<", 35763 ">": ">", 35764 '"': """, 35765 "'": "'", 35766 "`": "`" 35767 }; 35768 unsafe_chars = /&(?!\w+;)|[\<\>\"\'\`]/g; 35769 return text.replace(unsafe_chars, function(chr) { 35770 return map[chr] || "&"; 35771 }); 35772 }; 35773 35774 return SelectParser; 35775 35776 })(); 35777 35778 SelectParser.select_to_array = function(select) { 35779 var child, parser, _i, _len, _ref; 35780 parser = new SelectParser(); 35781 _ref = select.childNodes; 35782 for (_i = 0, _len = _ref.length; _i < _len; _i++) { 35783 child = _ref[_i]; 35784 parser.add_node(child); 35785 } 35786 return parser.parsed; 35787 }; 35788 35789 AbstractChosen = (function() { 35790 function AbstractChosen(form_field, options) { 35791 this.form_field = form_field; 35792 this.options = options != null ? options : {}; 35793 if (!AbstractChosen.browser_is_supported()) { 35794 return; 35795 } 35796 this.is_multiple = this.form_field.multiple; 35797 this.set_default_text(); 35798 this.set_default_values(); 35799 this.setup(); 35800 this.set_up_html(); 35801 this.register_observers(); 35802 this.on_ready(); 35803 } 35804 35805 AbstractChosen.prototype.set_default_values = function() { 35806 var _this = this; 35807 this.click_test_action = function(evt) { 35808 return _this.test_active_click(evt); 35809 }; 35810 this.activate_action = function(evt) { 35811 return _this.activate_field(evt); 35812 }; 35813 this.active_field = false;
vendor: 13,148 bytes, lines 35814-36173
35814 this.mouse_on_container = false; 35815 this.results_showing = false; 35816 this.result_highlighted = null; 35817 this.allow_single_deselect = (this.options.allow_single_deselect != null) && (this.form_field.options[0] != null) && this.form_field.options[0].text === "" ? this.options.allow_single_deselect : false; 35818 this.disable_search_threshold = this.options.disable_search_threshold || 0; 35819 this.disable_search = this.options.disable_search || false; 35820 this.enable_split_word_search = this.options.enable_split_word_search != null ? this.options.enable_split_word_search : true; 35821 this.group_search = this.options.group_search != null ? this.options.group_search : true; 35822 this.search_contains = this.options.search_contains || false; 35823 this.single_backstroke_delete = this.options.single_backstroke_delete != null ? this.options.single_backstroke_delete : true; 35824 this.max_selected_options = this.options.max_selected_options || Infinity; 35825 this.inherit_select_classes = this.options.inherit_select_classes || false; 35826 this.display_selected_options = this.options.display_selected_options != null ? this.options.display_selected_options : true; 35827 this.display_disabled_options = this.options.display_disabled_options != null ? this.options.display_disabled_options : true; 35828 this.include_group_label_in_selected = this.options.include_group_label_in_selected || false; 35829 this.max_shown_results = this.options.max_shown_results || Number.POSITIVE_INFINITY; 35830 return this.case_sensitive_search = this.options.case_sensitive_search || false; 35831 }; 35832 35833 AbstractChosen.prototype.set_default_text = function() { 35834 if (this.form_field.getAttribute("data-placeholder")) { 35835 this.default_text = this.form_field.getAttribute("data-placeholder"); 35836 } else if (this.is_multiple) { 35837 this.default_text = this.options.placeholder_text_multiple || this.options.placeholder_text || AbstractChosen.default_multiple_text; 35838 } else { 35839 this.default_text = this.options.placeholder_text_single || this.options.placeholder_text || AbstractChosen.default_single_text; 35840 } 35841 return this.results_none_found = this.form_field.getAttribute("data-no_results_text") || this.options.no_results_text || AbstractChosen.default_no_result_text; 35842 }; 35843 35844 AbstractChosen.prototype.choice_label = function(item) { 35845 if (this.include_group_label_in_selected && (item.group_label != null)) { 35846 return "<b class='group-name'>" + item.group_label + "</b>" + item.html; 35847 } else { 35848 return item.html; 35849 } 35850 }; 35851 35852 AbstractChosen.prototype.mouse_enter = function() { 35853 return this.mouse_on_container = true; 35854 }; 35855 35856 AbstractChosen.prototype.mouse_leave = function() { 35857 return this.mouse_on_container = false; 35858 }; 35859 35860 AbstractChosen.prototype.input_focus = function(evt) { 35861 var _this = this; 35862 if (this.is_multiple) { 35863 if (!this.active_field) { 35864 return setTimeout((function() { 35865 return _this.container_mousedown(); 35866 }), 50); 35867 } 35868 } else { 35869 if (!this.active_field) { 35870 return this.activate_field(); 35871 } 35872 } 35873 }; 35874 35875 AbstractChosen.prototype.input_blur = function(evt) { 35876 var _this = this; 35877 if (!this.mouse_on_container) { 35878 this.active_field = false; 35879 return setTimeout((function() { 35880 return _this.blur_test(); 35881 }), 100); 35882 } 35883 }; 35884 35885 AbstractChosen.prototype.results_option_build = function(options) { 35886 var content, data, data_content, shown_results, _i, _len, _ref; 35887 content = ''; 35888 shown_results = 0; 35889 _ref = this.results_data; 35890 for (_i = 0, _len = _ref.length; _i < _len; _i++) { 35891 data = _ref[_i]; 35892 data_content = ''; 35893 if (data.group) { 35894 data_content = this.result_add_group(data); 35895 } else { 35896 data_content = this.result_add_option(data); 35897 } 35898 if (data_content !== '') { 35899 shown_results++; 35900 content += data_content; 35901 } 35902 if (options != null ? options.first : void 0) { 35903 if (data.selected && this.is_multiple) { 35904 this.choice_build(data); 35905 } else if (data.selected && !this.is_multiple) { 35906 this.single_set_selected_text(this.choice_label(data)); 35907 } 35908 } 35909 if (shown_results >= this.max_shown_results) { 35910 break; 35911 } 35912 } 35913 return content; 35914 }; 35915 35916 AbstractChosen.prototype.result_add_option = function(option) { 35917 var classes, option_el; 35918 if (!option.search_match) { 35919 return ''; 35920 } 35921 if (!this.include_option_in_results(option)) { 35922 return ''; 35923 } 35924 classes = []; 35925 if (!option.disabled && !(option.selected && this.is_multiple)) { 35926 classes.push("active-result"); 35927 } 35928 if (option.disabled && !(option.selected && this.is_multiple)) { 35929 classes.push("disabled-result"); 35930 } 35931 if (option.selected) { 35932 classes.push("result-selected"); 35933 } 35934 if (option.group_array_index != null) { 35935 classes.push("group-option"); 35936 } 35937 if (option.classes !== "") { 35938 classes.push(option.classes); 35939 } 35940 option_el = document.createElement("li"); 35941 option_el.className = classes.join(" "); 35942 option_el.style.cssText = option.style; 35943 option_el.setAttribute("data-option-array-index", option.array_index); 35944 option_el.innerHTML = option.search_text; 35945 if (option.title) { 35946 option_el.title = option.title; 35947 } 35948 return this.outerHTML(option_el); 35949 }; 35950 35951 AbstractChosen.prototype.result_add_group = function(group) { 35952 var classes, group_el; 35953 if (!(group.search_match || group.group_match)) { 35954 return ''; 35955 } 35956 if (!(group.active_options > 0)) { 35957 return ''; 35958 } 35959 classes = []; 35960 classes.push("group-result"); 35961 if (group.classes) { 35962 classes.push(group.classes); 35963 } 35964 group_el = document.createElement("li"); 35965 group_el.className = classes.join(" "); 35966 group_el.innerHTML = group.search_text; 35967 if (group.title) { 35968 group_el.title = group.title; 35969 } 35970 return this.outerHTML(group_el); 35971 }; 35972 35973 AbstractChosen.prototype.results_update_field = function() { 35974 this.set_default_text(); 35975 if (!this.is_multiple) { 35976 this.results_reset_cleanup(); 35977 } 35978 this.result_clear_highlight(); 35979 this.results_build(); 35980 if (this.results_showing) { 35981 return this.winnow_results(); 35982 } 35983 }; 35984 35985 AbstractChosen.prototype.reset_single_select_options = function() { 35986 var result, _i, _len, _ref, _results; 35987 _ref = this.results_data; 35988 _results = []; 35989 for (_i = 0, _len = _ref.length; _i < _len; _i++) { 35990 result = _ref[_i]; 35991 if (result.selected) { 35992 _results.push(result.selected = false); 35993 } else { 35994 _results.push(void 0); 35995 } 35996 } 35997 return _results; 35998 }; 35999 36000 AbstractChosen.prototype.results_toggle = function() { 36001 if (this.results_showing) { 36002 return this.results_hide(); 36003 } else { 36004 return this.results_show(); 36005 } 36006 }; 36007 36008 AbstractChosen.prototype.results_search = function(evt) { 36009 if (this.results_showing) { 36010 return this.winnow_results(); 36011 } else { 36012 return this.results_show(); 36013 } 36014 }; 36015 36016 AbstractChosen.prototype.winnow_results = function() { 36017 var escapedSearchText, option, regex, results, results_group, searchText, startpos, text, zregex, _i, _len, _ref; 36018 this.no_results_clear(); 36019 results = 0; 36020 searchText = this.get_search_text(); 36021 escapedSearchText = searchText.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); 36022 zregex = new RegExp(escapedSearchText, 'i'); 36023 regex = this.get_search_regex(escapedSearchText); 36024 _ref = this.results_data; 36025 for (_i = 0, _len = _ref.length; _i < _len; _i++) { 36026 option = _ref[_i]; 36027 option.search_match = false; 36028 results_group = null; 36029 if (this.include_option_in_results(option)) { 36030 if (option.group) { 36031 option.group_match = false; 36032 option.active_options = 0; 36033 } 36034 if ((option.group_array_index != null) && this.results_data[option.group_array_index]) { 36035 results_group = this.results_data[option.group_array_index]; 36036 if (results_group.active_options === 0 && results_group.search_match) { 36037 results += 1; 36038 } 36039 results_group.active_options += 1; 36040 } 36041 option.search_text = option.group ? option.label : option.html; 36042 if (!(option.group && !this.group_search)) { 36043 option.search_match = this.search_string_match(option.search_text, regex); 36044 if (option.search_match && !option.group) { 36045 results += 1; 36046 } 36047 if (option.search_match) { 36048 if (searchText.length) { 36049 startpos = option.search_text.search(zregex); 36050 text = option.search_text.substr(0, startpos + searchText.length) + '</em>' + option.search_text.substr(startpos + searchText.length); 36051 option.search_text = text.substr(0, startpos) + '<em>' + text.substr(startpos); 36052 } 36053 if (results_group != null) { 36054 results_group.group_match = true; 36055 } 36056 } else if ((option.group_array_index != null) && this.results_data[option.group_array_index].search_match) { 36057 option.search_match = true; 36058 } 36059 } 36060 } 36061 } 36062 this.result_clear_highlight(); 36063 if (results < 1 && searchText.length) { 36064 this.update_results_content(""); 36065 return this.no_results(searchText); 36066 } else { 36067 this.update_results_content(this.results_option_build()); 36068 return this.winnow_results_set_highlight(); 36069 } 36070 }; 36071 36072 AbstractChosen.prototype.get_search_regex = function(escaped_search_string) { 36073 var regex_anchor, regex_flag; 36074 regex_anchor = this.search_contains ? "" : "^"; 36075 regex_flag = this.case_sensitive_search ? "" : "i"; 36076 return new RegExp(regex_anchor + escaped_search_string, regex_flag); 36077 }; 36078 36079 AbstractChosen.prototype.search_string_match = function(search_string, regex) { 36080 var part, parts, _i, _len; 36081 if (regex.test(search_string)) { 36082 return true; 36083 } else if (this.enable_split_word_search && (search_string.indexOf(" ") >= 0 || search_string.indexOf("[") === 0)) { 36084 parts = search_string.replace(/\[|\]/g, "").split(" "); 36085 if (parts.length) { 36086 for (_i = 0, _len = parts.length; _i < _len; _i++) { 36087 part = parts[_i]; 36088 if (regex.test(part)) { 36089 return true; 36090 } 36091 } 36092 } 36093 } 36094 }; 36095 36096 AbstractChosen.prototype.choices_count = function() { 36097 var option, _i, _len, _ref; 36098 if (this.selected_option_count != null) { 36099 return this.selected_option_count; 36100 } 36101 this.selected_option_count = 0; 36102 _ref = this.form_field.options; 36103 for (_i = 0, _len = _ref.length; _i < _len; _i++) { 36104 option = _ref[_i]; 36105 if (option.selected) { 36106 this.selected_option_count += 1; 36107 } 36108 } 36109 return this.selected_option_count; 36110 }; 36111 36112 AbstractChosen.prototype.choices_click = function(evt) { 36113 evt.preventDefault(); 36114 if (!(this.results_showing || this.is_disabled)) { 36115 return this.results_show(); 36116 } 36117 }; 36118 36119 AbstractChosen.prototype.keyup_checker = function(evt) { 36120 var stroke, _ref; 36121 stroke = (_ref = evt.which) != null ? _ref : evt.keyCode; 36122 this.search_field_scale(); 36123 switch (stroke) { 36124 case 8: 36125 if (this.is_multiple && this.backstroke_length < 1 && this.choices_count() > 0) { 36126 return this.keydown_backstroke(); 36127 } else if (!this.pending_backstroke) { 36128 this.result_clear_highlight(); 36129 return this.results_search(); 36130 } 36131 break; 36132 case 13: 36133 evt.preventDefault(); 36134 if (this.results_showing) { 36135 return this.result_select(evt); 36136 } 36137 break; 36138 case 27: 36139 if (this.results_showing) { 36140 this.results_hide(); 36141 } 36142 return true; 36143 case 9: 36144 case 38: 36145 case 40: 36146 case 16: 36147 case 91: 36148 case 17: 36149 case 18: 36150 break; 36151 default: 36152 return this.results_search(); 36153 } 36154 }; 36155 36156 AbstractChosen.prototype.clipboard_event_checker = function(evt) { 36157 var _this = this; 36158 return setTimeout((function() { 36159 return _this.results_search(); 36160 }), 50); 36161 }; 36162 36163 AbstractChosen.prototype.container_width = function() { 36164 if (this.options.width != null) { 36165 return this.options.width; 36166 } else { 36167 return "" + this.form_field.offsetWidth + "px"; 36168 } 36169 }; 36170 36171 AbstractChosen.prototype.include_option_in_results = function(option) { 36172 if (this.is_multiple && (!this.display_selected_options && option.selected)) { 36173 return false;
vendor: 1,446 bytes, lines 36174-36215
36174 } 36175 if (!this.display_disabled_options && option.disabled) { 36176 return false; 36177 } 36178 if (option.empty) { 36179 return false; 36180 } 36181 return true; 36182 }; 36183 36184 AbstractChosen.prototype.search_results_touchstart = function(evt) { 36185 this.touch_started = true; 36186 return this.search_results_mouseover(evt); 36187 }; 36188 36189 AbstractChosen.prototype.search_results_touchmove = function(evt) { 36190 this.touch_started = false; 36191 return this.search_results_mouseout(evt); 36192 }; 36193 36194 AbstractChosen.prototype.search_results_touchend = function(evt) { 36195 if (this.touch_started) { 36196 return this.search_results_mouseup(evt); 36197 } 36198 }; 36199 36200 AbstractChosen.prototype.outerHTML = function(element) { 36201 var tmp; 36202 if (element.outerHTML) { 36203 return element.outerHTML; 36204 } 36205 tmp = document.createElement("div"); 36206 tmp.appendChild(element); 36207 return tmp.innerHTML; 36208 }; 36209 36210 AbstractChosen.browser_is_supported = function() { 36211 if ("Microsoft Internet Explorer" === window.navigator.appName) { 36212 return document.documentMode >= 8; 36213 } 36214 if (/iP(od|hone)/i.test(window.navigator.userAgent) || /IEMobile/i.test(window.navigator.userAgent) || /Windows Phone/i.test(window.navigator.userAgent) || /BlackBerry/i.test(window.navigator.userAgent) || /BB10/i.test(window.navigator.userAgent) || /Android.*Mobile/i.test(window.navigator.userAgent)) { 36215 return false
vendor: 25,590 bytes, lines 36215-36938
36215; 36216 } 36217 return true; 36218 }; 36219 36220 AbstractChosen.default_multiple_text = "Select Some Options"; 36221 36222 AbstractChosen.default_single_text = "Select an Option"; 36223 36224 AbstractChosen.default_no_result_text = "No results match"; 36225 36226 return AbstractChosen; 36227 36228 })(); 36229 36230 $ = jQuery; 36231 36232 $.fn.extend({ 36233 chosen: function(options) { 36234 if (!AbstractChosen.browser_is_supported()) { 36235 return this; 36236 } 36237 return this.each(function(input_field) { 36238 var $this, chosen; 36239 $this = $(this); 36240 chosen = $this.data('chosen'); 36241 if (options === 'destroy') { 36242 if (chosen instanceof Chosen) { 36243 chosen.destroy(); 36244 } 36245 return; 36246 } 36247 if (!(chosen instanceof Chosen)) { 36248 $this.data('chosen', new Chosen(this, options)); 36249 } 36250 }); 36251 } 36252 }); 36253 36254 Chosen = (function(_super) { 36255 __extends(Chosen, _super); 36256 36257 function Chosen() { 36258 _ref = Chosen.__super__.constructor.apply(this, arguments); 36259 return _ref; 36260 } 36261 36262 Chosen.prototype.setup = function() { 36263 this.form_field_jq = $(this.form_field); 36264 this.current_selectedIndex = this.form_field.selectedIndex; 36265 return this.is_rtl = this.form_field_jq.hasClass("chosen-rtl"); 36266 }; 36267 36268 Chosen.prototype.set_up_html = function() { 36269 var container_classes, container_props; 36270 container_classes = ["chosen-container"]; 36271 container_classes.push("chosen-container-" + (this.is_multiple ? "multi" : "single")); 36272 if (this.inherit_select_classes && this.form_field.className) { 36273 container_classes.push(this.form_field.className); 36274 } 36275 if (this.is_rtl) { 36276 container_classes.push("chosen-rtl"); 36277 } 36278 container_props = { 36279 'class': container_classes.join(' '), 36280 'style': "width: " + (this.container_width()) + ";", 36281 'title': this.form_field.title 36282 }; 36283 if (this.form_field.id.length) { 36284 container_props.id = this.form_field.id.replace(/[^\w]/g, '_') + "_chosen"; 36285 } 36286 this.container = $("<div />", container_props); 36287 if (this.is_multiple) { 36288 this.container.html('<ul class="chosen-choices"><li class="search-field"><input type="text" value="' + this.default_text + '" class="default" autocomplete="off" style="width:25px;" /></li></ul><div class="chosen-drop"><ul class="chosen-results"></ul></div>'); 36289 } else { 36290 this.container.html('<a class="chosen-single chosen-default"><span>' + this.default_text + '</span><div><b></b></div></a><div class="chosen-drop"><div class="chosen-search"><input type="text" autocomplete="off" /></div><ul class="chosen-results"></ul></div>'); 36291 } 36292 this.form_field_jq.hide().after(this.container); 36293 this.dropdown = this.container.find('div.chosen-drop').first(); 36294 this.search_field = this.container.find('input').first(); 36295 this.search_results = this.container.find('ul.chosen-results').first(); 36296 this.search_field_scale(); 36297 this.search_no_results = this.container.find('li.no-results').first(); 36298 if (this.is_multiple) { 36299 this.search_choices = this.container.find('ul.chosen-choices').first(); 36300 this.search_container = this.container.find('li.search-field').first(); 36301 } else { 36302 this.search_container = this.container.find('div.chosen-search').first(); 36303 this.selected_item = this.container.find('.chosen-single').first(); 36304 } 36305 this.results_build(); 36306 this.set_tab_index(); 36307 return this.set_label_behavior(); 36308 }; 36309 36310 Chosen.prototype.on_ready = function() { 36311 return this.form_field_jq.trigger("chosen:ready", { 36312 chosen: this 36313 }); 36314 }; 36315 36316 Chosen.prototype.register_observers = function() { 36317 var _this = this; 36318 this.container.bind('touchstart.chosen', function(evt) { 36319 _this.container_mousedown(evt); 36320 return evt.preventDefault(); 36321 }); 36322 this.container.bind('touchend.chosen', function(evt) { 36323 _this.container_mouseup(evt); 36324 return evt.preventDefault(); 36325 }); 36326 this.container.bind('mousedown.chosen', function(evt) { 36327 _this.container_mousedown(evt); 36328 }); 36329 this.container.bind('mouseup.chosen', function(evt) { 36330 _this.container_mouseup(evt); 36331 }); 36332 this.container.bind('mouseenter.chosen', function(evt) { 36333 _this.mouse_enter(evt); 36334 }); 36335 this.container.bind('mouseleave.chosen', function(evt) { 36336 _this.mouse_leave(evt); 36337 }); 36338 this.search_results.bind('mouseup.chosen', function(evt) { 36339 _this.search_results_mouseup(evt); 36340 }); 36341 this.search_results.bind('mouseover.chosen', function(evt) { 36342 _this.search_results_mouseover(evt); 36343 }); 36344 this.search_results.bind('mouseout.chosen', function(evt) { 36345 _this.search_results_mouseout(evt); 36346 }); 36347 this.search_results.bind('mousewheel.chosen DOMMouseScroll.chosen', function(evt) { 36348 _this.search_results_mousewheel(evt); 36349 }); 36350 this.search_results.bind('touchstart.chosen', function(evt) { 36351 _this.search_results_touchstart(evt); 36352 }); 36353 this.search_results.bind('touchmove.chosen', function(evt) { 36354 _this.search_results_touchmove(evt); 36355 }); 36356 this.search_results.bind('touchend.chosen', function(evt) { 36357 _this.search_results_touchend(evt); 36358 }); 36359 this.form_field_jq.bind("chosen:updated.chosen", function(evt) { 36360 _this.results_update_field(evt); 36361 }); 36362 this.form_field_jq.bind("chosen:activate.chosen", function(evt) { 36363 _this.activate_field(evt); 36364 }); 36365 this.form_field_jq.bind("chosen:open.chosen", function(evt) { 36366 _this.container_mousedown(evt); 36367 }); 36368 this.form_field_jq.bind("chosen:close.chosen", function(evt) { 36369 _this.input_blur(evt); 36370 }); 36371 this.search_field.bind('blur.chosen', function(evt) { 36372 _this.input_blur(evt); 36373 }); 36374 this.search_field.bind('keyup.chosen', function(evt) { 36375 _this.keyup_checker(evt); 36376 }); 36377 this.search_field.bind('keydown.chosen', function(evt) { 36378 _this.keydown_checker(evt); 36379 }); 36380 this.search_field.bind('focus.chosen', function(evt) { 36381 _this.input_focus(evt); 36382 }); 36383 this.search_field.bind('cut.chosen', function(evt) { 36384 _this.clipboard_event_checker(evt); 36385 }); 36386 this.search_field.bind('paste.chosen', function(evt) { 36387 _this.clipboard_event_checker(evt); 36388 }); 36389 if (this.is_multiple) { 36390 return this.search_choices.bind('click.chosen', function(evt) { 36391 _this.choices_click(evt); 36392 }); 36393 } else { 36394 return this.container.bind('click.chosen', function(evt) { 36395 evt.preventDefault(); 36396 }); 36397 } 36398 }; 36399 36400 Chosen.prototype.destroy = function() { 36401 $(this.container[0].ownerDocument).unbind("click.chosen", this.click_test_action); 36402 if (this.search_field[0].tabIndex) { 36403 this.form_field_jq[0].tabIndex = this.search_field[0].tabIndex; 36404 } 36405 this.container.remove(); 36406 this.form_field_jq.removeData('chosen'); 36407 return this.form_field_jq.show(); 36408 }; 36409 36410 Chosen.prototype.search_field_disabled = function() { 36411 this.is_disabled = this.form_field_jq[0].disabled; 36412 if (this.is_disabled) { 36413 this.container.addClass('chosen-disabled'); 36414 this.search_field[0].disabled = true; 36415 if (!this.is_multiple) { 36416 this.selected_item.unbind("focus.chosen", this.activate_action); 36417 } 36418 return this.close_field(); 36419 } else { 36420 this.container.removeClass('chosen-disabled'); 36421 this.search_field[0].disabled = false; 36422 if (!this.is_multiple) { 36423 return this.selected_item.bind("focus.chosen", this.activate_action); 36424 } 36425 } 36426 }; 36427 36428 Chosen.prototype.container_mousedown = function(evt) { 36429 if (!this.is_disabled) { 36430 if (evt && evt.type === "mousedown" && !this.results_showing) { 36431 evt.preventDefault(); 36432 } 36433 if (!((evt != null) && ($(evt.target)).hasClass("search-choice-close"))) { 36434 if (!this.active_field) { 36435 if (this.is_multiple) { 36436 this.search_field.val(""); 36437 } 36438 $(this.container[0].ownerDocument).bind('click.chosen', this.click_test_action); 36439 this.results_show(); 36440 } else if (!this.is_multiple && evt && (($(evt.target)[0] === this.selected_item[0]) || $(evt.target).parents("a.chosen-single").length)) { 36441 evt.preventDefault(); 36442 this.results_toggle(); 36443 } 36444 return this.activate_field(); 36445 } 36446 } 36447 }; 36448 36449 Chosen.prototype.container_mouseup = function(evt) { 36450 if (evt.target.nodeName === "ABBR" && !this.is_disabled) { 36451 return this.results_reset(evt); 36452 } 36453 }; 36454 36455 Chosen.prototype.search_results_mousewheel = function(evt) { 36456 var delta; 36457 if (evt.originalEvent) { 36458 delta = evt.originalEvent.deltaY || -evt.originalEvent.wheelDelta || evt.originalEvent.detail; 36459 } 36460 if (delta != null) { 36461 evt.preventDefault(); 36462 if (evt.type === 'DOMMouseScroll') { 36463 delta = delta * 40; 36464 } 36465 return this.search_results.scrollTop(delta + this.search_results.scrollTop()); 36466 } 36467 }; 36468 36469 Chosen.prototype.blur_test = function(evt) { 36470 if (!this.active_field && this.container.hasClass("chosen-container-active")) { 36471 return this.close_field(); 36472 } 36473 }; 36474 36475 Chosen.prototype.close_field = function() { 36476 $(this.container[0].ownerDocument).unbind("click.chosen", this.click_test_action); 36477 this.active_field = false; 36478 this.results_hide(); 36479 this.container.removeClass("chosen-container-active"); 36480 this.clear_backstroke(); 36481 this.show_search_field_default(); 36482 return this.search_field_scale(); 36483 }; 36484 36485 Chosen.prototype.activate_field = function() { 36486 this.container.addClass("chosen-container-active"); 36487 this.active_field = true; 36488 this.search_field.val(this.search_field.val()); 36489 return this.search_field.focus(); 36490 }; 36491 36492 Chosen.prototype.test_active_click = function(evt) { 36493 var active_container; 36494 active_container = $(evt.target).closest('.chosen-container'); 36495 if (active_container.length && this.container[0] === active_container[0]) { 36496 return this.active_field = true; 36497 } else { 36498 return this.close_field(); 36499 } 36500 }; 36501 36502 Chosen.prototype.results_build = function() { 36503 this.parsing = true; 36504 this.selected_option_count = null; 36505 this.results_data = SelectParser.select_to_array(this.form_field); 36506 if (this.is_multiple) { 36507 this.search_choices.find("li.search-choice").remove(); 36508 } else if (!this.is_multiple) { 36509 this.single_set_selected_text(); 36510 if (this.disable_search || this.form_field.options.length <= this.disable_search_threshold) { 36511 this.search_field[0].readOnly = true; 36512 this.container.addClass("chosen-container-single-nosearch"); 36513 } else { 36514 this.search_field[0].readOnly = false; 36515 this.container.removeClass("chosen-container-single-nosearch"); 36516 } 36517 } 36518 this.update_results_content(this.results_option_build({ 36519 first: true 36520 })); 36521 this.search_field_disabled(); 36522 this.show_search_field_default(); 36523 this.search_field_scale(); 36524 return this.parsing = false; 36525 }; 36526 36527 Chosen.prototype.result_do_highlight = function(el) { 36528 var high_bottom, high_top, maxHeight, visible_bottom, visible_top; 36529 if (el.length) { 36530 this.result_clear_highlight(); 36531 this.result_highlight = el; 36532 this.result_highlight.addClass("highlighted"); 36533 maxHeight = parseInt(this.search_results.css("maxHeight"), 10); 36534 visible_top = this.search_results.scrollTop(); 36535 visible_bottom = maxHeight + visible_top; 36536 high_top = this.result_highlight.position().top + this.search_results.scrollTop(); 36537 high_bottom = high_top + this.result_highlight.outerHeight(); 36538 if (high_bottom >= visible_bottom) { 36539 return this.search_results.scrollTop((high_bottom - maxHeight) > 0 ? high_bottom - maxHeight : 0); 36540 } else if (high_top < visible_top) { 36541 return this.search_results.scrollTop(high_top); 36542 } 36543 } 36544 }; 36545 36546 Chosen.prototype.result_clear_highlight = function() { 36547 if (this.result_highlight) { 36548 this.result_highlight.removeClass("highlighted"); 36549 } 36550 return this.result_highlight = null; 36551 }; 36552 36553 Chosen.prototype.results_show = function() { 36554 if (this.is_multiple && this.max_selected_options <= this.choices_count()) { 36555 this.form_field_jq.trigger("chosen:maxselected", { 36556 chosen: this 36557 }); 36558 return false; 36559 } 36560 this.container.addClass("chosen-with-drop"); 36561 this.results_showing = true; 36562 this.search_field.focus(); 36563 this.search_field.val(this.search_field.val()); 36564 this.winnow_results(); 36565 return this.form_field_jq.trigger("chosen:showing_dropdown", { 36566 chosen: this 36567 }); 36568 }; 36569 36570 Chosen.prototype.update_results_content = function(content) { 36571 return this.search_results.html(content); 36572 }; 36573 36574 Chosen.prototype.results_hide = function() { 36575 if (this.results_showing) { 36576 this.result_clear_highlight(); 36577 this.container.removeClass("chosen-with-drop"); 36578 this.form_field_jq.trigger("chosen:hiding_dropdown", { 36579 chosen: this 36580 }); 36581 } 36582 return this.results_showing = false; 36583 }; 36584 36585 Chosen.prototype.set_tab_index = function(el) { 36586 var ti; 36587 if (this.form_field.tabIndex) { 36588 ti = this.form_field.tabIndex; 36589 this.form_field.tabIndex = -1; 36590 return this.search_field[0].tabIndex = ti; 36591 } 36592 }; 36593 36594 Chosen.prototype.set_label_behavior = function() { 36595 var _this = this; 36596 this.form_field_label = this.form_field_jq.parents("label"); 36597 if (!this.form_field_label.length && this.form_field.id.length) { 36598 this.form_field_label = $("label[for='" + this.form_field.id + "']"); 36599 } 36600 if (this.form_field_label.length > 0) { 36601 return this.form_field_label.bind('click.chosen', function(evt) { 36602 if (_this.is_multiple) { 36603 return _this.container_mousedown(evt); 36604 } else { 36605 return _this.activate_field(); 36606 } 36607 }); 36608 } 36609 }; 36610 36611 Chosen.prototype.show_search_field_default = function() { 36612 if (this.is_multiple && this.choices_count() < 1 && !this.active_field) { 36613 this.search_field.val(this.default_text); 36614 return this.search_field.addClass("default"); 36615 } else { 36616 this.search_field.val(""); 36617 return this.search_field.removeClass("default"); 36618 } 36619 }; 36620 36621 Chosen.prototype.search_results_mouseup = function(evt) { 36622 var target; 36623 target = $(evt.target).hasClass("active-result") ? $(evt.target) : $(evt.target).parents(".active-result").first(); 36624 if (target.length) { 36625 this.result_highlight = target; 36626 this.result_select(evt); 36627 return this.search_field.focus(); 36628 } 36629 }; 36630 36631 Chosen.prototype.search_results_mouseover = function(evt) { 36632 var target; 36633 target = $(evt.target).hasClass("active-result") ? $(evt.target) : $(evt.target).parents(".active-result").first(); 36634 if (target) { 36635 return this.result_do_highlight(target); 36636 } 36637 }; 36638 36639 Chosen.prototype.search_results_mouseout = function(evt) { 36640 if ($(evt.target).hasClass("active-result" || $(evt.target).parents('.active-result').first())) { 36641 return this.result_clear_highlight(); 36642 } 36643 }; 36644 36645 Chosen.prototype.choice_build = function(item) { 36646 var choice, close_link, 36647 _this = this; 36648 choice = $('<li />', { 36649 "class": "search-choice" 36650 }).html("<span>" + (this.choice_label(item)) + "</span>"); 36651 if (item.disabled) { 36652 choice.addClass('search-choice-disabled'); 36653 } else { 36654 close_link = $('<a />', { 36655 "class": 'search-choice-close', 36656 'data-option-array-index': item.array_index 36657 }); 36658 close_link.bind('click.chosen', function(evt) { 36659 return _this.choice_destroy_link_click(evt); 36660 }); 36661 choice.append(close_link); 36662 } 36663 return this.search_container.before(choice); 36664 }; 36665 36666 Chosen.prototype.choice_destroy_link_click = function(evt) { 36667 evt.preventDefault(); 36668 evt.stopPropagation(); 36669 if (!this.is_disabled) { 36670 return this.choice_destroy($(evt.target)); 36671 } 36672 }; 36673 36674 Chosen.prototype.choice_destroy = function(link) { 36675 if (this.result_deselect(link[0].getAttribute("data-option-array-index"))) { 36676 this.show_search_field_default(); 36677 if (this.is_multiple && this.choices_count() > 0 && this.search_field.val().length < 1) { 36678 this.results_hide(); 36679 } 36680 link.parents('li').first().remove(); 36681 return this.search_field_scale(); 36682 } 36683 }; 36684 36685 Chosen.prototype.results_reset = function() { 36686 this.reset_single_select_options(); 36687 this.form_field.options[0].selected = true; 36688 this.single_set_selected_text(); 36689 this.show_search_field_default(); 36690 this.results_reset_cleanup(); 36691 this.form_field_jq.trigger("change"); 36692 if (this.active_field) { 36693 return this.results_hide(); 36694 } 36695 }; 36696 36697 Chosen.prototype.results_reset_cleanup = function() { 36698 this.current_selectedIndex = this.form_field.selectedIndex; 36699 return this.selected_item.find("abbr").remove(); 36700 }; 36701 36702 Chosen.prototype.result_select = function(evt) { 36703 var high, item; 36704 if (this.result_highlight) { 36705 high = this.result_highlight; 36706 this.result_clear_highlight(); 36707 if (this.is_multiple && this.max_selected_options <= this.choices_count()) { 36708 this.form_field_jq.trigger("chosen:maxselected", { 36709 chosen: this 36710 }); 36711 return false; 36712 } 36713 if (this.is_multiple) { 36714 high.removeClass("active-result"); 36715 } else { 36716 this.reset_single_select_options(); 36717 } 36718 high.addClass("result-selected"); 36719 item = this.results_data[high[0].getAttribute("data-option-array-index")]; 36720 item.selected = true; 36721 this.form_field.options[item.options_index].selected = true; 36722 this.selected_option_count = null; 36723 if (this.is_multiple) { 36724 this.choice_build(item); 36725 } else { 36726 this.single_set_selected_text(this.choice_label(item)); 36727 } 36728 if (!((evt.metaKey || evt.ctrlKey) && this.is_multiple)) { 36729 this.results_hide(); 36730 } 36731 this.show_search_field_default(); 36732 if (this.is_multiple || this.form_field.selectedIndex !== this.current_selectedIndex) { 36733 this.form_field_jq.trigger("change", { 36734 'selected': this.form_field.options[item.options_index].value 36735 }); 36736 } 36737 this.current_selectedIndex = this.form_field.selectedIndex; 36738 evt.preventDefault(); 36739 return this.search_field_scale(); 36740 } 36741 }; 36742 36743 Chosen.prototype.single_set_selected_text = function(text) { 36744 if (text == null) { 36745 text = this.default_text; 36746 } 36747 if (text === this.default_text) { 36748 this.selected_item.addClass("chosen-default"); 36749 } else { 36750 this.single_deselect_control_build(); 36751 this.selected_item.removeClass("chosen-default"); 36752 } 36753 return this.selected_item.find("span").html(text); 36754 }; 36755 36756 Chosen.prototype.result_deselect = function(pos) { 36757 var result_data; 36758 result_data = this.results_data[pos]; 36759 if (!this.form_field.options[result_data.options_index].disabled) { 36760 result_data.selected = false; 36761 this.form_field.options[result_data.options_index].selected = false; 36762 this.selected_option_count = null; 36763 this.result_clear_highlight(); 36764 if (this.results_showing) { 36765 this.winnow_results(); 36766 } 36767 this.form_field_jq.trigger("change", { 36768 deselected: this.form_field.options[result_data.options_index].value 36769 }); 36770 this.search_field_scale(); 36771 return true; 36772 } else { 36773 return false; 36774 } 36775 }; 36776 36777 Chosen.prototype.single_deselect_control_build = function() { 36778 if (!this.allow_single_deselect) { 36779 return; 36780 } 36781 if (!this.selected_item.find("abbr").length) { 36782 this.selected_item.find("span").first().after("<abbr class=\"search-choice-close\"></abbr>"); 36783 } 36784 return this.selected_item.addClass("chosen-single-with-deselect"); 36785 }; 36786 36787 Chosen.prototype.get_search_text = function() { 36788 return $('<div/>').text($.trim(this.search_field.val())).html(); 36789 }; 36790 36791 Chosen.prototype.winnow_results_set_highlight = function() { 36792 var do_high, selected_results; 36793 selected_results = !this.is_multiple ? this.search_results.find(".result-selected.active-result") : []; 36794 do_high = selected_results.length ? selected_results.first() : this.search_results.find(".active-result").first(); 36795 if (do_high != null) { 36796 return this.result_do_highlight(do_high); 36797 } 36798 }; 36799 36800 Chosen.prototype.no_results = function(terms) { 36801 var no_results_html; 36802 no_results_html = $('<li class="no-results">' + this.results_none_found + ' "<span></span>"</li>'); 36803 no_results_html.find("span").first().html(terms); 36804 this.search_results.append(no_results_html); 36805 return this.form_field_jq.trigger("chosen:no_results", { 36806 chosen: this 36807 }); 36808 }; 36809 36810 Chosen.prototype.no_results_clear = function() { 36811 return this.search_results.find(".no-results").remove(); 36812 }; 36813 36814 Chosen.prototype.keydown_arrow = function() { 36815 var next_sib; 36816 if (this.results_showing && this.result_highlight) { 36817 next_sib = this.result_highlight.nextAll("li.active-result").first(); 36818 if (next_sib) { 36819 return this.result_do_highlight(next_sib); 36820 } 36821 } else { 36822 return this.results_show(); 36823 } 36824 }; 36825 36826 Chosen.prototype.keyup_arrow = function() { 36827 var prev_sibs; 36828 if (!this.results_showing && !this.is_multiple) { 36829 return this.results_show(); 36830 } else if (this.result_highlight) { 36831 prev_sibs = this.result_highlight.prevAll("li.active-result"); 36832 if (prev_sibs.length) { 36833 return this.result_do_highlight(prev_sibs.first()); 36834 } else { 36835 if (this.choices_count() > 0) { 36836 this.results_hide(); 36837 } 36838 return this.result_clear_highlight(); 36839 } 36840 } 36841 }; 36842 36843 Chosen.prototype.keydown_backstroke = function() { 36844 var next_available_destroy; 36845 if (this.pending_backstroke) { 36846 this.choice_destroy(this.pending_backstroke.find("a").first()); 36847 return this.clear_backstroke(); 36848 } else { 36849 next_available_destroy = this.search_container.siblings("li.search-choice").last(); 36850 if (next_available_destroy.length && !next_available_destroy.hasClass("search-choice-disabled")) { 36851 this.pending_backstroke = next_available_destroy; 36852 if (this.single_backstroke_delete) { 36853 return this.keydown_backstroke(); 36854 } else { 36855 return this.pending_backstroke.addClass("search-choice-focus"); 36856 } 36857 } 36858 } 36859 }; 36860 36861 Chosen.prototype.clear_backstroke = function() { 36862 if (this.pending_backstroke) { 36863 this.pending_backstroke.removeClass("search-choice-focus"); 36864 } 36865 return this.pending_backstroke = null; 36866 }; 36867 36868 Chosen.prototype.keydown_checker = function(evt) { 36869 var stroke, _ref1; 36870 stroke = (_ref1 = evt.which) != null ? _ref1 : evt.keyCode; 36871 this.search_field_scale(); 36872 if (stroke !== 8 && this.pending_backstroke) { 36873 this.clear_backstroke(); 36874 } 36875 switch (stroke) { 36876 case 8: 36877 this.backstroke_length = this.search_field.val().length; 36878 break; 36879 case 9: 36880 if (this.results_showing && !this.is_multiple) { 36881 this.result_select(evt); 36882 } 36883 this.mouse_on_container = false; 36884 break; 36885 case 13: 36886 if (this.results_showing) { 36887 evt.preventDefault(); 36888 } 36889 break; 36890 case 32: 36891 if (this.disable_search) { 36892 evt.preventDefault(); 36893 } 36894 break; 36895 case 38: 36896 evt.preventDefault(); 36897 this.keyup_arrow(); 36898 break; 36899 case 40: 36900 evt.preventDefault(); 36901 this.keydown_arrow(); 36902 break; 36903 } 36904 }; 36905 36906 Chosen.prototype.search_field_scale = function() { 36907 var div, f_width, h, style, style_block, styles, w, _i, _len; 36908 if (this.is_multiple) { 36909 h = 0; 36910 w = 0; 36911 style_block = "position:absolute; left: -1000px; top: -1000px; display:none;"; 36912 styles = ['font-size', 'font-style', 'font-weight', 'font-family', 'line-height', 'text-transform', 'letter-spacing']; 36913 for (_i = 0, _len = styles.length; _i < _len; _i++) { 36914 style = styles[_i]; 36915 style_block += style + ":" + this.search_field.css(style) + ";"; 36916 } 36917 div = $('<div />', { 36918 'style': style_block 36919 }); 36920 div.text(this.search_field.val()); 36921 $('body').append(div); 36922 w = div.width() + 25; 36923 div.remove(); 36924 f_width = this.container.outerWidth(); 36925 if (w > f_width - 10) { 36926 w = f_width - 10; 36927 } 36928 return this.search_field.css({ 36929 'width': w + 'px' 36930 }); 36931 } 36932 }; 36933 36934 return Chosen; 36935 36936 })(AbstractChosen); 36937 36938}).call(this);
36939 36940define("chosen", ["jquery"], (function (global) { 36941 return function () { 36942 var ret, fn; 36943 return ret || global.$; 36944 }; 36945}(this))); 36946 36947/* 36948 * For the given element hide children with an index greater than n. 36949 * 36950 * Examples: 36951 * 36952 * 1. For compacting a list 36953 * 36954 * <ul class="foo"> 36955 * <li>1st Child</li> 36956 * <li>2nd Child</li> 36957 * <li>3rd Child</li> 36958 * <li>4th Child</li> 36959 * <li>5th Child</li> 36960 * </ul> 36961 * 36962 * $('.foo').compactChildren(); 36963 * 36964 * 2. Set options for all matched elements by passing arguments to compactChildren(). 36965 * 36966 * $('.foo').compactChildren({ numberChildren: 5 }); 36967 * 36968 * 3. Set global defaults values using the CompactChildren.defaults object. 36969 * 36970 * CompactChildren.defaults.numberChildren = false 36971 * 36972 * TODO 36973 * 1. Allow users to provide selectors for their own more and fewer links. 36974 */ 36975 36976; (function ($, window, document, undefined) { 36977 36978 'use strict'; 36979 var pluginName = 'compactChildren', 36980 Plugin = function (element, options) { 36981 this.element = element; 36982 this.$element = $(element); 36983 this.options = options; 36984 this.metadata = this.$element.data(); 36985 36986 this._name = pluginName; 36987 }; 36988 36989 Plugin.prototype = { 36990 defaults: { 36991 numberChildren: 3, 36992 moreElement: '' 36993 }, 36994 36995 init: function () { 36996 36997 this.config = $.extend( 36998 {}, 36999 this.defaults, 37000 this.options, 37001 this.metadata); 37002 37003 // If less child elements than 37004 if (this.$element.children().length < this.config.numberChildren + 1){ 37005 return this; 37006 } 37007 37008 this._hideChildren(); 37009 37010 this._addMoreLink(); 37011 37012 this._addFewerLink(); 37013 37014 return this; 37015 }, 37016 37017 _hideChildren: function () { 37018 var index = this.config.numberChildren - 1; 37019 this.$element.children(':gt(' + index + ')').hide(); 37020 }, 37021 37022 _showChildren: function () { 37023 this.$element.children().show(); 37024 }, 37025 37026 _addMoreLink: function () { 37027 37028 var self = this; 37029 37030 // Insert link into DOM 37031 self.$element.append('<small class="js-compact-children-more"><a href="#">More</a> <i class="icon-caret-down"></i></small>'); 37032 37033 // Create a delegate event as we cannot be sure the link has been added yet 37034 self.$element.on('click', '.js-compact-children-more', function (event) { 37035 event.preventDefault(); 37036 self._showChildren(); 37037 self._hideLink('.js-compact-children-more'); 37038 self._showLink('.js-compact-children-fewer') 37039 }); 37040 37041 }, 37042 37043 _addFewerLink: function () { 37044 37045 var self = this; 37046 37047 self.$element.append('<small class="js-compact-children-fewer" style="display: none;"><a href="#">Fewer</a> <i class="icon-caret-up"></i></small>'); 37048 37049 self.$element.on('click', '.js-compact-children-fewer', function (event) { 37050 event.preventDefault(); 37051 self._hideChildren(); 37052 self._hideLink('.js-compact-children-fewer'); 37053 self._showLink('.js-compact-children-more'); 37054 }); 37055 37056 }, 37057 37058 _hideLink: function (selector) { 37059 this.$element.children(selector).hide(); 37060 }, 37061 37062 _showLink: function (selector) { 37063 this.$element.children(selector).show(); 37064 } 37065 37066 }; 37067 37068 Plugin.defaults = Plugin.prototype.defaults; 37069 37070 $.fn[pluginName] = function (options) { 37071 return this.each(function () { 37072 new Plugin(this, options).init(); 37073 }); 37074 }; 37075 37076 //Expose the plugin class so it can be modified 37077 window.CompactChildren = Plugin; 37078 37079})(jQuery, window, document); 37080 37081define("compactChildren", ["jquery"], (function (global) { 37082 return function () { 37083 var ret, fn; 37084 return ret || global.$; 37085 }; 37086}(this))); 37087 37088/* 37089 * cropit - v0.1.9 37090 * Customizable crop and zoom. 37091 * https://github.com/scottcheng/cropit 37092 * 37093 * Made by Scott Cheng 37094 * Based on https://github.com/yufeiliu/simple_image_uploader 37095 * Under MIT License 37096 */ 37097(function($) { 37098 var Zoomer; 37099 Zoomer = function() { 37100 function Zoomer() {} 37101 Zoomer.prototype.setup = function(imageSize, previewSize, exportZoom, options) { 37102 var heightRatio, widthRatio; 37103 if (exportZoom == null) { 37104 exportZoom = 1; 37105 } 37106 widthRatio = previewSize.w / imageSize.w; 37107 heightRatio = previewSize.h / imageSize.h; 37108 if ((options != null ? options.fitWidth : void 0) && !(options != null ? options.fitHeight : void 0)) { 37109 this.minZoom = widthRatio; 37110 } else if ((options != null ? options.fitHeight : void 0) && !(options != null ? options.fitWidth : void 0)) { 37111 this.minZoom = heightRatio; 37112 } else if ((options != null ? options.fitWidth : void 0) && (options != null ? options.fitHeight : void 0)) {
37113 this.minZoom = widthRatio < heightRatio ? widthRatio : heightRatio; 37114 } else { 37115 this.minZoom = widthRatio < heightRatio ? heightRatio : widthRatio; 37116 } 37117 return this.maxZoom = this.minZoom < 1 / exportZoom ? 1 / exportZoom : this.minZoom; 37118 }; 37119 Zoomer.prototype.getZoom = function(sliderPos) { 37120 if (!(this.minZoom && this.maxZoom)) { 37121 return null; 37122 } 37123 return sliderPos * (this.maxZoom - this.minZoom) + this.minZoom; 37124 }; 37125 Zoomer.prototype.getSliderPos = function(zoom) { 37126 if (!(this.minZoom && this.maxZoom)) { 37127 return null; 37128 } 37129 if (this.minZoom === this.maxZoom) { 37130 return 0; 37131 } else { 37132 return (zoom - this.minZoom) / (this.maxZoom - this.minZoom); 37133 } 37134 }; 37135 Zoomer.prototype.isZoomable = function() { 37136 if (!(this.minZoom && this.maxZoom)) { 37137 return null; 37138 } 37139 return this.minZoom !== this.maxZoom; 37140 }; 37141 Zoomer.prototype.fixZoom = function(zoom) { 37142 if (zoom < this.minZoom) { 37143 return this.minZoom; 37144 } 37145 if (zoom > this.maxZoom) { 37146 return this.maxZoom; 37147 } 37148 return zoom; 37149 }; 37150 return Zoomer; 37151 }(); 37152 var Cropit; 37153 Cropit = function() { 37154 Cropit._DEFAULTS = { 37155 exportZoom: 1, 37156 imageBackground: false, 37157 imageBackgroundBorderWidth: 0, 37158 imageState: null, 37159 allowCrossOrigin: false 37160 }; 37161 Cropit.PREVIEW_EVENTS = function() { 37162 return [ "mousedown", "mouseup", "mouseleave", "touchstart", "touchend", "touchcancel", "touchleave" ].map(function(type) { 37163 return "" + type + ".cropit"; 37164 }).join(" "); 37165 }(); 37166 Cropit.PREVIEW_MOVE_EVENTS = "mousemove.cropit touchmove.cropit"; 37167 Cropit.ZOOM_INPUT_EVENTS = function() { 37168 return [ "mousemove", "touchmove", "change" ].map(function(type) { 37169 return "" + type + ".cropit"; 37170 }).join(" "); 37171 }(); 37172 function Cropit(element, options) { 37173 var dynamicDefaults; 37174 this.element = element; 37175 this.$el = $(this.element); 37176 dynamicDefaults = { 37177 $fileInput: this.$("input.cropit-image-input"), 37178 $preview: this.$(".cropit-image-preview"), 37179 $zoomSlider: this.$("input.cropit-image-zoom-input"), 37180 $previewContainer: this.$(".cropit-image-preview-container") 37181 }; 37182 this.options = $.extend({}, Cropit._DEFAULTS, dynamicDefaults, options); 37183 this.init(); 37184 } 37185 Cropit.prototype.init = function() { 37186 var $previewContainer, _ref, _ref1, _ref2; 37187 this.image = new Image(); 37188 if (this.options.allowCrossOrigin) { 37189 this.image.crossOrigin = "Anonymous"; 37190 } 37191 if ($.isArray(this.options.imageBackgroundBorderWidth)) { 37192 this.imageBgBorderWidthArray = this.options.imageBackgroundBorderWidth; 37193 } else { 37194 this.imageBgBorderWidthArray = []; 37195 [ 0, 1, 2, 3 ].forEach(function(_this) { 37196 return function(i) { 37197 return _this.imageBgBorderWidthArray[i] = _this.options.imageBackgroundBorderWidth; 37198 }; 37199 }(this)); 37200 } 37201 this.$fileInput = this.options.$fileInput.attr({ 37202 accept: "image/*" 37203 }); 37204 this.$preview = this.options.$preview.css({ 37205 backgroundRepeat: "no-repeat" 37206 }); 37207 this.$zoomSlider = this.options.$zoomSlider.attr({ 37208 min: 0, 37209 max: 1, 37210 step: .01 37211 }); 37212 this.previewSize = { 37213 w: this.options.width || this.$preview.width(), 37214 h: this.options.height || this.$preview.height() 37215 }; 37216 if (this.options.width) { 37217 this.$preview.width(this.previewSize.w); 37218 } 37219 if (this.options.height) { 37220 this.$preview.height(this.previewSize.h); 37221 }
37222 if (this.options.imageBackground) { 37223 $previewContainer = this.options.$previewContainer; 37224 this.$imageBg = $("<img />").addClass("cropit-image-background").attr("alt", "").css("position", "absolute"); 37225 this.$imageBgContainer = $("<div />").addClass("cropit-image-background-container").css({ 37226 position: "absolute", 37227 zIndex: 0, 37228 left: -this.imageBgBorderWidthArray[3] + window.parseInt(this.$preview.css("border-left-width")), 37229 top: -this.imageBgBorderWidthArray[0] + window.parseInt(this.$preview.css("border-top-width")), 37230 width: this.previewSize.w + this.imageBgBorderWidthArray[1] + this.imageBgBorderWidthArray[3], 37231 height: this.previewSize.h + this.imageBgBorderWidthArray[0] + this.imageBgBorderWidthArray[2] 37232 }).append(this.$imageBg); 37233 if (this.imageBgBorderWidthArray[0] > 0) { 37234 this.$imageBgContainer.css({ 37235 overflow: "hidden" 37236 }); 37237 } 37238 $previewContainer.css("position", "relative").prepend(this.$imageBgContainer); 37239 this.$preview.css("position", "relative"); 37240 this.$preview.hover(function(_this) { 37241 return function() { 37242 return _this.$imageBg.addClass("cropit-preview-hovered"); 37243 }; 37244 }(this), function(_this) { 37245 return function() { 37246 return _this.$imageBg.removeClass("cropit-preview-hovered"); 37247 }; 37248 }(this)); 37249 } 37250 this.initialOffset = { 37251 x: 0, 37252 y: 0 37253 }; 37254 this.initialZoom = 0; 37255 this.initialZoomSliderPos = 0; 37256 this.imageLoaded = false; 37257 this.moveContinue = false; 37258 this.zoomer = new Zoomer(); 37259 this.bindListeners(); 37260 this.$zoomSlider.val(this.initialZoomSliderPos); 37261 this.setOffset(((_ref = this.options.imageState) != null ? _ref.offset : void 0) || this.initialOffset); 37262 this.zoom = ((_ref1 = this.options.imageState) != null ? _ref1.zoom : void 0) || this.initialZoom; 37263 return this.loadImage(((_ref2 = this.options.imageState) != null ? _ref2.src : void 0) || null); 37264 }; 37265 Cropit.prototype.bindListeners = function() { 37266 this.$fileInput.on("change.cropit", this.onFileChange.bind(this)); 37267 this.$preview.on(Cropit.PREVIEW_EVENTS, this.onPreviewEvent.bind(this)); 37268 return this.$zoomSlider.on(Cropit.ZOOM_INPUT_EVENTS, this.onZoomSliderChange.bind(this)); 37269 }; 37270 Cropit.prototype.unbindListeners = function() { 37271 this.$fileInput.off("change.cropit"); 37272 this.$preview.off(Cropit.PREVIEW_EVENTS); 37273 return this.$zoomSlider.off(Cropit.ZOOM_INPUT_EVENTS); 37274 }; 37275 Cropit.prototype.reset = function() { 37276 this.zoom = this.initialZoom; 37277 return this.offset = this.initialOffset; 37278 }; 37279 Cropit.prototype.onFileChange = function() { 37280 var file, fileReader, _base; 37281 if (typeof (_base = this.options).onFileChange === "function") { 37282 _base.onFileChange(); 37283 } 37284 fileReader = new FileReader(); 37285 file = this.$fileInput.get(0).files[0]; 37286 if (file != null ? file.type.match("image") : void 0) { 37287 this.setImageLoadingClass(); 37288 fileReader.readAsDataURL(file); 37289 fileReader.onload = this.onFileReaderLoaded.bind(this); 37290 return fileReader.onerror = this.onFileReaderError.bind(this); 37291 } 37292 }; 37293 Cropit.prototype.onFileReaderLoaded = function(e) { 37294 this.reset(); 37295 return this.loadImage(e.target.result); 37296 }; 37297 Cropit.prototype.onFileReaderError = function() { 37298 var _base; 37299 return typeof (_base = this.options).onFileReaderError === "function" ? _base.onFileReaderError() : void 0; 37300 }; 37301 Cropit.prototype.loadImage = function(imageSrc) { 37302 var _base; 37303 this.imageSrc = imageSrc; 37304 if (!this.imageSrc) { 37305 return; 37306 } 37307 if (typeof (_base = this.options).onImageLoading === "function") { 37308 _base.onImageLoading(); 37309 } 37310 this.setImageLoadingClass(); 37311 this.image.onload = this.onImageLoaded.bind(this); 37312 this.image.onerror = this.onImageError.bind(this); 37313 return this.image.src = this.imageSrc; 37314 }; 37315 Cropit.prototype.onImageLoaded = function() { 37316 var _base; 37317 this.setImageLoadedClass(); 37318 this.setOffset(this.offset); 37319 this.$preview.css("background-image", "url(" + this.imageSrc + ")");
37320 if (this.options.imageBackground) { 37321 this.$imageBg.attr("src", this.imageSrc); 37322 } 37323 this.imageSize = { 37324 w: this.image.width, 37325 h: this.image.height 37326 }; 37327 this.setupZoomer(); 37328 this.imageLoaded = true; 37329 return typeof (_base = this.options).onImageLoaded === "function" ? _base.onImageLoaded() : void 0; 37330 }; 37331 Cropit.prototype.onImageError = function() { 37332 var _base; 37333 return typeof (_base = this.options).onImageError === "function" ? _base.onImageError() : void 0; 37334 }; 37335 Cropit.prototype.setImageLoadingClass = function() { 37336 return this.$preview.removeClass("cropit-image-loaded").addClass("cropit-image-loading"); 37337 }; 37338 Cropit.prototype.setImageLoadedClass = function() { 37339 return this.$preview.removeClass("cropit-image-loading").addClass("cropit-image-loaded"); 37340 }; 37341 Cropit.prototype.getEventPosition = function(e) { 37342 var _ref, _ref1, _ref2, _ref3; 37343 if ((_ref = e.originalEvent) != null ? (_ref1 = _ref.touches) != null ? _ref1[0] : void 0 : void 0) { 37344 e = (_ref2 = e.originalEvent) != null ? (_ref3 = _ref2.touches) != null ? _ref3[0] : void 0 : void 0; 37345 } 37346 if (e.clientX && e.clientY) { 37347 return { 37348 x: e.clientX, 37349 y: e.clientY 37350 }; 37351 } 37352 }; 37353 Cropit.prototype.onPreviewEvent = function(e) { 37354 if (!this.imageLoaded) { 37355 return; 37356 } 37357 this.moveContinue = false; 37358 this.$preview.off(Cropit.PREVIEW_MOVE_EVENTS); 37359 if (e.type === "mousedown" || e.type === "touchstart") { 37360 this.origin = this.getEventPosition(e); 37361 this.moveContinue = true; 37362 this.$preview.on(Cropit.PREVIEW_MOVE_EVENTS, this.onMove.bind(this)); 37363 } else { 37364 $(document.body).focus(); 37365 } 37366 e.stopPropagation(); 37367 return false; 37368 }; 37369 Cropit.prototype.onMove = function(e) { 37370 var eventPosition; 37371 eventPosition = this.getEventPosition(e); 37372 if (this.moveContinue && eventPosition) { 37373 this.setOffset({ 37374 x: this.offset.x + eventPosition.x - this.origin.x, 37375 y: this.offset.y + eventPosition.y - this.origin.y 37376 }); 37377 } 37378 this.origin = eventPosition; 37379 e.stopPropagation(); 37380 return false; 37381 }; 37382 Cropit.prototype.setOffset = function(position) { 37383 this.offset = this.fixOffset(position); 37384 this.$preview.css("background-position", "" + this.offset.x + "px " + this.offset.y + "px"); 37385 if (this.options.imageBackground) { 37386 return this.$imageBg.css({ 37387 left: this.offset.x + this.imageBgBorderWidthArray[3], 37388 top: this.offset.y + this.imageBgBorderWidthArray[0] 37389 }); 37390 } 37391 }; 37392 Cropit.prototype.fixOffset = function(offset) { 37393 var ret; 37394 if (!this.imageLoaded) { 37395 return offset; 37396 } 37397 ret = { 37398 x: offset.x, 37399 y: offset.y 37400 }; 37401 if (this.imageSize.w * this.zoom <= this.previewSize.w) { 37402 ret.x = 0; 37403 } else if (ret.x > 0) { 37404 ret.x = 0; 37405 } else if (ret.x + this.imageSize.w * this.zoom < this.previewSize.w) { 37406 ret.x = this.previewSize.w - this.imageSize.w * this.zoom; 37407 } 37408 if (this.imageSize.h * this.zoom <= this.previewSize.h) { 37409 ret.y = 0; 37410 } else if (ret.y > 0) { 37411 ret.y = 0; 37412 } else if (ret.y + this.imageSize.h * this.zoom < this.previewSize.h) { 37413 ret.y = this.previewSize.h - this.imageSize.h * this.zoom; 37414 } 37415 ret.x = this.round(ret.x); 37416 ret.y = this.round(ret.y); 37417 return ret; 37418 }; 37419 Cropit.prototype.onZoomSliderChange = function() { 37420 var newZoom; 37421 if (!this.imageLoaded) { 37422 return; 37423 } 37424 this.zoomSliderPos = Number(this.$zoomSlider.val());
37425 newZoom = this.zoomer.getZoom(this.zoomSliderPos); 37426 return this.setZoom(newZoom); 37427 }; 37428 Cropit.prototype.enableZoomSlider = function() { 37429 var _base; 37430 this.$zoomSlider.removeAttr("disabled"); 37431 return typeof (_base = this.options).onZoomEnabled === "function" ? _base.onZoomEnabled() : void 0; 37432 }; 37433 Cropit.prototype.disableZoomSlider = function() { 37434 var _base; 37435 this.$zoomSlider.attr("disabled", true); 37436 return typeof (_base = this.options).onZoomDisabled === "function" ? _base.onZoomDisabled() : void 0; 37437 }; 37438 Cropit.prototype.setupZoomer = function() { 37439 this.zoomer.setup(this.imageSize, this.previewSize, this.options.exportZoom, this.options); 37440 this.zoom = this.fixZoom(this.zoom); 37441 this.setZoom(this.zoom); 37442 if (this.isZoomable()) { 37443 return this.enableZoomSlider(); 37444 } else { 37445 return this.disableZoomSlider(); 37446 } 37447 }; 37448 Cropit.prototype.setZoom = function(newZoom) { 37449 var newX, newY, oldZoom, updatedHeight, updatedWidth; 37450 newZoom = this.fixZoom(newZoom); 37451 updatedWidth = this.round(this.imageSize.w * newZoom); 37452 updatedHeight = this.round(this.imageSize.h * newZoom); 37453 oldZoom = this.zoom; 37454 newX = this.previewSize.w / 2 - (this.previewSize.w / 2 - this.offset.x) * newZoom / oldZoom; 37455 newY = this.previewSize.h / 2 - (this.previewSize.h / 2 - this.offset.y) * newZoom / oldZoom; 37456 this.zoom = newZoom; 37457 this.setOffset({ 37458 x: newX, 37459 y: newY 37460 }); 37461 this.zoomSliderPos = this.zoomer.getSliderPos(this.zoom); 37462 this.$zoomSlider.val(this.zoomSliderPos); 37463 this.$preview.css("background-size", "" + updatedWidth + "px " + updatedHeight + "px"); 37464 if (this.options.imageBackground) { 37465 return this.$imageBg.css({ 37466 width: updatedWidth, 37467 height: updatedHeight 37468 }); 37469 } 37470 }; 37471 Cropit.prototype.fixZoom = function(zoom) { 37472 return this.zoomer.fixZoom(zoom); 37473 }; 37474 Cropit.prototype.isZoomable = function() { 37475 return this.zoomer.isZoomable(); 37476 }; 37477 Cropit.prototype.getCroppedImageData = function(exportOptions) { 37478 var canvas, canvasContext, croppedSize, exportDefaults, exportZoom; 37479 if (!this.imageSrc) { 37480 return null; 37481 } 37482 exportDefaults = { 37483 type: "image/png", 37484 quality: .75, 37485 originalSize: false, 37486 fillBg: "#fff" 37487 }; 37488 exportOptions = $.extend({}, exportDefaults, exportOptions); 37489 croppedSize = { 37490 w: this.previewSize.w, 37491 h: this.previewSize.h 37492 }; 37493 if (this.options.fitHeight && !this.options.fitWidth && this.imageSize.w * this.zoom < this.previewSize.w) { 37494 croppedSize.w = this.imageSize.w * this.zoom; 37495 } else if (this.options.fitWidth && !this.options.fitHeight && this.imageSize.h * this.zoom < this.previewSize.h) { 37496 croppedSize.h = this.imageSize.h * this.zoom; 37497 } 37498 exportZoom = exportOptions.originalSize ? 1 / this.zoom : this.options.exportZoom; 37499 canvas = $("<canvas />").attr({ 37500 width: croppedSize.w * exportZoom, 37501 height: croppedSize.h * exportZoom 37502 }).get(0); 37503 canvasContext = canvas.getContext("2d"); 37504 if (exportOptions.type === "image/jpeg") { 37505 canvasContext.fillStyle = exportOptions.fillBg; 37506 canvasContext.fillRect(0, 0, canvas.width, canvas.height); 37507 } 37508 canvasContext.drawImage(this.image, this.offset.x * exportZoom, this.offset.y * exportZoom, this.zoom * exportZoom * this.imageSize.w, this.zoom * exportZoom * this.imageSize.h); 37509 return canvas.toDataURL(exportOptions.type, exportOptions.quality); 37510 }; 37511 Cropit.prototype.getImageState = function() { 37512 return { 37513 src: this.imageSrc, 37514 offset: this.offset, 37515 zoom: this.zoom 37516 }; 37517 }; 37518 Cropit.prototype.getImageSrc = function() { 37519 return this.imageSrc; 37520 }; 37521 Cropit.prototype.getOffset = function() { 37522 return this.offset; 37523 }; 37524 Cropit.prototype.getZoom = function() { 37525 return this.zoom; 37526 }; 37527 Cropit.prototype.getImageSize = function() { 37528 if (!this.imageSize) { 37529 return null; 37530 } 37531 return { 37532 width: this.imageSize.w, 37533 height: this.imageSize.h 37534 }; 37535 }; 37536 Cropit.prototype.getPreviewSize = function() { 37537 return { 37538 width: this.previewSize.w, 37539 height: this.previewSize.h 37540 }; 37541 }; 37542 Cropit.prototype.setPreviewSize = function(size) { 37543 if (!((size != null ? size.width : void 0) > 0 && (size != null ? size.height : void 0) > 0)) { 37544 return; 37545 } 37546 this.previewSize = { 37547 w: size.width, 37548 h: size.height 37549 }; 37550 this.$preview.css({ 37551 width: this.previewSize.w, 37552 height: this.previewSize.h 37553 });
37554 if (this.options.imageBackground) { 37555 this.$imageBgContainer.css({ 37556 width: this.previewSize.w + this.imageBgBorderWidthArray[1] + this.imageBgBorderWidthArray[3], 37557 height: this.previewSize.h + this.imageBgBorderWidthArray[0] + this.imageBgBorderWidthArray[2] 37558 }); 37559 } 37560 if (this.imageLoaded) { 37561 return this.setupZoomer(); 37562 } 37563 }; 37564 Cropit.prototype.disable = function() { 37565 this.unbindListeners(); 37566 this.disableZoomSlider(); 37567 return this.$el.addClass("cropit-disabled"); 37568 }; 37569 Cropit.prototype.reenable = function() { 37570 this.bindListeners(); 37571 this.enableZoomSlider(); 37572 return this.$el.removeClass("cropit-disabled"); 37573 }; 37574 Cropit.prototype.round = function(x) { 37575 return Math.round(x * 1e5) / 1e5; 37576 }; 37577 Cropit.prototype.$ = function(selector) { 37578 if (!this.$el) { 37579 return null; 37580 } 37581 return this.$el.find(selector); 37582 }; 37583 return Cropit; 37584 }(); 37585 var dataKey, methods; 37586 dataKey = "cropit"; 37587 methods = { 37588 init: function(options) { 37589 return this.each(function() { 37590 var cropit; 37591 if (!$.data(this, dataKey)) { 37592 cropit = new Cropit(this, options); 37593 return $.data(this, dataKey, cropit); 37594 } 37595 }); 37596 }, 37597 destroy: function() { 37598 return this.each(function() { 37599 return $.removeData(this, dataKey); 37600 }); 37601 }, 37602 isZoomable: function() { 37603 var cropit; 37604 cropit = this.first().data(dataKey); 37605 return cropit != null ? cropit.isZoomable() : void 0; 37606 }, 37607 "export": function(options) { 37608 var cropit; 37609 cropit = this.first().data(dataKey); 37610 return cropit != null ? cropit.getCroppedImageData(options) : void 0; 37611 }, 37612 imageState: function() { 37613 var cropit; 37614 cropit = this.first().data(dataKey); 37615 return cropit != null ? cropit.getImageState() : void 0; 37616 }, 37617 imageSrc: function(newImageSrc) { 37618 var cropit; 37619 if (newImageSrc != null) { 37620 return this.each(function() { 37621 var cropit; 37622 cropit = $.data(this, dataKey); 37623 if (cropit != null) { 37624 cropit.reset(); 37625 } 37626 return cropit != null ? cropit.loadImage(newImageSrc) : void 0; 37627 }); 37628 } else { 37629 cropit = this.first().data(dataKey); 37630 return cropit != null ? cropit.getImageSrc() : void 0; 37631 } 37632 }, 37633 offset: function(newOffset) { 37634 var cropit; 37635 if (newOffset != null && newOffset.x != null && newOffset.y != null) { 37636 return this.each(function() { 37637 var cropit; 37638 cropit = $.data(this, dataKey); 37639 return cropit != null ? cropit.setOffset(newOffset) : void 0; 37640 }); 37641 } else { 37642 cropit = this.first().data(dataKey); 37643 return cropit != null ? cropit.getOffset() : void 0; 37644 } 37645 }, 37646 zoom: function(newZoom) { 37647 var cropit; 37648 if (newZoom != null) { 37649 return this.each(function() { 37650 var cropit; 37651 cropit = $.data(this, dataKey); 37652 return cropit != null ? cropit.setZoom(newZoom) : void 0; 37653 }); 37654 } else { 37655 cropit = this.first().data(dataKey); 37656 return cropit != null ? cropit.getZoom() : void 0; 37657 } 37658 }, 37659 imageSize: function() { 37660 var cropit; 37661 cropit = this.first().data(dataKey); 37662 return cropit != null ? cropit.getImageSize() : void 0; 37663 }, 37664 previewSize: function(newSize) { 37665 var cropit; 37666 if (newSize != null) { 37667 return this.each(function() { 37668 var cropit; 37669 cropit = $.data(this, dataKey); 37670 return cropit != null ? cropit.setPreviewSize(newSize) : void 0; 37671 }); 37672 } else { 37673 cropit = this.first().data(dataKey); 37674 return cropit != null ? cropit.getPreviewSize() : void 0; 37675 } 37676 }, 37677 disable: function() { 37678 return this.each(function() { 37679 var cropit; 37680 cropit = $.data(this, dataKey); 37681 return cropit.disable(); 37682 }); 37683 }, 37684 reenable: function() { 37685 return this.each(function() { 37686 var cropit; 37687 cropit = $.data(this, dataKey); 37688 return cropit.reenable(); 37689 }); 37690 } 37691 }; 37692 $.fn.cropit = function(method) { 37693 if (methods[method]) { 37694 return methods[method].apply(this, [].slice.call(arguments, 1)); 37695 } else { 37696 return methods.init.apply(this, arguments); 37697 } 37698 }; 37699})(window.jQuery); 37700define("cropit", ["jquery"], function(){}); 37701 37702/*jslint indent:4, white:true, nomen:true, plusplus:true */ 37703/*global define:false, require:false, exports:false, module:false, signals:false */ 37704 37705/** @license 37706 * JS Signals <http://millermedeiros.github.com/js-signals/> 37707 * Released under the MIT license 37708 * Author: Miller Medeiros 37709 * Version: 0.8.1 - Build: 266 (2012/07/31 03:33 PM) 37710 */ 37711 37712(function(global){ 37713 37714 // SignalBinding ------------------------------------------------- 37715 //================================================================ 37716 37717 /** 37718 * Object that represents a binding between a Signal and a listener function. 37719 * <br />- <strong>
37719This is an internal constructor and shouldn't be called by regular users.</strong> 37720 * <br />- inspired by Joa Ebert AS3 SignalBinding and Robert Penner's Slot classes. 37721 * @author Miller Medeiros 37722 * @constructor 37723 * @internal 37724 * @name SignalBinding 37725 * @param {Signal} signal Reference to Signal object that listener is currently bound to. 37726 * @param {Function} listener Handler function bound to the signal. 37727 * @param {boolean} isOnce If binding should be executed just once. 37728 * @param {Object} [listenerContext] Context on which listener will be executed (object that should represent the `this` variable inside listener function). 37729 * @param {Number} [priority] The priority level of the event listener. (default = 0). 37730 */ 37731 function SignalBinding(signal, listener, isOnce, listenerContext, priority) { 37732 37733 /** 37734 * Handler function bound to the signal. 37735 * @type Function 37736 * @private 37737 */ 37738 this._listener = listener; 37739 37740 /** 37741 * If binding should be executed just once. 37742 * @type boolean 37743 * @private 37744 */ 37745 this._isOnce = isOnce; 37746 37747 /** 37748 * Context on which listener will be executed (object that should represent the `this` variable inside listener function). 37749 * @memberOf SignalBinding.prototype 37750 * @name context 37751 * @type Object|undefined|null 37752 */ 37753 this.context = listenerContext; 37754 37755 /** 37756 * Reference to Signal object that listener is currently bound to. 37757 * @type Signal 37758 * @private 37759 */ 37760 this._signal = signal; 37761 37762 /** 37763 * Listener priority 37764 * @type Number 37765 * @private 37766 */ 37767 this._priority = priority || 0; 37768 } 37769 37770 SignalBinding.prototype = { 37771 37772 /** 37773 * If binding is active and should be executed. 37774 * @type boolean 37775 */ 37776 active : true, 37777 37778 /** 37779 * Default parameters passed to listener during `Signal.dispatch` and `SignalBinding.execute`. (curried parameters) 37780 * @type Array|null 37781 */ 37782 params : null, 37783 37784 /** 37785 * Call listener passing arbitrary parameters. 37786 * <p>If binding was added using `Signal.addOnce()` it will be automatically removed from signal dispatch queue, this method is used internally for the signal dispatch.</p> 37787 * @param {Array} [paramsArr] Array of parameters that should be passed to the listener 37788 * @return {*} Value returned by the listener. 37789 */ 37790 execute : function (paramsArr) { 37791 var handlerReturn, params; 37792 if (this.active && !!this._listener) { 37793 params = this.params? this.params.concat(paramsArr) : paramsArr; 37794 handlerReturn = this._listener.apply(this.context, params); 37795 if (this._isOnce) { 37796 this.detach(); 37797 } 37798 } 37799 return handlerReturn; 37800 }, 37801 37802 /** 37803 * Detach binding from signal. 37804 * - alias to: mySignal.remove(myBinding.getListener()); 37805 * @return {Function|null} Handler function bound to the signal or `null` if binding was previously detached. 37806 */ 37807 detach : function () { 37808 return this.isBound()? this._signal.remove(this._listener, this.context) : null; 37809 }, 37810 37811 /** 37812 * @return {Boolean} `true` if binding is still bound to the signal and have a listener. 37813 */ 37814 isBound : function () { 37815 return (!!this._signal && !!this._listener); 37816 }, 37817 37818 /** 37819 * @return {Function} Handler function bound to the signal. 37820 */ 37821 getListener : function () { 37822 return this._listener; 37823 }, 37824 37825 /** 37826 * Delete instance properties 37827 * @private 37828 */ 37829 _destroy : function () { 37830 delete this._signal; 37831 delete this._listener; 37832 delete this.context; 37833 }, 37834 37835 /** 37836 * @return {boolean} If SignalBinding will only be executed once. 37837 */ 37838 isOnce : function () { 37839 return this._isOnce; 37840 }, 37841 37842 /** 37843 * @return {string} String representation of the object. 37844 */ 37845 toString : function () { 37846 return '[SignalBinding isOnce:' + this._isOnce +', isBound:'+ this.isBound() +', active:' + this.active + ']'; 37847 } 37848 37849 }; 37850 37851 37852/*global SignalBinding:false*/ 37853 37854 // Signal -------------------------------------------------------- 37855 //================================================================ 37856 37857 function validateListener(listener, fnName) { 37858 if (typeof listener !== 'function') { 37859 throw new Error( 'listener is a required param of {fn}() and should be a Function.'.replace('{fn}', fnName) ); 37860 } 37861 } 37862 37863 /** 37864 * Custom event broadcaster 37865 * <br />- inspired by Robert Penner's AS3 Signals. 37866 * @name Signal 37867 * @author Miller Medeiros 37868 * @constructor 37869 */ 37870 function Signal() { 37871 /** 37872 * @type Array.<SignalBinding> 37873 * @private 37874 */ 37875 this._bindings = []; 37876 this._prevParams = null; 37877 } 37878 37879 Signal.prototype = { 37880 37881 /** 37882 * Signals Version Number
vendor: 9,593 bytes, lines 37883-38141
37883 * @type String 37884 * @const 37885 */ 37886 VERSION : '0.8.1', 37887 37888 /** 37889 * If Signal should keep record of previously dispatched parameters and 37890 * automatically execute listener during `add()`/`addOnce()` if Signal was 37891 * already dispatched before. 37892 * @type boolean 37893 */ 37894 memorize : false, 37895 37896 /** 37897 * @type boolean 37898 * @private 37899 */ 37900 _shouldPropagate : true, 37901 37902 /** 37903 * If Signal is active and should broadcast events. 37904 * <p><strong>IMPORTANT:</strong> Setting this property during a dispatch will only affect the next dispatch, if you want to stop the propagation of a signal use `halt()` instead.</p> 37905 * @type boolean 37906 */ 37907 active : true, 37908 37909 /** 37910 * @param {Function} listener 37911 * @param {boolean} isOnce 37912 * @param {Object} [listenerContext] 37913 * @param {Number} [priority] 37914 * @return {SignalBinding} 37915 * @private 37916 */ 37917 _registerListener : function (listener, isOnce, listenerContext, priority) { 37918 37919 var prevIndex = this._indexOfListener(listener, listenerContext), 37920 binding; 37921 37922 if (prevIndex !== -1) { 37923 binding = this._bindings[prevIndex]; 37924 if (binding.isOnce() !== isOnce) { 37925 throw new Error('You cannot add'+ (isOnce? '' : 'Once') +'() then add'+ (!isOnce? '' : 'Once') +'() the same listener without removing the relationship first.'); 37926 } 37927 } else { 37928 binding = new SignalBinding(this, listener, isOnce, listenerContext, priority); 37929 this._addBinding(binding); 37930 } 37931 37932 if(this.memorize && this._prevParams){ 37933 binding.execute(this._prevParams); 37934 } 37935 37936 return binding; 37937 }, 37938 37939 /** 37940 * @param {SignalBinding} binding 37941 * @private 37942 */ 37943 _addBinding : function (binding) { 37944 //simplified insertion sort 37945 var n = this._bindings.length; 37946 do { --n; } while (this._bindings[n] && binding._priority <= this._bindings[n]._priority); 37947 this._bindings.splice(n + 1, 0, binding); 37948 }, 37949 37950 /** 37951 * @param {Function} listener 37952 * @return {number} 37953 * @private 37954 */ 37955 _indexOfListener : function (listener, context) { 37956 var n = this._bindings.length, 37957 cur; 37958 while (n--) { 37959 cur = this._bindings[n]; 37960 if (cur._listener === listener && cur.context === context) { 37961 return n; 37962 } 37963 } 37964 return -1; 37965 }, 37966 37967 /** 37968 * Check if listener was attached to Signal. 37969 * @param {Function} listener 37970 * @param {Object} [context] 37971 * @return {boolean} if Signal has the specified listener. 37972 */ 37973 has : function (listener, context) { 37974 return this._indexOfListener(listener, context) !== -1; 37975 }, 37976 37977 /** 37978 * Add a listener to the signal. 37979 * @param {Function} listener Signal handler function. 37980 * @param {Object} [listenerContext] Context on which listener will be executed (object that should represent the `this` variable inside listener function). 37981 * @param {Number} [priority] The priority level of the event listener. Listeners with higher priority will be executed before listeners with lower priority. Listeners with same priority level will be executed at the same order as they were added. (default = 0) 37982 * @return {SignalBinding} An Object representing the binding between the Signal and listener. 37983 */ 37984 add : function (listener, listenerContext, priority) { 37985 validateListener(listener, 'add'); 37986 return this._registerListener(listener, false, listenerContext, priority); 37987 }, 37988 37989 /** 37990 * Add listener to the signal that should be removed after first execution (will be executed only once). 37991 * @param {Function} listener Signal handler function. 37992 * @param {Object} [listenerContext] Context on which listener will be executed (object that should represent the `this` variable inside listener function). 37993 * @param {Number} [priority] The priority level of the event listener. Listeners with higher priority will be executed before listeners with lower priority. Listeners with same priority level will be executed at the same order as they were added. (default = 0) 37994 * @return {SignalBinding} An Object representing the binding between the Signal and listener. 37995 */ 37996 addOnce : function (listener, listenerContext, priority) { 37997 validateListener(listener, 'addOnce'); 37998 return this._registerListener(listener, true, listenerContext, priority); 37999 }, 38000 38001 /** 38002 * Remove a single listener from the dispatch queue. 38003 * @param {Function} listener Handler function that should be removed. 38004 * @param {Object} [context] Execution context (since you can add the same handler multiple times if executing in a different context). 38005 * @return {Function} Listener handler function. 38006 */ 38007 remove : function (listener, context) { 38008 validateListener(listener, 'remove'); 38009 38010 var i = this._indexOfListener(listener, context); 38011 if (i !== -1) { 38012 this._bindings[i]._destroy(); //no reason to a SignalBinding exist if it isn't attached to a signal 38013 this._bindings.splice(i, 1); 38014 } 38015 return listener; 38016 }, 38017 38018 /** 38019 * Remove all listeners from the Signal. 38020 */ 38021 removeAll : function () { 38022 var n = this._bindings.length; 38023 while (n--) { 38024 this._bindings[n]._destroy(); 38025 } 38026 this._bindings.length = 0; 38027 }, 38028 38029 /** 38030 * @return {number} Number of listeners attached to the Signal. 38031 */ 38032 getNumListeners : function () { 38033 return this._bindings.length; 38034 }, 38035 38036 /** 38037 * Stop propagation of the event, blocking the dispatch to next listeners on the queue. 38038 * <p><strong>IMPORTANT:</strong> should be called only during signal dispatch, calling it before/after dispatch won't affect signal broadcast.</p> 38039 * @see Signal.prototype.disable 38040 */ 38041 halt : function () { 38042 this._shouldPropagate = false; 38043 }, 38044 38045 /** 38046 * Dispatch/Broadcast Signal to all listeners added to the queue. 38047 * @param {...*} [params] Parameters that should be passed to each handler. 38048 */ 38049 dispatch : function (params) { 38050 if (! this.active) { 38051 return; 38052 } 38053 38054 var paramsArr = Array.prototype.slice.call(arguments), 38055 n = this._bindings.length, 38056 bindings; 38057 38058 if (this.memorize) { 38059 this._prevParams = paramsArr; 38060 } 38061 38062 if (! n) { 38063 //should come after memorize 38064 return; 38065 } 38066 38067 bindings = this._bindings.slice(); //clone array in case add/remove items during dispatch 38068 this._shouldPropagate = true; //in case `halt` was called before dispatch or during the previous dispatch. 38069 38070 //execute all callbacks until end of the list or until a callback returns `false` or stops propagation 38071 //reverse loop since listeners with higher priority will be added at the end of the list 38072 do { n--; } while (bindings[n] && this._shouldPropagate && bindings[n].execute(paramsArr) !== false); 38073 }, 38074 38075 /** 38076 * Forget memorized arguments. 38077 * @see Signal.memorize 38078 */ 38079 forget : function(){ 38080 this._prevParams = null; 38081 }, 38082 38083 /** 38084 * Remove all bindings from signal and destroy any reference to external objects (destroy Signal object). 38085 * <p><strong>IMPORTANT:</strong> calling any method on the signal instance after calling dispose will throw errors.</p> 38086 */ 38087 dispose : function () { 38088 this.removeAll(); 38089 delete this._bindings; 38090 delete this._prevParams; 38091 }, 38092 38093 /** 38094 * @return {string} String representation of the object. 38095 */ 38096 toString : function () { 38097 return '[Signal active:'+ this.active +' numListeners:'+ this.getNumListeners() +']'; 38098 } 38099 38100 }; 38101 38102 38103 // Namespace ----------------------------------------------------- 38104 //================================================================ 38105 38106 /** 38107 * Signals namespace 38108 * @namespace 38109 * @name signals 38110 */ 38111 var signals = Signal; 38112 38113 /** 38114 * Custom event broadcaster 38115 * @see Signal 38116 */ 38117 // alias for backwards compatibility (see #gh-44) 38118 signals.Signal = Signal; 38119 38120 38121 38122 //exports to multiple environments 38123 if(typeof define === 'function' && define.amd){ //AMD 38124 define('signals',[],function () { return signals; }); 38125 } else if (typeof module !== 'undefined' && module.exports){ //node 38126 module.exports = signals; 38127 } else { //browser 38128 //use string because of Google closure compiler ADVANCED_MODE 38129 /*jslint sub:true */ 38130 global['signals'] = signals; 38131 } 38132 38133}(this)); 38134 38135/** @license 38136 * crossroads <http://millermedeiros.github.com/crossroads.js/> 38137 * Author: Miller Medeiros | MIT License 38138 * v0.12.2 (2015/07/31 18:37) 38139 */ 38140 38141(function () {
38142var factory = function (signals) { 38143 38144 var crossroads, 38145 _hasOptionalGroupBug, 38146 UNDEF; 38147 38148 // Helpers ----------- 38149 //==================== 38150 38151 // IE 7-8 capture optional groups as empty strings while other browsers 38152 // capture as `undefined` 38153 _hasOptionalGroupBug = (/t(.+)?/).exec('t')[1] === ''; 38154 38155 function arrayIndexOf(arr, val) { 38156 if (arr.indexOf) { 38157 return arr.indexOf(val); 38158 } else { 38159 //Array.indexOf doesn't work on IE 6-7 38160 var n = arr.length; 38161 while (n--) { 38162 if (arr[n] === val) { 38163 return n; 38164 } 38165 } 38166 return -1; 38167 } 38168 } 38169 38170 function arrayRemove(arr, item) { 38171 var i = arrayIndexOf(arr, item); 38172 if (i !== -1) { 38173 arr.splice(i, 1); 38174 } 38175 } 38176 38177 function isKind(val, kind) { 38178 return '[object '+ kind +']' === Object.prototype.toString.call(val); 38179 } 38180 38181 function isRegExp(val) { 38182 return isKind(val, 'RegExp'); 38183 } 38184 38185 function isArray(val) { 38186 return isKind(val, 'Array'); 38187 } 38188 38189 function isFunction(val) { 38190 return typeof val === 'function'; 38191 } 38192 38193 //borrowed from AMD-utils 38194 function typecastValue(val) { 38195 var r; 38196 if (val === null || val === 'null') { 38197 r = null; 38198 } else if (val === 'true') { 38199 r = true; 38200 } else if (val === 'false') { 38201 r = false; 38202 } else if (val === UNDEF || val === 'undefined') { 38203 r = UNDEF; 38204 } else if (val === '' || isNaN(val)) { 38205 //isNaN('') returns false 38206 r = val; 38207 } else { 38208 //parseFloat(null || '') returns NaN 38209 r = parseFloat(val); 38210 } 38211 return r; 38212 } 38213 38214 function typecastArrayValues(values) { 38215 var n = values.length, 38216 result = []; 38217 while (n--) { 38218 result[n] = typecastValue(values[n]); 38219 } 38220 return result; 38221 } 38222 38223 // borrowed from MOUT 38224 function decodeQueryString(queryStr, shouldTypecast) { 38225 var queryArr = (queryStr || '').replace('?', '').split('&'), 38226 reg = /([^=]+)=(.+)/, 38227 i = -1, 38228 obj = {}, 38229 equalIndex, cur, pValue, pName; 38230 38231 while ((cur = queryArr[++i])) { 38232 equalIndex = cur.indexOf('='); 38233 pName = cur.substring(0, equalIndex); 38234 pValue = decodeURIComponent(cur.substring(equalIndex + 1)); 38235 if (shouldTypecast !== false) { 38236 pValue = typecastValue(pValue); 38237 } 38238 if (pName in obj){ 38239 if(isArray(obj[pName])){ 38240 obj[pName].push(pValue); 38241 } else { 38242 obj[pName] = [obj[pName], pValue]; 38243 } 38244 } else { 38245 obj[pName] = pValue; 38246 } 38247 } 38248 return obj; 38249 } 38250 38251 38252 // Crossroads -------- 38253 //==================== 38254 38255 /** 38256 * @constructor 38257 */ 38258 function Crossroads() { 38259 this.bypassed = new signals.Signal(); 38260 this.routed = new signals.Signal(); 38261 this._routes = []; 38262 this._prevRoutes = []; 38263 this._piped = []; 38264 this.resetState(); 38265 } 38266 38267 Crossroads.prototype = { 38268 38269 greedy : false, 38270 38271 greedyEnabled : true, 38272 38273 ignoreCase : true, 38274 38275 ignoreState : false, 38276 38277 shouldTypecast : false, 38278 38279 normalizeFn : null, 38280 38281 resetState : function(){ 38282 this._prevRoutes.length = 0; 38283 this._prevMatchedRequest = null; 38284 this._prevBypassedRequest = null; 38285 }, 38286 38287 create : function () { 38288 return new Crossroads(); 38289 }, 38290 38291 addRoute : function (pattern, callback, priority) { 38292 var route = new Route(pattern, callback, priority, this); 38293 this._sortedInsert(route); 38294 return route; 38295 }, 38296 38297 removeRoute : function (route) { 38298 arrayRemove(this._routes, route); 38299 route._destroy(); 38300 }, 38301 38302 removeAllRoutes : function () { 38303 var n = this.getNumRoutes(); 38304 while (n--) { 38305 this._routes[n]._destroy(); 38306 } 38307 this._routes.length = 0; 38308 }, 38309 38310 parse : function (request, defaultArgs) { 38311 request = request || ''; 38312 defaultArgs = defaultArgs || []; 38313 38314 // should only care about different requests if ignoreState isn't true 38315 if ( !this.ignoreState && 38316 (request === this._prevMatchedRequest || 38317 request === this._prevBypassedRequest) ) { 38318 return; 38319 } 38320 38321 var routes = this._getMatchedRoutes(request), 38322 i = 0, 38323 n = routes.length, 38324 cur; 38325 38326 if (n) { 38327 this._prevMatchedRequest = request; 38328 38329 this._notifyPrevRoutes(routes, request); 38330 this._prevRoutes = routes; 38331 //should be incremental loop, execute routes in order 38332 while (i < n) { 38333 cur = routes[i]; 38334 cur.route.matched.dispatch.apply(cur.route.matched, defaultArgs.concat(cur.params)); 38335 cur.isFirst = !i; 38336 this.routed.dispatch.apply(this.routed, defaultArgs.concat([request, cur])); 38337 i += 1; 38338 } 38339 } else { 38340 this._prevBypassedRequest = request; 38341 this.bypassed.dispatch.apply(this.bypassed, defaultArgs.concat([request])); 38342 } 38343 38344 this._pipeParse(request, defaultArgs); 38345 }, 38346 38347 _notifyPrevRoutes : function(matchedRoutes, request) { 38348 var i = 0, prev; 38349 while (prev = this._prevRoutes[i++]) { 38350 //check if switched exist since route may be disposed 38351 if(prev.route.switched && this._didSwitch(prev.route, matchedRoutes)) { 38352 prev.route.switched.dispatch(request); 38353 } 38354 } 38355 }, 38356 38357 _didSwitch : function (route, matchedRoutes){ 38358 var matched, 38359 i = 0; 38360 while (matched = matchedRoutes[i++]) { 38361 // only dispatch switched if it is going to a different route 38362 if (matched.route === route) { 38363 return false;
38364 } 38365 } 38366 return true; 38367 }, 38368 38369 _pipeParse : function(request, defaultArgs) { 38370 var i = 0, route; 38371 while (route = this._piped[i++]) { 38372 route.parse(request, defaultArgs); 38373 } 38374 }, 38375 38376 getNumRoutes : function () { 38377 return this._routes.length; 38378 }, 38379 38380 _sortedInsert : function (route) { 38381 //simplified insertion sort 38382 var routes = this._routes, 38383 n = routes.length; 38384 do { --n; } while (routes[n] && route._priority <= routes[n]._priority); 38385 routes.splice(n+1, 0, route); 38386 }, 38387 38388 _getMatchedRoutes : function (request) { 38389 var res = [], 38390 routes = this._routes, 38391 n = routes.length, 38392 route; 38393 //should be decrement loop since higher priorities are added at the end of array 38394 while (route = routes[--n]) { 38395 if ((!res.length || this.greedy || route.greedy) && route.match(request)) { 38396 res.push({ 38397 route : route, 38398 params : route._getParamsArray(request) 38399 }); 38400 } 38401 if (!this.greedyEnabled && res.length) { 38402 break; 38403 } 38404 } 38405 return res; 38406 }, 38407 38408 pipe : function (otherRouter) { 38409 this._piped.push(otherRouter); 38410 }, 38411 38412 unpipe : function (otherRouter) { 38413 arrayRemove(this._piped, otherRouter); 38414 }, 38415 38416 toString : function () { 38417 return '[crossroads numRoutes:'+ this.getNumRoutes() +']'; 38418 } 38419 }; 38420 38421 //"static" instance 38422 crossroads = new Crossroads(); 38423 crossroads.VERSION = '0.12.2'; 38424 38425 crossroads.NORM_AS_ARRAY = function (req, vals) { 38426 return [vals.vals_]; 38427 }; 38428 38429 crossroads.NORM_AS_OBJECT = function (req, vals) { 38430 return [vals]; 38431 }; 38432 38433 38434 // Route -------------- 38435 //===================== 38436 38437 /** 38438 * @constructor 38439 */ 38440 function Route(pattern, callback, priority, router) { 38441 var isRegexPattern = isRegExp(pattern), 38442 patternLexer = router.patternLexer; 38443 this._router = router; 38444 this._pattern = pattern; 38445 this._paramsIds = isRegexPattern? null : patternLexer.getParamIds(pattern); 38446 this._optionalParamsIds = isRegexPattern? null : patternLexer.getOptionalParamsIds(pattern); 38447 this._matchRegexp = isRegexPattern? pattern : patternLexer.compilePattern(pattern, router.ignoreCase); 38448 this.matched = new signals.Signal(); 38449 this.switched = new signals.Signal(); 38450 if (callback) { 38451 this.matched.add(callback); 38452 } 38453 this._priority = priority || 0; 38454 } 38455 38456 Route.prototype = { 38457 38458 greedy : false, 38459 38460 rules : void(0), 38461 38462 match : function (request) { 38463 request = request || ''; 38464 return this._matchRegexp.test(request) && this._validateParams(request); //validate params even if regexp because of `request_` rule. 38465 }, 38466 38467 _validateParams : function (request) { 38468 var rules = this.rules, 38469 values = this._getParamsObject(request), 38470 key; 38471 for (key in rules) { 38472 // normalize_ isn't a validation rule... (#39) 38473 if(key !== 'normalize_' && rules.hasOwnProperty(key) && ! this._isValidParam(request, key, values)){ 38474 return false; 38475 } 38476 } 38477 return true; 38478 }, 38479 38480 _isValidParam : function (request, prop, values) { 38481 var validationRule = this.rules[prop], 38482 val = values[prop], 38483 isValid = false, 38484 isQuery = (prop.indexOf('?') === 0); 38485 38486 if (val == null && this._optionalParamsIds && arrayIndexOf(this._optionalParamsIds, prop) !== -1) { 38487 isValid = true; 38488 } 38489 else if (isRegExp(validationRule)) { 38490 if (isQuery) { 38491 val = values[prop +'_']; //use raw string 38492 } 38493 isValid = validationRule.test(val); 38494 } 38495 else if (isArray(validationRule)) { 38496 if (isQuery) { 38497 val = values[prop +'_']; //use raw string 38498 } 38499 isValid = this._isValidArrayRule(validationRule, val); 38500 }
38501 else if (isFunction(validationRule)) { 38502 isValid = validationRule(val, request, values); 38503 } 38504 38505 return isValid; //fail silently if validationRule is from an unsupported type 38506 }, 38507 38508 _isValidArrayRule : function (arr, val) { 38509 if (! this._router.ignoreCase) { 38510 return arrayIndexOf(arr, val) !== -1; 38511 } 38512 38513 if (typeof val === 'string') { 38514 val = val.toLowerCase(); 38515 } 38516 38517 var n = arr.length, 38518 item, 38519 compareVal; 38520 38521 while (n--) { 38522 item = arr[n]; 38523 compareVal = (typeof item === 'string')? item.toLowerCase() : item; 38524 if (compareVal === val) { 38525 return true; 38526 } 38527 } 38528 return false; 38529 }, 38530 38531 _getParamsObject : function (request) { 38532 var shouldTypecast = this._router.shouldTypecast, 38533 values = this._router.patternLexer.getParamValues(request, this._matchRegexp, shouldTypecast), 38534 o = {}, 38535 n = values.length, 38536 param, val; 38537 while (n--) { 38538 val = values[n]; 38539 if (this._paramsIds) { 38540 param = this._paramsIds[n]; 38541 if (param.indexOf('?') === 0 && val) { 38542 //make a copy of the original string so array and 38543 //RegExp validation can be applied properly 38544 o[param +'_'] = val; 38545 //update vals_ array as well since it will be used 38546 //during dispatch 38547 val = decodeQueryString(val, shouldTypecast); 38548 values[n] = val; 38549 } 38550 // IE will capture optional groups as empty strings while other 38551 // browsers will capture `undefined` so normalize behavior. 38552 // see: #gh-58, #gh-59, #gh-60 38553 if ( _hasOptionalGroupBug && val === '' && arrayIndexOf(this._optionalParamsIds, param) !== -1 ) { 38554 val = void(0); 38555 values[n] = val; 38556 } 38557 o[param] = val; 38558 } 38559 //alias to paths and for RegExp pattern 38560 o[n] = val; 38561 } 38562 o.request_ = shouldTypecast? typecastValue(request) : request; 38563 o.vals_ = values; 38564 return o; 38565 }, 38566 38567 _getParamsArray : function (request) { 38568 var norm = this.rules? this.rules.normalize_ : null, 38569 params; 38570 norm = norm || this._router.normalizeFn; // default normalize 38571 if (norm && isFunction(norm)) { 38572 params = norm(request, this._getParamsObject(request)); 38573 } else { 38574 params = this._getParamsObject(request).vals_; 38575 } 38576 return params; 38577 }, 38578 38579 interpolate : function(replacements) { 38580 var str = this._router.patternLexer.interpolate(this._pattern, replacements); 38581 if (! this._validateParams(str) ) { 38582 throw new Error('Generated string doesn\'t validate against `Route.rules`.'); 38583 } 38584 return str; 38585 }, 38586 38587 dispose : function () { 38588 this._router.removeRoute(this); 38589 }, 38590 38591 _destroy : function () { 38592 this.matched.dispose(); 38593 this.switched.dispose(); 38594 this.matched = this.switched = this._pattern = this._matchRegexp = null; 38595 }, 38596 38597 toString : function () { 38598 return '[Route pattern:"'+ this._pattern +'", numListeners:'+ this.matched.getNumListeners() +']'; 38599 } 38600 38601 }; 38602 38603 38604 38605 // Pattern Lexer ------ 38606 //===================== 38607 38608 Crossroads.prototype.patternLexer = (function () { 38609 38610 var 38611 //match chars that should be escaped on string regexp 38612 ESCAPE_CHARS_REGEXP = /[\\.+*?\^$\[\](){}\/'#]/g, 38613 38614 //trailing slashes (begin/end of string) 38615 LOOSE_SLASHES_REGEXP = /^\/|\/$/g, 38616 LEGACY_SLASHES_REGEXP = /\/$/g, 38617 38618 //params - everything between `{ }` or `: :` 38619 PARAMS_REGEXP = /(?:\{|:)([^}:]+)(?:\}|:)/g, 38620 38621 //used to save params during compile (avoid escaping things that 38622 //shouldn't be escaped). 38623 TOKENS = { 38624 'OS' : { 38625 //optional slashes 38626 //slash between `::` or `}:` or `\w:` or `:{?` or `}{?` or `\w{?` 38627 rgx : /([:}]|\w(?=\/))\/?(:|(?:\{\?))/g, 38628 save : '$1{{id}}$2', 38629 res : '\\/?' 38630 }, 38631 'RS' : { 38632 //required slashes 38633 //used to insert slash between `:{` and `}{` 38634 rgx : /([:}])\/?(\{)/g, 38635 save : '$1{{id}}$2', 38636 res : '\\/' 38637 }, 38638 'RQ' : { 38639 //required query string - everything in between `{? }` 38640 rgx : /\{\?([^}]+)\}/g, 38641 //everything from `?` till `#` or end of string 38642 res : '\\?([^#]+)' 38643 }, 38644 'OQ' : { 38645 //optional query string - everything in between `:? :` 38646 rgx : /:\?([^:]+):/g, 38647 //everything from `?` till `#` or end of string 38648 res : '(?:\\?([^#]*))?' 38649 }, 38650 'OR' : { 38651 //optional rest - everything in between `: *:` 38652 rgx : /:([^:]+)\*:/g, 38653 res : '(.*)?' // optional group to avoid passing empty string as captured 38654 }, 38655 'RR' : { 38656 //rest param - everything in between `{ *}` 38657 rgx : /\{([^}]+)\*\}/g, 38658 res : '(.+)' 38659 }, 38660 // required/optional params should come after rest segments 38661 'RP' : { 38662 //required params - everything between `{ }` 38663 rgx : /\{([^}]+)\}/g, 38664 res : '([^\\/?]+)' 38665 }, 38666 'OP' : { 38667 //optional params - everything between `: :` 38668 rgx : /:([^:]+):/g, 38669 res : '([^\\/?]+)?\/?' 38670 } 38671 }, 38672 38673 LOOSE_SLASH = 1, 38674 STRICT_SLASH = 2, 38675 LEGACY_SLASH = 3, 38676 38677 _slashMode = LOOSE_SLASH; 38678 38679 38680 function precompileTokens(){ 38681 var key, cur; 38682 for (key in TOKENS) { 38683 if (TOKENS.hasOwnProperty(key)) { 38684 cur = TOKENS[key]; 38685 cur.id = '__CR_'+ key +'__'; 38686 cur.save = ('save' in cur)? cur.save.replace('{{id}}', cur.id) : cur.id; 38687 cur.rRestore = new RegExp(cur.id, 'g'); 38688 } 38689 } 38690 } 38691 precompileTokens(); 38692 38693 38694 function captureVals(regex, pattern) { 38695 var vals = [], match; 38696 // very important to reset lastIndex since RegExp can have "g" flag 38697 // and multiple runs might affect the result, specially if matching 38698 // same string multiple times on IE 7-8 38699 regex.lastIndex = 0; 38700 while (match = regex.exec(pattern)) { 38701 vals.push(match[1]); 38702 } 38703 return vals; 38704 } 38705 38706 function getParamIds(pattern) { 38707 return captureVals(PARAMS_REGEXP, pattern); 38708 } 38709 38710 function getOptionalParamsIds(pattern) { 38711 return captureVals(TOKENS.OP.rgx, pattern); 38712 } 38713 38714 function compilePattern(pattern, ignoreCase) { 38715 pattern = pattern || ''; 38716 38717 if(pattern){ 38718 if (_slashMode === LOOSE_SLASH) { 38719 pattern = pattern.replace(LOOSE_SLASHES_REGEXP, ''); 38720 } 38721 else if (_slashMode === LEGACY_SLASH) { 38722 pattern = pattern.replace(LEGACY_SLASHES_REGEXP, ''); 38723 } 38724 38725 //save tokens 38726 pattern = replaceTokens(pattern, 'rgx', 'save'); 38727 //regexp escape 38728 pattern = pattern.replace(ESCAPE_CHARS_REGEXP, '\\$&'); 38729 //restore tokens 38730 pattern = replaceTokens(pattern, 'rRestore', 'res'); 38731 38732 if (_slashMode === LOOSE_SLASH) { 38733 pattern = '\\/?'+ pattern; 38734 } 38735 } 38736 38737 if (_slashMode !== STRICT_SLASH) { 38738 //single slash is treated as empty and end slash is optional 38739 pattern += '\\/?'; 38740 } 38741 return new RegExp('^'+ pattern + '$', ignoreCase? 'i' : ''); 38742 } 38743 38744 function replaceTokens(pattern, regexpName, replaceName) { 38745 var cur, key; 38746 for (key in TOKENS) { 38747 if (TOKENS.hasOwnProperty(key)) { 38748 cur = TOKENS[key]; 38749 pattern = pattern.replace(cur[regexpName], cur[replaceName]); 38750 } 38751 } 38752 return pattern; 38753 } 38754 38755 function getParamValues(request, regexp, shouldTypecast) { 38756 var vals = regexp.exec(request); 38757 if (vals) { 38758 vals.shift(); 38759 if (shouldTypecast) { 38760 vals = typecastArrayValues(vals); 38761 } 38762 } 38763 return vals; 38764 } 38765 38766 function interpolate(pattern, replacements) { 38767 // default to an empty object because pattern might have just 38768 // optional arguments 38769 replacements = replacements || {}; 38770 if (typeof pattern !== 'string') { 38771 throw new Error('Route pattern should be a string.'); 38772 } 38773 38774 var replaceFn = function(match, prop){ 38775 var val; 38776 prop = (prop.substr(0, 1) === '?')? prop.substr(1) : prop; 38777 if (replacements[prop] != null) { 38778 if (typeof replacements[prop] === 'object') { 38779 var queryParts = [], rep; 38780 for(var key in replacements[prop]) { 38781 rep = replacements[prop][key]; 38782 if (isArray(rep)) { 38783 for (var k in rep) { 38784 if ( key.slice(-2) == '[]' ) { 38785 queryParts.push(encodeURI(key.slice(0, -2)) + '[]=' + encodeURI(rep[k])); 38786 } else { 38787 queryParts.push(encodeURI(key + '=' + rep[k])); 38788 } 38789 } 38790 } 38791 else { 38792 queryParts.push(encodeURI(key + '=' + rep)); 38793 } 38794 } 38795 val = '?' + queryParts.join('&'); 38796 } else { 38797 // make sure value is a string see #gh-54 38798 val = String(replacements[prop]); 38799 } 38800 38801 if (match.indexOf('*') === -1 && val.indexOf('/') !== -1) { 38802 throw new Error('Invalid value "'+ val +'" for segment "'+ match +'".'); 38803 } 38804 } 38805 else if (match.indexOf('{') !== -1) { 38806 throw new Error('The segment '+ match +' is required.'); 38807 } 38808 else { 38809 val = ''; 38810 } 38811 return val; 38812 }; 38813 38814 if (! TOKENS.OS.trail) { 38815 TOKENS.OS.trail = new RegExp('(?:'+ TOKENS.OS.id +')+$'); 38816 } 38817 38818 return pattern 38819 .replace(TOKENS.OS.rgx, TOKENS.OS.save) 38820 .replace(PARAMS_REGEXP, replaceFn) 38821 .replace(TOKENS.OS.trail, '') // remove trailing 38822 .replace(TOKENS.OS.rRestore, '/'); // add slash between segments 38823 } 38824 38825 //API 38826 return {
38827 strict : function(){ 38828 _slashMode = STRICT_SLASH; 38829 }, 38830 loose : function(){ 38831 _slashMode = LOOSE_SLASH; 38832 }, 38833 legacy : function(){ 38834 _slashMode = LEGACY_SLASH; 38835 }, 38836 getParamIds : getParamIds, 38837 getOptionalParamsIds : getOptionalParamsIds, 38838 getParamValues : getParamValues, 38839 compilePattern : compilePattern, 38840 interpolate : interpolate 38841 }; 38842 38843 }()); 38844 38845 38846 return crossroads; 38847}; 38848 38849if (typeof define === 'function' && define.amd) { 38850 define('crossroads',['signals'], factory); 38851} else if (typeof module !== 'undefined' && module.exports) { //Node 38852 module.exports = factory(require('signals')); 38853} else { 38854 /*jshint sub:true */ 38855 window['crossroads'] = factory(window['signals']); 38856} 38857 38858}()); 38859 38860 38861define('dataFilterProcessor',[], 38862function () { 38863 38864 return { 38865 38866 currentParams: [], 38867 38868 previousParams: [], 38869 38870 clearParams: function () { 38871 this.currentParams = []; 38872 this.previousParams = []; 38873 }, 38874 38875 calDifference: function(previousParams, currentParams, processCohorts) { 38876 var deletedCohorts = [], 38877 addedCohorts = []; 38878 var iPrevious = 0, 38879 iCurrent = 0; 38880 while (iPrevious < previousParams.length || iCurrent < currentParams.length) { 38881 if (iPrevious >= previousParams.length) { 38882 //put into added box 38883 addedCohorts.push(currentParams[iCurrent]); 38884 iCurrent++; 38885 } 38886 else if (iCurrent >= currentParams.length) { 38887 //put into deleted box 38888 deletedCohorts.push(previousParams[iPrevious]); 38889 iPrevious++; 38890 } 38891 else if (this.isSameCohort(previousParams[iPrevious], currentParams[iCurrent])) { 38892 iPrevious++; 38893 iCurrent++; 38894 } 38895 else { 38896 //put into deleted box 38897 deletedCohorts.push(previousParams[iPrevious]); 38898 iPrevious++; 38899 } 38900 } 38901 38902 processCohorts(deletedCohorts, addedCohorts); 38903 }, 38904 38905 processFilterParams: function(params, processCohorts) { 38906 if (params == null) { 38907 params = ''; 38908 } 38909 38910 var result = { notEmpty: false, filling: "" }; 38911 38912 // split the url; 38913 var parameters = params.split('/'); 38914 38915 // group the params by filter 38916 var paramsGroups = [], size = 7; 38917 38918 while (parameters.length > 0) 38919 paramsGroups.push(parameters.splice(0, size)); 38920 38921 var lastLength = paramsGroups[paramsGroups.length - 1].length; 38922 if (lastLength < 7 && lastLength > 1) { 38923 // fill the params if incomplete 38924 for (var i = lastLength - 1; i < 7; i++) { 38925 paramsGroups[paramsGroups.length - 1].push(""); 38926 result.filling += '/'; 38927 } 38928 } else if (lastLength <= 1) { 38929 paramsGroups.pop(paramsGroups[paramsGroups.length - 1]); 38930 } 38931 38932 this.previousParams = this.currentParams; 38933 this.currentParams = paramsGroups; 38934 38935 this.calDifference(this.previousParams, this.currentParams, processCohorts); 38936 38937 result.notEmpty = this.currentParams.length > 0; 38938 38939 return result; 38940 }, 38941 38942 getFilterFromParams: function(params) { 38943 var filter = {}; 38944 38945 // 0 userfilter 38946 filter.userfilter = params[0]; 38947 38948 switch (filter.userfilter) { 38949 case 'Country': 38950 var country_region = params[1].split('_'); 38951 filter.selectedcountry = country_region[0]; 38952 if (country_region[1] != '') { 38953 filter.selectedregion = country_region[1]; 38954 } 38955 break; 38956 case 'Group': 38957 filter.selectedgroupid = params[1]; 38958 break; 38959 case 'Department': 38960 var temp = params[1].split('-'); 38961 filter.selecteddepartmentid = temp[0]; 38962 if (temp[1] != null) { 38963 filter.isfilteredbyyeargroup = true; 38964 filter.selectedyeargroupid = temp[1]; 38965 } 38966 break; 38967 case 'Teacher': 38968 filter.selectedteacherid = params[1]; 38969 break; 38970 case 'Student': 38971 filter.selecteduserid = params[1]; 38972 break; 38973 case 'School': 38974 filter.selectedschoolid = params[1]; 38975 break; 38976 case 'Assignment': 38977 filter.selectedassignmentid = params[1]; 38978 break; 38979 default: 38980 break; 38981 } 38982 38983 38984 // 2 start date 38985 if (params[2] != '') { 38986 filter.IsFilteredByDateRange = true; 38987 filter.StartDate = this.DateStringFromUrl(params[2]); 38988 } 38989 38990 // 3 end date 38991 if (params[3] != '') { 38992 filter.IsFilteredByDateRange = true; 38993 filter.EndDate = this.DateStringFromUrl(params[3]); 38994 } 38995 38996 // 4, 5 age range 38997 if (params[4] != '') { 38998 filter.IsFilteredByAgeRange = true; 38999 filter.AgeRangeYoungest = params[4]; 39000 } 39001 39002 // 3 end date 39003 if (params[5] != '') { 39004 filter.IsFilteredByAgeRange = true; 39005 filter.AgeRangeOldest = params[5]; 39006 } 39007 39008 // 6 gender and extension 39009 if (params[6] != '') { 39010 var extendParams = params[6].split('_'); 39011 var i = 0; 39012 if (extendParams[i] != '') { 39013 filter.GenderFilter = params[6] == 'M' ? 'Male' : 'Female'; 39014 } 39015 i++; 39016 if (extendParams[i] == 'T') { 39017 filter.IsOnlyShowCompletedAttempts = true; 39018 i++; 39019 } 39020 if (extendParams[i] == 'LQ') { 39021 filter.IsFilteredByLiveQuiz = true; 39022 filter.SelectedLiveQuizId = extendParams[i + 1];
39023 } 39024 39025 } 39026 39027 return filter; 39028 }, 39029 39030 getUrlFromFilter: function(filter) { 39031 39032 if (filter == null) 39033 return 'All///////'; 39034 39035 var url = ''; 39036 39037 url += filter.userfilter; 39038 url += '/'; 39039 39040 switch (filter.userfilter) { 39041 case 'Country': 39042 url += filter.selectedcountry; 39043 url += '_'; 39044 if (filter.selectedregion != null) 39045 url += filter.selectedregion; 39046 break; 39047 case 'Group': 39048 url += filter.selectedgroupid; 39049 break; 39050 case 'Department': 39051 url += filter.selecteddepartmentid; 39052 if (filter.isfilteredbyyeargroup) { 39053 url = url + '-' + filter.selectedyeargroupid; 39054 } 39055 break; 39056 case 'Teacher': 39057 url += filter.selectedteacherid; 39058 break; 39059 case 'Student': 39060 url += filter.selecteduserid; 39061 break; 39062 case 'School': 39063 url += filter.selectedschoolid; 39064 break; 39065 case 'Assignment': 39066 url += filter.selectedassignmentid; 39067 default: 39068 break; 39069 } 39070 url += '/'; 39071 39072 if (filter.StartDate != null) 39073 url += this.UrlFromDateString(filter.StartDate); 39074 url += '/'; 39075 39076 if (filter.EndDate != null) 39077 url += this.UrlFromDateString(filter.EndDate); 39078 url += '/'; 39079 39080 if (filter.AgeRangeYoungest != null) 39081 url += filter.AgeRangeYoungest; 39082 url += '/'; 39083 39084 if (filter.AgeRangeOldest != null) 39085 url += filter.AgeRangeOldest; 39086 url += '/'; 39087 39088 if (filter.GenderFilter != null && filter.GenderFilter != 'All') { 39089 url += filter.GenderFilter == 'Male' ? 'M' : 'F'; 39090 } 39091 if (filter.IsOnlyShowCompletedAttempts == true) { 39092 url += '_T'; 39093 } 39094 if (filter.IsFilteredByLiveQuiz == true) { 39095 url += '_LQ_' + filter.SelectedLiveQuizId; 39096 } 39097 url += '/'; 39098 39099 return url; 39100 }, 39101 39102 UrlFromDateString: function(dateString) { 39103 var dateurl = dateString; 39104 dateurl = dateurl.replace('/', ''); 39105 dateurl = dateurl.replace('/', ''); 39106 dateurl = dateurl.replace(' ', ''); 39107 dateurl = dateurl.replace(':', ''); 39108 return dateurl; 39109 }, 39110 39111 DateStringFromUrl: function(dateUrl) { 39112 var dateString = dateUrl.substring(0, 2) + '/' 39113 + dateUrl.substring(2, 4) + '/' 39114 + dateUrl.substring(4, 8) + ' ' 39115 + dateUrl.substring(8, 10) + ':' 39116 + dateUrl.substring(10, 12); 39117 return dateString; 39118 }, 39119 39120 getUniqueCohortName: function(candidate, existing) { 39121 for (var i = 0; i < existing.length; i++) { 39122 if (existing[i] == candidate) { 39123 return this.tryName(candidate, 2, existing); 39124 } 39125 } 39126 return candidate; 39127 }, 39128 39129 tryName: function(candidate, num, existing) { 39130 for (var i = 0; i < existing.length; i++) { 39131 if (existing[i] == candidate + ' ' + num) { 39132 return this.tryName(candidate, num + 1, existing); 39133 } 39134 } 39135 return candidate + ' ' + num; 39136 }, 39137 39138 getDateRangeString: function(filter) { 39139 var result = ""; 39140 39141 result += filter.StartDate + " to " + filter.EndDate + "\n"; 39142 39143 return result; 39144 }, 39145 39146 getFilterDetailString: function(filter) { 39147 var result = []; 39148 39149 if (filter.GenderFilter != null && filter.GenderFilter != "All") 39150 result.push(filter.GenderFilter); 39151 39152 if (filter.IsFilteredByDateRange) 39153 result.push(filter.StartDate + " - " + filter.EndDate); 39154 39155 if (filter.IsFilteredByAgeRange) 39156 result.push((filter.AgeRangeYoungest == null ? "Any" : filter.AgeRangeYoungest) + " - " + (filter.AgeRangeOldest == null ? "Any" : filter.AgeRangeOldest)); 39157 39158 if (result.length == 0) { 39159 return ' '; 39160 } 39161 return result.join(' | '); 39162 }, 39163 39164 getCohortNameByUrl: function(url, existing) { 39165 for (var i = 0; i < existing.length; i++) { 39166 if (existing[i].url == url) 39167 return existing[i].name; 39168 } 39169 return null; 39170 }, 39171 39172 isSameCohort: function(params1, params2) 39173 { 39174 for(var i = 0; i < params1.length; i++) 39175 { 39176 if (params1[i] != params2[i]) 39177 return false; 39178 } 39179 return true; 39180 }, 39181 39182 union_arrays: function(x, y) { 39183 var obj = {}; 39184 for (var i = x.length-1; i >= 0; -- i) 39185 obj[x[i]] = x[i]; 39186 for (var i = y.length-1; i >= 0; -- i) 39187 obj[y[i]] = y[i]; 39188 var res = [] 39189 for (var k in obj) { 39190 if (obj.hasOwnProperty(k)) // <-- optional 39191 res.push(obj[k]); 39192 } 39193 return res; 39194 } 39195 39196 } 39197}); 39198define('dataFilter',['jquery', 'bootstrap'], (function ($) { 39199 39200 //constructor 39201 var dataFilter = function () { 39202 39203 }; 39204 39205 //public method 39206 dataFilter.prototype.init = function () { 39207 39208 $('.js-set-deadline').click(function () { 39209 if (this.checked) { 39210 $('.js-date-entry').removeClass('hide'); 39211 } else { 39212 $('.js-date-entry').addClass('hide'); 39213 } 39214 }); 39215 39216 $('#startDateTimePicker').datetimepicker({ 39217 icons: { 39218 time: "icon-time", 39219 date: "icon-calendar", 39220 up: "icon-chevron-up", 39221 down: "icon-chevron-down" 39222 }, 39223 format: "DD/MM/YYYY HH:mm" 39224 }); 39225 39226 $('#endDateTimePicker').datetimepicker({ 39227 icons: { 39228 time: "icon-time", 39229 date: "icon-calendar", 39230 up: "icon-chevron-up", 39231 down: "icon-chevron-down" 39232 }, 39233 format: "DD/MM/YYYY HH:mm" 39234 }); 39235 39236 $('#startDateTimePicker').on("dp.change", function (e) { 39237 $('#endDateTimePicker').data("DateTimePicker").setMinDate(e.date); 39238 }); 39239 39240 $('.js-set-age-range').click(function () { 39241 if (this.checked) { 39242 $('.js-age-entry').removeClass('hide'); 39243 } else { 39244 $('.js-age-entry').addClass('hide'); 39245 } 39246 }); 39247 39248 $('.js-delete-filter-table-row').click(function (event) { 39249 event.preventDefault(); 39250 $(this).closest('tr').remove(); 39251 }); 39252 39253 $('#UserFilter').change(function () { 39254 39255 switch (this.value) { 39256 case "Group": 39257 $('#SelectedGroupId').removeClass('hide'); 39258 $('.js-filter-dropdown').not('#SelectedGroupId').addClass('hide'); 39259 break; 39260 case "Teacher": 39261 $('#SelectedTeacherId').removeClass('hide'); 39262 $('.js-filter-dropdown').not('#SelectedTeacherId').addClass('hide'); 39263 break; 39264 case "Country": 39265 $('#SelectedCountry').removeClass('hide'); 39266 $('#SelectedRegion').removeClass('hide'); 39267 $('.js-filter-dropdown').not('#SelectedCountry,#SelectedRegion').addClass('hide'); 39268 break; 39269 case "Student": 39270 $('#SelectedUserId').removeClass('hide'); 39271 $('.js-filter-dropdown').not('#SelectedUserId').addClass('hide'); 39272 break; 39273 default: 39274 $('.js-filter-dropdown').addClass('hide'); 39275 break; 39276 }; 39277 39278 SwitchLoadDropDownItems(this.value); 39279 39280 }); 39281 39282 $('#SelectedCountry').change(function () { 39283 LoadRegionsDropDown(this.value); 39284 }); 39285 39286 39287 $('input:radio[name=toggleCountsPercentage]').change(function () { 39288 39289 if (this.value == 'counts') { 39290 $('.js-answer-dots').addClass('hide'); 39291 $('.js-answer-count').removeClass('hide'); 39292 $('.js-answer-percentage').addClass('hide'); 39293 } else if (this.value == 'percentage') { 39294 $('.js-answer-dots').addClass('hide'); 39295 $('.js-answer-count').addClass('hide'); 39296 $('.js-answer-percentage').removeClass('hide'); 39297 } else { 39298 $('.js-answer-dots').removeClass('hide'); 39299 $('.js-answer-count').addClass('hide'); 39300 $('.js-answer-percentage').addClass('hide'); 39301 } 39302 }); 39303 39304 SwitchLoadDropDownItems($('#UserFilter').val()); 39305 39306 39307 }; 39308 39309 function SwitchLoadDropDownItems(userFilterValue) { 39310 39311 switch (userFilterValue) { 39312 case "Group": 39313 LoadDropDownItems('#SelectedGroupId', '/Data/LoadGroups') 39314 break; 39315 case "Teacher": 39316 LoadDropDownItems('#SelectedTeacherId', '/Data/LoadTeachers') 39317 break; 39318 case "Country": 39319 LoadDropDownItems('#SelectedCountry', '/Data/LoadCountries') 39320 if ($('#SelectedCountry').val() != "") 39321 LoadRegionsDropDown($('#SelectedCountry').val()); 39322 break; 39323 case "Student": 39324 LoadDropDownItems('#SelectedUserId', '/Data/LoadStudents') 39325 break; 39326 default: 39327 break; 39328 }; 39329 39330 } 39331 39332 function LoadRegionsDropDown(countryname) { 39333 var model = { countryname: countryname }; 39334 var id = '#SelectedRegion' 39335 39336 $.ajax({
39337 url: '/Data/LoadRegions', 39338 type: 'POST', 39339 data: JSON.stringify(model), 39340 datatype: 'json', 39341 processData: false, 39342 contentType: 'application/json; charset=utf-8', 39343 success: function (data) { 39344 var dropDown = $(id); 39345 var selectedValue = $(dropDown).val(); 39346 39347 $(dropDown).empty(); 39348 39349 $(document.createElement('option')) 39350 .attr('value', '') 39351 .text('Choose...') 39352 .appendTo(dropDown); 39353 39354 $(data).each(function () { 39355 $(document.createElement('option')) 39356 .attr('value', this.Value) 39357 .text(this.Text) 39358 .appendTo(dropDown); 39359 }); 39360 39361 $(dropDown).val(selectedValue); 39362 $(dropDown).data('listed', true); 39363 } 39364 }); 39365 } 39366 39367 function LoadDropDownItems(id, url) { 39368 if (!($(id).data('listed') === true)) { 39369 $.getJSON(url, function (data) { 39370 var dropDown = $(id); 39371 var selectedValue = $(dropDown).val(); 39372 39373 $(dropDown).empty(); 39374 39375 $(document.createElement('option')) 39376 .attr('value', '') 39377 .text('Choose...') 39378 .appendTo(dropDown); 39379 39380 $(data).each(function () { 39381 $(document.createElement('option')) 39382 .attr('value', this.Value) 39383 .text(this.Text) 39384 .appendTo(dropDown); 39385 }); 39386 39387 $(dropDown).val(selectedValue); 39388 $(dropDown).data('listed', true); 39389 }); 39390 } 39391 }; 39392 39393 //public module 39394 return dataFilter; 39395 39396})); 39397 39398(function (exports) { 39399 function copyOwnFrom(target, source) { 39400 Object.getOwnPropertyNames(source).forEach(function(propName) { 39401 Object.defineProperty(target, propName, 39402 Object.getOwnPropertyDescriptor(source, propName)); 39403 }); 39404 return target; 39405 } 39406 39407 function Symbol(name, props) { 39408 this.name = name; 39409 if (props) { 39410 copyOwnFrom(this, props); 39411 } 39412 Object.freeze(this); 39413 } 39414 /** We donât want the mutable Object.prototype in the prototype chain */ 39415 Symbol.prototype = Object.create(null); 39416 Symbol.prototype.constructor = Symbol; 39417 /** 39418 * Without Object.prototype in the prototype chain, we need toString() 39419 * in order to display symbols. 39420 */ 39421 Symbol.prototype.toString = function () { 39422 return "|"+this.name+"|"; 39423 }; 39424 Object.freeze(Symbol.prototype); 39425 39426 Enum = function (obj) { 39427 if (arguments.length === 1 && obj !== null && typeof obj === "object") { 39428 Object.keys(obj).forEach(function (name) { 39429 this[name] = new Symbol(name, obj[name]); 39430 }, this); 39431 } else { 39432 Array.prototype.forEach.call(arguments, function (name) { 39433 this[name] = new Symbol(name); 39434 }, this); 39435 } 39436 Object.freeze(this); 39437 } 39438 Enum.prototype.symbols = function() { 39439 return Object.keys(this).map( 39440 function(key) { 39441 return this[key]; 39442 }, this 39443 ); 39444 } 39445 Enum.prototype.contains = function(sym) { 39446 if (! sym instanceof Symbol) return false; 39447 return this[sym.name] === sym; 39448 } 39449 exports.Enum = Enum; 39450 exports.Symbol = Symbol; 39451}(typeof exports === "undefined" ? this.enums = {} : exports)); 39452// Explanation of this pattern: http://www.2ality.com/2011/08/universal-modules.html; 39453define("enums", (function (global) { 39454 return function () { 39455 var ret, fn; 39456 return ret || global.enums; 39457 }; 39458}(this))); 39459 39460/* build: `node build.js modules=ALL exclude=gestures` */ 39461/*! Fabric.js Copyright 2008-2013, Printio (Juriy Zaytsev, Maxim Chernyak) */ 39462 39463var fabric = fabric || { version: "1.3.7" }; 39464if (typeof exports !== 'undefined') { 39465 exports.fabric = fabric; 39466} 39467 39468if (typeof document !== 'undefined' && typeof window !== 'undefined') { 39469 fabric.document = document; 39470 fabric.window = window; 39471} 39472else { 39473 // assume we're running under node.js when document/window are not present 39474 fabric.document = require("jsdom").jsdom("<!DOCTYPE html><html><head></head><body></body></html>"); 39475 fabric.window = fabric.document.createWindow(); 39476} 39477 39478/** 39479 * True when in environment that supports touch events 39480 * @type boolean 39481 */ 39482fabric.isTouchSupported = "ontouchstart" in fabric.document.documentElement; 39483 39484/** 39485 * True when in environment that's probably Node.js 39486 * @type boolean 39487 */ 39488fabric.isLikelyNode = typeof Buffer !== 'undefined' && typeof window === 'undefined'; 39489 39490 39491/*! 39492 * Copyright (c) 2009 Simo Kinnunen. 39493 * Licensed under the MIT license. 39494 */ 39495 39496var Cufon = (function() { 39497 39498 /** @ignore */ 39499 var api = function() { 39500 return api.replace.apply(null, arguments); 39501 }; 39502 39503 /** @ignore */ 39504 var DOM = api.DOM = { 39505 39506 ready: (function() { 39507 39508 var complete = false, readyStatus = { loaded: 1, complete: 1 }; 39509 39510 var queue = [], /** @ignore */ perform = function() { 39511 if (complete) return; 39512 complete = true; 39513 for (var fn; fn = queue.shift(); fn()); 39514 }; 39515 39516 // Gecko, Opera, WebKit r26101+ 39517 39518 if (fabric.document.addEventListener) { 39519 fabric.document.addEventListener('DOMContentLoaded', perform, false); 39520 fabric.window.addEventListener('pageshow', perform, false); // For cached Gecko pages 39521 } 39522 39523 // Old WebKit, Internet Explorer 39524 39525 if (!fabric.window.opera && fabric.document.readyState) (function() { 39526 readyStatus[fabric.document.readyState] ? perform() : setTimeout(arguments.callee, 10); 39527 })(); 39528 39529 // Internet Explorer 39530 39531 if (fabric.document.readyState && fabric.document.createStyleSheet) (function() { 39532 try { 39533 fabric.document.body.doScroll('left'); 39534 perform(); 39535 } 39536 catch (e) { 39537 setTimeout(arguments.callee, 1); 39538 } 39539 })(); 39540 39541 addEvent(fabric.window, 'load', perform); // Fallback 39542 39543 return function(listener) { 39544 if (!arguments.length) perform(); 39545 else complete ? listener() : queue.push(listener); 39546 }; 39547 39548 })() 39549 39550 }; 39551 39552 /** @ignore */ 39553 var CSS = api.CSS = /** @ignore */ { 39554 39555 /** @ignore */ 39556 Size: function(value, base) { 39557 39558 this.value = parseFloat(value); 39559 this.unit = String(value).match(/[a-z%]*$/)[0] || 'px'; 39560 39561 /** @ignore */ 39562 this.convert = function(value) { 39563 return value / base * this.value; 39564 }; 39565 39566 /** @ignore */ 39567 this.convertFrom = function(value) { 39568 return value / this.value * base; 39569 }; 39570 39571 /** @ignore */ 39572 this.toString = function() { 39573 return this.value + this.unit; 39574 }; 39575 39576 }, 39577 39578 /** @ignore */ 39579 getStyle: function(el) { 39580 return new Style(el.style); 39581 /* 39582 var view = document.defaultView; 39583 if (view && view.getComputedStyle) return new Style(view.getComputedStyle(el, null)); 39584 if (el.currentStyle) return new Style(el.currentStyle); 39585 return new Style(el.style); 39586 */ 39587 }, 39588 39589 quotedList: cached(function(value) { 39590 // doesn't work properly with empty quoted strings (""), but 39591 // it's not worth the extra code.
39592 var list = [], re = /\s*((["'])([\s\S]*?[^\\])\2|[^,]+)\s*/g, match; 39593 while (match = re.exec(value)) list.push(match[3] || match[1]); 39594 return list; 39595 }), 39596 39597 ready: (function() { 39598 39599 var complete = false; 39600 39601 var queue = [], perform = function() { 39602 complete = true; 39603 for (var fn; fn = queue.shift(); fn()); 39604 }; 39605 39606 // Safari 2 does not include <style> elements in document.styleSheets. 39607 // Safari 2 also does not support Object.prototype.propertyIsEnumerable. 39608 39609 var styleElements = Object.prototype.propertyIsEnumerable ? elementsByTagName('style') : { length: 0 }; 39610 var linkElements = elementsByTagName('link'); 39611 39612 DOM.ready(function() { 39613 // These checks are actually only needed for WebKit-based browsers, but don't really hurt other browsers. 39614 var linkStyles = 0, link; 39615 for (var i = 0, l = linkElements.length; link = linkElements[i], i < l; ++i) { 39616 // WebKit does not load alternate stylesheets. 39617 if (!link.disabled && link.rel.toLowerCase() == 'stylesheet') ++linkStyles; 39618 } 39619 if (fabric.document.styleSheets.length >= styleElements.length + linkStyles) perform(); 39620 else setTimeout(arguments.callee, 10); 39621 }); 39622 39623 return function(listener) { 39624 if (complete) listener(); 39625 else queue.push(listener); 39626 }; 39627 39628 })(), 39629 39630 /** @ignore */ 39631 supports: function(property, value) { 39632 var checker = fabric.document.createElement('span').style; 39633 if (checker[property] === undefined) return false; 39634 checker[property] = value; 39635 return checker[property] === value; 39636 }, 39637 39638 /** @ignore */ 39639 textAlign: function(word, style, position, wordCount) { 39640 if (style.get('textAlign') == 'right') { 39641 if (position > 0) word = ' ' + word; 39642 } 39643 else if (position < wordCount - 1) word += ' '; 39644 return word; 39645 }, 39646 39647 /** @ignore */ 39648 textDecoration: function(el, style) { 39649 if (!style) style = this.getStyle(el); 39650 var types = { 39651 underline: null, 39652 overline: null, 39653 'line-through': null 39654 }; 39655 for (var search = el; search.parentNode && search.parentNode.nodeType == 1; ) { 39656 var foundAll = true; 39657 for (var type in types) { 39658 if (types[type]) continue; 39659 if (style.get('textDecoration').indexOf(type) != -1) types[type] = style.get('color'); 39660 foundAll = false; 39661 } 39662 if (foundAll) break; // this is rather unlikely to happen 39663 style = this.getStyle(search = search.parentNode); 39664 } 39665 return types; 39666 }, 39667 39668 textShadow: cached(function(value) { 39669 if (value == 'none') return null; 39670 var shadows = [], currentShadow = {}, result, offCount = 0; 39671 var re = /(#[a-f0-9]+|[a-z]+\(.*?\)|[a-z]+)|(-?[\d.]+[a-z%]*)|,/ig; 39672 while (result = re.exec(value)) { 39673 if (result[0] == ',') { 39674 shadows.push(currentShadow); 39675 currentShadow = {}, offCount = 0; 39676 } 39677 else if (result[1]) { 39678 currentShadow.color = result[1]; 39679 } 39680 else { 39681 currentShadow[[ 'offX', 'offY', 'blur' ][offCount++]] = result[2]; 39682 } 39683 } 39684 shadows.push(currentShadow); 39685 return shadows; 39686 }), 39687 39688 color: cached(function(value) { 39689 var parsed = {}; 39690 parsed.color = value.replace(/^rgba\((.*?),\s*([\d.]+)\)/, function($0, $1, $2) { 39691 parsed.opacity = parseFloat($2); 39692 return 'rgb(' + $1 + ')'; 39693 }); 39694 return parsed; 39695 }), 39696 39697 /** @ignore */ 39698 textTransform: function(text, style) { 39699 return text[{ 39700 uppercase: 'toUpperCase', 39701 lowercase: 'toLowerCase' 39702 }[style.get('textTransform')] || 'toString'](); 39703 } 39704 39705 }; 39706 39707 function Font(data) { 39708 39709 var face = this.face = data.face; 39710 this.glyphs = data.glyphs; 39711 this.w = data.w; 39712 this.baseSize = parseInt(face['units-per-em'], 10); 39713 39714 this.family = face['font-family'].toLowerCase(); 39715 this.weight = face['font-weight']; 39716 this.style = face['font-style'] || 'normal'; 39717 39718 this.viewBox = (function () { 39719 var parts = face.bbox.split(/\s+/); 39720 var box = { 39721 minX: parseInt(parts[0], 10), 39722 minY: parseInt(parts[1], 10), 39723 maxX: parseInt(parts[2], 10), 39724 maxY: parseInt(parts[3], 10) 39725 }; 39726 box.width = box.maxX - box.minX, 39727 box.height = box.maxY - box.minY; 39728 /** @ignore */ 39729 box.toString = function() { 39730 return [ this.minX, this.minY, this.width, this.height ].join(' '); 39731 }; 39732 return box; 39733 })(); 39734 39735 this.ascent = -parseInt(face.ascent, 10);
39736 this.descent = -parseInt(face.descent, 10); 39737 39738 this.height = -this.ascent + this.descent; 39739 39740 } 39741 39742 function FontFamily() { 39743 39744 var styles = {}, mapping = { 39745 oblique: 'italic', 39746 italic: 'oblique' 39747 }; 39748 39749 this.add = function(font) { 39750 (styles[font.style] || (styles[font.style] = {}))[font.weight] = font; 39751 }; 39752 39753 /** @ignore */ 39754 this.get = function(style, weight) { 39755 var weights = styles[style] || styles[mapping[style]] 39756 || styles.normal || styles.italic || styles.oblique; 39757 if (!weights) return null; 39758 // we don't have to worry about "bolder" and "lighter" 39759 // because IE's currentStyle returns a numeric value for it, 39760 // and other browsers use the computed value anyway 39761 weight = { 39762 normal: 400, 39763 bold: 700 39764 }[weight] || parseInt(weight, 10); 39765 if (weights[weight]) return weights[weight]; 39766 // http://www.w3.org/TR/CSS21/fonts.html#propdef-font-weight 39767 // Gecko uses x99/x01 for lighter/bolder 39768 var up = { 39769 1: 1, 39770 99: 0 39771 }[weight % 100], alts = [], min, max; 39772 if (up === undefined) up = weight > 400; 39773 if (weight == 500) weight = 400; 39774 for (var alt in weights) { 39775 alt = parseInt(alt, 10); 39776 if (!min || alt < min) min = alt; 39777 if (!max || alt > max) max = alt; 39778 alts.push(alt); 39779 } 39780 if (weight < min) weight = min; 39781 if (weight > max) weight = max; 39782 alts.sort(function(a, b) { 39783 return (up 39784 ? (a > weight && b > weight) ? a < b : a > b 39785 : (a < weight && b < weight) ? a > b : a < b) ? -1 : 1; 39786 }); 39787 return weights[alts[0]]; 39788 }; 39789 39790 } 39791 39792 function HoverHandler() { 39793 39794 function contains(node, anotherNode) { 39795 if (node.contains) return node.contains(anotherNode); 39796 return node.compareDocumentPosition(anotherNode) & 16; 39797 } 39798 39799 function onOverOut(e) { 39800 var related = e.relatedTarget; 39801 if (!related || contains(this, related)) return; 39802 trigger(this); 39803 } 39804 39805 function onEnterLeave(e) { 39806 trigger(this); 39807 } 39808 39809 function trigger(el) { 39810 // A timeout is needed so that the event can actually "happen" 39811 // before replace is triggered. This ensures that styles are up 39812 // to date. 39813 setTimeout(function() { 39814 api.replace(el, sharedStorage.get(el).options, true); 39815 }, 10); 39816 } 39817 39818 this.attach = function(el) { 39819 if (el.onmouseenter === undefined) { 39820 addEvent(el, 'mouseover', onOverOut); 39821 addEvent(el, 'mouseout', onOverOut); 39822 } 39823 else { 39824 addEvent(el, 'mouseenter', onEnterLeave); 39825 addEvent(el, 'mouseleave', onEnterLeave); 39826 } 39827 }; 39828 39829 } 39830 39831 function Storage() { 39832 39833 var map = {}, at = 0; 39834 39835 function identify(el) { 39836 return el.cufid || (el.cufid = ++at); 39837 } 39838 39839 /** @ignore */ 39840 this.get = function(el) { 39841 var id = identify(el); 39842 return map[id] || (map[id] = {}); 39843 }; 39844 39845 } 39846 39847 function Style(style) { 39848 39849 var custom = {}, sizes = {}; 39850 39851 this.get = function(property) { 39852 return custom[property] != undefined ? custom[property] : style[property]; 39853 }; 39854 39855 this.getSize = function(property, base) { 39856 return sizes[property] || (sizes[property] = new CSS.Size(this.get(property), base)); 39857 }; 39858 39859 this.extend = function(styles) { 39860 for (var property in styles) custom[property] = styles[property]; 39861 return this; 39862 }; 39863 39864 } 39865 39866 function addEvent(el, type, listener) { 39867 if (el.addEventListener) { 39868 el.addEventListener(type, listener, false); 39869 } 39870 else if (el.attachEvent) { 39871 el.attachEvent('on' + type, function() { 39872 return listener.call(el, fabric.window.event); 39873 }); 39874 } 39875 } 39876 39877 function attach(el, options) { 39878 var storage = sharedStorage.get(el); 39879 if (storage.options) return el; 39880 if (options.hover && options.hoverables[el.nodeName.toLowerCase()]) { 39881 hoverHandler.attach(el); 39882 } 39883 storage.options = options; 39884 return el; 39885 } 39886 39887 function cached(fun) { 39888 var cache = {}; 39889 return function(key) { 39890 if (!cache.hasOwnProperty(key)) cache[key] = fun.apply(null, arguments); 39891 return cache[key]; 39892 }; 39893 } 39894 39895 function getFont(el, style) {
39896 if (!style) style = CSS.getStyle(el); 39897 var families = CSS.quotedList(style.get('fontFamily').toLowerCase()), family; 39898 for (var i = 0, l = families.length; i < l; ++i) { 39899 family = families[i]; 39900 if (fonts[family]) return fonts[family].get(style.get('fontStyle'), style.get('fontWeight')); 39901 } 39902 return null; 39903 } 39904 39905 function elementsByTagName(query) { 39906 return fabric.document.getElementsByTagName(query); 39907 } 39908 39909 function merge() { 39910 var merged = {}, key; 39911 for (var i = 0, l = arguments.length; i < l; ++i) { 39912 for (key in arguments[i]) merged[key] = arguments[i][key]; 39913 } 39914 return merged; 39915 } 39916 39917 function process(font, text, style, options, node, el) { 39918 39919 var separate = options.separate; 39920 if (separate == 'none') return engines[options.engine].apply(null, arguments); 39921 var fragment = fabric.document.createDocumentFragment(), processed; 39922 var parts = text.split(separators[separate]), needsAligning = (separate == 'words'); 39923 if (needsAligning && HAS_BROKEN_REGEXP) { 39924 // @todo figure out a better way to do this 39925 if (/^\s/.test(text)) parts.unshift(''); 39926 if (/\s$/.test(text)) parts.push(''); 39927 } 39928 for (var i = 0, l = parts.length; i < l; ++i) { 39929 processed = engines[options.engine](font, 39930 needsAligning ? CSS.textAlign(parts[i], style, i, l) : parts[i], 39931 style, options, node, el, i < l - 1); 39932 if (processed) fragment.appendChild(processed); 39933 } 39934 return fragment; 39935 } 39936 39937 /** @ignore */ 39938 function replaceElement(el, options) { 39939 var font, style, nextNode, redraw; 39940 for (var node = attach(el, options).firstChild; node; node = nextNode) { 39941 nextNode = node.nextSibling; 39942 redraw = false; 39943 if (node.nodeType == 1) { 39944 if (!node.firstChild) continue; 39945 if (!/cufon/.test(node.className)) { 39946 arguments.callee(node, options); 39947 continue; 39948 } 39949 else redraw = true; 39950 } 39951 if (!style) style = CSS.getStyle(el).extend(options); 39952 if (!font) font = getFont(el, style); 39953 39954 if (!font) continue; 39955 if (redraw) { 39956 engines[options.engine](font, null, style, options, node, el); 39957 continue; 39958 } 39959 var text = node.data; 39960 //for some reason, the carriage return is not stripped by IE but "\n" is, so let's keep \r as a new line marker... 39961 if (typeof G_vmlCanvasManager != 'undefined') { 39962 text = text.replace(/\r/g, "\n"); 39963 } 39964 if (text === '') continue; 39965 var processed = process(font, text, style, options, node, el); 39966 if (processed) node.parentNode.replaceChild(processed, node); 39967 else node.parentNode.removeChild(node); 39968 } 39969 } 39970 39971 var HAS_BROKEN_REGEXP = ' '.split(/\s+/).length == 0; 39972 39973 var sharedStorage = new Storage(); 39974 var hoverHandler = new HoverHandler(); 39975 var replaceHistory = []; 39976 39977 var engines = {}, fonts = {}, defaultOptions = { 39978 engine: null, 39979 //fontScale: 1, 39980 //fontScaling: false, 39981 hover: false, 39982 hoverables: { 39983 a: true 39984 }, 39985 printable: true, 39986 //rotation: 0, 39987 //selectable: false, 39988 selector: ( 39989 fabric.window.Sizzle 39990 || (fabric.window.jQuery && function(query) { return jQuery(query); }) // avoid noConflict issues 39991 || (fabric.window.dojo && dojo.query) 39992 || (fabric.window.$$ && function(query) { return $$(query); }) 39993 || (fabric.window.$ && function(query) { return $(query); }) 39994 || (fabric.document.querySelectorAll && function(query) { return fabric.document.querySelectorAll(query); }) 39995 || elementsByTagName 39996 ), 39997 separate: 'words', // 'none' and 'characters' are also accepted 39998 textShadow: 'none' 39999 }; 40000 40001 var separators = { 40002 words: /\s+/, 40003 characters: '' 40004 }; 40005 40006 /** @ignore */ 40007 api.now = function() { 40008 DOM.ready(); 40009 return api; 40010 }; 40011 40012 /** @ignore */ 40013 api.refresh = function() { 40014 var currentHistory = replaceHistory.splice(0, replaceHistory.length); 40015 for (var i = 0, l = currentHistory.length; i < l; ++i) { 40016 api.replace.apply(null, currentHistory[i]); 40017 } 40018 return api; 40019 }; 40020 40021 /** @ignore */ 40022 api.registerEngine = function(id, engine) { 40023 if (!engine) return api; 40024 engines[id] = engine; 40025 return api.set('engine', id); 40026 }; 40027 40028 /** @ignore */ 40029 api.registerFont = function(data) { 40030 var font = new Font(data), family = font.family; 40031 if (!fonts[family]) fonts[family] = new FontFamily(); 40032 fonts[family].add(font); 40033 return api.set('fontFamily', '"' + family + '"'); 40034 }; 40035 40036 /** @ignore */ 40037 api.replace = function(elements, options, ignoreHistory) { 40038 options = merge(defaultOptions, options); 40039 if (!options.engine) return api; // there's no browser support so we'll just stop here 40040 if (typeof options.textShadow == 'string' && options.textShadow) 40041 options.textShadow = CSS.textShadow(options.textShadow); 40042 if (!ignoreHistory) replaceHistory.push(arguments); 40043 if (elements.nodeType || typeof elements == 'string') elements = [ elements ]; 40044 CSS.ready(function() { 40045 for (var i = 0, l = elements.length; i < l; ++i) { 40046 var el = elements[i]; 40047 if (typeof el == 'string') api.replace(options.selector(el), options, true); 40048 else replaceElement(el, options); 40049 } 40050 }); 40051 return api; 40052 }; 40053 40054 /** @ignore */ 40055 api.replaceElement = function(el, options) { 40056 options = merge(defaultOptions, options); 40057 if (typeof options.textShadow == 'string' && options.textShadow) 40058 options.textShadow = CSS.textShadow(options.textShadow); 40059 return replaceElement(el, options); 40060 }; 40061 40062 api.engines = engines; 40063 api.fonts = fonts; 40064 /** @ignore */ 40065 api.getOptions = function() { 40066 return merge(defaultOptions); 40067 }; 40068 40069 /** @ignore */ 40070 api.set = function(option, value) { 40071 defaultOptions[option] = value; 40072 return api; 40073 }; 40074 40075 return api; 40076 40077})(); 40078 40079Cufon.registerEngine('canvas', (function() { 40080 40081 // Safari 2 doesn't support .apply() on native methods 40082 var HAS_INLINE_BLOCK = Cufon.CSS.supports('display', 'inline-block'); 40083 40084 // Firefox 2 w/ non-strict doctype (almost standards mode) 40085 var HAS_BROKEN_LINEHEIGHT = !HAS_INLINE_BLOCK && (fabric.document.compatMode == 'BackCompat' || /frameset|transitional/i.test(fabric.document.doctype.publicId)); 40086 40087 var styleSheet = fabric.document.createElement('style'); 40088 styleSheet.type = 'text/css'; 40089 40090 var textNode = fabric.document.createTextNode( 40091 '.cufon-canvas{text-indent:0}' + 40092 '@media screen,projection{' + 40093 '.cufon-canvas{display:inline;display:inline-block;position:relative;vertical-align:middle' + 40094 (HAS_BROKEN_LINEHEIGHT 40095 ? '' 40096 : ';font-size:1px;line-height:1px') + 40097 '}.cufon-canvas .cufon-alt{display:-moz-inline-box;display:inline-block;width:0;height:0;overflow:hidden}' + 40098 (HAS_INLINE_BLOCK 40099 ? '.cufon-canvas canvas{position:relative}' 40100 : '.cufon-canvas canvas{position:absolute}') + 40101 '}' + 40102 '@media print{' + 40103 '.cufon-canvas{padding:0 !important}' + 40104 '.cufon-canvas canvas{display:none}' + 40105 '.cufon-canvas .cufon-alt{display:inline}' + 40106 '}' 40107 ) 40108 40109 try { 40110 styleSheet.appendChild(textNode); 40111 } catch(e) { 40112 //IE8- can't do this... 40113 styleSheet.setAttribute("type", "text/css"); 40114 styleSheet.styleSheet.cssText = textNode.data; 40115 } 40116 fabric.document.getElementsByTagName('head')[0].appendChild(styleSheet); 40117 40118 function generateFromVML(path, context) { 40119 var atX = 0, atY = 0; 40120 var code = [], re = /([mrvxe])([^a-z]*)/g, match; 40121 generate: for (var i = 0; match = re.exec(path); ++i) { 40122 var c = match[2].split(','); 40123 switch (match[1]) { 40124 case 'v': 40125 code[i] = { m: 'bezierCurveTo', a: [ atX + ~~c[0], atY + ~~c[1], atX + ~~c[2], atY + ~~c[3], atX += ~~c[4], atY += ~~c[5] ] }; 40126 break; 40127 case 'r': 40128 code[i] = { m: 'lineTo', a: [ atX += ~~c[0], atY += ~~c[1] ] }; 40129 break; 40130 case 'm': 40131 code[i] = { m: 'moveTo', a: [ atX = ~~c[0], atY = ~~c[1] ] }; 40132 break; 40133 case 'x': 40134 code[i] = { m: 'closePath', a: [] }; 40135 break; 40136 case 'e': 40137 break generate; 40138 } 40139 context[code[i].m].apply(context, code[i].a); 40140 } 40141 return code; 40142 } 40143 40144 function interpret(code, context) { 40145 for (var i = 0, l = code.length; i < l; ++i) { 40146 var line = code[i]; 40147 context[line.m].apply(context, line.a); 40148 } 40149 } 40150 40151 return function(font, text, style, options, node, el) { 40152 40153 var redraw = (text === null); 40154 40155 var viewBox = font.viewBox; 40156 40157 var size = style.getSize('fontSize', font.baseSize); 40158 40159 var letterSpacing = style.get('letterSpacing'); 40160 letterSpacing = (letterSpacing == 'normal') ? 0 : size.convertFrom(parseInt(letterSpacing, 10)); 40161 40162 var expandTop = 0, expandRight = 0, expandBottom = 0, expandLeft = 0; 40163 var shadows = options.textShadow, shadowOffsets = []; 40164 40165 Cufon.textOptions.shadowOffsets = [ ]; 40166 Cufon.textOptions.shadows = null; 40167 40168 if (shadows) { 40169 Cufon.textOptions.shadows = shadows; 40170 for (var i = 0, l = shadows.length; i < l; ++i) { 40171 var shadow = shadows[i]; 40172 var x = size.convertFrom(parseFloat(shadow.offX)); 40173 var y = size.convertFrom(parseFloat(shadow.offY)); 40174 shadowOffsets[i] = [ x, y ]; 40175 //if (y < expandTop) expandTop = y; 40176 //if (x > expandRight) expandRight = x; 40177 //if (y > expandBottom) expandBottom = y; 40178 //if (x < expandLeft) expandLeft = x; 40179 } 40180 } 40181 40182 var chars = Cufon.CSS.textTransform(redraw ? node.alt : text, style).split(''); 40183 40184 var width = 0, lastWidth = null; 40185 40186 var maxWidth = 0, lines = 1, lineWidths = [ ]; 40187 for (var i = 0, l = chars.length; i < l; ++i) { 40188 if (chars[i] === '\n') { 40189 lines++; 40190 if (width > maxWidth) { 40191 maxWidth = width; 40192 } 40193 lineWidths.push(width); 40194 width = 0; 40195 continue; 40196 } 40197 var glyph = font.glyphs[chars[i]] || font.missingGlyph; 40198 if (!glyph) continue; 40199 width += lastWidth = Number(glyph.w || font.w) + letterSpacing; 40200 } 40201 lineWidths.push(width); 40202 40203 width = Math.max(maxWidth, width); 40204 40205 var lineOffsets = [ ]; 40206 for (var i = lineWidths.length; i--; ) { 40207 lineOffsets[i] = width - lineWidths[i]; 40208 } 40209 40210 if (lastWidth === null) return null; // there's nothing to render 40211 40212 expandRight += (viewBox.width - lastWidth); 40213 expandLeft += viewBox.minX; 40214 40215 var wrapper, canvas; 40216 40217 if (redraw) { 40218 wrapper = node; 40219 canvas = node.firstChild; 40220 } 40221 else { 40222 wrapper = fabric.document.createElement('span'); 40223 wrapper.className = 'cufon cufon-canvas'; 40224 wrapper.alt = text; 40225 40226 canvas = fabric.document.createElement('canvas'); 40227 wrapper.appendChild(canvas); 40228 40229 if (options.printable) { 40230 var print = fabric.document.createElement('span'); 40231 print.className = 'cufon-alt'; 40232 print.appendChild(fabric.document.createTextNode(text)); 40233 wrapper.appendChild(print); 40234 } 40235 } 40236 40237 var wStyle = wrapper.style; 40238 var cStyle = canvas.style || { }; 40239 40240 var height = size.convert(viewBox.height - expandTop + expandBottom);
40241 var roundedHeight = Math.ceil(height); 40242 var roundingFactor = roundedHeight / height; 40243 40244 canvas.width = Math.ceil(size.convert(width + expandRight - expandLeft) * roundingFactor); 40245 canvas.height = roundedHeight; 40246 40247 expandTop += viewBox.minY; 40248 40249 cStyle.top = Math.round(size.convert(expandTop - font.ascent)) + 'px'; 40250 cStyle.left = Math.round(size.convert(expandLeft)) + 'px'; 40251 40252 var _width = Math.ceil(size.convert(width * roundingFactor)); 40253 var wrapperWidth = _width + 'px'; 40254 var _height = size.convert(font.height); 40255 var totalLineHeight = (options.lineHeight - 1) * size.convert(-font.ascent / 5) * (lines - 1); 40256 40257 Cufon.textOptions.width = _width; 40258 Cufon.textOptions.height = (_height * lines) + totalLineHeight; 40259 Cufon.textOptions.lines = lines; 40260 Cufon.textOptions.totalLineHeight = totalLineHeight; 40261 40262 if (HAS_INLINE_BLOCK) { 40263 wStyle.width = wrapperWidth; 40264 wStyle.height = _height + 'px'; 40265 } 40266 else { 40267 wStyle.paddingLeft = wrapperWidth; 40268 wStyle.paddingBottom = (_height - 1) + 'px'; 40269 } 40270 40271 var g = Cufon.textOptions.context || canvas.getContext('2d'), 40272 scale = roundedHeight / viewBox.height; 40273 40274 Cufon.textOptions.fontAscent = font.ascent * scale; 40275 Cufon.textOptions.boundaries = null; 40276 40277 for (var offsets = Cufon.textOptions.shadowOffsets, i = shadowOffsets.length; i--; ) { 40278 offsets[i] = [ shadowOffsets[i][0] * scale, shadowOffsets[i][1] * scale ]; 40279 } 40280 40281 g.save(); 40282 g.scale(scale, scale); 40283 40284 g.translate( 40285 // we're at the center of an object and need to jump to the top left corner 40286 // where first character is to be drawn 40287 -expandLeft - ((1/scale * canvas.width) / 2) + (Cufon.fonts[font.family].offsetLeft || 0), 40288 -expandTop - ((Cufon.textOptions.height / scale) / 2) + (Cufon.fonts[font.family].offsetTop || 0) 40289 ); 40290 40291 g.lineWidth = font.face['underline-thickness']; 40292 40293 g.save(); 40294 40295 function line(y, color) { 40296 g.strokeStyle = color; 40297 40298 g.beginPath(); 40299 40300 g.moveTo(0, y); 40301 g.lineTo(width, y); 40302 40303 g.stroke(); 40304 } 40305 40306 var textDecoration = Cufon.getTextDecoration(options), 40307 isItalic = options.fontStyle === 'italic'; 40308 40309 function renderBackground() { 40310 g.save(); 40311 40312 var left = 0, lineNum = 0, boundaries = [{ left: 0 }]; 40313 40314 if (options.backgroundColor) { 40315 g.save(); 40316 g.fillStyle = options.backgroundColor; 40317 g.translate(0, font.ascent); 40318 g.fillRect(0, 0, width + 10, (-font.ascent + font.descent) * lines); 40319 g.restore(); 40320 } 40321 40322 if (options.textAlign === 'right') { 40323 g.translate(lineOffsets[lineNum], 0); 40324 boundaries[0].left = lineOffsets[lineNum] * scale; 40325 } 40326 else if (options.textAlign === 'center') { 40327 g.translate(lineOffsets[lineNum] / 2, 0); 40328 boundaries[0].left = lineOffsets[lineNum] / 2 * scale; 40329 } 40330 40331 for (var i = 0, l = chars.length; i < l; ++i) { 40332 if (chars[i] === '\n') { 40333 40334 lineNum++; 40335 40336 var topOffset = -font.ascent - ((font.ascent / 5) * options.lineHeight); 40337 var boundary = boundaries[boundaries.length - 1]; 40338 var nextBoundary = { left: 0 }; 40339 40340 boundary.width = left * scale; 40341 boundary.height = (-font.ascent + font.descent) * scale; 40342 40343 if (options.textAlign === 'right') { 40344 g.translate(-width, topOffset); 40345 g.translate(lineOffsets[lineNum], 0); 40346 nextBoundary.left = lineOffsets[lineNum] * scale; 40347 } 40348 else if (options.textAlign === 'center') { 40349 // offset to the start of text in previous line AND half of its offset 40350 // (essentially moving caret to the left edge of bounding box) 40351 g.translate(-left - (lineOffsets[lineNum - 1] / 2), topOffset); 40352 g.translate(lineOffsets[lineNum] / 2, 0); 40353 nextBoundary.left = lineOffsets[lineNum] / 2 * scale; 40354 } 40355 else { 40356 g.translate(-left, topOffset); 40357 } 40358 40359 /* push next boundary (for the next line) */ 40360 boundaries.push(nextBoundary); 40361 40362 left = 0; 40363 40364 continue; 40365 } 40366 var glyph = font.glyphs[chars[i]] || font.missingGlyph; 40367 if (!glyph) continue; 40368 40369 var charWidth = Number(glyph.w || font.w) + letterSpacing; 40370 40371 // only draw text-background when there's some kind of value
40372 if (options.textBackgroundColor) { 40373 g.save(); 40374 g.fillStyle = options.textBackgroundColor; 40375 g.translate(0, font.ascent); 40376 g.fillRect(0, 0, charWidth + 10, -font.ascent + font.descent); 40377 g.restore(); 40378 } 40379 40380 g.translate(charWidth, 0); 40381 left += charWidth; 40382 40383 if (i == l-1) { 40384 boundaries[boundaries.length - 1].width = left * scale; 40385 boundaries[boundaries.length - 1].height = (-font.ascent + font.descent) * scale; 40386 } 40387 } 40388 g.restore(); 40389 40390 Cufon.textOptions.boundaries = boundaries; 40391 } 40392 40393 function renderText(color) { 40394 g.fillStyle = color || Cufon.textOptions.color || style.get('color'); 40395 40396 var left = 0, lineNum = 0; 40397 40398 if (options.textAlign === 'right') { 40399 g.translate(lineOffsets[lineNum], 0); 40400 } 40401 else if (options.textAlign === 'center') { 40402 g.translate(lineOffsets[lineNum] / 2, 0); 40403 } 40404 40405 for (var i = 0, l = chars.length; i < l; ++i) { 40406 if (chars[i] === '\n') { 40407 40408 lineNum++; 40409 40410 var topOffset = -font.ascent - ((font.ascent / 5) * options.lineHeight); 40411 40412 if (options.textAlign === 'right') { 40413 g.translate(-width, topOffset); 40414 g.translate(lineOffsets[lineNum], 0); 40415 } 40416 else if (options.textAlign === 'center') { 40417 // offset to the start of text in previous line AND half of its offset 40418 // (essentially moving caret to the left edge of bounding box) 40419 g.translate(-left - (lineOffsets[lineNum - 1] / 2), topOffset); 40420 g.translate(lineOffsets[lineNum] / 2, 0); 40421 } 40422 else { 40423 g.translate(-left, topOffset); 40424 } 40425 40426 left = 0; 40427 40428 continue; 40429 } 40430 var glyph = font.glyphs[chars[i]] || font.missingGlyph; 40431 if (!glyph) continue; 40432 40433 var charWidth = Number(glyph.w || font.w) + letterSpacing; 40434 40435 if (textDecoration) { 40436 g.save(); 40437 g.strokeStyle = g.fillStyle; 40438 40439 // add 2x more thickness â closer to SVG rendering 40440 g.lineWidth += g.lineWidth; 40441 40442 g.beginPath(); 40443 if (textDecoration.underline) { 40444 g.moveTo(0, -font.face['underline-position'] + 0.5); 40445 g.lineTo(charWidth, -font.face['underline-position'] + 0.5); 40446 } 40447 if (textDecoration.overline) { 40448 g.moveTo(0, font.ascent + 0.5); 40449 g.lineTo(charWidth, font.ascent + 0.5); 40450 } 40451 if (textDecoration['line-through']) { 40452 g.moveTo(0, -font.descent + 0.5); 40453 g.lineTo(charWidth, -font.descent + 0.5); 40454 } 40455 g.stroke(); 40456 g.restore(); 40457 } 40458 40459 if (isItalic) { 40460 g.save(); 40461 g.transform(1, 0, -0.25, 1, 0, 0); 40462 } 40463 40464 g.beginPath(); 40465 if (glyph.d) { 40466 if (glyph.code) interpret(glyph.code, g); 40467 else glyph.code = generateFromVML('m' + glyph.d, g); 40468 } 40469 40470 g.fill(); 40471 40472 if (options.strokeStyle) { 40473 g.closePath(); 40474 g.save(); 40475 g.lineWidth = options.strokeWidth; 40476 g.strokeStyle = options.strokeStyle; 40477 g.stroke(); 40478 g.restore(); 40479 } 40480 40481 if (isItalic) { 40482 g.restore(); 40483 } 40484 40485 g.translate(charWidth, 0); 40486 left += charWidth; 40487 } 40488 } 40489 40490 g.save(); 40491 renderBackground(); 40492 if (shadows) { 40493 for (var i = 0, l = shadows.length; i < l; ++i) { 40494 var shadow = shadows[i]; 40495 g.save(); 40496 g.translate.apply(g, shadowOffsets[i]); 40497 renderText(shadow.color); 40498 g.restore(); 40499 } 40500 } 40501 renderText(); 40502 g.restore(); 40503 g.restore(); 40504 g.restore(); 40505 40506 return wrapper; 40507 40508 }; 40509 40510})()); 40511 40512Cufon.registerEngine('vml', (function() { 40513 40514 if (!fabric.document.namespaces) return; 40515 40516 var canvasEl = fabric.document.createElement('canvas'); 40517 if (canvasEl && canvasEl.getContext && canvasEl.getContext.apply) return; 40518 40519 if (fabric.document.namespaces.cvml == null) { 40520 fabric.document.namespaces.add('cvml', 'urn:schemas-microsoft-com:vml'); 40521 } 40522 40523 var check = fabric.document.createElement('cvml:shape'); 40524 check.style.behavior = 'url(#default#VML)'; 40525 if (!check.coordsize) return; // VML isn't supported 40526 check = null; 40527
40528 fabric.document.write('<style type="text/css">' + 40529 '.cufon-vml-canvas{text-indent:0}' + 40530 '@media screen{' + 40531 'cvml\\:shape,cvml\\:shadow{behavior:url(#default#VML);display:block;antialias:true;position:absolute}' + 40532 '.cufon-vml-canvas{position:absolute;text-align:left}' + 40533 '.cufon-vml{display:inline-block;position:relative;vertical-align:middle}' + 40534 '.cufon-vml .cufon-alt{position:absolute;left:-10000in;font-size:1px}' + 40535 'a .cufon-vml{cursor:pointer}' + 40536 '}' + 40537 '@media print{' + 40538 '.cufon-vml *{display:none}' + 40539 '.cufon-vml .cufon-alt{display:inline}' + 40540 '}' + 40541 '</style>'); 40542 40543 function getFontSizeInPixels(el, value) { 40544 return getSizeInPixels(el, /(?:em|ex|%)$/i.test(value) ? '1em' : value); 40545 } 40546 40547 // Original by Dead Edwards. 40548 // Combined with getFontSizeInPixels it also works with relative units. 40549 function getSizeInPixels(el, value) { 40550 if (/px$/i.test(value)) return parseFloat(value); 40551 var style = el.style.left, runtimeStyle = el.runtimeStyle.left; 40552 el.runtimeStyle.left = el.currentStyle.left; 40553 el.style.left = value; 40554 var result = el.style.pixelLeft; 40555 el.style.left = style; 40556 el.runtimeStyle.left = runtimeStyle; 40557 return result; 40558 } 40559 40560 return function(font, text, style, options, node, el, hasNext) { 40561 var redraw = (text === null); 40562 40563 if (redraw) text = node.alt; 40564 40565 // @todo word-spacing, text-decoration 40566 40567 var viewBox = font.viewBox; 40568 40569 var size = style.computedFontSize || 40570 (style.computedFontSize = new Cufon.CSS.Size(getFontSizeInPixels(el, style.get('fontSize')) + 'px', font.baseSize)); 40571 40572 var letterSpacing = style.computedLSpacing; 40573 40574 if (letterSpacing == undefined) { 40575 letterSpacing = style.get('letterSpacing'); 40576 style.computedLSpacing = letterSpacing = 40577 (letterSpacing == 'normal') ? 0 : ~~size.convertFrom(getSizeInPixels(el, letterSpacing)); 40578 } 40579 40580 var wrapper, canvas; 40581 40582 if (redraw) { 40583 wrapper = node; 40584 canvas = node.firstChild; 40585 } 40586 else { 40587 wrapper = fabric.document.createElement('span'); 40588 wrapper.className = 'cufon cufon-vml'; 40589 wrapper.alt = text; 40590 40591 canvas = fabric.document.createElement('span'); 40592 canvas.className = 'cufon-vml-canvas'; 40593 wrapper.appendChild(canvas); 40594 40595 if (options.printable) { 40596 var print = fabric.document.createElement('span'); 40597 print.className = 'cufon-alt'; 40598 print.appendChild(fabric.document.createTextNode(text)); 40599 wrapper.appendChild(print); 40600 } 40601 40602 // ie6, for some reason, has trouble rendering the last VML element in the document. 40603 // we can work around this by injecting a dummy element where needed. 40604 // @todo find a better solution 40605 if (!hasNext) wrapper.appendChild(fabric.document.createElement('cvml:shape')); 40606 } 40607 40608 var wStyle = wrapper.style; 40609 var cStyle = canvas.style; 40610 40611 var height = size.convert(viewBox.height), roundedHeight = Math.ceil(height); 40612 var roundingFactor = roundedHeight / height; 40613 var minX = viewBox.minX, minY = viewBox.minY; 40614 40615 cStyle.height = roundedHeight; 40616 cStyle.top = Math.round(size.convert(minY - font.ascent)); 40617 cStyle.left = Math.round(size.convert(minX)); 40618 40619 wStyle.height = size.convert(font.height) + 'px'; 40620 40621 var textDecoration = Cufon.getTextDecoration(options); 40622 40623 var color = style.get('color'); 40624 40625 var chars = Cufon.CSS.textTransform(text, style).split(''); 40626 40627 var width = 0, offsetX = 0, advance = null; 40628 40629 var glyph, shape, shadows = options.textShadow; 40630 40631 // pre-calculate width 40632 for (var i = 0, k = 0, l = chars.length; i < l; ++i) { 40633 glyph = font.glyphs[chars[i]] || font.missingGlyph; 40634 if (glyph) width += advance = ~~(glyph.w || font.w) + letterSpacing; 40635 } 40636 40637 if (advance === null) return null; 40638 40639 var fullWidth = -minX + width + (viewBox.width - advance); 40640 40641 var shapeWidth = size.convert(fullWidth * roundingFactor), roundedShapeWidth = Math.round(shapeWidth); 40642 40643 var coordSize = fullWidth + ',' + viewBox.height, coordOrigin; 40644 var stretch = 'r' + coordSize + 'nsnf'; 40645 40646 for (i = 0; i < l; ++i) { 40647 40648 glyph = font.glyphs[chars[i]] || font.missingGlyph; 40649 if (!glyph) continue; 40650 40651 if (redraw) { 40652 // some glyphs may be missing so we can't use i 40653 shape = canvas.childNodes[k]; 40654 if (shape.firstChild) shape.removeChild(shape.firstChild); // shadow 40655 } 40656 else { 40657 shape = fabric.document.createElement('cvml:shape'); 40658 canvas.appendChild(shape); 40659 } 40660 40661 shape.stroked = 'f'; 40662 shape.coordsize = coordSize; 40663 shape.coordorigin = coordOrigin = (minX - offsetX) + ',' + minY; 40664 shape.path = (glyph.d ? 'm' + glyph.d + 'xe' : '') + 'm' + co
40664ordOrigin + stretch; 40665 shape.fillcolor = color; 40666 40667 // it's important to not set top/left or IE8 will grind to a halt 40668 var sStyle = shape.style; 40669 sStyle.width = roundedShapeWidth; 40670 sStyle.height = roundedHeight; 40671 40672 if (shadows) { 40673 // due to the limitations of the VML shadow element there 40674 // can only be two visible shadows. opacity is shared 40675 // for all shadows. 40676 var shadow1 = shadows[0], shadow2 = shadows[1]; 40677 var color1 = Cufon.CSS.color(shadow1.color), color2; 40678 var shadow = fabric.document.createElement('cvml:shadow'); 40679 shadow.on = 't'; 40680 shadow.color = color1.color; 40681 shadow.offset = shadow1.offX + ',' + shadow1.offY; 40682 if (shadow2) { 40683 color2 = Cufon.CSS.color(shadow2.color); 40684 shadow.type = 'double'; 40685 shadow.color2 = color2.color; 40686 shadow.offset2 = shadow2.offX + ',' + shadow2.offY; 40687 } 40688 shadow.opacity = color1.opacity || (color2 && color2.opacity) || 1; 40689 shape.appendChild(shadow); 40690 } 40691 40692 offsetX += ~~(glyph.w || font.w) + letterSpacing; 40693 40694 ++k; 40695 40696 } 40697 40698 wStyle.width = Math.max(Math.ceil(size.convert(width * roundingFactor)), 0); 40699 40700 return wrapper; 40701 40702 }; 40703 40704})()); 40705 40706Cufon.getTextDecoration = function(options) { 40707 return { 40708 underline: options.textDecoration === 'underline', 40709 overline: options.textDecoration === 'overline', 40710 'line-through': options.textDecoration === 'line-through' 40711 }; 40712}; 40713 40714if (typeof exports != 'undefined') { 40715 exports.Cufon = Cufon; 40716} 40717 40718 40719/* 40720 json2.js 40721 2011-10-19 40722 40723 Public Domain. 40724 40725 NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. 40726 40727 See http://www.JSON.org/js.html 40728 40729 40730 This code should be minified before deployment. 40731 See http://javascript.crockford.com/jsmin.html 40732 40733 USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO 40734 NOT CONTROL. 40735 40736 40737 This file creates a global JSON object containing two methods: stringify 40738 and parse. 40739 40740 JSON.stringify(value, replacer, space) 40741 value any JavaScript value, usually an object or array. 40742 40743 replacer an optional parameter that determines how object 40744 values are stringified for objects. It can be a 40745 function or an array of strings. 40746 40747 space an optional parameter that specifies the indentation 40748 of nested structures. If it is omitted, the text will 40749 be packed without extra whitespace. If it is a number, 40750 it will specify the number of spaces to indent at each 40751 level. If it is a string (such as '\t' or ' '), 40752 it contains the characters used to indent at each level. 40753 40754 This method produces a JSON text from a JavaScript value. 40755 40756 When an object value is found, if the object contains a toJSON 40757 method, its toJSON method will be called and the result will be 40758 stringified. A toJSON method does not serialize: it returns the 40759 value represented by the name/value pair that should be serialized, 40760 or undefined if nothing should be serialized. The toJSON method 40761 will be passed the key associated with the value, and this will be 40762 bound to the value 40763 40764 For example, this would serialize Dates as ISO strings. 40765 40766 Date.prototype.toJSON = function (key) { 40767 function f(n) { 40768 // Format integers to have at least two digits. 40769 return n < 10 ? '0' + n : n; 40770 } 40771 40772 return this.getUTCFullYear() + '-' + 40773 f(this.getUTCMonth() + 1) + '-' + 40774 f(this.getUTCDate()) + 'T' + 40775 f(this.getUTCHours()) + ':' + 40776 f(this.getUTCMinutes()) + ':' + 40777 f(this.getUTCSeconds()) + 'Z'; 40778 }; 40779 40780 You can provide an optional replacer method. It will be passed the 40781 key and value of each member, with this bound to the containing 40782 object. The value that is returned from your method will be 40783 serialized. If your method returns undefined, then the member will 40784 be excluded from the serialization. 40785
40786 If the replacer parameter is an array of strings, then it will be 40787 used to select the members to be serialized. It filters the results 40788 such that only members with keys listed in the replacer array are 40789 stringified. 40790 40791 Values that do not have JSON representations, such as undefined or 40792 functions, will not be serialized. Such values in objects will be 40793 dropped; in arrays they will be replaced with null. You can use 40794 a replacer function to replace those with JSON values. 40795 JSON.stringify(undefined) returns undefined. 40796 40797 The optional space parameter produces a stringification of the 40798 value that is filled with line breaks and indentation to make it 40799 easier to read. 40800 40801 If the space parameter is a non-empty string, then that string will 40802 be used for indentation. If the space parameter is a number, then 40803 the indentation will be that many spaces. 40804 40805 Example: 40806 40807 text = JSON.stringify(['e', {pluribus: 'unum'}]); 40808 // text is '["e",{"pluribus":"unum"}]' 40809 40810 40811 text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t'); 40812 // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]' 40813 40814 text = JSON.stringify([new Date()], function (key, value) { 40815 return this[key] instanceof Date ? 40816 'Date(' + this[key] + ')' : value; 40817 }); 40818 // text is '["Date(---current time---)"]' 40819 40820 40821 JSON.parse(text, reviver) 40822 This method parses a JSON text to produce an object or array. 40823 It can throw a SyntaxError exception. 40824 40825 The optional reviver parameter is a function that can filter and 40826 transform the results. It receives each of the keys and values, 40827 and its return value is used instead of the original value. 40828 If it returns what it received, then the structure is not modified. 40829 If it returns undefined then the member is deleted. 40830 40831 Example: 40832 40833 // Parse the text. Values that look like ISO date strings will 40834 // be converted to Date objects. 40835 40836 myData = JSON.parse(text, function (key, value) { 40837 var a; 40838 if (typeof value === 'string') { 40839 a = 40840/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value); 40841 if (a) { 40842 return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4], 40843 +a[5], +a[6])); 40844 } 40845 } 40846 return value; 40847 }); 40848 40849 myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) { 40850 var d; 40851 if (typeof value === 'string' && 40852 value.slice(0, 5) === 'Date(' && 40853 value.slice(-1) === ')') { 40854 d = new Date(value.slice(5, -1)); 40855 if (d) { 40856 return d; 40857 } 40858 } 40859 return value; 40860 }); 40861 40862 40863 This is a reference implementation. You are free to copy, modify, or 40864 redistribute. 40865*/ 40866 40867/*jslint evil: true, regexp: true */ 40868 40869/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply, 40870 call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours, 40871 getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join, 40872 lastIndex, length, parse, prototype, push, replace, slice, stringify, 40873 test, toJSON, toString, valueOf 40874*/ 40875 40876 40877// Create a JSON object only if one does not already exist. We create the 40878// methods in a closure to avoid creating global variables. 40879 40880var JSON; 40881if (!JSON) { 40882 JSON = {}; 40883} 40884 40885(function () { 40886 'use strict'; 40887 40888 function f(n) { 40889 // Format integers to have at least two digits. 40890 return n < 10 ? '0' + n : n; 40891 } 40892 40893 if (typeof Date.prototype.toJSON !== 'function') { 40894 40895 /** @ignore */ 40896 Date.prototype.toJSON = function (key) { 40897 40898 return isFinite(this.valueOf()) 40899 ? this.getUTCFullYear() + '-' + 40900 f(this.getUTCMonth() + 1) + '-' + 40901 f(this.getUTCDate()) + 'T' + 40902 f(this.getUTCHours()) + ':' + 40903 f(this.getUTCMinutes()) + ':' + 40904 f(this.getUTCSeconds()) + 'Z' 40905 : null; 40906 }; 40907 40908 String.prototype.toJSON = 40909 Number.prototype.toJSON = 40910 /** @ignore */ 40911 Boolean.prototype.toJSON = function (key) { 40912 return this.valueOf(); 40913 }; 40914 } 40915 40916 var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, 40917 escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, 40918 gap, 40919 indent, 40920 meta = { // table of character substitutions 40921 '\b': '\\b', 40922 '\t': '\\t', 40923 '\n': '\\n', 40924 '\f': '\\f', 40925 '\r': '\\r', 40926 '"' : '\\"', 40927 '\\': '\\\\' 40928 }, 40929 rep; 40930 40931 40932 function quote(string) { 40933
vendor: 9,025 bytes, lines 40934-41193
40934// If the string contains no control characters, no quote characters, and no 40935// backslash characters, then we can safely slap some quotes around it. 40936// Otherwise we must also replace the offending characters with safe escape 40937// sequences. 40938 40939 escapable.lastIndex = 0; 40940 return escapable.test(string) ? '"' + string.replace(escapable, function (a) { 40941 var c = meta[a]; 40942 return typeof c === 'string' 40943 ? c 40944 : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); 40945 }) + '"' : '"' + string + '"'; 40946 } 40947 40948 40949 function str(key, holder) { 40950 40951// Produce a string from holder[key]. 40952 40953 var i, // The loop counter. 40954 k, // The member key. 40955 v, // The member value. 40956 length, 40957 mind = gap, 40958 partial, 40959 value = holder[key]; 40960 40961// If the value has a toJSON method, call it to obtain a replacement value. 40962 40963 if (value && typeof value === 'object' && 40964 typeof value.toJSON === 'function') { 40965 value = value.toJSON(key); 40966 } 40967 40968// If we were called with a replacer function, then call the replacer to 40969// obtain a replacement value. 40970 40971 if (typeof rep === 'function') { 40972 value = rep.call(holder, key, value); 40973 } 40974 40975// What happens next depends on the value's type. 40976 40977 switch (typeof value) { 40978 case 'string': 40979 return quote(value); 40980 40981 case 'number': 40982 40983// JSON numbers must be finite. Encode non-finite numbers as null. 40984 40985 return isFinite(value) ? String(value) : 'null'; 40986 40987 case 'boolean': 40988 case 'null': 40989 40990// If the value is a boolean or null, convert it to a string. Note: 40991// typeof null does not produce 'null'. The case is included here in 40992// the remote chance that this gets fixed someday. 40993 40994 return String(value); 40995 40996// If the type is 'object', we might be dealing with an object or an array or 40997// null. 40998 40999 case 'object': 41000 41001// Due to a specification blunder in ECMAScript, typeof null is 'object', 41002// so watch out for that case. 41003 41004 if (!value) { 41005 return 'null'; 41006 } 41007 41008// Make an array to hold the partial results of stringifying this object value. 41009 41010 gap += indent; 41011 partial = []; 41012 41013// Is the value an array? 41014 41015 if (Object.prototype.toString.apply(value) === '[object Array]') { 41016 41017// The value is an array. Stringify every element. Use null as a placeholder 41018// for non-JSON values. 41019 41020 length = value.length; 41021 for (i = 0; i < length; i += 1) { 41022 partial[i] = str(i, value) || 'null'; 41023 } 41024 41025// Join all of the elements together, separated with commas, and wrap them in 41026// brackets. 41027 41028 v = partial.length === 0 41029 ? '[]' 41030 : gap 41031 ? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' 41032 : '[' + partial.join(',') + ']'; 41033 gap = mind; 41034 return v; 41035 } 41036 41037// If the replacer is an array, use it to select the members to be stringified. 41038 41039 if (rep && typeof rep === 'object') { 41040 length = rep.length; 41041 for (i = 0; i < length; i += 1) { 41042 if (typeof rep[i] === 'string') { 41043 k = rep[i]; 41044 v = str(k, value); 41045 if (v) { 41046 partial.push(quote(k) + (gap ? ': ' : ':') + v); 41047 } 41048 } 41049 } 41050 } else { 41051 41052// Otherwise, iterate through all of the keys in the object. 41053 41054 for (k in value) { 41055 if (Object.prototype.hasOwnProperty.call(value, k)) { 41056 v = str(k, value); 41057 if (v) { 41058 partial.push(quote(k) + (gap ? ': ' : ':') + v); 41059 } 41060 } 41061 } 41062 } 41063 41064// Join all of the member texts together, separated with commas, 41065// and wrap them in braces. 41066 41067 v = partial.length === 0 41068 ? '{}' 41069 : gap 41070 ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' 41071 : '{' + partial.join(',') + '}'; 41072 gap = mind; 41073 return v; 41074 } 41075 } 41076 41077// If the JSON object does not yet have a stringify method, give it one. 41078 41079 if (typeof JSON.stringify !== 'function') { 41080 /** @ignore */ 41081 JSON.stringify = function (value, replacer, space) { 41082 41083// The stringify method takes a value and an optional replacer, and an optional 41084// space parameter, and returns a JSON text. The replacer can be a function 41085// that can replace values, or an array of strings that will select the keys. 41086// A default replacer method can be provided. Use of the space parameter can 41087// produce text that is more easily readable. 41088 41089 var i; 41090 gap = ''; 41091 indent = ''; 41092 41093// If the space parameter is a number, make an indent string containing that 41094// many spaces. 41095 41096 if (typeof space === 'number') { 41097 for (i = 0; i < space; i += 1) { 41098 indent += ' '; 41099 } 41100 41101// If the space parameter is a string, it will be used as the indent string. 41102 41103 } else if (typeof space === 'string') { 41104 indent = space; 41105 } 41106 41107// If there is a replacer, it must be a function or an array. 41108// Otherwise, throw an error. 41109 41110 rep = replacer; 41111 if (replacer && typeof replacer !== 'function' && 41112 (typeof replacer !== 'object' || 41113 typeof replacer.length !== 'number')) { 41114 throw new Error('JSON.stringify'); 41115 } 41116 41117// Make a fake root object containing our value under the key of ''. 41118// Return the result of stringifying the value. 41119 41120 return str('', {'': value}); 41121 }; 41122 } 41123 41124 41125// If the JSON object does not yet have a parse method, give it one. 41126 41127 if (typeof JSON.parse !== 'function') { 41128 /** @ignore */ 41129 JSON.parse = function (text, reviver) { 41130 41131// The parse method takes a text and an optional reviver function, and returns 41132// a JavaScript value if the text is a valid JSON text. 41133 41134 var j; 41135 41136 function walk(holder, key) { 41137 41138// The walk method is used to recursively walk the resulting structure so 41139// that modifications can be made. 41140 41141 var k, v, value = holder[key]; 41142 if (value && typeof value === 'object') { 41143 for (k in value) { 41144 if (Object.prototype.hasOwnProperty.call(value, k)) { 41145 v = walk(value, k); 41146 if (v !== undefined) { 41147 value[k] = v; 41148 } else { 41149 delete value[k]; 41150 } 41151 } 41152 } 41153 } 41154 return reviver.call(holder, key, value); 41155 } 41156 41157 41158// Parsing happens in four stages. In the first stage, we replace certain 41159// Unicode characters with escape sequences. JavaScript handles many characters 41160// incorrectly, either silently deleting them, or treating them as line endings. 41161 41162 text = String(text); 41163 cx.lastIndex = 0; 41164 if (cx.test(text)) { 41165 text = text.replace(cx, function (a) { 41166 return '\\u' + 41167 ('0000' + a.charCodeAt(0).toString(16)).slice(-4); 41168 }); 41169 } 41170 41171// In the second stage, we run the text against regular expressions that look 41172// for non-JSON patterns. We are especially concerned with '()' and 'new' 41173// because they can cause invocation, and '=' because it can cause mutation. 41174// But just to be safe, we want to reject all unexpected forms. 41175 41176// We split the second stage into 4 regexp operations in order to work around 41177// crippling inefficiencies in IE's and Safari's regexp engines. First we 41178// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we 41179// replace all simple value tokens with ']' characters. Third, we delete all 41180// open brackets that follow a colon or comma or that begin the text. Finally, 41181// we look to see that the remaining characters are only whitespace or ']' or 41182// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval. 41183 41184 if (/^[\],:{}\s]*$/ 41185 .test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@') 41186 .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']') 41187 .replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) { 41188 41189// In the third stage we use the eval function to compile the text into a 41190// JavaScript structure. The '{' operator is subject to a syntactic ambiguity 41191// in JavaScript: it can begin a block or an object literal. We wrap the text 41192// in parens to eliminate the ambiguity. 41193
41194 j = eval('(' + text + ')'); 41195 41196// In the optional fourth stage, we recursively walk the new structure, passing 41197// each name/value pair to a reviver function for possible transformation. 41198 41199 return typeof reviver === 'function' 41200 ? walk({'': j}, '') 41201 : j; 41202 } 41203 41204// If the text is not JSON parseable, then a SyntaxError is thrown. 41205 41206 throw new SyntaxError('JSON.parse'); 41207 }; 41208 } 41209}()); 41210 41211/** 41212 * Wrapper around `console.log` (when available) 41213 * @param {Any} values Values to log 41214 */ 41215fabric.log = function() { }; 41216 41217/** 41218 * Wrapper around `console.warn` (when available) 41219 * @param {Any} Values to log as a warning 41220 */ 41221fabric.warn = function() { }; 41222 41223if (typeof console !== 'undefined') { 41224 if (typeof console.log !== 'undefined' && console.log.apply) { 41225 fabric.log = function() { 41226 return console.log.apply(console, arguments); 41227 }; 41228 } 41229 if (typeof console.warn !== 'undefined' && console.warn.apply) { 41230 fabric.warn = function() { 41231 return console.warn.apply(console, arguments); 41232 }; 41233 } 41234} 41235 41236 41237(function(){ 41238 41239 /** 41240 * @private 41241 * @param {String} eventName 41242 * @param {Function} handler 41243 */ 41244 function _removeEventListener(eventName, handler) { 41245 if (!this.__eventListeners[eventName]) return; 41246 41247 if (handler) { 41248 fabric.util.removeFromArray(this.__eventListeners[eventName], handler); 41249 } 41250 else { 41251 this.__eventListeners[eventName].length = 0; 41252 } 41253 } 41254 41255 /** 41256 * Observes specified event 41257 * @deprecated `observe` deprecated since 0.8.34 (use `on` instead) 41258 * @memberOf fabric.Observable 41259 * @alias on 41260 * @param {String|Object} eventName Event name (eg. 'after:render') or object with key/value pairs (eg. {'after:render': handler, 'selection:cleared': handler}) 41261 * @param {Function} handler Function that receives a notification when an event of the specified type occurs 41262 * @return {Self} thisArg 41263 * @chainable 41264 */ 41265 function observe(eventName, handler) { 41266 if (!this.__eventListeners) { 41267 this.__eventListeners = { }; 41268 } 41269 // one object with key/value pairs was passed 41270 if (arguments.length === 1) { 41271 for (var prop in eventName) { 41272 this.on(prop, eventName[prop]); 41273 } 41274 } 41275 else { 41276 if (!this.__eventListeners[eventName]) { 41277 this.__eventListeners[eventName] = [ ]; 41278 } 41279 this.__eventListeners[eventName].push(handler); 41280 } 41281 return this; 41282 } 41283 41284 /** 41285 * Stops event observing for a particular event handler 41286 * @deprecated `stopObserving` deprecated since 0.8.34 (use `off` instead) 41287 * @memberOf fabric.Observable 41288 * @alias off 41289 * @param {String|Object} eventName Event name (eg. 'after:render') or object with key/value pairs (eg. {'after:render': handler, 'selection:cleared': handler}) 41290 * @param {Function} handler Function to be deleted from EventListeners 41291 * @return {Self} thisArg 41292 * @chainable 41293 */ 41294 function stopObserving(eventName, handler) { 41295 if (!this.__eventListeners) return; 41296 41297 // one object with key/value pairs was passed 41298 if (arguments.length === 1 && typeof arguments[0] === 'object') { 41299 for (var prop in eventName) { 41300 _removeEventListener.call(this, prop, eventName[prop]); 41301 } 41302 } 41303 else { 41304 _removeEventListener.call(this, eventName, handler); 41305 } 41306 return this; 41307 } 41308 41309 /** 41310 * Fires event with an optional options object 41311 * @deprecated `fire` deprecated since 1.0.7 (use `trigger` instead) 41312 * @memberOf fabric.Observable 41313 * @alias trigger 41314 * @param {String} eventName Event name to fire 41315 * @param {Object} [options] Options object 41316 * @return {Self} thisArg 41317 * @chainable 41318 */ 41319 function fire(eventName, options) { 41320 if (!this.__eventListeners) return; 41321 41322 var listenersForEvent = this.__eventListeners[eventName]; 41323 if (!listenersForEvent) return; 41324 for (var i = 0, len = listenersForEvent.length; i < len; i++) { 41325 // avoiding try/catch for perf. reasons 41326 listenersForEvent[i].call(this, options || { }); 41327 } 41328 return this; 41329 } 41330 41331 /** 41332 * @namespace fabric.Observable 41333 * @tutorial {@link http://fabricjs.com/fabric-intro-part-2/#events} 41334 * @see {@link http://fabricjs.com/events/|Events demo} 41335 */ 41336 fabric.Observable = { 41337 observe: observe, 41338 stopObserving: stopObserving, 41339 fire: fire, 41340 41341 on: observe, 41342 off: stopObserving, 41343 trigger: fire 41344 }; 41345})(); 41346 41347 41348/** 41349 * @namespace fabric.Collection 41350 */ 41351fabric.Collection = { 41352 41353 /** 41354 * Adds objects to collection, then renders canvas (if `renderOnAddRemove` is not `false`) 41355 * Objects should be instances of (or inherit from) fabric.Object 41356 * @param [...] Zero or more fabric instances 41357 * @return {Self} thisArg 41358 */ 41359 add: function () { 41360 this._objects.push.apply(this._objects, arguments); 41361 for (var i = arguments.length; i--; ) { 41362 this._onObjectAdded(arguments[i]); 41363 } 41364 this.renderOnAddRemove && this.renderAll(); 41365 return this; 41366 }, 41367 41368 /** 41369 * Inserts an object into collection at specified index, then renders canvas (if `renderOnAddRemove` is not `false`) 41370 * An object should be an instance of (or inherit from) fabric.Object 41371 * @param {Object} object Object to insert 41372 * @param {Number} index Index to insert object at 41373 * @param {Boolean} nonSplicing When `true`, no splicing (shifting) of objects occurs 41374 * @return {Self} thisArg 41375 */ 41376 insertAt: function (object, index, nonSplicing) { 41377 var objects = this.getObjects(); 41378 if (nonSplicing) { 41379 objects[index] = object; 41380 } 41381 else { 41382 objects.splice(index, 0, object); 41383 } 41384 this._onObjectAdded(object); 41385 this.renderOnAddRemove && this.renderAll(); 41386 return this; 41387 }, 41388 41389 /** 41390 * Removes an object from a collection, then renders canvas (if `renderOnAddRemove` is not `false`) 41391 * @param {Object} object Object to remove 41392 * @return {Self} thisArg 41393 */ 41394 remove: function(object) { 41395 var objects = this.getObjects(), 41396 index = objects.indexOf(object); 41397 41398 // only call onObjectRemoved if an object was actually removed 41399 if (index !== -1) { 41400 objects.splice(index, 1); 41401 this._onObjectRemoved(object); 41402 } 41403 41404 this.renderOnAddRemove && this.renderAll(); 41405 return object; 41406 }, 41407 41408 /** 41409 * Executes given function for each object in this group 41410 * @param {Function} callback 41411 * Callback invoked with current object as first argument,
41412 * index - as second and an array of all objects - as third. 41413 * Iteration happens in reverse order (for performance reasons). 41414 * Callback is invoked in a context of Global Object (e.g. `window`) 41415 * when no `context` argument is given 41416 * 41417 * @param {Object} context Context (aka thisObject) 41418 * @return {Self} thisArg 41419 */ 41420 forEachObject: function(callback, context) { 41421 var objects = this.getObjects(), 41422 i = objects.length; 41423 while (i--) { 41424 callback.call(context, objects[i], i, objects); 41425 } 41426 return this; 41427 }, 41428 41429 /** 41430 * Returns object at specified index 41431 * @param {Number} index 41432 * @return {Self} thisArg 41433 */ 41434 item: function (index) { 41435 return this.getObjects()[index]; 41436 }, 41437 41438 /** 41439 * Returns true if collection contains no objects 41440 * @return {Boolean} true if collection is empty 41441 */ 41442 isEmpty: function () { 41443 return this.getObjects().length === 0; 41444 }, 41445 41446 /** 41447 * Returns a size of a collection (i.e: length of an array containing its objects) 41448 * @return {Number} Collection size 41449 */ 41450 size: function() { 41451 return this.getObjects().length; 41452 }, 41453 41454 /** 41455 * Returns true if collection contains an object 41456 * @param {Object} object Object to check against 41457 * @return {Boolean} `true` if collection contains an object 41458 */ 41459 contains: function(object) { 41460 return this.getObjects().indexOf(object) > -1; 41461 }, 41462 41463 /** 41464 * Returns number representation of a collection complexity 41465 * @return {Number} complexity 41466 */ 41467 complexity: function () { 41468 return this.getObjects().reduce(function (memo, current) { 41469 memo += current.complexity ? current.complexity() : 0; 41470 return memo; 41471 }, 0); 41472 } 41473}; 41474 41475 41476(function(global) { 41477 41478 var sqrt = Math.sqrt, 41479 atan2 = Math.atan2; 41480 41481 /** 41482 * @namespace fabric.util 41483 */ 41484 fabric.util = { }; 41485 41486 /** 41487 * Removes value from an array. 41488 * Presence of value (and its position in an array) is determined via `Array.prototype.indexOf` 41489 * @static 41490 * @memberOf fabric.util 41491 * @param {Array} array 41492 * @param {Any} value 41493 * @return {Array} original array 41494 */ 41495 function removeFromArray(array, value) { 41496 var idx = array.indexOf(value); 41497 if (idx !== -1) { 41498 array.splice(idx, 1); 41499 } 41500 return array; 41501 } 41502 41503 /** 41504 * Returns random number between 2 specified ones. 41505 * @static 41506 * @memberOf fabric.util 41507 * @param {Number} min lower limit 41508 * @param {Number} max upper limit 41509 * @return {Number} random value (between min and max) 41510 */ 41511 function getRandomInt(min, max) { 41512 return Math.floor(Math.random() * (max - min + 1)) + min; 41513 } 41514 41515 var PiBy180 = Math.PI / 180; 41516 41517 /** 41518 * Transforms degrees to radians. 41519 * @static 41520 * @memberOf fabric.util 41521 * @param {Number} degrees value in degrees 41522 * @return {Number} value in radians 41523 */ 41524 function degreesToRadians(degrees) { 41525 return degrees * PiBy180; 41526 } 41527 41528 /** 41529 * Transforms radians to degrees. 41530 * @static 41531 * @memberOf fabric.util 41532 * @param {Number} radians value in radians 41533 * @return {Number} value in degrees 41534 */ 41535 function radiansToDegrees(radians) { 41536 return radians / PiBy180; 41537 } 41538 41539 /** 41540 * Rotates `point` around `origin` with `radians` 41541 * @static 41542 * @memberOf fabric.util 41543 * @param {fabric.Point} The point to rotate 41544 * @param {fabric.Point} The origin of the rotation 41545 * @param {Number} The radians of the angle for the rotation 41546 * @return {fabric.Point} The new rotated point 41547 */ 41548 function rotatePoint(point, origin, radians) { 41549 var sin = Math.sin(radians), 41550 cos = Math.cos(radians); 41551 41552 point.subtractEquals(origin); 41553 41554 var rx = point.x * cos - point.y * sin; 41555 var ry = point.x * sin + point.y * cos; 41556 41557 return new fabric.Point(rx, ry).addEquals(origin); 41558 } 41559 41560 /** 41561 * A wrapper around Number#toFixed, which contrary to native method returns number, not string. 41562 * @static 41563 * @memberOf fabric.util 41564 * @param {Number | String} number number to operate on 41565 * @param {Number} fractionDigits number of fraction digits to "leave" 41566 * @return {Number} 41567 */ 41568 function toFixed(number, fractionDigits) { 41569 return parseFloat(Number(number).toFixed(fractionDigits)); 41570 } 41571 41572 /** 41573 * Function which always returns `false`. 41574 * @static 41575 * @memberOf fabric.util 41576 * @return {Boolean} 41577 */ 41578 function falseFunction() { 41579 return false;
41580 } 41581 41582 /** 41583 * Returns klass "Class" object of given namespace 41584 * @memberOf fabric.util 41585 * @param {String} type Type of object (eg. 'circle') 41586 * @param {String} namespace Namespace to get klass "Class" object from 41587 * @return {Object} klass "Class" 41588 */ 41589 function getKlass(type, namespace) { 41590 // capitalize first letter only 41591 type = fabric.util.string.camelize(type.charAt(0).toUpperCase() + type.slice(1)); 41592 return resolveNamespace(namespace)[type]; 41593 } 41594 41595 /** 41596 * Returns object of given namespace 41597 * @memberOf fabric.util 41598 * @param {String} namespace Namespace string e.g. 'fabric.Image.filter' or 'fabric' 41599 * @return {Object} Object for given namespace (default fabric) 41600 */ 41601 function resolveNamespace(namespace) { 41602 if (!namespace) return fabric; 41603 41604 var parts = namespace.split('.'), 41605 len = parts.length, 41606 obj = global || fabric.window; 41607 41608 for (var i = 0; i < len; ++i) { 41609 obj = obj[parts[i]]; 41610 } 41611 41612 return obj; 41613 } 41614 41615 /** 41616 * Loads image element from given url and passes it to a callback 41617 * @memberOf fabric.util 41618 * @param {String} url URL representing an image 41619 * @param {Function} callback Callback; invoked with loaded image 41620 * @param {Any} context optional Context to invoke callback in 41621 */ 41622 function loadImage(url, callback, context) { 41623 if (url) { 41624 var img = fabric.util.createImage(); 41625 /** @ignore */ 41626 img.onload = function () { 41627 callback && callback.call(context, img); 41628 img = img.onload = null; 41629 }; 41630 img.src = url; 41631 } 41632 else { 41633 callback && callback.call(context, url); 41634 } 41635 } 41636 41637 /** 41638 * Creates corresponding fabric instances from their object representations 41639 * @static 41640 * @memberOf fabric.util 41641 * @param {Array} objects Objects to enliven 41642 * @param {Function} callback Callback to invoke when all objects are created 41643 * @param {Function} [reviver] Method for further parsing of object elements, called after each fabric object created. 41644 */ 41645 function enlivenObjects(objects, callback, namespace, reviver) { 41646 41647 function onLoaded() { 41648 if (++numLoadedObjects === numTotalObjects) { 41649 if (callback) { 41650 callback(enlivenedObjects); 41651 } 41652 } 41653 } 41654 41655 var enlivenedObjects = [ ], 41656 numLoadedObjects = 0, 41657 numTotalObjects = objects.length; 41658 41659 objects.forEach(function (o, index) { 41660 // if sparse array 41661 if (!o || !o.type) { 41662 onLoaded(); 41663 return; 41664 } 41665 var klass = fabric.util.getKlass(o.type, namespace); 41666 if (klass.async) { 41667 klass.fromObject(o, function (obj, error) { 41668 if (!error) { 41669 enlivenedObjects[index] = obj; 41670 reviver && reviver(o, enlivenedObjects[index]); 41671 } 41672 onLoaded(); 41673 }); 41674 } 41675 else { 41676 enlivenedObjects[index] = klass.fromObject(o); 41677 reviver && reviver(o, enlivenedObjects[index]); 41678 onLoaded(); 41679 } 41680 }); 41681 } 41682 41683 /** 41684 * Groups SVG elements (usually those retrieved from SVG document) 41685 * @static 41686 * @memberOf fabric.util 41687 * @param {Array} elements SVG elements to group 41688 * @param {Object} [options] Options object 41689 * @return {fabric.Object|fabric.PathGroup} 41690 */ 41691 function groupSVGElements(elements, options, path) { 41692 var object; 41693 41694 if (elements.length > 1) { 41695 object = new fabric.PathGroup(elements, options); 41696 } 41697 else { 41698 object = elements[0]; 41699 } 41700 41701 if (typeof path !== 'undefined') { 41702 object.setSourcePath(path); 41703 } 41704 return object; 41705 } 41706 41707 /** 41708 * Populates an object with properties of another object 41709 * @static 41710 * @memberOf fabric.util 41711 * @param {Object} source Source object 41712 * @param {Object} destination Destination object 41713 * @return {Array} properties Propertie names to include 41714 */ 41715 function populateWithProperties(source, destination, properties) { 41716 if (properties && Object.prototype.toString.call(properties) === '[object Array]') { 41717 for (var i = 0, len = properties.length; i < len; i++) { 41718 if (properties[i] in source) { 41719 destination[properties[i]] = source[properties[i]]; 41720 } 41721 } 41722 } 41723 } 41724 41725 /** 41726 * Draws a dashed line between two points 41727 * 41728 * This method is used to draw dashed line around selection area.
41729 * See <a href="http://stackoverflow.com/questions/4576724/dotted-stroke-in-canvas">dotted stroke in canvas</a> 41730 * 41731 * @param ctx {Canvas} context 41732 * @param x {Number} start x coordinate 41733 * @param y {Number} start y coordinate 41734 * @param x2 {Number} end x coordinate 41735 * @param y2 {Number} end y coordinate 41736 * @param da {Array} dash array pattern 41737 */ 41738 function drawDashedLine(ctx, x, y, x2, y2, da) { 41739 var dx = x2 - x, 41740 dy = y2 - y, 41741 len = sqrt(dx*dx + dy*dy), 41742 rot = atan2(dy, dx), 41743 dc = da.length, 41744 di = 0, 41745 draw = true; 41746 41747 ctx.save(); 41748 ctx.translate(x, y); 41749 ctx.moveTo(0, 0); 41750 ctx.rotate(rot); 41751 41752 x = 0; 41753 while (len > x) { 41754 x += da[di++ % dc]; 41755 if (x > len) { 41756 x = len; 41757 } 41758 ctx[draw ? 'lineTo' : 'moveTo'](x, 0); 41759 draw = !draw; 41760 } 41761 41762 ctx.restore(); 41763 } 41764 41765 /** 41766 * Creates canvas element and initializes it via excanvas if necessary 41767 * @static 41768 * @memberOf fabric.util 41769 * @param {CanvasElement} [canvasEl] optional canvas element to initialize; when not given, element is created implicitly 41770 * @return {CanvasElement} initialized canvas element 41771 */ 41772 function createCanvasElement(canvasEl) { 41773 canvasEl || (canvasEl = fabric.document.createElement('canvas')); 41774 if (!canvasEl.getContext && typeof G_vmlCanvasManager !== 'undefined') { 41775 G_vmlCanvasManager.initElement(canvasEl); 41776 } 41777 return canvasEl; 41778 } 41779 41780 /** 41781 * Creates image element (works on client and node) 41782 * @static 41783 * @memberOf fabric.util 41784 * @return {HTMLImageElement} HTML image element 41785 */ 41786 function createImage() { 41787 return fabric.isLikelyNode 41788 ? new (require('canvas').Image)() 41789 : fabric.document.createElement('img'); 41790 } 41791 41792 /** 41793 * Creates accessors (getXXX, setXXX) for a "class", based on "stateProperties" array 41794 * @static 41795 * @memberOf fabric.util 41796 * @param {Object} klass "Class" to create accessors for 41797 */ 41798 function createAccessors(klass) { 41799 var proto = klass.prototype; 41800 41801 for (var i = proto.stateProperties.length; i--; ) { 41802 41803 var propName = proto.stateProperties[i], 41804 capitalizedPropName = propName.charAt(0).toUpperCase() + propName.slice(1), 41805 setterName = 'set' + capitalizedPropName, 41806 getterName = 'get' + capitalizedPropName; 41807 41808 // using `new Function` for better introspection 41809 if (!proto[getterName]) { 41810 proto[getterName] = (function(property) { 41811 return new Function('return this.get("' + property + '")'); 41812 })(propName); 41813 } 41814 if (!proto[setterName]) { 41815 proto[setterName] = (function(property) { 41816 return new Function('value', 'return this.set("' + property + '", value)'); 41817 })(propName); 41818 } 41819 } 41820 } 41821 41822 /** 41823 * @static 41824 * @memberOf fabric.util 41825 * @param {fabric.Object} receiver Object implementing `clipTo` method 41826 * @param {CanvasRenderingContext2D} ctx Context to clip 41827 */ 41828 function clipContext(receiver, ctx) { 41829 ctx.save(); 41830 ctx.beginPath(); 41831 receiver.clipTo(ctx); 41832 ctx.clip(); 41833 } 41834 41835 /** 41836 * Multiply matrix A by matrix B to nest transformations 41837 * @static 41838 * @memberOf fabric.util 41839 * @param {Array} matrixA First transformMatrix 41840 * @param {Array} matrixB Second transformMatrix 41841 * @return {Array} The product of the two transform matrices 41842 */ 41843 function multiplyTransformMatrices(matrixA, matrixB) { 41844 // Matrix multiply matrixA * matrixB 41845 var a = [ 41846 [matrixA[0], matrixA[2], matrixA[4]], 41847 [matrixA[1], matrixA[3], matrixA[5]], 41848 [0 , 0 , 1 ] 41849 ]; 41850 41851 var b = [ 41852 [matrixB[0], matrixB[2], matrixB[4]], 41853 [matrixB[1], matrixB[3], matrixB[5]], 41854 [0 , 0 , 1 ] 41855 ]; 41856 41857 var result = []; 41858 for (var r=0; r<3; r++) { 41859 result[r] = []; 41860 for (var c=0; c<3; c++) { 41861 var sum = 0; 41862 for (var k=0; k<3; k++) { 41863 sum += a[r][k]*b[k][c]; 41864 } 41865 41866 result[r][c] = sum; 41867 } 41868 } 41869 41870 return [ 41871 result[0][0], 41872 result[1][0], 41873 result[0][1], 41874 result[1][1], 41875 result[0][2], 41876 result[1][2] 41877 ]; 41878 } 41879 41880 function getFunctionBody(fn) { 41881 return (String(fn).match(/function[^{]*\{([\s\S]*)\}/) || {})[1]; 41882 } 41883 41884 function drawArc(ctx, x, y, coords) { 41885 var rx = coords[0]; 41886 var ry = coords[1]; 41887 var rot = coords[2]; 41888 var large = coords[3]; 41889 var sweep = coords[4]; 41890 var ex = coords[5]; 41891 var ey = coords[6]; 41892 var segs = arcToSegments(ex, ey, rx, ry, large, sweep, rot, x, y); 41893 for (var i=0; i<segs.length; i++) { 41894 var bez = segmentToBezier.apply(this, segs[i]); 41895 ctx.bezierCurveTo.apply(ctx, bez); 41896 } 41897 } 41898 41899 var arcToSegmentsCache = { }, 41900 segmentToBezierCache = { }, 41901 _join = Array.prototype.join, 41902 argsString; 41903 41904 // Generous contribution by Raph Levien, from libsvg-0.1.0.tar.gz 41905 function arcToSegments(x, y, rx, ry, large, sweep, rotateX, ox, oy) { 41906 argsString = _join.call(arguments); 41907 if (arcToSegmentsCache[argsString]) { 41908 return arcToSegmentsCache[argsString]; 41909 } 41910 41911 var th = rotateX * (Math.PI/180); 41912 var sin_th = Math.sin(th); 41913 var cos_th = Math.cos(th); 41914 rx = Math.abs(rx); 41915 ry = Math.abs(ry); 41916 var px = cos_th * (ox - x) * 0.5 + sin_th * (oy - y) * 0.5; 41917 var py = cos_th * (oy - y) * 0.5 - sin_th * (ox - x) * 0.5; 41918 var pl = (px*px) / (rx*rx) + (py*py) / (ry*ry); 41919 if (pl > 1) { 41920 pl = Math.sqrt(pl); 41921 rx *= pl; 41922 ry *= pl; 41923 } 41924 41925 var a00 = cos_th / rx; 41926 var a01 = sin_th / rx; 41927 var a10 = (-sin_th) / ry; 41928 var a11 = (cos_th) / ry; 41929 var x0 = a00 * ox + a01 * oy; 41930 var y0 = a10 * ox + a11 * oy; 41931 var x1 = a00 * x + a01 * y; 41932 var y1 = a10 * x + a11 * y; 41933 41934 var d = (x1-x0) * (x1-x0) + (y1-y0) * (y1-y0); 41935 var sfactor_sq = 1 / d - 0.25; 41936 if (sfactor_sq < 0) sfactor_sq = 0; 41937 var sfactor = Math.sqrt(sfactor_sq); 41938 if (sweep === large) sfactor = -sfactor; 41939 var xc = 0.5 * (x0 + x1) - sfactor * (y1-y0); 41940 var yc = 0.5 * (y0 + y1) + sfactor * (x1-x0); 41941 41942 var th0 = Math.atan2(y0-yc, x0-xc); 41943 var th1 = Math.atan2(y1-yc, x1-xc); 41944 41945 var th_arc = th1-th0; 41946 if (th_arc < 0 && sweep === 1){ 41947 th_arc += 2*Math.PI; 41948 } else if (th_arc > 0 && sweep === 0) { 41949 th_arc -= 2 * Math.PI; 41950 } 41951 41952 var segments = Math.ceil(Math.abs(th_arc / (Math.PI * 0.5 + 0.001))); 41953 var result = []; 41954 for (var i=0; i<segments; i++) { 41955 var th2 = th0 + i * th_arc / segments; 41956 var th3 = th0 + (i+1) * th_arc / segments; 41957 result[i] = [xc, yc, th2, th3, rx, ry, sin_th, cos_th]; 41958 } 41959 41960 arcToSegmentsCache[argsString] = result; 41961 return result; 41962 } 41963 41964 function segmentToBezier(cx, cy, th0, th1, rx, ry, sin_th, cos_th) { 41965 argsString = _join.call(arguments); 41966 if (segmentToBezierCache[argsString]) { 41967 return segmentToBezierCache[argsString]; 41968 } 41969 41970 var a00 = cos_th * rx; 41971 var a01 = -sin_th * ry; 41972 var a10 = sin_th * rx; 41973 var a11 = cos_th * ry; 41974 41975 var th_half = 0.5 * (th1 - th0); 41976 var t = (8/3) * Math.sin(th_half * 0.5) * Math.sin(th_half * 0.5) / Math.sin(th_half);
41977 var x1 = cx + Math.cos(th0) - t * Math.sin(th0); 41978 var y1 = cy + Math.sin(th0) + t * Math.cos(th0); 41979 var x3 = cx + Math.cos(th1); 41980 var y3 = cy + Math.sin(th1); 41981 var x2 = x3 + t * Math.sin(th1); 41982 var y2 = y3 - t * Math.cos(th1); 41983 41984 segmentToBezierCache[argsString] = [ 41985 a00 * x1 + a01 * y1, a10 * x1 + a11 * y1, 41986 a00 * x2 + a01 * y2, a10 * x2 + a11 * y2, 41987 a00 * x3 + a01 * y3, a10 * x3 + a11 * y3 41988 ]; 41989 41990 return segmentToBezierCache[argsString]; 41991 } 41992 41993 fabric.util.removeFromArray = removeFromArray; 41994 fabric.util.degreesToRadians = degreesToRadians; 41995 fabric.util.radiansToDegrees = radiansToDegrees; 41996 fabric.util.rotatePoint = rotatePoint; 41997 fabric.util.toFixed = toFixed; 41998 fabric.util.getRandomInt = getRandomInt; 41999 fabric.util.falseFunction = falseFunction; 42000 fabric.util.getKlass = getKlass; 42001 fabric.util.resolveNamespace = resolveNamespace; 42002 fabric.util.loadImage = loadImage; 42003 fabric.util.enlivenObjects = enlivenObjects; 42004 fabric.util.groupSVGElements = groupSVGElements; 42005 fabric.util.populateWithProperties = populateWithProperties; 42006 fabric.util.drawDashedLine = drawDashedLine; 42007 fabric.util.createCanvasElement = createCanvasElement; 42008 fabric.util.createImage = createImage; 42009 fabric.util.createAccessors = createAccessors; 42010 fabric.util.clipContext = clipContext; 42011 fabric.util.multiplyTransformMatrices = multiplyTransformMatrices; 42012 fabric.util.getFunctionBody = getFunctionBody; 42013 fabric.util.drawArc = drawArc; 42014 42015})(typeof exports !== 'undefined' ? exports : this); 42016 42017 42018(function() { 42019 42020 var slice = Array.prototype.slice; 42021 42022 /* _ES5_COMPAT_START_ */ 42023 42024 if (!Array.prototype.indexOf) { 42025 /** 42026 * Finds index of an element in an array 42027 * @param {Any} searchElement 42028 * @param {Number} [fromIndex] 42029 * @return {Number} 42030 */ 42031 Array.prototype.indexOf = function (searchElement /*, fromIndex */ ) { 42032 if (this === void 0 || this === null) { 42033 throw new TypeError(); 42034 } 42035 var t = Object(this), len = t.length >>> 0; 42036 if (len === 0) { 42037 return -1; 42038 } 42039 var n = 0; 42040 if (arguments.length > 0) { 42041 n = Number(arguments[1]); 42042 if (n !== n) { // shortcut for verifying if it's NaN 42043 n = 0; 42044 } 42045 else if (n !== 0 && n !== Number.POSITIVE_INFINITY && n !== Number.NEGATIVE_INFINITY) { 42046 n = (n > 0 || -1) * Math.floor(Math.abs(n)); 42047 } 42048 } 42049 if (n >= len) { 42050 return -1; 42051 } 42052 var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0); 42053 for (; k < len; k++) { 42054 if (k in t && t[k] === searchElement) { 42055 return k; 42056 } 42057 } 42058 return -1; 42059 }; 42060 } 42061 42062 if (!Array.prototype.forEach) { 42063 /** 42064 * Iterates an array, invoking callback for each element 42065 * @param {Function} fn Callback to invoke for each element 42066 * @param {Object} [context] Context to invoke callback in 42067 * @return {Array} 42068 */ 42069 Array.prototype.forEach = function(fn, context) { 42070 for (var i = 0, len = this.length >>> 0; i < len; i++) { 42071 if (i in this) { 42072 fn.call(context, this[i], i, this); 42073 } 42074 } 42075 }; 42076 } 42077 42078 if (!Array.prototype.map) { 42079 /** 42080 * Returns a result of iterating over an array, invoking callback for each element 42081 * @param {Function} fn Callback to invoke for each element 42082 * @param {Object} [context] Context to invoke callback in 42083 * @return {Array} 42084 */ 42085 Array.prototype.map = function(fn, context) { 42086 var result = [ ]; 42087 for (var i = 0, len = this.length >>> 0; i < len; i++) { 42088 if (i in this) { 42089 result[i] = fn.call(context, this[i], i, this); 42090 } 42091 } 42092 return result; 42093 }; 42094 } 42095 42096 if (!Array.prototype.every) { 42097 /** 42098 * Returns true if a callback returns truthy value for all elements in an array 42099 * @param {Function} fn Callback to invoke for each element 42100 * @param {Object} [context] Context to invoke callback in 42101 * @return {Boolean} 42102 */ 42103 Array.prototype.every = function(fn, context) { 42104 for (var i = 0, len = this.length >>> 0; i < len; i++) { 42105 if (i in this && !fn.call(context, this[i], i, this)) { 42106 return false;
42107 } 42108 } 42109 return true; 42110 }; 42111 } 42112 42113 if (!Array.prototype.some) { 42114 /** 42115 * Returns true if a callback returns truthy value for at least one element in an array 42116 * @param {Function} fn Callback to invoke for each element 42117 * @param {Object} [context] Context to invoke callback in 42118 * @return {Boolean} 42119 */ 42120 Array.prototype.some = function(fn, context) { 42121 for (var i = 0, len = this.length >>> 0; i < len; i++) { 42122 if (i in this && fn.call(context, this[i], i, this)) { 42123 return true; 42124 } 42125 } 42126 return false; 42127 }; 42128 } 42129 42130 if (!Array.prototype.filter) { 42131 /** 42132 * Returns the result of iterating over elements in an array 42133 * @param {Function} fn Callback to invoke for each element 42134 * @param {Object} [context] Context to invoke callback in 42135 * @return {Array} 42136 */ 42137 Array.prototype.filter = function(fn, context) { 42138 var result = [ ], val; 42139 for (var i = 0, len = this.length >>> 0; i < len; i++) { 42140 if (i in this) { 42141 val = this[i]; // in case fn mutates this 42142 if (fn.call(context, val, i, this)) { 42143 result.push(val); 42144 } 42145 } 42146 } 42147 return result; 42148 }; 42149 } 42150 42151 if (!Array.prototype.reduce) { 42152 /** 42153 * Returns "folded" (reduced) result of iterating over elements in an array 42154 * @param {Function} fn Callback to invoke for each element 42155 * @param {Object} [context] Context to invoke callback in 42156 * @return {Any} 42157 */ 42158 Array.prototype.reduce = function(fn /*, initial*/) { 42159 var len = this.length >>> 0, 42160 i = 0, 42161 rv; 42162 42163 if (arguments.length > 1) { 42164 rv = arguments[1]; 42165 } 42166 else { 42167 do { 42168 if (i in this) { 42169 rv = this[i++]; 42170 break; 42171 } 42172 // if array contains no values, no initial value to return 42173 if (++i >= len) { 42174 throw new TypeError(); 42175 } 42176 } 42177 while (true); 42178 } 42179 for (; i < len; i++) { 42180 if (i in this) { 42181 rv = fn.call(null, rv, this[i], i, this); 42182 } 42183 } 42184 return rv; 42185 }; 42186 } 42187 42188 /* _ES5_COMPAT_END_ */ 42189 42190 /** 42191 * Invokes method on all items in a given array 42192 * @memberOf fabric.util.array 42193 * @param {Array} array Array to iterate over 42194 * @param {String} method Name of a method to invoke 42195 * @return {Array} 42196 */ 42197 function invoke(array, method) { 42198 var args = slice.call(arguments, 2), result = [ ]; 42199 for (var i = 0, len = array.length; i < len; i++) { 42200 result[i] = args.length ? array[i][method].apply(array[i], args) : array[i][method].call(array[i]); 42201 } 42202 return result; 42203 } 42204 42205 /** 42206 * Finds maximum value in array (not necessarily "first" one) 42207 * @memberOf fabric.util.array 42208 * @param {Array} array Array to iterate over 42209 * @param {String} byProperty 42210 * @return {Any} 42211 */ 42212 function max(array, byProperty) { 42213 if (!array || array.length === 0) return undefined; 42214 42215 var i = array.length - 1, 42216 result = byProperty ? array[i][byProperty] : array[i]; 42217 if (byProperty) { 42218 while (i--) { 42219 if (array[i][byProperty] >= result) { 42220 result = array[i][byProperty]; 42221 } 42222 } 42223 } 42224 else { 42225 while (i--) { 42226 if (array[i] >= result) { 42227 result = array[i]; 42228 } 42229 } 42230 } 42231 return result; 42232 } 42233 42234 /** 42235 * Finds minimum value in array (not necessarily "first" one) 42236 * @memberOf fabric.util.array 42237 * @param {Array} array Array to iterate over 42238 * @param {String} byProperty 42239 * @return {Any} 42240 */ 42241 function min(array, byProperty) { 42242 if (!array || array.length === 0) return undefined; 42243 42244 var i = array.length - 1, 42245 result = byProperty ? array[i][byProperty] : array[i]; 42246 42247 if (byProperty) { 42248 while (i--) { 42249 if (array[i][byProperty] < result) { 42250 result = array[i][byProperty]; 42251 } 42252 } 42253 } 42254 else { 42255 while (i--) { 42256 if (array[i] < result) { 42257 result = array[i]; 42258 } 42259 } 42260 } 42261 return result; 42262 } 42263 42264 /** 42265 * @namespace fabric.util.array 42266 */ 42267 fabric.util.array = { 42268 invoke: invoke, 42269 min: min, 42270 max: max 42271 }; 42272 42273})(); 42274 42275 42276(function(){ 42277 42278 /** 42279 * Copies all enumerable properties of one object to another 42280 * @memberOf fabric.util.object 42281 * @param {Object} destination Where to copy to 42282 * @param {Object} source Where to copy from 42283 * @return {Object} 42284 */ 42285 function extend(destination, source) { 42286 // JScript DontEnum bug is not taken care of 42287 for (var property in source) { 42288 destination[property] = source[property]; 42289 } 42290 return destination; 42291 } 42292 42293 /** 42294 * Creates an empty object and copies all enumerable properties of another object to it 42295 * @memberOf fabric.util.object 42296 * @param {Object} object Object to clone 42297 * @return {Object} 42298 */ 42299 function clone(object) { 42300 return extend({ }, object); 42301 } 42302 42303 /** @namespace fabric.util.object */ 42304 fabric.util.object = { 42305 extend: extend, 42306 clone: clone 42307 }; 42308 42309})(); 42310 42311 42312(function() { 42313 42314/* _ES5_COMPAT_START_ */ 42315if (!String.prototype.trim) { 42316 /** 42317 * Trims a string (removing whitespace from the beginning and the end) 42318 * @function external:String#trim 42319 * @see <a href="https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String/Trim">String#trim on MDN</a> 42320 */ 42321 String.prototype.trim = function () { 42322 // this trim is not fully ES3 or ES5 compliant, but it should cover most cases for now 42323 return this.replace(/^[\s\xA0]+/, '').replace(/[\s\xA0]+$/, ''); 42324 }; 42325} 42326/* _ES5_COMPAT_END_ */ 42327 42328/** 42329 * Camelizes a string 42330 * @memberOf fabric.util.string 42331 * @param {String} string String to camelize 42332 * @return {String} Camelized version of a string 42333 */ 42334function camelize(string) { 42335 return string.replace(/-+(.)?/g, function(match, character) { 42336 return character ? character.toUpperCase() : ''; 42337 }); 42338} 42339 42340/** 42341 * Capitalizes a string 42342 * @memberOf fabric.util.string 42343 * @param {String} string String to capitalize 42344 * @return {String} Capitalized version of a string 42345 */ 42346function capitalize(string) { 42347 return string.charAt(0).toUpperCase() + string.slice(1).toLowerCase(); 42348} 42349 42350/** 42351 * Escapes XML in a string 42352 * @memberOf fabric.util.string 42353 * @param {String} string String to escape 42354 * @return {String} Escaped version of a string 42355 */ 42356function escapeXml(string) { 42357 return string.replace(/&/g, '&') 42358 .replace(/"/g, '"') 42359 .replace(/'/g, ''') 42360 .replace(/</g, '<') 42361 .replace(/>/g, '>'); 42362} 42363 42364/** 42365 * String utilities 42366 * @namespace fabric.util.string 42367 */ 42368fabric.util.string = { 42369 camelize: camelize, 42370 capitalize: capitalize, 42371 escapeXml: escapeXml 42372}; 42373}()); 42374 42375 42376/* _ES5_COMPAT_START_ */ 42377(function() { 42378 42379 var slice = Array.prototype.slice, 42380 apply = Function.prototype.apply, 42381 Dummy = function() { }; 42382 42383 if (!Function.prototype.bind) { 42384 /** 42385 * Cross-browser approximation of ES5 Function.prototype.bind (not fully spec conforming) 42386 * @see <a href="https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind">Function#bind on MDN</a> 42387 * @param {Object} thisArg Object to bind function to 42388 * @param {Any[]} [...] Values to pass to a bound function 42389 * @return {Function} 42390 */ 42391 Function.prototype.bind = function(thisArg) { 42392 var fn = this, args = slice.call(arguments, 1), bound; 42393 if (args.length) { 42394 bound = function() {
42395 return apply.call(fn, this instanceof Dummy ? this : thisArg, args.concat(slice.call(arguments))); 42396 }; 42397 } 42398 else { 42399 /** @ignore */ 42400 bound = function() { 42401 return apply.call(fn, this instanceof Dummy ? this : thisArg, arguments); 42402 }; 42403 } 42404 Dummy.prototype = this.prototype; 42405 bound.prototype = new Dummy(); 42406 42407 return bound; 42408 }; 42409 } 42410 42411})(); 42412/* _ES5_COMPAT_END_ */ 42413 42414 42415(function() { 42416 42417 var slice = Array.prototype.slice, emptyFunction = function() { }; 42418 42419 var IS_DONTENUM_BUGGY = (function(){ 42420 for (var p in { toString: 1 }) { 42421 if (p === 'toString') return false; 42422 } 42423 return true; 42424 })(); 42425 42426 /** @ignore */ 42427 var addMethods = function(klass, source, parent) { 42428 for (var property in source) { 42429 42430 if (property in klass.prototype && 42431 typeof klass.prototype[property] === 'function' && 42432 (source[property] + '').indexOf('callSuper') > -1) { 42433 42434 klass.prototype[property] = (function(property) { 42435 return function() { 42436 42437 var superclass = this.constructor.superclass; 42438 this.constructor.superclass = parent; 42439 var returnValue = source[property].apply(this, arguments); 42440 this.constructor.superclass = superclass; 42441 42442 if (property !== 'initialize') { 42443 return returnValue; 42444 } 42445 }; 42446 })(property); 42447 } 42448 else { 42449 klass.prototype[property] = source[property]; 42450 } 42451 42452 if (IS_DONTENUM_BUGGY) { 42453 if (source.toString !== Object.prototype.toString) { 42454 klass.prototype.toString = source.toString; 42455 } 42456 if (source.valueOf !== Object.prototype.valueOf) { 42457 klass.prototype.valueOf = source.valueOf; 42458 } 42459 } 42460 } 42461 }; 42462 42463 function Subclass() { } 42464 42465 function callSuper(methodName) { 42466 var fn = this.constructor.superclass.prototype[methodName]; 42467 return (arguments.length > 1) 42468 ? fn.apply(this, slice.call(arguments, 1)) 42469 : fn.call(this); 42470 } 42471 42472 /** 42473 * Helper for creation of "classes". 42474 * @memberOf fabric.util 42475 * @param parent optional "Class" to inherit from 42476 * @param properties Properties shared by all instances of this class 42477 * (be careful modifying objects defined here as this would affect all instances) 42478 */ 42479 function createClass() { 42480 var parent = null, 42481 properties = slice.call(arguments, 0); 42482 42483 if (typeof properties[0] === 'function') { 42484 parent = properties.shift(); 42485 } 42486 function klass() { 42487 this.initialize.apply(this, arguments); 42488 } 42489 42490 klass.superclass = parent; 42491 klass.subclasses = [ ]; 42492 42493 if (parent) { 42494 Subclass.prototype = parent.prototype; 42495 klass.prototype = new Subclass(); 42496 parent.subclasses.push(klass); 42497 } 42498 for (var i = 0, length = properties.length; i < length; i++) { 42499 addMethods(klass, properties[i], parent); 42500 } 42501 if (!klass.prototype.initialize) { 42502 klass.prototype.initialize = emptyFunction; 42503 } 42504 klass.prototype.constructor = klass; 42505 klass.prototype.callSuper = callSuper; 42506 return klass; 42507 } 42508 42509 fabric.util.createClass = createClass; 42510})(); 42511 42512 42513(function () { 42514 42515 /* EVENT HANDLING */ 42516 42517 function areHostMethods(object) { 42518 var methodNames = Array.prototype.slice.call(arguments, 1), 42519 t, i, len = methodNames.length; 42520 for (i = 0; i < len; i++) { 42521 t = typeof object[methodNames[i]]; 42522 if (!(/^(?:function|object|unknown)$/).test(t)) return false; 42523 } 42524 return true; 42525 } 42526 var getUniqueId = (function () { 42527 var uid = 0; 42528 return function (element) { 42529 return element.__uniqueID || (element.__uniqueID = 'uniqueID__' + uid++); 42530 }; 42531 })(); 42532 42533 /** @ignore */ 42534 var getElement, setElement; 42535 42536 (function () { 42537 var elements = { }; 42538 /** @ignore */ 42539 getElement = function (uid) { 42540 return elements[uid]; 42541 }; 42542 /** @ignore */ 42543 setElement = function (uid, element) { 42544 elements[uid] = element; 42545 }; 42546 })(); 42547 42548 function createListener(uid, handler) { 42549 return { 42550 handler: handler, 42551 wrappedHandler: createWrappedHandler(uid, handler) 42552 }; 42553 } 42554 42555 function createWrappedHandler(uid, handler) { 42556 return function (e) { 42557 handler.call(getElement(uid), e || fabric.window.event); 42558 }; 42559 } 42560 42561 function createDispatcher(uid, eventName) { 42562 return function (e) { 42563 if (handlers[uid] && handlers[uid][eventName]) { 42564 var handlersForEvent = handlers[uid][eventName]; 42565 for (var i = 0, len = handlersForEvent.length; i < len; i++) { 42566 handlersForEvent[i].call(this, e || fabric.window.event); 42567 } 42568 } 42569 }; 42570 } 42571 42572 var shouldUseAddListenerRemoveListener = ( 42573 areHostMethods(fabric.document.documentElement, 'addEventListener', 'removeEventListener') && 42574 areHostMethods(fabric.window, 'addEventListener', 'removeEventListener')), 42575 42576 shouldUseAttachEventDetachEvent = ( 42577 areHostMethods(fabric.document.documentElement, 'attachEvent', 'detachEvent') && 42578 areHostMethods(fabric.window, 'attachEvent', 'detachEvent')), 42579 42580 // IE branch 42581 listeners = { }, 42582 42583 // DOM L0 branch 42584 handlers = { }, 42585 42586 addListener, removeListener; 42587 42588 if (shouldUseAddListenerRemoveListener) { 42589 /** @ignore */ 42590 addListener = function (element, eventName, handler) { 42591 element.addEventListener(eventName, handler, false); 42592 }; 42593 /** @ignore */ 42594 removeListener = function (element, eventName, handler) { 42595 element.removeEventListener(eventName, handler, false); 42596 }; 42597 } 42598 42599 else if (shouldUseAttachEventDetachEvent) { 42600 /** @ignore */ 42601 addListener = function (element, eventName, handler) { 42602 var uid = getUniqueId(element); 42603 setElement(uid, element); 42604 if (!listeners[uid]) { 42605 listeners[uid] = { }; 42606 } 42607 if (!listeners[uid][eventName]) { 42608 listeners[uid][eventName] = [ ]; 42609 42610 } 42611 var listener = createListener(uid, handler); 42612 listeners[uid][eventName].push(listener); 42613 element.attachEvent('on' + eventName, listener.wrappedHandler); 42614 }; 42615 /** @ignore */ 42616 removeListener = function (element, eventName, handler) { 42617 var uid = getUniqueId(element), listener; 42618 if (listeners[uid] && listeners[uid][eventName]) { 42619 for (var i = 0, len = listeners[uid][eventName].length; i < len; i++) { 42620 listener = listeners[uid][eventName][i]; 42621 if (listener && listener.handler === handler) { 42622 element.detachEvent('on' + eventName, listener.wrappedHandler); 42623 listeners[uid][eventName][i] = null; 42624 } 42625 } 42626 } 42627 }; 42628 } 42629 else { 42630 /** @ignore */ 42631 addListener = function (element, eventName, handler) { 42632 var uid = getUniqueId(element); 42633 if (!handlers[uid]) { 42634 handlers[uid] = { }; 42635 } 42636 if (!handlers[uid][eventName]) { 42637 handlers[uid][eventName] = [ ]; 42638 var existingHandler = element['on' + eventName]; 42639 if (existingHandler) { 42640 handlers[uid][eventName].push(existingHandler); 42641 } 42642 element['on' + eventName] = createDispatcher(uid, eventName); 42643 } 42644 handlers[uid][eventName].push(handler); 42645 }; 42646 /** @ignore */ 42647 removeListener = function (element, eventName, handler) { 42648 var uid = getUniqueId(element); 42649 if (handlers[uid] && handlers[uid][eventName]) { 42650 var handlersForEvent = handlers[uid][eventName]; 42651 for (var i = 0, len = handlersForEvent.length; i < len; i++) { 42652 if (handlersForEvent[i] === handler) { 42653 handlersForEvent.splice(i, 1); 42654 } 42655 } 42656 } 42657 }; 42658 } 42659 42660 /** 42661 * Adds an event listener to an element 42662 * @function 42663 * @memberOf fabric.util 42664 * @param {HTMLElement} element 42665 * @param {String} eventName 42666 * @param {Function} handler 42667 */ 42668 fabric.util.addListener = addListener; 42669 42670 /** 42671 * Removes an event listener from an element 42672 * @function 42673 * @memberOf fabric.util 42674 * @param {HTMLElement} element 42675 * @param {String} eventName 42676 * @param {Function} handler 42677 */ 42678 fabric.util.removeListener = removeListener; 42679 42680 /**
42681 * Cross-browser wrapper for getting event's coordinates 42682 * @memberOf fabric.util 42683 * @param {Event} event Event object 42684 * @param {HTMLCanvasElement} upperCanvasEl <canvas> element on which object selection is drawn 42685 */ 42686 function getPointer(event, upperCanvasEl) { 42687 event || (event = fabric.window.event); 42688 42689 var element = event.target || (typeof event.srcElement !== 'unknown' ? event.srcElement : null), 42690 body = fabric.document.body || {scrollLeft: 0, scrollTop: 0}, 42691 docElement = fabric.document.documentElement, 42692 orgElement = element, 42693 scrollLeft = 0, 42694 scrollTop = 0, 42695 firstFixedAncestor; 42696 42697 while (element && element.parentNode && !firstFixedAncestor) { 42698 element = element.parentNode; 42699 42700 if (element !== fabric.document && 42701 fabric.util.getElementStyle(element, 'position') === 'fixed') { 42702 firstFixedAncestor = element; 42703 } 42704 42705 if (element !== fabric.document && 42706 orgElement !== upperCanvasEl && 42707 fabric.util.getElementStyle(element, 'position') === 'absolute') { 42708 scrollLeft = 0; 42709 scrollTop = 0; 42710 } 42711 else if (element === fabric.document) { 42712 scrollLeft = body.scrollLeft || docElement.scrollLeft || 0; 42713 scrollTop = body.scrollTop || docElement.scrollTop || 0; 42714 } 42715 else { 42716 scrollLeft += element.scrollLeft || 0; 42717 scrollTop += element.scrollTop || 0; 42718 } 42719 } 42720 42721 return { 42722 x: pointerX(event) + scrollLeft, 42723 y: pointerY(event) + scrollTop 42724 }; 42725 } 42726 42727 var pointerX = function(event) { 42728 // looks like in IE (<9) clientX at certain point (apparently when mouseup fires on VML element) 42729 // is represented as COM object, with all the consequences, like "unknown" type and error on [[Get]] 42730 // need to investigate later 42731 return (typeof event.clientX !== 'unknown' ? event.clientX : 0); 42732 }; 42733 42734 var pointerY = function(event) { 42735 return (typeof event.clientY !== 'unknown' ? event.clientY : 0); 42736 }; 42737 42738 if (fabric.isTouchSupported) { 42739 pointerX = function(event) { 42740 if (event.type !== 'touchend') { 42741 return (event.touches && event.touches[0] ? 42742 (event.touches[0].pageX - (event.touches[0].pageX - event.touches[0].clientX)) || event.clientX : event.clientX); 42743 } 42744 return (event.changedTouches && event.changedTouches[0] 42745 ? (event.changedTouches[0].pageX - (event.changedTouches[0].pageX - event.changedTouches[0].clientX)) || event.clientX : event.clientX); 42746 }; 42747 pointerY = function(event) { 42748 if (event.type !== 'touchend') { 42749 return (event.touches && event.touches[0] 42750 ? (event.touches[0].pageY - (event.touches[0].pageY - event.touches[0].clientY)) || event.clientY : event.clientY); 42751 } 42752 return (event.changedTouches && event.changedTouches[0] 42753 ? (event.changedTouches[0].pageY - (event.changedTouches[0].pageY - event.changedTouches[0].clientY)) || event.clientY : event.clientY); 42754 }; 42755 } 42756 42757 fabric.util.getPointer = getPointer; 42758 42759 fabric.util.object.extend(fabric.util, fabric.Observable); 42760 42761})(); 42762 42763 42764(function () { 42765 42766 /** 42767 * Cross-browser wrapper for setting element's style 42768 * @memberOf fabric.util 42769 * @param {HTMLElement} element 42770 * @param {Object} styles 42771 * @return {HTMLElement} Element that was passed as a first argument 42772 */ 42773 function setStyle(element, styles) { 42774 var elementStyle = element.style; 42775 if (!elementStyle) { 42776 return element; 42777 } 42778 if (typeof styles === 'string') { 42779 element.style.cssText += ';' + styles; 42780 return styles.indexOf('opacity') > -1 42781 ? setOpacity(element, styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) 42782 : element; 42783 } 42784 for (var property in styles) { 42785 if (property === 'opacity') { 42786 setOpacity(element, styles[property]); 42787 } 42788 else { 42789 var normalizedProperty = (property === 'float' || property === 'cssFloat') 42790 ? (typeof elementStyle.styleFloat === 'undefined' ? 'cssFloat' : 'styleFloat') 42791 : property; 42792 elementStyle[normalizedProperty] = styles[property]; 42793 } 42794 } 42795 return element; 42796 } 42797 42798 var parseEl = fabric.document.createElement('div'), 42799 supportsOpacity = typeof parseEl.style.opacity === 'string', 42800 supportsFilters = typeof parseEl.style.filter === 'string', 42801 reOpacity = /alpha\s*\(\s*opacity\s*=\s*([^\)]+)\)/, 42802 42803 /** @ignore */ 42804 setOpacity = function (element) { return element; }; 42805 42806 if (supportsOpacity) { 42807 /** @ignore */ 42808 setOpacity = function(element, value) { 42809 element.style.opacity = value; 42810 return element; 42811 }; 42812 } 42813 else if (supportsFilters) { 42814 /** @ignore */ 42815 setOpacity = function(element, value) { 42816 var es = element.style; 42817 if (element.currentStyle && !element.currentStyle.hasLayout) { 42818 es.zoom = 1; 42819 } 42820 if (reOpacity.test(es.filter)) { 42821 value = value >= 0.9999 ? '' : ('alpha(opacity=' + (value * 100) + ')'); 42822 es.filter = es.filter.replace(reOpacity, value); 42823 } 42824 else { 42825 es.filter += ' alpha(opacity=' + (value * 100) + ')'; 42826 } 42827 return element; 42828 }; 42829 } 42830 42831 fabric.util.setStyle = setStyle; 42832 42833})(); 42834 42835 42836(function() { 42837 42838 var _slice = Array.prototype.slice; 42839 42840 /** 42841 * Takes id and returns an element with that id (if one exists in a document) 42842 * @memberOf fabric.util 42843 * @param {String|HTMLElement}
42843 id 42844 * @return {HTMLElement|null} 42845 */ 42846 function getById(id) { 42847 return typeof id === 'string' ? fabric.document.getElementById(id) : id; 42848 } 42849 42850 /** 42851 * Converts an array-like object (e.g. arguments or NodeList) to an array 42852 * @memberOf fabric.util 42853 * @param {Object} arrayLike 42854 * @return {Array} 42855 */ 42856 var toArray = function(arrayLike) { 42857 return _slice.call(arrayLike, 0); 42858 }; 42859 42860 var sliceCanConvertNodelists; 42861 try { 42862 sliceCanConvertNodelists = toArray(fabric.document.childNodes) instanceof Array; 42863 } 42864 catch(err) { } 42865 42866 if (!sliceCanConvertNodelists) { 42867 toArray = function(arrayLike) { 42868 var arr = new Array(arrayLike.length), i = arrayLike.length; 42869 while (i--) { 42870 arr[i] = arrayLike[i]; 42871 } 42872 return arr; 42873 }; 42874 } 42875 42876 /** 42877 * Creates specified element with specified attributes 42878 * @memberOf fabric.util 42879 * @param {String} tagName Type of an element to create 42880 * @param {Object} [attributes] Attributes to set on an element 42881 * @return {HTMLElement} Newly created element 42882 */ 42883 function makeElement(tagName, attributes) { 42884 var el = fabric.document.createElement(tagName); 42885 for (var prop in attributes) { 42886 if (prop === 'class') { 42887 el.className = attributes[prop]; 42888 } 42889 else if (prop === 'for') { 42890 el.htmlFor = attributes[prop]; 42891 } 42892 else { 42893 el.setAttribute(prop, attributes[prop]); 42894 } 42895 } 42896 return el; 42897 } 42898 42899 /** 42900 * Adds class to an element 42901 * @memberOf fabric.util 42902 * @param {HTMLElement} element Element to add class to 42903 * @param {String} className Class to add to an element 42904 */ 42905 function addClass(element, className) { 42906 if ((' ' + element.className + ' ').indexOf(' ' + className + ' ') === -1) { 42907 element.className += (element.className ? ' ' : '') + className; 42908 } 42909 } 42910 42911 /** 42912 * Wraps element with another element 42913 * @memberOf fabric.util 42914 * @param {HTMLElement} element Element to wrap 42915 * @param {HTMLElement|String} wrapper Element to wrap with 42916 * @param {Object} [attributes] Attributes to set on a wrapper 42917 * @return {HTMLElement} wrapper 42918 */ 42919 function wrapElement(element, wrapper, attributes) { 42920 if (typeof wrapper === 'string') { 42921 wrapper = makeElement(wrapper, attributes); 42922 } 42923 if (element.parentNode) { 42924 element.parentNode.replaceChild(wrapper, element); 42925 } 42926 wrapper.appendChild(element); 42927 return wrapper; 42928 } 42929 42930 /** 42931 * Returns offset for a given element 42932 * @function 42933 * @memberOf fabric.util 42934 * @param {HTMLElement} element Element to get offset for 42935 * @return {Object} Object with "left" and "top" properties 42936 */ 42937 function getElementOffset(element) { 42938 var docElem, win, 42939 box = {left: 0, top: 0}, 42940 doc = element && element.ownerDocument, 42941 offset = {left: 0, top: 0}, 42942 offsetAttributes = { 42943 'borderLeftWidth': 'left', 42944 'borderTopWidth': 'top', 42945 'paddingLeft': 'left', 42946 'paddingTop': 'top' 42947 }; 42948 42949 if (!doc){ 42950 return {left: 0, top: 0}; 42951 } 42952 42953 for (var attr in offsetAttributes) { 42954 offset[offsetAttributes[attr]] += parseInt(getElementStyle(element, attr), 10) || 0; 42955 } 42956 42957 docElem = doc.documentElement; 42958 if ( typeof element.getBoundingClientRect !== "undefined" ) { 42959 box = element.getBoundingClientRect(); 42960 } 42961 if(doc != null && doc === doc.window){ 42962 win = doc; 42963 } else { 42964 win = doc.nodeType === 9 && (doc.defaultView || doc.parentWindow); 42965 } 42966 return { 42967 left: box.left + (win.pageXOffset || docElem.scrollLeft) - (docElem.clientLeft || 0) + offset.left, 42968 top: box.top + (win.pageYOffset || docElem.scrollTop) - (docElem.clientTop || 0) + offset.top 42969 }; 42970 } 42971 42972 /** 42973 * Returns style attribute value of a given element 42974 * @memberOf fabric.util 42975 * @param {HTMLElement} element Element to get style attribute for 42976 * @param {String} attr Style attribute to get for element 42977 * @return {String} Style attribute value of the given element. 42978 */ 42979 function getElementStyle(element, attr) { 42980 if (!element.style) { 42981 element.style = { }; 42982 } 42983 42984 if (fabric.document.defaultView && fabric.document.defaultView.getComputedStyle) { 42985 return fabric.document.defaultView.getComputedStyle(element, null)[attr]; 42986 } 42987 else { 42988 var value = element.style[attr]; 42989 if (!value && element.currentStyle) value = element.currentStyle[attr]; 42990 return value; 42991 } 42992 } 42993 42994 (function () { 42995 var style = fabric.document.documentElement.style; 42996 42997 var selectProp = 'userSelect' in style 42998 ? 'userSelect' 42999 : 'MozUserSelect' in style 43000 ? 'MozUserSelect' 43001 : 'WebkitUserSelect' in style 43002 ? 'WebkitUserSelect' 43003 : 'KhtmlUserSelect' in style 43004 ? 'KhtmlUserSelect' 43005 : ''; 43006 43007 /** 43008 * Makes element unselectable 43009 * @memberOf fabric.util 43010 * @param {HTMLElement} element Element to make unselectable 43011 * @return {HTMLElement} Element that was passed in 43012 */ 43013 function makeElementUnselectable(element) { 43014 if (typeof element.onselectstart !== 'undefined') { 43015 element.onselectstart = fabric.util.falseFunction; 43016 } 43017 if (selectProp) { 43018 element.style[selectProp] = 'none'; 43019 } 43020 else if (typeof element.unselectable === 'string') { 43021 element.unselectable = 'on'; 43022 } 43023 return element; 43024 } 43025 43026 /** 43027 * Makes element selectable 43028 * @memberOf fabric.util 43029 * @param {HTMLElement} element Element to make selectable 43030 * @return {HTMLElement} Element that was passed in 43031 */ 43032 function makeElementSelectable(element) { 43033 if (typeof element.onselectstart !== 'undefined') { 43034 element.onselectstart = null; 43035 } 43036 if (selectProp) { 43037 element.style[selectProp] = ''; 43038 } 43039 else if (typeof element.unselectable === 'string') { 43040 element.unselectable = ''; 43041 } 43042 return element; 43043 } 43044 43045 fabric.util.makeElementUnselectable = makeElementUnselectable; 43046 fabric.util.makeElementSelectable = makeElementSelectable; 43047 })(); 43048 43049 (function() { 43050 43051 /** 43052 * Inserts a script element with a given url into a document; invokes callback, when that script is finished loading 43053 * @memberOf fabric.util 43054 * @param {String} url URL of a script to load 43055 * @param {Function} callback Callback to execute when script is finished loading 43056 */ 43057 function getScript(url, callback) { 43058 var headEl = fabric.document.getElementsByTagName("head")[0], 43059 scriptEl = fabric.document.createElement('script'), 43060 loading = true; 43061 43062 /** @ignore */ 43063 scriptEl.onload = /** @ignore */ scriptEl.onreadystatechange = function(e) { 43064 if (loading) { 43065 if (typeof this.readyState === 'string' && 43066 this.readyState !== 'loaded' && 43067 this.readyState !== 'complete') return; 43068 loading = false;
43069 callback(e || fabric.window.event); 43070 scriptEl = scriptEl.onload = scriptEl.onreadystatechange = null; 43071 } 43072 }; 43073 scriptEl.src = url; 43074 headEl.appendChild(scriptEl); 43075 // causes issue in Opera 43076 // headEl.removeChild(scriptEl); 43077 } 43078 43079 fabric.util.getScript = getScript; 43080 })(); 43081 43082 fabric.util.getById = getById; 43083 fabric.util.toArray = toArray; 43084 fabric.util.makeElement = makeElement; 43085 fabric.util.addClass = addClass; 43086 fabric.util.wrapElement = wrapElement; 43087 fabric.util.getElementOffset = getElementOffset; 43088 fabric.util.getElementStyle = getElementStyle; 43089 43090})(); 43091 43092 43093(function(){ 43094 43095 function addParamToUrl(url, param) { 43096 return url + (/\?/.test(url) ? '&' : '?') + param; 43097 } 43098 43099 var makeXHR = (function() { 43100 var factories = [ 43101 function() { return new ActiveXObject("Microsoft.XMLHTTP"); }, 43102 function() { return new ActiveXObject("Msxml2.XMLHTTP"); }, 43103 function() { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); }, 43104 function() { return new XMLHttpRequest(); } 43105 ]; 43106 for (var i = factories.length; i--; ) { 43107 try { 43108 var req = factories[i](); 43109 if (req) { 43110 return factories[i]; 43111 } 43112 } 43113 catch (err) { } 43114 } 43115 })(); 43116 43117 function emptyFn() { } 43118 43119 /** 43120 * Cross-browser abstraction for sending XMLHttpRequest 43121 * @memberOf fabric.util 43122 * @param {String} url URL to send XMLHttpRequest to 43123 * @param {Object} [options] Options object 43124 * @param {String} [options.method="GET"] 43125 * @param {Function} options.onComplete Callback to invoke when request is completed 43126 * @return {XMLHttpRequest} request 43127 */ 43128 function request(url, options) { 43129 43130 options || (options = { }); 43131 43132 var method = options.method ? options.method.toUpperCase() : 'GET', 43133 onComplete = options.onComplete || function() { }, 43134 xhr = makeXHR(), 43135 body; 43136 43137 /** @ignore */ 43138 xhr.onreadystatechange = function() { 43139 if (xhr.readyState === 4) { 43140 onComplete(xhr); 43141 xhr.onreadystatechange = emptyFn; 43142 } 43143 }; 43144 43145 if (method === 'GET') { 43146 body = null; 43147 if (typeof options.parameters === 'string') { 43148 url = addParamToUrl(url, options.parameters); 43149 } 43150 } 43151 43152 xhr.open(method, url, true); 43153 43154 if (method === 'POST' || method === 'PUT') { 43155 xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); 43156 } 43157 43158 xhr.send(body); 43159 return xhr; 43160 } 43161 43162 fabric.util.request = request; 43163})(); 43164 43165 43166(function() { 43167 43168 /** 43169 * Changes value from one to another within certain period of time, invoking callbacks as value is being changed. 43170 * @memberOf fabric.util 43171 * @param {Object} [options] Animation options 43172 * @param {Function} [options.onChange] Callback; invoked on every value change 43173 * @param {Function} [options.onComplete] Callback; invoked when value change is completed 43174 * @param {Number} [options.startValue=0] Starting value 43175 * @param {Number} [options.endValue=100] Ending value 43176 * @param {Number} [options.byValue=100] Value to modify the property by 43177 * @param {Function} [options.easing] Easing function 43178 * @param {Number} [options.duration=500] Duration of change 43179 */ 43180 function animate(options) { 43181 43182 options || (options = { }); 43183 43184 var start = +new Date(), 43185 duration = options.duration || 500, 43186 finish = start + duration, time, 43187 onChange = options.onChange || function() { }, 43188 abort = options.abort || function() { return false; }, 43189 easing = options.easing || function(t, b, c, d) {return -c * Math.cos(t/d * (Math.PI/2)) + c + b;}, 43190 startValue = 'startValue' in options ? options.startValue : 0, 43191 endValue = 'endValue' in options ? options.endValue : 100, 43192 byValue = options.byValue || endValue - startValue; 43193 43194 options.onStart && options.onStart(); 43195 43196 (function tick() { 43197 time = +new Date(); 43198 var currentTime = time > finish ? duration : (time - start); 43199 if (abort()) { 43200 options.onComplete && options.onComplete(); 43201 return; 43202 } 43203 onChange(easing(currentTime, startValue, byValue, duration)); 43204 if (time > finish) { 43205 options.onComplete && options.onComplete(); 43206 return; 43207 }
43208 requestAnimFrame(tick); 43209 })(); 43210 } 43211 43212 var _requestAnimFrame = fabric.window.requestAnimationFrame || 43213 fabric.window.webkitRequestAnimationFrame || 43214 fabric.window.mozRequestAnimationFrame || 43215 fabric.window.oRequestAnimationFrame || 43216 fabric.window.msRequestAnimationFrame || 43217 function(callback) { 43218 fabric.window.setTimeout(callback, 1000 / 60); 43219 }; 43220 /** 43221 * requestAnimationFrame polyfill based on http://paulirish.com/2011/requestanimationframe-for-smart-animating/ 43222 * @memberOf fabric.util 43223 * @param {Function} callback Callback to invoke 43224 * @param {DOMElement} element optional Element to associate with animation 43225 */ 43226 var requestAnimFrame = function() { 43227 return _requestAnimFrame.apply(fabric.window, arguments); 43228 }; 43229 43230 fabric.util.animate = animate; 43231 fabric.util.requestAnimFrame = requestAnimFrame; 43232 43233})(); 43234 43235 43236(function() { 43237 43238 /** 43239 * Quadratic easing in 43240 * @memberOf fabric.util.ease 43241 */ 43242 function easeInQuad(t, b, c, d) { 43243 return c*(t/=d)*t + b; 43244 } 43245 43246 /** 43247 * Quadratic easing out 43248 * @memberOf fabric.util.ease 43249 */ 43250 function easeOutQuad(t, b, c, d) { 43251 return -c *(t/=d)*(t-2) + b; 43252 } 43253 43254 /** 43255 * Quadratic easing in and out 43256 * @memberOf fabric.util.ease 43257 */ 43258 function easeInOutQuad(t, b, c, d) { 43259 t /= (d/2); 43260 if (t < 1) return c/2*t*t + b; 43261 return -c/2 * ((--t)*(t-2) - 1) + b; 43262 } 43263 43264 /** 43265 * Cubic easing in 43266 * @memberOf fabric.util.ease 43267 */ 43268 function easeInCubic(t, b, c, d) { 43269 return c*(t/=d)*t*t + b; 43270 } 43271 43272 /** 43273 * Cubic easing out 43274 * @memberOf fabric.util.ease 43275 */ 43276 function easeOutCubic(t, b, c, d) { 43277 return c*((t=t/d-1)*t*t + 1) + b; 43278 } 43279 43280 /** 43281 * Cubic easing in and out 43282 * @memberOf fabric.util.ease 43283 */ 43284 function easeInOutCubic(t, b, c, d) { 43285 t /= d/2; 43286 if (t < 1) return c/2*t*t*t + b; 43287 return c/2*((t-=2)*t*t + 2) + b; 43288 } 43289 43290 /** 43291 * Quartic easing in 43292 * @memberOf fabric.util.ease 43293 */ 43294 function easeInQuart(t, b, c, d) { 43295 return c*(t/=d)*t*t*t + b; 43296 } 43297 43298 /** 43299 * Quartic easing out 43300 * @memberOf fabric.util.ease 43301 */ 43302 function easeOutQuart(t, b, c, d) { 43303 return -c * ((t=t/d-1)*t*t*t - 1) + b; 43304 } 43305 43306 /** 43307 * Quartic easing in and out 43308 * @memberOf fabric.util.ease 43309 */ 43310 function easeInOutQuart(t, b, c, d) { 43311 t /= d/2; 43312 if (t < 1) return c/2*t*t*t*t + b; 43313 return -c/2 * ((t-=2)*t*t*t - 2) + b; 43314 } 43315 43316 /** 43317 * Quintic easing in 43318 * @memberOf fabric.util.ease 43319 */ 43320 function easeInQuint(t, b, c, d) { 43321 return c*(t/=d)*t*t*t*t + b; 43322 } 43323 43324 /** 43325 * Quintic easing out 43326 * @memberOf fabric.util.ease 43327 */ 43328 function easeOutQuint(t, b, c, d) { 43329 return c*((t=t/d-1)*t*t*t*t + 1) + b; 43330 } 43331 43332 /** 43333 * Quintic easing in and out 43334 * @memberOf fabric.util.ease 43335 */ 43336 function easeInOutQuint(t, b, c, d) { 43337 t /= d/2; 43338 if (t < 1) return c/2*t*t*t*t*t + b; 43339 return c/2*((t-=2)*t*t*t*t + 2) + b; 43340 } 43341 43342 /** 43343 * Sinusoidal easing in 43344 * @memberOf fabric.util.ease 43345 */ 43346 function easeInSine(t, b, c, d) { 43347 return -c * Math.cos(t/d * (Math.PI/2)) + c + b; 43348 } 43349 43350 /** 43351 * Sinusoidal easing out 43352 * @memberOf fabric.util.ease 43353 */ 43354 function easeOutSine(t, b, c, d) { 43355 return c * Math.sin(t/d * (Math.PI/2)) + b; 43356 } 43357 43358 /** 43359 * Sinusoidal easing in and out 43360 * @memberOf fabric.util.ease 43361 */ 43362 function easeInOutSine(t, b, c, d) { 43363 return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b; 43364 } 43365 43366 /** 43367 * Exponential easing in 43368 * @memberOf fabric.util.ease 43369 */ 43370 function easeInExpo(t, b, c, d) { 43371 return (t===0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b; 43372 } 43373 43374 /** 43375 * Exponential easing out 43376 * @memberOf fabric.util.ease 43377 */ 43378 function easeOutExpo(t, b, c, d) { 43379 return (t===d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b; 43380 } 43381 43382 /** 43383 * Exponential easing in and out 43384 * @memberOf fabric.util.ease 43385 */ 43386 function easeInOutExpo(t, b, c, d) { 43387 if (t===0) return b; 43388 if (t===d) return b+c; 43389 t /= d/2; 43390 if (t < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b; 43391 return c/2 * (-Math.pow(2, -10 * --t) + 2) + b; 43392 } 43393 43394 /** 43395 * Circular easing in 43396 * @memberOf fabric.util.ease 43397 */ 43398 function easeInCirc(t, b, c, d) { 43399 return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b; 43400 } 43401 43402 /** 43403 * Circular easing out 43404 * @memberOf fabric.util.ease 43405 */ 43406 function easeOutCirc(t, b, c, d) { 43407 return c * Math.sqrt(1 - (t=t/d-1)*t) + b; 43408 } 43409 43410 /** 43411 * Circular easing in and out 43412 * @memberOf fabric.util.ease 43413 */ 43414 function easeInOutCirc(t, b, c, d) { 43415 t /= d/2;
43416 if (t < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b; 43417 return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b; 43418 } 43419 43420 /** 43421 * Elastic easing in 43422 * @memberOf fabric.util.ease 43423 */ 43424 function easeInElastic(t, b, c, d) { 43425 var s=1.70158;var p=0;var a=c; 43426 if (t===0) return b; 43427 t /= d; 43428 if (t===1) return b+c; 43429 if (!p) p=d*0.3; 43430 if (a < Math.abs(c)) { a=c; s=p/4; } 43431 else s = p/(2*Math.PI) * Math.asin (c/a); 43432 return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; 43433 } 43434 43435 /** 43436 * Elastic easing out 43437 * @memberOf fabric.util.ease 43438 */ 43439 function easeOutElastic(t, b, c, d) { 43440 var s=1.70158;var p=0;var a=c; 43441 if (t===0) return b; 43442 t /= d; 43443 if (t===1) return b+c; 43444 if (!p) p=d*0.3; 43445 if (a < Math.abs(c)) { a=c; s=p/4; } 43446 else s = p/(2*Math.PI) * Math.asin (c/a); 43447 return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b; 43448 } 43449 43450 /** 43451 * Elastic easing in and out 43452 * @memberOf fabric.util.ease 43453 */ 43454 function easeInOutElastic(t, b, c, d) { 43455 var s=1.70158;var p=0;var a=c; 43456 if (t===0) return b; 43457 t /= d/2; 43458 if (t===2) return b+c; 43459 if (!p) p=d*(0.3*1.5); 43460 if (a < Math.abs(c)) { a=c; s=p/4; } 43461 else s = p/(2*Math.PI) * Math.asin (c/a); 43462 if (t < 1) return -0.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; 43463 return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*0.5 + c + b; 43464 } 43465 43466 /** 43467 * Backwards easing in 43468 * @memberOf fabric.util.ease 43469 */ 43470 function easeInBack(t, b, c, d, s) { 43471 if (s === undefined) s = 1.70158; 43472 return c*(t/=d)*t*((s+1)*t - s) + b; 43473 } 43474 43475 /** 43476 * Backwards easing out 43477 * @memberOf fabric.util.ease 43478 */ 43479 function easeOutBack(t, b, c, d, s) { 43480 if (s === undefined) s = 1.70158; 43481 return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b; 43482 } 43483 43484 /** 43485 * Backwards easing in and out 43486 * @memberOf fabric.util.ease 43487 */ 43488 function easeInOutBack(t, b, c, d, s) { 43489 if (s === undefined) s = 1.70158; 43490 t /= d/2; 43491 if (t < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b; 43492 return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b; 43493 } 43494 43495 /** 43496 * Bouncing easing in 43497 * @memberOf fabric.util.ease 43498 */ 43499 function easeInBounce(t, b, c, d) { 43500 return c - easeOutBounce (d-t, 0, c, d) + b; 43501 } 43502 43503 /** 43504 * Bouncing easing out 43505 * @memberOf fabric.util.ease 43506 */ 43507 function easeOutBounce(t, b, c, d) { 43508 if ((t/=d) < (1/2.75)) { 43509 return c*(7.5625*t*t) + b; 43510 } else if (t < (2/2.75)) { 43511 return c*(7.5625*(t-=(1.5/2.75))*t + 0.75) + b; 43512 } else if (t < (2.5/2.75)) { 43513 return c*(7.5625*(t-=(2.25/2.75))*t + 0.9375) + b; 43514 } else { 43515 return c*(7.5625*(t-=(2.625/2.75))*t + 0.984375) + b; 43516 } 43517 } 43518 43519 /** 43520 * Bouncing easing in and out 43521 * @memberOf fabric.util.ease 43522 */ 43523 function easeInOutBounce(t, b, c, d) { 43524 if (t < d/2) return easeInBounce (t*2, 0, c, d) * 0.5 + b; 43525 return easeOutBounce (t*2-d, 0, c, d) * 0.5 + c*0.5 + b; 43526 } 43527 43528 /** 43529 * Easing functions 43530 * See <a href="http://gizma.com/easing/">Easing Equations by Robert Penner</a> 43531 * @namespace fabric.util.ease 43532 */ 43533 fabric.util.ease = { 43534 easeInQuad: easeInQuad, 43535 easeOutQuad: easeOutQuad, 43536 easeInOutQuad: easeInOutQuad, 43537 easeInCubic: easeInCubic, 43538 easeOutCubic: easeOutCubic, 43539 easeInOutCubic: easeInOutCubic, 43540 easeInQuart: easeInQuart, 43541 easeOutQuart: easeOutQuart, 43542 easeInOutQuart: easeInOutQuart, 43543 easeInQuint: easeInQuint, 43544 easeOutQuint: easeOutQuint, 43545 easeInOutQuint: easeInOutQuint, 43546 easeInSine: easeInSine, 43547 easeOutSine: easeOutSine, 43548 easeInOutSine: easeInOutSine, 43549 easeInExpo: easeInExpo, 43550 easeOutExpo: easeOutExpo, 43551 easeInOutExpo: easeInOutExpo, 43552 easeInCirc: easeInCirc, 43553 easeOutCirc: easeOutCirc, 43554 easeInOutCirc: easeInOutCirc, 43555 easeInElastic: easeInElastic, 43556 easeOutElastic: easeOutElastic, 43557 easeInOutElastic: easeInOutElastic, 43558 easeInBack: easeInBack, 43559 easeOutBack: easeOutBack, 43560 easeInOutBack: easeInOutBack, 43561 easeInBounce: easeInBounce, 43562 easeOutBounce: easeOutBounce, 43563 easeInOutBounce: easeInOutBounce 43564 }; 43565 43566}()); 43567 43568 43569(function(global) { 43570 43571 "use strict"; 43572 43573 /** 43574 * @name fabric 43575 * @namespace 43576 */ 43577 43578 var fabric = global.fabric || (global.fabric = { }), 43579 extend = fabric.util.object.extend, 43580 capitalize = fabric.util.string.capitalize, 43581 clone = fabric.util.object.clone, 43582 toFixed = fabric.util.toFixed, 43583 multiplyTransformMatrices = fabric.util.multiplyTransformMatrices; 43584 43585 fabric.SHARED_ATTRIBUTES = [ 43586 "transform", 43587 "fill", "fill-opacity", "fill-rule", 43588 "opacity", 43589 "stroke", "stroke-dasharray", "stroke-linecap", "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", "stroke-width" 43590 ]; 43591 43592 var attributesMap = { 43593 'fill-opacity': 'fillOpacity', 43594 'fill-rule': 'fillRule', 43595 'font-family': 'fontFamily', 43596 'font-size': 'fontSize', 43597 'font-style': 'fontStyle', 43598 'font-weight': 'fontWeight', 43599 'cx': 'left', 43600 'x': 'left',
43601 'r': 'radius', 43602 'stroke-dasharray': 'strokeDashArray', 43603 'stroke-linecap': 'strokeLineCap', 43604 'stroke-linejoin': 'strokeLineJoin', 43605 'stroke-miterlimit':'strokeMiterLimit', 43606 'stroke-opacity': 'strokeOpacity', 43607 'stroke-width': 'strokeWidth', 43608 'text-decoration': 'textDecoration', 43609 'cy': 'top', 43610 'y': 'top', 43611 'transform': 'transformMatrix' 43612 }; 43613 43614 var colorAttributes = { 43615 'stroke': 'strokeOpacity', 43616 'fill': 'fillOpacity' 43617 }; 43618 43619 function normalizeAttr(attr) { 43620 // transform attribute names 43621 if (attr in attributesMap) { 43622 return attributesMap[attr]; 43623 } 43624 return attr; 43625 } 43626 43627 function normalizeValue(attr, value, parentAttributes) { 43628 var isArray; 43629 43630 if ((attr === 'fill' || attr === 'stroke') && value === 'none') { 43631 value = ''; 43632 } 43633 else if (attr === 'fillRule') { 43634 value = (value === 'evenodd') ? 'destination-over' : value; 43635 } 43636 else if (attr === 'strokeDashArray') { 43637 value = value.replace(/,/g, ' ').split(/\s+/); 43638 } 43639 else if (attr === 'transformMatrix') { 43640 if (parentAttributes && parentAttributes.transformMatrix) { 43641 value = multiplyTransformMatrices( 43642 parentAttributes.transformMatrix, fabric.parseTransformAttribute(value)); 43643 } 43644 else { 43645 value = fabric.parseTransformAttribute(value); 43646 } 43647 } 43648 43649 isArray = Object.prototype.toString.call(value) === '[object Array]'; 43650 43651 // TODO: need to normalize em, %, pt, etc. to px (!) 43652 var parsed = isArray ? value.map(parseFloat) : parseFloat(value); 43653 43654 return (!isArray && isNaN(parsed) ? value : parsed); 43655 } 43656 43657 /** 43658 * @private 43659 * @param {Object} attributes Array of attributes to parse 43660 */ 43661 function _setStrokeFillOpacity(attributes) { 43662 for (var attr in colorAttributes) { 43663 43664 if (!attributes[attr] || typeof attributes[colorAttributes[attr]] === 'undefined') continue; 43665
43666 if (attributes[attr].indexOf('url(') === 0) continue; 43667 43668 var color = new fabric.Color(attributes[attr]); 43669 attributes[attr] = color.setAlpha(toFixed(color.getAlpha() * attributes[colorAttributes[attr]], 2)).toRgba(); 43670 43671 delete attributes[colorAttributes[attr]]; 43672 } 43673 return attributes; 43674 } 43675 43676 /** 43677 * Returns an object of attributes' name/value, given element and an array of attribute names; 43678 * Parses parent "g" nodes recursively upwards. 43679 * @static 43680 * @memberOf fabric 43681 * @param {DOMElement} element Element to parse 43682 * @param {Array} attributes Array of attributes to parse 43683 * @return {Object} object containing parsed attributes' names/values 43684 */ 43685 function parseAttributes(element, attributes) { 43686 43687 if (!element) { 43688 return; 43689 } 43690 43691 var value, 43692 parentAttributes = { }; 43693 43694 // if there's a parent container (`g` node), parse its attributes recursively upwards 43695 if (element.parentNode && /^g$/i.test(element.parentNode.nodeName)) { 43696 parentAttributes = fabric.parseAttributes(element.parentNode, attributes); 43697 } 43698 43699 var ownAttributes = attributes.reduce(function(memo, attr) { 43700 value = element.getAttribute(attr); 43701 if (value) { 43702 attr = normalizeAttr(attr); 43703 value = normalizeValue(attr, value, parentAttributes); 43704 43705 memo[attr] = value; 43706 } 43707 return memo; 43708 }, { }); 43709 43710 // add values parsed from style, which take precedence over attributes 43711 // (see: http://www.w3.org/TR/SVG/styling.html#UsingPresentationAttributes) 43712 43713 ownAttributes = extend(ownAttributes, 43714 extend(getGlobalStylesForElement(element), fabric.parseStyleAttribute(element))); 43715 return _setStrokeFillOpacity(extend(parentAttributes, ownAttributes)); 43716 } 43717 43718 /** 43719 * Parses "transform" attribute, returning an array of values 43720 * @static 43721 * @function 43722 * @memberOf fabric 43723 * @param attributeValue {String} string containing attribute value 43724 * @return {Array} array of 6 elements representing transformation matrix 43725 */ 43726 fabric.parseTransformAttribute = (function() { 43727 function rotateMatrix(matrix, args) { 43728 var angle = args[0]; 43729 43730 matrix[0] = Math.cos(angle); 43731 matrix[1] = Math.sin(angle); 43732 matrix[2] = -Math.sin(angle); 43733 matrix[3] = Math.cos(angle); 43734 } 43735 43736 function scaleMatrix(matrix, args) { 43737 var multiplierX = args[0], 43738 multiplierY = (args.length === 2) ? args[1] : args[0]; 43739 43740 matrix[0] = multiplierX; 43741 matrix[3] = multiplierY; 43742 } 43743 43744 function skewXMatrix(matrix, args) { 43745 matrix[2] = args[0]; 43746 } 43747 43748 function skewYMatrix(matrix, args) { 43749 matrix[1] = args[0]; 43750 } 43751 43752 function translateMatrix(matrix, args) { 43753 matrix[4] = args[0]; 43754 if (args.length === 2) { 43755 matrix[5] = args[1]; 43756 } 43757 } 43758 43759 // identity matrix 43760 var iMatrix = [ 43761 1, // a 43762 0, // b 43763 0, // c 43764 1, // d 43765 0, // e 43766 0 // f 43767 ], 43768 43769 // == begin transform regexp 43770 number = '(?:[-+]?\\d+(?:\\.\\d+)?(?:e[-+]?\\d+)?)', 43771 comma_wsp = '(?:\\s+,?\\s*|,\\s*)', 43772 43773 skewX = '(?:(skewX)\\s*\\(\\s*(' + number + ')\\s*\\))', 43774 skewY = '(?:(skewY)\\s*\\(\\s*(' + number + ')\\s*\\))', 43775 rotate = '(?:(rotate)\\s*\\(\\s*(' + number + ')(?:' + comma_wsp + '(' + number + ')' + comma_wsp + '(' + number + '))?\\s*\\))', 43776 scale = '(?:(scale)\\s*\\(\\s*(' + number + ')(?:' + comma_wsp + '(' + number + '))?\\s*\\))', 43777 translate = '(?:(translate)\\s*\\(\\s*(' + number + ')(?:' + comma_wsp + '(' + number + '))?\\s*\\))', 43778 43779 matrix = '(?:(matrix)\\s*\\(\\s*' + 43780 '(' + number + ')' + comma_wsp + 43781 '(' + number + ')' + comma_wsp + 43782 '(' + number + ')' + comma_wsp + 43783 '(' + number + ')' + comma_wsp + 43784 '(' + number + ')' + comma_wsp + 43785 '(' + number + ')' + 43786 '\\s*\\))', 43787 43788 transform = '(?:' + 43789 matrix + '|' + 43790 translate + '|' + 43791 scale + '|' + 43792 rotate + '|' + 43793 skewX + '|' + 43794 skewY + 43795 ')', 43796 43797 transforms = '(?:' + transform + '(?:' + comma_wsp + transform + ')*' + ')', 43798 43799 transform_list = '^\\s*(?:' + transforms + '?)\\s*$', 43800 43801 // http://www.w3.org/TR/SVG/coords.html#TransformAttribute 43802 reTransformList = new RegExp(transform_list), 43803 // == end transform regexp 43804 43805 reTransform = new RegExp(transform, 'g'); 43806 43807 return function(attributeValue) { 43808
43809 // start with identity matrix 43810 var matrix = iMatrix.concat(); 43811 var matrices = [ ]; 43812 43813 // return if no argument was given or 43814 // an argument does not match transform attribute regexp 43815 if (!attributeValue || (attributeValue && !reTransformList.test(attributeValue))) { 43816 return matrix; 43817 } 43818 43819 attributeValue.replace(reTransform, function(match) { 43820 43821 var m = new RegExp(transform).exec(match).filter(function (match) { 43822 return (match !== '' && match != null); 43823 }), 43824 operation = m[1], 43825 args = m.slice(2).map(parseFloat); 43826 43827 switch(operation) { 43828 case 'translate': 43829 translateMatrix(matrix, args); 43830 break; 43831 case 'rotate': 43832 rotateMatrix(matrix, args); 43833 break; 43834 case 'scale': 43835 scaleMatrix(matrix, args); 43836 break; 43837 case 'skewX': 43838 skewXMatrix(matrix, args); 43839 break; 43840 case 'skewY': 43841 skewYMatrix(matrix, args); 43842 break; 43843 case 'matrix': 43844 matrix = args; 43845 break; 43846 } 43847 43848 // snapshot current matrix into matrices array 43849 matrices.push(matrix.concat()); 43850 // reset 43851 matrix = iMatrix.concat(); 43852 }); 43853 43854 var combinedMatrix = matrices[0]; 43855 while (matrices.length > 1) { 43856 matrices.shift(); 43857 combinedMatrix = fabric.util.multiplyTransformMatrices(combinedMatrix, matrices[0]); 43858 } 43859 return combinedMatrix; 43860 }; 43861 })(); 43862 43863 /** 43864 * Parses "points" attribute, returning an array of values 43865 * @static 43866 * @memberOf fabric 43867 * @param points {String} points attribute string 43868 * @return {Array} array of points 43869 */ 43870 function parsePointsAttribute(points) { 43871 43872 // points attribute is required and must not be empty 43873 if (!points) return null; 43874 43875 points = points.trim(); 43876 var asPairs = points.indexOf(',') > -1; 43877 43878 points = points.split(/\s+/); 43879 var parsedPoints = [ ], i, len; 43880
43881 // points could look like "10,20 30,40" or "10 20 30 40" 43882 if (asPairs) { 43883 i = 0; 43884 len = points.length; 43885 for (; i < len; i++) { 43886 var pair = points[i].split(','); 43887 parsedPoints.push({ x: parseFloat(pair[0]), y: parseFloat(pair[1]) }); 43888 } 43889 } 43890 else { 43891 i = 0; 43892 len = points.length; 43893 for (; i < len; i+=2) { 43894 parsedPoints.push({ x: parseFloat(points[i]), y: parseFloat(points[i+1]) }); 43895 } 43896 } 43897 43898 // odd number of points is an error 43899 if (parsedPoints.length % 2 !== 0) { 43900 // return null; 43901 } 43902 43903 return parsedPoints; 43904 } 43905 43906 function parseFontDeclaration(value, oStyle) { 43907 43908 // TODO: support non-px font size 43909 var match = value.match(/(normal|italic)?\s*(normal|small-caps)?\s*(normal|bold|bolder|lighter|100|200|300|400|500|600|700|800|900)?\s*(\d+)px(?:\/(normal|[\d\.]+))?\s+(.*)/); 43910 43911 if (!match) return; 43912 43913 var fontStyle = match[1]; 43914 // Font variant is not used 43915 // var fontVariant = match[2]; 43916 var fontWeight = match[3]; 43917 var fontSize = match[4]; 43918 var lineHeight = match[5]; 43919 var fontFamily = match[6]; 43920 43921 if (fontStyle) { 43922 oStyle.fontStyle = fontStyle; 43923 } 43924 if (fontWeight) { 43925 oStyle.fontSize = isNaN(parseFloat(fontWeight)) ? fontWeight : parseFloat(fontWeight); 43926 } 43927 if (fontSize) { 43928 oStyle.fontSize = parseFloat(fontSize); 43929 } 43930 if (fontFamily) { 43931 oStyle.fontFamily = fontFamily; 43932 } 43933 if (lineHeight) { 43934 oStyle.lineHeight = lineHeight === 'normal' ? 1 : lineHeight; 43935 } 43936 } 43937 43938 /** 43939 * Parses "style" attribute, retuning an object with values 43940 * @static 43941 * @memberOf fabric 43942 * @param {SVGElement} element Element to parse 43943 * @return {Object} Objects with values parsed from style attribute of an element 43944 */ 43945 function parseStyleAttribute(element) { 43946 var oStyle = { }, 43947 style = element.getAttribute('style'), 43948 attr, value; 43949 43950 if (!style) return oStyle; 43951 43952 if (typeof style === 'string') { 43953 style.replace(/;$/, '').split(';').forEach(function (chunk) { 43954 var pair = chunk.split(':'); 43955 43956 attr = normalizeAttr(pair[0].trim().toLowerCase()); 43957 value = normalizeValue(attr, pair[1].trim()); 43958 43959 if (attr === 'font') { 43960 parseFontDeclaration(value, oStyle); 43961 } 43962 else { 43963 oStyle[attr] = value; 43964 } 43965 }); 43966 } 43967 else { 43968 for (var prop in style) { 43969 if (typeof style[prop] === 'undefined') continue; 43970 43971 attr = normalizeAttr(prop.toLowerCase()); 43972 value = normalizeValue(attr, style[prop]); 43973 43974 if (attr === 'font') { 43975 parseFontDeclaration(value, oStyle); 43976 } 43977 else { 43978 oStyle[attr] = value; 43979 } 43980 } 43981 } 43982 43983 return oStyle; 43984 } 43985 43986 function resolveGradients(instances) { 43987 for (var i = instances.length; i--; ) { 43988 var instanceFillValue = instances[i].get('fill'); 43989 43990 if (/^url\(/.test(instanceFillValue)) { 43991 43992 var gradientId = instanceFillValue.slice(5, instanceFillValue.length - 1); 43993 43994 if (fabric.gradientDefs[gradientId]) { 43995 instances[i].set('fill', 43996 fabric.Gradient.fromElement(fabric.gradientDefs[gradientId], instances[i])); 43997 } 43998 } 43999 } 44000 } 44001 44002 /** 44003 * Transforms an array of svg elements to corresponding fabric.*
44003instances 44004 * @static 44005 * @memberOf fabric 44006 * @param {Array} elements Array of elements to parse 44007 * @param {Function} callback Being passed an array of fabric instances (transformed from SVG elements) 44008 * @param {Object} [options] Options object 44009 * @param {Function} [reviver] Method for further parsing of SVG elements, called after each fabric object created. 44010 */ 44011 function parseElements(elements, callback, options, reviver) { 44012 var instances = new Array(elements.length), i = elements.length; 44013 44014 function checkIfDone() { 44015 if (--i === 0) { 44016 instances = instances.filter(function(el) { 44017 return el != null; 44018 }); 44019 resolveGradients(instances); 44020 callback(instances); 44021 } 44022 } 44023 44024 for (var index = 0, el, len = elements.length; index < len; index++) { 44025 el = elements[index]; 44026 var klass = fabric[capitalize(el.tagName)]; 44027 if (klass && klass.fromElement) { 44028 try { 44029 if (klass.async) { 44030 klass.fromElement(el, (function(index, el) { 44031 return function(obj) { 44032 reviver && reviver(el, obj); 44033 instances.splice(index, 0, obj); 44034 checkIfDone(); 44035 }; 44036 })(index, el), options); 44037 } 44038 else { 44039 var obj = klass.fromElement(el, options); 44040 reviver && reviver(el, obj); 44041 instances.splice(index, 0, obj); 44042 checkIfDone(); 44043 } 44044 } 44045 catch(err) { 44046 fabric.log(err); 44047 } 44048 } 44049 else { 44050 checkIfDone(); 44051 } 44052 } 44053 } 44054 44055 /** 44056 * Returns CSS rules for a given SVG document 44057 * @static 44058 * @function 44059 * @memberOf fabric 44060 * @param {SVGDocument} doc SVG document to parse 44061 * @return {Object} CSS rules of this document 44062 */ 44063 function getCSSRules(doc) { 44064 var styles = doc.getElementsByTagName('style'), 44065 allRules = { }, 44066 rules; 44067 44068 // very crude parsing of style contents 44069 for (var i = 0, len = styles.length; i < len; i++) { 44070 var styleContents = styles[0].textContent; 44071 44072 // remove comments 44073 styleContents = styleContents.replace(/\/\*[\s\S]*?\*\//g, ''); 44074 44075 rules = styleContents.match(/[^{]*\{[\s\S]*?\}/g); 44076 rules = rules.map(function(rule) { return rule.trim(); }); 44077
44078 rules.forEach(function(rule) { 44079 var match = rule.match(/([\s\S]*?)\s*\{([^}]*)\}/); 44080 rule = match[1]; 44081 var declaration = match[2].trim(), 44082 propertyValuePairs = declaration.replace(/;$/, '').split(/\s*;\s*/); 44083 44084 if (!allRules[rule]) { 44085 allRules[rule] = { }; 44086 } 44087 44088 for (var i = 0, len = propertyValuePairs.length; i < len; i++) { 44089 var pair = propertyValuePairs[i].split(/\s*:\s*/), 44090 property = pair[0], 44091 value = pair[1]; 44092 44093 allRules[rule][property] = value; 44094 } 44095 }); 44096 } 44097 44098 return allRules; 44099 } 44100 44101 /** 44102 * @private 44103 */ 44104 function getGlobalStylesForElement(element) { 44105 var nodeName = element.nodeName, 44106 className = element.getAttribute('class'), 44107 id = element.getAttribute('id'), 44108 styles = { }; 44109 44110 for (var rule in fabric.cssRules) { 44111 var ruleMatchesElement = (className && new RegExp('^\\.' + className).test(rule)) || 44112 (id && new RegExp('^#' + id).test(rule)) || 44113 (new RegExp('^' + nodeName).test(rule)); 44114 44115 if (ruleMatchesElement) { 44116 for (var property in fabric.cssRules[rule]) { 44117 styles[property] = fabric.cssRules[rule][property]; 44118 } 44119 } 44120 } 44121 44122 return styles; 44123 } 44124 44125 /** 44126 * Parses an SVG document, converts it to an array of corresponding fabric.*
44126instances and passes them to a callback 44127 * @static 44128 * @function 44129 * @memberOf fabric 44130 * @param {SVGDocument} doc SVG document to parse 44131 * @param {Function} callback Callback to call when parsing is finished; It's being passed an array of elements (parsed from a document). 44132 * @param {Function} [reviver] Method for further parsing of SVG elements, called after each fabric object created. 44133 */ 44134 fabric.parseSVGDocument = (function() { 44135 44136 var reAllowedSVGTagNames = /^(path|circle|polygon|polyline|ellipse|rect|line|image|text)$/; 44137 44138 // http://www.w3.org/TR/SVG/coords.html#ViewBoxAttribute 44139 // \d doesn't quite cut it (as we need to match an actual float number) 44140 44141 // matches, e.g.: +14.56e-12, etc. 44142 var reNum = '(?:[-+]?\\d+(?:\\.\\d+)?(?:e[-+]?\\d+)?)'; 44143 44144 var reViewBoxAttrValue = new RegExp( 44145 '^' + 44146 '\\s*(' + reNum + '+)\\s*,?' + 44147 '\\s*(' + reNum + '+)\\s*,?' + 44148 '\\s*(' + reNum + '+)\\s*,?' + 44149 '\\s*(' + reNum + '+)\\s*' + 44150 '$' 44151 ); 44152 44153 function hasAncestorWithNodeName(element, nodeName) { 44154 while (element && (element = element.parentNode)) { 44155 if (nodeName.test(element.nodeName)) { 44156 return true; 44157 } 44158 } 44159 return false; 44160 } 44161 44162 return function(doc, callback, reviver) { 44163 if (!doc) return; 44164 44165 var startTime = new Date(), 44166 descendants = fabric.util.toArray(doc.getElementsByTagName('*')); 44167 44168 if (descendants.length === 0) { 44169 // we're likely in node, where "o3-xml" library fails to gEBTN("*") 44170 // https://github.com/ajaxorg/node-o3-xml/issues/21 44171 descendants = doc.selectNodes("//*[name(.)!='svg']"); 44172 var arr = [ ]; 44173 for (var i = 0, len = descendants.length; i < len; i++) { 44174 arr[i] = descendants[i]; 44175 } 44176 descendants = arr; 44177 } 44178 44179 var elements = descendants.filter(function(el) { 44180 return reAllowedSVGTagNames.test(el.tagName) && 44181 !hasAncestorWithNodeName(el, /^(?:pattern|defs)$/); // http://www.w3.org/TR/SVG/struct.html#DefsElement 44182 }); 44183 44184 if (!elements || (elements && !elements.length)) return; 44185 44186 var viewBoxAttr = doc.getAttribute('viewBox'), 44187 widthAttr = doc.getAttribute('width'), 44188 heightAttr = doc.getAttribute('height'), 44189 width = null, 44190 height = null, 44191 minX, 44192 minY; 44193 44194 if (viewBoxAttr && (viewBoxAttr = viewBoxAttr.match(reViewBoxAttrValue))) { 44195 minX = parseInt(viewBoxAttr[1], 10); 44196 minY = parseInt(viewBoxAttr[2], 10); 44197 width = parseInt(viewBoxAttr[3], 10); 44198 height = parseInt(viewBoxAttr[4], 10); 44199 } 44200 44201 // values of width/height attributes overwrite those extracted from viewbox attribute 44202 width = widthAttr ? parseFloat(widthAttr) : width; 44203 height = heightAttr ? parseFloat(heightAttr) : height; 44204 44205 var options = { 44206 width: width, 44207 height: height 44208 }; 44209 44210 fabric.gradientDefs = fabric.getGradientDefs(doc); 44211 fabric.cssRules = getCSSRules(doc); 44212 44213 // Precedence of rules: style > class > attribute 44214 44215 fabric.parseElements(elements, function(instances) { 44216 fabric.documentParsingTime = new Date() - startTime; 44217 if (callback) { 44218 callback(instances, options); 44219 } 44220 }, clone(options), reviver); 44221 }; 44222 })(); 44223 44224 /** 44225 * Used for caching SVG documents (loaded via `fabric.Canvas#loadSVGFromURL`) 44226 * @namespace 44227 */ 44228 var svgCache = { 44229 44230 /** 44231 * @param {String} name 44232 * @param {Function} callback 44233 */ 44234 has: function (name, callback) { 44235 callback(false); 44236 }, 44237 44238 /** 44239 * @param {String} url 44240 * @param {Function} callback 44241 */ 44242 get: function () { 44243 /* NOOP */ 44244 }, 44245 44246 /** 44247 * @param {String} url 44248 * @param {Object} object 44249 */ 44250 set: function () { 44251 /* NOOP */ 44252 } 44253 }; 44254 44255 /** 44256 * Takes url corresponding to an SVG document, and parses it into a set of fabric objects. Note that SVG is fetched via XMLHttpRequest, so it needs to conform to SOP (Same Origin Policy) 44257 * @memberof fabric 44258 * @param {String} url 44259 * @param {Function} callback 44260 * @param {Function} [reviver] Method for further parsing of SVG elements, called after each fabric object created. 44261 */ 44262 function loadSVGFromURL(url, callback, reviver) { 44263 44264 url = url.replace(/^\n\s*/, '').trim(); 44265 44266 svgCache.has(url, function (hasUrl) { 44267 if (hasUrl) { 44268 svgCache.get(url, function (value) { 44269 var enlivedRecord = _enlivenCachedObject(value); 44270 callback(enlivedRecord.objects, enlivedRecord.options); 44271 }); 44272 } 44273 else { 44274 new fabric.util.request(url, { 44275 method: 'get', 44276 onComplete: onComplete 44277 }); 44278 } 44279 }); 44280 44281 function onComplete(r) { 44282 44283 var xml = r.responseXML; 44284 if (!xml.documentElement && fabric.window.ActiveXObject && r.responseText) { 44285 xml = new ActiveXObject('Microsoft.XMLDOM');
44286 xml.async = 'false'; 44287 //IE chokes on DOCTYPE 44288 xml.loadXML(r.responseText.replace(/<!DOCTYPE[\s\S]*?(\[[\s\S]*\])*?>/i,'')); 44289 } 44290 if (!xml.documentElement) return; 44291 44292 fabric.parseSVGDocument(xml.documentElement, function (results, options) { 44293 svgCache.set(url, { 44294 objects: fabric.util.array.invoke(results, 'toObject'), 44295 options: options 44296 }); 44297 callback(results, options); 44298 }, reviver); 44299 } 44300 } 44301 44302 /** 44303 * @private 44304 */ 44305 function _enlivenCachedObject(cachedObject) { 44306 44307 var objects = cachedObject.objects, 44308 options = cachedObject.options; 44309 44310 objects = objects.map(function (o) { 44311 return fabric[capitalize(o.type)].fromObject(o); 44312 }); 44313 44314 return ({ objects: objects, options: options }); 44315 } 44316 44317 /** 44318 * Takes string corresponding to an SVG document, and parses it into a set of fabric objects 44319 * @memberof fabric 44320 * @param {String} string 44321 * @param {Function} callback 44322 * @param {Function} [reviver] Method for further parsing of SVG elements, called after each fabric object created. 44323 */ 44324 function loadSVGFromString(string, callback, reviver) { 44325 string = string.trim(); 44326 var doc; 44327 if (typeof DOMParser !== 'undefined') { 44328 var parser = new DOMParser(); 44329 if (parser && parser.parseFromString) { 44330 doc = parser.parseFromString(string, 'text/xml'); 44331 } 44332 } 44333 else if (fabric.window.ActiveXObject) { 44334 doc = new ActiveXObject('Microsoft.XMLDOM'); 44335 doc.async = 'false'; 44336 //IE chokes on DOCTYPE 44337 doc.loadXML(string.replace(/<!DOCTYPE[\s\S]*?(\[[\s\S]*\])*?>/i,'')); 44338 } 44339 44340 fabric.parseSVGDocument(doc.documentElement, function (results, options) { 44341 callback(results, options); 44342 }, reviver); 44343 } 44344 44345 /** 44346 * Creates markup containing SVG font faces 44347 * @param {Array} objects Array of fabric objects 44348 * @return {String} 44349 */ 44350 function createSVGFontFacesMarkup(objects) { 44351 var markup = ''; 44352 44353 for (var i = 0, len = objects.length; i < len; i++) { 44354 if (objects[i].type !== 'text' || !objects[i].path) continue; 44355 44356 markup += [ 44357 '@font-face {', 44358 'font-family: ', objects[i].fontFamily, '; ', 44359 'src: url(\'', objects[i].path, '\')', 44360 '}' 44361 ].join(''); 44362 } 44363 44364 if (markup) { 44365 markup = [ 44366 '<style type="text/css">', 44367 '<![CDATA[', 44368 markup, 44369 ']]>', 44370 '</style>' 44371 ].join(''); 44372 } 44373 44374 return markup; 44375 } 44376 44377 /** 44378 * Creates markup containing SVG referenced elements like patterns, gradients etc. 44379 * @param {fabric.Canvas} canvas instance of fabric.Canvas 44380 * @return {String} 44381 */ 44382 function createSVGRefElementsMarkup(canvas) { 44383 var markup = ''; 44384 44385 if (canvas.backgroundColor && canvas.backgroundColor.source) { 44386 markup = [ 44387 '<pattern x="0" y="0" id="backgroundColorPattern" ', 44388 'width="', canvas.backgroundColor.source.width, 44389 '" height="', canvas.backgroundColor.source.height, 44390 '" patternUnits="userSpaceOnUse">', 44391 '<image x="0" y="0" ', 44392 'width="', canvas.backgroundColor.source.width, 44393 '" height="', canvas.backgroundColor.source.height, 44394 '" xlink:href="', canvas.backgroundColor.source.src, 44395 '"></image></pattern>' 44396 ].join(''); 44397 } 44398 44399 return markup; 44400 } 44401 44402 /** 44403 * Parses an SVG document, returning all of the gradient declarations found in it 44404 * @static 44405 * @function 44406 * @memberOf fabric 44407 * @param {SVGDocument} doc SVG document to parse 44408 * @return {Object} Gradient definitions; key corresponds to element id, value -- to gradient definition element 44409 */ 44410 function getGradientDefs(doc) { 44411 var linearGradientEls = doc.getElementsByTagName('linearGradient'), 44412 radialGradientEls = doc.getElementsByTagName('radialGradient'), 44413 el, i, 44414 gradientDefs = { }; 44415 44416 i = linearGradientEls.length; 44417 for (; i--; ) { 44418 el = linearGradientEls[i]; 44419 gradientDefs[el.getAttribute('id')] = el; 44420 } 44421 44422 i = radialGradientEls.length; 44423 for (; i--; ) { 44424 el = radialGradientEls[i]; 44425 gradientDefs[el.getAttribute('id')] = el; 44426 } 44427 44428 return gradientDefs; 44429 } 44430 44431 extend(fabric, { 44432 44433 parseAttributes: parseAttributes, 44434 parseElements: parseElements, 44435 parseStyleAttribute: parseStyleAttribute, 44436 parsePointsAttribute: parsePointsAttribute, 44437 getCSSRules: getCSSRules, 44438 44439 loadSVGFromURL: loadSVGFromURL, 44440 loadSVGFromString: loadSVGFromString, 44441 44442 createSVGFontFacesMarkup: createSVGFontFacesMarkup, 44443 createSVGRefElementsMarkup: createSVGRefElementsMarkup, 44444 44445 getGradientDefs: getGradientDefs 44446 }); 44447 44448})(typeof exports !== 'undefined' ? exports : this); 44449 44450 44451(function(global) { 44452 44453 "use strict"; 44454 44455 /* Adaptation of work of Kevin Lindsey ([email protected]) */ 44456 44457 var fabric = global.fabric || (global.fabric = { }); 44458 44459 if (fabric.Point) { 44460 fabric.warn('fabric.Point is already defined'); 44461 return; 44462 } 44463 44464 fabric.Point = Point; 44465 44466 /** 44467 * Point class 44468 * @class fabric.Point 44469 * @memberOf fabric 44470 * @constructor 44471 * @param {Number} x 44472 * @param {Number} y 44473 * @return {fabric.Point} thisArg 44474 */ 44475 function Point(x, y) { 44476 this.x = x; 44477 this.y = y; 44478 } 44479 44480 Point.prototype = /** @lends fabric.Point.prototype */ { 44481 44482 constructor: Point, 44483 44484 /** 44485 * Adds another point to this one and returns another one 44486 * @param {fabric.Point} that 44487 * @return {fabric.Point} new Point instance with added values 44488 */ 44489 add: function (that) { 44490 return new Point(this.x + that.x, this.y + that.y); 44491 }, 44492 44493 /** 44494 * Adds another point to this one 44495 * @param {fabric.Point} that 44496 * @return {fabric.Point} thisArg 44497 */ 44498 addEquals: function (that) { 44499 this.x += that.x; 44500 this.y += that.y; 44501 return this; 44502 }, 44503 44504 /** 44505 * Adds value to this point and returns a new one 44506 * @param {Number} scalar 44507 * @return {fabric.Point} new Point with added value 44508 */ 44509 scalarAdd: function (scalar) { 44510 return new Point(this.x + scalar, this.y + scalar); 44511 }, 44512 44513 /** 44514 * Adds value to this point 44515 * @param {Number} scalar 44516 * @param {fabric.Point} thisArg 44517 */ 44518 scalarAddEquals: function (scalar) { 44519 this.x += scalar; 44520 this.y += scalar; 44521 return this; 44522 }, 44523 44524 /** 44525 * Subtracts another point from this point and returns a new one 44526 * @param {fabric.Point} that 44527 * @return {fabric.Point} new Point object with subtracted values 44528 */ 44529 subtract: function (that) { 44530 return new Point(this.x - that.x, this.y - that.y); 44531 }, 44532 44533 /** 44534 * Subtracts another point from this point 44535 * @param {fabric.Point} that 44536 * @return {fabric.Point} thisArg 44537 */ 44538 subtractEquals: function (that) { 44539 this.x -= that.x; 44540 this.y -= that.y; 44541 return this; 44542 }, 44543 44544 /** 44545 * Subtracts value from this point and returns a new one 44546 * @param {Number} scalar 44547 * @return {fabric.Point} 44548 */ 44549 scalarSubtract: function (scalar) { 44550 return new Point(this.x - scalar, this.y - scalar); 44551 }, 44552 44553 /** 44554 * Subtracts value from this point 44555 * @param {Number} scalar 44556 * @return {fabric.Point} thisArg 44557 */ 44558 scalarSubtractEquals: function (scalar) { 44559 this.x -= scalar; 44560 this.y -= scalar; 44561 return this; 44562 }, 44563 44564 /**
vendor: 19,368 bytes, lines 44565-45278
44565 * Miltiplies this point by a value and returns a new one 44566 * @param {Number} scalar 44567 * @return {fabric.Point} 44568 */ 44569 multiply: function (scalar) { 44570 return new Point(this.x * scalar, this.y * scalar); 44571 }, 44572 44573 /** 44574 * Miltiplies this point by a value 44575 * @param {Number} scalar 44576 * @return {fabric.Point} thisArg 44577 */ 44578 multiplyEquals: function (scalar) { 44579 this.x *= scalar; 44580 this.y *= scalar; 44581 return this; 44582 }, 44583 44584 /** 44585 * Divides this point by a value and returns a new one 44586 * @param {Number} scalar 44587 * @return {fabric.Point} 44588 */ 44589 divide: function (scalar) { 44590 return new Point(this.x / scalar, this.y / scalar); 44591 }, 44592 44593 /** 44594 * Divides this point by a value 44595 * @param {Number} scalar 44596 * @return {fabric.Point} thisArg 44597 */ 44598 divideEquals: function (scalar) { 44599 this.x /= scalar; 44600 this.y /= scalar; 44601 return this; 44602 }, 44603 44604 /** 44605 * Returns true if this point is equal to another one 44606 * @param {fabric.Point} that 44607 * @return {Boolean} 44608 */ 44609 eq: function (that) { 44610 return (this.x === that.x && this.y === that.y); 44611 }, 44612 44613 /** 44614 * Returns true if this point is less than another one 44615 * @param {fabric.Point} that 44616 * @return {Boolean} 44617 */ 44618 lt: function (that) { 44619 return (this.x < that.x && this.y < that.y); 44620 }, 44621 44622 /** 44623 * Returns true if this point is less than or equal to another one 44624 * @param {fabric.Point} that 44625 * @return {Boolean} 44626 */ 44627 lte: function (that) { 44628 return (this.x <= that.x && this.y <= that.y); 44629 }, 44630 44631 /** 44632 44633 * Returns true if this point is greater another one 44634 * @param {fabric.Point} that 44635 * @return {Boolean} 44636 */ 44637 gt: function (that) { 44638 return (this.x > that.x && this.y > that.y); 44639 }, 44640 44641 /** 44642 * Returns true if this point is greater than or equal to another one 44643 * @param {fabric.Point} that 44644 * @return {Boolean} 44645 */ 44646 gte: function (that) { 44647 return (this.x >= that.x && this.y >= that.y); 44648 }, 44649 44650 /** 44651 * Returns new point which is the result of linear interpolation with this one and another one 44652 * @param {fabric.Point} that 44653 * @param {Number} t 44654 * @return {fabric.Point} 44655 */ 44656 lerp: function (that, t) { 44657 return new Point(this.x + (that.x - this.x) * t, this.y + (that.y - this.y) * t); 44658 }, 44659 44660 /** 44661 * Returns distance from this point and another one 44662 * @param {fabric.Point} that 44663 * @return {Number} 44664 */ 44665 distanceFrom: function (that) { 44666 var dx = this.x - that.x, 44667 dy = this.y - that.y; 44668 return Math.sqrt(dx * dx + dy * dy); 44669 }, 44670 44671 /** 44672 * Returns the point between this point and another one 44673 * @param {fabric.Point} that 44674 * @return {fabric.Point} 44675 */ 44676 midPointFrom: function (that) { 44677 return new Point(this.x + (that.x - this.x)/2, this.y + (that.y - this.y)/2); 44678 }, 44679 44680 /** 44681 * Returns a new point which is the min of this and another one 44682 * @param {fabric.Point} that 44683 * @return {fabric.Point} 44684 */ 44685 min: function (that) { 44686 return new Point(Math.min(this.x, that.x), Math.min(this.y, that.y)); 44687 }, 44688 44689 /** 44690 * Returns a new point which is the max of this and another one 44691 * @param {fabric.Point} that 44692 * @return {fabric.Point} 44693 */ 44694 max: function (that) { 44695 return new Point(Math.max(this.x, that.x), Math.max(this.y, that.y)); 44696 }, 44697 44698 /** 44699 * Returns string representation of this point 44700 * @return {String} 44701 */ 44702 toString: function () { 44703 return this.x + "," + this.y; 44704 }, 44705 44706 /** 44707 * Sets x/y of this point 44708 * @param {Number} x 44709 * @return {Number} y 44710 */ 44711 setXY: function (x, y) { 44712 this.x = x; 44713 this.y = y; 44714 }, 44715 44716 /** 44717 * Sets x/y of this point from another point 44718 * @param {fabric.Point} that 44719 */ 44720 setFromPoint: function (that) { 44721 this.x = that.x; 44722 this.y = that.y; 44723 }, 44724 44725 /** 44726 * Swaps x/y of this point and another point 44727 * @param {fabric.Point} that 44728 */ 44729 swap: function (that) { 44730 var x = this.x, 44731 y = this.y; 44732 this.x = that.x; 44733 this.y = that.y; 44734 that.x = x; 44735 that.y = y; 44736 } 44737 }; 44738 44739})(typeof exports !== 'undefined' ? exports : this); 44740 44741 44742(function(global) { 44743 44744 "use strict"; 44745 44746 /* Adaptation of work of Kevin Lindsey ([email protected]) */ 44747 44748 var fabric = global.fabric || (global.fabric = { }); 44749 44750 if (fabric.Intersection) { 44751 fabric.warn('fabric.Intersection is already defined'); 44752 return; 44753 } 44754 44755 /** 44756 * Intersection class 44757 * @class fabric.Intersection 44758 * @memberOf fabric 44759 * @constructor 44760 */ 44761 function Intersection(status) { 44762 this.status = status; 44763 this.points = []; 44764 } 44765 44766 fabric.Intersection = Intersection; 44767 44768 fabric.Intersection.prototype = /** @lends fabric.Intersection.prototype */ { 44769 44770 /** 44771 * Appends a point to intersection 44772 * @param {fabric.Point} point 44773 */ 44774 appendPoint: function (point) { 44775 this.points.push(point); 44776 }, 44777 44778 /** 44779 * Appends points to intersection 44780 * @param {Array} points 44781 */ 44782 appendPoints: function (points) { 44783 this.points = this.points.concat(points); 44784 } 44785 }; 44786 44787 /** 44788 * Checks if one line intersects another 44789 * @static 44790 * @param {fabric.Point} a1 44791 * @param {fabric.Point} a2 44792 * @param {fabric.Point} b1 44793 * @param {fabric.Point} b2 44794 * @return {fabric.Intersection} 44795 */ 44796 fabric.Intersection.intersectLineLine = function (a1, a2, b1, b2) { 44797 var result, 44798 ua_t = (b2.x - b1.x) * (a1.y - b1.y) - (b2.y - b1.y) * (a1.x - b1.x), 44799 ub_t = (a2.x - a1.x) * (a1.y - b1.y) - (a2.y - a1.y) * (a1.x - b1.x), 44800 u_b = (b2.y - b1.y) * (a2.x - a1.x) - (b2.x - b1.x) * (a2.y - a1.y); 44801 if (u_b !== 0) { 44802 var ua = ua_t / u_b, 44803 ub = ub_t / u_b; 44804 if (0 <= ua && ua <= 1 && 0 <= ub && ub <= 1) { 44805 result = new Intersection("Intersection"); 44806 result.points.push(new fabric.Point(a1.x + ua * (a2.x - a1.x), a1.y + ua * (a2.y - a1.y))); 44807 } 44808 else { 44809 result = new Intersection(); 44810 } 44811 } 44812 else { 44813 if (ua_t === 0 || ub_t === 0) { 44814 result = new Intersection("Coincident"); 44815 } 44816 else { 44817 result = new Intersection("Parallel"); 44818 } 44819 } 44820 return result; 44821 }; 44822 44823 /** 44824 * Checks if line intersects polygon 44825 * @static 44826 * @param {fabric.Point} a1 44827 * @param {fabric.Point} a2 44828 * @param {Array} points 44829 * @return {fabric.Intersection} 44830 */ 44831 fabric.Intersection.intersectLinePolygon = function(a1,a2,points){ 44832 var result = new Intersection(), 44833 length = points.length; 44834 44835 for (var i = 0; i < length; i++) { 44836 var b1 = points[i], 44837 b2 = points[(i+1) % length], 44838 inter = Intersection.intersectLineLine(a1, a2, b1, b2); 44839 44840 result.appendPoints(inter.points); 44841 } 44842 if (result.points.length > 0) { 44843 result.status = "Intersection"; 44844 } 44845 return result; 44846 }; 44847 44848 /** 44849 * Checks if polygon intersects another polygon 44850 * @static 44851 * @param {Array} points1 44852 * @param {Array} points2 44853 * @return {fabric.Intersection} 44854 */ 44855 fabric.Intersection.intersectPolygonPolygon = function (points1, points2) { 44856 var result = new Intersection(), 44857 length = points1.length; 44858 44859 for (var i = 0; i < length; i++) { 44860 var a1 = points1[i], 44861 a2 = points1[(i+1) % length], 44862 inter = Intersection.intersectLinePolygon(a1, a2, points2); 44863 44864 result.appendPoints(inter.points); 44865 } 44866 if (result.points.length > 0) { 44867 result.status = "Intersection"; 44868 } 44869 return result; 44870 }; 44871 44872 /** 44873 * Checks if polygon intersects rectangle 44874 * @static 44875 * @param {Array} points 44876 * @param {Number} r1 44877 * @param {Number} r2 44878 * @return {fabric.Intersection} 44879 */ 44880 fabric.Intersection.intersectPolygonRectangle = function (points, r1, r2) { 44881 var min = r1.min(r2), 44882 max = r1.max(r2), 44883 topRight = new fabric.Point(max.x, min.y), 44884 bottomLeft = new fabric.Point(min.x, max.y), 44885 inter1 = Intersection.intersectLinePolygon(min, topRight, points), 44886 inter2 = Intersection.intersectLinePolygon(topRight, max, points), 44887 inter3 = Intersection.intersectLinePolygon(max, bottomLeft, points), 44888 inter4 = Intersection.intersectLinePolygon(bottomLeft, min, points), 44889 result = new Intersection(); 44890 44891 result.appendPoints(inter1.points); 44892 result.appendPoints(inter2.points); 44893 result.appendPoints(inter3.points); 44894 result.appendPoints(inter4.points); 44895 44896 if (result.points.length > 0) { 44897 result.status = "Intersection"; 44898 } 44899 return result; 44900 }; 44901 44902})(typeof exports !== 'undefined' ? exports : this); 44903 44904 44905(function(global) { 44906 44907 "use strict"; 44908 44909 var fabric = global.fabric || (global.fabric = { }); 44910 44911 if (fabric.Color) { 44912 fabric.warn('fabric.Color is already defined.'); 44913 return; 44914 } 44915 44916 /** 44917 * Color class 44918 * The purpose of {@link fabric.Color} is to abstract and encapsulate common color operations; 44919 * {@link fabric.Color} is a constructor and creates instances of {@link fabric.Color} objects. 44920 * 44921 * @class fabric.Color 44922 * @param {String} color optional in hex or rgb(a) format 44923 * @return {fabric.Color} thisArg 44924 * @tutorial {@link http://fabricjs.com/fabric-intro-part-2/#colors} 44925 */ 44926 function Color(color) { 44927 if (!color) { 44928 this.setSource([0, 0, 0, 1]); 44929 } 44930 else { 44931 this._tryParsingColor(color); 44932 } 44933 } 44934 44935 fabric.Color = Color; 44936 44937 fabric.Color.prototype = /** @lends fabric.Color.prototype */ { 44938 44939 /** 44940 * @private 44941 * @param {String|Array} color Color value to parse 44942 */ 44943 _tryParsingColor: function(color) { 44944 var source; 44945 44946 if (color in Color.colorNameMap) { 44947 color = Color.colorNameMap[color]; 44948 } 44949 44950 source = Color.sourceFromHex(color); 44951 44952 if (!source) { 44953 source = Color.sourceFromRgb(color); 44954 } 44955 if (!source) { 44956 source = Color.sourceFromHsl(color); 44957 } 44958 if (source) { 44959 this.setSource(source); 44960 } 44961 }, 44962 44963 /** 44964 * Adapted from <a href="https://rawgithub.com/mjijackson/mjijackson.github.com/master/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript.html">https://github.com/mjijackson</a> 44965 * @private 44966 * @param {Number} r Red color value 44967 * @param {Number} g Green color value 44968 * @param {Number} b Blue color value 44969 * @return {Array} Hsl color 44970 */ 44971 _rgbToHsl: function(r, g, b) { 44972 r /= 255, g /= 255, b /= 255; 44973 44974 var h, s, l, 44975 max = fabric.util.array.max([r, g, b]), 44976 min = fabric.util.array.min([r, g, b]); 44977 44978 l = (max + min) / 2; 44979 44980 if (max === min) { 44981 h = s = 0; // achromatic 44982 } 44983 else { 44984 var d = max - min; 44985 s = l > 0.5 ? d / (2 - max - min) : d / (max + min); 44986 switch (max) { 44987 case r: 44988 h = (g - b) / d + (g < b ? 6 : 0); 44989 break; 44990 case g: 44991 h = (b - r) / d + 2; 44992 break; 44993 case b: 44994 h = (r - g) / d + 4; 44995 break; 44996 } 44997 h /= 6; 44998 } 44999 45000 return [ 45001 Math.round(h * 360), 45002 Math.round(s * 100), 45003 Math.round(l * 100) 45004 ]; 45005 }, 45006 45007 /** 45008 * Returns source of this color (where source is an array representation; ex: [200, 200, 100, 1]) 45009 * @return {Array} 45010 */ 45011 getSource: function() { 45012 return this._source; 45013 }, 45014 45015 /** 45016 * Sets source of this color (where source is an array representation; ex: [200, 200, 100, 1]) 45017 * @param {Array} source 45018 */ 45019 setSource: function(source) { 45020 this._source = source; 45021 }, 45022 45023 /** 45024 * Returns color represenation in RGB format 45025 * @return {String} ex: rgb(0-255,0-255,0-255) 45026 */ 45027 toRgb: function() { 45028 var source = this.getSource(); 45029 return 'rgb(' + source[0] + ',' + source[1] + ',' + source[2] + ')'; 45030 }, 45031 45032 /** 45033 * Returns color represenation in RGBA format 45034 * @return {String} ex: rgba(0-255,0-255,0-255,0-1) 45035 */ 45036 toRgba: function() { 45037 var source = this.getSource(); 45038 return 'rgba(' + source[0] + ',' + source[1] + ',' + source[2] + ',' + source[3] + ')'; 45039 }, 45040 45041 /** 45042 * Returns color represenation in HSL format 45043 * @return {String} ex: hsl(0-360,0%-100%,0%-100%) 45044 */ 45045 toHsl: function() { 45046 var source = this.getSource(), 45047 hsl = this._rgbToHsl(source[0], source[1], source[2]); 45048 45049 return 'hsl(' + hsl[0] + ',' + hsl[1] + '%,' + hsl[2] + '%)'; 45050 }, 45051 45052 /** 45053 * Returns color represenation in HSLA format 45054 * @return {String} ex: hsla(0-360,0%-100%,0%-100%,0-1) 45055 */ 45056 toHsla: function() { 45057 var source = this.getSource(), 45058 hsl = this._rgbToHsl(source[0], source[1], source[2]); 45059 45060 return 'hsla(' + hsl[0] + ',' + hsl[1] + '%,' + hsl[2] + '%,' + source[3] + ')'; 45061 }, 45062 45063 /** 45064 * Returns color represenation in HEX format 45065 * @return {String} ex: FF5555 45066 */ 45067 toHex: function() { 45068 var source = this.getSource(); 45069 45070 var r = source[0].toString(16); 45071 r = (r.length === 1) ? ('0' + r) : r; 45072 45073 var g = source[1].toString(16); 45074 g = (g.length === 1) ? ('0' + g) : g; 45075 45076 var b = source[2].toString(16); 45077 b = (b.length === 1) ? ('0' + b) : b; 45078 45079 return r.toUpperCase() + g.toUpperCase() + b.toUpperCase(); 45080 }, 45081 45082 /** 45083 * Gets value of alpha channel for this color 45084 * @return {Number} 0-1 45085 */ 45086 getAlpha: function() { 45087 return this.getSource()[3]; 45088 }, 45089 45090 /** 45091 * Sets value of alpha channel for this color 45092 * @param {Number} alpha Alpha value 0-1 45093 * @return {fabric.Color} thisArg 45094 */ 45095 setAlpha: function(alpha) { 45096 var source = this.getSource(); 45097 source[3] = alpha; 45098 this.setSource(source); 45099 return this; 45100 }, 45101 45102 /** 45103 * Transforms color to its grayscale representation 45104 * @return {fabric.Color} thisArg 45105 */ 45106 toGrayscale: function() { 45107 var source = this.getSource(), 45108 average = parseInt((source[0] * 0.3 + source[1] * 0.59 + source[2] * 0.11).toFixed(0), 10), 45109 currentAlpha = source[3]; 45110 this.setSource([average, average, average, currentAlpha]); 45111 return this; 45112 }, 45113 45114 /** 45115 * Transforms color to its black and white representation 45116 * @param {Number} threshold 45117 * @return {fabric.Color} thisArg 45118 */ 45119 toBlackWhite: function(threshold) { 45120 var source = this.getSource(), 45121 average = (source[0] * 0.3 + source[1] * 0.59 + source[2] * 0.11).toFixed(0), 45122 currentAlpha = source[3]; 45123 45124 threshold = threshold || 127; 45125 45126 average = (Number(average) < Number(threshold)) ? 0 : 255; 45127 this.setSource([average, average, average, currentAlpha]); 45128 return this; 45129 }, 45130 45131 /** 45132 * Overlays color with another color 45133 * @param {String|fabric.Color} otherColor 45134 * @return {fabric.Color} thisArg 45135 */ 45136 overlayWith: function(otherColor) { 45137 if (!(otherColor instanceof Color)) { 45138 otherColor = new Color(otherColor); 45139 } 45140 45141 var result = [], 45142 alpha = this.getAlpha(), 45143 otherAlpha = 0.5, 45144 source = this.getSource(), 45145 otherSource = otherColor.getSource(); 45146 45147 for (var i = 0; i < 3; i++) { 45148 result.push(Math.round((source[i] * (1 - otherAlpha)) + (otherSource[i] * otherAlpha))); 45149 } 45150 45151 result[3] = alpha; 45152 this.setSource(result); 45153 return this; 45154 } 45155 }; 45156 45157 /** 45158 * Regex matching color in RGB or RGBA formats (ex: rgb(0, 0, 0), rgba(255, 100, 10, 0.5), rgba( 255 , 100 , 10 , 0.5 ), rgb(1,1,1), rgba(100%, 60%, 10%, 0.5)) 45159 * @static 45160 * @field 45161 * @memberOf fabric.Color 45162 */ 45163 fabric.Color.reRGBa = /^rgba?\(\s*(\d{1,3}\%?)\s*,\s*(\d{1,3}\%?)\s*,\s*(\d{1,3}\%?)\s*(?:\s*,\s*(\d+(?:\.\d+)?)\s*)?\)$/; 45164 45165 /** 45166 * Regex matching color in HSL or HSLA formats (ex: hsl(200, 80%, 10%), hsla(300, 50%, 80%, 0.5), hsla( 300 , 50% , 80% , 0.5 )) 45167 * @static 45168 * @field 45169 * @memberOf fabric.Color 45170 */ 45171 fabric.Color.reHSLa = /^hsla?\(\s*(\d{1,3})\s*,\s*(\d{1,3}\%)\s*,\s*(\d{1,3}\%)\s*(?:\s*,\s*(\d+(?:\.\d+)?)\s*)?\)$/; 45172 45173 /** 45174 * Regex matching color in HEX format (ex: #FF5555, 010155, aff) 45175 * @static 45176 * @field 45177 * @memberOf fabric.Color 45178 */ 45179 fabric.Color.reHex = /^#?([0-9a-f]{6}|[0-9a-f]{3})$/i; 45180 45181 /** 45182 * Map of the 17 basic color names with HEX code 45183 * @static 45184 * @field 45185 * @memberOf fabric.Color 45186 * @see: http://www.w3.org/TR/CSS2/syndata.html#color-units 45187 */ 45188 fabric.Color.colorNameMap = { 45189 'aqua': '#00FFFF', 45190 'black': '#000000', 45191 'blue': '#0000FF', 45192 'fuchsia': '#FF00FF', 45193 'gray': '#808080', 45194 'green': '#008000', 45195 'lime': '#00FF00', 45196 'maroon': '#800000', 45197 'navy': '#000080', 45198 'olive': '#808000', 45199 'orange': '#FFA500', 45200 'purple': '#800080', 45201 'red': '#FF0000', 45202 'silver': '#C0C0C0', 45203 'teal': '#008080', 45204 'white': '#FFFFFF', 45205 'yellow': '#FFFF00' 45206 }; 45207 45208 /** 45209 * @private 45210 * @param {Number} p 45211 * @param {Number} q 45212 * @param {Number} t 45213 * @return {Number} 45214 */ 45215 function hue2rgb(p, q, t){ 45216 if (t < 0) t += 1; 45217 if (t > 1) t -= 1; 45218 if (t < 1/6) return p + (q - p) * 6 * t; 45219 if (t < 1/2) return q; 45220 if (t < 2/3) return p + (q - p) * (2/3 - t) * 6; 45221 return p; 45222 } 45223 45224 /** 45225 * Returns new color object, when given a color in RGB format 45226 * @memberOf fabric.Color 45227 * @param {String} color Color value ex: rgb(0-255,0-255,0-255) 45228 * @return {fabric.Color} 45229 */ 45230 fabric.Color.fromRgb = function(color) { 45231 return Color.fromSource(Color.sourceFromRgb(color)); 45232 }; 45233 45234 /** 45235 * Returns array represenatation (ex: [100, 100, 200, 1]) of a color that's in RGB or RGBA format 45236 * @memberOf fabric.Color 45237 * @param {String} color Color value ex: rgb(0-255,0-255,0-255), rgb(0%-100%,0%-100%,0%-100%) 45238 * @return {Array} source 45239 */ 45240 fabric.Color.sourceFromRgb = function(color) { 45241 var match = color.match(Color.reRGBa); 45242 if (match) { 45243 var r = parseInt(match[1], 10) / (/%$/.test(match[1]) ? 100 : 1) * (/%$/.test(match[1]) ? 255 : 1), 45244 g = parseInt(match[2], 10) / (/%$/.test(match[2]) ? 100 : 1) * (/%$/.test(match[2]) ? 255 : 1), 45245 b = parseInt(match[3], 10) / (/%$/.test(match[3]) ? 100 : 1) * (/%$/.test(match[3]) ? 255 : 1); 45246 45247 return [ 45248 parseInt(r, 10), 45249 parseInt(g, 10), 45250 parseInt(b, 10), 45251 match[4] ? parseFloat(match[4]) : 1 45252 ]; 45253 } 45254 }; 45255 45256 /** 45257 * Returns new color object, when given a color in RGBA format 45258 * @static 45259 * @function 45260 * @memberOf fabric.Color 45261 * @param {String} color 45262 * @return {fabric.Color} 45263 */ 45264 fabric.Color.fromRgba = Color.fromRgb; 45265 45266 /** 45267 * Returns new color object, when given a color in HSL format 45268 * @param {String} color Color value ex: hsl(0-260,0%-100%,0%-100%) 45269 * @memberOf fabric.Color 45270 * @return {fabric.Color} 45271 */ 45272 fabric.Color.fromHsl = function(color) { 45273 return Color.fromSource(Color.sourceFromHsl(color)); 45274 }; 45275 45276 /** 45277 * Returns array represenatation (ex: [100, 100, 200, 1]) of a color that's in HSL or HSLA format. 45278 * Adapted from <a href="https://rawgithub.com/mjijackson/mjijackson.github.com/master/2008/02/rgb-to-hsl-
45278and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript.html">https://github.com/mjijackson</a> 45279 * @memberOf fabric.Color 45280 * @param {String} color Color value ex: hsl(0-360,0%-100%,0%-100%) or hsla(0-360,0%-100%,0%-100%, 0-1) 45281 * @return {Array} source 45282 * @see http://http://www.w3.org/TR/css3-color/#hsl-color 45283 */ 45284 fabric.Color.sourceFromHsl = function(color) { 45285 var match = color.match(Color.reHSLa); 45286 if (!match) return; 45287 45288 var h = (((parseFloat(match[1]) % 360) + 360) % 360) / 360, 45289 s = parseFloat(match[2]) / (/%$/.test(match[2]) ? 100 : 1), 45290 l = parseFloat(match[3]) / (/%$/.test(match[3]) ? 100 : 1), 45291 r, g, b; 45292 45293 if (s === 0) { 45294 r = g = b = l; 45295 } 45296 else { 45297 var q = l <= 0.5 ? l * (s + 1) : l + s - l * s; 45298 var p = l * 2 - q; 45299 45300 r = hue2rgb(p, q, h + 1/3); 45301 g = hue2rgb(p, q, h); 45302 b = hue2rgb(p, q, h - 1/3); 45303 } 45304 45305 return [ 45306 Math.round(r * 255), 45307 Math.round(g * 255), 45308 Math.round(b * 255), 45309 match[4] ? parseFloat(match[4]) : 1 45310 ]; 45311 }; 45312 45313 /** 45314 * Returns new color object, when given a color in HSLA format 45315 * @static 45316 * @function 45317 * @memberOf fabric.Color 45318 * @param {String} color 45319 * @return {fabric.Color} 45320 */ 45321 fabric.Color.fromHsla = Color.fromHsl; 45322 45323 /** 45324 * Returns new color object, when given a color in HEX format 45325 * @static 45326 * @memberOf fabric.Color 45327 * @param {String} color Color value ex: FF5555 45328 * @return {fabric.Color} 45329 */ 45330 fabric.Color.fromHex = function(color) { 45331 return Color.fromSource(Color.sourceFromHex(color)); 45332 }; 45333 45334 /** 45335 * Returns array represenatation (ex: [100, 100, 200, 1]) of a color that's in HEX format 45336 * @static 45337 * @memberOf fabric.Color 45338 * @param {String} color ex: FF5555 45339 * @return {Array} source 45340 */ 45341 fabric.Color.sourceFromHex = function(color) { 45342 if (color.match(Color.reHex)) { 45343 var value = color.slice(color.indexOf('#') + 1), 45344 isShortNotation = (value.length === 3), 45345 r = isShortNotation ? (value.charAt(0) + value.charAt(0)) : value.substring(0, 2), 45346 g = isShortNotation ? (value.charAt(1) + value.charAt(1)) : value.substring(2, 4), 45347 b = isShortNotation ? (value.charAt(2) + value.charAt(2)) : value.substring(4, 6); 45348 45349 return [ 45350 parseInt(r, 16), 45351 parseInt(g, 16), 45352 parseInt(b, 16), 45353 1 45354 ]; 45355 } 45356 }; 45357 45358 /** 45359 * Returns new color object, when given color in array representation (ex: [200, 100, 100, 0.5]) 45360 * @static 45361 * @memberOf fabric.Color 45362 * @param {Array} source 45363 * @return {fabric.Color} 45364 */ 45365 fabric.Color.fromSource = function(source) { 45366 var oColor = new Color(); 45367 oColor.setSource(source); 45368 return oColor; 45369 }; 45370 45371})(typeof exports !== 'undefined' ? exports : this); 45372 45373 45374(function() { 45375 45376 /* _FROM_SVG_START_ */ 45377 function getColorStop(el) { 45378 var style = el.getAttribute('style'), 45379 offset = el.getAttribute('offset'), 45380 color, opacity; 45381 45382 // convert percents to absolute values 45383 offset = parseFloat(offset) / (/%$/.test(offset) ? 100 : 1); 45384 45385 if (style) { 45386 var keyValuePairs = style.split(/\s*;\s*/); 45387 45388 if (keyValuePairs[keyValuePairs.length-1] === '') { 45389 keyValuePairs.pop(); 45390 } 45391 45392 for (var i = keyValuePairs.length; i--; ) { 45393 45394 var split = keyValuePairs[i].split(/\s*:\s*/), 45395 key = split[0].trim(), 45396 value = split[1].trim(); 45397 45398 if (key === 'stop-color') { 45399 color = value; 45400 } 45401 else if (key === 'stop-opacity') { 45402 opacity = value; 45403 } 45404 } 45405 } 45406 45407 if (!color) { 45408 color = el.getAttribute('stop-color') || 'rgb(0,0,0)'; 45409 } 45410 if (!opacity) { 45411 opacity = el.getAttribute('stop-opacity'); 45412 } 45413 45414 // convert rgba color to rgb color - alpha value has no affect in svg 45415 color = new fabric.Color(color).toRgb(); 45416 45417 return { 45418 offset: offset, 45419 color: color, 45420 opacity: isNaN(parseFloat(opacity)) ? 1 : parseFloat(opacity) 45421 }; 45422 } 45423 /* _FROM_SVG_END_ */ 45424 45425 /** 45426 * Gradient class 45427 * @class fabric.Gradient 45428 * @tutorial {@link http://fabricjs.com/fabric-intro-part-2/#gradients} 45429 */ 45430 fabric.Gradient = fabric.util.createClass(/** @lends fabric.Gradient.prototype */ { 45431 45432 /** 45433 * Constructor 45434 * @param {Object} [options] Options object with type, coords, gradientUnits and colorStops 45435 * @return {fabric.Gradient} thisArg 45436 */ 45437 initialize: function(options) {
45438 options || (options = { }); 45439 45440 var coords = { }; 45441 45442 this.id = fabric.Object.__uid++; 45443 this.type = options.type || 'linear'; 45444 45445 coords = { 45446 x1: options.coords.x1 || 0, 45447 y1: options.coords.y1 || 0, 45448 x2: options.coords.x2 || 0, 45449 y2: options.coords.y2 || 0 45450 }; 45451 45452 if (this.type === 'radial') { 45453 coords.r1 = options.coords.r1 || 0; 45454 coords.r2 = options.coords.r2 || 0; 45455 } 45456 45457 this.coords = coords; 45458 this.gradientUnits = options.gradientUnits || 'objectBoundingBox'; 45459 this.colorStops = options.colorStops.slice(); 45460 }, 45461 45462 /** 45463 * Adds another colorStop 45464 * @param {Object} colorStop Object with offset and color 45465 * @return {fabric.Gradient} thisArg 45466 */ 45467 addColorStop: function(colorStop) { 45468 for (var position in colorStop) { 45469 var color = new fabric.Color(colorStop[position]); 45470 this.colorStops.push({offset: position, color: color.toRgb(), opacity: color.getAlpha()}); 45471 } 45472 return this; 45473 }, 45474 45475 /** 45476 * Returns object representation of a gradient 45477 * @return {Object} 45478 */ 45479 toObject: function() { 45480 return { 45481 type: this.type, 45482 coords: this.coords, 45483 gradientUnits: this.gradientUnits, 45484 colorStops: this.colorStops 45485 }; 45486 }, 45487 45488 /* _TO_SVG_START_ */ 45489 /** 45490 * Returns SVG representation of an gradient 45491 * @param {Object} object Object to create a gradient for 45492 * @param {Boolean} normalize Whether coords should be normalized 45493 * @return {String} SVG representation of an gradient (linear/radial) 45494 */ 45495 toSVG: function(object, normalize) { 45496 var coords = fabric.util.object.clone(this.coords), 45497 markup; 45498 45499 // colorStops must be sorted ascending 45500 this.colorStops.sort(function(a, b) { 45501 return a.offset - b.offset; 45502 }); 45503 45504 if (normalize && this.gradientUnits === 'userSpaceOnUse') { 45505 coords.x1 += object.width / 2; 45506 coords.y1 += object.height / 2; 45507 coords.x2 += object.width / 2; 45508 coords.y2 += object.height / 2; 45509 } 45510 else if (this.gradientUnits === 'objectBoundingBox') { 45511 _convertValuesToPercentUnits(object, coords); 45512 } 45513 45514 if (this.type === 'linear') { 45515 markup = [ 45516 '<linearGradient ', 45517 'id="SVGID_', this.id, 45518 '" gradientUnits="', this.gradientUnits, 45519 '" x1="', coords.x1, 45520 '" y1="', coords.y1, 45521 '" x2="', coords.x2, 45522 '" y2="', coords.y2, 45523 '">' 45524 ]; 45525 } 45526 else if (this.type === 'radial') { 45527 markup = [ 45528 '<radialGradient ', 45529 'id="SVGID_', this.id, 45530 '" gradientUnits="', this.gradientUnits, 45531 '" cx="', coords.x2, 45532 '" cy="', coords.y2, 45533 '" r="', coords.r2, 45534 '" fx="', coords.x1, 45535 '" fy="', coords.y1, 45536 '">' 45537 ]; 45538 } 45539 45540 for (var i = 0; i < this.colorStops.length; i++) { 45541 markup.push( 45542 '<stop ', 45543 'offset="', (this.colorStops[i].offset * 100) + '%', 45544 '" style="stop-color:', this.colorStops[i].color, 45545 (this.colorStops[i].opacity ? ';stop-opacity: ' + this.colorStops[i].opacity : ';'), 45546 '"/>' 45547 ); 45548 } 45549 45550 markup.push((this.type === 'linear' ? '</linearGradient>' : '</radialGradient>')); 45551 45552 return markup.join(''); 45553 }, 45554 /* _TO_SVG_END_ */ 45555 45556 /** 45557 * Returns an instance of CanvasGradient 45558 * @param {CanvasRenderingContext2D} ctx Context to render on 45559 * @return {CanvasGradient} 45560 */ 45561 toLive: function(ctx) { 45562 var gradient; 45563 45564 if (!this.type) return; 45565 45566 if (this.type === 'linear') { 45567 gradient = ctx.createLinearGradient( 45568 this.coords.x1, this.coords.y1, this.coords.x2, this.coords.y2); 45569 } 45570 else if (this.type === 'radial') { 45571 gradient = ctx.createRadialGradient( 45572 this.coords.x1, this.coords.y1, this.coords.r1, this.coords.x2, this.coords.y2, this.coords.r2); 45573 } 45574 45575 for (var i = 0, len = this.colorStops.length; i < len; i++) { 45576 var color = this.colorStops[i].color, 45577 opacity = this.colorStops[i].opacity, 45578 offset = this.colorStops[i].offset; 45579 45580 if (typeof opacity !== 'undefined') { 45581 color = new fabric.Color(color).setAlpha(opacity).toRgba(); 45582 } 45583 gradient.addColorStop(parseFloat(offset), color); 45584 } 45585 45586 return gradient; 45587 } 45588 }); 45589 45590 fabric.util.object.extend(fabric.Gradient, { 45591 45592 /* _FROM_SVG_START_ */ 45593 /** 45594 * Returns {@link fabric.Gradient} instance from an SVG element 45595 * @static 45596 * @memberof fabric.Gradient 45597 * @param {SVGGradientElement} el SVG gradient element 45598 * @param {fabric.Object} instance 45599 * @return {fabric.Gradient} Gradient instance 45600 * @see http://www.w3.org/TR/SVG/pservers.html#LinearGradientElement 45601 * @see http://www.w3.org/TR/SVG/pservers.html#RadialGradientElement 45602 */ 45603 fromElement: function(el, instance) { 45604 45605 /** 45606 * @example: 45607 * 45608 * <linearGradient id="linearGrad1"> 45609 * <stop offset="0%" stop-color="white"/> 45610 * <stop offset="100%" stop-color="black"/> 45611 * </linearGradient> 45612 * 45613 * OR 45614 * 45615 * <linearGradient id="linearGrad2"> 45616 * <stop offset="0" style="stop-color:rgb(255,255,255)"/> 45617 * <stop offset="1" style="stop-color:rgb(0,0,0)"/> 45618 * </linearGradient> 45619 * 45620 * OR 45621 * 45622 * <radialGradient id="radialGrad1"> 45623 * <stop offset="0%" stop-color="white" stop-opacity="1" /> 45624 * <stop offset="50%" stop-color="black" stop-opacity="0.5" /> 45625 * <stop offset="100%" stop-color="white" stop-opacity="1" /> 45626 * </radialGradient> 45627 * 45628 * OR 45629 * 45630 * <radialGradient id="radialGrad2"> 45631 * <stop offset="0" stop-color="rgb(255,255,255)" /> 45632 * <stop offset="0.5" stop-color="rgb(0,0,0)" /> 45633 * <stop offset="1" stop-color="rgb(255,255,255)" /> 45634 * </radialGradient> 45635 * 45636 */ 45637 45638 var colorStopEls = el.getElementsByTagName('stop'), 45639 type = (el.nodeName === 'linearGradient' ? 'linear' : 'radial'), 45640 gradientUnits = el.getAttribute('gradientUnits') || 'objectBoundingBox', 45641 colorStops = [], 45642 coords = { }; 45643 45644 if (type === 'linear') { 45645 coords = { 45646 x1: el.getAttribute('x1') || 0, 45647 y1: el.getAttribute('y1') || 0, 45648 x2: el.getAttribute('x2') || '100%', 45649 y2: el.getAttribute('y2') || 0 45650 }; 45651 } 45652 else if (type === 'radial') { 45653 coords = { 45654 x1: el.getAttribute('fx') || el.getAttribute('cx') || '50%', 45655 y1: el.getAttribute('fy') || el.getAttribute('cy') || '50%', 45656 r1: 0, 45657 x2: el.getAttribute('cx') || '50%', 45658 y2: el.getAttribute('cy') || '50%', 45659 r2: el.getAttribute('r') || '50%' 45660 }; 45661 } 45662 45663 for (var i = colorStopEls.length; i--; ) { 45664 colorStops.push(getColorStop(colorStopEls[i])); 45665 } 45666 45667 _convertPercentUnitsToValues(instance, coords); 45668 45669 return new fabric.Gradient({ 45670 type: type, 45671 coords: coords, 45672 gradientUnits: gradientUnits, 45673 colorStops: colorStops 45674 }); 45675 }, 45676 /* _FROM_SVG_END_ */ 45677 45678 /** 45679 * Returns {@link fabric.Gradient} instance from its object representation 45680 * @static 45681 * @memberof fabric.Gradient 45682 * @param {Object} obj 45683 * @param {Object} [options] Options object 45684 */ 45685 forObject: function(obj, options) {
45686 options || (options = { }); 45687 _convertPercentUnitsToValues(obj, options); 45688 return new fabric.Gradient(options); 45689 } 45690 }); 45691 45692 /** 45693 * @private 45694 */ 45695 function _convertPercentUnitsToValues(object, options) { 45696 for (var prop in options) { 45697 if (typeof options[prop] === 'string' && /^\d+%$/.test(options[prop])) { 45698 var percents = parseFloat(options[prop], 10); 45699 if (prop === 'x1' || prop === 'x2' || prop === 'r2') { 45700 options[prop] = fabric.util.toFixed(object.width * percents / 100, 2); 45701 } 45702 else if (prop === 'y1' || prop === 'y2') { 45703 options[prop] = fabric.util.toFixed(object.height * percents / 100, 2); 45704 } 45705 } 45706 // normalize rendering point (should be from top/left corner rather than center of the shape) 45707 if (prop === 'x1' || prop === 'x2') { 45708 options[prop] -= fabric.util.toFixed(object.width / 2, 2); 45709 } 45710 else if (prop === 'y1' || prop === 'y2') { 45711 options[prop] -= fabric.util.toFixed(object.height / 2, 2); 45712 } 45713 } 45714 } 45715 45716 /* _TO_SVG_START_ */ 45717 /** 45718 * @private 45719 */ 45720 function _convertValuesToPercentUnits(object, options) { 45721 for (var prop in options) { 45722 // normalize rendering point (should be from center rather than top/left corner of the shape) 45723 if (prop === 'x1' || prop === 'x2') { 45724 options[prop] += fabric.util.toFixed(object.width / 2, 2); 45725 } 45726 else if (prop === 'y1' || prop === 'y2') { 45727 options[prop] += fabric.util.toFixed(object.height / 2, 2); 45728 } 45729 // convert to percent units 45730 if (prop === 'x1' || prop === 'x2' || prop === 'r2') { 45731 options[prop] = fabric.util.toFixed(options[prop] / object.width * 100, 2) + '%'; 45732 } 45733 else if (prop === 'y1' || prop === 'y2') { 45734 options[prop] = fabric.util.toFixed(options[prop] / object.height * 100, 2) + '%'; 45735 } 45736 } 45737 } 45738 /* _TO_SVG_END_ */ 45739 45740})(); 45741 45742 45743/** 45744 * Pattern class 45745 * @class fabric.Pattern 45746 * @see {@link http://fabricjs.com/patterns/|Pattern demo} 45747 * @see {@link http://fabricjs.com/dynamic-patterns/|DynamicPattern demo} 45748 */ 45749fabric.Pattern = fabric.util.createClass(/** @lends fabric.Pattern.prototype */ { 45750 45751 /** 45752 * Repeat property of a pattern (one of repeat, repeat-x, repeat-y or no-repeat)
45753 * @type String 45754 * @default 45755 */ 45756 repeat: 'repeat', 45757 45758 /** 45759 * Pattern horizontal offset from object's left/top corner 45760 * @type Number 45761 * @default 45762 */ 45763 offsetX: 0, 45764 45765 /** 45766 * Pattern vertical offset from object's left/top corner 45767 * @type Number 45768 * @default 45769 */ 45770 offsetY: 0, 45771 45772 /** 45773 * Constructor 45774 * @param {Object} [options] Options object 45775 * @return {fabric.Pattern} thisArg 45776 */ 45777 initialize: function(options) { 45778 options || (options = { }); 45779 45780 this.id = fabric.Object.__uid++; 45781 45782 if (options.source) { 45783 if (typeof options.source === 'string') { 45784 // function string 45785 if (typeof fabric.util.getFunctionBody(options.source) !== 'undefined') { 45786 this.source = new Function(fabric.util.getFunctionBody(options.source)); 45787 } 45788 else { 45789 // img src string 45790 var _this = this; 45791 this.source = fabric.util.createImage(); 45792 fabric.util.loadImage(options.source, function(img) { 45793 _this.source = img; 45794 }); 45795 } 45796 } 45797 else { 45798 // img element 45799 this.source = options.source; 45800 } 45801 } 45802 if (options.repeat) { 45803 this.repeat = options.repeat; 45804 } 45805 if (options.offsetX) { 45806 this.offsetX = options.offsetX; 45807 } 45808 if (options.offsetY) { 45809 this.offsetY = options.offsetY; 45810 } 45811 }, 45812 45813 /** 45814 * Returns object representation of a pattern 45815 * @return {Object} Object representation of a pattern instance 45816 */ 45817 toObject: function() { 45818 45819 var source; 45820 45821 // callback 45822 if (typeof this.source === 'function') { 45823 source = String(this.source); 45824 } 45825 // <img> element 45826 else if (typeof this.source.src === 'string') { 45827 source = this.source.src; 45828 } 45829 45830 return { 45831 source: source, 45832 repeat: this.repeat, 45833 offsetX: this.offsetX, 45834 offsetY: this.offsetY 45835 }; 45836 }, 45837 45838 /* _TO_SVG_START_ */ 45839 /** 45840 * Returns SVG representation of a pattern 45841 * @param {fabric.Object} object 45842 * @return {String} SVG representation of a pattern 45843 */ 45844 toSVG: function(object) { 45845 var patternSource = typeof this.source === 'function' ? this.source() : this.source; 45846 var patternWidth = patternSource.width / object.getWidth(); 45847 var patternHeight = patternSource.height / object.getHeight(); 45848 var patternImgSrc = ''; 45849 45850 if (patternSource.src) { 45851 patternImgSrc = patternSource.src; 45852 } 45853 else if (patternSource.toDataURL) { 45854 patternImgSrc = patternSource.toDataURL(); 45855 } 45856 45857 return '<pattern id="SVGID_' + this.id + 45858 '" x="' + this.offsetX + 45859 '" y="' + this.offsetY + 45860 '" width="' + patternWidth + 45861 '" height="' + patternHeight + '">' + 45862 '<image x="0" y="0"' + 45863 ' width="' + patternSource.width + 45864 '" height="' + patternSource.height + 45865 '" xlink:href="' + patternImgSrc + 45866 '"></image>' + 45867 '</pattern>'; 45868 }, 45869 /* _TO_SVG_END_ */ 45870 45871 /** 45872 * Returns an instance of CanvasPattern 45873 * @param {CanvasRenderingContext2D} ctx Context to create pattern 45874 * @return {CanvasPattern} 45875 */ 45876 toLive: function(ctx) { 45877 var source = typeof this.source === 'function' ? this.source() : this.source; 45878 return ctx.createPattern(source, this.repeat); 45879 } 45880}); 45881 45882 45883(function(global) { 45884 45885 "use strict"; 45886 45887 var fabric = global.fabric || (global.fabric = { }); 45888 45889 if (fabric.Shadow) { 45890 fabric.warn('fabric.Shadow is already defined.'); 45891 return; 45892 } 45893 45894 /** 45895 * Shadow class 45896 * @class fabric.Shadow 45897 * @see {@link http://fabricjs.com/shadows/|Shadow demo} 45898 */ 45899 fabric.Shadow = fabric.util.createClass(/** @lends fabric.Shadow.prototype */ { 45900 45901 /** 45902 * Shadow color
45903 * @type String 45904 * @default 45905 */ 45906 color: 'rgb(0,0,0)', 45907 45908 /** 45909 * Shadow blur 45910 * @type Number 45911 */ 45912 blur: 0, 45913 45914 /** 45915 * Shadow horizontal offset 45916 * @type Number 45917 * @default 45918 */ 45919 offsetX: 0, 45920 45921 /** 45922 * Shadow vertical offset 45923 * @type Number 45924 * @default 45925 */ 45926 offsetY: 0, 45927 45928 /** 45929 * Whether the shadow should affect stroke operations 45930 * @type Boolean 45931 * @default 45932 */ 45933 affectStroke: false, 45934 45935 /** 45936 * Constructor 45937 * @param {Object|String} [options] Options object with any of color, blur, offsetX, offsetX properties or string (e.g. "rgba(0,0,0,0.2) 2px 2px 10px, "2px 2px 10px rgba(0,0,0,0.2)") 45938 * @return {fabric.Shadow} thisArg 45939 */ 45940 initialize: function(options) { 45941 if (typeof options === 'string') { 45942 options = this._parseShadow(options); 45943 } 45944 45945 for (var prop in options) { 45946 this[prop] = options[prop]; 45947 } 45948 45949 this.id = fabric.Object.__uid++; 45950 }, 45951 45952 /** 45953 * @private 45954 * @param {String} shadow Shadow value to parse 45955 * @return {Object} Shadow object with color, offsetX, offsetY and blur 45956 */ 45957 _parseShadow: function(shadow) { 45958 var shadowStr = shadow.trim(); 45959 45960 var offsetsAndBlur = fabric.Shadow.reOffsetsAndBlur.exec(shadowStr) || [ ], 45961 color = shadowStr.replace(fabric.Shadow.reOffsetsAndBlur, '') || 'rgb(0,0,0)'; 45962 45963 return { 45964 color: color.trim(), 45965 offsetX: parseInt(offsetsAndBlur[1], 10) || 0, 45966 offsetY: parseInt(offsetsAndBlur[2], 10) || 0, 45967 blur: parseInt(offsetsAndBlur[3], 10) || 0 45968 }; 45969 }, 45970 45971 /** 45972 * Returns a string representation of an instance 45973 * @see http://www.w3.org/TR/css-text-decor-3/#text-shadow 45974 * @return {String} Returns CSS3 text-shadow declaration 45975 */ 45976 toString: function() { 45977 return [this.offsetX, this.offsetY, this.blur, this.color].join('px '); 45978 }, 45979 45980 /* _TO_SVG_START_ */ 45981 /** 45982 * Returns SVG representation of a shadow 45983 * @param {fabric.Object} object 45984 * @return {String} SVG representation of a shadow 45985 */ 45986 toSVG: function(object) { 45987 var mode = 'SourceAlpha'; 45988 45989 if (object && (object.fill === this.color || object.stroke === this.color)) { 45990 mode = 'SourceGraphic'; 45991 } 45992 45993 return ( 45994 '<filter id="SVGID_' + this.id + '" y="-40%" height="180%">' + 45995 '<feGaussianBlur in="' + mode + '" stdDeviation="' + 45996 (this.blur ? this.blur / 3 : 0) + 45997 '"></feGaussianBlur>' + 45998 '<feOffset dx="' + this.offsetX + '" dy="' + this.offsetY + '"></feOffset>' + 45999 '<feMerge>' + 46000 '<feMergeNode></feMergeNode>' + 46001 '<feMergeNode in="SourceGraphic"></feMergeNode>' + 46002 '</feMerge>' + 46003 '</filter>'); 46004 }, 46005 /* _TO_SVG_END_ */ 46006 46007 /** 46008 * Returns object representation of a shadow 46009 * @return {Object} Object representation of a shadow instance 46010 */ 46011 toObject: function() { 46012 return { 46013 color: this.color, 46014 blur: this.blur, 46015 offsetX: this.offsetX, 46016 offsetY: this.offsetY 46017 }; 46018 } 46019 }); 46020 46021 /** 46022 * Regex matching shadow offsetX, offsetY and blur (ex: "2px 2px 10px rgba(0,0,0,0.2)", "rgb(0,255,0) 2px 2px") 46023 * @static 46024 * @field 46025 * @memberOf fabric.Shadow 46026 */ 46027 fabric.Shadow.reOffsetsAndBlur = /(?:\s|^)(-?\d+(?:px)?(?:\s?|$))?(-?\d+(?:px)?(?:\s?|$))?(\d+(?:px)?)?(?:\s?|$)(?:$|\s)/; 46028 46029})(typeof exports !== 'undefined' ? exports : this); 46030 46031 46032(function () { 46033 46034 "use strict"; 46035 46036 if (fabric.StaticCanvas) { 46037 fabric.warn('fabric.StaticCanvas is already defined.'); 46038 return; 46039 } 46040 46041 // aliases for faster resolution 46042 var extend = fabric.util.object.extend, 46043 getElementOffset = fabric.util.getElementOffset, 46044 removeFromArray = fabric.util.removeFromArray, 46045 removeListener = fabric.util.removeListener, 46046 46047 CANVAS_INIT_ERROR = new Error('Could not initialize `canvas` element'); 46048 46049 /** 46050 * Static canvas class 46051 * @class fabric.StaticCanvas 46052 * @mixes fabric.Collection 46053 * @mixes fabric.Observable 46054 * @see {@link http://fabricjs.com/static_canvas/|StaticCanvas demo} 46055 * @fires before:render 46056 * @fires after:render 46057 * @fires canvas:cleared 46058 * @fires object:added 46059 * @fires object:removed 46060 */ 46061 fabric.StaticCanvas = fabric.util.createClass(/** @lends fabric.StaticCanvas.prototype */ { 46062 46063 /** 46064 * Constructor 46065 * @param {HTMLElement | String} el <canvas> element to initialize instance on 46066 * @param {Object} [options] Options object 46067 * @return {Object} thisArg 46068 */ 46069 initialize: function(el, options) {
46070 options || (options = { }); 46071 46072 this._initStatic(el, options); 46073 fabric.StaticCanvas.activeInstance = this; 46074 }, 46075 46076 /** 46077 * Background color of canvas instance 46078 * @type String 46079 * @default 46080 */ 46081 backgroundColor: '', 46082 46083 /** 46084 * Background image of canvas instance 46085 * Should be set via {@link fabric.StaticCanvas#setBackgroundImage} 46086 * @type String 46087 * @default 46088 */ 46089 backgroundImage: '', 46090 46091 /** 46092 * Opacity of the background image of the canvas instance 46093 * @type Float 46094 * @default 46095 */ 46096 backgroundImageOpacity: 1, 46097 46098 /** 46099 * Indicates whether the background image should be stretched to fit the 46100 * dimensions of the canvas instance. 46101 * @type Boolean 46102 * @default 46103 */ 46104 backgroundImageStretch: true, 46105 46106 /** 46107 * Overlay image of canvas instance 46108 * Should be set via {@link fabric.StaticCanvas#setOverlayImage} 46109 * @type String 46110 * @default 46111 */ 46112 overlayImage: '', 46113 46114 /** 46115 * Left offset of overlay image (if present) 46116 * @type Number 46117 * @default 46118 */ 46119 overlayImageLeft: 0, 46120 46121 /** 46122 * Top offset of overlay image (if present) 46123 * @type Number 46124 * @default 46125 */ 46126 overlayImageTop: 0, 46127 46128 /** 46129 * Indicates whether toObject/toDatalessObject should include default values 46130 * @type Boolean 46131 * @default 46132 */ 46133 includeDefaultValues: true, 46134 46135 /** 46136 * Indicates whether objects' state should be saved 46137 * @type Boolean 46138 * @default 46139 */ 46140 stateful: true, 46141 46142 /** 46143 * Indicates whether {@link fabric.Collection.add}, {@link fabric.Collection.insertAt} and {@link fabric.Collection.remove} should also re-render canvas. 46144 * Disabling this option could give a great performance boost when adding/removing a lot of objects to/from canvas at once 46145 * (followed by a manual rendering after addition/deletion) 46146 * @type Boolean 46147 * @default 46148 */ 46149 renderOnAddRemove: true, 46150 46151 /** 46152 * Function that determines clipping of entire canvas area 46153 * Being passed context as first argument. See clipping canvas area in {@link https://github.com/kangax/fabric.js/wiki/FAQ} 46154 * @type Function 46155 * @default 46156 */ 46157 clipTo: null, 46158 46159 /** 46160 * Indicates whether object controls (borders/controls) are rendered above overlay image 46161 * @type Boolean 46162 * @default 46163 */ 46164 controlsAboveOverlay: false, 46165 46166 /** 46167 * Indicates whether the browser can be scrolled when using a touchscreen and dragging on the canvas 46168 * @type Boolean 46169 * @default 46170 */ 46171 allowTouchScrolling: false, 46172 46173 /** 46174 * Callback; invoked right before object is about to be scaled/rotated 46175 * @param {fabric.Object} target Object that's about to be scaled/rotated 46176 */ 46177 onBeforeScaleRotate: function () { 46178 /* NOOP */ 46179 }, 46180 46181 /** 46182 * @private 46183 * @param {HTMLElement | String} el <canvas> element to initialize instance on 46184 * @param {Object} [options] Options object 46185 */ 46186 _initStatic: function(el, options) { 46187 this._objects = []; 46188 46189 this._createLowerCanvas(el); 46190 this._initOptions(options); 46191 46192 if (options.overlayImage) { 46193 this.setOverlayImage(options.overlayImage, this.renderAll.bind(this)); 46194 } 46195 if (options.backgroundImage) { 46196 this.setBackgroundImage(options.backgroundImage, this.renderAll.bind(this)); 46197 } 46198 if (options.backgroundColor) { 46199 this.setBackgroundColor(options.backgroundColor, this.renderAll.bind(this)); 46200 } 46201 this.calcOffset(); 46202 }, 46203 46204 /** 46205 * Calculates canvas element offset relative to the document 46206 * This method is also attached as "resize" event handler of window 46207 * @return {fabric.Canvas} instance 46208 * @chainable 46209 */ 46210 calcOffset: function () { 46211 this._offset = getElementOffset(this.lowerCanvasEl); 46212 return this; 46213 }, 46214 46215 /** 46216 * Sets {@link fabric.StaticCanvas#overlayImage|overlay image} for this canvas 46217 * @param {String} url url of an image to set overlay to 46218 * @param {Function} callback callback to invoke when image is loaded and set as an overlay 46219 * @param {Object} [options] Optional options to set for the overlay image 46220 * @param {Number} [options.overlayImageLeft] {@link fabric.StaticCanvas#overlayImageLeft|Left offset} of overlay image 46221 * @param {Number} [options.overlayImageTop] {@link fabric.StaticCanvas#overlayImageTop|Top offset} of overlay image 46222 * @return {fabric.Canvas} thisArg 46223 * @chainable 46224 * @see {@link http://jsfiddle.net/fabricjs/MnzHT/|jsFiddle demo} 46225 * @example <caption>Normal overlayImage</caption> 46226 * canvas.setOverlayImage('http://fabricjs.com/assets/jail_cell_bars.png', canvas.renderAll.bind(canvas)); 46227 * @example <caption>Displaced overlayImage (left and top != 0)</caption> 46228 * canvas.setOverlayImage('http://fabricjs.com/assets/jail_cell_bars.png', canvas.renderAll.bind(canvas), { 46229 * overlayImageLeft: 100, 46230 * overlayImageTop: 100 46231 * }); 46232 */ 46233 setOverlayImage: function (url, callback, options) { // TODO (kangax): test callback 46234 fabric.util.loadImage(url, function(img) { 46235 this.overlayImage = img; 46236 if (options && ('overlayImageLeft' in options)) { 46237 this.overlayImageLeft = options.overlayImageLeft; 46238 } 46239 if (options && ('overlayImageTop' in options)) { 46240 this.overlayImageTop = options.overlayImageTop; 46241 } 46242 callback && callback(); 46243 }, this); 46244 46245 return this; 46246 }, 46247 46248 /** 46249 * Sets {@link fabric.StaticCanvas#backgroundImage|background image} for this canvas 46250 * @param {String} url URL of an image to set background to 46251 * @param {Function} callback callback to invoke when image is loaded and set as background 46252 * @param {Object} [options] Optional options to set for the background image 46253 * @param {Float} [options.backgroundImageOpacity] {@link fabric.StaticCanvas#backgroundImageOpacity|Opacity} of the background image of the canvas instance 46254 * @param {Boolean} [options.backgroundImageStretch] Indicates whether the background image should be {@link fabric.StaticCanvas#backgroundImageStretch|strechted} to fit the canvas 46255 * @return {fabric.Canvas} thisArg 46256 * @chainable 46257 * @see {@link http://jsfiddle.net/fabricjs/YH9yD/|jsFiddle demo} 46258 * @example <caption>Normal backgroundImage</caption>
46259 * canvas.setBackgroundImage('http://fabricjs.com/assets/jail_cell_bars.png', canvas.renderAll.bind(canvas)); 46260 * @example <caption>Stretched backgroundImage with opacity</caption> 46261 * canvas.setBackgroundImage('http://fabricjs.com/assets/jail_cell_bars.png', canvas.renderAll.bind(canvas), { 46262 * backgroundImageOpacity: 0.5, 46263 * backgroundImageStretch: true 46264 * }); 46265 */ 46266 setBackgroundImage: function (url, callback, options) { 46267 fabric.util.loadImage(url, function(img) { 46268 this.backgroundImage = img; 46269 if (options && ('backgroundImageOpacity' in options)) { 46270 this.backgroundImageOpacity = options.backgroundImageOpacity; 46271 } 46272 if (options && ('backgroundImageStretch' in options)) { 46273 this.backgroundImageStretch = options.backgroundImageStretch; 46274 } 46275 callback && callback(); 46276 }, this); 46277 46278 return this; 46279 }, 46280 46281 /** 46282 * Sets {@link fabric.StaticCanvas#backgroundColor|background color} for this canvas 46283 * @param {String|fabric.Pattern} backgroundColor Color or pattern to set background color to 46284 * @param {Function} callback callback to invoke when background color is set 46285 * @return {fabric.Canvas} thisArg 46286 * @chainable 46287 * @see {@link http://jsfiddle.net/fabricjs/hXzvk/|jsFiddle demo} 46288 * @example <caption>Normal backgroundColor - color value</caption> 46289 * canvas.setBackgroundColor('rgba(255, 73, 64, 0.6)', canvas.renderAll.bind(canvas)); 46290 * @example <caption>fabric.Pattern used as backgroundColor</caption> 46291 * canvas.setBackgroundColor({ 46292 * source: 'http://fabricjs.com/assets/escheresque_ste.png' 46293 * }, canvas.renderAll.bind(canvas)); 46294 */ 46295 setBackgroundColor: function(backgroundColor, callback) { 46296 if (backgroundColor.source) { 46297 var _this = this; 46298 fabric.util.loadImage(backgroundColor.source, function(img) { 46299 _this.backgroundColor = new fabric.Pattern({ 46300 source: img, 46301 repeat: backgroundColor.repeat 46302 }); 46303 callback && callback(); 46304 }); 46305 } 46306 else { 46307 this.backgroundColor = backgroundColor; 46308 callback && callback(); 46309 } 46310 46311 return this; 46312 }, 46313 46314 /** 46315 * @private 46316 */ 46317 _createCanvasElement: function() { 46318 var element = fabric.document.createElement('canvas'); 46319 if (!element.style) { 46320 element.style = { }; 46321 } 46322 if (!element) { 46323 throw CANVAS_INIT_ERROR; 46324 } 46325 this._initCanvasElement(element); 46326 return element; 46327 }, 46328 46329 /** 46330 * @private 46331 * @param {HTMLElement} element 46332 */ 46333 _initCanvasElement: function(element) { 46334 fabric.util.createCanvasElement(element); 46335 46336 if (typeof element.getContext === 'undefined') { 46337 throw CANVAS_INIT_ERROR; 46338 } 46339 }, 46340 46341 /** 46342 * @private 46343 * @param {Object} [options] Options object 46344 */ 46345 _initOptions: function (options) { 46346 for (var prop in options) { 46347 this[prop] = options[prop]; 46348 } 46349 46350 this.width = parseInt(this.lowerCanvasEl.width, 10) || 0; 46351 this.height = parseInt(this.lowerCanvasEl.height, 10) || 0; 46352 46353 if (!this.lowerCanvasEl.style) return; 46354 46355 this.lowerCanvasEl.style.width = this.width + 'px'; 46356 this.lowerCanvasEl.style.height = this.height + 'px'; 46357 }, 46358 46359 /** 46360 * Creates a bottom canvas 46361 * @private 46362 * @param {HTMLElement} [canvasEl] 46363 */ 46364 _createLowerCanvas: function (canvasEl) { 46365 this.lowerCanvasEl = fabric.util.getById(canvasEl) || this._createCanvasElement(); 46366 this._initCanvasElement(this.lowerCanvasEl); 46367 46368 fabric.util.addClass(this.lowerCanvasEl, 'lower-canvas'); 46369 46370 if (this.interactive) { 46371 this._applyCanvasStyle(this.lowerCanvasEl); 46372 } 46373 46374 this.contextContainer = this.lowerCanvasEl.getContext('2d'); 46375 }, 46376 46377 /** 46378 * Returns canvas width (in px) 46379 * @return {Number} 46380 */ 46381 getWidth: function () { 46382 return this.width; 46383 }, 46384 46385 /** 46386 * Returns canvas height (in px) 46387 * @return {Number} 46388 */ 46389 getHeight: function () { 46390 return this.height; 46391 }, 46392 46393 /** 46394 * Sets width of this canvas instance 46395 * @param {Number} width value to set width to 46396 * @return {fabric.Canvas} instance 46397 * @chainable true 46398 */ 46399 setWidth: function (value) { 46400 return this._setDimension('width', value); 46401 }, 46402 46403 /** 46404 * Sets height of this canvas instance 46405 * @param {Number} height value to set height to 46406 * @return {fabric.Canvas} instance 46407 * @chainable true 46408 */ 46409 setHeight: function (value) { 46410 return this._setDimension('height', value); 46411 }, 46412 46413 /** 46414 * Sets dimensions (width, height) of this canvas instance 46415 * @param {Object} dimensions Object with width/height properties 46416 * @param {Number} [dimensions.width] Width of canvas element 46417 * @param {Number} [dimensions.height] Height of canvas element 46418 * @return {fabric.Canvas} thisArg 46419 * @chainable 46420 */ 46421 setDimensions: function(dimensions) { 46422 for (var prop in dimensions) { 46423 this._setDimension(prop, dimensions[prop]); 46424 } 46425 return this; 46426 }, 46427 46428 /** 46429 * Helper for setting width/height 46430 * @private 46431 * @param {String} prop property (width|height) 46432 * @param {Number} value value to set property to 46433 * @return {fabric.Canvas} instance 46434 * @chainable true 46435 */ 46436 _setDimension: function (prop, value) { 46437 this.lowerCanvasEl[prop] = value; 46438 this.lowerCanvasEl.style[prop] = value + 'px'; 46439 46440 if (this.upperCanvasEl) { 46441 this.upperCanvasEl[prop] = value; 46442 this.upperCanvasEl.style[prop] = value + 'px'; 46443 } 46444 46445 if (this.cacheCanvasEl) { 46446 this.cacheCanvasEl[prop] = value; 46447 } 46448 46449 if (this.wrapperEl) { 46450 this.wrapperEl.style[prop] = value + 'px'; 46451 } 46452 46453 this[prop] = value; 46454 46455 this.calcOffset(); 46456 this.renderAll(); 46457 46458 return this; 46459 }, 46460 46461 /** 46462 * Returns <canvas> element corresponding to this instance 46463 * @return {HTMLCanvasElement} 46464 */ 46465 getElement: function () { 46466 return this.lowerCanvasEl; 46467 }, 46468 46469 /** 46470 * Returns currently selected object, if any 46471 * @return {fabric.Object} 46472 */ 46473 getActiveObject: function() { 46474 return null; 46475 }, 46476 46477 /** 46478 * Returns currently selected group of object, if any 46479 * @return {fabric.Group} 46480 */ 46481 getActiveGroup: function() { 46482 return null; 46483 }, 46484 46485 /** 46486 * Given a context, renders an object on that context 46487 * @param {CanvasRenderingContext2D} ctx Context to render object on 46488 * @param {fabric.Object} object Object to render 46489 * @private 46490 */ 46491 _draw: function (ctx, object) { 46492 if (!object) return; 46493 46494 if (this.controlsAboveOverlay) { 46495 var hasBorders = object.hasBorders, hasControls = object.hasControls; 46496 object.hasBorders = object.hasControls = false;
46497 object.render(ctx); 46498 object.hasBorders = hasBorders; 46499 object.hasControls = hasControls; 46500 } 46501 else { 46502 object.render(ctx); 46503 } 46504 }, 46505 46506 /** 46507 * @private 46508 * @param {fabric.Object} obj Object that was added 46509 */ 46510 _onObjectAdded: function(obj) { 46511 this.stateful && obj.setupState(); 46512 obj.setCoords(); 46513 obj.canvas = this; 46514 this.fire('object:added', { target: obj }); 46515 obj.fire('added'); 46516 }, 46517 46518 /** 46519 * @private 46520 * @param {fabric.Object} obj Object that was removed 46521 */ 46522 _onObjectRemoved: function(obj) { 46523 this.fire('object:removed', { target: obj }); 46524 obj.fire('removed'); 46525 }, 46526 46527 /** 46528 * Returns an array of objects this instance has 46529 * @return {Array} 46530 */ 46531 getObjects: function () { 46532 return this._objects; 46533 }, 46534 46535 /** 46536 * Clears specified context of canvas element 46537 * @param {CanvasRenderingContext2D} ctx Context to clear 46538 * @return {fabric.Canvas} thisArg 46539 * @chainable 46540 */ 46541 clearContext: function(ctx) { 46542 ctx.clearRect(0, 0, this.width, this.height); 46543 return this; 46544 }, 46545 46546 /** 46547 * Returns context of canvas where objects are drawn 46548 * @return {CanvasRenderingContext2D} 46549 */ 46550 getContext: function () { 46551 return this.contextContainer; 46552 }, 46553 46554 /** 46555 * Clears all contexts (background, main, top) of an instance 46556 * @return {fabric.Canvas} thisArg 46557 * @chainable 46558 */ 46559 clear: function () { 46560 this._objects.length = 0; 46561 if (this.discardActiveGroup) { 46562 this.discardActiveGroup(); 46563 } 46564 if (this.discardActiveObject) { 46565 this.discardActiveObject(); 46566 } 46567 this.clearContext(this.contextContainer); 46568 if (this.contextTop) { 46569 this.clearContext(this.contextTop); 46570 } 46571 this.fire('canvas:cleared'); 46572 this.renderAll(); 46573 return this; 46574 }, 46575 46576 /** 46577 * Renders both the top canvas and the secondary container canvas. 46578 * @param {Boolean} [allOnTop] Whether we want to force all images to be rendered on the top canvas 46579 * @return {fabric.Canvas} instance 46580 * @chainable 46581 */ 46582 renderAll: function (allOnTop) { 46583 46584 var canvasToDrawOn = this[(allOnTop === true && this.interactive) ? 'contextTop' : 'contextContainer']; 46585 46586 if (this.contextTop && this.selection && !this._groupSelector) { 46587 this.clearContext(this.contextTop); 46588 } 46589 46590 if (!allOnTop) { 46591 this.clearContext(canvasToDrawOn); 46592 } 46593 46594 this.fire('before:render'); 46595 46596 if (this.clipTo) { 46597 fabric.util.clipContext(this, canvasToDrawOn); 46598 } 46599 46600 if (this.backgroundColor) { 46601 canvasToDrawOn.fillStyle = this.backgroundColor.toLive 46602 ? this.backgroundColor.toLive(canvasToDrawOn) 46603 : this.backgroundColor; 46604 46605 canvasToDrawOn.fillRect( 46606 this.backgroundColor.offsetX || 0, 46607 this.backgroundColor.offsetY || 0, 46608 this.width, 46609 this.height); 46610 } 46611 46612 if (typeof this.backgroundImage === 'object') { 46613 this._drawBackroundImage(canvasToDrawOn); 46614 } 46615 46616 var activeGroup = this.getActiveGroup(); 46617 for (var i = 0, length = this._objects.length; i < length; ++i) { 46618 if (!activeGroup || 46619 (activeGroup && this._objects[i] && !activeGroup.contains(this._objects[i]))) { 46620 this._draw(canvasToDrawOn, this._objects[i]); 46621 } 46622 } 46623 46624 // delegate rendering to group selection (if one exists) 46625 if (activeGroup) { 46626 //Store objects in group preserving order, then replace 46627 var sortedObjects = []; 46628 this.forEachObject(function (object) { 46629 if (activeGroup.contains(object)) { 46630 sortedObjects.push(object); 46631 } 46632 }); 46633 activeGroup._set('objects', sortedObjects); 46634 this._draw(canvasToDrawOn, activeGroup); 46635 } 46636 46637 if (this.clipTo) { 46638 canvasToDrawOn.restore(); 46639 } 46640 46641 if (this.overlayImage) { 46642 canvasToDrawOn.drawImage(this.overlayImage, this.overlayImageLeft, this.overlayImageTop); 46643 } 46644 46645 if (this.controlsAboveOverlay && this.interactive) { 46646 this.drawControls(canvasToDrawOn); 46647 } 46648 46649 this.fire('after:render'); 46650 46651 return this; 46652 }, 46653 46654 /** 46655 * @private 46656 * @param {CanvasRenderingContext2D} canvasToDrawOn Context to render on 46657 */ 46658 _drawBackroundImage: function(canvasToDrawOn) { 46659 canvasToDrawOn.save(); 46660 canvasToDrawOn.globalAlpha = this.backgroundImageOpacity; 46661 46662 if (this.backgroundImageStretch) { 46663 canvasToDrawOn.drawImage(this.backgroundImage, 0, 0, this.width, this.height); 46664 } 46665 else {
46666 canvasToDrawOn.drawImage(this.backgroundImage, 0, 0); 46667 } 46668 canvasToDrawOn.restore(); 46669 }, 46670 46671 /** 46672 * Method to render only the top canvas. 46673 * Also used to render the group selection box. 46674 * @return {fabric.Canvas} thisArg 46675 * @chainable 46676 */ 46677 renderTop: function () { 46678 var ctx = this.contextTop || this.contextContainer; 46679 this.clearContext(ctx); 46680 46681 // we render the top context - last object 46682 if (this.selection && this._groupSelector) { 46683 this._drawSelection(); 46684 } 46685 46686 // delegate rendering to group selection if one exists 46687 // used for drawing selection borders/controls 46688 var activeGroup = this.getActiveGroup(); 46689 if (activeGroup) { 46690 activeGroup.render(ctx); 46691 } 46692 46693 if (this.overlayImage) { 46694 ctx.drawImage(this.overlayImage, this.overlayImageLeft, this.overlayImageTop); 46695 } 46696 46697 this.fire('after:render'); 46698 46699 return this; 46700 }, 46701 46702 /** 46703 * Returns coordinates of a center of canvas. 46704 * Returned value is an object with top and left properties 46705 * @return {Object} object with "top" and "left" number values 46706 */ 46707 getCenter: function () { 46708 return { 46709 top: this.getHeight() / 2, 46710 left: this.getWidth() / 2 46711 }; 46712 }, 46713 46714 /** 46715 * Centers object horizontally. 46716 * You might need to call `setCoords` on an object after centering, to update controls area. 46717 * @param {fabric.Object} object Object to center 46718 * @return {fabric.Canvas} thisArg 46719 */ 46720 centerObjectH: function (object) { 46721 object.set('left', this.getCenter().left); 46722 this.renderAll(); 46723 return this; 46724 }, 46725 46726 /** 46727 * Centers object vertically. 46728 * You might need to call `setCoords` on an object after centering, to update controls area. 46729 * @param {fabric.Object} object Object to center 46730 * @return {fabric.Canvas} thisArg 46731 * @chainable 46732 */ 46733 centerObjectV: function (object) { 46734 object.set('top', this.getCenter().top); 46735 this.renderAll(); 46736 return this; 46737 }, 46738 46739 /** 46740 * Centers object vertically and horizontally. 46741 * You might need to call `setCoords` on an object after centering, to update controls area. 46742 * @param {fabric.Object} object Object to center 46743 * @return {fabric.Canvas} thisArg 46744 * @chainable 46745 */ 46746 centerObject: function (object) { 46747 return this.centerObjectH(object).centerObjectV(object); 46748 }, 46749 46750 /** 46751 * Returs dataless JSON representation of canvas 46752 * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output 46753 * @return {String} json string 46754 */ 46755 toDatalessJSON: function (propertiesToInclude) { 46756 return this.toDatalessObject(propertiesToInclude); 46757 }, 46758 46759 /** 46760 * Returns object representation of canvas 46761 * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output 46762 * @return {Object} object representation of an instance 46763 */ 46764 toObject: function (propertiesToInclude) { 46765 return this._toObjectMethod('toObject', propertiesToInclude); 46766 }, 46767 46768 /** 46769 * Returns dataless object representation of canvas 46770 * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output 46771 * @return {Object} object representation of an instance 46772 */ 46773 toDatalessObject: function (propertiesToInclude) { 46774 return this._toObjectMethod('toDatalessObject', propertiesToInclude); 46775 }, 46776 46777 /** 46778 * @private 46779 */ 46780 _toObjectMethod: function (methodName, propertiesToInclude) { 46781 46782 var activeGroup = this.getActiveGroup(); 46783 if (activeGroup) { 46784 this.discardActiveGroup(); 46785 } 46786 var data = { 46787 objects: this.getObjects().map(function (instance) { 46788 // TODO (kangax): figure out how to clean this up 46789 var originalValue; 46790 if (!this.includeDefaultValues) { 46791 originalValue = instance.includeDefaultValues; 46792 instance.includeDefaultValues = false; 46793 } 46794 var object = instance[methodName](propertiesToInclude); 46795 if (!this.includeDefaultValues) { 46796 instance.includeDefaultValues = originalValue; 46797 } 46798 return object; 46799 }, this), 46800 background: (this.backgroundColor && this.backgroundColor.toObject) 46801 ? this.backgroundColor.toObject() 46802 : this.backgroundColor 46803 }; 46804 if (this.backgroundImage) { 46805 data.backgroundImage = this.backgroundImage.src; 46806 data.backgroundImageOpacity = this.backgroundImageOpacity; 46807 data.backgroundImageStretch = this.backgroundImageStretch; 46808 } 46809 if (this.overlayImage) { 46810 data.overlayImage = this.overlayImage.src; 46811 data.overlayImageLeft = this.overlayImageLeft; 46812 data.overlayImageTop = this.overlayImageTop; 46813 } 46814 fabric.util.populateWithProperties(this, data, propertiesToInclude); 46815 if (activeGroup) { 46816 this.setActiveGroup(new fabric.Group(activeGroup.getObjects())); 46817 activeGroup.forEachObject(function(o) { o.set('active', true) }); 46818 } 46819 return data; 46820 }, 46821 46822 /* _TO_SVG_START_ */ 46823 /** 46824 * Returns SVG representation of canvas 46825 * @function 46826 * @param {Object} [options] Options object for SVG output 46827 * @param {Boolean} [options.suppressPreamble=false] If true xml tag is not included 46828 * @param {Object} [options.viewBox] SVG viewbox object 46829 * @param {Number} [options.viewBox.x] x-cooridnate of viewbox 46830 * @param {Number} [options.viewBox.y] y-coordinate of viewbox 46831 * @param {Number} [options.viewBox.width] Width of viewbox 46832 * @param {Number} [options.viewBox.height] Height of viewbox 46833 * @param {String} [options.encoding=UTF-8] Encoding of SVG output 46834 * @param {Function} [reviver] Method for further parsing of svg elements, called after each fabric object c
46834onverted into svg representation. 46835 * @return {String} SVG string 46836 * @tutorial {@link http://fabricjs.com/fabric-intro-part-3/#serialization} 46837 * @see {@link http://jsfiddle.net/fabricjs/jQ3ZZ/|jsFiddle demo} 46838 * @example <caption>Normal SVG output</caption> 46839 * var svg = canvas.toSVG(); 46840 * @example <caption>SVG output without preamble (without <?xml ../>)</caption> 46841 * var svg = canvas.toSVG({suppressPreamble: true}); 46842 * @example <caption>SVG output with viewBox attribute</caption> 46843 * var svg = canvas.toSVG({ 46844 * viewBox: { 46845 * x: 100, 46846 * y: 100, 46847 * width: 200, 46848 * height: 300 46849 * } 46850 * }); 46851 * @example <caption>SVG output with different encoding (default: UTF-8)</caption> 46852 * var svg = canvas.toSVG({encoding: 'ISO-8859-1'}); 46853 * @example <caption>Modify SVG output with reviver function</caption> 46854 * var svg = canvas.toSVG(null, function(svg) { 46855 * return svg.replace('stroke-dasharray: ; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; ', ''); 46856 * }); 46857 */ 46858 toSVG: function(options, reviver) { 46859 options || (options = { }); 46860 var markup = []; 46861 46862 if (!options.suppressPreamble) { 46863 markup.push( 46864 '<?xml version="1.0" encoding="', (options.encoding || 'UTF-8'), '" standalone="no" ?>', 46865 '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" ', 46866 '"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">\n' 46867 ); 46868 } 46869 markup.push( 46870 '<svg ', 46871 'xmlns="http://www.w3.org/2000/svg" ', 46872 'xmlns:xlink="http://www.w3.org/1999/xlink" ', 46873 'version="1.1" ', 46874 'width="', (options.viewBox ? options.viewBox.width : this.width), '" ', 46875 'height="', (options.viewBox ? options.viewBox.height : this.height), '" ', 46876 (this.backgroundColor && !this.backgroundColor.source ? 'style="background-color: ' + this.backgroundColor +'" ' : null), 46877 (options.viewBox ? 'viewBox="' + options.viewBox.x + ' ' + options.viewBox.y + ' ' + options.viewBox.width + ' ' + options.viewBox.height + '" ' : null), 46878 'xml:space="preserve">', 46879 '<desc>Created with Fabric.js ', fabric.version, '</desc>', 46880 '<defs>', fabric.createSVGFontFacesMarkup(this.getObjects()), fabric.createSVGRefElementsMarkup(this), '</defs>' 46881 ); 46882 46883 if (this.backgroundColor && this.backgroundColor.source) { 46884 markup.push( 46885 '<rect x="0" y="0" ', 46886 'width="', (this.backgroundColor.repeat === 'repeat-y' || this.backgroundColor.repeat === 'no-repeat' ? this.backgroundColor.source.width : this.width), 46887 '" height="', (this.backgroundColor.repeat === 'repeat-x' || this.backgroundColor.repeat === 'no-repeat' ? this.backgroundColor.source.height : this.height), 46888 '" fill="url(#backgroundColorPattern)"', 46889 '></rect>' 46890 ); 46891 } 46892 46893 if (this.backgroundImage) { 46894 markup.push( 46895 '<image x="0" y="0" ', 46896 'width="', (this.backgroundImageStretch ? this.width : this.backgroundImage.width), 46897 '" height="', (this.backgroundImageStretch ? this.height : this.backgroundImage.height), 46898 '" preserveAspectRatio="', (this.backgroundImageStretch ? 'none' : 'defer'), 46899 '" xlink:href="', this.backgroundImage.src, 46900 '" style="opacity:', this.backgroundImageOpacity, 46901 '"></image>' 46902 ); 46903 } 46904 46905 if (this.overlayImage) { 46906 markup.push( 46907 '<image x="', this.overlayImageLeft, 46908 '" y="', this.overlayImageTop, 46909 '" width="', this.overlayImage.width, 46910 '" height="', this.overlayImage.height, 46911 '" xlink:href="', this.overlayImage.src, 46912 '"></image>' 46913 ); 46914 } 46915 46916 var activeGroup = this.getActiveGroup(); 46917 if (activeGroup) { 46918 this.discardActiveGroup(); 46919 } 46920 for (var i = 0, objects = this.getObjects(), len = objects.length; i < len; i++) { 46921 markup.push(objects[i].toSVG(reviver)); 46922 } 46923 if (activeGroup) { 46924 this.setActiveGroup(new fabric.Group(activeGroup.getObjects())); 46925 activeGroup.forEachObject(function(o) { o.set('active', true) }); 46926 } 46927 markup.push('</svg>'); 46928 46929 return markup.join(''); 46930 }, 46931 /* _TO_SVG_END_ */ 46932 46933 /** 46934 * Removes an object from canvas and returns it 46935 * @param {fabric.Object} object Object to remove 46936 * @return {fabric.Object} removed object 46937 */ 46938 remove: function (object) { 46939 // removing active object should fire "selection:cleared" events 46940 if (this.getActiveObject() === object) { 46941 this.fire('before:selection:cleared', { target: object }); 46942 this.discardActiveObject(); 46943 this.fire('selection:cleared'); 46944 } 46945 46946 return fabric.Collection.remove.call(this, object); 46947 }, 46948 46949 /** 46950 * Moves an object to the bottom of the stack of drawn objects 46951 * @param {fabric.Object} object Object to send to back 46952 * @return {fabric.Canvas} thisArg 46953 * @chainable 46954 */ 46955 sendToBack: function (object) { 46956 removeFromArray(this._objects, object); 46957 this._objects.unshift(object); 46958 return this.renderAll && this.renderAll(); 46959 }, 46960 46961 /** 46962 * Moves an object to the top of the stack of drawn objects 46963 * @param {fabric.Object} object Object to send 46964 * @return {fabric.Canvas} thisArg 46965 * @chainable 46966 */ 46967 bringToFront: function (object) { 46968 removeFromArray(this._objects, object); 46969 this._objects.push(object); 46970 return this.renderAll && this.renderAll(); 46971 }, 46972 46973 /** 46974 * Moves an object down in stack of drawn objects 46975 * @param {fabric.Object} object Object to send 46976 * @param {Boolean} [intersecting] If `true`, send object behind next lower intersecting object 46977 * @return {fabric.Canvas} thisArg 46978 * @chainable 46979 */ 46980 sendBackwards: function (object, intersecting) { 46981 var idx = this._objects.indexOf(object); 46982 46983 // if object is not on the bottom of stack 46984 if (idx !== 0) { 46985 var newIdx; 46986 46987 if (intersecting) { 46988 newIdx = idx; 46989 46990 // traverse down the stack looking for the nearest intersecting object 46991 for (var i=idx-1; i>=0; --i) { 46992 46993 var isIntersecting = object.intersectsWithObject(this._objects[i]) || 46994 object.isContainedWithinObject(this._objects[i]) || 46995 this._objects[i].isContainedWithinObject(object); 46996 46997 if (isIntersecting) { 46998 newIdx = i; 46999 break; 47000 } 47001 } 47002 } 47003 else { 47004 newIdx = idx-1; 47005 } 47006 47007 removeFromArray(this._objects, object); 47008 this._objects.splice(newIdx, 0, object); 47009 this.renderAll && this.renderAll(); 47010 } 47011 return this; 47012 }, 47013 47014 /** 47015 * Moves an object up in stack of drawn objects 47016 * @param {fabric.Object} object Object to send 47017 * @param {Boolean} [intersecting] If `true`, send object in front of next upper intersecting object 47018 * @return {fabric.Canvas} thisArg 47019 * @chainable 47020 */ 47021 bringForward: function (object, intersecting) { 47022 var idx = this._objects.indexOf(object); 47023 47024 // if object is not on top of stack (last item in an array) 47025 if (idx !== this._objects.length-1) { 47026 var newIdx; 47027 47028 if (intersecting) { 47029 newIdx = idx; 47030 47031 // traverse up the stack looking for the nearest intersecting object 47032 for (var i = idx + 1; i < this._objects.length; ++i) { 47033 47034 var isIntersecting = object.intersectsWithObject(this._objects[i]) || 47035 object.isContainedWithinObject(this._objects[i]) || 47036 this._objects[i].isContainedWithinObject(object); 47037 47038 if (isIntersecting) { 47039 newIdx = i; 47040 break; 47041 } 47042 } 47043 } 47044 else { 47045 newIdx = idx+1; 47046 } 47047 47048 removeFromArray(this._objects, object); 47049 this._objects.splice(newIdx, 0, object); 47050 this.renderAll && this.renderAll(); 47051 } 47052 return this; 47053 }, 47054 47055 /** 47056 * Moves an object to specified level in stack of drawn objects 47057 * @param {fabric.Object} object Object to send 47058 * @param {Number} index Position to move to 47059 * @return {fabric.Canvas} thisArg 47060 * @chainable 47061 */ 47062 moveTo: function (object, index) { 47063 removeFromArray(this._objects, object); 47064 this._objects.splice(index, 0, object); 47065 return this.renderAll && this.renderAll(); 47066 }, 47067 47068 /** 47069 * Clears a canvas element and removes all event handlers. 47070 * @return {fabric.Canvas} thisArg 47071 * @chainable 47072 */ 47073 dispose: function () { 47074 this.clear(); 47075 47076 if (!this.interactive) return this; 47077 47078 if (fabric.isTouchSupported) { 47079 removeListener(this.upperCanvasEl, 'touchstart', this._onMouseDown); 47080 removeListener(this.upperCanvasEl, 'touchmove', this._onMouseMove); 47081 if (typeof Event !== 'undefined' && 'remove' in Event) { 47082 Event.remove(this.upperCanvasEl, 'gesture', this._onGesture); 47083 } 47084 } 47085 else { 47086 removeListener(this.upperCanvasEl, 'mousedown', this._onMouseDown); 47087 removeListener(this.upperCanvasEl, 'mousemove', this._onMouseMove); 47088 removeListener(fabric.window, 'resize', this._onResize); 47089 } 47090 return this; 47091 }, 47092 47093 /** 47094 * Returns a string representation of an instance 47095 * @return {String} string representation of an instance 47096 */ 47097 toString: function () { 47098 return '#<fabric.Canvas (' + this.complexity() + '): '+ 47099 '{ objects: ' + this.getObjects().length + ' }>'; 47100 } 47101 }); 47102 47103 extend(fabric.StaticCanvas.prototype, fabric.Observable); 47104 extend(fabric.StaticCanvas.prototype, fabric.Collection); 47105 extend(fabric.StaticCanvas.prototype, fabric.DataURLExporter); 47106 47107 extend(fabric.StaticCanvas, /** @lends fabric.StaticCanvas */ { 47108 47109 /** 47110 * @static
47111 * @type String 47112 * @default 47113 */ 47114 EMPTY_JSON: '{"objects": [], "background": "white"}', 47115 47116 /** 47117 * Provides a way to check support of some of the canvas methods 47118 * (either those of HTMLCanvasElement itself, or rendering context) 47119 * 47120 * @param methodName {String} Method to check support for; 47121 * Could be one of "getImageData", "toDataURL", "toDataURLWithQuality" or "setLineDash" 47122 * @return {Boolean | null} `true` if method is supported (or at least exists), 47123 * `null` if canvas element or context can not be initialized 47124 */ 47125 supports: function (methodName) { 47126 var el = fabric.util.createCanvasElement(); 47127 47128 if (!el || !el.getContext) { 47129 return null; 47130 } 47131 47132 var ctx = el.getContext('2d'); 47133 if (!ctx) { 47134 return null; 47135 } 47136 47137 switch (methodName) { 47138 47139 case 'getImageData': 47140 return typeof ctx.getImageData !== 'undefined'; 47141 47142 case 'setLineDash': 47143 return typeof ctx.setLineDash !== 'undefined'; 47144 47145 case 'toDataURL': 47146 return typeof el.toDataURL !== 'undefined'; 47147 47148 case 'toDataURLWithQuality': 47149 try { 47150 el.toDataURL('image/jpeg', 0); 47151 return true; 47152 } 47153 catch (e) { } 47154 return false; 47155 47156 default: 47157 return null; 47158 } 47159 } 47160 }); 47161 47162 /** 47163 * Returns JSON representation of canvas 47164 * @function 47165 * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output 47166 * @return {String} JSON string 47167 * @tutorial {@link http://fabricjs.com/fabric-intro-part-3/#serialization} 47168 * @see {@link http://jsfiddle.net/fabricjs/pec86/|jsFiddle demo} 47169 * @example <caption>JSON without additional properties</caption> 47170 * var json = canvas.toJSON(); 47171 * @example <caption>JSON with additional properties included</caption> 47172 * var json = canvas.toJSON(['lockMovementX', 'lockMovementY', 'lockRotation', 'lockScalingX', 'lockScalingY', 'lockUniScaling']); 47173 * @example <caption>JSON without default values</caption> 47174 * canvas.includeDefaultValues = false; 47175 * var json = canvas.toJSON(); 47176 */ 47177 fabric.StaticCanvas.prototype.toJSON = fabric.StaticCanvas.prototype.toObject; 47178 47179})(); 47180 47181 47182/** 47183 * BaseBrush class 47184 * @class fabric.BaseBrush 47185 * @see {@link http://fabricjs.com/freedrawing/|Freedrawing demo} 47186 */ 47187fabric.BaseBrush = fabric.util.createClass(/** @lends fabric.BaseBrush.prototype */ { 47188 47189 /** 47190 * Color of a brush
47191 * @type String 47192 * @default 47193 */ 47194 color: 'rgb(0, 0, 0)', 47195 47196 /** 47197 * Width of a brush 47198 * @type Number 47199 * @default 47200 */ 47201 width: 1, 47202 47203 /** 47204 * Shadow object representing shadow of this shape. 47205 * <b>Backwards incompatibility note:</b> This property replaces "shadowColor" (String), "shadowOffsetX" (Number), 47206 * "shadowOffsetY" (Number) and "shadowBlur" (Number) since v1.2.12 47207 * @type fabric.Shadow 47208 * @default 47209 */ 47210 shadow: null, 47211 47212 /** 47213 * Line endings style of a brush (one of "butt", "round", "square") 47214 * @type String 47215 * @default 47216 */ 47217 strokeLineCap: 'round', 47218 47219 /** 47220 * Corner style of a brush (one of "bevil", "round", "miter") 47221 * @type String 47222 * @default 47223 */ 47224 strokeLineJoin: 'round', 47225 47226 /** 47227 * Sets shadow of an object 47228 * @param {Object|String} [options] Options object or string (e.g. "2px 2px 10px rgba(0,0,0,0.2)") 47229 * @return {fabric.Object} thisArg 47230 * @chainable 47231 */ 47232 setShadow: function(options) { 47233 this.shadow = new fabric.Shadow(options); 47234 return this; 47235 }, 47236 47237 /** 47238 * Sets brush styles 47239 * @private 47240 */ 47241 _setBrushStyles: function() { 47242 var ctx = this.canvas.contextTop; 47243 47244 ctx.strokeStyle = this.color; 47245 ctx.lineWidth = this.width; 47246 ctx.lineCap = this.strokeLineCap; 47247 ctx.lineJoin = this.strokeLineJoin; 47248 }, 47249 47250 /** 47251 * Sets brush shadow styles 47252 * @private 47253 */ 47254 _setShadow: function() { 47255 if (!this.shadow) return; 47256 47257 var ctx = this.canvas.contextTop; 47258 47259 ctx.shadowColor = this.shadow.color; 47260 ctx.shadowBlur = this.shadow.blur; 47261 ctx.shadowOffsetX = this.shadow.offsetX; 47262 ctx.shadowOffsetY = this.shadow.offsetY; 47263 }, 47264 47265 /** 47266 * Removes brush shadow styles 47267 * @private 47268 */ 47269 _resetShadow: function() { 47270 var ctx = this.canvas.contextTop; 47271 47272 ctx.shadowColor = ''; 47273 ctx.shadowBlur = ctx.shadowOffsetX = ctx.shadowOffsetY = 0; 47274 } 47275}); 47276 47277 47278(function() { 47279 47280 var utilMin = fabric.util.array.min, 47281 utilMax = fabric.util.array.max; 47282 47283 /** 47284 * PencilBrush class 47285 * @class fabric.PencilBrush 47286 * @extends fabric.BaseBrush 47287 */ 47288 fabric.PencilBrush = fabric.util.createClass(fabric.BaseBrush, /** @lends fabric.PencilBrush.prototype */ { 47289 47290 /** 47291 * Constructor 47292 * @param {fabric.Canvas} canvas 47293 * @return {fabric.PencilBrush} Instance of a pencil brush 47294 */ 47295 initialize: function(canvas) { 47296 this.canvas = canvas; 47297 this._points = [ ]; 47298 }, 47299 47300 /** 47301 * Inovoked on mouse down 47302 * @param {Object} pointer 47303 */ 47304 onMouseDown: function(pointer) { 47305 this._prepareForDrawing(pointer); 47306 // capture coordinates immediately 47307 // this allows to draw dots (when movement never occurs) 47308 this._captureDrawingPath(pointer); 47309 this._render(); 47310 }, 47311 47312 /** 47313 * Inovoked on mouse move 47314 * @param {Object} pointer 47315 */ 47316 onMouseMove: function(pointer) { 47317 this._captureDrawingPath(pointer); 47318 // redraw curve 47319 // clear top canvas 47320 this.canvas.clearContext(this.canvas.contextTop); 47321 this._render(); 47322 }, 47323 47324 /** 47325 * Invoked on mouse up 47326 */ 47327 onMouseUp: function() { 47328 this._finalizeAndAddPath(); 47329 }, 47330 47331 /** 47332 * @param {Object} pointer 47333 */ 47334 _prepareForDrawing: function(pointer) { 47335 47336 var p = new fabric.Point(pointer.x, pointer.y); 47337 47338 this._reset(); 47339 this._addPoint(p); 47340 47341 this.canvas.contextTop.moveTo(p.x, p.y); 47342 }, 47343 47344 /** 47345 * @private 47346 * @param {fabric.Point} point 47347 */ 47348 _addPoint: function(point) { 47349 this._points.push(point); 47350 }, 47351 47352 /** 47353 * Clear points array and set contextTop canvas 47354 * style. 47355 * 47356 * @private 47357 * 47358 */ 47359 _reset: function() { 47360 this._points.length = 0; 47361 47362 this._setBrushStyles(); 47363 this._setShadow(); 47364 }, 47365 47366 /** 47367 * @private 47368 * 47369 * @param point {pointer} (fabric.util.pointer) actual mouse position 47370 * related to the canvas. 47371 */ 47372 _captureDrawingPath: function(pointer) { 47373 var pointerPoint = new fabric.Point(pointer.x, pointer.y); 47374 this._addPoint(pointerPoint); 47375 }, 47376 47377 /** 47378 * Draw a smooth path on the topCanvas using quadraticCurveTo 47379 * 47380 * @private 47381 */ 47382 _render: function() { 47383 var ctx = this.canvas.contextTop; 47384 ctx.beginPath(); 47385 47386 var p1 = this._points[0]; 47387 var p2 = this._points[1]; 47388 47389 //if we only have 2 points in the path and they are the same 47390 //it means that the user only clicked the canvas without moving the mouse 47391 //then we should be drawing a dot. A path isn't drawn between two identical dots 47392 //that's why we set them apart a bit 47393 if (this._points.length === 2 && p1.x === p2.x && p1.y === p2.y) { 47394 p1.x -= 0.5; 47395 p2.x += 0.5; 47396 } 47397 ctx.moveTo(p1.x, p1.y); 47398 47399 for (var i = 1, len = this._points.length; i < len; i++) { 47400 // we pick the point between pi+1 & pi+2 as the 47401 // end point and p1 as our control point. 47402 var midPoint = p1.midPointFrom(p2); 47403 ctx.quadraticCurveTo(p1.x, p1.y, midPoint.x, midPoint.y); 47404 47405 p1 = this._points[i]; 47406 p2 = this._points[i+1]; 47407 } 47408 // Draw last line as a straight line while 47409 // we wait for the next point to be able to calculate 47410 // the bezier control point 47411 ctx.lineTo(p1.x, p1.y); 47412 ctx.stroke(); 47413 }, 47414 47415 /** 47416 * Return an SVG path based on our captured points and their bounding box 47417 * 47418 * @private 47419 */ 47420 _getSVGPathData: function() { 47421 this.box = this.getPathBoundingBox(this._points); 47422 return this.convertPointsToSVGPath( 47423 this._points, this.box.minx, this.box.maxx, this.box.miny, this.box.maxy); 47424 }, 47425 47426 /** 47427 * Returns bounding box of a path based on given points 47428 * @param {Array} points 47429 * @return {Object} object with minx, miny, maxx, maxy 47430 */ 47431 getPathBoundingBox: function(points) { 47432 var xBounds = [], 47433 yBounds = [], 47434 p1 = points[0], 47435 p2 = points[1], 47436 startPoint = p1; 47437 47438 for (var i = 1, len = points.length; i < len; i++) { 47439 var midPoint = p1.midPointFrom(p2); 47440 // with startPoint, p1 as control point, midpoint as end point 47441 xBounds.push(startPoint.x); 47442 xBounds.push(midPoint.x); 47443 yBounds.push(startPoint.y); 47444 yBounds.push(midPoint.y); 47445 47446 p1 = points[i]; 47447 p2 = points[i+1]; 47448 startPoint = midPoint; 47449 } // end for 47450 47451 xBounds.push(p1.x); 47452 yBounds.push(p1.y); 47453 47454 return { 47455 minx: utilMin(xBounds), 47456 miny: utilMin(yBounds), 47457 maxx: utilMax(xBounds), 47458 maxy: utilMax(yBounds) 47459 }; 47460 }, 47461 47462 /** 47463 * Converts points to SVG path 47464 * @param {Array} points Array of points 47465 * @return {String} SVG path 47466 */ 47467 convertPointsToSVGPath: function(points, minX, maxX, minY) { 47468 var path = []; 47469 var p1 = new fabric.Point(points[0].x - minX, points[0].y - minY); 47470 var p2 = new fabric.Point(points[1].x - minX, points[1].y - minY); 47471 47472 path.push('M ', points[0].x - minX, ' ', points[0].y - minY, ' '); 47473 for (var i = 1, len = points.length; i < len; i++) { 47474 var midPoint = p1.midPointFrom(p2); 47475 // p1 is our bezier control point 47476 // midpoint is our endpoint 47477 // start point is p(i-1) value. 47478 path.push('Q ', p1.x, ' ', p1.y, ' ', midPoint.x, ' ', midPoint.y, ' '); 47479 p1 = new fabric.Point(points[i].x - minX, points[i].y - minY); 47480 if ((i+1) < points.length) { 47481 p2 = new fabric.Point(points[i+1].x - minX, points[i+1].y - minY); 47482 } 47483 } 47484 path.push('L ', p1.x, ' ', p1.y, ' '); 47485 return path; 47486 }, 47487 47488 /** 47489 * Creates fabric.Path object to add on canvas 47490 * @param {String} pathData Path data 47491 * @return {fabric.Path} path to add on canvas 47492 */ 47493 createPath: function(pathData) { 47494 var path = new fabric.Path(pathData); 47495 path.fill = null; 47496 path.stroke = this.color; 47497 path.strokeWidth = this.width; 47498 path.strokeLineCap = this.strokeLineCap; 47499 path.strokeLineJoin = this.strokeLineJoin; 47500 47501 if (this.shadow) { 47502 this.shadow.affectStroke = true; 47503 path.setShadow(this.shadow); 47504 } 47505 47506 return path; 47507 }, 47508 47509 /** 47510 * On mouseup after drawing the path on contextTop canvas 47511 * we use the points captured to create an new fabric path object 47512 * and add it to the fabric canvas. 47513 * 47514 */ 47515 _finalizeAndAddPath: function() { 47516 var ctx = this.canvas.contextTop; 47517 ctx.closePath(); 47518 47519 var pathData = this._getSVGPathData().join(''); 47520 if (pathData === "M 0 0 Q 0 0 0 0 L 0 0") { 47521 // do not create 0 width/height paths, as they are 47522 // rendered inconsistently across browsers 47523 // Firefox 4, for example, renders a dot, 47524 // whereas Chrome 10 renders nothing 47525 this.canvas.renderAll(); 47526 return; 47527 } 47528 47529 // set path origin coordinates based on our bounding box 47530 var originLeft = this.box.minx + (this.box.maxx - this.box.minx) /2; 47531 var originTop = this.box.miny + (this.box.maxy - this.box.miny) /2; 47532 47533 this.canvas.contextTop.arc(originLeft, originTop, 3, 0, Math.PI * 2, false); 47534 47535 var path = this.createPath(pathData); 47536 path.set({ left: originLeft, top: originTop }); 47537 47538 this.canvas.add(path); 47539 path.setCoords(); 47540 47541 this.canvas.clearContext(this.canvas.contextTop); 47542 this._resetShadow(); 47543 this.canvas.renderAll(); 47544 47545 // fire event 'path' created 47546 this.canvas.fire('path:created', { path: path }); 47547 } 47548 }); 47549})(); 47550 47551 47552/** 47553 * CircleBrush class 47554 * @class fabric.CircleBrush 47555 */ 47556fabric.CircleBrush = fabric.util.createClass(fabric.BaseBrush, /** @lends fabric.CircleBrush.prototype */ { 47557 47558 /** 47559 * Width of a brush 47560 * @type Number 47561 * @default 47562 */ 47563 width: 10, 47564 47565 /** 47566 * Constructor 47567 * @param {fabric.Canvas} canvas 47568 * @return {fabric.CircleBrush} Instance of a circle brush 47569 */ 47570 initialize: function(canvas) { 47571 this.canvas = canvas; 47572 this.points = [ ]; 47573 }, 47574 /** 47575 * Invoked inside on mouse down and mouse move 47576 * @param {Object} pointer 47577 */ 47578 drawDot: function(pointer) { 47579 var point = this.addPoint(pointer); 47580 var ctx = this.canvas.contextTop; 47581 47582 ctx.fillStyle = point.fill; 47583 ctx.beginPath(); 47584 ctx.arc(point.x, point.y, point.radius, 0, Math.PI * 2, false); 47585 ctx.closePath(); 47586 ctx.fill(); 47587 }, 47588 47589 /** 47590 * Invoked on mouse down 47591 */ 47592 onMouseDown: function(pointer) { 47593 this.points.length = 0; 47594 this.canvas.clearContext(this.canvas.contextTop); 47595 this._setShadow(); 47596 this.drawDot(pointer); 47597 }, 47598 47599 /** 47600 * Invoked on mouse move 47601 * @param {Object} pointer 47602 */ 47603 onMouseMove: function(pointer) { 47604 this.drawDot(pointer); 47605 }, 47606 47607 /** 47608 * Invoked on mouse up 47609 */ 47610 onMouseUp: function() { 47611 var originalRenderOnAddRemove = this.canvas.renderOnAddRemove; 47612 this.canvas.renderOnAddRemove = false;
vendor: 9,591 bytes, lines 47613-48008
47613 47614 var circles = [ ]; 47615 47616 for (var i = 0, len = this.points.length; i < len; i++) { 47617 var point = this.points[i]; 47618 var circle = new fabric.Circle({ 47619 radius: point.radius, 47620 left: point.x, 47621 top: point.y, 47622 fill: point.fill 47623 }); 47624 47625 this.shadow && circle.setShadow(this.shadow); 47626 47627 circles.push(circle); 47628 } 47629 var group = new fabric.Group(circles); 47630 47631 this.canvas.add(group); 47632 this.canvas.fire('path:created', { path: group }); 47633 47634 this.canvas.clearContext(this.canvas.contextTop); 47635 this._resetShadow(); 47636 this.canvas.renderOnAddRemove = originalRenderOnAddRemove; 47637 this.canvas.renderAll(); 47638 }, 47639 47640 /** 47641 * @param {Object} pointer 47642 * @return {fabric.Point} Just added pointer point 47643 */ 47644 addPoint: function(pointer) { 47645 var pointerPoint = new fabric.Point(pointer.x, pointer.y); 47646 47647 var circleRadius = fabric.util.getRandomInt( 47648 Math.max(0, this.width - 20), this.width + 20) / 2; 47649 47650 var circleColor = new fabric.Color(this.color) 47651 .setAlpha(fabric.util.getRandomInt(0, 100) / 100) 47652 .toRgba(); 47653 47654 pointerPoint.radius = circleRadius; 47655 pointerPoint.fill = circleColor; 47656 47657 this.points.push(pointerPoint); 47658 47659 return pointerPoint; 47660 } 47661}); 47662 47663 47664/** 47665 * SprayBrush class 47666 * @class fabric.SprayBrush 47667 */ 47668fabric.SprayBrush = fabric.util.createClass( fabric.BaseBrush, /** @lends fabric.SprayBrush.prototype */ { 47669 47670 /** 47671 * Width of a spray 47672 * @type Number 47673 * @default 47674 */ 47675 width: 10, 47676 47677 /** 47678 * Density of a spray (number of dots per chunk) 47679 * @type Number 47680 * @default 47681 */ 47682 density: 20, 47683 47684 /** 47685 * Width of spray dots 47686 * @type Number 47687 * @default 47688 */ 47689 dotWidth: 1, 47690 47691 /** 47692 * Width variance of spray dots 47693 * @type Number 47694 * @default 47695 */ 47696 dotWidthVariance: 1, 47697 47698 /** 47699 * Whether opacity of a dot should be random 47700 * @type Boolean 47701 * @default 47702 */ 47703 randomOpacity: false, 47704 47705 /** 47706 * Whether overlapping dots (rectangles) should be removed (for performance reasons) 47707 * @type Boolean 47708 * @default 47709 */ 47710 optimizeOverlapping: true, 47711 47712 /** 47713 * Constructor 47714 * @param {fabric.Canvas} canvas 47715 * @return {fabric.SprayBrush} Instance of a spray brush 47716 */ 47717 initialize: function(canvas) { 47718 this.canvas = canvas; 47719 this.sprayChunks = [ ]; 47720 }, 47721 47722 /** 47723 * Invoked on mouse down 47724 * @param {Object} pointer 47725 */ 47726 onMouseDown: function(pointer) { 47727 this.sprayChunks.length = 0; 47728 this.canvas.clearContext(this.canvas.contextTop); 47729 this._setShadow(); 47730 47731 this.addSprayChunk(pointer); 47732 this.render(); 47733 }, 47734 47735 /** 47736 * Invoked on mouse move 47737 * @param {Object} pointer 47738 */ 47739 onMouseMove: function(pointer) { 47740 this.addSprayChunk(pointer); 47741 this.render(); 47742 }, 47743 47744 /** 47745 * Invoked on mouse up 47746 */ 47747 onMouseUp: function() { 47748 var originalRenderOnAddRemove = this.canvas.renderOnAddRemove; 47749 this.canvas.renderOnAddRemove = false; 47750 47751 var rects = [ ]; 47752 47753 for (var i = 0, ilen = this.sprayChunks.length; i < ilen; i++) { 47754 var sprayChunk = this.sprayChunks[i]; 47755 47756 for (var j = 0, jlen = sprayChunk.length; j < jlen; j++) { 47757 47758 var rect = new fabric.Rect({ 47759 width: sprayChunk[j].width, 47760 height: sprayChunk[j].width, 47761 left: sprayChunk[j].x + 1, 47762 top: sprayChunk[j].y + 1, 47763 fill: this.color 47764 }); 47765 47766 this.shadow && rect.setShadow(this.shadow); 47767 rects.push(rect); 47768 } 47769 } 47770 47771 if (this.optimizeOverlapping) { 47772 rects = this._getOptimizedRects(rects); 47773 } 47774 47775 var group = new fabric.Group(rects); 47776 this.canvas.add(group); 47777 this.canvas.fire('path:created', { path: group }); 47778 47779 this.canvas.clearContext(this.canvas.contextTop); 47780 this._resetShadow(); 47781 this.canvas.renderOnAddRemove = originalRenderOnAddRemove; 47782 this.canvas.renderAll(); 47783 }, 47784 47785 _getOptimizedRects: function(rects) { 47786 47787 // avoid creating duplicate rects at the same coordinates 47788 var uniqueRects = { }, key; 47789 47790 for (var i = 0, len = rects.length; i < len; i++) { 47791 key = rects[i].left + '' + rects[i].top; 47792 if (!uniqueRects[key]) { 47793 uniqueRects[key] = rects[i]; 47794 } 47795 } 47796 var uniqueRectsArray = [ ]; 47797 for (key in uniqueRects) { 47798 uniqueRectsArray.push(uniqueRects[key]); 47799 } 47800 47801 return uniqueRectsArray; 47802 }, 47803 47804 /** 47805 * Renders brush 47806 */ 47807 render: function() { 47808 var ctx = this.canvas.contextTop; 47809 ctx.fillStyle = this.color; 47810 ctx.save(); 47811 47812 for (var i = 0, len = this.sprayChunkPoints.length; i < len; i++) { 47813 var point = this.sprayChunkPoints[i]; 47814 if (typeof point.opacity !== 'undefined') { 47815 ctx.globalAlpha = point.opacity; 47816 } 47817 ctx.fillRect(point.x, point.y, point.width, point.width); 47818 } 47819 ctx.restore(); 47820 }, 47821 47822 /** 47823 * @param {Object} pointer 47824 */ 47825 addSprayChunk: function(pointer) { 47826 this.sprayChunkPoints = [ ]; 47827 47828 var x, y, width, radius = this.width / 2; 47829 47830 for (var i = 0; i < this.density; i++) { 47831 47832 x = fabric.util.getRandomInt(pointer.x - radius, pointer.x + radius); 47833 y = fabric.util.getRandomInt(pointer.y - radius, pointer.y + radius); 47834 47835 if (this.dotWidthVariance) { 47836 width = fabric.util.getRandomInt( 47837 // bottom clamp width to 1 47838 Math.max(1, this.dotWidth - this.dotWidthVariance), 47839 this.dotWidth + this.dotWidthVariance); 47840 } 47841 else { 47842 width = this.dotWidth; 47843 } 47844 47845 var point = { x: x, y: y, width: width }; 47846 47847 if (this.randomOpacity) { 47848 point.opacity = fabric.util.getRandomInt(0, 100) / 100; 47849 } 47850 47851 this.sprayChunkPoints.push(point); 47852 } 47853 47854 this.sprayChunks.push(this.sprayChunkPoints); 47855 } 47856}); 47857 47858 47859/** 47860 * PatternBrush class 47861 * @class fabric.PatternBrush 47862 * @extends fabric.BaseBrush 47863 */ 47864fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fabric.PatternBrush.prototype */ { 47865 47866 getPatternSrc: function() { 47867 47868 var dotWidth = 20, 47869 dotDistance = 5, 47870 patternCanvas = fabric.document.createElement('canvas'), 47871 patternCtx = patternCanvas.getContext('2d'); 47872 47873 patternCanvas.width = patternCanvas.height = dotWidth + dotDistance; 47874 47875 patternCtx.fillStyle = this.color; 47876 patternCtx.beginPath(); 47877 patternCtx.arc(dotWidth / 2, dotWidth / 2, dotWidth / 2, 0, Math.PI * 2, false); 47878 patternCtx.closePath(); 47879 patternCtx.fill(); 47880 47881 return patternCanvas; 47882 }, 47883 47884 getPatternSrcFunction: function() { 47885 return String(this.getPatternSrc).replace('this.color', '"' + this.color + '"'); 47886 }, 47887 47888 /** 47889 * Creates "pattern" instance property 47890 */ 47891 getPattern: function() { 47892 return this.canvas.contextTop.createPattern(this.source || this.getPatternSrc(), 'repeat'); 47893 }, 47894 47895 /** 47896 * Sets brush styles 47897 */ 47898 _setBrushStyles: function() { 47899 this.callSuper('_setBrushStyles'); 47900 this.canvas.contextTop.strokeStyle = this.getPattern(); 47901 }, 47902 47903 /** 47904 * Creates path 47905 */ 47906 createPath: function(pathData) { 47907 var path = this.callSuper('createPath', pathData); 47908 path.stroke = new fabric.Pattern({ 47909 source: this.source || this.getPatternSrcFunction() 47910 }); 47911 return path; 47912 } 47913}); 47914 47915 47916(function() { 47917 47918 var getPointer = fabric.util.getPointer, 47919 degreesToRadians = fabric.util.degreesToRadians, 47920 radiansToDegrees = fabric.util.radiansToDegrees, 47921 atan2 = Math.atan2, 47922 abs = Math.abs, 47923 min = Math.min, 47924 max = Math.max, 47925 47926 STROKE_OFFSET = 0.5; 47927 47928 /** 47929 * Canvas class 47930 * @class fabric.Canvas 47931 * @extends fabric.StaticCanvas 47932 * @tutorial {@link http://fabricjs.com/fabric-intro-part-1/#canvas} 47933 * 47934 * @fires object:modified 47935 * @fires object:rotating 47936 * @fires object:scaling 47937 * @fires object:moving 47938 * @fires object:selected 47939 * 47940 * @fires before:selection:cleared 47941 * @fires selection:cleared 47942 * @fires selection:created 47943 * 47944 * @fires path:created 47945 * @fires mouse:down 47946 * @fires mouse:move 47947 * @fires mouse:up 47948 * 47949 */ 47950 fabric.Canvas = fabric.util.createClass(fabric.StaticCanvas, /** @lends fabric.Canvas.prototype */ { 47951 47952 /** 47953 * Constructor 47954 * @param {HTMLElement | String} el <canvas> element to initialize instance on 47955 * @param {Object} [options] Options object 47956 * @return {Object} thisArg 47957 */ 47958 initialize: function(el, options) { 47959 options || (options = { }); 47960 47961 this._initStatic(el, options); 47962 this._initInteractive(); 47963 this._createCacheCanvas(); 47964 47965 fabric.Canvas.activeInstance = this; 47966 }, 47967 47968 /** 47969 * When true, objects can be transformed by one side (unproportionally) 47970 * @type Boolean 47971 * @default 47972 */ 47973 uniScaleTransform: false, 47974 47975 /** 47976 * When true, objects use center point as the origin of scale transformation. 47977 * <b>Backwards incompatibility note:</b> This property replaces "centerTransform" (Boolean). 47978 * @since 1.3.4 47979 * @type Boolean 47980 * @default 47981 */ 47982 centeredScaling: false, 47983 47984 /** 47985 * When true, objects use center point as the origin of rotate transformation. 47986 * <b>Backwards incompatibility note:</b> This property replaces "centerTransform" (Boolean). 47987 * @since 1.3.4 47988 * @type Boolean 47989 * @default 47990 */ 47991 centeredRotation: false, 47992 47993 /** 47994 * Indicates that canvas is interactive. This property should not be changed. 47995 * @type Boolean 47996 * @default 47997 */ 47998 interactive: true, 47999 48000 /** 48001 * Indicates whether group selection should be enabled 48002 * @type Boolean 48003 * @default 48004 */ 48005 selection: true, 48006 48007 /** 48008 * Color of selection
48009 * @type String 48010 * @default 48011 */ 48012 selectionColor: 'rgba(100, 100, 255, 0.3)', // blue 48013 48014 /** 48015 * Default dash array pattern 48016 * If not empty the selection border is dashed 48017 * @type Array 48018 */ 48019 selectionDashArray: [ ], 48020 48021 /** 48022 * Color of the border of selection (usually slightly darker than color of selection itself) 48023 * @type String 48024 * @default 48025 */ 48026 selectionBorderColor: 'rgba(255, 255, 255, 0.3)', 48027 48028 /** 48029 * Width of a line used in object/group selection 48030 * @type Number 48031 * @default 48032 */ 48033 selectionLineWidth: 1, 48034 48035 /** 48036 * Default cursor value used when hovering over an object on canvas 48037 * @type String 48038 * @default 48039 */ 48040 hoverCursor: 'move', 48041 48042 /** 48043 * Default cursor value used when moving an object on canvas 48044 * @type String 48045 * @default 48046 */ 48047 moveCursor: 'move', 48048 48049 /** 48050 * Default cursor value used for the entire canvas 48051 * @type String 48052 * @default 48053 */ 48054 defaultCursor: 'default', 48055 48056 /** 48057 * Cursor value used during free drawing
48058 * @type String 48059 * @default 48060 */ 48061 freeDrawingCursor: 'crosshair', 48062 48063 /** 48064 * Cursor value used for rotation point 48065 * @type String 48066 * @default 48067 */ 48068 rotationCursor: 'crosshair', 48069 48070 /** 48071 * Default element class that's given to wrapper (div) element of canvas 48072 * @type String 48073 * @default 48074 */ 48075 containerClass: 'canvas-container', 48076 48077 /** 48078 * When true, object detection happens on per-pixel basis rather than on per-bounding-box 48079 * @type Boolean 48080 * @default 48081 */ 48082 perPixelTargetFind: false, 48083 48084 /** 48085 * Number of pixels around target pixel to tolerate (consider active) during object detection 48086 * @type Number 48087 * @default 48088 */ 48089 targetFindTolerance: 0, 48090 48091 /** 48092 * When true, target detection is skipped when hovering over canvas. This can be used to improve performance. 48093 * @type Boolean 48094 * @default 48095 */ 48096 skipTargetFind: false, 48097 48098 /** 48099 * @private 48100 */ 48101 _initInteractive: function() { 48102 this._currentTransform = null; 48103 this._groupSelector = null; 48104 this._initWrapperElement(); 48105 this._createUpperCanvas(); 48106 this._initEvents(); 48107 48108 this.freeDrawingBrush = fabric.PencilBrush && new fabric.PencilBrush(this); 48109 48110 this.calcOffset(); 48111 }, 48112 48113 /** 48114 * Resets the current transform to its original values and chooses the type of resizing based on the event 48115 * @private 48116 * @param {Event} e Event object fired on mousemove 48117 */ 48118 _resetCurrentTransform: function(e) { 48119 var t = this._currentTransform; 48120 48121 t.target.set({ 48122 'scaleX': t.original.scaleX, 48123 'scaleY': t.original.scaleY, 48124 'left': t.original.left, 48125 'top': t.original.top 48126 }); 48127 48128 if (this._shouldCenterTransform(e, t.target)) { 48129 if (t.action === 'rotate') { 48130 this._setOriginToCenter(t.target); 48131 } 48132 else { 48133 if (t.originX !== 'center') { 48134 if (t.originX === 'right') { 48135 t.mouseXSign = -1; 48136 } 48137 else { 48138 t.mouseXSign = 1; 48139 } 48140 } 48141 if (t.originY !== 'center') { 48142 if (t.originY === 'bottom') { 48143 t.mouseYSign = -1; 48144 } 48145 else { 48146 t.mouseYSign = 1; 48147 } 48148 } 48149 48150 t.originX = 'center'; 48151 t.originY = 'center'; 48152 } 48153 } 48154 else { 48155 t.originX = t.original.originX; 48156 t.originY = t.original.originY; 48157 } 48158 }, 48159 48160 /** 48161 * Checks if point is contained within an area of given object 48162 * @param {Event} e Event object 48163 * @param {fabric.Object} target Object to test against 48164 * @return {Boolean} true if point is contained within an area of given object 48165 */ 48166 containsPoint: function (e, target) { 48167 var pointer = this.getPointer(e), 48168 xy = this._normalizePointer(target, pointer); 48169 48170 // http://www.geog.ubc.ca/courses/klink/gis.notes/ncgia/u32.html 48171 // http://idav.ucdavis.edu/~okreylos/TAship/Spring2000/PointInPolygon.html 48172 return (target.containsPoint(xy) || target._findTargetCorner(e, this._offset)); 48173 }, 48174 48175 /** 48176 * @private 48177 */ 48178 _normalizePointer: function (object, pointer) { 48179 var activeGroup = this.getActiveGroup(), 48180 x = pointer.x, 48181 y = pointer.y; 48182 48183 var isObjectInGroup = ( 48184 activeGroup && 48185 object.type !== 'group' && 48186 activeGroup.contains(object) 48187 ); 48188 48189 if (isObjectInGroup) { 48190 x -= activeGroup.left; 48191 y -= activeGroup.top; 48192 } 48193 return { x: x, y: y }; 48194 }, 48195 48196 /** 48197 * Returns true if object is transparent at a certain location 48198 * @param {fabric.Object} target Object to check 48199 * @param {Number} x Left coordinate 48200 * @param {Number} y Top coordinate 48201 * @return {Boolean} 48202 */ 48203 isTargetTransparent: function (target, x, y) { 48204 var cacheContext = this.contextCache; 48205 48206 var hasBorders = target.hasBorders, 48207 transparentCorners = target.transparentCorners; 48208 48209 target.hasBorders = target.transparentCorners = false;
48210 48211 this._draw(cacheContext, target); 48212 48213 target.hasBorders = hasBorders; 48214 target.transparentCorners = transparentCorners; 48215 48216 // If tolerance is > 0 adjust start coords to take into account. If moves off Canvas fix to 0 48217 if (this.targetFindTolerance > 0) { 48218 if (x > this.targetFindTolerance) { 48219 x -= this.targetFindTolerance; 48220 } 48221 else { 48222 x = 0; 48223 } 48224 if (y > this.targetFindTolerance) { 48225 y -= this.targetFindTolerance; 48226 } 48227 else { 48228 y = 0; 48229 } 48230 } 48231 48232 var isTransparent = true; 48233 var imageData = cacheContext.getImageData( 48234 x, y, (this.targetFindTolerance * 2) || 1, (this.targetFindTolerance * 2) || 1); 48235 48236 // Split image data - for tolerance > 1, pixelDataSize = 4; 48237 for (var i = 3, l = imageData.data.length; i < l; i += 4) { 48238 var temp = imageData.data[i]; 48239 isTransparent = temp <= 0; 48240 if (isTransparent === false) break; //Stop if colour found 48241 } 48242 48243 imageData = null; 48244 this.clearContext(cacheContext); 48245 48246 return isTransparent; 48247 }, 48248 48249 /** 48250 * @private 48251 * @param {Event} e Event object 48252 * @param {fabric.Object} target 48253 */ 48254 _shouldClearSelection: function (e, target) { 48255 var activeGroup = this.getActiveGroup(); 48256 48257 return ( 48258 !target || ( 48259 target && 48260 activeGroup && 48261 !activeGroup.contains(target) && 48262 activeGroup !== target && 48263 !e.shiftKey) || ( 48264 target && 48265 !target.evented) 48266 ); 48267 }, 48268 48269 /** 48270 * @private 48271 * @param {Event} e Event object 48272 * @param {fabric.Object} target 48273 */ 48274 _shouldCenterTransform: function (e, target) { 48275 if (!target) return; 48276 48277 var t = this._currentTransform, 48278 centerTransform; 48279 48280 if (t.action === 'scale' || t.action === 'scaleX' || t.action === 'scaleY') { 48281 centerTransform = this.centeredScaling || target.centeredScaling; 48282 } 48283 else if (t.action === 'rotate') { 48284 centerTransform = this.centeredRotation || target.centeredRotation; 48285 } 48286 48287 return centerTransform ? !e.altKey : e.altKey; 48288 }, 48289 48290 /** 48291 * @private 48292 * @param {Event} e Event object 48293 * @param {fabric.Object} target 48294 */ 48295 _setupCurrentTransform: function (e, target) { 48296 if (!target) return; 48297 48298 var action = 'drag', 48299 corner, 48300 pointer = getPointer(e, target.canvas.upperCanvasEl); 48301 48302 corner = target._findTargetCorner(e, this._offset); 48303 if (corner) { 48304 action = (corner === 'ml' || corner === 'mr') 48305 ? 'scaleX' 48306 : (corner === 'mt' || corner === 'mb') 48307 ? 'scaleY' 48308 : corner === 'mtr' 48309 ? 'rotate' 48310 : 'scale'; 48311 } 48312 48313 var originX = target.originX, 48314 originY = target.originY; 48315 48316 if (corner === 'ml' || corner === 'tl' || corner === 'bl') { 48317 originX = "right"; 48318 } 48319 else if (corner === 'mr' || corner === 'tr' || corner === 'br') { 48320 originX = "left"; 48321 } 48322 48323 if (corner === 'tl' || corner === 'mt' || corner === 'tr') { 48324 originY = "bottom"; 48325 } 48326 else if (corner === 'bl' || corner === 'mb' || corner === 'br') { 48327 originY = "top"; 48328 } 48329 48330 this._currentTransform = { 48331 target: target, 48332 action: action, 48333 scaleX: target.scaleX, 48334 scaleY: target.scaleY, 48335 offsetX: pointer.x - target.left, 48336 offsetY: pointer.y - target.top, 48337 originX: originX, 48338 originY: originY, 48339 ex: pointer.x, 48340 ey: pointer.y, 48341 left: target.left, 48342 top: target.top, 48343 theta: degreesToRadians(target.angle), 48344 width: target.width * target.scaleX, 48345 mouseXSign: 1, 48346 mouseYSign: 1 48347 }; 48348 48349 this._currentTransform.original = { 48350 left: target.left, 48351 top: target.top, 48352 scaleX: target.scaleX, 48353 scaleY: target.scaleY, 48354 originX: originX, 48355 originY: originY 48356 }; 48357 48358 this._resetCurrentTransform(e); 48359 }, 48360 48361 /** 48362 * @private 48363 * @param {Event} e Event object 48364 * @param {fabric.Object} target 48365 * @return {Boolean} 48366 */ 48367 _shouldHandleGroupLogic: function(e, target) { 48368 var activeObject = this.getActiveObject(); 48369 return e.shiftKey && 48370 (this.getActiveGroup() || (activeObject && activeObject !== target)) 48371 && this.selection; 48372 }, 48373 48374 /** 48375 * @private 48376 * @param {Event} e Event object 48377 * @param {fabric.Object} target 48378 */ 48379 _handleGroupLogic: function (e, target) { 48380 if (target === this.getActiveGroup()) { 48381 // if it's a group, find target again, this time skipping group 48382 target = this.findTarget(e, true); 48383 // if even object is not found, bail out 48384 if (!target || target.isType('group')) { 48385 return; 48386 } 48387 } 48388 var activeGroup = this.getActiveGroup(); 48389 if (activeGroup) { 48390 if (activeGroup.contains(target)) { 48391 activeGroup.removeWithUpdate(target); 48392 this._resetObjectTransform(activeGroup); 48393 target.set('active', false); 48394 if (activeGroup.size() === 1) { 48395 // remove group alltogether if after removal it only contains 1 object 48396 this.discardActiveGroup(); 48397 } 48398 } 48399 else { 48400 activeGroup.addWithUpdate(target); 48401 this._resetObjectTransform(activeGroup); 48402 } 48403 this.fire('selection:created', { target: activeGroup, e: e }); 48404 activeGroup.set('active', true); 48405 } 48406 else { 48407 // group does not exist 48408 if (this._activeObject) { 48409 // only if there's an active object 48410 if (target !== this._activeObject) { 48411 // and that object is not the actual target 48412 var objects = this.getObjects(); 48413 var isActiveLower = objects.indexOf(this._activeObject) < objects.indexOf(target); 48414 var group = new fabric.Group( 48415 isActiveLower ? [ target, this._activeObject ] : [ this._activeObject, target ]); 48416 48417 this.setActiveGroup(group); 48418 this._activeObject = null; 48419 activeGroup = this.getActiveGroup(); 48420 this.fire('selection:created', { target: activeGroup, e: e }); 48421 } 48422 } 48423 // activate target object in any case 48424 target.set('active', true); 48425 } 48426 48427 if (activeGroup) { 48428 activeGroup.saveCoords(); 48429 } 48430 }, 48431 48432 /** 48433 * Translates object by "setting" its left/top 48434 * @private 48435 * @param x {Number} pointer's x coordinate 48436 * @param y {Number} pointer's y coordinate 48437 */
48438 _translateObject: function (x, y) { 48439 var target = this._currentTransform.target; 48440 48441 if (!target.get('lockMovementX')) { 48442 target.set('left', x - this._currentTransform.offsetX); 48443 } 48444 if (!target.get('lockMovementY')) { 48445 target.set('top', y - this._currentTransform.offsetY); 48446 } 48447 }, 48448 48449 /** 48450 * Scales object by invoking its scaleX/scaleY methods 48451 * @private 48452 * @param x {Number} pointer's x coordinate 48453 * @param y {Number} pointer's y coordinate 48454 * @param by {String} Either 'x' or 'y' - specifies dimension constraint by which to scale an object. 48455 * When not provided, an object is scaled by both dimensions equally 48456 */ 48457 _scaleObject: function (x, y, by) { 48458 var t = this._currentTransform, 48459 offset = this._offset, 48460 target = t.target; 48461 48462 var lockScalingX = target.get('lockScalingX'), 48463 lockScalingY = target.get('lockScalingY'); 48464 48465 if (lockScalingX && lockScalingY) return; 48466 48467 // Get the constraint point 48468 var constraintPosition = target.translateToOriginPoint(target.getCenterPoint(), t.originX, t.originY); 48469 var localMouse = target.toLocalPoint(new fabric.Point(x - offset.left, y - offset.top), t.originX, t.originY); 48470 48471 if (t.originX === 'right') { 48472 localMouse.x *= -1; 48473 } 48474 else if (t.originX === 'center') { 48475 localMouse.x *= t.mouseXSign * 2; 48476 48477 if (localMouse.x < 0) { 48478 t.mouseXSign = -t.mouseXSign; 48479 } 48480 } 48481 48482 if (t.originY === 'bottom') { 48483 localMouse.y *= -1; 48484 } 48485 else if (t.originY === 'center') { 48486 localMouse.y *= t.mouseYSign * 2; 48487 48488 if (localMouse.y < 0) { 48489 t.mouseYSign = -t.mouseYSign; 48490 } 48491 } 48492 48493 // adjust the mouse coordinates when dealing with padding 48494 if (abs(localMouse.x) > target.padding) { 48495 if (localMouse.x < 0 ) { 48496 localMouse.x += target.padding; 48497 } else { 48498 localMouse.x -= target.padding; 48499 } 48500 } else { // mouse is within the padding, set to 0 48501 localMouse.x = 0; 48502 } 48503 48504 if (abs(localMouse.y) > target.padding) { 48505 if (localMouse.y < 0 ) { 48506 localMouse.y += target.padding; 48507 } else { 48508 localMouse.y -= target.padding; 48509 } 48510 } else { 48511 localMouse.y = 0; 48512 } 48513 48514 // Actually scale the object 48515 var newScaleX = target.scaleX, newScaleY = target.scaleY; 48516 if (by === 'equally' && !lockScalingX && !lockScalingY) { 48517 var dist = localMouse.y + localMouse.x; 48518 var lastDist = (target.height + (target.strokeWidth)) * t.original.scaleY + 48519 (target.width + (target.strokeWidth)) * t.original.scaleX; 48520 48521 // We use t.scaleX/Y instead of target.scaleX/Y because the object may have a min scale and we'll loose the proportions 48522 newScaleX = t.original.scaleX * dist/lastDist; 48523 newScaleY = t.original.scaleY * dist/lastDist; 48524 48525 target.set('scaleX', newScaleX); 48526 target.set('scaleY', newScaleY); 48527 } 48528 else if (!by) { 48529 newScaleX = localMouse.x/(target.width+target.strokeWidth); 48530 newScaleY = localMouse.y/(target.height+target.strokeWidth); 48531 48532 lockScalingX || target.set('scaleX', newScaleX); 48533 lockScalingY || target.set('scaleY', newScaleY); 48534 } 48535 else if (by === 'x' && !target.get('lockUniScaling')) { 48536 newScaleX = localMouse.x/(target.width + target.strokeWidth); 48537 lockScalingX || target.set('scaleX', newScaleX); 48538 } 48539 else if (by === 'y' && !target.get('lockUniScaling')) { 48540 newScaleY = localMouse.y/(target.height + target.strokeWidth); 48541 lockScalingY || target.set('scaleY', newScaleY); 48542 } 48543 48544 // Check if we flipped 48545 if (newScaleX < 0) 48546 { 48547 if (t.originX === 'left') 48548 t.originX = 'right'; 48549 else if (t.originX === 'right') 48550 t.originX = 'left'; 48551 } 48552 48553 if (newScaleY < 0) 48554 { 48555 if (t.originY === 'top') 48556 t.originY = 'bottom'; 48557 else if (t.originY === 'bottom') 48558 t.originY = 'top'; 48559 } 48560 48561 // Make sure the constraints apply 48562 target.setPositionByOrigin(constraintPosition, t.originX, t.originY); 48563 }, 48564 48565 /** 48566 * Rotates object by invoking its rotate method 48567 * @private 48568 * @param x {Number} pointer's x coordinate 48569 * @param y {Number} pointer's y coordinate 48570 */ 48571 _rotateObject: function (x, y) { 48572 48573 var t = this._currentTransform, 48574 o = this._offset; 48575 48576 if (t.target.get('lockRotation')) return; 48577 48578 var lastAngle = atan2(t.ey - t.top - o.top, t.ex - t.left - o.left), 48579 curAngle = atan2(y - t.top - o.top, x - t.left - o.left), 48580 angle = radiansToDegrees(curAngle - lastAngle + t.theta); 48581 48582 // normalize angle to positive value 48583 if (angle < 0) { 48584 angle = 360 + angle; 48585 } 48586 48587 t.target.angle = angle; 48588 }, 48589 48590 /** 48591 * @private 48592 */ 48593 _setCursor: function (value) { 48594 this.upperCanvasEl.style.cursor = value; 48595 }, 48596 48597 /** 48598 * @private 48599 */ 48600 _resetObjectTransform: function (target) { 48601 target.scaleX = 1; 48602 target.scaleY = 1; 48603 target.setAngle(0); 48604 }, 48605 48606 /** 48607 * @private 48608 */ 48609 _drawSelection: function () { 48610 var ctx = this.contextTop, 48611 groupSelector = this._groupSelector, 48612 left = groupSelector.left, 48613 top = groupSelector.top, 48614 aleft = abs(left), 48615 atop = abs(top); 48616 48617 ctx.fillStyle = this.selectionColor; 48618 48619 ctx.fillRect( 48620 groupSelector.ex - ((left > 0) ? 0 : -left), 48621 groupSelector.ey - ((top > 0) ? 0 : -top), 48622 aleft, 48623 atop 48624 ); 48625 48626 ctx.lineWidth = this.selectionLineWidth; 48627 ctx.strokeStyle = this.selectionBorderColor; 48628 48629 // selection border 48630 if (this.selectionDashArray.length > 1) { 48631 48632 var px = groupSelector.ex + STROKE_OFFSET - ((left > 0) ? 0: aleft); 48633 var py = groupSelector.ey + STROKE_OFFSET - ((top > 0) ? 0: atop); 48634 48635 ctx.beginPath(); 48636 48637 fabric.util.drawDashedLine(ctx, px, py, px+aleft, py, this.selectionDashArray); 48638 fabric.util.drawDashedLine(ctx, px, py+atop-1, px+aleft, py+atop-1, this.selectionDashArray); 48639 fabric.util.drawDashedLine(ctx, px, py, px, py+atop, this.selectionDashArray); 48640 fabric.util.drawDashedLine(ctx, px+aleft-1, py, px+aleft-1, py+atop, this.selectionDashArray); 48641 48642 ctx.closePath(); 48643 ctx.stroke(); 48644 } 48645 else { 48646 ctx.strokeRect( 48647 groupSelector.ex + STROKE_OFFSET - ((left > 0) ? 0 : aleft), 48648 groupSelector.ey + STROKE_OFFSET - ((top > 0) ? 0 : atop), 48649 aleft, 48650 atop 48651 ); 48652 } 48653 }, 48654 48655 /** 48656 * @private 48657 */ 48658 _findSelectedObjects: function (e) { 48659 var group = [ ], 48660 x1 = this._groupSelector.ex, 48661 y1 = this._groupSelector.ey, 48662 x2 = x1 + this._groupSelector.left, 48663 y2 = y1 + this._groupSelector.top, 48664 currentObject, 48665 selectionX1Y1 = new fabric.Point(min(x1, x2), min(y1, y2)), 48666 selectionX2Y2 = new fabric.Point(max(x1, x2), max(y1, y2)), 48667 isClick = x1 === x2 && y1 === y2; 48668 48669 for (var i = this._objects.length; i--; ) { 48670 currentObject = this._objects[i]; 48671 48672 if (!currentObject) continue; 48673 48674 if (currentObject.intersectsWithRect(selectionX1Y1, selectionX2Y2) || 48675 currentObject.isContainedWithinRect(selectionX1Y1, selectionX2Y2) || 48676 currentObject.containsPoint(selectionX1Y1) || 48677 currentObject.containsPoint(selectionX2Y2)) { 48678 48679 if (this.selection && currentObject.selectable) { 48680 currentObject.set('active', true); 48681 group.push(currentObject); 48682 48683 // only add one object if it's a click 48684 if (isClick) break; 48685 } 48686 } 48687 } 48688 48689 // do not create group for 1 element only 48690 if (group.length === 1) { 48691 this.setActiveObject(group[0], e); 48692 } 48693 else if (group.length > 1) { 48694 group = new fabric.Group(group.reverse()); 48695 this.setActiveGroup(group); 48696 group.saveCoords(); 48697 this.fire('selection:created', { target: group }); 48698 this.renderAll(); 48699 } 48700 }, 48701 48702 /** 48703 * Method that determines what object we are clicking on 48704 * @param {Event} e mouse event 48705 * @param {Boolean} skipGroup when true, group is skipped and only objects are traversed through 48706 */ 48707 findTarget: function (e, skipGroup) { 48708 if (this.skipTargetFind) return; 48709 48710 var target, 48711 pointer = this.getPointer(e); 48712 48713 if (this.controlsAboveOverlay && 48714 this.lastRenderedObjectWithControlsAboveOverlay && 48715 this.lastRenderedObjectWithControlsAboveOverlay.visible && 48716 this.containsPoint(e, this.lastRenderedObjectWithControlsAboveOverlay) && 48717 this.lastRenderedObjectWithControlsAboveOverlay._findTargetCorner(e, this._offset)) { 48718 target = this.lastRenderedObjectWithControlsAboveOverlay; 48719 return target; 48720 } 48721 48722 // first check current group (if one exists) 48723 var activeGroup = this.getActiveGroup(); 48724 if (activeGroup && !skipGroup && this.containsPoint(e, activeGroup)) { 48725 target = activeGroup; 48726 return target; 48727 } 48728 48729 // then check all of the objects on canvas 48730 // Cache all targets where their bounding box contains point. 48731 var possibleTargets = []; 48732 48733 for (var i = this._objects.length; i--; ) { 48734 48735 if (this._objects[i] && 48736 this._objects[i].visible && 48737 this._objects[i].evented && 48738 this.containsPoint(e, this._objects[i])) { 48739 48740 if (this.perPixelTargetFind || this._objects[i].perPixelTargetFind) { 48741 possibleTargets[possibleTargets.length] = this._objects[i]; 48742 } 48743 else { 48744 target = this._objects[i]; 48745 this.relatedTarget = target; 48746 break; 48747 } 48748 } 48749 } 48750 for (var j = 0, len = possibleTargets.length; j < len; j++) { 48751 pointer = this.getPointer(e);
48752 var isTransparent = this.isTargetTransparent(possibleTargets[j], pointer.x, pointer.y); 48753 if (!isTransparent) { 48754 target = possibleTargets[j]; 48755 this.relatedTarget = target; 48756 break; 48757 } 48758 } 48759 48760 return target; 48761 }, 48762 48763 /** 48764 * Returns pointer coordinates relative to canvas. 48765 * @param {Event} e 48766 * @return {Object} object with "x" and "y" number values 48767 */ 48768 getPointer: function (e) { 48769 var pointer = getPointer(e, this.upperCanvasEl); 48770 return { 48771 x: pointer.x - this._offset.left, 48772 y: pointer.y - this._offset.top 48773 }; 48774 }, 48775 48776 /** 48777 * @private 48778 * @param {HTMLElement|String} canvasEl Canvas element 48779 * @throws {CANVAS_INIT_ERROR} If canvas can not be initialized 48780 */ 48781 _createUpperCanvas: function () { 48782 var lowerCanvasClass = this.lowerCanvasEl.className.replace(/\s*lower-canvas\s*/, ''); 48783 48784 this.upperCanvasEl = this._createCanvasElement(); 48785 fabric.util.addClass(this.upperCanvasEl, 'upper-canvas ' + lowerCanvasClass); 48786 48787 this.wrapperEl.appendChild(this.upperCanvasEl); 48788 48789 this._copyCanvasStyle(this.lowerCanvasEl, this.upperCanvasEl); 48790 this._applyCanvasStyle(this.upperCanvasEl); 48791 this.contextTop = this.upperCanvasEl.getContext('2d'); 48792 }, 48793 48794 /** 48795 * @private 48796 */ 48797 _createCacheCanvas: function () { 48798 this.cacheCanvasEl = this._createCanvasElement(); 48799 this.cacheCanvasEl.setAttribute('width', this.width); 48800 this.cacheCanvasEl.setAttribute('height', this.height); 48801 this.contextCache = this.cacheCanvasEl.getContext('2d'); 48802 }, 48803 48804 /** 48805 * @private 48806 * @param {Number} width 48807 * @param {Number} height 48808 */ 48809 _initWrapperElement: function () { 48810 this.wrapperEl = fabric.util.wrapElement(this.lowerCanvasEl, 'div', { 48811 'class': this.containerClass 48812 }); 48813 fabric.util.setStyle(this.wrapperEl, { 48814 width: this.getWidth() + 'px', 48815 height: this.getHeight() + 'px', 48816 position: 'relative' 48817 }); 48818 fabric.util.makeElementUnselectable(this.wrapperEl); 48819 }, 48820 48821 /** 48822 * @private 48823 * @param {Element} element 48824 */ 48825 _applyCanvasStyle: function (element) { 48826 var width = this.getWidth() || element.width, 48827 height = this.getHeight() || element.height; 48828 48829 fabric.util.setStyle(element, { 48830 position: 'absolute', 48831 width: width + 'px', 48832 height: height + 'px', 48833 left: 0, 48834 top: 0 48835 }); 48836 element.width = width; 48837 element.height = height; 48838 fabric.util.makeElementUnselectable(element); 48839 }, 48840 48841 /** 48842 * Copys the the entire inline style from one element (fromEl) to another (toEl) 48843 * @private 48844 * @param {Element} fromEl Element style is copied from 48845 * @param {Element} toEl Element copied style is applied to 48846 */ 48847 _copyCanvasStyle: function (fromEl, toEl) { 48848 toEl.style.cssText = fromEl.style.cssText; 48849 }, 48850 48851 /** 48852 * Returns context of canvas where object selection is drawn 48853 * @return {CanvasRenderingContext2D} 48854 */ 48855 getSelectionContext: function() { 48856 return this.contextTop; 48857 }, 48858 48859 /** 48860 * Returns <canvas> element on which object selection is drawn 48861 * @return {HTMLCanvasElement} 48862 */ 48863 getSelectionElement: function () {
48864 return this.upperCanvasEl; 48865 }, 48866 48867 /** 48868 * Sets given object as the only active object on canvas 48869 * @param {fabric.Object} object Object to set as an active one 48870 * @param {Event} [e] Event (passed along when firing "object:selected") 48871 * @return {fabric.Canvas} thisArg 48872 * @chainable 48873 */ 48874 setActiveObject: function (object, e) { 48875 if (this._activeObject) { 48876 this._activeObject.set('active', false); 48877 } 48878 this._activeObject = object; 48879 object.set('active', true); 48880 48881 this.renderAll(); 48882 48883 this.fire('object:selected', { target: object, e: e }); 48884 object.fire('selected', { e: e }); 48885 return this; 48886 }, 48887 48888 /** 48889 * Returns currently active object 48890 * @return {fabric.Object} active object 48891 */ 48892 getActiveObject: function () { 48893 return this._activeObject; 48894 }, 48895 48896 /** 48897 * Discards currently active object 48898 * @return {fabric.Canvas} thisArg 48899 * @chainable 48900 */ 48901 discardActiveObject: function () { 48902 if (this._activeObject) { 48903 this._activeObject.set('active', false); 48904 } 48905 this._activeObject = null; 48906 return this; 48907 }, 48908 48909 /** 48910 * Sets active group to a speicified one 48911 * @param {fabric.Group} group Group to set as a current one 48912 * @return {fabric.Canvas} thisArg 48913 * @chainable 48914 */ 48915 setActiveGroup: function (group) { 48916 this._activeGroup = group; 48917 if (group) { 48918 group.canvas = this; 48919 group.set('active', true); 48920 } 48921 return this; 48922 }, 48923 48924 /** 48925 * Returns currently active group 48926 * @return {fabric.Group} Current group 48927 */ 48928 getActiveGroup: function () { 48929 return this._activeGroup; 48930 }, 48931 48932 /** 48933 * Removes currently active group 48934 * @return {fabric.Canvas} thisArg 48935 */ 48936 discardActiveGroup: function () { 48937 var g = this.getActiveGroup(); 48938 if (g) { 48939 g.destroy(); 48940 } 48941 return this.setActiveGroup(null); 48942 }, 48943 48944 /** 48945 * Deactivates all objects on canvas, removing any active group or object 48946 * @return {fabric.Canvas} thisArg 48947 */ 48948 deactivateAll: function () { 48949 var allObjects = this.getObjects(), 48950 i = 0, 48951 len = allObjects.length; 48952 for ( ; i < len; i++) { 48953 allObjects[i].set('active', false); 48954 } 48955 this.discardActiveGroup(); 48956 this.discardActiveObject(); 48957 return this; 48958 }, 48959 48960 /** 48961 * Deactivates all objects and dispatches appropriate events 48962 * @return {fabric.Canvas} thisArg 48963 */ 48964 deactivateAllWithDispatch: function () { 48965 var activeObject = this.getActiveGroup() || this.getActiveObject(); 48966 if (activeObject) { 48967 this.fire('before:selection:cleared', { target: activeObject }); 48968 } 48969 this.deactivateAll(); 48970 if (activeObject) { 48971 this.fire('selection:cleared'); 48972 } 48973 return this; 48974 }, 48975 48976 /** 48977 * Draws objects' controls (borders/controls) 48978 * @param {CanvasRenderingContext2D} ctx Context to render controls on 48979 */ 48980 drawControls: function(ctx) { 48981 var activeGroup = this.getActiveGroup(); 48982 if (activeGroup) { 48983 ctx.save(); 48984 fabric.Group.prototype.transform.call(activeGroup, ctx); 48985 activeGroup.drawBorders(ctx).drawControls(ctx); 48986 ctx.restore(); 48987 } 48988 else { 48989 for (var i = 0, len = this._objects.length; i < len; ++i) { 48990 if (!this._objects[i] || !this._objects[i].active) continue; 48991 48992 ctx.save(); 48993 fabric.Object.prototype.transform.call(this._objects[i], ctx); 48994 this._objects[i].drawBorders(ctx).drawControls(ctx); 48995 ctx.restore(); 48996 48997 this.lastRenderedObjectWithControlsAboveOverlay = this._objects[i]; 48998 } 48999 } 49000 } 49001 }); 49002 49003 // copying static properties manually to work around Opera's bug, 49004 // where "prototype" property is enumerable and overrides existing prototype 49005 for (var prop in fabric.StaticCanvas) { 49006 if (prop !== 'prototype') { 49007 fabric.Canvas[prop] = fabric.StaticCanvas[prop]; 49008 } 49009 } 49010 49011 if (fabric.isTouchSupported) { 49012 /** @ignore */ 49013 fabric.Canvas.prototype._setCursorFromEvent = function() { }; 49014 } 49015 49016 /** 49017 * @class fabric.Element 49018 * @alias fabric.Canvas 49019 * @deprecated Use {@link fabric.Canvas} instead. 49020 * @constructor 49021 */ 49022 fabric.Element = fabric.Canvas; 49023})(); 49024 49025 49026(function(){ 49027 49028 var cursorMap = [ 49029 'n-resize', 49030 'ne-resize', 49031 'e-resize', 49032 'se-resize', 49033 's-resize', 49034 'sw-resize', 49035 'w-resize', 49036 'nw-resize' 49037 ],
49038 cursorOffset = { 49039 'mt': 0, // n 49040 'tr': 1, // ne 49041 'mr': 2, // e 49042 'br': 3, // se 49043 'mb': 4, // s 49044 'bl': 5, // sw 49045 'ml': 6, // w 49046 'tl': 7 // nw 49047 }, 49048 addListener = fabric.util.addListener, 49049 removeListener = fabric.util.removeListener, 49050 getPointer = fabric.util.getPointer; 49051 49052 fabric.util.object.extend(fabric.Canvas.prototype, /** @lends fabric.Canvas.prototype */ { 49053 49054 /** 49055 * Adds mouse listeners to canvas 49056 * @private 49057 */ 49058 _initEvents: function () { 49059 var _this = this; 49060 49061 this._onMouseDown = this._onMouseDown.bind(this); 49062 this._onMouseMove = this._onMouseMove.bind(this); 49063 this._onMouseUp = this._onMouseUp.bind(this); 49064 this._onResize = this._onResize.bind(this); 49065 49066 this._onGesture = function(e, s) { 49067 _this.__onTransformGesture(e, s); 49068 }; 49069 49070 addListener(fabric.window, 'resize', this._onResize); 49071 49072 if (fabric.isTouchSupported) { 49073 addListener(this.upperCanvasEl, 'touchstart', this._onMouseDown); 49074 addListener(this.upperCanvasEl, 'touchmove', this._onMouseMove); 49075 49076 if (typeof Event !== 'undefined' && 'add' in Event) { 49077 Event.add(this.upperCanvasEl, 'gesture', this._onGesture); 49078 } 49079 } 49080 else { 49081 addListener(this.upperCanvasEl, 'mousedown', this._onMouseDown); 49082 addListener(this.upperCanvasEl, 'mousemove', this._onMouseMove); 49083 } 49084 }, 49085 49086 /** 49087 * @private 49088 * @param {Event} e Event object fired on mousedown 49089 */ 49090 _onMouseDown: function (e) { 49091 this.__onMouseDown(e); 49092 49093 !fabric.isTouchSupported && addListener(fabric.document, 'mouseup', this._onMouseUp); 49094 fabric.isTouchSupported && addListener(fabric.document, 'touchend', this._onMouseUp); 49095 49096 !fabric.isTouchSupported && addListener(fabric.document, 'mousemove', this._onMouseMove); 49097 fabric.isTouchSupported && addListener(fabric.document, 'touchmove', this._onMouseMove); 49098 49099 !fabric.isTouchSupported && removeListener(this.upperCanvasEl, 'mousemove', this._onMouseMove); 49100 fabric.isTouchSupported && removeListener(this.upperCanvasEl, 'touchmove', this._onMouseMove); 49101 }, 49102 49103 /** 49104 * @private 49105 * @param {Event} e Event object fired on mouseup 49106 */ 49107 _onMouseUp: function (e) { 49108 this.__onMouseUp(e); 49109 49110 !fabric.isTouchSupported && removeListener(fabric.document, 'mouseup', this._onMouseUp); 49111 fabric.isTouchSupported && removeListener(fabric.document, 'touchend', this._onMouseUp); 49112 49113 !fabric.isTouchSupported && removeListener(fabric.document, 'mousemove', this._onMouseMove); 49114 fabric.isTouchSupported && removeListener(fabric.document, 'touchmove', this._onMouseMove); 49115 49116 !fabric.isTouchSupported && addListener(this.upperCanvasEl, 'mousemove', this._onMouseMove); 49117 fabric.isTouchSupported && addListener(this.upperCanvasEl, 'touchmove', this._onMouseMove); 49118 }, 49119 49120 /** 49121 * @private 49122 * @param {Event} e Event object fired on mousemove 49123 */ 49124 _onMouseMove: function (e) { 49125 !this.allowTouchScrolling && e.preventDefault && e.preventDefault(); 49126 this.__onMouseMove(e); 49127 }, 49128 49129 /** 49130 * @private 49131 */ 49132 _onResize: function () { 49133 this.calcOffset(); 49134 }, 49135 49136 /** 49137 * Decides whether the canvas should be redrawn in mouseup and mousedown events. 49138 * @private 49139 * @param {Object} target 49140 * @param {Object} pointer 49141 */ 49142 _shouldRender: function(target, pointer) { 49143 var activeObject = this.getActiveGroup() || this.getActiveObject(); 49144 49145 return ( 49146 (target && ( 49147 target.isMoving || 49148 target !== activeObject)) || 49149 (!target && activeObject) || 49150 (pointer && 49151 this._previousPointer && 49152 this.selection && ( 49153 pointer.x !== this._previousPointer.x || 49154 pointer.y !== this._previousPointer.y)) 49155 ); 49156 }, 49157 49158 /** 49159 * Method that defines the actions when mouse is released on canvas. 49160 * The method resets the currentTransform parameters, store the image corner 49161 * position in the image object and render the canvas on top. 49162 * @private 49163 * @param {Event} e Event object fired on mouseup 49164 */ 49165 __onMouseUp: function (e) { 49166 var target, 49167 pointer, 49168 render; 49169 49170 if (this.isDrawingMode && this._isCurrentlyDrawing) { 49171 this._isCurrentlyDrawing = false;
49172 if (this.clipTo) { 49173 this.contextTop.restore(); 49174 } 49175 this.freeDrawingBrush.onMouseUp(); 49176 this.fire('mouse:up', { e: e }); 49177 return; 49178 } 49179 49180 if (this._currentTransform) { 49181 49182 var transform = this._currentTransform; 49183 49184 target = transform.target; 49185 if (target._scaling) { 49186 target._scaling = false; 49187 } 49188 49189 target.setCoords(); 49190 49191 // only fire :modified event if target coordinates were changed during mousedown-mouseup 49192 if (this.stateful && target.hasStateChanged()) { 49193 this.fire('object:modified', { target: target }); 49194 target.fire('modified'); 49195 } 49196 49197 if (this._previousOriginX && this._previousOriginY) { 49198 49199 var originPoint = target.translateToOriginPoint( 49200 target.getCenterPoint(), 49201 this._previousOriginX, 49202 this._previousOriginY); 49203 49204 target.originX = this._previousOriginX; 49205 target.originY = this._previousOriginY; 49206 49207 target.left = originPoint.x; 49208 target.top = originPoint.y; 49209 49210 this._previousOriginX = null; 49211 this._previousOriginY = null; 49212 } 49213 } 49214 else { 49215 pointer = this.getPointer(e); 49216 } 49217 49218 render = this._shouldRender(target, pointer); 49219 49220 if (this.selection && this._groupSelector) { 49221 // group selection was completed, determine its bounds 49222 this._findSelectedObjects(e); 49223 } 49224 49225 var activeGroup = this.getActiveGroup(); 49226 if (activeGroup) { 49227 activeGroup.setObjectsCoords(); 49228 activeGroup.isMoving = false; 49229 this._setCursor(this.defaultCursor); 49230 } 49231 49232 // clear selection and current transformation 49233 this._groupSelector = null; 49234 this._currentTransform = null; 49235 49236 if (target) { 49237 target.isMoving = false; 49238 } 49239 49240 render && this.renderAll(); 49241 49242 this._setCursorFromEvent(e, target); 49243 49244 var _this = this; 49245 setTimeout(function () { 49246 _this._setCursorFromEvent(e, target); 49247 }, 50); 49248 49249 this.fire('mouse:up', { target: target, e: e }); 49250 target && target.fire('mouseup', { e: e }); 49251 }, 49252 49253 /** 49254 * @private 49255 * @param {Event} e Event object fired on mousedown 49256 */ 49257 _onMouseDownInDrawingMode: function(e) { 49258 this._isCurrentlyDrawing = true; 49259 this.discardActiveObject().renderAll(); 49260 if (this.clipTo) { 49261 fabric.util.clipContext(this, this.contextTop); 49262 } 49263 this.freeDrawingBrush.onMouseDown(this.getPointer(e)); 49264 this.fire('mouse:down', { e: e }); 49265 }, 49266 49267 /** 49268 * Method that defines the actions when mouse is clic ked on canvas. 49269 * The method inits the currentTransform parameters and renders all the 49270 * canvas so the current image can be placed on the top canvas and the rest 49271 * in on the container one. 49272 * @private 49273 * @param {Event} e Event object fired on mousedown 49274 */ 49275 __onMouseDown: function (e) { 49276 // accept only left clicks 49277 var isLeftClick = 'which' in e ? e.which === 1 : e.button === 1; 49278 if (!isLeftClick && !fabric.isTouchSupported) return; 49279 49280 if (this.isDrawingMode) { 49281 this._onMouseDownInDrawingMode(e); 49282 return; 49283 } 49284 49285 // ignore if some object is being transformed at this moment 49286 if (this._currentTransform) return; 49287 49288 var target = this.findTarget(e), 49289 pointer = this.getPointer(e), 49290 corner, 49291 render; 49292 49293 // save pointer for check in __onMouseUp event 49294 this._previousPointer = pointer; 49295 49296 render = this._shouldRender(target, pointer); 49297 49298 if (this._shouldClearSelection(e, target)) { 49299 if (this.selection) { 49300 this._groupSelector = { 49301 ex: pointer.x, 49302 ey: pointer.y, 49303 top: 0, 49304 left: 0 49305 }; 49306 } 49307 this.deactivateAllWithDispatch(); 49308 target && target.selectable && this.setActiveObject(target, e); 49309 } 49310 else if (this._shouldHandleGroupLogic(e, target)) { 49311 this._handleGroupLogic(e, target); 49312 target = this.getActiveGroup(); 49313 } 49314 else { 49315 // determine if it's a drag or rotate case 49316 this.stateful && target.saveState(); 49317 49318 if ((corner = target._findTargetCorner(e, this._offset))) { 49319 this.onBeforeScaleRotate(target); 49320 } 49321 49322 if (target !== this.getActiveGroup() && target !== this.getActiveObject()) { 49323 this.deactivateAll(); 49324 this.setActiveObject(target, e); 49325 } 49326 49327 this._setupCurrentTransform(e, target); 49328 } 49329 // we must renderAll so that active image is placed on the top canvas 49330 render && this.renderAll(); 49331
49332 this.fire('mouse:down', { target: target, e: e }); 49333 target && target.fire('mousedown', { e: e }); 49334 }, 49335 49336 /** 49337 * @private 49338 * @param {Object} target Object for that origin is set to center 49339 */ 49340 _setOriginToCenter: function(target) { 49341 this._previousOriginX = this._currentTransform.target.originX; 49342 this._previousOriginY = this._currentTransform.target.originY; 49343 49344 var center = target.getCenterPoint(); 49345 49346 target.originX = 'center'; 49347 target.originY = 'center'; 49348 49349 target.left = center.x; 49350 target.top = center.y; 49351 49352 this._currentTransform.left = target.left; 49353 this._currentTransform.top = target.top; 49354 }, 49355 49356 /** 49357 * @private 49358 * @param {Object} target Object for that center is set to origin 49359 */ 49360 _setCenterToOrigin: function(target) { 49361 var originPoint = target.translateToOriginPoint( 49362 target.getCenterPoint(), 49363 this._previousOriginX, 49364 this._previousOriginY); 49365 49366 target.originX = this._previousOriginX; 49367 target.originY = this._previousOriginY; 49368 49369 target.left = originPoint.x; 49370 target.top = originPoint.y; 49371 49372 this._previousOriginX = null; 49373 this._previousOriginY = null; 49374 }, 49375 49376 /** 49377 * Method that defines the actions when mouse is hovering the canvas. 49378 * The currentTransform parameter will definde whether the user is rotating/scaling/translating 49379 * an image or neither of them (only hovering). A group selection is also possible and would cancel 49380 * all any other type of action. 49381 * In case of an image transformation only the top canvas will be rendered. 49382 * @private 49383 * @param {Event} e Event object fired on mousemove 49384 */ 49385 __onMouseMove: function (e) { 49386 var target, pointer; 49387 49388 if (this.isDrawingMode) { 49389 if (this._isCurrentlyDrawing) { 49390 pointer = this.getPointer(e); 49391 this.freeDrawingBrush.onMouseMove(pointer); 49392 } 49393 this.upperCanvasEl.style.cursor = this.freeDrawingCursor; 49394 this.fire('mouse:move', { e: e }); 49395 return; 49396 } 49397 49398 var groupSelector = this._groupSelector; 49399 49400 // We initially clicked in an empty area, so we draw a box for multiple selection. 49401 if (groupSelector) { 49402 pointer = getPointer(e, this.upperCanvasEl); 49403 49404 groupSelector.left = pointer.x - this._offset.left - groupSelector.ex; 49405 groupSelector.top = pointer.y - this._offset.top - groupSelector.ey; 49406 this.renderTop(); 49407 } 49408 else if (!this._currentTransform) { 49409 49410 // alias style to elimintate unnecessary lookup 49411 var style = this.upperCanvasEl.style; 49412 49413 // Here we are hovering the canvas then we will determine 49414 // what part of the pictures we are hovering to change the caret symbol. 49415 // We won't do that while dragging or rotating in order to improve the 49416 // performance. 49417 target = this.findTarget(e); 49418 49419 if (!target || target && !target.selectable) { 49420 // no target - set default cursor 49421 style.cursor = this.defaultCursor; 49422 } 49423 else { 49424 // set proper cursor 49425 this._setCursorFromEvent(e, target); 49426 } 49427 } 49428 else { 49429 // object is being transformed (scaled/rotated/moved/etc.) 49430 pointer = getPointer(e, this.upperCanvasEl); 49431 49432 var x = pointer.x, 49433 y = pointer.y, 49434 reset = false, 49435 centerTransform, 49436 transform = this._currentTransform; 49437 49438 target = transform.target; 49439 target.isMoving = true; 49440 49441 if (transform.action === 'scale' || transform.action === 'scaleX' || transform.action === 'scaleY') { 49442 centerTransform = this._shouldCenterTransform(e, target); 49443 49444 // Switch from a normal resize to center-based 49445 if ((centerTransform && (transform.originX !== 'center' || transform.originY !== 'center')) || 49446 // Switch from center-based resize to normal one 49447 (!centerTransform && transform.originX === 'center' && transform.originY === 'center') 49448 ) { 49449 this._resetCurrentTransform(e); 49450 reset = true; 49451 } 49452 } 49453 49454 if (transform.action === 'rotate') { 49455 this._rotateObject(x, y); 49456 49457 this.fire('object:rotating', { target: target, e: e }); 49458 target.fire('rotating', { e: e }); 49459 } 49460 else if (transform.action === 'scale') { 49461 // rotate object only if shift key is not pressed 49462 // and if it is not a group we are transforming 49463 if ((e.shiftKey || this.uniScaleTransform) && !target.get('lockUniScaling')) { 49464 transform.currentAction = 'scale'; 49465 this._scaleObject(x, y); 49466 } 49467 else { 49468 // Switch from a normal resize to proportional 49469 if (!reset && transform.currentAction === 'scale') { 49470 this._resetCurrentTransform(e, target); 49471 } 49472 49473 transform.currentAction = 'scaleEqually'; 49474 this._scaleObject(x, y, 'equally'); 49475 } 49476 49477 this.fire('object:scaling', { target: target, e: e }); 49478 target.fire('scaling', { e: e }); 49479 } 49480 else if (transform.action === 'scaleX') { 49481 this._scaleObject(x, y, 'x'); 49482 49483 this.fire('object:scaling', { target: target, e: e}); 49484 target.fire('scaling', { e: e }); 49485 } 49486 else if (transform.action === 'scaleY') { 49487 this._scaleObject(x, y, 'y'); 49488 49489 this.fire('object:scaling', { target: target, e: e}); 49490 target.fire('scaling', { e: e }); 49491 } 49492 else {
49493 this._translateObject(x, y); 49494 49495 this.fire('object:moving', { target: target, e: e}); 49496 target.fire('moving', { e: e }); 49497 this._setCursor(this.moveCursor); 49498 } 49499 49500 this.renderAll(); 49501 } 49502 this.fire('mouse:move', { target: target, e: e }); 49503 target && target.fire('mousemove', { e: e }); 49504 }, 49505 49506 /** 49507 * Sets the cursor depending on where the canvas is being hovered. 49508 * Note: very buggy in Opera 49509 * @param {Event} e Event object 49510 * @param {Object} target Object that the mouse is hovering, if so. 49511 */ 49512 _setCursorFromEvent: function (e, target) { 49513 var s = this.upperCanvasEl.style; 49514 if (!target) { 49515 s.cursor = this.defaultCursor; 49516 return false; 49517 } 49518 else { 49519 var activeGroup = this.getActiveGroup(); 49520 // only show proper corner when group selection is not active 49521 var corner = target._findTargetCorner 49522 && (!activeGroup || !activeGroup.contains(target)) 49523 && target._findTargetCorner(e, this._offset); 49524 49525 if (!corner) { 49526 s.cursor = target.hoverCursor || this.hoverCursor; 49527 } 49528 else { 49529 if (corner in cursorOffset) { 49530 var n = Math.round((target.getAngle() % 360) / 45); 49531 if (n<0) { 49532 n += 8; // full circle ahead 49533 } 49534 n += cursorOffset[corner]; 49535 // normalize n to be from 0 to 7 49536 n %= 8; 49537 s.cursor = cursorMap[n]; 49538 } 49539 else if (corner === 'mtr' && target.hasRotatingPoint) { 49540 s.cursor = this.rotationCursor; 49541 } 49542 else { 49543 s.cursor = this.defaultCursor; 49544 return false; 49545 } 49546 } 49547 } 49548 return true; 49549 } 49550 }); 49551})(); 49552 49553 49554fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.StaticCanvas.prototype */ { 49555 49556 /** 49557 * Exports canvas element to a dataurl image. Note that when multiplier is used, cropping is scaled appropriately 49558 * @param {Object} [options] Options object 49559 * @param {String} [options.format=png] The format of the output image. Either "jpeg" or "png" 49560 * @param {Number} [options.quality=1] Quality level (0..1). Only used for jpeg. 49561 * @param {Number} [options.multiplier=1] Multiplier to scale by 49562 * @param {Number} [options.left] Cropping left offset. Introduced in v1.2.14 49563 * @param {Number} [options.top] Cropping top offset. Introduced in v1.2.14 49564 * @param {Number} [options.width] Cropping width. Introduced in v1.2.14 49565 * @param {Number} [options.height] Cropping height. Introduced in v1.2.14 49566 * @return {String} Returns a data: URL containing a representation of the object in the format specified by options.format 49567 * @see {@link http://jsfiddle.net/fabricjs/NfZVb/|jsFiddle demo} 49568 * @example <caption>Generate jpeg dataURL with lower quality</caption> 49569 * var dataURL = canvas.toDataURL({ 49570 * format: 'jpeg', 49571 * quality: 0.8 49572 * }); 49573 * @example <caption>Generate cropped png dataURL (clipping of canvas)</caption> 49574 * var dataURL = canvas.toDataURL({ 49575 * format: 'png', 49576 * left: 100, 49577 * top: 100, 49578 * width: 200, 49579 * height: 200 49580 * }); 49581 * @example <caption>Generate double scaled png dataURL</caption> 49582 * var dataURL = canvas.toDataURL({ 49583 * format: 'png', 49584 * multiplier: 2 49585 * }); 49586 */ 49587 toDataURL: function (options) { 49588 options || (options = { }); 49589 49590 var format = options.format || 'png', 49591 quality = options.quality || 1, 49592 multiplier = options.multiplier || 1, 49593 cropping = { 49594 left: options.left, 49595 top: options.top, 49596 width: options.width, 49597 height: options.height 49598 }; 49599 49600 if (multiplier !== 1) { 49601 return this.__toDataURLWithMultiplier(format, quality, cropping, multiplier); 49602 } 49603 else { 49604 return this.__toDataURL(format, quality, cropping); 49605 } 49606 }, 49607 49608 /** 49609 * @private 49610 */ 49611 __toDataURL: function(format, quality, cropping) { 49612 49613 this.renderAll(true); 49614 49615 var canvasEl = this.upperCanvasEl || this.lowerCanvasEl; 49616 var croppedCanvasEl = this.__getCroppedCanvas(canvasEl, cropping); 49617 49618 // to avoid common confusion https://github.com/kangax/fabric.js/issues/806 49619 if (format === 'jpg') { 49620 format = 'jpeg'; 49621 } 49622 49623 var data = (fabric.StaticCanvas.supports('toDataURLWithQuality')) 49624 ? (croppedCanvasEl || canvasEl).toDataURL('image/' + format, quality) 49625 : (croppedCanvasEl || canvasEl).toDataURL('image/' + format); 49626 49627 this.contextTop && this.clearContext(this.contextTop); 49628 this.renderAll(); 49629 49630 if (croppedCanvasEl) { 49631 croppedCanvasEl = null; 49632 } 49633 49634 return data; 49635 }, 49636 49637 /** 49638 * @private 49639 */ 49640 __getCroppedCanvas: function(canvasEl, cropping) { 49641 49642 var croppedCanvasEl, 49643 croppedCtx; 49644 49645 var shouldCrop = 'left' in cropping || 49646 'top' in cropping || 49647 'width' in cropping || 49648 'height' in cropping; 49649 49650 if (shouldCrop) { 49651 49652 croppedCanvasEl = fabric.util.createCanvasElement(); 49653 croppedCtx = croppedCanvasEl.getContext('2d'); 49654 49655 croppedCanvasEl.width = cropping.width || this.width; 49656 croppedCanvasEl.height = cropping.height || this.height; 49657 49658 croppedCtx.drawImage(canvasEl, -cropping.left || 0, -cropping.top || 0); 49659 } 49660 49661 return croppedCanvasEl; 49662 }, 49663 49664 /** 49665 * @private 49666 */ 49667 __toDataURLWithMultiplier: function(format, quality, cropping, multiplier) { 49668 49669 var origWidth = this.getWidth(), 49670 origHeight = this.getHeight(), 49671 scaledWidth = origWidth * multiplier, 49672 scaledHeight = origHeight * multiplier, 49673 activeObject = this.getActiveObject(), 49674 activeGroup = this.getActiveGroup(), 49675 49676 ctx = this.contextTop || this.contextContainer; 49677 49678 this.setWidth(scaledWidth).setHeight(scaledHeight); 49679 ctx.scale(multiplier, multiplier); 49680 49681 if (cropping.left) { 49682 cropping.left *= multiplier; 49683 } 49684 if (cropping.top) { 49685 cropping.top *= multiplier; 49686 } 49687 if (cropping.width) { 49688 cropping.width *= multiplier; 49689 } 49690 if (cropping.height) { 49691 cropping.height *= multiplier; 49692 } 49693 49694 if (activeGroup) { 49695 // not removing group due to complications with restoring it with correct state afterwords
49696 this._tempRemoveBordersControlsFromGroup(activeGroup); 49697 } 49698 else if (activeObject && this.deactivateAll) { 49699 this.deactivateAll(); 49700 } 49701 49702 // restoring width, height for `renderAll` to draw 49703 // background properly (while context is scaled) 49704 this.width = origWidth; 49705 this.height = origHeight; 49706 49707 this.renderAll(true); 49708 49709 var data = this.__toDataURL(format, quality, cropping); 49710 49711 ctx.scale(1 / multiplier, 1 / multiplier); 49712 this.setWidth(origWidth).setHeight(origHeight); 49713 49714 if (activeGroup) { 49715 this._restoreBordersControlsOnGroup(activeGroup); 49716 } 49717 else if (activeObject && this.setActiveObject) { 49718 this.setActiveObject(activeObject); 49719 } 49720 49721 this.contextTop && this.clearContext(this.contextTop); 49722 this.renderAll(); 49723 49724 return data; 49725 }, 49726 49727 /** 49728 * Exports canvas element to a dataurl image (allowing to change image size via multiplier). 49729 * @deprecated since 1.0.13 49730 * @param {String} format (png|jpeg) 49731 * @param {Number} multiplier 49732 * @param {Number} quality (0..1) 49733 * @return {String} 49734 */ 49735 toDataURLWithMultiplier: function (format, multiplier, quality) { 49736 return this.toDataURL({ 49737 format: format, 49738 multiplier: multiplier, 49739 quality: quality 49740 }); 49741 }, 49742 49743 /** 49744 * @private 49745 */ 49746 _tempRemoveBordersControlsFromGroup: function(group) { 49747 group.origHasControls = group.hasControls; 49748 group.origBorderColor = group.borderColor; 49749 49750 group.hasControls = true; 49751 group.borderColor = 'rgba(0,0,0,0)'; 49752 49753 group.forEachObject(function(o) { 49754 o.origBorderColor = o.borderColor; 49755 o.borderColor = 'rgba(0,0,0,0)'; 49756 }); 49757 }, 49758 49759 /** 49760 * @private 49761 */ 49762 _restoreBordersControlsOnGroup: function(group) { 49763 group.hideControls = group.origHideControls; 49764 group.borderColor = group.origBorderColor; 49765 49766 group.forEachObject(function(o) { 49767 o.borderColor = o.origBorderColor; 49768 delete o.origBorderColor; 49769 }); 49770 } 49771}); 49772 49773 49774fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.StaticCanvas.prototype */ { 49775 49776 /** 49777 * Populates canvas with data from the specified dataless JSON. 49778 * JSON format must conform to the one of {@link fabric.Canvas#toDatalessJSON} 49779 * @deprecated since 1.2.2 49780 * @param {String|Object} json JSON string or object 49781 * @param {Function} callback Callback, invoked when json is parsed 49782 * and corresponding objects (e.g: {@link fabric.Image}) 49783 * are initialized 49784 * @param {Function} [reviver] Method for further parsing of JSON elements, called after each fabric object created. 49785 * @return {fabric.Canvas} instance 49786 * @chainable 49787 * @tutorial {@link http://fabricjs.com/fabric-intro-part-3/#deserialization} 49788 */ 49789 loadFromDatalessJSON: function (json, callback, reviver) { 49790 return this.loadFromJSON(json, callback, reviver); 49791 }, 49792 49793 /** 49794 * Populates canvas with data from the specified JSON. 49795 * JSON format must conform to the one of {@link fabric.Canvas#toJSON} 49796 * @param {String|Object} json JSON string or object 49797 * @param {Function} callback Callback, invoked when json is parsed 49798 * and corresponding objects (e.g: {@link fabric.Image}) 49799 * are initialized 49800 * @param {Function} [reviver] Method for further parsing of JSON elements, called after each fabric object created. 49801 * @return {fabric.Canvas} instance 49802 * @chainable 49803 * @tutorial {@link http://fabricjs.com/fabric-intro-part-3/#deserialization} 49804 * @see {@link http://jsfiddle.net/fabricjs/fmgXt/|jsFiddle demo} 49805 * @example <caption>loadFromJSON</caption> 49806 * canvas.loadFromJSON(json, canvas.renderAll.bind(canvas)); 49807 * @example <caption>loadFromJSON with reviver</caption> 49808 * canvas.loadFromJSON(json, canvas.renderAll.bind(canvas), function(o, object) { 49809 * // `o` = json object 49810 * // `object` = fabric.Object instance 49811 * // ... do some stuff ... 49812 * }); 49813 */ 49814 loadFromJSON: function (json, callback, reviver) { 49815 if (!json) return; 49816 49817 // serialize if it wasn't already 49818 var serialized = (typeof json === 'string') 49819 ? JSON.parse(json) 49820 : json; 49821 49822 this.clear(); 49823 49824 var _this = this; 49825 this._enlivenObjects(serialized.objects, function () { 49826 _this._setBgOverlayImages(serialized, callback); 49827 }, reviver); 49828 49829 return this; 49830 }, 49831 49832 _setBgOverlayImages: function(serialized, callback) { 49833 49834 var _this = this, 49835 backgroundPatternLoaded, 49836 backgroundImageLoaded, 49837 overlayImageLoaded; 49838 49839 var cbIfLoaded = function () { 49840 callback && backgroundImageLoaded && overlayImageLoaded && backgroundPatternLoaded && callback(); 49841 }; 49842 49843 if (serialized.backgroundImage) {
49844 this.setBackgroundImage(serialized.backgroundImage, function() { 49845 49846 _this.backgroundImageOpacity = serialized.backgroundImageOpacity; 49847 _this.backgroundImageStretch = serialized.backgroundImageStretch; 49848 49849 _this.renderAll(); 49850 49851 backgroundImageLoaded = true; 49852 49853 cbIfLoaded(); 49854 }); 49855 } 49856 else { 49857 backgroundImageLoaded = true; 49858 } 49859 49860 if (serialized.overlayImage) { 49861 this.setOverlayImage(serialized.overlayImage, function() { 49862 49863 _this.overlayImageLeft = serialized.overlayImageLeft || 0; 49864 _this.overlayImageTop = serialized.overlayImageTop || 0; 49865 49866 _this.renderAll(); 49867 overlayImageLoaded = true; 49868 49869 cbIfLoaded(); 49870 }); 49871 } 49872 else { 49873 overlayImageLoaded = true; 49874 } 49875 49876 if (serialized.background) { 49877 this.setBackgroundColor(serialized.background, function() { 49878 49879 _this.renderAll(); 49880 backgroundPatternLoaded = true; 49881 49882 cbIfLoaded(); 49883 }); 49884 } 49885 else { 49886 backgroundPatternLoaded = true; 49887 } 49888 49889 if (!serialized.backgroundImage && !serialized.overlayImage && !serialized.background) { 49890 callback && callback(); 49891 } 49892 }, 49893 49894 /** 49895 * @private 49896 * @param {Array} objects 49897 * @param {Function} callback 49898 * @param {Function} [reviver] 49899 */ 49900 _enlivenObjects: function (objects, callback, reviver) { 49901 var _this = this; 49902 49903 if (objects.length === 0) { 49904 callback && callback(); 49905 } 49906 49907 var renderOnAddRemove = this.renderOnAddRemove; 49908 this.renderOnAddRemove = false; 49909 49910 fabric.util.enlivenObjects(objects, function(enlivenedObjects) { 49911 enlivenedObjects.forEach(function(obj, index) { 49912 _this.insertAt(obj, index, true); 49913 }); 49914 49915 _this.renderOnAddRemove = renderOnAddRemove; 49916 callback && callback(); 49917 }, null, reviver); 49918 }, 49919 49920 /** 49921 * @private 49922 * @param {String} format 49923 * @param {Function} callback 49924 */ 49925 _toDataURL: function (format, callback) { 49926 this.clone(function (clone) { 49927 callback(clone.toDataURL(format)); 49928 }); 49929 }, 49930 49931 /** 49932 * @private 49933 * @param {String} format 49934 * @param {Number} multiplier 49935 * @param {Function} callback 49936 */ 49937 _toDataURLWithMultiplier: function (format, multiplier, callback) { 49938 this.clone(function (clone) { 49939 callback(clone.toDataURLWithMultiplier(format, multiplier)); 49940 }); 49941 }, 49942 49943 /** 49944 * Clones canvas instance 49945 * @param {Object} [callback] Receives cloned instance as a first argument 49946 */ 49947 clone: function (callback) { 49948 var data = JSON.stringify(this); 49949 this.cloneWithoutData(function(clone) { 49950 clone.loadFromJSON(data, function() { 49951 callback && callback(clone); 49952 }); 49953 }); 49954 }, 49955 49956 /** 49957 * Clones canvas instance without cloning existing data. 49958 * This essentially copies canvas dimensions, clipping properties, etc. 49959 * but leaves data empty (so that you can populate it with your own) 49960 * @param {Object} [callback] Receives cloned instance as a first argument 49961 */ 49962 cloneWithoutData: function(callback) { 49963 var el = fabric.document.createElement('canvas'); 49964 49965 el.width = this.getWidth(); 49966 el.height = this.getHeight(); 49967 49968 var clone = new fabric.Canvas(el); 49969 clone.clipTo = this.clipTo; 49970 if (this.backgroundImage) { 49971 clone.setBackgroundImage(this.backgroundImage.src, function() { 49972 clone.renderAll(); 49973 callback && callback(clone); 49974 }); 49975 clone.backgroundImageOpacity = this.backgroundImageOpacity; 49976 clone.backgroundImageStretch = this.backgroundImageStretch; 49977 } 49978 else { 49979 callback && callback(clone); 49980 } 49981 } 49982}); 49983 49984 49985(function(global) { 49986 49987 "use strict"; 49988 49989 var fabric = global.fabric || (global.fabric = { }), 49990 extend = fabric.util.object.extend, 49991 toFixed = fabric.util.toFixed, 49992 capitalize = fabric.util.string.capitalize, 49993 degreesToRadians = fabric.util.degreesToRadians, 49994 supportsLineDash = fabric.StaticCanvas.supports('setLineDash'); 49995 49996 if (fabric.Object) { 49997 return; 49998 } 49999 50000 /** 50001 * Root object class from which all 2d shape classes inherit from 50002 * @class fabric.Object 50003 * @tutorial {@link http://fabricjs.com/fabric-intro-part-1/#objects} 50004 * 50005 * @fires added 50006 * @fires removed 50007 * 50008 * @fires selected 50009 * @fires modified 50010 * @fires rotating 50011 * @fires scaling 50012 * @fires moving 50013 * 50014 * @fires mousedown 50015 * @fires mouseup 50016 */ 50017 fabric.Object = fabric.util.createClass(/** @lends fabric.Object.prototype */ { 50018 50019 /** 50020 * Retrieves object's {@link fabric.Object#clipTo|clipping function} 50021 * @method getClipTo 50022 * @memberOf fabric.Object.prototype 50023 * @return {Function} 50024 */ 50025 50026 /** 50027 * Sets object's {@link fabric.Object#clipTo|clipping function} 50028 * @method setClipTo 50029 * @memberOf fabric.Object.prototype 50030 * @param {Function} clipTo Clipping function 50031 * @return {fabric.Object} thisArg 50032 * @chainable 50033 */ 50034 50035 /** 50036 * Retrieves object's {@link fabric.Object#transformMatrix|transformMatrix} 50037 * @method getTransformMatrix 50038 * @memberOf fabric.Object.prototype 50039 * @return {Array} transformMatrix 50040 */ 50041 50042 /** 50043 * Sets object's {@link fabric.Object#transformMatrix|transformMatrix} 50044 * @method setTransformMatrix 50045 * @memberOf fabric.Object.prototype 50046 * @param {Array} transformMatrix 50047 * @return {fabric.Object} thisArg 50048 * @chainable 50049 */ 50050 50051 /** 50052 * Retrieves object's {@link fabric.Object#visible|visible} state 50053 * @method getVisible 50054 * @memberOf fabric.Object.prototype 50055 * @return {Boolean} True if visible 50056 */ 50057 50058 /** 50059 * Sets object's {@link fabric.Object#visible|visible} state 50060 * @method setVisible 50061 * @memberOf fabric.Object.prototype 50062 * @param {Boolean} value visible value 50063 * @return {fabric.Object} thisArg 50064 * @chainable 50065 */ 50066 50067 /** 50068 * Retrieves object's {@link fabric.Object#shadow|shadow} 50069 * @method getShadow 50070 * @memberOf fabric.Object.prototype 50071 * @return {Object} Shadow instance 50072 */ 50073 50074 /** 50075 * Retrieves object's {@link fabric.Object#stroke|stroke} 50076 * @method getStroke 50077 * @memberOf fabric.Object.prototype 50078 * @return {String} stroke value 50079 */ 50080 50081 /** 50082 * Sets object's {@link fabric.Object#stroke|stroke} 50083 * @method setStroke 50084 * @memberOf fabric.Object.prototype 50085 * @param {String} value stroke value 50086 * @return {fabric.Object} thisArg 50087 * @chainable 50088 */ 50089 50090 /** 50091 * Retrieves object's {@link fabric.Object#strokeWidth|strokeWidth} 50092 * @method getStrokeWidth 50093 * @memberOf fabric.Object.prototype 50094 * @return {Number} strokeWidth value 50095 */ 50096 50097 /** 50098 * Sets object's {@link fabric.Object#strokeWidth|strokeWidth} 50099 * @method setStrokeWidth 50100 * @memberOf fabric.Object.prototype 50101 * @param {Number} value strokeWidth value 50102 * @return {fabric.Object} thisArg 50103 * @chainable 50104 */ 50105 50106 /** 50107 * Retrieves object's {@link fabric.Object#originX|originX} 50108 * @method getOriginX 50109 * @memberOf fabric.Object.prototype 50110 * @return {String} originX value 50111 */ 50112 50113 /** 50114 * Sets object's {@link fabric.Object#originX|originX} 50115 * @method setOriginX 50116 * @memberOf fabric.Object.prototype 50117 * @param {String} value originX value 50118 * @return {fabric.Object} thisArg 50119 * @chainable 50120 */ 50121 50122 /** 50123 * Retrieves object's {@link fabric.Object#originY|originY} 50124 * @method getOriginY 50125 * @memberOf fabric.Object.prototype 50126 * @return {String} originY value 50127 */ 50128 50129 /** 50130 * Sets object's {@link fabric.Object#originY|originY} 50131 * @method setOriginY 50132 * @memberOf fabric.Object.prototype 50133 * @param {String} value originY value 50134 * @return {fabric.Object} thisArg 50135 * @chainable 50136 */ 50137 50138 /** 50139 * Retrieves object's {@link fabric.Object#fill|fill} 50140 * @method getFill 50141 * @memberOf fabric.Object.prototype 50142 * @return {String} Fill value 50143 */ 50144 50145 /** 50146 * Sets object's {@link fabric.Object#fill|fill} 50147 * @method setFill 50148 * @memberOf fabric.Object.prototype 50149 * @param {String} value Fill value 50150 * @return {fabric.Object} thisArg 50151 * @chainable 50152 */ 50153 50154 /** 50155 * Retrieves object's {@link fabric.Object#opacity|opacity} 50156 * @method getOpacity 50157 * @memberOf fabric.Object.prototype 50158 * @return {Number} Opacity value (0-1) 50159 */ 50160 50161 /** 50162 * Sets object's {@link fabric.Object#opacity|opacity} 50163 * @method setOpacity 50164 * @memberOf fabric.Object.prototype 50165 * @param {Number} value Opacity value (0-1) 50166 * @return {fabric.Object} thisArg 50167 * @chainable 50168 */ 50169 50170 /** 50171 * Retrieves object's {@link fabric.Object#angle|angle} (in degrees) 50172 * @method getAngle 50173 * @memberOf fabric.Object.prototype 50174 * @return {Number} 50175 */ 50176 50177 /** 50178 * Sets object's {@link fabric.Object#angle|angle} 50179 * @method setAngle 50180 * @memberOf fabric.Object.prototype 50181 * @param {Number} value Angle value (in degrees) 50182 * @return {fabric.Object} thisArg 50183 * @chainable 50184 */ 50185 50186 /** 50187 * Retrieves object's {@link fabric.Object#top|top position} 50188 * @method getTop 50189 * @memberOf fabric.Object.prototype 50190 * @return {Number} Top value (in pixels) 50191 */ 50192 50193 /** 50194 * Sets object's {@link fabric.Object#top|top position} 50195 * @method setTop 50196 * @memberOf fabric.Object.prototype 50197 * @param {Number} value Top value (in pixels) 50198 * @return {fabric.Object} thisArg 50199 * @chainable 50200 */ 50201 50202 /** 50203 * Retrieves object's {@link fabric.Object#left|left position} 50204 * @method getLeft 50205 * @memberOf fabric.Object.prototype 50206 * @return {Number} Left value (in pixels) 50207 */ 50208 50209 /** 50210 * Sets object's {@link fabric.Object#left|left position} 50211 * @method setLeft 50212 * @memberOf fabric.Object.prototype 50213 * @param {Number} value Left value (in pixels) 50214 * @return {fabric.Object} thisArg 50215 * @chainable 50216 */ 50217 50218 /** 50219 * Retrieves object's {@link fabric.Object#scaleX|scaleX} value 50220 * @method getScaleX 50221 * @memberOf fabric.Object.prototype 50222 * @return {Number} scaleX value 50223 */ 50224 50225 /** 50226 * Sets object's {@link fabric.Object#scaleX|scaleX} value 50227 * @method setScaleX 50228 * @memberOf fabric.Object.prototype 50229 * @param {Number} value scaleX value 50230 * @return {fabric.Object} thisArg 50231 * @chainable 50232 */ 50233 50234 /** 50235 * Retrieves object's {@link fabric.Object#scaleY|scaleY} value 50236 * @method getScaleY 50237 * @memberOf fabric.Object.prototype 50238 * @return {Number} scaleY value 50239 */ 50240 50241 /** 50242 * Sets object's {@link fabric.Object#scaleY|scaleY} value 50243 * @method setScaleY 50244 * @memberOf fabric.Object.prototype 50245 * @param {Number} value scaleY value 50246 * @return {fabric.Object} thisArg 50247 * @chainable 50248 */ 50249 50250 /** 50251 * Retrieves object's {@link fabric.Object#flipX|flipX} value 50252 * @method getFlipX 50253 * @memberOf fabric.Object.prototype 50254 * @return {Boolean} flipX value 50255 */ 50256 50257 /** 50258 * Sets object's {@link fabric.Object#flipX|flipX} value 50259 * @method setFlipX 50260 * @memberOf fabric.Object.prototype 50261 * @param {Boolean} value flipX value 50262 * @return {fabric.Object} thisArg 50263 * @chainable 50264 */ 50265 50266 /** 50267 * Retrieves object's {@link fabric.Object#flipY|flipY} value 50268 * @method getFlipY 50269 * @memberOf fabric.Object.prototype 50270 * @return {Boolean} flipY value 50271 */ 50272 50273 /** 50274 * Sets object's {@link fabric.Object#flipY|flipY} value 50275 * @method setFlipY 50276 * @memberOf fabric.Object.prototype 50277 * @param {Boolean} value flipY value 50278 * @return {fabric.Object} thisArg 50279 * @chainable 50280 */ 50281 50282 /** 50283 * Type of an object (rect, circle, path, etc.)
50284 * @type String 50285 * @default 50286 */ 50287 type: 'object', 50288 50289 /** 50290 * Horizontal origin of transformation of an object (one of "left", "right", "center") 50291 * @type String 50292 * @default 50293 */ 50294 originX: 'center', 50295 50296 /** 50297 * Vertical origin of transformation of an object (one of "top", "bottom", "center") 50298 * @type String 50299 * @default 50300 */ 50301 originY: 'center', 50302 50303 /** 50304 * Top position of an object. Note that by default it's relative to object center. You can change this by setting originY={top/center/bottom} 50305 * @type Number 50306 * @default 50307 */ 50308 top: 0, 50309 50310 /** 50311 * Left position of an object. Note that by default it's relative to object center. You can change this by setting originX={left/center/right} 50312 * @type Number 50313 * @default 50314 */ 50315 left: 0, 50316 50317 /** 50318 * Object width 50319 * @type Number 50320 * @default 50321 */ 50322 width: 0, 50323 50324 /** 50325 * Object height 50326 * @type Number 50327 * @default 50328 */ 50329 height: 0, 50330 50331 /** 50332 * Object scale factor (horizontal) 50333 * @type Number 50334 * @default 50335 */ 50336 scaleX: 1, 50337 50338 /** 50339 * Object scale factor (vertical) 50340 * @type Number 50341 * @default 50342 */ 50343 scaleY: 1, 50344 50345 /** 50346 * When true, an object is rendered as flipped horizontally 50347 * @type Boolean 50348 * @default 50349 */ 50350 flipX: false, 50351 50352 /** 50353 * When true, an object is rendered as flipped vertically 50354 * @type Boolean 50355 * @default 50356 */ 50357 flipY: false, 50358 50359 /** 50360 * Opacity of an object 50361 * @type Number 50362 * @default 50363 */ 50364 opacity: 1, 50365 50366 /** 50367 * Angle of rotation of an object (in degrees) 50368 * @type Number 50369 * @default 50370 */ 50371 angle: 0, 50372 50373 /** 50374 * Size of object's controlling corners (in pixels) 50375 * @type Number 50376 * @default 50377 */ 50378 cornerSize: 12, 50379 50380 /** 50381 * When true, object's controlling corners are rendered as transparent inside (i.e. stroke instead of fill) 50382 * @type Boolean 50383 * @default 50384 */ 50385 transparentCorners: true, 50386 50387 /** 50388 * Default cursor value used when hovering over this object on canvas
50389 * @type String 50390 * @default 50391 */ 50392 hoverCursor: null, 50393 50394 /** 50395 * Padding between object and its controlling borders (in pixels) 50396 * @type Number 50397 * @default 50398 */ 50399 padding: 0, 50400 50401 /** 50402 * Color of controlling borders of an object (when it's active) 50403 * @type String 50404 * @default 50405 */ 50406 borderColor: 'rgba(102,153,255,0.75)', 50407 50408 /** 50409 * Color of controlling corners of an object (when it's active) 50410 * @type String 50411 * @default 50412 */ 50413 cornerColor: 'rgba(102,153,255,0.5)', 50414 50415 /** 50416 * When true, this object will use center point as the origin of transformation 50417 * when being scaled via the controls. 50418 * <b>Backwards incompatibility note:</b> This property replaces "centerTransform" (Boolean). 50419 * @since 1.3.4 50420 * @type Boolean 50421 * @default 50422 */ 50423 centeredScaling: false, 50424 50425 /** 50426 * When true, this object will use center point as the origin of transformation 50427 * when being rotated via the controls. 50428 * <b>Backwards incompatibility note:</b> This property replaces "centerTransform" (Boolean). 50429 * @since 1.3.4 50430 * @type Boolean 50431 * @default 50432 */ 50433 centeredRotation: false, 50434 50435 /** 50436 * Color of object's fill
50437 * @type String 50438 * @default 50439 */ 50440 fill: 'rgb(0,0,0)', 50441 50442 /** 50443 * Fill rule used to fill an object 50444 * @type String 50445 * @default 50446 */ 50447 fillRule: 'source-over', 50448 50449 /** 50450 * Background color of an object. Only works with text objects at the moment. 50451 * @type String 50452 * @default 50453 */ 50454 backgroundColor: '', 50455 50456 /** 50457 * When defined, an object is rendered via stroke and this property specifies its color 50458 * @type String 50459 * @default 50460 */ 50461 stroke: null, 50462 50463 /** 50464 * Width of a stroke used to render this object 50465 * @type Number 50466 * @default 50467 */ 50468 strokeWidth: 1, 50469 50470 /** 50471 * Array specifying dash pattern of an object's stroke (stroke must be defined) 50472 * @type Array 50473 */ 50474 strokeDashArray: null, 50475 50476 /** 50477 * Line endings style of an object's stroke (one of "butt", "round", "square") 50478 * @type String 50479 * @default 50480 */ 50481 strokeLineCap: 'butt', 50482 50483 /** 50484 * Corner style of an object's stroke (one of "bevil", "round", "miter")
50485 * @type String 50486 * @default 50487 */ 50488 strokeLineJoin: 'miter', 50489 50490 /** 50491 * Maximum miter length (used for strokeLineJoin = "miter") of an object's stroke 50492 * @type Number 50493 * @default 50494 */ 50495 strokeMiterLimit: 10, 50496 50497 /** 50498 * Shadow object representing shadow of this shape 50499 * @type fabric.Shadow 50500 * @default 50501 */ 50502 shadow: null, 50503 50504 /** 50505 * Opacity of object's controlling borders when object is active and moving 50506 * @type Number 50507 * @default 50508 */ 50509 borderOpacityWhenMoving: 0.4, 50510 50511 /** 50512 * Scale factor of object's controlling borders 50513 * @type Number 50514 * @default 50515 */ 50516 borderScaleFactor: 1, 50517 50518 /** 50519 * Transform matrix (similar to SVG's transform matrix) 50520 * @type Array 50521 */ 50522 transformMatrix: null, 50523 50524 /** 50525 * Minimum allowed scale value of an object 50526 * @type Number 50527 * @default 50528 */ 50529 minScaleLimit: 0.01, 50530 50531 /** 50532 * When set to `false`, an object can not be selected for modification (using either point-click-based or group-based selection). 50533 * But events still fire on it. 50534 * @type Boolean 50535 * @default 50536 */ 50537 selectable: true, 50538 50539 /** 50540 * When set to `false`, an object can not be a target of events. All events propagate through it. Introduced in v1.3.4 50541 * @type Boolean 50542 * @default 50543 */ 50544 evented: true, 50545 50546 /** 50547 * When set to `false`, an object is not rendered on canvas 50548 * @type Boolean 50549 * @default 50550 */ 50551 visible: true, 50552 50553 /** 50554 * When set to `false`, object's controls are not displayed and can not be used to manipulate object 50555 * @type Boolean 50556 * @default 50557 */ 50558 hasControls: true, 50559 50560 /** 50561 * When set to `false`, object's controlling borders are not rendered 50562 * @type Boolean 50563 * @default 50564 */ 50565 hasBorders: true, 50566 50567 /** 50568 * When set to `false`, object's controlling rotating point will not be visible or selectable 50569 * @type Boolean 50570 * @default 50571 */ 50572 hasRotatingPoint: true, 50573 50574 /** 50575 * Offset for object's controlling rotating point (when enabled via `hasRotatingPoint`) 50576 * @type Number 50577 * @default 50578 */ 50579 rotatingPointOffset: 40, 50580 50581 /** 50582 * When set to `true`, objects are "found" on canvas on per-pixel basis rather than according to bounding box 50583 * @type Boolean 50584 * @default 50585 */ 50586 perPixelTargetFind: false, 50587 50588 /** 50589 * When `false`, default object's values are not included in its serialization 50590 * @type Boolean 50591 * @default 50592 */ 50593 includeDefaultValues: true, 50594 50595 /** 50596 * Function that determines clipping of an object (context is passed as a first argument) 50597 * @type Function 50598 */ 50599 clipTo: null, 50600 50601 /** 50602 * When `true`, object horizontal movement is locked 50603 * @type Boolean 50604 * @default 50605 */ 50606 lockMovementX: false, 50607 50608 /** 50609 * When `true`, object vertical movement is locked 50610 * @type Boolean 50611 * @default 50612 */ 50613 lockMovementY: false, 50614 50615 /** 50616 * When `true`, object rotation is locked 50617 * @type Boolean 50618 * @default 50619 */ 50620 lockRotation: false, 50621 50622 /** 50623 * When `true`, object horizontal scaling is locked 50624 * @type Boolean 50625 * @default 50626 */ 50627 lockScalingX: false, 50628 50629 /** 50630 * When `true`, object vertical scaling is locked 50631 * @type Boolean 50632 * @default 50633 */ 50634 lockScalingY: false, 50635 50636 /** 50637 * When `true`, object non-uniform scaling is locked 50638 * @type Boolean 50639 * @default 50640 */ 50641 lockUniScaling: false, 50642 50643 /** 50644 * List of properties to consider when checking if state 50645 * of an object is changed (fabric.Object#hasStateChanged) 50646 * as well as for history (undo/redo) purposes 50647 * @type Array 50648 */ 50649 stateProperties: ( 50650 'top left width height scaleX scaleY flipX flipY originX originY transformMatrix ' + 50651 'stroke strokeWidth strokeDashArray strokeLineCap strokeLineJoin strokeMiterLimit ' + 50652 'angle opacity fill fillRule shadow clipTo visible backgroundColor' 50653 ).split(' '), 50654 50655 /** 50656 * Constructor 50657 * @param {Object} [options] Options object 50658 */ 50659 initialize: function(options) { 50660 if (options) { 50661 this.setOptions(options); 50662 } 50663 }, 50664 50665 /** 50666 * @private 50667 */ 50668 _initGradient: function(options) { 50669 if (options.fill && options.fill.colorStops && !(options.fill instanceof fabric.Gradient)) { 50670 this.set('fill', new fabric.Gradient(options.fill)); 50671 } 50672 }, 50673 50674 /** 50675 * @private 50676 */ 50677 _initPattern: function(options) { 50678 if (options.fill && options.fill.source && !(options.fill instanceof fabric.Pattern)) { 50679 this.set('fill', new fabric.Pattern(options.fill)); 50680 } 50681 if (options.stroke && options.stroke.source && !(options.stroke instanceof fabric.Pattern)) { 50682 this.set('stroke', new fabric.Pattern(options.stroke)); 50683 } 50684 }, 50685 50686 /** 50687 * @private 50688 */ 50689 _initClipping: function(options) { 50690 if (!options.clipTo || typeof options.clipTo !== 'string') return; 50691 50692 var functionBody = fabric.util.getFunctionBody(options.clipTo); 50693 if (typeof functionBody !== 'undefined') { 50694 this.clipTo = new Function('ctx', functionBody); 50695 } 50696 }, 50697 50698 /** 50699 * Sets object's properties from options 50700 * @param {Object} [options] Options object 50701 */ 50702 setOptions: function(options) { 50703 for (var prop in options) { 50704 this.set(prop, options[prop]); 50705 } 50706 this._initGradient(options); 50707 this._initPattern(options); 50708 this._initClipping(options); 50709 }, 50710 50711 /** 50712 * Transforms context when rendering an object 50713 * @param {CanvasRenderingContext2D} ctx Context 50714 * @param {Boolean} fromLeft When true, context is transformed to object's top/left corner. This is used when rendering text on Node 50715 */ 50716 transform: function(ctx, fromLeft) { 50717 ctx.globalAlpha = this.opacity; 50718 50719 var center = fromLeft ? this._getLeftTopCoords() : this.getCenterPoint(); 50720 ctx.translate(center.x, center.y); 50721 ctx.rotate(degreesToRadians(this.angle)); 50722 ctx.scale( 50723 this.scaleX * (this.flipX ? -1 : 1), 50724 this.scaleY * (this.flipY ? -1 : 1) 50725 ); 50726 }, 50727 50728 /** 50729 * Returns an object representation of an instance 50730 * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output 50731 * @return {Object} Object representation of an instance 50732 */ 50733 toObject: function(propertiesToInclude) { 50734 50735 var NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS; 50736 50737 var object = { 50738 type: this.type, 50739 originX: this.originX, 50740 originY: this.originY, 50741 left: toFixed(this.left, NUM_FRACTION_DIGITS), 50742 top: toFixed(this.top, NUM_FRACTION_DIGITS), 50743 width: toFixed(this.width, NUM_FRACTION_DIGITS), 50744 height: toFixed(this.height, NUM_FRACTION_DIGITS), 50745 fill: (this.fill && this.fill.toObject) ? this.fill.toObject() : this.fill, 50746 stroke: (this.stroke && this.stroke.toObject) ? this.stroke.toObject() : this.stroke, 50747 strokeWidth: toFixed(this.strokeWidth, NUM_FRACTION_DIGITS), 50748 strokeDashArray: this.strokeDashArray, 50749 strokeLineCap: this.strokeLineCap, 50750 strokeLineJoin: this.strokeLineJoin, 50751 strokeMiterLimit: toFixed(this.strokeMiterLimit, NUM_FRACTION_DIGITS), 50752 scaleX: toFixed(this.scaleX, NUM_FRACTION_DIGITS), 50753 scaleY: toFixed(this.scaleY, NUM_FRACTION_DIGITS), 50754 angle: toFixed(this.getAngle(), NUM_FRACTION_DIGITS), 50755 flipX: this.flipX, 50756 flipY: this.flipY, 50757 opacity: toFixed(this.opacity, NUM_FRACTION_DIGITS), 50758 shadow: (this.shadow && this.shadow.toObject) ? this.shadow.toObject() : this.shadow, 50759 visible: this.visible, 50760 clipTo: this.clipTo && String(this.clipTo), 50761 backgroundColor: this.backgroundColor 50762 }; 50763 50764 if (!this.includeDefaultValues) { 50765 object = this._removeDefaultValues(object); 50766 } 50767 50768 fabric.util.populateWithProperties(this, object, propertiesToInclude); 50769 50770 return object; 50771 }, 50772 50773 /** 50774 * Returns (dataless) object representation of an instance 50775 * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output 50776 * @return {Object} Object representation of an instance 50777 */ 50778 toDatalessObject: function(propertiesToInclude) { 50779 // will be overwritten by subclasses 50780 return this.toObject(propertiesToInclude); 50781 }, 50782 50783 /* _TO_SVG_START_ */ 50784 /** 50785 * Returns styles-string for svg-export 50786 * @return {String} 50787 */ 50788 getSvgStyles: function() { 50789 50790 var fill = this.fill 50791 ? (this.fill.toLive ? 'url(#SVGID_' + this.fill.id + ')' : this.fill) 50792 : 'none'; 50793 50794 var stroke = this.stroke 50795 ? (this.stroke.toLive ? 'url(#SVGID_' + this.stroke.id + ')' : this.stroke) 50796 : 'none'; 50797 50798 var strokeWidth = this.strokeWidth ? this.strokeWidth : '0'; 50799 var strokeDashArray = this.strokeDashArray ? this.strokeDashArray.join(' ') : ''; 50800 var strokeLineCap = this.strokeLineCap ? this.strokeLineCap : 'butt'; 50801 var strokeLineJoin = this.strokeLineJoin ? this.strokeLineJoin : 'miter'; 50802 var strokeMiterLimit = this.strokeMiterLimit ? this.strokeMiterLimit : '4'; 50803 var opacity = typeof this.opacity !== 'undefined' ? this.opacity : '1'; 50804 50805 var visibility = this.visible ? '' : " visibility: hidden;"; 50806 var filter = this.shadow && this.type !== 'text' ? 'filter: url(#SVGID_' + this.shadow.id + ');' : ''; 50807 50808 return [ 50809 "stroke: ", stroke, "; ", 50810 "stroke-width: ", strokeWidth, "; ", 50811 "stroke-dasharray: ", strokeDashArray, "; ", 50812 "stroke-linecap: ", strokeLineCap, "; ", 50813 "stroke-linejoin: ", strokeLineJoin, "; ", 50814 "stroke-miterlimit: ", strokeMiterLimit, "; ", 50815 "fill: ", fill, "; ", 50816 "opacity: ", opacity, ";", 50817 filter, 50818 visibility 50819 ].join(''); 50820 }, 50821 50822 /** 50823 * Returns transform-string for svg-export 50824 * @return {String} 50825 */ 50826 getSvgTransform: function() { 50827 var angle = this.getAngle(); 50828 var center = this.getCenterPoint(); 50829 50830 var NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS; 50831 50832 var translatePart = "translate(" + 50833 toFixed(center.x, NUM_FRACTION_DIGITS) + 50834 " " + 50835 toFixed(center.y, NUM_FRACTION_DIGITS) + 50836 ")"; 50837 50838 var anglePart = angle !== 0 50839 ? (" rotate(" + toFixed(angle, NUM_FRACTION_DIGITS) + ")") 50840 : ''; 50841 50842 var scalePart = (this.scaleX === 1 && this.scaleY === 1) 50843 ? '' : 50844 (" scale(" + 50845 toFixed(this.scaleX, NUM_FRACTION_DIGITS) + 50846 " " + 50847 toFixed(this.scaleY, NUM_FRACTION_DIGITS) + 50848 ")"); 50849 50850 var flipXPart = this.flipX ? "matrix(-1 0 0 1 0 0) " : ""; 50851 var flipYPart = this.flipY ? "matrix(1 0 0 -1 0 0)" : ""; 50852 50853 return [ translatePart, anglePart, scalePart, flipXPart, flipYPart ].join(''); 50854 }, 50855 50856 _createBaseSVGMarkup: function() { 50857 var markup = [ ]; 50858 50859 if (this.fill && this.fill.toLive) { 50860 markup.push(this.fill.toSVG(this, false)); 50861 } 50862 if (this.stroke && this.stroke.toLive) { 50863 markup.push(this.stroke.toSVG(this, false)); 50864 } 50865 if (this.shadow) { 50866 markup.push(this.shadow.toSVG(this)); 50867 } 50868 return markup; 50869 }, 50870 /* _TO_SVG_END_ */ 50871 50872 /** 50873 * @private 50874 * @param {Object} object 50875 */ 50876 _removeDefaultValues: function(object) { 50877 var prototype = fabric.util.getKlass(object.type).prototype; 50878 var stateProperties = prototype.stateProperties; 50879
50880 stateProperties.forEach(function(prop) { 50881 if (object[prop] === prototype[prop]) { 50882 delete object[prop]; 50883 } 50884 }); 50885 50886 return object; 50887 }, 50888 50889 /** 50890 * Returns a string representation of an instance 50891 * @return {String} 50892 */ 50893 toString: function() { 50894 return "#<fabric." + capitalize(this.type) + ">"; 50895 }, 50896 50897 /** 50898 * Basic getter 50899 * @param {String} property Property name 50900 * @return {Any} value of a property 50901 */ 50902 get: function(property) { 50903 return this[property]; 50904 }, 50905 50906 /** 50907 * Sets property to a given value. When changing position/dimension -related properties (left, top, scale, angle, etc.) `set` does not update position of object's borders/controls. If you need to update those, call `setCoords()`. 50908 * @param {String|Object} key Property name or object (if object, iterate over the object properties) 50909 * @param {Object|Function} value Property value (if function, the value is passed into it and its return value is used as a new one) 50910 * @return {fabric.Object} thisArg 50911 * @chainable 50912 */ 50913 set: function(key, value) { 50914 if (typeof key === 'object') { 50915 for (var prop in key) { 50916 this._set(prop, key[prop]); 50917 } 50918 } 50919 else { 50920 if (typeof value === 'function' && key !== 'clipTo') { 50921 this._set(key, value(this.get(key))); 50922 } 50923 else { 50924 this._set(key, value); 50925 } 50926 } 50927 return this; 50928 }, 50929 50930 /** 50931 * @private 50932 * @param {String} key 50933 * @param {Any} value 50934 * @return {fabric.Object} thisArg 50935 */ 50936 _set: function(key, value) { 50937 var shouldConstrainValue = (key === 'scaleX' || key === 'scaleY'); 50938 50939 if (shouldConstrainValue) { 50940 value = this._constrainScale(value); 50941 } 50942 if (key === 'scaleX' && value < 0) { 50943 this.flipX = !this.flipX; 50944 value *= -1; 50945 } 50946 else if (key === 'scaleY' && value < 0) { 50947 this.flipY = !this.flipY; 50948 value *= -1; 50949 } 50950 else if (key === 'width' || key === 'height') { 50951 this.minScaleLimit = toFixed(Math.min(0.1, 1/Math.max(this.width, this.height)), 2); 50952 } 50953 else if (key === 'shadow' && value && !(value instanceof fabric.Shadow)) { 50954 value = new fabric.Shadow(value); 50955 } 50956 50957 this[key] = value; 50958 50959 return this; 50960 }, 50961 50962 /** 50963 * Toggles specified property from `true` to `false` or from `false` to `true` 50964 * @param {String} property Property to toggle 50965 * @return {fabric.Object} thisArg 50966 * @chainable 50967 */ 50968 toggle: function(property) { 50969 var value = this.get(property); 50970 if (typeof value === 'boolean') { 50971 this.set(property, !value); 50972 } 50973 return this; 50974 }, 50975 50976 /** 50977 * Sets sourcePath of an object 50978 * @param {String} value Value to set sourcePath to 50979 * @return {fabric.Object} thisArg 50980 * @chainable 50981 */ 50982 setSourcePath: function(value) { 50983 this.sourcePath = value; 50984 return this; 50985 }, 50986 50987 /** 50988 * Renders an object on a specified context 50989 * @param {CanvasRenderingContext2D} ctx Context to render on 50990 * @param {Boolean} [noTransform] When true, context is not transformed 50991 */ 50992 render: function(ctx, noTransform) { 50993 // do not render if width/height are zeros or object is not visible 50994 if (this.width === 0 || this.height === 0 || !this.visible) return; 50995 50996 ctx.save(); 50997 50998 var m = this.transformMatrix; 50999 if (m && !this.group) { 51000 ctx.setTransform(m[0], m[1], m[2], m[3], m[4], m[5]); 51001 } 51002 51003 if (!noTransform) { 51004 this.transform(ctx); 51005 } 51006 51007 if (this.stroke) { 51008 ctx.lineWidth = this.strokeWidth; 51009 ctx.lineCap = this.strokeLineCap; 51010 ctx.lineJoin = this.strokeLineJoin; 51011 ctx.miterLimit = this.strokeMiterLimit; 51012 ctx.strokeStyle = this.stroke.toLive 51013 ? this.stroke.toLive(ctx) 51014 : this.stroke; 51015 } 51016 51017 if (this.fill) { 51018 ctx.fillStyle = this.fill.toLive 51019 ? this.fill.toLive(ctx) 51020 : this.fill; 51021 } 51022 51023 if (m && this.group) { 51024 ctx.translate(-this.group.width/2, -this.group.height/2); 51025 ctx.transform(m[0], m[1], m[2], m[3], m[4], m[5]); 51026 } 51027 51028 this._setShadow(ctx); 51029 this.clipTo && fabric.util.clipContext(this, ctx); 51030 this._render(ctx, noTransform);
51031 this.clipTo && ctx.restore(); 51032 this._removeShadow(ctx); 51033 51034 if (this.active && !noTransform) { 51035 this.drawBorders(ctx); 51036 this.drawControls(ctx); 51037 } 51038 ctx.restore(); 51039 }, 51040 51041 /** 51042 * @private 51043 * @param {CanvasRenderingContext2D} ctx Context to render on 51044 */ 51045 _setShadow: function(ctx) { 51046 if (!this.shadow) return; 51047 51048 ctx.shadowColor = this.shadow.color; 51049 ctx.shadowBlur = this.shadow.blur; 51050 ctx.shadowOffsetX = this.shadow.offsetX; 51051 ctx.shadowOffsetY = this.shadow.offsetY; 51052 }, 51053 51054 /** 51055 * @private 51056 * @param {CanvasRenderingContext2D} ctx Context to render on 51057 */ 51058 _removeShadow: function(ctx) { 51059 ctx.shadowColor = ''; 51060 ctx.shadowBlur = ctx.shadowOffsetX = ctx.shadowOffsetY = 0; 51061 }, 51062 51063 /** 51064 * @private 51065 * @param {CanvasRenderingContext2D} ctx Context to render on 51066 */ 51067 _renderFill: function(ctx) { 51068 if (!this.fill) return; 51069 51070 if (this.fill.toLive) { 51071 ctx.save(); 51072 ctx.translate( 51073 -this.width / 2 + this.fill.offsetX || 0, 51074 -this.height / 2 + this.fill.offsetY || 0); 51075 } 51076 ctx.fill(); 51077 if (this.fill.toLive) { 51078 ctx.restore(); 51079 } 51080 if (this.shadow && !this.shadow.affectStroke) { 51081 this._removeShadow(ctx); 51082 } 51083 }, 51084 51085 /** 51086 * @private 51087 * @param {CanvasRenderingContext2D} ctx Context to render on 51088 */ 51089 _renderStroke: function(ctx) { 51090 if (!this.stroke) return; 51091 51092 ctx.save(); 51093 if (this.strokeDashArray) { 51094 // Spec requires the concatenation of two copies the dash list when the number of elements is odd 51095 if (1 & this.strokeDashArray.length) { 51096 this.strokeDashArray.push.apply(this.strokeDashArray, this.strokeDashArray); 51097 } 51098 51099 if (supportsLineDash) { 51100 ctx.setLineDash(this.strokeDashArray); 51101 this._stroke && this._stroke(ctx); 51102 } 51103 else { 51104 this._renderDashedStroke && this._renderDashedStroke(ctx); 51105 } 51106 ctx.stroke(); 51107 } 51108 else { 51109 this._stroke ? this._stroke(ctx) : ctx.stroke(); 51110 } 51111 this._removeShadow(ctx); 51112 ctx.restore(); 51113 }, 51114 51115 /** 51116 * Clones an instance 51117 * @param {Function} callback Callback is invoked with a clone as a first argument 51118 * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output 51119 * @return {fabric.Object} clone of an instance 51120 */ 51121 clone: function(callback, propertiesToInclude) { 51122 if (this.constructor.fromObject) { 51123 return this.constructor.fromObject(this.toObject(propertiesToInclude), callback); 51124 } 51125 return new fabric.Object(this.toObject(propertiesToInclude)); 51126 }, 51127 51128 /** 51129 * Creates an instance of fabric.Image out of an object 51130 * @param callback {Function} callback, invoked with an instance as a first argument 51131 * @return {fabric.Object} thisArg 51132 */ 51133 cloneAsImage: function(callback) { 51134 var dataUrl = this.toDataURL(); 51135 fabric.util.loadImage(dataUrl, function(img) { 51136 if (callback) { 51137 callback(new fabric.Image(img)); 51138 } 51139 }); 51140 return this; 51141 }, 51142 51143 /** 51144 * Converts an object into a data-url-like string 51145 * @param {Object} options Options object 51146 * @param {String} [options.format=png] The format of the output image. Either "jpeg" or "png" 51147 * @param {Number} [options.quality=1] Quality level (0..1). Only used for jpeg. 51148 * @param {Number} [options.multiplier=1] Multiplier to scale by 51149 * @param {Number} [options.left] Cropping left offset. Introduced in v1.2.14 51150 * @param {Number} [options.top] Cropping top offset. Introduced in v1.2.14 51151 * @param {Number} [options.width] Cropping width. Introduced in v1.2.14 51152 * @param {Number} [options.height] Cropping height. Introduced in v1.2.14 51153 * @return {String} Returns a data: URL containing a representation of the object in the format specified by options.format 51154 */ 51155 toDataURL: function(options) { 51156 options || (options = { }); 51157 51158 var el = fabric.util.createCanvasElement(),
51159 boundingRect = this.getBoundingRect(); 51160 51161 el.width = boundingRect.width; 51162 el.height = boundingRect.height; 51163 51164 fabric.util.wrapElement(el, 'div'); 51165 var canvas = new fabric.Canvas(el); 51166 51167 // to avoid common confusion https://github.com/kangax/fabric.js/issues/806 51168 if (options.format === 'jpg') { 51169 options.format = 'jpeg'; 51170 } 51171 51172 if (options.format === 'jpeg') { 51173 canvas.backgroundColor = '#fff'; 51174 } 51175 51176 var origParams = { 51177 active: this.get('active'), 51178 left: this.getLeft(), 51179 top: this.getTop() 51180 }; 51181 51182 this.set('active', false); 51183 this.setPositionByOrigin(new fabric.Point(el.width / 2, el.height / 2), 'center', 'center'); 51184 51185 canvas.add(this); 51186 var data = canvas.toDataURL(options); 51187 51188 this.set(origParams).setCoords(); 51189 51190 canvas.dispose(); 51191 canvas = null; 51192 51193 return data; 51194 }, 51195 51196 /** 51197 * Returns true if specified type is identical to the type of an instance 51198 * @param type {String} type Type to check against 51199 * @return {Boolean} 51200 */ 51201 isType: function(type) { 51202 return this.type === type; 51203 }, 51204 51205 /** 51206 * Returns complexity of an instance 51207 * @return {Number} complexity of this instance 51208 */ 51209 complexity: function() { 51210 return 0; 51211 }, 51212 51213 /** 51214 * Returns a JSON representation of an instance 51215 * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output 51216 * @return {Object} JSON 51217 */ 51218 toJSON: function(propertiesToInclude) { 51219 // delegate, not alias 51220 return this.toObject(propertiesToInclude); 51221 }, 51222 51223 /** 51224 * Sets gradient (fill or stroke) of an object 51225 * <b>Backwards incompatibility note:</b> This method was named "setGradientFill" until v1.1.0 51226 * @param {String} property Property name 'stroke' or 'fill' 51227 * @param {Object} [options] Options object 51228 * @param {String} [options.type] Type of gradient 'radial' or 'linear' 51229 * @param {Number} [options.x1=0] x-coordinate of start point 51230 * @param {Number} [options.y1=0] y-coordinate of start point 51231 * @param {Number} [options.x2=0] x-coordinate of end point 51232 * @param {Number} [options.y2=0] y-coordinate of end point 51233 * @param {Number} [options.r1=0] Radius of start point (only for radial gradients) 51234 * @param {Number} [options.r2=0] Radius of end point (only for radial gradients) 51235 * @param {Object} [options.colorStops] Color stops object eg. {0: 'ff0000', 1: '000000'} 51236 * @return {fabric.Object} thisArg 51237 * @chainable 51238 * @see {@link http://jsfiddle.net/fabricjs/58y8b/|jsFiddle demo} 51239 * @example <caption>Set linear gradient</caption> 51240 * object.setGradient('fill', { 51241 * type: 'linear', 51242 * x1: -object.width / 2, 51243 * y1: 0, 51244 * x2: object.width / 2, 51245 * y2: 0, 51246 * colorStops: { 51247 * 0: 'red', 51248 * 0.5: '#005555', 51249 * 1: 'rgba(0,0,255,0.5)' 51250 * } 51251 * }); 51252 * canvas.renderAll(); 51253 * @example <caption>Set radial gradient</caption> 51254 * object.setGradient('fill', { 51255 * type: 'radial', 51256 * x1: 0, 51257 * y1: 0, 51258 * x2: 0, 51259 * y2: 0, 51260 * r1: object.width / 2, 51261 * r2: 10, 51262 * colorStops: { 51263 * 0: 'red', 51264 * 0.5: '#005555', 51265 * 1: 'rgba(0,0,255,0.5)' 51266 * } 51267 * }); 51268 * canvas.renderAll(); 51269 */ 51270 setGradient: function(property, options) { 51271 options || (options = { }); 51272 51273 var gradient = {colorStops: []}; 51274 51275 gradient.type = options.type || (options.r1 || options.r2 ? 'radial' : 'linear'); 51276 gradient.coords = { 51277 x1: options.x1, 51278 y1: options.y1, 51279 x2: options.x2, 51280 y2: options.y2 51281 }; 51282 51283 if (options.r1 || options.r2) { 51284 gradient.coords.r1 = options.r1; 51285 gradient.coords.r2 = options.r2; 51286 } 51287 51288 for (var position in options.colorStops) { 51289 var color = new fabric.Color(options.colorStops[position]); 51290 gradient.colorStops.push({offset: position, color: color.toRgb(), opacity: color.getAlpha()}); 51291 } 51292 51293 return this.set(property, fabric.Gradient.forObject(this, gradient)); 51294 }, 51295 51296 /** 51297 * Sets pattern fill of an object 51298 * @param {Object} options Options object 51299 * @param {(String|HTMLImageElement)} options.source Pattern source 51300 * @param {String} [options.repeat=repeat] Repeat property of a pattern (one of repeat, repeat-x, repeat-y or no-repeat) 51301 * @param {Number} [options.offsetX=0] Pattern horizontal offset from object's left/top corner 51302 * @param {Number} [options.offsetY=0] Pattern vertical offset from object's left/top corner 51303 * @return {fabric.Object} thisArg 51304 * @chainable 51305 * @see {@link http://jsfiddle.net/fabricjs/QT3pa/|jsFiddle demo} 51306 * @example <caption>Set pattern</caption> 51307 * fabric.util.loadImage('http://fabricjs.com/assets/escheresque_ste.png', function(img) { 51308 * object.setPatternFill({ 51309 * source: img, 51310 * repeat: 'repeat' 51311 * }); 51312 * canvas.renderAll(); 51313 * }); 51314 */ 51315 setPatternFill: function(options) { 51316 return this.set('fill', new fabric.Pattern(options)); 51317 }, 51318 51319 /** 51320 * Sets {@link fabric.Object#shadow|shadow} of an object 51321 * @param {Object|String} [options] Options object or string (e.g. "2px 2px 10px rgba(0,0,0,0.2)") 51322 * @param {String} [options.color=rgb(0,0,0)] Shadow color 51323 * @param {Number} [options.blur=0] Shadow blur 51324 * @param {Number} [options.offsetX=0] Shadow horizontal offset 51325 * @param {Number} [options.offsetY=0] Shadow vertical offset 51326 * @return {fabric.Object} thisArg 51327 * @chainable 51328 * @see {@link http://jsfiddle.net/fabricjs/7gvJG/|jsFiddle demo} 51329 * @example <caption>Set shadow with string notation</caption> 51330 * object.setShadow('2px 2px 10px rgba(0,0,0,0.2)'); 51331 * canvas.renderAll(); 51332 * @example <caption>Set shadow with object notation</caption> 51333 * object.setShadow({ 51334 * color: 'red', 51335 * blur: 10, 51336 * offsetX: 20, 51337 * offsetY: 20 51338 * }); 51339 * canvas.renderAll(); 51340 */ 51341 setShadow: function(options) { 51342 return this.set('shadow', new fabric.Shadow(options)); 51343 }, 51344 51345 /** 51346 * Sets "color" of an instance (alias of `set('fill', …)`) 51347 * @param {String} color Color value 51348 * @return {fabric.Text} thisArg 51349 * @chainable 51350 */ 51351 setColor: function(color) { 51352 this.set('fill', color); 51353 return this; 51354 }, 51355 51356 /** 51357 * Centers object horizontally on canvas to which it was added last.
51358 * You might need to call `setCoords` on an object after centering, to update controls area. 51359 * @return {fabric.Object} thisArg 51360 * @chainable 51361 */ 51362 centerH: function () { 51363 this.canvas.centerObjectH(this); 51364 return this; 51365 }, 51366 51367 /** 51368 * Centers object vertically on canvas to which it was added last. 51369 * You might need to call `setCoords` on an object after centering, to update controls area. 51370 * @return {fabric.Object} thisArg 51371 * @chainable 51372 */ 51373 centerV: function () { 51374 this.canvas.centerObjectV(this); 51375 return this; 51376 }, 51377 51378 /** 51379 * Centers object vertically and horizontally on canvas to which is was added last 51380 * You might need to call `setCoords` on an object after centering, to update controls area. 51381 * @return {fabric.Object} thisArg 51382 * @chainable 51383 */ 51384 center: function () { 51385 return this.centerH().centerV(); 51386 }, 51387 51388 /** 51389 * Removes object from canvas to which it was added last 51390 * @return {fabric.Object} thisArg 51391 * @chainable 51392 */ 51393 remove: function() { 51394 return this.canvas.remove(this); 51395 }, 51396 51397 /** 51398 * Moves an object to the bottom of the stack of drawn objects 51399 * @return {fabric.Object} thisArg 51400 * @chainable 51401 */ 51402 sendToBack: function() { 51403 if (this.group) { 51404 fabric.StaticCanvas.prototype.sendToBack.call(this.group, this); 51405 } 51406 else { 51407 this.canvas.sendToBack(this); 51408 } 51409 return this; 51410 }, 51411 51412 /** 51413 * Moves an object to the top of the stack of drawn objects 51414 * @return {fabric.Object} thisArg 51415 * @chainable 51416 */ 51417 bringToFront: function() { 51418 if (this.group) { 51419 fabric.StaticCanvas.prototype.bringToFront.call(this.group, this); 51420 } 51421 else { 51422 this.canvas.bringToFront(this); 51423 } 51424 return this; 51425 }, 51426 51427 /** 51428 * Moves an object down in stack of drawn objects 51429 * @param {Boolean} [intersecting] If `true`, send object behind next lower intersecting object 51430 * @return {fabric.Object} thisArg 51431 * @chainable 51432 */ 51433 sendBackwards: function(intersecting) { 51434 if (this.group) { 51435 fabric.StaticCanvas.prototype.sendBackwards.call(this.group, this, intersecting); 51436 } 51437 else { 51438 this.canvas.sendBackwards(this, intersecting); 51439 } 51440 return this; 51441 }, 51442 51443 /** 51444 * Moves an object up in stack of drawn objects 51445 * @param {Boolean} [intersecting] If `true`, send object in front of next upper intersecting object 51446 * @return {fabric.Object} thisArg 51447 * @chainable 51448 */ 51449 bringForward: function(intersecting) { 51450 if (this.group) { 51451 fabric.StaticCanvas.prototype.bringForward.call(this.group, this, intersecting); 51452 } 51453 else { 51454 this.canvas.bringForward(this, intersecting); 51455 } 51456 return this; 51457 }, 51458 51459 /** 51460 * Moves an object to specified level in stack of drawn objects 51461 * @param {Number} index New position of object 51462 * @return {fabric.Object} thisArg 51463 * @chainable 51464 */ 51465 moveTo: function(index) { 51466 if (this.group) { 51467 fabric.StaticCanvas.prototype.moveTo.call(this.group, this, index); 51468 } 51469 else { 51470 this.canvas.moveTo(this, index); 51471 } 51472 return this; 51473 } 51474 }); 51475 51476 fabric.util.createAccessors(fabric.Object); 51477 51478 /** 51479 * Alias for {@link fabric.Object.prototype.setAngle} 51480 * @alias rotate -> setAngle 51481 * @memberof fabric.Object 51482 */ 51483 fabric.Object.prototype.rotate = fabric.Object.prototype.setAngle; 51484 51485 extend(fabric.Object.prototype, fabric.Observable); 51486 51487 /** 51488 * Defines the number of fraction digits to use when serializing object values. 51489 * You can use it to increase/decrease precision of such values like left, top, scaleX, scaleY, etc. 51490 * @static 51491 * @memberof fabric.Object 51492 * @constant 51493 * @type Number 51494 */ 51495 fabric.Object.NUM_FRACTION_DIGITS = 2; 51496 51497 /** 51498 * Unique id used internally when creating SVG elements 51499 * @static 51500 * @memberof fabric.Object 51501 * @type Number 51502 */ 51503 fabric.Object.__uid = 0; 51504 51505})(typeof exports !== 'undefined' ? exports : this); 51506 51507 51508(function() { 51509 51510 var degreesToRadians = fabric.util.degreesToRadians; 51511 51512 fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ { 51513 51514 /** 51515 * Translates the coordinates from origin to center coordinates (based on the object's dimensions) 51516 * @param {fabric.Point} point The point which corresponds to the originX and originY params 51517 * @param {String} originX Horizontal origin: 'left', 'center' or 'right' 51518 * @param {String} originY Vertical origin: 'top', 'center' or 'bottom' 51519 * @return {fabric.Point} 51520 */ 51521 translateToCenterPoint: function(point, originX, originY) { 51522 var cx = point.x, cy = point.y; 51523 51524 if ( originX === "left" ) { 51525 cx = point.x + ( this.getWidth() + (this.strokeWidth*this.scaleX) )/ 2; 51526 } 51527 else if ( originX === "right" ) { 51528 cx = point.x - ( this.getWidth() + (this.strokeWidth*this.scaleX) ) / 2; 51529 } 51530 51531 if ( originY === "top" ) { 51532 cy = point.y +( this.getHeight() + (this.strokeWidth*this.scaleY) ) / 2; 51533 } 51534 else if ( originY === "bottom" ) { 51535 cy = point.y - ( this.getHeight() + (this.strokeWidth*this.scaleY) ) / 2; 51536 } 51537 51538 // Apply the reverse rotation to the point (it's already scaled properly) 51539 return fabric.util.rotatePoint(new fabric.Point(cx, cy), point, degreesToRadians(this.angle)); 51540 }, 51541 51542 /** 51543 * Translates the coordinates from center to origin coordinates (based on the object's dimensions) 51544 * @param {fabric.Point} point The point which corresponds to center of the object 51545 * @param {String} originX Horizontal origin: 'left', 'center' or 'right' 51546 * @param {String} originY Vertical origin: 'top', 'center' or 'bottom' 51547 * @return {fabric.Point} 51548 */ 51549 translateToOriginPoint: function(center, originX, originY) { 51550 var x = center.x, y = center.y; 51551 51552 // Get the point coordinates 51553 if ( originX === "left" ) { 51554 x = center.x - ( this.getWidth() + (this.strokeWidth*this.scaleX) ) / 2; 51555 } 51556 else if ( originX === "right" ) { 51557 x = center.x + ( this.getWidth() + (this.strokeWidth*this.scaleX) ) / 2; 51558 } 51559 if ( originY === "top" ) { 51560 y = center.y - ( this.getHeight() + (this.strokeWidth*this.scaleY) )/ 2; 51561 } 51562 else if ( originY === "bottom" ) { 51563 y = center.y + ( this.getHeight() + (this.strokeWidth*this.scaleY) )/ 2; 51564 } 51565 51566 // Apply the rotation to the point (it's already scaled properly) 51567 return fabric.util.rotatePoint(new fabric.Point(x, y), center, degreesToRadians(this.angle)); 51568 }, 51569 51570 /** 51571 * Returns the real center coordinates of the object 51572 * @return {fabric.Point} 51573 */ 51574 getCenterPoint: function() { 51575 var leftTop = new fabric.Point(this.left, this.top); 51576 return this.translateToCenterPoint(leftTop, this.originX, this.originY); 51577 }, 51578 51579 /** 51580 * Returns the coordinates of the object based on center coordinates 51581 * @param {fabric.Point} point The point which corresponds to the originX and originY params 51582 * @return {fabric.Point} 51583 */ 51584 // getOriginPoint: function(center) { 51585 // return this.translateToOriginPoint(center, this.originX, this.originY); 51586 // }, 51587 51588 /** 51589 * Returns the coordinates of the object as if it has a different origin 51590 * @param {String} originX Horizontal origin: 'left', 'center' or 'right' 51591 * @param {String} originY Vertical origin: 'top', 'center' or 'bottom' 51592 * @return {fabric.Point} 51593 */ 51594 getPointByOrigin: function(originX, originY) { 51595 var center = this.getCenterPoint(); 51596 return this.translateToOriginPoint(center, originX, originY); 51597 }, 51598 51599 /** 51600 * Returns the point in local coordinates 51601 * @param {fabric.Point} The point relative to the global coordinate system 51602 * @return {fabric.Point} 51603 */ 51604 toLocalPoint: function(point, originX, originY) { 51605 var center = this.getCenterPoint(); 51606 51607 var x, y; 51608 if (originX !== undefined && originY !== undefined) { 51609 if ( originX === "left" ) { 51610 x = center.x - (this.getWidth() + this.strokeWidth*this.scaleX) / 2; 51611 } 51612 else if ( originX === "right" ) { 51613 x = center.x + (this.getWidth() + this.strokeWidth*this.scaleX)/ 2; 51614 } 51615 else { 51616 x = center.x; 51617 } 51618 51619 if ( originY === "top" ) { 51620 y = center.y - (this.getHeight() + this.strokeWidth*this.scaleY) / 2; 51621 } 51622 else if ( originY === "bottom" ) { 51623 y = center.y + (this.getHeight() + this.strokeWidth*this.scaleY)/ 2; 51624 } 51625 else { 51626 y = center.y; 51627 } 51628 } 51629 else { 51630 x = this.left; 51631 y = this.top; 51632 } 51633 51634 return fabric.util.rotatePoint(new fabric.Point(point.x, point.y), center, -degreesToRadians(this.angle)) 51635 .subtractEquals(new fabric.Point(x, y)); 51636 }, 51637 51638 /** 51639 * Returns the point in global coordinates 51640 * @param {fabric.Point} The point relative to the local coordinate system 51641 * @return {fabric.Point} 51642 */ 51643 // toGlobalPoint: function(point) { 51644 // return fabric.util.rotatePoint(point, this.getCenterPoint(), degreesToRadians(this.angle)).addEquals(new fabric.Point(this.left, this.top)); 51645 // }, 51646 51647 /** 51648 * Sets the position of the object taking into consideration the object's origin 51649 * @param {fabric.Point} point The new position of the object 51650 * @param {String} originX Horizontal origin: 'left', 'center' or 'right' 51651 * @param {String} originY Vertical origin: 'top', 'center' or 'bottom' 51652 * @return {void} 51653 */ 51654 setPositionByOrigin: function(pos, originX, originY) { 51655 var center = this.translateToCenterPoint(pos, originX, originY); 51656 var position = this.translateToOriginPoint(center, this.originX, this.originY); 51657 51658 this.set('left', position.x); 51659 this.set('top', position.y); 51660 }, 51661 51662 /** 51663 * @param {String} to One of left, center, right 51664 */ 51665 adjustPosition: function(to) { 51666 var angle = degreesToRadians(this.angle); 51667 var hypotHalf = this.getWidth() / 2;
51668 var xHalf = Math.cos(angle) * hypotHalf; 51669 var yHalf = Math.sin(angle) * hypotHalf; 51670 var hypotFull = this.getWidth(); 51671 var xFull = Math.cos(angle) * hypotFull; 51672 var yFull = Math.sin(angle) * hypotFull; 51673 51674 if (this.originX === 'center' && to === 'left' || 51675 this.originX === 'right' && to === 'center') { 51676 // move half left 51677 this.left -= xHalf; 51678 this.top -= yHalf; 51679 } 51680 else if (this.originX === 'left' && to === 'center' || 51681 this.originX === 'center' && to === 'right') { 51682 // move half right 51683 this.left += xHalf; 51684 this.top += yHalf; 51685 } 51686 else if (this.originX === 'left' && to === 'right') { 51687 // move full right 51688 this.left += xFull; 51689 this.top += yFull; 51690 } 51691 else if (this.originX === 'right' && to === 'left') { 51692 // move full left 51693 this.left -= xFull; 51694 this.top -= yFull; 51695 } 51696 51697 this.setCoords(); 51698 this.originX = to; 51699 }, 51700 51701 /** 51702 * @private 51703 */ 51704 _getLeftTopCoords: function() { 51705 return this.translateToOriginPoint(this.getCenterPoint(), 'left', 'center'); 51706 } 51707 }); 51708 51709})(); 51710 51711 51712(function() { 51713 51714 var degreesToRadians = fabric.util.degreesToRadians; 51715 51716 fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ { 51717 51718 /** 51719 * Object containing coordinates of object's controls 51720 * @type Object 51721 * @default 51722 */ 51723 oCoords: null, 51724 51725 /** 51726 * Checks if object intersects with an area formed by 2 points 51727 * @param {Object} pointTL top-left point of area 51728 * @param {Object} pointBR bottom-right point of area 51729 * @return {Boolean} true if object intersects with an area formed by 2 points 51730 */ 51731 intersectsWithRect: function(pointTL, pointBR) { 51732 var oCoords = this.oCoords, 51733 tl = new fabric.Point(oCoords.tl.x, oCoords.tl.y), 51734 tr = new fabric.Point(oCoords.tr.x, oCoords.tr.y), 51735 bl = new fabric.Point(oCoords.bl.x, oCoords.bl.y), 51736 br = new fabric.Point(oCoords.br.x, oCoords.br.y); 51737 51738 var intersection = fabric.Intersection.intersectPolygonRectangle( 51739 [tl, tr, br, bl], 51740 pointTL, 51741 pointBR 51742 ); 51743 return intersection.status === 'Intersection'; 51744 }, 51745 51746 /** 51747 * Checks if object intersects with another object 51748 * @param {Object} other Object to test 51749 * @return {Boolean} true if object intersects with another object 51750 */ 51751 intersectsWithObject: function(other) { 51752 // extracts coords 51753 function getCoords(oCoords) { 51754 return { 51755 tl: new fabric.Point(oCoords.tl.x, oCoords.tl.y), 51756 tr: new fabric.Point(oCoords.tr.x, oCoords.tr.y), 51757 bl: new fabric.Point(oCoords.bl.x, oCoords.bl.y), 51758 br: new fabric.Point(oCoords.br.x, oCoords.br.y) 51759 }; 51760 } 51761 var thisCoords = getCoords(this.oCoords), 51762 otherCoords = getCoords(other.oCoords); 51763 51764 var intersection = fabric.Intersection.intersectPolygonPolygon( 51765 [thisCoords.tl, thisCoords.tr, thisCoords.br, thisCoords.bl], 51766 [otherCoords.tl, otherCoords.tr, otherCoords.br, otherCoords.bl] 51767 ); 51768 51769 return intersection.status === 'Intersection'; 51770 }, 51771 51772 /** 51773 * Checks if object is fully contained within area of another object 51774 * @param {Object} other Object to test 51775 * @return {Boolean} true if object is fully contained within area of another object 51776 */ 51777 isContainedWithinObject: function(other) { 51778 var boundingRect = other.getBoundingRect(), 51779 point1 = new fabric.Point(boundingRect.left, boundingRect.top), 51780 point2 = new fabric.Point(boundingRect.left + boundingRect.width, boundingRect.top + boundingRect.height); 51781 51782 return this.isContainedWithinRect(point1, point2); 51783 }, 51784 51785 /** 51786 * Checks if object is fully contained within area formed by 2 points 51787 * @param {Object} pointTL top-left point of area 51788 * @param {Object} pointBR bottom-right point of area 51789 * @return {Boolean} true if object is fully contained within area formed by 2 points 51790 */ 51791 isContainedWithinRect: function(pointTL, pointBR) {
51792 var boundingRect = this.getBoundingRect(); 51793 51794 return ( 51795 boundingRect.left > pointTL.x && 51796 boundingRect.left + boundingRect.width < pointBR.x && 51797 boundingRect.top > pointTL.y && 51798 boundingRect.top + boundingRect.height < pointBR.y 51799 ); 51800 }, 51801 51802 /** 51803 * Checks if point is inside the object 51804 * @param {Object} point 51805 * @return {Boolean} true if point is inside the object 51806 */ 51807 containsPoint: function(point) { 51808 var lines = this._getImageLines(this.oCoords), 51809 xPoints = this._findCrossPoints(point, lines); 51810 51811 // if xPoints is odd then point is inside the object 51812 return (xPoints !== 0 && xPoints % 2 === 1); 51813 }, 51814 51815 /** 51816 * Method that returns an object with the object edges in it, given the coordinates of the corners 51817 * @private 51818 * @param {Object} oCoords Coordinates of the object corners 51819 */ 51820 _getImageLines: function(oCoords) { 51821 return { 51822 topline: { 51823 o: oCoords.tl, 51824 d: oCoords.tr 51825 }, 51826 rightline: { 51827 o: oCoords.tr, 51828 d: oCoords.br 51829 }, 51830 bottomline: { 51831 o: oCoords.br, 51832 d: oCoords.bl 51833 }, 51834 leftline: { 51835 o: oCoords.bl, 51836 d: oCoords.tl 51837 } 51838 }; 51839 }, 51840 51841 /** 51842 * Helper method to determine how many cross points are between the 4 object edges 51843 * and the horizontal line determined by a point on canvas 51844 * @private 51845 * @param {Object} point 51846 * @param {Object} oCoords Coordinates of the image being evaluated 51847 */ 51848 _findCrossPoints: function(point, oCoords) { 51849 var b1, b2, a1, a2, xi, yi, 51850 xcount = 0, 51851 iLine; 51852 51853 for (var lineKey in oCoords) { 51854 iLine = oCoords[lineKey]; 51855 // optimisation 1: line below point. no cross 51856 if ((iLine.o.y < point.y) && (iLine.d.y < point.y)) { 51857 continue; 51858 } 51859 // optimisation 2: line above point. no cross 51860 if ((iLine.o.y >= point.y) && (iLine.d.y >= point.y)) { 51861 continue; 51862 } 51863 // optimisation 3: vertical line case 51864 if ((iLine.o.x === iLine.d.x) && (iLine.o.x >= point.x)) { 51865 xi = iLine.o.x; 51866 yi = point.y; 51867 } 51868 // calculate the intersection point 51869 else { 51870 b1 = 0; 51871 b2 = (iLine.d.y - iLine.o.y) / (iLine.d.x - iLine.o.x); 51872 a1 = point.y- b1 * point.x; 51873 a2 = iLine.o.y - b2 * iLine.o.x; 51874 51875 xi = - (a1 - a2) / (b1 - b2); 51876 yi = a1 + b1 * xi; 51877 } 51878 // dont count xi < point.x cases 51879 if (xi >= point.x) { 51880 xcount += 1; 51881 } 51882 // optimisation 4: specific for square images 51883 if (xcount === 2) { 51884 break; 51885 } 51886 } 51887 return xcount; 51888 }, 51889 51890 /** 51891 * Returns width of an object's bounding rectangle 51892 * @deprecated since 1.0.4 51893 * @return {Number} width value 51894 */ 51895 getBoundingRectWidth: function() { 51896 return this.getBoundingRect().width; 51897 }, 51898 51899 /** 51900 * Returns height of an object's bounding rectangle 51901 * @deprecated since 1.0.4 51902 * @return {Number} height value 51903 */ 51904 getBoundingRectHeight: function() { 51905 return this.getBoundingRect().height; 51906 }, 51907 51908 /** 51909 * Returns coordinates of object's bounding rectangle (left, top, width, height) 51910 * @return {Object} Object with left, top, width, height properties 51911 */ 51912 getBoundingRect: function() { 51913 this.oCoords || this.setCoords(); 51914 51915 var xCoords = [this.oCoords.tl.x, this.oCoords.tr.x, this.oCoords.br.x, this.oCoords.bl.x]; 51916 var minX = fabric.util.array.min(xCoords); 51917 var maxX = fabric.util.array.max(xCoords); 51918 var width = Math.abs(minX - maxX); 51919 51920 var yCoords = [this.oCoords.tl.y, this.oCoords.tr.y, this.oCoords.br.y, this.oCoords.bl.y]; 51921 var minY = fabric.util.array.min(yCoords); 51922 var maxY = fabric.util.array.max(yCoords); 51923 var height = Math.abs(minY - maxY); 51924 51925 return { 51926 left: minX, 51927 top: minY, 51928 width: width, 51929 height: height 51930 }; 51931 }, 51932 51933 /** 51934 * Returns width of an object 51935 * @return {Number} width value 51936 */ 51937 getWidth: function() { 51938 return this.width * this.scaleX; 51939 }, 51940 51941 /** 51942 * Returns height of an object 51943 * @return {Number} height value 51944 */ 51945 getHeight: function() { 51946 return this.height * this.scaleY; 51947 }, 51948 51949 /** 51950 * Makes sure the scale is valid and modifies it if necessary 51951 * @private 51952 * @param {Number} value 51953 * @return {Number} 51954 */ 51955 _constrainScale: function(value) { 51956 if (Math.abs(value) < this.minScaleLimit) { 51957 if (value < 0) 51958 return -this.minScaleLimit; 51959 else 51960 return this.minScaleLimit; 51961 } 51962 51963 return value; 51964 }, 51965 51966 /** 51967 * Scales an object (equally by x and y) 51968 * @param value {Number} scale factor 51969 * @return {fabric.Object} thisArg 51970 * @chainable 51971 */ 51972 scale: function(value) { 51973 value = this._constrainScale(value); 51974 51975 if (value < 0) { 51976 this.flipX = !this.flipX; 51977 this.flipY = !this.flipY; 51978 value *= -1; 51979 } 51980 51981 this.scaleX = value; 51982 this.scaleY = value; 51983 this.setCoords(); 51984 return this; 51985 }, 51986 51987 /**
51988 * Scales an object to a given width, with respect to bounding box (scaling by x/y equally) 51989 * @param value {Number} new width value 51990 * @return {fabric.Object} thisArg 51991 * @chainable 51992 */ 51993 scaleToWidth: function(value) { 51994 // adjust to bounding rect factor so that rotated shapes would fit as well 51995 var boundingRectFactor = this.getBoundingRectWidth() / this.getWidth(); 51996 return this.scale(value / this.width / boundingRectFactor); 51997 }, 51998 51999 /** 52000 * Scales an object to a given height, with respect to bounding box (scaling by x/y equally) 52001 * @param value {Number} new height value 52002 * @return {fabric.Object} thisArg 52003 * @chainable 52004 */ 52005 scaleToHeight: function(value) { 52006 // adjust to bounding rect factor so that rotated shapes would fit as well 52007 var boundingRectFactor = this.getBoundingRectHeight() / this.getHeight(); 52008 return this.scale(value / this.height / boundingRectFactor); 52009 }, 52010 52011 /** 52012 * Sets corner position coordinates based on current angle, width and height 52013 * @return {fabric.Object} thisArg 52014 * @chainable 52015 */ 52016 setCoords: function() { 52017 52018 var strokeWidth = this.strokeWidth > 1 ? this.strokeWidth : 0, 52019 padding = this.padding, 52020 theta = degreesToRadians(this.angle); 52021 52022 this.currentWidth = (this.width + strokeWidth) * this.scaleX + padding * 2; 52023 this.currentHeight = (this.height + strokeWidth) * this.scaleY + padding * 2; 52024 52025 // If width is negative, make postive. Fixes path selection issue 52026 if (this.currentWidth < 0) { 52027 this.currentWidth = Math.abs(this.currentWidth); 52028 } 52029 52030 var _hypotenuse = Math.sqrt( 52031 Math.pow(this.currentWidth / 2, 2) + 52032 Math.pow(this.currentHeight / 2, 2)); 52033 52034 var _angle = Math.atan(isFinite(this.currentHeight / this.currentWidth) ? this.currentHeight / this.currentWidth : 0); 52035 52036 // offset added for rotate and scale actions 52037 var offsetX = Math.cos(_angle + theta) * _hypotenuse, 52038 offsetY = Math.sin(_angle + theta) * _hypotenuse, 52039 sinTh = Math.sin(theta), 52040 cosTh = Math.cos(theta); 52041 52042 var coords = this.getCenterPoint(); 52043 var tl = { 52044 x: coords.x - offsetX, 52045 y: coords.y - offsetY 52046 }; 52047 var tr = { 52048 x: tl.x + (this.currentWidth * cosTh), 52049 y: tl.y + (this.currentWidth * sinTh) 52050 }; 52051 var br = { 52052 x: tr.x - (this.currentHeight * sinTh), 52053 y: tr.y + (this.currentHeight * cosTh) 52054 }; 52055 var bl = { 52056 x: tl.x - (this.currentHeight * sinTh), 52057 y: tl.y + (this.currentHeight * cosTh) 52058 }; 52059 var ml = { 52060 x: tl.x - (this.currentHeight/2 * sinTh), 52061 y: tl.y + (this.currentHeight/2 * cosTh) 52062 }; 52063 var mt = { 52064 x: tl.x + (this.currentWidth/2 * cosTh), 52065 y: tl.y + (this.currentWidth/2 * sinTh) 52066 }; 52067 var mr = { 52068 x: tr.x - (this.currentHeight/2 * sinTh), 52069 y: tr.y + (this.currentHeight/2 * cosTh) 52070 }; 52071 var mb = { 52072 x: bl.x + (this.currentWidth/2 * cosTh), 52073 y: bl.y + (this.currentWidth/2 * sinTh) 52074 }; 52075 var mtr = { 52076 x: mt.x, 52077 y: mt.y 52078 }; 52079 52080 // debugging 52081 52082 // setTimeout(function() { 52083 // canvas.contextTop.fillStyle = 'green'; 52084 // canvas.contextTop.fillRect(mb.x, mb.y, 3, 3); 52085 // canvas.contextTop.fillRect(bl.x, bl.y, 3, 3); 52086 // canvas.contextTop.fillRect(br.x, br.y, 3, 3); 52087 // canvas.contextTop.fillRect(tl.x, tl.y, 3, 3); 52088 // canvas.contextTop.fillRect(tr.x, tr.y, 3, 3); 52089 // canvas.contextTop.fillRect(ml.x, ml.y, 3, 3); 52090 // canvas.contextTop.fillRect(mr.x, mr.y, 3, 3); 52091 // canvas.contextTop.fillRect(mt.x, mt.y, 3, 3); 52092 // }, 50); 52093 52094 this.oCoords = { 52095 // corners 52096 tl: tl, tr: tr, br: br, bl: bl, 52097 // middle 52098 ml: ml, mt: mt, mr: mr, mb: mb, 52099 // rotating point 52100 mtr: mtr 52101 }; 52102 52103 // set coordinates of the draggable boxes in the corners used to scale/rotate the image 52104 this._setCornerCoords && this._setCornerCoords(); 52105 52106 return this; 52107 } 52108 }); 52109})(); 52110 52111 52112/* 52113 Depends on `stateProperties` 52114*/ 52115fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ { 52116 52117 /** 52118 * Returns true if object state (one of its state properties) was changed 52119 * @return {Boolean} true if instance' state has changed since `{@link fabric.Object#saveState}` was called 52120 */ 52121 hasStateChanged: function() { 52122 return this.stateProperties.some(function(prop) { 52123 return this.get(prop) !== this.originalState[prop]; 52124 }, this); 52125 }, 52126 52127 /** 52128 * Saves state of an object 52129 * @param {Object} [options] Object with additional `stateProperties` array to include when saving state 52130 * @return {fabric.Object} thisArg 52131 */ 52132 saveState: function(options) {
52133 this.stateProperties.forEach(function(prop) { 52134 this.originalState[prop] = this.get(prop); 52135 }, this); 52136 52137 if (options && options.stateProperties) { 52138 options.stateProperties.forEach(function(prop) { 52139 this.originalState[prop] = this.get(prop); 52140 }, this); 52141 } 52142 52143 return this; 52144 }, 52145 52146 /** 52147 * Setups state of an object 52148 * @return {fabric.Object} thisArg 52149 */ 52150 setupState: function() { 52151 this.originalState = { }; 52152 this.saveState(); 52153 52154 return this; 52155 } 52156}); 52157 52158 52159(function(){ 52160 52161 var getPointer = fabric.util.getPointer, 52162 degreesToRadians = fabric.util.degreesToRadians; 52163 52164 fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ { 52165 52166 /** 52167 * Determines which one of the four corners has been clicked 52168 * @private 52169 * @param {Event} e Event object 52170 * @param {Object} offset Canvas offset 52171 * @return {String|Boolean} corner code (tl, tr, bl, br, etc.), or false if nothing is found 52172 */ 52173 _findTargetCorner: function(e, offset) { 52174 if (!this.hasControls || !this.active) return false; 52175 52176 var pointer = getPointer(e, this.canvas.upperCanvasEl), 52177 ex = pointer.x - offset.left, 52178 ey = pointer.y - offset.top, 52179 xPoints, 52180 lines; 52181 52182 for (var i in this.oCoords) { 52183 52184 if (i === 'mtr' && !this.hasRotatingPoint) { 52185 continue; 52186 } 52187 52188 if (this.get('lockUniScaling') && (i === 'mt' || i === 'mr' || i === 'mb' || i === 'ml')) { 52189 continue; 52190 } 52191 52192 lines = this._getImageLines(this.oCoords[i].corner); 52193 52194 // debugging 52195 52196 // canvas.contextTop.fillRect(lines.bottomline.d.x, lines.bottomline.d.y, 2, 2); 52197 // canvas.contextTop.fillRect(lines.bottomline.o.x, lines.bottomline.o.y, 2, 2); 52198 52199 // canvas.contextTop.fillRect(lines.leftline.d.x, lines.leftline.d.y, 2, 2); 52200 // canvas.contextTop.fillRect(lines.leftline.o.x, lines.leftline.o.y, 2, 2); 52201 52202 // canvas.contextTop.fillRect(lines.topline.d.x, lines.topline.d.y, 2, 2); 52203 // canvas.contextTop.fillRect(lines.topline.o.x, lines.topline.o.y, 2, 2); 52204 52205 // canvas.contextTop.fillRect(lines.rightline.d.x, lines.rightline.d.y, 2, 2); 52206 // canvas.contextTop.fillRect(lines.rightline.o.x, lines.rightline.o.y, 2, 2); 52207 52208 xPoints = this._findCrossPoints({x: ex, y: ey}, lines); 52209 if (xPoints !== 0 && xPoints % 2 === 1) { 52210 this.__corner = i; 52211 return i; 52212 } 52213 } 52214 return false; 52215 }, 52216 52217 /** 52218 * Sets the coordinates of the draggable boxes in the corners of 52219 * the image used to scale/rotate it. 52220 * @private 52221 */ 52222 _setCornerCoords: function() { 52223 var coords = this.oCoords, 52224 theta = degreesToRadians(this.angle), 52225 newTheta = degreesToRadians(45 - this.angle), 52226 cornerHypotenuse = Math.sqrt(2 * Math.pow(this.cornerSize, 2)) / 2, 52227 cosHalfOffset = cornerHypotenuse * Math.cos(newTheta), 52228 sinHalfOffset = cornerHypotenuse * Math.sin(newTheta), 52229 sinTh = Math.sin(theta), 52230 cosTh = Math.cos(theta); 52231 52232 coords.tl.corner = { 52233 tl: { 52234 x: coords.tl.x - sinHalfOffset, 52235 y: coords.tl.y - cosHalfOffset 52236 }, 52237 tr: { 52238 x: coords.tl.x + cosHalfOffset, 52239 y: coords.tl.y - sinHalfOffset 52240 }, 52241 bl: { 52242 x: coords.tl.x - cosHalfOffset, 52243 y: coords.tl.y + sinHalfOffset 52244 }, 52245 br: { 52246 x: coords.tl.x + sinHalfOffset, 52247 y: coords.tl.y + cosHalfOffset 52248 } 52249 }; 52250 52251 coords.tr.corner = { 52252 tl: { 52253 x: coords.tr.x - sinHalfOffset, 52254 y: coords.tr.y - cosHalfOffset 52255 }, 52256 tr: { 52257 x: coords.tr.x + cosHalfOffset, 52258 y: coords.tr.y - sinHalfOffset 52259 }, 52260 br: { 52261 x: coords.tr.x + sinHalfOffset, 52262 y: coords.tr.y + cosHalfOffset 52263 }, 52264 bl: { 52265 x: coords.tr.x - cosHalfOffset, 52266 y: coords.tr.y + sinHalfOffset 52267 } 52268 }; 52269 52270 coords.bl.corner = { 52271 tl: { 52272 x: coords.bl.x - sinHalfOffset, 52273 y: coords.bl.y - cosHalfOffset 52274 }, 52275 bl: { 52276 x: coords.bl.x - cosHalfOffset, 52277 y: coords.bl.y + sinHalfOffset 52278 }, 52279 br: { 52280 x: coords.bl.x + sinHalfOffset, 52281 y: coords.bl.y + cosHalfOffset 52282 }, 52283 tr: { 52284 x: coords.bl.x + cosHalfOffset, 52285 y: coords.bl.y - sinHalfOffset 52286 } 52287 }; 52288 52289 coords.br.corner = { 52290 tr: { 52291 x: coords.br.x + cosHalfOffset, 52292 y: coords.br.y - sinHalfOffset 52293 }, 52294 bl: { 52295 x: coords.br.x - cosHalfOffset, 52296 y: coords.br.y + sinHalfOffset 52297 }, 52298 br: { 52299 x: coords.br.x + sinHalfOffset, 52300 y: coords.br.y + cosHalfOffset 52301 }, 52302 tl: { 52303 x: coords.br.x - sinHalfOffset, 52304 y: coords.br.y - cosHalfOffset 52305 } 52306 }; 52307 52308 coords.ml.corner = { 52309 tl: { 52310 x: coords.ml.x - sinHalfOffset,
52311 y: coords.ml.y - cosHalfOffset 52312 }, 52313 tr: { 52314 x: coords.ml.x + cosHalfOffset, 52315 y: coords.ml.y - sinHalfOffset 52316 }, 52317 bl: { 52318 x: coords.ml.x - cosHalfOffset, 52319 y: coords.ml.y + sinHalfOffset 52320 }, 52321 br: { 52322 x: coords.ml.x + sinHalfOffset, 52323 y: coords.ml.y + cosHalfOffset 52324 } 52325 }; 52326 52327 coords.mt.corner = { 52328 tl: { 52329 x: coords.mt.x - sinHalfOffset, 52330 y: coords.mt.y - cosHalfOffset 52331 }, 52332 tr: { 52333 x: coords.mt.x + cosHalfOffset, 52334 y: coords.mt.y - sinHalfOffset 52335 }, 52336 bl: { 52337 x: coords.mt.x - cosHalfOffset, 52338 y: coords.mt.y + sinHalfOffset 52339 }, 52340 br: { 52341 x: coords.mt.x + sinHalfOffset, 52342 y: coords.mt.y + cosHalfOffset 52343 } 52344 }; 52345 52346 coords.mr.corner = { 52347 tl: { 52348 x: coords.mr.x - sinHalfOffset, 52349 y: coords.mr.y - cosHalfOffset 52350 }, 52351 tr: { 52352 x: coords.mr.x + cosHalfOffset, 52353 y: coords.mr.y - sinHalfOffset 52354 }, 52355 bl: { 52356 x: coords.mr.x - cosHalfOffset, 52357 y: coords.mr.y + sinHalfOffset 52358 }, 52359 br: { 52360 x: coords.mr.x + sinHalfOffset, 52361 y: coords.mr.y + cosHalfOffset 52362 } 52363 }; 52364 52365 coords.mb.corner = { 52366 tl: { 52367 x: coords.mb.x - sinHalfOffset, 52368 y: coords.mb.y - cosHalfOffset 52369 }, 52370 tr: { 52371 x: coords.mb.x + cosHalfOffset, 52372 y: coords.mb.y - sinHalfOffset 52373 }, 52374 bl: { 52375 x: coords.mb.x - cosHalfOffset, 52376 y: coords.mb.y + sinHalfOffset 52377 }, 52378 br: { 52379 x: coords.mb.x + sinHalfOffset, 52380 y: coords.mb.y + cosHalfOffset 52381 } 52382 }; 52383 52384 coords.mtr.corner = { 52385 tl: { 52386 x: coords.mtr.x - sinHalfOffset + (sinTh * this.rotatingPointOffset), 52387 y: coords.mtr.y - cosHalfOffset - (cosTh * this.rotatingPointOffset) 52388 }, 52389 tr: { 52390 x: coords.mtr.x + cosHalfOffset + (sinTh * this.rotatingPointOffset), 52391 y: coords.mtr.y - sinHalfOffset - (cosTh * this.rotatingPointOffset) 52392 }, 52393 bl: { 52394 x: coords.mtr.x - cosHalfOffset + (sinTh * this.rotatingPointOffset), 52395 y: coords.mtr.y + sinHalfOffset - (cosTh * this.rotatingPointOffset) 52396 }, 52397 br: { 52398 x: coords.mtr.x + sinHalfOffset + (sinTh * this.rotatingPointOffset), 52399 y: coords.mtr.y + cosHalfOffset - (cosTh * this.rotatingPointOffset) 52400 } 52401 }; 52402 }, 52403 /** 52404 * Draws borders of an object's bounding box. 52405 * Requires public properties: width, height 52406 * Requires public options: padding, borderColor 52407 * @param {CanvasRenderingContext2D} ctx Context to draw on 52408 * @return {fabric.Object} thisArg 52409 * @chainable 52410 */ 52411 drawBorders: function(ctx) { 52412 if (!this.hasBorders) return this; 52413 52414 var padding = this.padding, 52415 padding2 = padding * 2, 52416 strokeWidth = ~~(this.strokeWidth / 2) * 2; // Round down to even number 52417 52418 ctx.save(); 52419 52420 ctx.globalAlpha = this.isMoving ? this.borderOpacityWhenMoving : 1; 52421 ctx.strokeStyle = this.borderColor; 52422 52423 var scaleX = 1 / this._constrainScale(this.scaleX), 52424 scaleY = 1 / this._constrainScale(this.scaleY); 52425 52426 ctx.lineWidth = 1 / this.borderScaleFactor; 52427 52428 ctx.scale(scaleX, scaleY); 52429 52430 var w = this.getWidth(), 52431 h = this.getHeight(); 52432 52433 ctx.strokeRect( 52434 ~~(-(w / 2) - padding - strokeWidth / 2 * this.scaleX) - 0.5, // offset needed to make lines look sharper 52435 ~~(-(h / 2) - padding - strokeWidth / 2 * this.scaleY) - 0.5, 52436 ~~(w + padding2 + strokeWidth * this.scaleX) + 1, // double offset needed to make lines look sharper 52437 ~~(h + padding2 + strokeWidth * this.scaleY) + 1 52438 ); 52439 52440 if (this.hasRotatingPoint && !this.get('lockRotation') && this.hasControls) { 52441 52442 var rotateHeight = ( 52443 this.flipY 52444 ? h + (strokeWidth * this.scaleY) + (padding * 2) 52445 : -h - (strokeWidth * this.scaleY) - (padding * 2) 52446 ) / 2; 52447 52448 ctx.beginPath(); 52449 ctx.moveTo(0, rotateHeight); 52450 ctx.lineTo(0, rotateHeight + (this.flipY ? this.rotatingPointOffset : -this.rotatingPointOffset)); 52451 ctx.closePath(); 52452 ctx.stroke(); 52453 } 52454
52455 ctx.restore(); 52456 return this; 52457 }, 52458 52459 /** 52460 * Draws corners of an object's bounding box. 52461 * Requires public properties: width, height, scaleX, scaleY 52462 * Requires public options: cornerSize, padding 52463 * @param {CanvasRenderingContext2D} ctx Context to draw on 52464 * @return {fabric.Object} thisArg 52465 * @chainable 52466 */ 52467 drawControls: function(ctx) { 52468 if (!this.hasControls) return this; 52469 52470 var size = this.cornerSize, 52471 size2 = size / 2, 52472 strokeWidth2 = ~~(this.strokeWidth / 2), // half strokeWidth rounded down 52473 left = -(this.width / 2), 52474 top = -(this.height / 2), 52475 _left, 52476 _top, 52477 sizeX = size / this.scaleX, 52478 sizeY = size / this.scaleY, 52479 paddingX = this.padding / this.scaleX, 52480 paddingY = this.padding / this.scaleY, 52481 scaleOffsetY = size2 / this.scaleY, 52482 scaleOffsetX = size2 / this.scaleX, 52483 scaleOffsetSizeX = (size2 - size) / this.scaleX, 52484 scaleOffsetSizeY = (size2 - size) / this.scaleY, 52485 height = this.height, 52486 width = this.width, 52487 methodName = this.transparentCorners ? 'strokeRect' : 'fillRect', 52488 transparent = this.transparentCorners, 52489 isVML = typeof G_vmlCanvasManager !== 'undefined'; 52490 52491 ctx.save(); 52492 52493 ctx.lineWidth = 1 / Math.max(this.scaleX, this.scaleY); 52494 52495 ctx.globalAlpha = this.isMoving ? this.borderOpacityWhenMoving : 1; 52496 ctx.strokeStyle = ctx.fillStyle = this.cornerColor; 52497 52498 // top-left 52499 _left = left - scaleOffsetX - strokeWidth2 - paddingX; 52500 _top = top - scaleOffsetY - strokeWidth2 - paddingY; 52501 52502 isVML || transparent || ctx.clearRect(_left, _top, sizeX, sizeY); 52503 ctx[methodName](_left, _top, sizeX, sizeY); 52504 52505 // top-right 52506 _left = left + width - scaleOffsetX + strokeWidth2 + paddingX; 52507 _top = top - scaleOffsetY - strokeWidth2 - paddingY; 52508 52509 isVML || transparent || ctx.clearRect(_left, _top, sizeX, sizeY); 52510 ctx[methodName](_left, _top, sizeX, sizeY); 52511 52512 // bottom-left 52513 _left = left - scaleOffsetX - strokeWidth2 - paddingX; 52514 _top = top + height + scaleOffsetSizeY + strokeWidth2 + paddingY; 52515 52516 isVML || transparent || ctx.clearRect(_left, _top, sizeX, sizeY); 52517 ctx[methodName](_left, _top, sizeX, sizeY); 52518 52519 // bottom-right 52520 _left = left + width + scaleOffsetSizeX + strokeWidth2 + paddingX; 52521 _top = top + height + scaleOffsetSizeY + strokeWidth2 + paddingY; 52522 52523 isVML || transparent || ctx.clearRect(_left, _top, sizeX, sizeY); 52524 ctx[methodName](_left, _top, sizeX, sizeY); 52525 52526 if (!this.get('lockUniScaling')) { 52527 // middle-top 52528 _left = left + width/2 - scaleOffsetX; 52529 _top = top - scaleOffsetY - strokeWidth2 - paddingY; 52530 52531 isVML || transparent || ctx.clearRect(_left, _top, sizeX, sizeY); 52532 ctx[methodName](_left, _top, sizeX, sizeY); 52533 52534 // middle-bottom 52535 _left = left + width/2 - scaleOffsetX; 52536 _top = top + height + scaleOffsetSizeY + strokeWidth2 + paddingY; 52537 52538 isVML || transparent || ctx.clearRect(_left, _top, sizeX, sizeY); 52539 ctx[methodName](_left, _top, sizeX, sizeY); 52540 52541 // middle-right 52542 _left = left + width + scaleOffsetSizeX + strokeWidth2 + paddingX; 52543 _top = top + height/2 - scaleOffsetY; 52544 52545 isVML || transparent || ctx.clearRect(_left, _top, sizeX, sizeY); 52546 ctx[methodName](_left, _top, sizeX, sizeY); 52547 52548 // middle-left 52549 _left = left - scaleOffsetX - strokeWidth2 - paddingX; 52550 _top = top + height/2 - scaleOffsetY; 52551 52552 isVML || transparent || ctx.clearRect(_left, _top, sizeX, sizeY); 52553 ctx[methodName](_left, _top, sizeX, sizeY); 52554 } 52555 52556 // middle-top-rotate 52557 if (this.hasRotatingPoint) { 52558 52559 _left = left + width/2 - scaleOffsetX; 52560 _top = this.flipY ? 52561 (top + height + (this.rotatingPointOffset / this.scaleY) - sizeY/2 + strokeWidth2 + paddingY) 52562 : (top - (this.rotatingPointOffset / this.scaleY) - sizeY/2 - strokeWidth2 - paddingY); 52563 52564 isVML || transparent || ctx.clearRect(_left, _top, sizeX, sizeY); 52565 ctx[methodName](_left, _top, sizeX, sizeY); 52566 } 52567
vendor: 6,900 bytes, lines 52568-52822
52568 ctx.restore(); 52569 52570 return this; 52571 } 52572 }); 52573})(); 52574 52575 52576fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.StaticCanvas.prototype */ { 52577 52578 /** 52579 * Animation duration (in ms) for fx* methods 52580 * @type Number 52581 * @default 52582 */ 52583 FX_DURATION: 500, 52584 52585 /** 52586 * Centers object horizontally with animation. 52587 * @param {fabric.Object} object Object to center 52588 * @param {Object} [callbacks] Callbacks object with optional "onComplete" and/or "onChange" properties 52589 * @param {Function} [callbacks.onComplete] Invoked on completion 52590 * @param {Function} [callbacks.onChange] Invoked on every step of animation 52591 * @return {fabric.Canvas} thisArg 52592 * @chainable 52593 */ 52594 fxCenterObjectH: function (object, callbacks) { 52595 callbacks = callbacks || { }; 52596 52597 var empty = function() { }, 52598 onComplete = callbacks.onComplete || empty, 52599 onChange = callbacks.onChange || empty, 52600 _this = this; 52601 52602 fabric.util.animate({ 52603 startValue: object.get('left'), 52604 endValue: this.getCenter().left, 52605 duration: this.FX_DURATION, 52606 onChange: function(value) { 52607 object.set('left', value); 52608 _this.renderAll(); 52609 onChange(); 52610 }, 52611 onComplete: function() { 52612 object.setCoords(); 52613 onComplete(); 52614 } 52615 }); 52616 52617 return this; 52618 }, 52619 52620 /** 52621 * Centers object vertically with animation. 52622 * @param {fabric.Object} object Object to center 52623 * @param {Object} [callbacks] Callbacks object with optional "onComplete" and/or "onChange" properties 52624 * @param {Function} [callbacks.onComplete] Invoked on completion 52625 * @param {Function} [callbacks.onChange] Invoked on every step of animation 52626 * @return {fabric.Canvas} thisArg 52627 * @chainable 52628 */ 52629 fxCenterObjectV: function (object, callbacks) { 52630 callbacks = callbacks || { }; 52631 52632 var empty = function() { }, 52633 onComplete = callbacks.onComplete || empty, 52634 onChange = callbacks.onChange || empty, 52635 _this = this; 52636 52637 fabric.util.animate({ 52638 startValue: object.get('top'), 52639 endValue: this.getCenter().top, 52640 duration: this.FX_DURATION, 52641 onChange: function(value) { 52642 object.set('top', value); 52643 _this.renderAll(); 52644 onChange(); 52645 }, 52646 onComplete: function() { 52647 object.setCoords(); 52648 onComplete(); 52649 } 52650 }); 52651 52652 return this; 52653 }, 52654 52655 /** 52656 * Same as `fabric.Canvas#remove` but animated 52657 * @param {fabric.Object} object Object to remove 52658 * @param {Object} [callbacks] Callbacks object with optional "onComplete" and/or "onChange" properties 52659 * @param {Function} [callbacks.onComplete] Invoked on completion 52660 * @param {Function} [callbacks.onChange] Invoked on every step of animation 52661 * @return {fabric.Canvas} thisArg 52662 * @chainable 52663 */ 52664 fxRemove: function (object, callbacks) { 52665 callbacks = callbacks || { }; 52666 52667 var empty = function() { }, 52668 onComplete = callbacks.onComplete || empty, 52669 onChange = callbacks.onChange || empty, 52670 _this = this; 52671 52672 fabric.util.animate({ 52673 startValue: object.get('opacity'), 52674 endValue: 0, 52675 duration: this.FX_DURATION, 52676 onStart: function() { 52677 object.set('active', false); 52678 }, 52679 onChange: function(value) { 52680 object.set('opacity', value); 52681 _this.renderAll(); 52682 onChange(); 52683 }, 52684 onComplete: function () { 52685 _this.remove(object); 52686 onComplete(); 52687 } 52688 }); 52689 52690 return this; 52691 } 52692}); 52693 52694fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ { 52695 /** 52696 * Animates object's properties 52697 * @param {String|Object} property to animate (if string) or properties to animate (if object) 52698 * @param {Number|Object} value to animate property to (if string was given first) or options object 52699 * @return {fabric.Object} thisArg 52700 * @tutorial {@link http://fabricjs.com/fabric-intro-part-2/#animation} 52701 * @chainable 52702 * 52703 * As object â multiple properties 52704 * 52705 * object.animate({ left: ..., top: ... }); 52706 * object.animate({ left: ..., top: ... }, { duration: ... }); 52707 * 52708 * As string â one property 52709 * 52710 * object.animate('left', ...); 52711 * object.animate('left', { duration: ... }); 52712 * 52713 */ 52714 animate: function() { 52715 if (arguments[0] && typeof arguments[0] === 'object') { 52716 var propsToAnimate = [ ], prop, skipCallbacks; 52717 for (prop in arguments[0]) { 52718 propsToAnimate.push(prop); 52719 } 52720 for (var i = 0, len = propsToAnimate.length; i<len; i++) { 52721 prop = propsToAnimate[i]; 52722 skipCallbacks = i !== len - 1; 52723 this._animate(prop, arguments[0][prop], arguments[1], skipCallbacks); 52724 } 52725 } 52726 else { 52727 this._animate.apply(this, arguments); 52728 } 52729 return this; 52730 }, 52731 52732 /** 52733 * @private 52734 * @param {String} property Property to animate 52735 * @param {String} to Value to animate to 52736 * @param {Object} [options] Options object 52737 * @param {Boolean} [skipCallbacks] When true, callbacks like onchange and oncomplete are not invoked 52738 */ 52739 _animate: function(property, to, options, skipCallbacks) { 52740 var obj = this, propPair; 52741 52742 to = to.toString(); 52743 52744 if (!options) { 52745 options = { }; 52746 } 52747 else { 52748 options = fabric.util.object.clone(options); 52749 } 52750 52751 if (~property.indexOf('.')) { 52752 propPair = property.split('.'); 52753 } 52754 52755 var currentValue = propPair 52756 ? this.get(propPair[0])[propPair[1]] 52757 : this.get(property); 52758 52759 if (!('from' in options)) { 52760 options.from = currentValue; 52761 } 52762 52763 if (~to.indexOf('=')) { 52764 to = currentValue + parseFloat(to.replace('=', '')); 52765 } 52766 else { 52767 to = parseFloat(to); 52768 } 52769 52770 fabric.util.animate({ 52771 startValue: options.from, 52772 endValue: to, 52773 byValue: options.by, 52774 easing: options.easing, 52775 duration: options.duration, 52776 abort: options.abort && function() { 52777 return options.abort.call(obj); 52778 }, 52779 onChange: function(value) { 52780 if (propPair) { 52781 obj[propPair[0]][propPair[1]] = value; 52782 } 52783 else { 52784 obj.set(property, value); 52785 } 52786 if (skipCallbacks) return; 52787 options.onChange && options.onChange(); 52788 }, 52789 onComplete: function() { 52790 if (skipCallbacks) return; 52791 52792 obj.setCoords(); 52793 options.onComplete && options.onComplete(); 52794 } 52795 }); 52796 } 52797}); 52798 52799 52800(function(global) { 52801 52802 "use strict"; 52803 52804 var fabric = global.fabric || (global.fabric = { }), 52805 extend = fabric.util.object.extend, 52806 coordProps = { 'x1': 1, 'x2': 1, 'y1': 1, 'y2': 1 }, 52807 supportsLineDash = fabric.StaticCanvas.supports('setLineDash'); 52808 52809 if (fabric.Line) { 52810 fabric.warn('fabric.Line is already defined'); 52811 return; 52812 } 52813 52814 /** 52815 * Line class 52816 * @class fabric.Line 52817 * @extends fabric.Object 52818 */ 52819 fabric.Line = fabric.util.createClass(fabric.Object, /** @lends fabric.Line.prototype */ { 52820 52821 /** 52822 * Type of an object
52823 * @type String 52824 * @default 52825 */ 52826 type: 'line', 52827 52828 /** 52829 * Constructor 52830 * @param {Array} [points] Array of points 52831 * @param {Object} [options] Options object 52832 * @return {fabric.Line} thisArg 52833 */ 52834 initialize: function(points, options) { 52835 options = options || { }; 52836 52837 if (!points) { 52838 points = [0, 0, 0, 0]; 52839 } 52840 52841 this.callSuper('initialize', options); 52842 52843 this.set('x1', points[0]); 52844 this.set('y1', points[1]); 52845 this.set('x2', points[2]); 52846 this.set('y2', points[3]); 52847 52848 this._setWidthHeight(options); 52849 }, 52850 52851 /** 52852 * @private 52853 * @param {Object} [options] Options 52854 */ 52855 _setWidthHeight: function(options) { 52856 options || (options = { }); 52857 52858 this.set('width', Math.abs(this.x2 - this.x1) || 1); 52859 this.set('height', Math.abs(this.y2 - this.y1) || 1); 52860 52861 this.set('left', 'left' in options ? options.left : (Math.min(this.x1, this.x2) + this.width / 2)); 52862 this.set('top', 'top' in options ? options.top : (Math.min(this.y1, this.y2) + this.height / 2)); 52863 }, 52864 52865 /** 52866 * @private 52867 * @param {String} key 52868 * @param {Any} value 52869 */ 52870 _set: function(key, value) { 52871 this[key] = value; 52872 if (key in coordProps) { 52873 this._setWidthHeight(); 52874 } 52875 return this; 52876 }, 52877 52878 /** 52879 * @private 52880 * @param {CanvasRenderingContext2D} ctx Context to render on 52881 */ 52882 _render: function(ctx) { 52883 ctx.beginPath(); 52884 52885 var isInPathGroup = this.group && this.group.type !== 'group'; 52886 if (isInPathGroup && !this.transformMatrix) { 52887 ctx.translate(-this.group.width/2 + this.left, -this.group.height / 2 + this.top); 52888 } 52889 52890 if (!this.strokeDashArray || this.strokeDashArray && supportsLineDash) { 52891 52892 // move from center (of virtual box) to its left/top corner 52893 // we can't assume x1, y1 is top left and x2, y2 is bottom right 52894 var xMult = this.x1 <= this.x2 ? -1 : 1; 52895 var yMult = this.y1 <= this.y2 ? -1 : 1; 52896 52897 ctx.moveTo( 52898 this.width === 1 ? 0 : (xMult * this.width / 2), 52899 this.height === 1 ? 0 : (yMult * this.height / 2)); 52900 52901 ctx.lineTo( 52902 this.width === 1 ? 0 : (xMult * -1 * this.width / 2), 52903 this.height === 1 ? 0 : (yMult * -1 * this.height / 2)); 52904 } 52905 52906 ctx.lineWidth = this.strokeWidth; 52907 52908 // TODO: test this 52909 // make sure setting "fill" changes color of a line 52910 // (by copying fillStyle to strokeStyle, since line is stroked, not filled) 52911 var origStrokeStyle = ctx.strokeStyle; 52912 ctx.strokeStyle = this.stroke || ctx.fillStyle; 52913 this._renderStroke(ctx); 52914 ctx.strokeStyle = origStrokeStyle; 52915 }, 52916 52917 /** 52918 * @private 52919 * @param {CanvasRenderingContext2D} ctx Context to render on 52920 */ 52921 _renderDashedStroke: function(ctx) { 52922 var 52923 xMult = this.x1 <= this.x2 ? -1 : 1, 52924 yMult = this.y1 <= this.y2 ? -1 : 1, 52925 x = this.width === 1 ? 0 : xMult * this.width / 2, 52926 y = this.height === 1 ? 0 : yMult * this.height / 2; 52927 52928 ctx.beginPath(); 52929 fabric.util.drawDashedLine(ctx, x, y, -x, -y, this.strokeDashArray); 52930 ctx.closePath(); 52931 }, 52932 52933 /** 52934 * Returns object representation of an instance 52935 * @methd toObject 52936 * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output 52937 * @return {Object} object representation of an instance 52938 */ 52939 toObject: function(propertiesToInclude) { 52940 return extend(this.callSuper('toObject', propertiesToInclude), { 52941 x1: this.get('x1'), 52942 y1: this.get('y1'), 52943 x2: this.get('x2'), 52944 y2: this.get('y2') 52945 }); 52946 }, 52947 52948 /* _TO_SVG_START_ */ 52949 /** 52950 * Returns SVG representation of an instance 52951 * @param {Function} [reviver] Method for further parsing of svg representation. 52952 * @return {String} svg representation of an instance 52953 */ 52954 toSVG: function(reviver) { 52955 var markup = this._createBaseSVGMarkup(); 52956 52957 markup.push( 52958 '<line ', 52959 'x1="', this.get('x1'), 52960 '" y1="', this.get('y1'), 52961 '" x2="', this.get('x2'), 52962 '" y2="', this.get('y2'),
52963 '" style="', this.getSvgStyles(), 52964 '"/>' 52965 ); 52966 52967 return reviver ? reviver(markup.join('')) : markup.join(''); 52968 }, 52969 /* _TO_SVG_END_ */ 52970 52971 /** 52972 * Returns complexity of an instance 52973 * @return {Number} complexity 52974 */ 52975 complexity: function() { 52976 return 1; 52977 } 52978 }); 52979 52980 /* _FROM_SVG_START_ */ 52981 /** 52982 * List of attribute names to account for when parsing SVG element (used by {@link fabric.Line.fromElement}) 52983 * @static 52984 * @memberOf fabric.Line 52985 * @see http://www.w3.org/TR/SVG/shapes.html#LineElement 52986 */ 52987 fabric.Line.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat('x1 y1 x2 y2'.split(' ')); 52988 52989 /** 52990 * Returns fabric.Line instance from an SVG element 52991 * @static 52992 * @memberOf fabric.Line 52993 * @param {SVGElement} element Element to parse 52994 * @param {Object} [options] Options object 52995 * @return {fabric.Line} instance of fabric.Line 52996 */ 52997 fabric.Line.fromElement = function(element, options) { 52998 var parsedAttributes = fabric.parseAttributes(element, fabric.Line.ATTRIBUTE_NAMES); 52999 var points = [ 53000 parsedAttributes.x1 || 0, 53001 parsedAttributes.y1 || 0, 53002 parsedAttributes.x2 || 0, 53003 parsedAttributes.y2 || 0 53004 ]; 53005 return new fabric.Line(points, extend(parsedAttributes, options)); 53006 }; 53007 /* _FROM_SVG_END_ */ 53008 53009 /** 53010 * Returns fabric.Line instance from an object representation 53011 * @static 53012 * @memberOf fabric.Line 53013 * @param {Object} object Object to create an instance from 53014 * @return {fabric.Line} instance of fabric.Line 53015 */ 53016 fabric.Line.fromObject = function(object) { 53017 var points = [object.x1, object.y1, object.x2, object.y2]; 53018 return new fabric.Line(points, object); 53019 }; 53020 53021})(typeof exports !== 'undefined' ? exports : this); 53022 53023 53024(function(global) { 53025 53026 "use strict"; 53027 53028 var fabric = global.fabric || (global.fabric = { }), 53029 piBy2 = Math.PI * 2, 53030 extend = fabric.util.object.extend; 53031 53032 if (fabric.Circle) { 53033 fabric.warn('fabric.Circle is already defined.'); 53034 return; 53035 } 53036 53037 /** 53038 * Circle class 53039 * @class fabric.Circle 53040 * @extends fabric.Object 53041 */ 53042 fabric.Circle = fabric.util.createClass(fabric.Object, /** @lends fabric.Circle.prototype */ { 53043 53044 /** 53045 * Type of an object
53046 * @type String 53047 * @default 53048 */ 53049 type: 'circle', 53050 53051 /** 53052 * Constructor 53053 * @param {Object} [options] Options object 53054 * @return {fabric.Circle} thisArg 53055 */ 53056 initialize: function(options) { 53057 options = options || { }; 53058 53059 this.set('radius', options.radius || 0); 53060 this.callSuper('initialize', options); 53061 }, 53062 53063 /** 53064 * @private 53065 * @param {String} key 53066 * @param {Any} value 53067 * @return {fabric.Circle} thisArg 53068 */ 53069 _set: function(key, value) { 53070 this.callSuper('_set', key, value); 53071 53072 if (key === 'radius') { 53073 this.setRadius(value); 53074 } 53075 53076 return this; 53077 }, 53078 53079 /** 53080 * Returns object representation of an instance 53081 * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output 53082 * @return {Object} object representation of an instance 53083 */ 53084 toObject: function(propertiesToInclude) { 53085 return extend(this.callSuper('toObject', propertiesToInclude), { 53086 radius: this.get('radius') 53087 }); 53088 }, 53089 53090 /* _TO_SVG_START_ */ 53091 /** 53092 * Returns svg representation of an instance 53093 * @param {Function} [reviver] Method for further parsing of svg representation. 53094 * @return {String} svg representation of an instance 53095 */ 53096 toSVG: function(reviver) { 53097 var markup = this._createBaseSVGMarkup(); 53098 53099 markup.push( 53100 '<circle ', 53101 'cx="0" cy="0" ', 53102 'r="', this.radius, 53103 '" style="', this.getSvgStyles(), 53104 '" transform="', this.getSvgTransform(), 53105 '"/>' 53106 ); 53107 53108 return reviver ? reviver(markup.join('')) : markup.join(''); 53109 }, 53110 /* _TO_SVG_END_ */ 53111 53112 /** 53113 * @private 53114 * @param ctx {CanvasRenderingContext2D} context to render on 53115 */ 53116 _render: function(ctx, noTransform) { 53117 ctx.beginPath(); 53118 // multiply by currently set alpha (the one that was set by path group where this object is contained, for example) 53119 ctx.globalAlpha = this.group ? (ctx.globalAlpha * this.opacity) : this.opacity; 53120 ctx.arc(noTransform ? this.left : 0, noTransform ? this.top : 0, this.radius, 0, piBy2, false); 53121 ctx.closePath(); 53122 53123 this._renderFill(ctx); 53124 this._renderStroke(ctx); 53125 }, 53126 53127 /** 53128 * Returns horizontal radius of an object (according to how an object is scaled) 53129 * @return {Number} 53130 */ 53131 getRadiusX: function() { 53132 return this.get('radius') * this.get('scaleX'); 53133 }, 53134 53135 /** 53136 * Returns vertical radius of an object (according to how an object is scaled) 53137 * @return {Number} 53138 */ 53139 getRadiusY: function() { 53140 return this.get('radius') * this.get('scaleY'); 53141 }, 53142 53143 /** 53144 * Sets radius of an object (and updates width accordingly) 53145 * @return {Number} 53146 */ 53147 setRadius: function(value) { 53148 this.radius = value; 53149 this.set('width', value * 2).set('height', value * 2); 53150 }, 53151 53152 /** 53153 * Returns complexity of an instance 53154 * @return {Number} complexity of this instance 53155 */ 53156 complexity: function() { 53157 return 1; 53158 } 53159 }); 53160 53161 /* _FROM_SVG_START_ */ 53162 /** 53163 * List of attribute names to account for when parsing SVG element (used by {@link fabric.Circle.fromElement}) 53164 * @static 53165 * @memberOf fabric.Circle 53166 * @see: http://www.w3.org/TR/SVG/shapes.html#CircleElement 53167 */ 53168 fabric.Circle.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat('cx cy r'.split(' ')); 53169 53170 /** 53171 * Returns {@link fabric.Circle} instance from an SVG element 53172 * @static 53173 * @memberOf fabric.Circle 53174 * @param {SVGElement} element Element to parse 53175 * @param {Object} [options] Options object 53176 * @throws {Error} If value of `r` attribute is missing or invalid 53177 * @return {fabric.Circle} Instance of fabric.Circle 53178 */ 53179 fabric.Circle.fromElement = function(element, options) { 53180 options || (options = { }); 53181 var parsedAttributes = fabric.parseAttributes(element, fabric.Circle.ATTRIBUTE_NAMES); 53182 if (!isValidRadius(parsedAttributes)) { 53183 throw new Error('value of `r` attribute is required and can not be negative'); 53184 } 53185 if ('left' in parsedAttributes) { 53186 parsedAttributes.left -= (options.width / 2) || 0; 53187 } 53188 if ('top' in parsedAttributes) { 53189 parsedAttributes.top -= (options.height / 2) || 0; 53190 } 53191 var obj = new fabric.Circle(extend(parsedAttributes, options)); 53192 53193 obj.cx = parseFloat(element.getAttribute('cx')) || 0; 53194 obj.cy = parseFloat(element.getAttribute('cy')) || 0; 53195 53196 return obj; 53197 }; 53198 53199 /** 53200 * @private 53201 */ 53202 function isValidRadius(attributes) { 53203 return (('radius' in attributes) && (attributes.radius > 0)); 53204 } 53205 /* _FROM_SVG_END_ */ 53206 53207 /** 53208 * Returns {@link fabric.Circle} instance from an object representation 53209 * @static 53210 * @memberOf fabric.Circle 53211 * @param {Object} object Object to create an instance from 53212 * @return {Object} Instance of fabric.Circle 53213 */ 53214 fabric.Circle.fromObject = function(object) { 53215 return new fabric.Circle(object); 53216 }; 53217 53218})(typeof exports !== 'undefined' ? exports : this); 53219 53220 53221(function(global) { 53222 53223 "use strict"; 53224 53225 var fabric = global.fabric || (global.fabric = { }); 53226 53227 if (fabric.Triangle) { 53228 fabric.warn('fabric.Triangle is already defined'); 53229 return; 53230 } 53231 53232 /** 53233 * Triangle class 53234 * @class fabric.Triangle 53235 * @extends fabric.Object 53236 * @return {fabric.Triangle} thisArg 53237 */ 53238 fabric.Triangle = fabric.util.createClass(fabric.Object, /** @lends fabric.Triangle.prototype */ { 53239 53240 /** 53241 * Type of an object
53242 * @type String 53243 * @default 53244 */ 53245 type: 'triangle', 53246 53247 /** 53248 * Constructor 53249 * @param {Object} [options] Options object 53250 * @return {Object} thisArg 53251 */ 53252 initialize: function(options) { 53253 options = options || { }; 53254 53255 this.callSuper('initialize', options); 53256 53257 this.set('width', options.width || 100) 53258 .set('height', options.height || 100); 53259 }, 53260 53261 /** 53262 * @private 53263 * @param ctx {CanvasRenderingContext2D} Context to render on 53264 */ 53265 _render: function(ctx) { 53266 var widthBy2 = this.width / 2, 53267 heightBy2 = this.height / 2; 53268 53269 ctx.beginPath(); 53270 ctx.moveTo(-widthBy2, heightBy2); 53271 ctx.lineTo(0, -heightBy2); 53272 ctx.lineTo(widthBy2, heightBy2); 53273 ctx.closePath(); 53274 53275 this._renderFill(ctx); 53276 this._renderStroke(ctx); 53277 }, 53278 53279 /** 53280 * @private 53281 * @param ctx {CanvasRenderingContext2D} Context to render on 53282 */ 53283 _renderDashedStroke: function(ctx) { 53284 var widthBy2 = this.width / 2, 53285 heightBy2 = this.height / 2; 53286 53287 ctx.beginPath(); 53288 fabric.util.drawDashedLine(ctx, -widthBy2, heightBy2, 0, -heightBy2, this.strokeDashArray); 53289 fabric.util.drawDashedLine(ctx, 0, -heightBy2, widthBy2, heightBy2, this.strokeDashArray); 53290 fabric.util.drawDashedLine(ctx, widthBy2, heightBy2, -widthBy2, heightBy2, this.strokeDashArray); 53291 ctx.closePath(); 53292 }, 53293 53294 /* _TO_SVG_START_ */ 53295 /** 53296 * Returns SVG representation of an instance 53297 * @param {Function} [reviver] Method for further parsing of svg representation. 53298 * @return {String} svg representation of an instance 53299 */ 53300 toSVG: function(reviver) { 53301 var markup = this._createBaseSVGMarkup(), 53302 widthBy2 = this.width / 2, 53303 heightBy2 = this.height / 2; 53304 53305 var points = [ 53306 -widthBy2 + " " + heightBy2, 53307 "0 " + -heightBy2, 53308 widthBy2 + " " + heightBy2 53309 ].join(","); 53310 53311 markup.push( 53312 '<polygon ', 53313 'points="', points, 53314 '" style="', this.getSvgStyles(), 53315 '" transform="', this.getSvgTransform(), 53316 '"/>' 53317 ); 53318 53319 return reviver ? reviver(markup.join('')) : markup.join(''); 53320 }, 53321 /* _TO_SVG_END_ */ 53322 53323 /** 53324 * Returns complexity of an instance 53325 * @return {Number} complexity of this instance 53326 */ 53327 complexity: function() { 53328 return 1; 53329 } 53330 }); 53331 53332 /** 53333 * Returns fabric.Triangle instance from an object representation 53334 * @static 53335 * @memberOf fabric.Triangle 53336 * @param object {Object} object to create an instance from 53337 * @return {Object} instance of Canvas.Triangle 53338 */ 53339 fabric.Triangle.fromObject = function(object) { 53340 return new fabric.Triangle(object); 53341 }; 53342 53343})(typeof exports !== 'undefined' ? exports : this); 53344 53345 53346(function(global){ 53347 53348 "use strict"; 53349 53350 var fabric = global.fabric || (global.fabric = { }), 53351 piBy2 = Math.PI * 2, 53352 extend = fabric.util.object.extend; 53353 53354 if (fabric.Ellipse) { 53355 fabric.warn('fabric.Ellipse is already defined.'); 53356 return; 53357 } 53358 53359 /** 53360 * Ellipse class 53361 * @class fabric.Ellipse 53362 * @extends fabric.Object 53363 * @return {fabric.Ellipse} thisArg 53364 */ 53365 fabric.Ellipse = fabric.util.createClass(fabric.Object, /** @lends fabric.Ellipse.prototype */ { 53366 53367 /** 53368 * Type of an object
53369 * @type String 53370 * @default 53371 */ 53372 type: 'ellipse', 53373 53374 /** 53375 * Horizontal radius 53376 * @type Number 53377 * @default 53378 */ 53379 rx: 0, 53380 53381 /** 53382 * Vertical radius 53383 * @type Number 53384 * @default 53385 */ 53386 ry: 0, 53387 53388 /** 53389 * Constructor 53390 * @param {Object} [options] Options object 53391 * @return {fabric.Ellipse} thisArg 53392 */ 53393 initialize: function(options) { 53394 options = options || { }; 53395 53396 this.callSuper('initialize', options); 53397 53398 this.set('rx', options.rx || 0); 53399 this.set('ry', options.ry || 0); 53400 53401 this.set('width', this.get('rx') * 2); 53402 this.set('height', this.get('ry') * 2); 53403 }, 53404 53405 /** 53406 * Returns object representation of an instance 53407 * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output 53408 * @return {Object} object representation of an instance 53409 */ 53410 toObject: function(propertiesToInclude) { 53411 return extend(this.callSuper('toObject', propertiesToInclude), { 53412 rx: this.get('rx'), 53413 ry: this.get('ry') 53414 }); 53415 }, 53416 53417 /* _TO_SVG_START_ */ 53418 /** 53419 * Returns svg representation of an instance 53420 * @param {Function} [reviver] Method for further parsing of svg representation. 53421 * @return {String} svg representation of an instance 53422 */ 53423 toSVG: function(reviver) { 53424 var markup = this._createBaseSVGMarkup(); 53425 53426 markup.push( 53427 '<ellipse ', 53428 'rx="', this.get('rx'), 53429 '" ry="', this.get('ry'), 53430 '" style="', this.getSvgStyles(), 53431 '" transform="', this.getSvgTransform(), 53432 '"/>' 53433 ); 53434 53435 return reviver ? reviver(markup.join('')) : markup.join(''); 53436 }, 53437 /* _TO_SVG_END_ */ 53438 53439 /** 53440 * Renders this instance on a given context 53441 * @param ctx {CanvasRenderingContext2D} context to render on 53442 * @param noTransform {Boolean} context is not transformed when set to true 53443 */ 53444 render: function(ctx, noTransform) { 53445 // do not use `get` for perf. reasons 53446 if (this.rx === 0 || this.ry === 0) return; 53447 return this.callSuper('render', ctx, noTransform); 53448 }, 53449 53450 /** 53451 * @private 53452 * @param ctx {CanvasRenderingContext2D} context to render on 53453 */ 53454 _render: function(ctx, noTransform) { 53455 ctx.beginPath(); 53456 ctx.save(); 53457 ctx.globalAlpha = this.group ? (ctx.globalAlpha * this.opacity) : this.opacity; 53458 if (this.transformMatrix && this.group) { 53459 ctx.translate(this.cx, this.cy); 53460 } 53461 ctx.transform(1, 0, 0, this.ry/this.rx, 0, 0); 53462 ctx.arc(noTransform ? this.left : 0, noTransform ? this.top : 0, this.rx, 0, piBy2, false); 53463 53464 this._renderFill(ctx); 53465 this._renderStroke(ctx); 53466 ctx.restore(); 53467 }, 53468 53469 /** 53470 * Returns complexity of an instance 53471 * @return {Number} complexity 53472 */ 53473 complexity: function() { 53474 return 1; 53475 } 53476 }); 53477 53478 /* _FROM_SVG_START_ */ 53479 /** 53480 * List of attribute names to account for when parsing SVG element (used by {@link fabric.Ellipse.fromElement}) 53481 * @static 53482 * @memberOf fabric.Ellipse 53483 * @see http://www.w3.org/TR/SVG/shapes.html#EllipseElement 53484 */ 53485 fabric.Ellipse.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat('cx cy rx ry'.split(' ')); 53486 53487 /** 53488 * Returns {@link fabric.Ellipse} instance from an SVG element 53489 * @static 53490 * @memberOf fabric.Ellipse 53491 * @param {SVGElement} element Element to parse 53492 * @param {Object} [options] Options object 53493 * @return {fabric.Ellipse} 53494 */ 53495 fabric.Ellipse.fromElement = function(element, options) { 53496 options || (options = { }); 53497 53498 var parsedAttributes = fabric.parseAttributes(element, fabric.Ellipse.ATTRIBUTE_NAMES); 53499 var cx = parsedAttributes.left; 53500 var cy = parsedAttributes.top; 53501 53502 if ('left' in parsedAttributes) { 53503 parsedAttributes.left -= (options.width / 2) || 0; 53504 } 53505 if ('top' in parsedAttributes) { 53506 parsedAttributes.top -= (options.height / 2) || 0; 53507 } 53508 53509 var ellipse = new fabric.Ellipse(extend(parsedAttributes, options)); 53510 53511 ellipse.cx = cx || 0; 53512 ellipse.cy = cy || 0; 53513 53514 return ellipse; 53515 }; 53516 /* _FROM_SVG_END_ */ 53517 53518 /** 53519 * Returns {@link fabric.Ellipse} instance from an object representation 53520 * @static 53521 * @memberOf fabric.Ellipse 53522 * @param {Object} object Object to create an instance from 53523 * @return {fabric.Ellipse} 53524 */ 53525 fabric.Ellipse.fromObject = function(object) { 53526 return new fabric.Ellipse(object); 53527 }; 53528 53529})(typeof exports !== 'undefined' ? exports : this); 53530 53531 53532(function(global) { 53533 53534 "use strict"; 53535 53536 var fabric = global.fabric || (global.fabric = { }), 53537 extend = fabric.util.object.extend; 53538 53539 if (fabric.Rect) { 53540 console.warn('fabric.Rect is already defined'); 53541 return; 53542 } 53543 53544 var stateProperties = fabric.Object.prototype.stateProperties.concat(); 53545 stateProperties.push('rx', 'ry', 'x', 'y'); 53546 53547 /** 53548 * Rectangle class 53549 * @class fabric.Rect 53550 * @extends fabric.Object 53551 * @return {fabric.Rect} thisArg 53552 */ 53553 fabric.Rect = fabric.util.createClass(fabric.Object, /** @lends fabric.Rect.prototype */ { 53554 53555 /** 53556 * List of properties to consider when checking if state of an object is changed ({@link fabric.Object#hasStateChanged}) 53557 * as well as for history (undo/redo) purposes 53558 * @type Array 53559 */ 53560 stateProperties: stateProperties, 53561 53562 /** 53563 * Type of an object
53564 * @type String 53565 * @default 53566 */ 53567 type: 'rect', 53568 53569 /** 53570 * Horizontal border radius 53571 * @type Number 53572 * @default 53573 */ 53574 rx: 0, 53575 53576 /** 53577 * Vertical border radius 53578 * @type Number 53579 * @default 53580 */ 53581 ry: 0, 53582 53583 /** 53584 * @type Number 53585 * @default 53586 */ 53587 x: 0, 53588 53589 /** 53590 * @type Number 53591 * @default 53592 */ 53593 y: 0, 53594 53595 /** 53596 * Used to specify dash pattern for stroke on this object 53597 * @type Array 53598 */ 53599 strokeDashArray: null, 53600 53601 /** 53602 * Constructor 53603 * @param {Object} [options] Options object 53604 * @return {Object} thisArg 53605 */ 53606 initialize: function(options) { 53607 options = options || { }; 53608 53609 this.callSuper('initialize', options); 53610 this._initRxRy(); 53611 53612 this.x = options.x || 0; 53613 this.y = options.y || 0; 53614 }, 53615 53616 /** 53617 * Initializes rx/ry attributes 53618 * @private 53619 */ 53620 _initRxRy: function() { 53621 if (this.rx && !this.ry) { 53622 this.ry = this.rx; 53623 } 53624 else if (this.ry && !this.rx) { 53625 this.rx = this.ry; 53626 } 53627 }, 53628 53629 /** 53630 * @private 53631 * @param ctx {CanvasRenderingContext2D} context to render on 53632 */ 53633 _render: function(ctx) { 53634 var rx = this.rx || 0, 53635 ry = this.ry || 0, 53636 x = -this.width / 2, 53637 y = -this.height / 2, 53638 w = this.width, 53639 h = this.height, 53640 isInPathGroup = this.group && this.group.type !== 'group'; 53641 53642 ctx.beginPath(); 53643 ctx.globalAlpha = isInPathGroup ? (ctx.globalAlpha * this.opacity) : this.opacity; 53644 53645 if (this.transformMatrix && isInPathGroup) { 53646 ctx.translate( 53647 this.width / 2 + this.x, 53648 this.height / 2 + this.y); 53649 } 53650 if (!this.transformMatrix && isInPathGroup) { 53651 ctx.translate( 53652 -this.group.width / 2 + this.width / 2 + this.x, 53653 -this.group.height / 2 + this.height / 2 + this.y); 53654 } 53655 53656 var isRounded = rx !== 0 || ry !== 0; 53657 53658 ctx.moveTo(x+rx, y); 53659 ctx.lineTo(x+w-rx, y); 53660 isRounded && ctx.quadraticCurveTo(x+w, y, x+w, y+ry, x+w, y+ry); 53661 ctx.lineTo(x+w, y+h-ry); 53662 isRounded && ctx.quadraticCurveTo(x+w,y+h,x+w-rx,y+h,x+w-rx,y+h); 53663 ctx.lineTo(x+rx,y+h); 53664 isRounded && ctx.quadraticCurveTo(x,y+h,x,y+h-ry,x,y+h-ry); 53665 ctx.lineTo(x,y+ry); 53666 isRounded && ctx.quadraticCurveTo(x,y,x+rx,y,x+rx,y); 53667 ctx.closePath(); 53668 53669 this._renderFill(ctx); 53670 this._renderStroke(ctx); 53671 }, 53672 53673 /** 53674 * @private 53675 * @param ctx {CanvasRenderingContext2D} context to render on 53676 */ 53677 _renderDashedStroke: function(ctx) { 53678 var x = -this.width/2, 53679 y = -this.height/2, 53680 w = this.width, 53681 h = this.height; 53682 53683 ctx.beginPath(); 53684 fabric.util.drawDashedLine(ctx, x, y, x+w, y, this.strokeDashArray); 53685 fabric.util.drawDashedLine(ctx, x+w, y, x+w, y+h, this.strokeDashArray); 53686 fabric.util.drawDashedLine(ctx, x+w, y+h, x, y+h, this.strokeDashArray); 53687 fabric.util.drawDashedLine(ctx, x, y+h, x, y, this.strokeDashArray); 53688 ctx.closePath(); 53689 }, 53690 53691 /** 53692 * Since coordinate system differs from that of SVG 53693 * @private 53694 */ 53695 _normalizeLeftTopProperties: function(parsedAttributes) { 53696 if ('left' in parsedAttributes) { 53697 this.set('left', parsedAttributes.left + this.getWidth() / 2); 53698 } 53699 this.set('x', parsedAttributes.left || 0); 53700 if ('top' in parsedAttributes) { 53701 this.set('top', parsedAttributes.top + this.getHeight() / 2); 53702 } 53703 this.set('y', parsedAttributes.top || 0); 53704 return this; 53705 }, 53706 53707 /** 53708 * Returns object representation of an instance 53709 * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output 53710 * @return {Object} object representation of an instance 53711 */ 53712 toObject: function(propertiesToInclude) { 53713 var object = extend(this.callSuper('toObject', propertiesToInclude), { 53714 rx: this.get('rx') || 0, 53715 ry: this.get('ry') || 0, 53716 x: this.get('x'), 53717 y: this.get('y') 53718 }); 53719 if (!this.includeDefaultValues) { 53720 this._removeDefaultValues(object); 53721 } 53722 return object; 53723 }, 53724 53725 /* _TO_SVG_START_ */ 53726 /** 53727 * Returns svg representation of an instance 53728 * @param {Function} [reviver] Method for further parsing of svg representation. 53729 * @return {String} svg representation of an instance 53730 */ 53731 toSVG: function(reviver) { 53732 var markup = this._createBaseSVGMarkup(); 53733 53734 markup.push( 53735 '<rect ', 53736 'x="', (-1 * this.width / 2), '" y="', (-1 * this.height / 2), 53737 '" rx="', this.get('rx'), '" ry="', this.get('ry'), 53738 '" width="', this.width, '" height="', this.height,
53739 '" style="', this.getSvgStyles(), 53740 '" transform="', this.getSvgTransform(), 53741 '"/>' 53742 ); 53743 53744 return reviver ? reviver(markup.join('')) : markup.join(''); 53745 }, 53746 /* _TO_SVG_END_ */ 53747 53748 /** 53749 * Returns complexity of an instance 53750 * @return {Number} complexity 53751 */ 53752 complexity: function() { 53753 return 1; 53754 } 53755 }); 53756 53757 /* _FROM_SVG_START_ */ 53758 /** 53759 * List of attribute names to account for when parsing SVG element (used by `fabric.Rect.fromElement`) 53760 * @static 53761 * @memberOf fabric.Rect 53762 * @see: http://www.w3.org/TR/SVG/shapes.html#RectElement 53763 */ 53764 fabric.Rect.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat('x y rx ry width height'.split(' ')); 53765 53766 /** 53767 * @private 53768 */ 53769 function _setDefaultLeftTopValues(attributes) { 53770 attributes.left = attributes.left || 0; 53771 attributes.top = attributes.top || 0; 53772 return attributes; 53773 } 53774 53775 /** 53776 * Returns {@link fabric.Rect} instance from an SVG element 53777 * @static 53778 * @memberOf fabric.Rect 53779 * @param {SVGElement} element Element to parse 53780 * @param {Object} [options] Options object 53781 * @return {fabric.Rect} Instance of fabric.Rect 53782 */ 53783 fabric.Rect.fromElement = function(element, options) { 53784 if (!element) { 53785 return null; 53786 } 53787 53788 var parsedAttributes = fabric.parseAttributes(element, fabric.Rect.ATTRIBUTE_NAMES); 53789 parsedAttributes = _setDefaultLeftTopValues(parsedAttributes); 53790 53791 var rect = new fabric.Rect(extend((options ? fabric.util.object.clone(options) : { }), parsedAttributes)); 53792 rect._normalizeLeftTopProperties(parsedAttributes); 53793 53794 return rect; 53795 }; 53796 /* _FROM_SVG_END_ */ 53797 53798 /** 53799 * Returns {@link fabric.Rect} instance from an object representation 53800 * @static 53801 * @memberOf fabric.Rect 53802 * @param object {Object} object to create an instance from 53803 * @return {Object} instance of fabric.Rect 53804 */ 53805 fabric.Rect.fromObject = function(object) { 53806 return new fabric.Rect(object); 53807 }; 53808 53809})(typeof exports !== 'undefined' ? exports : this); 53810 53811 53812(function(global) { 53813 53814 "use strict"; 53815 53816 var fabric = global.fabric || (global.fabric = { }), 53817 toFixed = fabric.util.toFixed, 53818 min = fabric.util.array.min; 53819 53820 if (fabric.Polyline) { 53821 fabric.warn('fabric.Polyline is already defined'); 53822 return; 53823 } 53824 53825 /** 53826 * Polyline class 53827 * @class fabric.Polyline 53828 * @extends fabric.Object 53829 */ 53830 fabric.Polyline = fabric.util.createClass(fabric.Object, /** @lends fabric.Polyline.prototype */ { 53831 53832 /** 53833 * Type of an object
53834 * @type String 53835 * @default 53836 */ 53837 type: 'polyline', 53838 53839 /** 53840 * Constructor 53841 * @param {Array} points Array of points 53842 * @param {Object} [options] Options object 53843 * @param {Boolean} [skipOffset] Whether points offsetting should be skipped 53844 * @return {fabric.Polyline} thisArg 53845 */ 53846 initialize: function(points, options, skipOffset) { 53847 options = options || { }; 53848 this.set('points', points); 53849 this.callSuper('initialize', options); 53850 this._calcDimensions(skipOffset); 53851 }, 53852 53853 /** 53854 * @private 53855 * @param {Boolean} [skipOffset] Whether points offsetting should be skipped 53856 */ 53857 _calcDimensions: function(skipOffset) { 53858 return fabric.Polygon.prototype._calcDimensions.call(this, skipOffset); 53859 }, 53860 53861 /** 53862 * Returns object representation of an instance 53863 * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output 53864 * @return {Object} Object representation of an instance 53865 */ 53866 toObject: function(propertiesToInclude) { 53867 return fabric.Polygon.prototype.toObject.call(this, propertiesToInclude); 53868 }, 53869 53870 /* _TO_SVG_START_ */ 53871 /** 53872 * Returns SVG representation of an instance 53873 * @param {Function} [reviver] Method for further parsing of svg representation. 53874 * @return {String} svg representation of an instance 53875 */ 53876 toSVG: function(reviver) { 53877 var points = [], 53878 markup = this._createBaseSVGMarkup(); 53879 53880 for (var i = 0, len = this.points.length; i < len; i++) { 53881 points.push(toFixed(this.points[i].x, 2), ',', toFixed(this.points[i].y, 2), ' '); 53882 } 53883 53884 markup.push( 53885 '<polyline ', 53886 'points="', points.join(''), 53887 '" style="', this.getSvgStyles(), 53888 '" transform="', this.getSvgTransform(), 53889 '"/>' 53890 ); 53891 53892 return reviver ? reviver(markup.join('')) : markup.join(''); 53893 }, 53894 /* _TO_SVG_END_ */ 53895 53896 /** 53897 * @private 53898 * @param {CanvasRenderingContext2D} ctx Context to render on 53899 */ 53900 _render: function(ctx) { 53901 var point; 53902 ctx.beginPath(); 53903 ctx.moveTo(this.points[0].x, this.points[0].y); 53904 for (var i = 0, len = this.points.length; i < len; i++) { 53905 point = this.points[i]; 53906 ctx.lineTo(point.x, point.y); 53907 } 53908 53909 this._renderFill(ctx); 53910 this._renderStroke(ctx); 53911 }, 53912 53913 /** 53914 * @private 53915 * @param {CanvasRenderingContext2D} ctx Context to render on 53916 */ 53917 _renderDashedStroke: function(ctx) { 53918 var p1, p2; 53919 53920 ctx.beginPath(); 53921 for (var i = 0, len = this.points.length; i < len; i++) { 53922 p1 = this.points[i]; 53923 p2 = this.points[i+1] || p1; 53924 fabric.util.drawDashedLine(ctx, p1.x, p1.y, p2.x, p2.y, this.strokeDashArray); 53925 } 53926 }, 53927 53928 /** 53929 * Returns complexity of an instance 53930 * @return {Number} complexity of this instance 53931 */ 53932 complexity: function() { 53933 return this.get('points').length; 53934 } 53935 }); 53936 53937 /* _FROM_SVG_START_ */ 53938 /** 53939 * List of attribute names to account for when parsing SVG element (used by {@link fabric.Polyline.fromElement}) 53940 * @static 53941 * @memberOf fabric.Polyline 53942 * @see: http://www.w3.org/TR/SVG/shapes.html#PolylineElement 53943 */ 53944 fabric.Polyline.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat(); 53945 53946 /** 53947 * Returns fabric.Polyline instance from an SVG element 53948 * @static 53949 * @memberOf fabric.Polyline 53950 * @param {SVGElement} element Element to parse 53951 * @param {Object} [options] Options object 53952 * @return {fabric.Polyline} Instance of fabric.Polyline 53953 */ 53954 fabric.Polyline.fromElement = function(element, options) { 53955 if (!element) { 53956 return null; 53957 } 53958 options || (options = { }); 53959 53960 var points = fabric.parsePointsAttribute(element.getAttribute('points')), 53961 parsedAttributes = fabric.parseAttributes(element, fabric.Polyline.ATTRIBUTE_NAMES), 53962 minX = min(points, 'x'), 53963 minY = min(points, 'y'); 53964 53965 minX = minX < 0 ? minX : 0; 53966 minY = minX < 0 ? minY : 0; 53967 53968 for (var i = 0, len = points.length; i < len; i++) { 53969 // normalize coordinates, according to containing box (dimensions of which are passed via `options`) 53970 points[i].x -= (options.width / 2 + minX) || 0; 53971 points[i].y -= (options.height / 2 + minY) || 0; 53972 } 53973 53974 return new fabric.Polyline(points, fabric.util.object.extend(parsedAttributes, options), true); 53975 }; 53976 /* _FROM_SVG_END_ */ 53977 53978 /** 53979 * Returns fabric.Polyline instance from an object representation 53980 * @static 53981 * @memberOf fabric.Polyline 53982 * @param object {Object} object Object to create an instance from 53983 * @return {fabric.Polyline} Instance of fabric.Polyline 53984 */ 53985 fabric.Polyline.fromObject = function(object) { 53986 var points = object.points; 53987 return new fabric.Polyline(points, object, true); 53988 }; 53989 53990})(typeof exports !== 'undefined' ? exports : this); 53991 53992 53993(function(global) { 53994 53995 "use strict"; 53996 53997 var fabric = global.fabric || (global.fabric = { }), 53998 extend = fabric.util.object.extend, 53999 min = fabric.util.array.min, 54000 max = fabric.util.array.max, 54001 toFixed = fabric.util.toFixed; 54002 54003 if (fabric.Polygon) { 54004 fabric.warn('fabric.Polygon is already defined'); 54005 return; 54006 } 54007 54008 /** 54009 * Polygon class 54010 * @class fabric.Polygon 54011 * @extends fabric.Object 54012 */ 54013 fabric.Polygon = fabric.util.createClass(fabric.Object, /** @lends fabric.Polygon.prototype */ { 54014 54015 /** 54016 * Type of an object
54017 * @type String 54018 * @default 54019 */ 54020 type: 'polygon', 54021 54022 /** 54023 * Constructor 54024 * @param {Array} points Array of points 54025 * @param {Object} [options] Options object 54026 * @param {Boolean} [skipOffset] Whether points offsetting should be skipped 54027 * @return {fabric.Polygon} thisArg 54028 */ 54029 initialize: function(points, options, skipOffset) { 54030 options = options || { }; 54031 this.points = points; 54032 this.callSuper('initialize', options); 54033 this._calcDimensions(skipOffset); 54034 }, 54035 54036 /** 54037 * @private 54038 * @param {Boolean} [skipOffset] Whether points offsetting should be skipped 54039 */ 54040 _calcDimensions: function(skipOffset) { 54041 54042 var points = this.points, 54043 minX = min(points, 'x'), 54044 minY = min(points, 'y'), 54045 maxX = max(points, 'x'), 54046 maxY = max(points, 'y'); 54047 54048 this.width = (maxX - minX) || 1; 54049 this.height = (maxY - minY) || 1; 54050 54051 this.minX = minX; 54052 this.minY = minY; 54053 54054 if (skipOffset) return; 54055 54056 var halfWidth = this.width / 2 + this.minX, 54057 halfHeight = this.height / 2 + this.minY; 54058 54059 // change points to offset polygon into a bounding box 54060 this.points.forEach(function(p) { 54061 p.x -= halfWidth; 54062 p.y -= halfHeight; 54063 }, this); 54064 }, 54065 54066 /** 54067 * Returns object representation of an instance 54068 * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output 54069 * @return {Object} Object representation of an instance 54070 */ 54071 toObject: function(propertiesToInclude) { 54072 return extend(this.callSuper('toObject', propertiesToInclude), { 54073 points: this.points.concat() 54074 }); 54075 }, 54076 54077 /* _TO_SVG_START_ */ 54078 /** 54079 * Returns svg representation of an instance 54080 * @param {Function} [reviver] Method for further parsing of svg representation. 54081 * @return {String} svg representation of an instance 54082 */ 54083 toSVG: function(reviver) { 54084 var points = [], 54085 markup = this._createBaseSVGMarkup(); 54086 54087 for (var i = 0, len = this.points.length; i < len; i++) { 54088 points.push(toFixed(this.points[i].x, 2), ',', toFixed(this.points[i].y, 2), ' '); 54089 } 54090 54091 markup.push( 54092 '<polygon ', 54093 'points="', points.join(''), 54094 '" style="', this.getSvgStyles(), 54095 '" transform="', this.getSvgTransform(), 54096 '"/>' 54097 ); 54098 54099 return reviver ? reviver(markup.join('')) : markup.join(''); 54100 }, 54101 /* _TO_SVG_END_ */ 54102 54103 /** 54104 * @private 54105 * @param {CanvasRenderingContext2D} ctx Context to render on 54106 */ 54107 _render: function(ctx) { 54108 var point; 54109 ctx.beginPath(); 54110 ctx.moveTo(this.points[0].x, this.points[0].y); 54111 for (var i = 0, len = this.points.length; i < len; i++) { 54112 point = this.points[i]; 54113 ctx.lineTo(point.x, point.y); 54114 } 54115 this._renderFill(ctx); 54116 if (this.stroke || this.strokeDashArray) { 54117 ctx.closePath(); 54118 this._renderStroke(ctx); 54119 } 54120 }, 54121 54122 /** 54123 * @private 54124 * @param {CanvasRenderingContext2D} ctx Context to render on 54125 */ 54126 _renderDashedStroke: function(ctx) { 54127 var p1, p2; 54128 54129 ctx.beginPath(); 54130 for (var i = 0, len = this.points.length; i < len; i++) { 54131 p1 = this.points[i]; 54132 p2 = this.points[i+1] || this.points[0]; 54133 fabric.util.drawDashedLine(ctx, p1.x, p1.y, p2.x, p2.y, this.strokeDashArray); 54134 } 54135 ctx.closePath(); 54136 }, 54137 54138 /** 54139 * Returns complexity of an instance 54140 * @return {Number} complexity of this instance 54141 */ 54142 complexity: function() { 54143 return this.points.length; 54144 } 54145 }); 54146 54147 /* _FROM_SVG_START_ */ 54148 /** 54149 * List of attribute names to account for when parsing SVG element (used by `fabric.Polygon.fromElement`) 54150 * @static 54151 * @memberOf fabric.Polygon 54152 * @see: http://www.w3.org/TR/SVG/shapes.html#PolygonElement 54153 */ 54154 fabric.Polygon.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat(); 54155 54156 /** 54157 * Returns {@link fabric.Polygon} instance from an SVG element 54158 * @static 54159 * @memberOf fabric.Polygon 54160 * @param {SVGElement} element Element to parse 54161 * @param {Object} [options] Options object 54162 * @return {fabric.Polygon} Instance of fabric.Polygon 54163 */ 54164 fabric.Polygon.fromElement = function(element, options) { 54165 if (!element) { 54166 return null; 54167 }
54168 options || (options = { }); 54169 54170 var points = fabric.parsePointsAttribute(element.getAttribute('points')), 54171 parsedAttributes = fabric.parseAttributes(element, fabric.Polygon.ATTRIBUTE_NAMES), 54172 minX = min(points, 'x'), 54173 minY = min(points, 'y'); 54174 54175 minX = minX < 0 ? minX : 0; 54176 minY = minX < 0 ? minY : 0; 54177 54178 for (var i = 0, len = points.length; i < len; i++) { 54179 // normalize coordinates, according to containing box (dimensions of which are passed via `options`) 54180 points[i].x -= (options.width / 2 + minX) || 0; 54181 points[i].y -= (options.height / 2 + minY) || 0; 54182 } 54183 54184 return new fabric.Polygon(points, extend(parsedAttributes, options), true); 54185 }; 54186 /* _FROM_SVG_END_ */ 54187 54188 /** 54189 * Returns fabric.Polygon instance from an object representation 54190 * @static 54191 * @memberOf fabric.Polygon 54192 * @param object {Object} object Object to create an instance from 54193 * @return {fabric.Polygon} Instance of fabric.Polygon 54194 */ 54195 fabric.Polygon.fromObject = function(object) { 54196 return new fabric.Polygon(object.points, object, true); 54197 }; 54198 54199})(typeof exports !== 'undefined' ? exports : this); 54200 54201 54202(function(global) { 54203 54204 var commandLengths = { 54205 m: 2, 54206 l: 2, 54207 h: 1, 54208 v: 1, 54209 c: 6, 54210 s: 4, 54211 q: 4, 54212 t: 2, 54213 a: 7 54214 }; 54215 54216 "use strict"; 54217 54218 var fabric = global.fabric || (global.fabric = { }), 54219 min = fabric.util.array.min, 54220 max = fabric.util.array.max, 54221 extend = fabric.util.object.extend, 54222 _toString = Object.prototype.toString, 54223 drawArc = fabric.util.drawArc; 54224 54225 if (fabric.Path) { 54226 fabric.warn('fabric.Path is already defined'); 54227 return; 54228 } 54229 54230 /** 54231 * @private 54232 */ 54233 function getX(item) { 54234 if (item[0] === 'H') { 54235 return item[1]; 54236 } 54237 return item[item.length - 2]; 54238 } 54239 54240 /** 54241 * @private 54242 */ 54243 function getY(item) { 54244 if (item[0] === 'V') { 54245 return item[1]; 54246 } 54247 return item[item.length - 1]; 54248 } 54249 54250 /** 54251 * Path class 54252 * @class fabric.Path 54253 * @extends fabric.Object 54254 * @tutorial {@link http://fabricjs.com/fabric-intro-part-1/#path_and_pathgroup} 54255 */ 54256 fabric.Path = fabric.util.createClass(fabric.Object, /** @lends fabric.Path.prototype */ { 54257 54258 /** 54259 * Type of an object
54260 * @type String 54261 * @default 54262 */ 54263 type: 'path', 54264 54265 /** 54266 * Constructor 54267 * @param {Array|String} path Path data (sequence of coordinates and corresponding "command" tokens) 54268 * @param {Object} [options] Options object 54269 * @return {fabric.Path} thisArg 54270 */ 54271 initialize: function(path, options) { 54272 options = options || { }; 54273 54274 this.setOptions(options); 54275 54276 if (!path) { 54277 throw new Error('`path` argument is required'); 54278 } 54279 54280 var fromArray = _toString.call(path) === '[object Array]'; 54281 54282 this.path = fromArray 54283 ? path 54284 // one of commands (m,M,l,L,q,Q,c,C,etc.) followed by non-command characters (i.e. command values) 54285 : path.match && path.match(/[mzlhvcsqta][^mzlhvcsqta]*/gi); 54286 54287 if (!this.path) return; 54288 54289 if (!fromArray) { 54290 this.path = this._parsePath(); 54291 } 54292 this._initializePath(options); 54293 54294 if (options.sourcePath) { 54295 this.setSourcePath(options.sourcePath); 54296 } 54297 }, 54298 54299 /** 54300 * @private 54301 * @param {Object} [options] Options object 54302 */ 54303 _initializePath: function (options) { 54304 var isWidthSet = 'width' in options && options.width != null, 54305 isHeightSet = 'height' in options && options.width != null, 54306 isLeftSet = 'left' in options, 54307 isTopSet = 'top' in options, 54308 origLeft = isLeftSet ? this.left : 0, 54309 origTop = isTopSet ? this.top : 0; 54310 54311 if (!isWidthSet || !isHeightSet) { 54312 extend(this, this._parseDimensions()); 54313 if (isWidthSet) { 54314 this.width = options.width; 54315 } 54316 if (isHeightSet) { 54317 this.height = options.height; 54318 } 54319 } 54320 else { //Set center location relative to given height/width if not specified 54321 if (!isTopSet) { 54322 this.top = this.height / 2; 54323 } 54324 if (!isLeftSet) { 54325 this.left = this.width / 2; 54326 } 54327 } 54328 this.pathOffset = this.pathOffset || this._calculatePathOffset(origLeft, origTop); //Save top-left coords as offset 54329 }, 54330 54331 /** 54332 * @private 54333 * @param {Boolean} positionSet When false, path offset is returned otherwise 0 54334 */ 54335 _calculatePathOffset: function (origLeft, origTop) { 54336 return { 54337 x: this.left - origLeft - (this.width / 2), 54338 y: this.top - origTop - (this.height / 2) 54339 }; 54340 }, 54341 54342 /** 54343 * @private 54344 * @param {CanvasRenderingContext2D} ctx context to render path on 54345 */ 54346 _render: function(ctx) { 54347 var current, // current instruction 54348 previous = null, 54349 x = 0, // current x 54350 y = 0, // current y 54351 controlX = 0, // current control point x 54352 controlY = 0, // current control point y 54353 tempX, 54354 tempY, 54355 tempControlX, 54356 tempControlY, 54357 l = -((this.width / 2) + this.pathOffset.x), 54358 t = -((this.height / 2) + this.pathOffset.y); 54359 54360 for (var i = 0, len = this.path.length; i < len; ++i) { 54361 54362 current = this.path[i]; 54363 54364 switch (current[0]) { // first letter 54365 54366 case 'l': // lineto, relative 54367 x += current[1]; 54368 y += current[2]; 54369 ctx.lineTo(x + l, y + t); 54370 break; 54371 54372 case 'L': // lineto, absolute 54373 x = current[1]; 54374 y = current[2]; 54375 ctx.lineTo(x + l, y + t); 54376 break; 54377 54378 case 'h': // horizontal lineto, relative 54379 x += current[1]; 54380 ctx.lineTo(x + l, y + t); 54381 break; 54382 54383 case 'H': // horizontal lineto, absolute 54384 x = current[1]; 54385 ctx.lineTo(x + l, y + t); 54386 break; 54387 54388 case 'v': // vertical lineto, relative 54389 y += current[1]; 54390 ctx.lineTo(x + l, y + t); 54391 break; 54392 54393 case 'V': // verical lineto, absolute 54394 y = current[1]; 54395 ctx.lineTo(x + l, y + t); 54396 break; 54397 54398 case 'm': // moveTo, relative 54399 x += current[1]; 54400 y += current[2]; 54401 // draw a line if previous command was moveTo as well (otherwise, it will have no effect) 54402 ctx[(previous && (previous[0] === 'm' || previous[0] === 'M')) ? 'lineTo' : 'moveTo'](x + l, y + t); 54403 break; 54404 54405 case 'M': // moveTo, absolute 54406 x = current[1]; 54407 y = current[2]; 54408 // draw a line if previous command was moveTo as well (otherwise, it will have no effect) 54409 ctx[(previous && (previous[0] === 'm' || previous[0] === 'M')) ? 'lineTo' : 'moveTo'](x + l, y + t); 54410 break; 54411 54412 case 'c': // bezierCurveTo, relative 54413 tempX = x + current[5]; 54414 tempY = y + current[6]; 54415 controlX = x + current[3]; 54416 controlY = y + current[4]; 54417 ctx.bezierCurveTo( 54418 x + current[1] + l, // x1 54419 y + current[2] + t, // y1 54420 controlX + l, // x2 54421 controlY + t, // y2 54422 tempX + l, 54423 tempY + t 54424 ); 54425 x = tempX; 54426 y = tempY; 54427 break; 54428 54429 case 'C': // bezierCurveTo, absolute 54430 x = current[5]; 54431 y = current[6]; 54432 controlX = current[3]; 54433 controlY = current[4]; 54434 ctx.bezierCurveTo( 54435 current[1] + l, 54436 current[2] + t, 54437 controlX + l, 54438 controlY + t, 54439 x + l, 54440 y + t 54441 ); 54442 break; 54443 54444 case 's': // shorthand cubic bezierCurveTo, relative 54445 54446 // transform to absolute x,y 54447 tempX = x + current[3]; 54448 tempY = y + current[4]; 54449 54450 // calculate reflection of previous control points 54451 controlX = controlX ? (2 * x - controlX) : x; 54452 controlY = controlY ? (2 * y - controlY) : y; 54453 54454 ctx.bezierCurveTo( 54455 controlX + l, 54456 controlY + t, 54457 x + current[1] + l, 54458 y + current[2] + t, 54459 tempX + l, 54460 tempY + t 54461 ); 54462 // set control point to 2nd one of this command 54463 // "... the first control point is assumed to be the reflection of the second control point on the previous command relative to the current point." 54464 controlX = x + current[1]; 54465 controlY = y + current[2]; 54466 54467 x = tempX; 54468 y = tempY; 54469 break; 54470 54471 case 'S': // shorthand cubic bezierCurveTo, absolute 54472 tempX = current[3]; 54473 tempY = current[4]; 54474 // calculate reflection of previous control points 54475 controlX = 2*x - controlX; 54476 controlY = 2*y - controlY; 54477 ctx.bezierCurveTo( 54478 controlX + l, 54479 controlY + t, 54480 current[1] + l, 54481 current[2] + t, 54482 tempX + l, 54483 tempY + t 54484 ); 54485 x = tempX; 54486 y = tempY; 54487 54488 // set control point to 2nd one of this command 54489 // "... the first control point is assumed to be the reflection of the second control point on the previous command relative to the current point." 54490 controlX = current[1]; 54491 controlY = current[2]; 54492 54493 break; 54494 54495 case 'q': // quadraticCurveTo, relative 54496 // transform to absolute x,y 54497 tempX = x + current[3]; 54498 tempY = y + current[4]; 54499 54500 controlX = x + current[1]; 54501 controlY = y + current[2]; 54502 54503 ctx.quadraticCurveTo( 54504 controlX + l, 54505 controlY + t, 54506 tempX + l, 54507 tempY + t 54508 ); 54509 x = tempX; 54510 y = tempY; 54511 break; 54512 54513 case 'Q': // quadraticCurveTo, absolute 54514 tempX = current[3]; 54515 tempY = current[4]; 54516 54517 ctx.quadraticCurveTo( 54518 current[1] + l, 54519 current[2] + t, 54520 tempX + l, 54521 tempY + t 54522 ); 54523 x = tempX; 54524 y = tempY; 54525 controlX = current[1]; 54526 controlY = current[2]; 54527 break; 54528 54529 case 't': // shorthand quadraticCurveTo, relative 54530 54531 // transform to absolute x,y 54532 tempX = x + current[1]; 54533 tempY = y + current[2]; 54534 54535 54536 if (previous[0].match(/[QqTt]/) === null) { 54537 // If there is no previous command or if the previous command was not a Q, q, T or t, 54538 // assume the control point is coincident with the current point 54539 controlX = x; 54540 controlY = y; 54541 } 54542 else if (previous[0] === 't') { 54543 // calculate reflection of previous control points for t 54544 controlX = 2 * x - tempControlX; 54545 controlY = 2 * y - tempControlY; 54546 } 54547 else if (previous[0] === 'q') { 54548 // calculate reflection of previous control points for q 54549 controlX = 2 * x - controlX; 54550 controlY = 2 * y - controlY; 54551 } 54552 54553 tempControlX = controlX; 54554 tempControlY = controlY; 54555 54556 ctx.quadraticCurveTo( 54557 controlX + l, 54558 controlY + t, 54559 tempX + l, 54560 tempY + t 54561 ); 54562 x = tempX; 54563 y = tempY; 54564 controlX = x + current[1]; 54565 controlY = y + current[2]; 54566 break; 54567 54568 case 'T': 54569 tempX = current[1]; 54570 tempY = current[2]; 54571 54572 // calculate reflection of previous control points 54573 controlX = 2 * x - controlX; 54574 controlY = 2 * y - controlY; 54575 ctx.quadraticCurveTo( 54576 controlX + l, 54577 controlY + t, 54578 tempX + l, 54579 tempY + t 54580 ); 54581 x = tempX; 54582 y = tempY; 54583 break; 54584 54585 case 'a': 54586 // TODO: optimize this 54587 drawArc(ctx, x + l, y + t, [ 54588 current[1], 54589 current[2], 54590 current[3], 54591 current[4], 54592 current[5], 54593 current[6] + x + l, 54594 current[7] + y + t 54595 ]); 54596 x += current[6]; 54597 y += current[7]; 54598 break; 54599 54600 case 'A': 54601 // TODO: optimize this 54602 drawArc(ctx, x + l, y + t, [ 54603 current[1], 54604 current[2], 54605 current[3], 54606 current[4], 54607 current[5], 54608 current[6] + l, 54609 current[7] + t 54610 ]); 54611 x = current[6]; 54612 y = current[7]; 54613 break; 54614 54615 case 'z': 54616 case 'Z': 54617 ctx.closePath(); 54618 break; 54619 } 54620 previous = current; 54621 } 54622 }, 54623 54624 /**
54625 * Renders path on a specified context 54626 * @param {CanvasRenderingContext2D} ctx context to render path on 54627 * @param {Boolean} [noTransform] When true, context is not transformed 54628 */ 54629 render: function(ctx, noTransform) { 54630 // do not render if object is not visible 54631 if (!this.visible) return; 54632 54633 ctx.save(); 54634 var m = this.transformMatrix; 54635 if (m) { 54636 ctx.transform(m[0], m[1], m[2], m[3], m[4], m[5]); 54637 } 54638 if (!noTransform) { 54639 this.transform(ctx); 54640 } 54641 // ctx.globalCompositeOperation = this.fillRule; 54642 54643 if (this.fill) { 54644 ctx.fillStyle = this.fill.toLive 54645 ? this.fill.toLive(ctx) 54646 : this.fill; 54647 } 54648 54649 if (this.stroke) { 54650 ctx.lineWidth = this.strokeWidth; 54651 ctx.lineCap = this.strokeLineCap; 54652 ctx.lineJoin = this.strokeLineJoin; 54653 ctx.miterLimit = this.strokeMiterLimit; 54654 ctx.strokeStyle = this.stroke.toLive 54655 ? this.stroke.toLive(ctx) 54656 : this.stroke; 54657 } 54658 54659 this._setShadow(ctx); 54660 this.clipTo && fabric.util.clipContext(this, ctx); 54661 ctx.beginPath(); 54662 54663 this._render(ctx); 54664 this._renderFill(ctx); 54665 this._renderStroke(ctx); 54666 this.clipTo && ctx.restore(); 54667 this._removeShadow(ctx); 54668 54669 if (!noTransform && this.active) { 54670 this.drawBorders(ctx); 54671 this.drawControls(ctx); 54672 } 54673 ctx.restore(); 54674 }, 54675 54676 /** 54677 * Returns string representation of an instance 54678 * @return {String} string representation of an instance 54679 */ 54680 toString: function() { 54681 return '#<fabric.Path (' + this.complexity() + 54682 '): { "top": ' + this.top + ', "left": ' + this.left + ' }>'; 54683 }, 54684 54685 /** 54686 * Returns object representation of an instance 54687 * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output 54688 * @return {Object} object representation of an instance 54689 */ 54690 toObject: function(propertiesToInclude) { 54691 var o = extend(this.callSuper('toObject', propertiesToInclude), { 54692 path: this.path, 54693 pathOffset: this.pathOffset 54694 }); 54695 if (this.sourcePath) { 54696 o.sourcePath = this.sourcePath; 54697 } 54698 if (this.transformMatrix) { 54699 o.transformMatrix = this.transformMatrix; 54700 } 54701 return o; 54702 }, 54703 54704 /** 54705 * Returns dataless object representation of an instance 54706 * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output 54707 * @return {Object} object representation of an instance 54708 */ 54709 toDatalessObject: function(propertiesToInclude) { 54710 var o = this.toObject(propertiesToInclude); 54711 if (this.sourcePath) { 54712 o.path = this.sourcePath; 54713 } 54714 delete o.sourcePath; 54715 return o; 54716 }, 54717 54718 /* _TO_SVG_START_ */ 54719 /** 54720 * Returns svg representation of an instance 54721 * @param {Function} [reviver] Method for further parsing of svg representation. 54722 * @return {String} svg representation of an instance 54723 */ 54724 toSVG: function(reviver) { 54725 var chunks = [], 54726 markup = this._createBaseSVGMarkup(); 54727 54728 for (var i = 0, len = this.path.length; i < len; i++) { 54729 chunks.push(this.path[i].join(' ')); 54730 } 54731 var path = chunks.join(' '); 54732 54733 markup.push( 54734 '<g transform="', (this.group ? '' : this.getSvgTransform()), '">', 54735 '<path ', 54736 'd="', path, 54737 '" style="', this.getSvgStyles(), 54738 '" transform="translate(', (-this.width / 2), ' ', (-this.height/2), ')', 54739 '" stroke-linecap="round" ', 54740 '/>', 54741 '</g>' 54742 ); 54743 54744 return reviver ? reviver(markup.join('')) : markup.join(''); 54745 }, 54746 /* _TO_SVG_END_ */ 54747 54748 /** 54749 * Returns number representation of an instance complexity 54750 * @return {Number} complexity of this instance 54751 */ 54752 complexity: function() { 54753 return this.path.length; 54754 }, 54755 54756 /** 54757 * @private 54758 */ 54759 _parsePath: function() { 54760 var result = [ ], 54761 coords = [ ], 54762 currentPath, 54763 parsed, 54764 re = /(-?\.\d+)|(-?\d+(\.\d+)?)/g, 54765 match, 54766 coordsStr; 54767 54768 for (var i = 0, coordsParsed, len = this.path.length; i < len; i++) { 54769 currentPath = this.path[i]; 54770 54771 coordsStr = currentPath.slice(1).trim(); 54772 coords.length = 0; 54773 54774 while ((match = re.exec(coordsStr))) { 54775 coords.push(match[0]); 54776 } 54777 54778 coordsParsed = [ currentPath.charAt(0) ]; 54779 54780 for (var j = 0, jlen = coords.length; j < jlen; j++) { 54781 parsed = parseFloat(coords[j]); 54782 if (!isNaN(parsed)) { 54783 coordsParsed.push(parsed); 54784 } 54785 } 54786
54787 var command = coordsParsed[0].toLowerCase(), 54788 commandLength = commandLengths[command]; 54789 54790 if (coordsParsed.length - 1 > commandLength) { 54791 for (var k = 1, klen = coordsParsed.length; k < klen; k += commandLength) { 54792 result.push([ coordsParsed[0] ].concat(coordsParsed.slice(k, k + commandLength))); 54793 } 54794 } 54795 else { 54796 result.push(coordsParsed); 54797 } 54798 } 54799 54800 return result; 54801 }, 54802 54803 /** 54804 * @private 54805 */ 54806 _parseDimensions: function() { 54807 var aX = [], 54808 aY = [], 54809 previousX, 54810 previousY, 54811 isLowerCase = false, 54812 x, 54813 y; 54814 54815 this.path.forEach(function(item, i) { 54816 if (item[0] !== 'H') { 54817 previousX = (i === 0) ? getX(item) : getX(this.path[i-1]); 54818 } 54819 if (item[0] !== 'V') { 54820 previousY = (i === 0) ? getY(item) : getY(this.path[i-1]); 54821 } 54822 54823 // lowercased letter denotes relative position; 54824 // transform to absolute 54825 if (item[0] === item[0].toLowerCase()) { 54826 isLowerCase = true; 54827 } 54828 54829 // last 2 items in an array of coordinates are the actualy x/y (except H/V); 54830 // collect them 54831 54832 // TODO (kangax): support relative h/v commands 54833 54834 x = isLowerCase 54835 ? previousX + getX(item) 54836 : item[0] === 'V' 54837 ? previousX 54838 : getX(item); 54839 54840 y = isLowerCase 54841 ? previousY + getY(item) 54842 : item[0] === 'H' 54843 ? previousY 54844 : getY(item); 54845 54846 var val = parseInt(x, 10); 54847 if (!isNaN(val)) aX.push(val); 54848 54849 val = parseInt(y, 10); 54850 if (!isNaN(val)) aY.push(val); 54851 54852 }, this); 54853 54854 var minX = min(aX), 54855 minY = min(aY), 54856 maxX = max(aX), 54857 maxY = max(aY), 54858 deltaX = maxX - minX, 54859 deltaY = maxY - minY; 54860 54861 var o = { 54862 left: this.left + (minX + deltaX / 2), 54863 top: this.top + (minY + deltaY / 2), 54864 width: deltaX, 54865 height: deltaY 54866 }; 54867 54868 return o; 54869 } 54870 }); 54871 54872 /** 54873 * Creates an instance of fabric.Path from an object 54874 * @static 54875 * @memberOf fabric.Path 54876 * @param {Object} object 54877 * @param {Function} callback Callback to invoke when an fabric.Path instance is created 54878 */ 54879 fabric.Path.fromObject = function(object, callback) { 54880 if (typeof object.path === 'string') { 54881 fabric.loadSVGFromURL(object.path, function (elements) { 54882 var path = elements[0]; 54883 54884 var pathUrl = object.path; 54885 delete object.path; 54886 54887 fabric.util.object.extend(path, object); 54888 path.setSourcePath(pathUrl); 54889 54890 callback(path); 54891 }); 54892 } 54893 else { 54894 callback(new fabric.Path(object.path, object)); 54895 } 54896 }; 54897 54898 /* _FROM_SVG_START_ */ 54899 /** 54900 * List of attribute names to account for when parsing SVG element (used by `fabric.Path.fromElement`) 54901 * @static 54902 * @memberOf fabric.Path 54903 * @see http://www.w3.org/TR/SVG/paths.html#PathElement 54904 */ 54905 fabric.Path.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat(['d']); 54906 54907 /** 54908 * Creates an instance of fabric.Path from an SVG <path> element 54909 * @static 54910 * @memberOf fabric.Path 54911 * @param {SVGElement} element to parse 54912 * @param {Function} callback Callback to invoke when an fabric.Path instance is created 54913 * @param {Object} [options] Options object 54914 */ 54915 fabric.Path.fromElement = function(element, callback, options) { 54916 var parsedAttributes = fabric.parseAttributes(element, fabric.Path.ATTRIBUTE_NAMES); 54917 callback && callback(new fabric.Path(parsedAttributes.d, extend(parsedAttributes, options))); 54918 }; 54919 /* _FROM_SVG_END_ */ 54920 54921 /** 54922 * Indicates that instances of this type are async 54923 * @static 54924 * @memberOf fabric.Path 54925 * @type Boolean 54926 * @default 54927 */ 54928 fabric.Path.async = true; 54929 54930})(typeof exports !== 'undefined' ? exports : this); 54931 54932 54933(function(global) { 54934 54935 "use strict"; 54936 54937 var fabric = global.fabric || (global.fabric = { }), 54938 extend = fabric.util.object.extend, 54939 invoke = fabric.util.array.invoke, 54940 parentToObject = fabric.Object.prototype.toObject; 54941 54942 if (fabric.PathGroup) { 54943 fabric.warn('fabric.PathGroup is already defined'); 54944 return; 54945 } 54946 54947 /** 54948 * Path group class 54949 * @class fabric.PathGroup 54950 * @extends fabric.Path 54951 * @tutorial {@link http://fabricjs.com/fabric-intro-part-1/#path_and_pathgroup} 54952 */ 54953 fabric.PathGroup = fabric.util.createClass(fabric.Path, /** @lends fabric.PathGroup.prototype */ { 54954 54955 /** 54956 * Type of an object
54957 * @type String 54958 * @default 54959 */ 54960 type: 'path-group', 54961 54962 /** 54963 * Fill value 54964 * @type String 54965 * @default 54966 */ 54967 fill: '', 54968 54969 /** 54970 * Constructor 54971 * @param {Array} paths 54972 * @param {Object} [options] Options object 54973 * @return {fabric.PathGroup} thisArg 54974 */ 54975 initialize: function(paths, options) { 54976 54977 options = options || { }; 54978 this.paths = paths || [ ]; 54979 54980 for (var i = this.paths.length; i--; ) { 54981 this.paths[i].group = this; 54982 } 54983 54984 this.setOptions(options); 54985 this.setCoords(); 54986 54987 if (options.sourcePath) { 54988 this.setSourcePath(options.sourcePath); 54989 } 54990 }, 54991 54992 /** 54993 * Renders this group on a specified context 54994 * @param {CanvasRenderingContext2D} ctx Context to render this instance on 54995 */ 54996 render: function(ctx) { 54997 // do not render if object is not visible 54998 if (!this.visible) return; 54999 55000 ctx.save(); 55001 55002 var m = this.transformMatrix; 55003 if (m) { 55004 ctx.transform(m[0], m[1], m[2], m[3], m[4], m[5]); 55005 } 55006 55007 this.transform(ctx); 55008 55009 this._setShadow(ctx); 55010 this.clipTo && fabric.util.clipContext(this, ctx); 55011 for (var i = 0, l = this.paths.length; i < l; ++i) { 55012 this.paths[i].render(ctx, true); 55013 } 55014 this.clipTo && ctx.restore(); 55015 this._removeShadow(ctx); 55016 55017 if (this.active) { 55018 this.drawBorders(ctx); 55019 this.drawControls(ctx); 55020 } 55021 ctx.restore(); 55022 }, 55023 55024 /** 55025 * Sets certain property to a certain value 55026 * @param {String} prop 55027 * @param {Any} value 55028 * @return {fabric.PathGroup} thisArg 55029 */ 55030 _set: function(prop, value) { 55031 55032 if (prop === 'fill' && value && this.isSameColor()) { 55033 var i = this.paths.length; 55034 while (i--) { 55035 this.paths[i]._set(prop, value); 55036 } 55037 } 55038 55039 return this.callSuper('_set', prop, value); 55040 }, 55041 55042 /** 55043 * Returns object representation of this path group 55044 * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output 55045 * @return {Object} object representation of an instance 55046 */ 55047 toObject: function(propertiesToInclude) { 55048 var o = extend(parentToObject.call(this, propertiesToInclude), { 55049 paths: invoke(this.getObjects(), 'toObject', propertiesToInclude) 55050 }); 55051 if (this.sourcePath) { 55052 o.sourcePath = this.sourcePath; 55053 } 55054 return o; 55055 }, 55056 55057 /** 55058 * Returns dataless object representation of this path group 55059 * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output 55060 * @return {Object} dataless object representation of an instance 55061 */ 55062 toDatalessObject: function(propertiesToInclude) { 55063 var o = this.toObject(propertiesToInclude); 55064 if (this.sourcePath) { 55065 o.paths = this.sourcePath; 55066 } 55067 return o; 55068 }, 55069 55070 /* _TO_SVG_START_ */ 55071 /** 55072 * Returns svg representation of an instance 55073 * @param {Function} [reviver] Method for further parsing of svg representation. 55074 * @return {String} svg representation of an instance 55075 */ 55076 toSVG: function(reviver) { 55077 var objects = this.getObjects(); 55078 var markup = [ 55079 '<g ', 55080 'style="', this.getSvgStyles(), '" ', 55081 'transform="', this.getSvgTransform(), '" ', 55082 '>' 55083 ]; 55084 55085 for (var i = 0, len = objects.length; i < len; i++) { 55086 markup.push(objects[i].toSVG(reviver)); 55087 } 55088 markup.push('</g>'); 55089 55090 return reviver ? reviver(markup.join('')) : markup.join(''); 55091 }, 55092 /* _TO_SVG_END_ */ 55093 55094 /** 55095 * Returns a string representation of this path group 55096 * @return {String} string representation of an object 55097 */ 55098 toString: function() { 55099 return '#<fabric.PathGroup (' + this.complexity() + 55100 '): { top: ' + this.top + ', left: ' + this.left + ' }>'; 55101 }, 55102 55103 /** 55104 * Returns true if all paths in this group are of same color 55105 * @return {Boolean} true if all paths are of the same color (`fill`) 55106 */ 55107 isSameColor: function() { 55108 var firstPathFill = this.getObjects()[0].get('fill'); 55109 return this.getObjects().every(function(path) { 55110 return path.get('fill') === firstPathFill; 55111 }); 55112 }, 55113 55114 /** 55115 * Returns number representation of object's complexity 55116 * @return {Number} complexity 55117 */ 55118 complexity: function() { 55119 return this.paths.reduce(function(total, path) {
55120 return total + ((path && path.complexity) ? path.complexity() : 0); 55121 }, 0); 55122 }, 55123 55124 /** 55125 * Returns all paths in this path group 55126 * @return {Array} array of path objects included in this path group 55127 */ 55128 getObjects: function() { 55129 return this.paths; 55130 } 55131 }); 55132 55133 /** 55134 * Creates fabric.PathGroup instance from an object representation 55135 * @static 55136 * @memberOf fabric.PathGroup 55137 * @param {Object} object Object to create an instance from 55138 * @param {Function} callback Callback to invoke when an fabric.PathGroup instance is created 55139 */ 55140 fabric.PathGroup.fromObject = function(object, callback) { 55141 if (typeof object.paths === 'string') { 55142 fabric.loadSVGFromURL(object.paths, function (elements) { 55143 55144 var pathUrl = object.paths; 55145 delete object.paths; 55146 55147 var pathGroup = fabric.util.groupSVGElements(elements, object, pathUrl); 55148 55149 callback(pathGroup); 55150 }); 55151 } 55152 else { 55153 fabric.util.enlivenObjects(object.paths, function(enlivenedObjects) { 55154 delete object.paths; 55155 callback(new fabric.PathGroup(enlivenedObjects, object)); 55156 }); 55157 } 55158 }; 55159 55160 /** 55161 * Indicates that instances of this type are async 55162 * @static 55163 * @memberOf fabric.PathGroup 55164 * @type Boolean 55165 * @default 55166 */ 55167 fabric.PathGroup.async = true; 55168 55169})(typeof exports !== 'undefined' ? exports : this); 55170 55171 55172(function(global){ 55173 55174 "use strict"; 55175 55176 var fabric = global.fabric || (global.fabric = { }), 55177 extend = fabric.util.object.extend, 55178 min = fabric.util.array.min, 55179 max = fabric.util.array.max, 55180 invoke = fabric.util.array.invoke; 55181 55182 if (fabric.Group) { 55183 return; 55184 } 55185 55186 // lock-related properties, for use in fabric.Group#get 55187 // to enable locking behavior on group 55188 // when one of its objects has lock-related properties set 55189 var _lockProperties = { 55190 lockMovementX: true, 55191 lockMovementY: true, 55192 lockRotation: true, 55193 lockScalingX: true, 55194 lockScalingY: true, 55195 lockUniScaling: true 55196 }; 55197 55198 /** 55199 * Group class 55200 * @class fabric.Group 55201 * @extends fabric.Object 55202 * @mixes fabric.Collection 55203 * @tutorial {@link http://fabricjs.com/fabric-intro-part-3/#groups} 55204 */ 55205 fabric.Group = fabric.util.createClass(fabric.Object, fabric.Collection, /** @lends fabric.Group.prototype */ { 55206 55207 /** 55208 * Type of an object
55209 * @type String 55210 * @default 55211 */ 55212 type: 'group', 55213 55214 /** 55215 * Constructor 55216 * @param {Object} objects Group objects 55217 * @param {Object} [options] Options object 55218 * @return {Object} thisArg 55219 */ 55220 initialize: function(objects, options) { 55221 options = options || { }; 55222 55223 this._objects = objects || []; 55224 for (var i = this._objects.length; i--; ) { 55225 this._objects[i].group = this; 55226 } 55227 55228 this.originalState = { }; 55229 this.callSuper('initialize'); 55230 55231 this._calcBounds(); 55232 this._updateObjectsCoords(); 55233 55234 if (options) { 55235 extend(this, options); 55236 } 55237 this._setOpacityIfSame(); 55238 55239 this.setCoords(true); 55240 this.saveCoords(); 55241 }, 55242 55243 /** 55244 * @private 55245 */ 55246 _updateObjectsCoords: function() { 55247 var groupDeltaX = this.left, 55248 groupDeltaY = this.top; 55249 55250 this.forEachObject(function(object) { 55251 55252 var objectLeft = object.get('left'), 55253 objectTop = object.get('top'); 55254 55255 object.set('originalLeft', objectLeft); 55256 object.set('originalTop', objectTop); 55257 55258 object.set('left', objectLeft - groupDeltaX); 55259 object.set('top', objectTop - groupDeltaY); 55260 55261 object.setCoords(); 55262 55263 // do not display corners of objects enclosed in a group 55264 object.__origHasControls = object.hasControls; 55265 object.hasControls = false; 55266 }, this); 55267 }, 55268 55269 /** 55270 * Returns string represenation of a group 55271 * @return {String} 55272 */ 55273 toString: function() { 55274 return '#<fabric.Group: (' + this.complexity() + ')>'; 55275 }, 55276 55277 /** 55278 * Returns an array of all objects in this group 55279 * @return {Array} group objects 55280 */ 55281 getObjects: function() { 55282 return this._objects; 55283 }, 55284 55285 /** 55286 * Adds an object to a group; Then recalculates group's dimension, position. 55287 * @param {Object} object 55288 * @return {fabric.Group} thisArg 55289 * @chainable 55290 */ 55291 addWithUpdate: function(object) { 55292 this._restoreObjectsState(); 55293 this._objects.push(object); 55294 object.group = this; 55295 // since _restoreObjectsState set objects inactive 55296 this.forEachObject(function(o){ o.set('active', true); o.group = this; }, this); 55297 this._calcBounds(); 55298 this._updateObjectsCoords(); 55299 return this; 55300 }, 55301 55302 /** 55303 * Removes an object from a group; Then recalculates group's dimension, position. 55304 * @param {Object} object 55305 * @return {fabric.Group} thisArg 55306 * @chainable 55307 */ 55308 removeWithUpdate: function(object) { 55309 this._moveFlippedObject(object); 55310 this._restoreObjectsState(); 55311 // since _restoreObjectsState set objects inactive 55312 this.forEachObject(function(o){ o.set('active', true); o.group = this; }, this); 55313 55314 this.remove(object); 55315 this._calcBounds(); 55316 this._updateObjectsCoords(); 55317 return this; 55318 }, 55319 55320 /** 55321 * @private 55322 */ 55323 _onObjectAdded: function(object) { 55324 object.group = this; 55325 }, 55326 55327 /** 55328 * @private 55329 */ 55330 _onObjectRemoved: function(object) { 55331 delete object.group; 55332 object.set('active', false); 55333 }, 55334 55335 /** 55336 * Properties that are delegated to group objects when reading/writing 55337 * @param {Object} delegatedProperties 55338 */ 55339 delegatedProperties: { 55340 fill: true, 55341 opacity: true, 55342 fontFamily: true, 55343 fontWeight: true, 55344 fontSize: true, 55345 fontStyle: true, 55346 lineHeight: true, 55347 textDecoration: true, 55348 textAlign: true, 55349 backgroundColor: true 55350 }, 55351 55352 /** 55353 * @private 55354 */ 55355 _set: function(key, value) { 55356 if (key in this.delegatedProperties) { 55357 var i = this._objects.length; 55358 this[key] = value; 55359 while (i--) { 55360 this._objects[i].set(key, value); 55361 } 55362 } 55363 else { 55364 this[key] = value; 55365 } 55366 }, 55367 55368 /** 55369 * Returns object representation of an instance 55370 * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output 55371 * @return {Object} object representation of an instance 55372 */ 55373 toObject: function(propertiesToInclude) { 55374 return extend(this.callSuper('toObject', propertiesToInclude), { 55375 objects: invoke(this._objects, 'toObject', propertiesToInclude) 55376 }); 55377 }, 55378 55379 /**
55380 * Renders instance on a given context 55381 * @param {CanvasRenderingContext2D} ctx context to render instance on 55382 * @param {Boolean} [noTransform] When true, context is not transformed 55383 */ 55384 render: function(ctx, noTransform) { 55385 // do not render if object is not visible 55386 if (!this.visible) return; 55387 55388 ctx.save(); 55389 this.transform(ctx); 55390 55391 var groupScaleFactor = Math.max(this.scaleX, this.scaleY); 55392 55393 this.clipTo && fabric.util.clipContext(this, ctx); 55394 55395 //The array is now sorted in order of highest first, so start from end. 55396 for (var i = 0, len = this._objects.length; i < len; i++) { 55397 55398 var object = this._objects[i], 55399 originalScaleFactor = object.borderScaleFactor, 55400 originalHasRotatingPoint = object.hasRotatingPoint; 55401 55402 // do not render if object is not visible 55403 if (!object.visible) continue; 55404 55405 object.borderScaleFactor = groupScaleFactor; 55406 object.hasRotatingPoint = false; 55407 55408 object.render(ctx); 55409 55410 object.borderScaleFactor = originalScaleFactor; 55411 object.hasRotatingPoint = originalHasRotatingPoint; 55412 } 55413 this.clipTo && ctx.restore(); 55414 55415 if (!noTransform && this.active) { 55416 this.drawBorders(ctx); 55417 this.drawControls(ctx); 55418 } 55419 ctx.restore(); 55420 this.setCoords(); 55421 }, 55422 55423 /** 55424 * Retores original state of each of group objects (original state is that which was before group was created). 55425 * @private 55426 * @return {fabric.Group} thisArg 55427 * @chainable 55428 */ 55429 _restoreObjectsState: function() { 55430 this._objects.forEach(this._restoreObjectState, this); 55431 return this; 55432 }, 55433 55434 /** 55435 * Moves a flipped object to the position where it's displayed 55436 * @private 55437 * @param {fabric.Object} object 55438 * @return {fabric.Group} thisArg 55439 */ 55440 _moveFlippedObject: function(object) { 55441 var oldOriginX = object.get('originX'); 55442 var oldOriginY = object.get('originY'); 55443 var center = object.getCenterPoint(); 55444 object.set({ 55445 originX: 'center', 55446 originY: 'center', 55447 left: center.x, 55448 top: center.y 55449 }); 55450 55451 if (this.flipX) { 55452 object.toggle('flipX'); 55453 object.set('left', -object.get('left')); 55454 object.setAngle(-object.getAngle()); 55455 } 55456 if (this.flipY) { 55457 object.toggle('flipY'); 55458 object.set('top', -object.get('top')); 55459 object.setAngle(-object.getAngle()); 55460 } 55461 55462 var newOrigin = object.getPointByOrigin(oldOriginX, oldOriginY); 55463 object.set({ 55464 originX: oldOriginX, 55465 originY: oldOriginY, 55466 left: newOrigin.x, 55467 top: newOrigin.y 55468 }); 55469 return this; 55470 }, 55471 55472 /** 55473 * Restores original state of a specified object in group 55474 * @private 55475 * @param {fabric.Object} object 55476 * @return {fabric.Group} thisArg 55477 */ 55478 _restoreObjectState: function(object) { 55479 var groupLeft = this.get('left'), 55480 groupTop = this.get('top'), 55481 groupAngle = this.getAngle() * (Math.PI / 180), 55482 rotatedTop = Math.cos(groupAngle) * object.get('top') * this.get('scaleY') + Math.sin(groupAngle) * object.get('left') * this.get('scaleX'), 55483 rotatedLeft = -Math.sin(groupAngle) * object.get('top') * this.get('scaleY') + Math.cos(groupAngle) * object.get('left') * this.get('scaleX'); 55484 55485 object.setAngle(object.getAngle() + this.getAngle()); 55486 55487 object.set('left', groupLeft + rotatedLeft); 55488 object.set('top', groupTop + rotatedTop); 55489 55490 object.set('scaleX', object.get('scaleX') * this.get('scaleX')); 55491 object.set('scaleY', object.get('scaleY') * this.get('scaleY')); 55492 55493 object.setCoords(); 55494 object.hasControls = object.__origHasControls; 55495 delete object.__origHasControls; 55496 object.set('active', false); 55497 object.setCoords(); 55498 delete object.group; 55499 55500 return this; 55501 }, 55502 55503 /** 55504 * Destroys a group (restoring state of its objects) 55505 * @return {fabric.Group} thisArg 55506 * @chainable 55507 */ 55508 destroy: function() { 55509 this._objects.forEach(this._moveFlippedObject, this); 55510 return this._restoreObjectsState(); 55511 }, 55512 55513 /** 55514 * Saves coordinates of this instance (to be used together with `hasMoved`) 55515 * @saveCoords 55516 * @return {fabric.Group} thisArg 55517 * @chainable 55518 */ 55519 saveCoords: function() { 55520 this._originalLeft = this.get('left'); 55521 this._originalTop = this.get('top'); 55522 return this; 55523 }, 55524 55525 /** 55526 * Checks whether this group was moved (since `saveCoords` was called last) 55527 * @return {Boolean} true if an object was moved (since fabric.Group#saveCoords was called) 55528 */ 55529 hasMoved: function() { 55530 return this._originalLeft !== this.get('left') || 55531 this._originalTop !== this.get('top'); 55532 }, 55533 55534 /** 55535 * Sets coordinates of all group objects 55536 * @return {fabric.Group} thisArg 55537 * @chainable 55538 */ 55539 setObjectsCoords: function() { 55540 this.forEachObject(function(object) { 55541 object.setCoords(); 55542 }); 55543 return this; 55544 }, 55545 55546 /** 55547 * @private 55548 */ 55549 _setOpacityIfSame: function() { 55550 var objects = this.getObjects(), 55551 firstValue = objects[0] ? objects[0].get('opacity') : 1; 55552 55553 var isSameOpacity = objects.every(function(o) { 55554 return o.get('opacity') === firstValue; 55555 }); 55556 55557 if (isSameOpacity) { 55558 this.opacity = firstValue; 55559 } 55560 }, 55561 55562 /** 55563 * @private 55564 */ 55565 _calcBounds: function() { 55566 var aX = [], 55567 aY = [], 55568 minX, minY, maxX, maxY, o, width, height, 55569 i = 0, 55570 len = this._objects.length; 55571 55572 for (; i < len; ++i) { 55573 o = this._objects[i]; 55574 o.setCoords(); 55575 for (var prop in o.oCoords) { 55576 aX.push(o.oCoords[prop].x);
55577 aY.push(o.oCoords[prop].y); 55578 } 55579 } 55580 55581 minX = min(aX); 55582 maxX = max(aX); 55583 minY = min(aY); 55584 maxY = max(aY); 55585 55586 width = (maxX - minX) || 0; 55587 height = (maxY - minY) || 0; 55588 55589 this.width = width; 55590 this.height = height; 55591 55592 this.left = (minX + width / 2) || 0; 55593 this.top = (minY + height / 2) || 0; 55594 }, 55595 55596 /* _TO_SVG_START_ */ 55597 /** 55598 * Returns svg representation of an instance 55599 * @param {Function} [reviver] Method for further parsing of svg representation. 55600 * @return {String} svg representation of an instance 55601 */ 55602 toSVG: function(reviver) { 55603 var markup = [ 55604 '<g ', 55605 'transform="', this.getSvgTransform(), 55606 '">' 55607 ]; 55608 55609 for (var i = 0, len = this._objects.length; i < len; i++) { 55610 markup.push(this._objects[i].toSVG(reviver)); 55611 } 55612 55613 markup.push('</g>'); 55614 55615 return reviver ? reviver(markup.join('')) : markup.join(''); 55616 }, 55617 /* _TO_SVG_END_ */ 55618 55619 /** 55620 * Returns requested property 55621 * @param {String} prop Property to get 55622 * @return {Any} 55623 */ 55624 get: function(prop) { 55625 if (prop in _lockProperties) { 55626 if (this[prop]) { 55627 return this[prop]; 55628 } 55629 else { 55630 for (var i = 0, len = this._objects.length; i < len; i++) { 55631 if (this._objects[i][prop]) { 55632 return true; 55633 } 55634 } 55635 return false; 55636 } 55637 } 55638 else { 55639 if (prop in this.delegatedProperties) { 55640 return this._objects[0] && this._objects[0].get(prop); 55641 } 55642 return this[prop]; 55643 } 55644 } 55645 }); 55646 55647 /** 55648 * Returns {@link fabric.Group} instance from an object representation 55649 * @static 55650 * @memberOf fabric.Group 55651 * @param {Object} object Object to create a group from 55652 * @param {Object} [options] Options object 55653 * @return {fabric.Group} An instance of fabric.Group 55654 */ 55655 fabric.Group.fromObject = function(object, callback) { 55656 fabric.util.enlivenObjects(object.objects, function(enlivenedObjects) { 55657 delete object.objects; 55658 callback && callback(new fabric.Group(enlivenedObjects, object)); 55659 }); 55660 }; 55661 55662 /** 55663 * Indicates that instances of this type are async 55664 * @static 55665 * @memberOf fabric.Group 55666 * @type Boolean 55667 * @default 55668 */ 55669 fabric.Group.async = true; 55670 55671})(typeof exports !== 'undefined' ? exports : this); 55672 55673 55674(function(global) { 55675 55676 "use strict"; 55677 55678 var extend = fabric.util.object.extend; 55679 55680 if (!global.fabric) { 55681 global.fabric = { }; 55682 } 55683 55684 if (global.fabric.Image) { 55685 fabric.warn('fabric.Image is already defined.'); 55686 return; 55687 } 55688 55689 /** 55690 * Image class 55691 * @class fabric.Image 55692 * @extends fabric.Object 55693 * @tutorial {@link http://fabricjs.com/fabric-intro-part-1/#images} 55694 */ 55695 fabric.Image = fabric.util.createClass(fabric.Object, /** @lends fabric.Image.prototype */ { 55696 55697 /** 55698 * Type of an object
55699 * @type String 55700 * @default 55701 */ 55702 type: 'image', 55703 55704 /** 55705 * Constructor 55706 * @param {HTMLImageElement | String} element Image element 55707 * @param {Object} [options] Options object 55708 * @return {fabric.Image} thisArg 55709 */ 55710 initialize: function(element, options) { 55711 options || (options = { }); 55712 55713 this.filters = [ ]; 55714 55715 this.callSuper('initialize', options); 55716 this._initElement(element); 55717 this._initConfig(options); 55718 55719 if (options.filters) { 55720 this.filters = options.filters; 55721 this.applyFilters(); 55722 } 55723 }, 55724 55725 /** 55726 * Returns image element which this instance if based on 55727 * @return {HTMLImageElement} Image element 55728 */ 55729 getElement: function() { 55730 return this._element; 55731 }, 55732 55733 /** 55734 * Sets image element for this instance to a specified one. 55735 * If filters defined they are applied to new image. 55736 * You might need to call `canvas.renderAll` and `object.setCoords` after replacing, to render new image and update controls area. 55737 * @param {HTMLImageElement} element 55738 * @param {Function} [callback] Callback is invoked when all filters have been applied and new image is generated 55739 * @return {fabric.Image} thisArg 55740 * @chainable 55741 */ 55742 setElement: function(element, callback) { 55743 this._element = element; 55744 this._originalElement = element; 55745 this._initConfig(); 55746 55747 if (this.filters.length !== 0) { 55748 this.applyFilters(callback); 55749 } 55750 55751 return this; 55752 }, 55753 55754 /** 55755 * Returns original size of an image 55756 * @return {Object} Object with "width" and "height" properties 55757 */ 55758 getOriginalSize: function() { 55759 var element = this.getElement(); 55760 return { 55761 width: element.width, 55762 height: element.height 55763 }; 55764 }, 55765 55766 /** 55767 * Renders image on a specified context 55768 * @param {CanvasRenderingContext2D} ctx Context to render on 55769 * @param {Boolean} [noTransform] When true, context is not transformed 55770 */ 55771 render: function(ctx, noTransform) { 55772 // do not render if object is not visible 55773 if (!this.visible) return; 55774 55775 ctx.save(); 55776 var m = this.transformMatrix; 55777 var isInPathGroup = this.group && this.group.type !== 'group'; 55778 55779 // this._resetWidthHeight(); 55780 if (isInPathGroup) { 55781 ctx.translate(-this.group.width/2 + this.width/2, -this.group.height/2 + this.height/2); 55782 } 55783 if (m) { 55784 ctx.transform(m[0], m[1], m[2], m[3], m[4], m[5]); 55785 } 55786 if (!noTransform) { 55787 this.transform(ctx); 55788 } 55789 55790 ctx.save(); 55791 this._setShadow(ctx); 55792 this.clipTo && fabric.util.clipContext(this, ctx); 55793 this._render(ctx); 55794 if (this.shadow && !this.shadow.affectStroke) { 55795 this._removeShadow(ctx); 55796 } 55797 this._renderStroke(ctx); 55798 this.clipTo && ctx.restore(); 55799 ctx.restore(); 55800 55801 if (this.active && !noTransform) { 55802 this.drawBorders(ctx); 55803 this.drawControls(ctx); 55804 } 55805 ctx.restore(); 55806 }, 55807 55808 /** 55809 * @private 55810 * @param {CanvasRenderingContext2D} ctx Context to render on 55811 */ 55812 _stroke: function(ctx) { 55813 ctx.save(); 55814 ctx.lineWidth = this.strokeWidth; 55815 ctx.lineCap = this.strokeLineCap; 55816 ctx.lineJoin = this.strokeLineJoin; 55817 ctx.miterLimit = this.strokeMiterLimit; 55818 ctx.strokeStyle = this.stroke.toLive 55819 ? this.stroke.toLive(ctx) 55820 : this.stroke; 55821 55822 ctx.beginPath(); 55823 ctx.strokeRect(-this.width / 2, -this.height / 2, this.width, this.height); 55824 ctx.closePath(); 55825 ctx.restore(); 55826 }, 55827 55828 /** 55829 * @private 55830 * @param {CanvasRenderingContext2D} ctx Context to render on 55831 */ 55832 _renderDashedStroke: function(ctx) { 55833 var x = -this.width/2, 55834 y = -this.height/2, 55835 w = this.width, 55836 h = this.height; 55837 55838 ctx.save(); 55839 ctx.lineWidth = this.strokeWidth; 55840 ctx.lineCap = this.strokeLineCap; 55841 ctx.lineJoin = this.strokeLineJoin; 55842 ctx.miterLimit = this.strokeMiterLimit; 55843 ctx.strokeStyle = this.stroke.toLive 55844 ? this.stroke.toLive(ctx) 55845 : this.stroke; 55846 55847 ctx.beginPath(); 55848 fabric.util.drawDashedLine(ctx, x, y, x+w, y, this.strokeDashArray); 55849 fabric.util.drawDashedLine(ctx, x+w, y, x+w, y+h, this.strokeDashArray); 55850 fabric.util.drawDashedLine(ctx, x+w, y+h, x, y+h, this.strokeDashArray); 55851 fabric.util.drawDashedLine(ctx, x, y+h, x, y, this.strokeDashArray); 55852 ctx.closePath();
55853 ctx.restore(); 55854 }, 55855 55856 /** 55857 * Returns object representation of an instance 55858 * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output 55859 * @return {Object} Object representation of an instance 55860 */ 55861 toObject: function(propertiesToInclude) { 55862 return extend(this.callSuper('toObject', propertiesToInclude), { 55863 src: this._originalElement.src || this._originalElement._src, 55864 filters: this.filters.map(function(filterObj) { 55865 return filterObj && filterObj.toObject(); 55866 }) 55867 }); 55868 }, 55869 55870 /* _TO_SVG_START_ */ 55871 /** 55872 * Returns SVG representation of an instance 55873 * @param {Function} [reviver] Method for further parsing of svg representation. 55874 * @return {String} svg representation of an instance 55875 */ 55876 toSVG: function(reviver) { 55877 var markup = []; 55878 55879 markup.push( 55880 '<g transform="', this.getSvgTransform(), '">', 55881 '<image xlink:href="', this.getSvgSrc(), 55882 '" style="', this.getSvgStyles(), 55883 // we're essentially moving origin of transformation from top/left corner to the center of the shape 55884 // by wrapping it in container <g> element with actual transformation, then offsetting object to the top/left 55885 // so that object's center aligns with container's left/top 55886 '" transform="translate(' + (-this.width/2) + ' ' + (-this.height/2) + ')', 55887 '" width="', this.width, 55888 '" height="', this.height, 55889 '"></image>' 55890 ); 55891 55892 if (this.stroke || this.strokeDashArray) { 55893 var origFill = this.fill; 55894 this.fill = null; 55895 markup.push( 55896 '<rect ', 55897 'x="', (-1 * this.width / 2), '" y="', (-1 * this.height / 2), 55898 '" width="', this.width, '" height="', this.height, 55899 '" style="', this.getSvgStyles(), 55900 '"/>' 55901 ); 55902 this.fill = origFill; 55903 } 55904 55905 markup.push('</g>'); 55906 55907 return reviver ? reviver(markup.join('')) : markup.join(''); 55908 }, 55909 /* _TO_SVG_END_ */ 55910 55911 /** 55912 * Returns source of an image 55913 * @return {String} Source of an image 55914 */ 55915 getSrc: function() { 55916 return this.getElement().src || this.getElement()._src; 55917 }, 55918 55919 /** 55920 * Returns string representation of an instance 55921 * @return {String} String representation of an instance 55922 */ 55923 toString: function() { 55924 return '#<fabric.Image: { src: "' + this.getSrc() + '" }>'; 55925 }, 55926 55927 /** 55928 * Returns a clone of an instance 55929 * @param {Function} callback Callback is invoked with a clone as a first argument 55930 * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output 55931 */ 55932 clone: function(callback, propertiesToInclude) { 55933 this.constructor.fromObject(this.toObject(propertiesToInclude), callback); 55934 }, 55935 55936 /** 55937 * Applies filters assigned to this image (from "filters" array) 55938 * @mthod applyFilters 55939 * @param {Function} callback Callback is invoked when all filters have been applied and new image is generated 55940 * @return {fabric.Image} thisArg 55941 * @chainable 55942 */ 55943 applyFilters: function(callback) { 55944 55945 if (this.filters.length === 0) { 55946 this._element = this._originalElement; 55947 callback && callback(); 55948 return; 55949 } 55950 55951 var imgEl = this._originalElement, 55952 canvasEl = fabric.util.createCanvasElement(), 55953 replacement = fabric.util.createImage(), 55954 _this = this; 55955 55956 canvasEl.width = imgEl.width; 55957 canvasEl.height = imgEl.height; 55958 55959 canvasEl.getContext('2d').drawImage(imgEl, 0, 0, imgEl.width, imgEl.height); 55960 55961 this.filters.forEach(function(filter) { 55962 filter && filter.applyTo(canvasEl); 55963 }); 55964 55965 /** @ignore */ 55966 55967 replacement.width = imgEl.width; 55968 replacement.height = imgEl.height; 55969 55970 if (fabric.isLikelyNode) { 55971 replacement.src = canvasEl.toBuffer(undefined, fabric.Image.pngCompression); 55972 55973 // onload doesn't fire in some node versions, so we invoke callback manually 55974 _this._element = replacement; 55975 callback && callback(); 55976 } 55977 else { 55978 replacement.onload = function() { 55979 _this._element = replacement; 55980 callback && callback(); 55981 replacement.onload = canvasEl = imgEl = null; 55982 }; 55983 replacement.src = canvasEl.toDataURL('image/png'); 55984 } 55985 55986 return this; 55987 }, 55988 55989 /** 55990 * @private 55991 * @param {CanvasRenderingContext2D} ctx Context to render on 55992 */ 55993 _render: function(ctx) { 55994 ctx.drawImage( 55995 this._element, 55996 -this.width / 2, 55997 -this.height / 2, 55998 this.width, 55999 this.height 56000 ); 56001 }, 56002 56003 /** 56004 * @private 56005 */ 56006 _resetWidthHeight: function() { 56007 var element = this.getElement(); 56008 56009 this.set('width', element.width); 56010 this.set('height', element.height); 56011 }, 56012 56013 /** 56014 * The Image class's initialization method. This method is automatically 56015 * called by the constructor. 56016 * @private 56017 * @param {HTMLImageElement|String} element The element representing the image 56018 */ 56019 _initElement: function(element) { 56020 this.setElement(fabric.util.getById(element)); 56021 fabric.util.addClass(this.getElement(), fabric.Image.CSS_CANVAS); 56022 }, 56023 56024 /** 56025 * @private 56026 * @param {Object} [options] Options object 56027 */ 56028 _initConfig: function(options) {
56029 options || (options = { }); 56030 this.setOptions(options); 56031 this._setWidthHeight(options); 56032 }, 56033 56034 /** 56035 * @private 56036 * @param {Object} object Object with filters property 56037 * @param {Function} callback Callback to invoke when all fabric.Image.filters instances are created 56038 */ 56039 _initFilters: function(object, callback) { 56040 if (object.filters && object.filters.length) { 56041 fabric.util.enlivenObjects(object.filters, function(enlivenedObjects) { 56042 callback && callback(enlivenedObjects); 56043 }, 'fabric.Image.filters'); 56044 } 56045 else { 56046 callback && callback(); 56047 } 56048 }, 56049 56050 /** 56051 * @private 56052 * @param {Object} [options] Object with width/height properties 56053 */ 56054 _setWidthHeight: function(options) { 56055 this.width = 'width' in options 56056 ? options.width 56057 : (this.getElement().width || 0); 56058 56059 this.height = 'height' in options 56060 ? options.height 56061 : (this.getElement().height || 0); 56062 }, 56063 56064 /** 56065 * Returns complexity of an instance 56066 * @return {Number} complexity of this instance 56067 */ 56068 complexity: function() { 56069 return 1; 56070 } 56071 }); 56072 56073 /** 56074 * Default CSS class name for canvas 56075 * @static
56076 * @type String 56077 * @default 56078 */ 56079 fabric.Image.CSS_CANVAS = "canvas-img"; 56080 56081 /** 56082 * Alias for getSrc 56083 * @static 56084 */ 56085 fabric.Image.prototype.getSvgSrc = fabric.Image.prototype.getSrc; 56086 56087 /** 56088 * Creates an instance of fabric.Image from its object representation 56089 * @static 56090 * @param {Object} object Object to create an instance from 56091 * @param {Function} [callback] Callback to invoke when an image instance is created 56092 */ 56093 fabric.Image.fromObject = function(object, callback) { 56094 var img = fabric.document.createElement('img'), 56095 src = object.src; 56096 56097 /** @ignore */ 56098 img.onload = function() { 56099 fabric.Image.prototype._initFilters.call(object, object, function(filters) { 56100 object.filters = filters || [ ]; 56101 56102 var instance = new fabric.Image(img, object); 56103 callback && callback(instance); 56104 img = img.onload = img.onerror = null; 56105 }); 56106 }; 56107 56108 /** @ignore */ 56109 img.onerror = function() { 56110 fabric.log('Error loading ' + img.src); 56111 callback && callback(null, true); 56112 img = img.onload = img.onerror = null; 56113 }; 56114 56115 img.src = src; 56116 }; 56117 56118 /** 56119 * Creates an instance of fabric.Image from an URL string 56120 * @static 56121 * @param {String} url URL to create an image from 56122 * @param {Function} [callback] Callback to invoke when image is created (newly created image is passed as a first argument) 56123 * @param {Object} [imgOptions] Options object 56124 */ 56125 fabric.Image.fromURL = function(url, callback, imgOptions) { 56126 fabric.util.loadImage(url, function(img) { 56127 callback(new fabric.Image(img, imgOptions)); 56128 }); 56129 }; 56130 56131 /* _FROM_SVG_START_ */ 56132 /** 56133 * List of attribute names to account for when parsing SVG element (used by {@link fabric.Image.fromElement}) 56134 * @static 56135 * @see {@link http://www.w3.org/TR/SVG/struct.html#ImageElement} 56136 */ 56137 fabric.Image.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat('x y width height xlink:href'.split(' ')); 56138 56139 /** 56140 * Returns {@link fabric.Image} instance from an SVG element 56141 * @static 56142 * @param {SVGElement} element Element to parse 56143 * @param {Function} callback Callback to execute when fabric.Image object is created 56144 * @param {Object} [options] Options object 56145 * @return {fabric.Image} Instance of fabric.Image 56146 */ 56147 fabric.Image.fromElement = function(element, callback, options) { 56148 var parsedAttributes = fabric.parseAttributes(element, fabric.Image.ATTRIBUTE_NAMES); 56149 56150 fabric.Image.fromURL(parsedAttributes['xlink:href'], callback, 56151 extend((options ? fabric.util.object.clone(options) : { }), parsedAttributes)); 56152 }; 56153 /* _FROM_SVG_END_ */ 56154 56155 /** 56156 * Indicates that instances of this type are async 56157 * @static 56158 * @type Boolean 56159 * @default 56160 */ 56161 fabric.Image.async = true; 56162 56163 /** 56164 * Indicates compression level used when generating PNG under Node (in applyFilters). Any of 0-9 56165 * @static 56166 * @type Number 56167 * @default 56168 */ 56169 fabric.Image.pngCompression = 1; 56170 56171})(typeof exports !== 'undefined' ? exports : this); 56172 56173 56174fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ { 56175 56176 /** 56177 * @private 56178 * @return {Number} angle value 56179 */ 56180 _getAngleValueForStraighten: function() { 56181 var angle = this.getAngle() % 360; 56182 if (angle > 0) { 56183 return Math.round((angle-1)/90) * 90; 56184 } 56185 return Math.round(angle/90) * 90; 56186 }, 56187 56188 /** 56189 * Straightens an object (rotating it from current angle to one of 0, 90, 180, 270, etc. depending on which is closer) 56190 * @return {fabric.Object} thisArg 56191 * @chainable 56192 */ 56193 straighten: function() { 56194 this.setAngle(this._getAngleValueForStraighten()); 56195 return this; 56196 }, 56197 56198 /** 56199 * Same as {@link fabric.Object.prototype.straighten} but with animation 56200 * @param {Object} callbacks Object with callback functions 56201 * @param {Function} [callbacks.onComplete] Invoked on completion 56202 * @param {Function} [callbacks.onChange] Invoked on every step of animation 56203 * @return {fabric.Object} thisArg 56204 * @chainable 56205 */ 56206 fxStraighten: function(callbacks) { 56207 callbacks = callbacks || { }; 56208 56209 var empty = function() { }, 56210 onComplete = callbacks.onComplete || empty, 56211 onChange = callbacks.onChange || empty, 56212 _this = this; 56213 56214 fabric.util.animate({ 56215 startValue: this.get('angle'), 56216 endValue: this._getAngleValueForStraighten(), 56217 duration: this.FX_DURATION, 56218 onChange: function(value) { 56219 _this.setAngle(value); 56220 onChange(); 56221 }, 56222 onComplete: function() { 56223 _this.setCoords(); 56224 onComplete(); 56225 }, 56226 onStart: function() { 56227 _this.set('active', false); 56228 } 56229 }); 56230 56231 return this; 56232 } 56233}); 56234 56235fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.StaticCanvas.prototype */ { 56236 56237 /** 56238 * Straightens object, then rerenders canvas 56239 * @param {fabric.Object} object Object to straighten 56240 * @return {fabric.Canvas} thisArg 56241 * @chainable 56242 */ 56243 straightenObject: function (object) { 56244 object.straighten(); 56245 this.renderAll(); 56246 return this; 56247 }, 56248 56249 /** 56250 * Same as {@link fabric.Canvas.prototype.straightenObject}, but animated 56251 * @param {fabric.Object} object Object to straighten 56252 * @return {fabric.Canvas} thisArg 56253 * @chainable 56254 */ 56255 fxStraightenObject: function (object) { 56256 object.fxStraighten({ 56257 onChange: this.renderAll.bind(this) 56258 }); 56259 return this; 56260 } 56261}); 56262 56263 56264/** 56265 * @namespace fabric.Image.filters 56266 * @memberOf fabric.Image 56267 * @tutorial {@link http://fabricjs.com/fabric-intro-part-2/#image_filters} 56268 * @see {@link http://fabricjs.com/image-filters/|ImageFilters demo} 56269 */ 56270fabric.Image.filters = fabric.Image.filters || { }; 56271 56272 56273/** 56274 * Root filter class from which all filter classes inherit from 56275 * @class fabric.Image.filters.BaseFilter 56276 * @memberOf fabric.Image.filters 56277 */ 56278fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Image.filters.BaseFilter.prototype */ { 56279 56280 /** 56281 * Filter type 56282 * @param {String} type 56283 * @default 56284 */ 56285 type: 'BaseFilter', 56286 56287 /** 56288 * Returns object representation of an instance 56289 * @return {Object} Object representation of an instance 56290 */ 56291 toObject: function() { 56292 return { type: this.type }; 56293 }, 56294 56295 /** 56296 * Returns a JSON representation of an instance 56297 * @return {Object} JSON 56298 */ 56299 toJSON: function() { 56300 // delegate, not alias 56301 return this.toObject(); 56302 } 56303}); 56304 56305 56306(function(global) { 56307 56308 "use strict"; 56309 56310 var fabric = global.fabric || (global.fabric = { }), 56311 extend = fabric.util.object.extend; 56312 56313 /** 56314 * Brightness filter class 56315 * @class fabric.Image.filters.Brightness 56316 * @memberOf fabric.Image.filters 56317 * @extends fabric.Image.filters.BaseFilter 56318 */ 56319 fabric.Image.filters.Brightness = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.Brightness.prototype */ { 56320 56321 /** 56322 * Filter type 56323 * @param {String} type 56324 * @default 56325 */ 56326 type: 'Brightness', 56327 56328 /** 56329 * Constructor 56330 * @memberOf fabric.Image.filters.Brightness.prototype 56331 * @param {Object} [options] Options object 56332 * @param {Number} [options.brightness=100] Value to brighten the image up (0..255) 56333 */ 56334 initialize: function(options) { 56335 options = options || { }; 56336 this.brightness = options.brightness || 100; 56337 }, 56338 56339 /** 56340 * Applies filter to canvas element 56341 * @param {Object} canvasEl Canvas element to apply filter to 56342 */ 56343 applyTo: function(canvasEl) { 56344 var context = canvasEl.getContext('2d'), 56345 imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), 56346 data = imageData.data, 56347 brightness = this.brightness; 56348 56349 for (var i = 0, len = data.length; i < len; i += 4) { 56350 data[i] += brightness; 56351 data[i + 1] += brightness; 56352 data[i + 2] += brightness; 56353 } 56354 56355 context.putImageData(imageData, 0, 0); 56356 }, 56357 56358 /** 56359 * Returns object representation of an instance 56360 * @return {Object} Object representation of an instance 56361 */ 56362 toObject: function() { 56363 return extend(this.callSuper('toObject'), { 56364 brightness: this.brightness 56365 }); 56366 } 56367 }); 56368 56369 /** 56370 * Returns filter instance from an object representation 56371 * @static 56372 * @param {Object} object Object to create an instance from 56373 * @return {fabric.Image.filters.Brightness} Instance of fabric.Image.filters.Brightness 56374 */ 56375 fabric.Image.filters.Brightness.fromObject = function(object) { 56376 return new fabric.Image.filters.Brightness(object); 56377 }; 56378 56379})(typeof exports !== 'undefined' ? exports : this); 56380 56381 56382(function(global) { 56383 56384 "use strict"; 56385 56386 var fabric = global.fabric || (global.fabric = { }), 56387 extend = fabric.util.object.extend; 56388 56389 /** 56390 * Adapted from <a href="http://www.html5rocks.com/en/tutorials/canvas/imagefilters/">html5rocks article</a> 56391 * @class fabric.Image.filters.Convolute 56392 * @memberOf fabric.Image.filters 56393 * @extends fabric.Image.filters.BaseFilter 56394 */ 56395 fabric.Image.filters.Convolute = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.Convolute.prototype */ { 56396 56397 /** 56398 * Filter type 56399 * @param {String} type 56400 * @default 56401 */ 56402 type: 'Convolute', 56403 56404 /** 56405 * Constructor 56406 * @memberOf fabric.Image.filters.Convolute.prototype 56407 * @param {Object} [options] Options object 56408 * @param {Boolean} [options.opaque=false] Opaque value (true/false) 56409 * @param {Array} [options.matrix] Filter matrix 56410 */ 56411 initialize: function(options) { 56412 options = options || { }; 56413 56414 this.opaque = options.opaque; 56415 this.matrix = options.matrix || [ 0, 0, 0, 56416 0, 1, 0, 56417 0, 0, 0 ]; 56418 56419 var canvasEl = fabric.util.createCanvasElement(); 56420 this.tmpCtx = canvasEl.getContext('2d'); 56421 }, 56422 56423 /** 56424 * @private 56425 */ 56426 _createImageData: function(w, h) { 56427 return this.tmpCtx.createImageData(w, h); 56428 }, 56429 56430 /** 56431 * Applies filter to canvas element 56432 * @param {Object} canvasEl Canvas element to apply filter to 56433 */ 56434 applyTo: function(canvasEl) { 56435 var weights = this.matrix; 56436 var context = canvasEl.getContext('2d'); 56437 var pixels = context.getImageData(0, 0, canvasEl.width, canvasEl.height); 56438 56439 var side = Math.round(Math.sqrt(weights.length)); 56440 var halfSide = Math.floor(side/2); 56441 var src = pixels.data; 56442 var sw = pixels.width; 56443 var sh = pixels.height; 56444 56445 // pad output by the convolution matrix 56446 var w = sw; 56447 var h = sh; 56448 var output = this._createImageData(w, h); 56449 56450 var dst = output.data; 56451 56452 // go through the destination image pixels 56453 var alphaFac = this.opaque ? 1 : 0; 56454 for (var y=0; y<h; y++) { 56455 for (var x=0; x<w; x++) { 56456 var sy = y; 56457 var sx = x; 56458 var dstOff = (y*w+x)*4; 56459 // calculate the weighed sum of the source image pixels that 56460 // fall under the convolution matrix 56461 var r=0, g=0, b=0, a=0; 56462 for (var cy=0; cy<side; cy++) { 56463 for (var cx=0; cx<side; cx++) { 56464 var scy = sy + cy - halfSide; 56465 var scx = sx + cx - halfSide; 56466 if (scy >= 0 && scy < sh && scx >= 0 && scx < sw) { 56467 var srcOff = (scy*sw+scx)*4; 56468 var wt = weights[cy*side+cx]; 56469 r += src[srcOff] * wt; 56470 g += src[srcOff+1] * wt; 56471 b += src[srcOff+2] * wt; 56472 a += src[srcOff+3] * wt; 56473 } 56474 } 56475 } 56476 dst[dstOff] = r; 56477 dst[dstOff+1] = g; 56478 dst[dstOff+2] = b; 56479 dst[dstOff+3] = a + alphaFac*(255-a); 56480 } 56481 } 56482 56483 context.putImageData(output, 0, 0); 56484 }, 56485 56486 /** 56487 * Returns object representation of an instance 56488 * @return {Object} Object representation of an instance 56489 */ 56490 toObject: function() { 56491 return extend(this.callSuper('toObject'), { 56492 opaque: this.opaque, 56493 matrix: this.matrix 56494 }); 56495 } 56496 }); 56497 56498 /** 56499 * Returns filter instance from an object representation 56500 * @static 56501 * @param {Object} object Object to create an instance from 56502 * @return {fabric.Image.filters.Convolute} Instance of fabric.Image.filters.Convolute 56503 */ 56504 fabric.Image.filters.Convolute.fromObject = function(object) { 56505 return new fabric.Image.filters.Convolute(object); 56506 }; 56507 56508})(typeof exports !== 'undefined' ? exports : this); 56509 56510 56511(function(global) { 56512 56513 "use strict"; 56514 56515 var fabric = global.fabric || (global.fabric = { }), 56516 extend = fabric.util.object.extend; 56517 56518 /**
56519 * GradientTransparency filter class 56520 * @class fabric.Image.filters.GradientTransparency 56521 * @memberOf fabric.Image.filters 56522 * @extends fabric.Image.filters.BaseFilter 56523 */ 56524 fabric.Image.filters.GradientTransparency = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.GradientTransparency.prototype */ { 56525 56526 /** 56527 * Filter type 56528 * @param {String} type 56529 * @default 56530 */ 56531 type: 'GradientTransparency', 56532 56533 /** 56534 * Constructor 56535 * @memberOf fabric.Image.filters.GradientTransparency 56536 * @param {Object} [options] Options object 56537 * @param {Number} [options.threshold=100] Threshold value 56538 */ 56539 initialize: function(options) { 56540 options = options || { }; 56541 this.threshold = options.threshold || 100; 56542 }, 56543 56544 /** 56545 * Applies filter to canvas element 56546 * @param {Object} canvasEl Canvas element to apply filter to 56547 */ 56548 applyTo: function(canvasEl) { 56549 var context = canvasEl.getContext('2d'), 56550 imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), 56551 data = imageData.data, 56552 threshold = this.threshold, 56553 total = data.length; 56554 56555 for (var i = 0, len = data.length; i < len; i += 4) { 56556 data[i + 3] = threshold + 255 * (total - i) / total; 56557 } 56558 56559 context.putImageData(imageData, 0, 0); 56560 }, 56561 56562 /** 56563 * Returns object representation of an instance 56564 * @return {Object} Object representation of an instance 56565 */ 56566 toObject: function() { 56567 return extend(this.callSuper('toObject'), { 56568 threshold: this.threshold 56569 }); 56570 } 56571 }); 56572 56573 /** 56574 * Returns filter instance from an object representation 56575 * @static 56576 * @param {Object} object Object to create an instance from 56577 * @return {fabric.Image.filters.GradientTransparency} Instance of fabric.Image.filters.GradientTransparency 56578 */ 56579 fabric.Image.filters.GradientTransparency.fromObject = function(object) { 56580 return new fabric.Image.filters.GradientTransparency(object); 56581 }; 56582 56583})(typeof exports !== 'undefined' ? exports : this); 56584 56585 56586(function(global) { 56587 56588 "use strict"; 56589 56590 var fabric = global.fabric || (global.fabric = { }); 56591 56592 /** 56593 * Grayscale image filter class 56594 * @class fabric.Image.filters.Grayscale 56595 * @memberOf fabric.Image.filters 56596 * @extends fabric.Image.filters.BaseFilter 56597 */ 56598 fabric.Image.filters.Grayscale = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.Grayscale.prototype */ { 56599 56600 /** 56601 * Filter type 56602 * @param {String} type 56603 * @default 56604 */ 56605 type: 'Grayscale', 56606 56607 /** 56608 * Applies filter to canvas element 56609 * @memberOf fabric.Image.filters.Grayscale.prototype 56610 * @param {Object} canvasEl Canvas element to apply filter to 56611 */ 56612 applyTo: function(canvasEl) { 56613 var context = canvasEl.getContext('2d'), 56614 imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), 56615 data = imageData.data, 56616 len = imageData.width * imageData.height * 4, 56617 index = 0, 56618 average; 56619 56620 while (index < len) { 56621 average = (data[index] + data[index + 1] + data[index + 2]) / 3; 56622 data[index] = average; 56623 data[index + 1] = average; 56624 data[index + 2] = average; 56625 index += 4; 56626 } 56627 56628 context.putImageData(imageData, 0, 0); 56629 } 56630 }); 56631 56632 /** 56633 * Returns filter instance from an object representation 56634 * @static 56635 * @return {fabric.Image.filters.Grayscale} Instance of fabric.Image.filters.Grayscale 56636 */ 56637 fabric.Image.filters.Grayscale.fromObject = function() { 56638 return new fabric.Image.filters.Grayscale(); 56639 }; 56640 56641})(typeof exports !== 'undefined' ? exports : this); 56642 56643 56644(function(global) { 56645 56646 "use strict"; 56647 56648 var fabric = global.fabric || (global.fabric = { }); 56649 56650 /** 56651 * Invert filter class 56652 * @class fabric.Image.filters.Invert 56653 * @memberOf fabric.Image.filters 56654 * @extends fabric.Image.filters.BaseFilter 56655 */ 56656 fabric.Image.filters.Invert = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.Invert.prototype */ { 56657 56658 /** 56659 * Filter type 56660 * @param {String} type 56661 * @default 56662 */ 56663 type: 'Invert', 56664 56665 /** 56666 * Applies filter to canvas element 56667 * @memberOf fabric.Image.filters.Invert.prototype 56668 * @param {Object} canvasEl Canvas element to apply filter to 56669 */ 56670 applyTo: function(canvasEl) { 56671 var context = canvasEl.getContext('2d'), 56672 imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), 56673 data = imageData.data, 56674 iLen = data.length, i; 56675 56676 for (i = 0; i < iLen; i+=4) { 56677 data[i] = 255 - data[i]; 56678 data[i + 1] = 255 - data[i + 1]; 56679 data[i + 2] = 255 - data[i + 2]; 56680 } 56681 56682 context.putImageData(imageData, 0, 0); 56683 } 56684 }); 56685 56686 /** 56687 * Returns filter instance from an object representation 56688 * @static 56689 * @return {fabric.Image.filters.Invert} Instance of fabric.Image.filters.Invert 56690 */ 56691 fabric.Image.filters.Invert.fromObject = function() { 56692 return new fabric.Image.filters.Invert(); 56693 }; 56694 56695})(typeof exports !== 'undefined' ? exports : this); 56696 56697 56698(function(global) { 56699 56700 "use strict"; 56701 56702 var fabric = global.fabric || (global.fabric = { }), 56703 extend = fabric.util.object.extend; 56704 56705 /** 56706 * Mask filter class 56707 * See http://resources.aleph-1.com/mask/ 56708 * @class fabric.Image.filters.Mask 56709 * @memberOf fabric.Image.filters 56710 * @extends fabric.Image.filters.BaseFilter 56711 */ 56712 fabric.Image.filters.Mask = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.Mask.prototype */ { 56713 56714 /** 56715 * Filter type 56716 * @param {String} type 56717 * @default 56718 */ 56719 type: 'Mask', 56720 56721 /** 56722 * Constructor 56723 * @memberOf fabric.Image.filters.Mask.prototype 56724 * @param {Object} [options] Options object 56725 * @param {fabric.Image} [options.mask] Mask image object 56726 * @param {Number} [options.channel=0] Rgb channel (0, 1, 2 or 3) 56727 */ 56728 initialize: function(options) { 56729 options = options || { }; 56730 56731 this.mask = options.mask; 56732 this.channel = [ 0, 1, 2, 3 ].indexOf(options.channel) > -1 ? options.channel : 0; 56733 }, 56734 56735 /** 56736 * Applies filter to canvas element 56737 * @param {Object} canvasEl Canvas element to apply filter to 56738 */ 56739 applyTo: function(canvasEl) { 56740 if (!this.mask) return; 56741 56742 var context = canvasEl.getContext('2d'), 56743 imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), 56744 data = imageData.data, 56745 maskEl = this.mask.getElement(), 56746 maskCanvasEl = fabric.util.createCanvasElement(), 56747 channel = this.channel, 56748 i, 56749 iLen = imageData.width * imageData.height * 4; 56750 56751 maskCanvasEl.width = maskEl.width; 56752 maskCanvasEl.height = maskEl.height; 56753 56754 maskCanvasEl.getContext('2d').drawImage(maskEl, 0, 0, maskEl.width, maskEl.height); 56755 56756 var maskImageData = maskCanvasEl.getContext('2d').getImageData(0, 0, maskEl.width, maskEl.height), 56757 maskData = maskImageData.data; 56758 56759 for (i = 0; i < iLen; i += 4) { 56760 data[i + 3] = maskData[i + channel]; 56761 } 56762 56763 context.putImageData(imageData, 0, 0); 56764 }, 56765 56766 /** 56767 * Returns object representation of an instance 56768 * @return {Object} Object representation of an instance 56769 */ 56770 toObject: function() { 56771 return extend(this.callSuper('toObject'), { 56772 mask: this.mask.toObject(), 56773 channel: this.channel 56774 }); 56775 } 56776 }); 56777 56778 /** 56779 * Returns filter instance from an object representation 56780 * @static 56781 * @param {Object} object Object to create an instance from 56782 * @param {Function} [callback] Callback to invoke when a mask filter instance is created 56783 */ 56784 fabric.Image.filters.Mask.fromObject = function(object, callback) { 56785 var img = fabric.document.createElement('img'), 56786 src = object.mask.src; 56787 56788 /** @ignore */ 56789 img.onload = function() { 56790 object.mask = new fabric.Image(img, object.mask); 56791 56792 callback && callback(new fabric.Image.filters.Mask(object)); 56793 img = img.onload = img.onerror = null; 56794 }; 56795 56796 /** @ignore */ 56797 img.onerror = function() { 56798 fabric.log('Error loading ' + img.src); 56799 callback && callback(null, true); 56800 img = img.onload = img.onerror = null; 56801 }; 56802 56803 img.src = src; 56804 }; 56805 56806 /** 56807 * Indicates that instances of this type are async 56808 * @static 56809 * @type Boolean 56810 * @default 56811 */ 56812 fabric.Image.filters.Mask.async = true; 56813 56814})(typeof exports !== 'undefined' ? exports : this); 56815 56816 56817(function(global) { 56818 56819 "use strict"; 56820 56821 var fabric = global.fabric || (global.fabric = { }), 56822 extend = fabric.util.object.extend; 56823 56824 /** 56825 * Noise filter class 56826 * @class fabric.Image.filters.Noise 56827 * @memberOf fabric.Image.filters 56828 * @extends fabric.Image.filters.BaseFilter 56829 */ 56830 fabric.Image.filters.Noise = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.Noise.prototype */ { 56831 56832 /** 56833 * Filter type 56834 * @param {String} type 56835 * @default 56836 */ 56837 type: 'Noise', 56838 56839 /** 56840 * Constructor 56841 * @memberOf fabric.Image.filters.Noise.prototype 56842 * @param {Object} [options] Options object 56843 * @param {Number} [options.noise=100] Noise value 56844 */ 56845 initialize: function(options) { 56846 options = options || { }; 56847 this.noise = options.noise || 100; 56848 }, 56849 56850 /** 56851 * Applies filter to canvas element 56852 * @param {Object} canvasEl Canvas element to apply filter to 56853 */ 56854 applyTo: function(canvasEl) { 56855 var context = canvasEl.getContext('2d'), 56856 imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), 56857 data = imageData.data, 56858 noise = this.noise, rand; 56859 56860 for (var i = 0, len = data.length; i < len; i += 4) { 56861 56862 rand = (0.5 - Math.random()) * noise; 56863 56864 data[i] += rand; 56865 data[i + 1] += rand; 56866 data[i + 2] += rand; 56867 } 56868 56869 context.putImageData(imageData, 0, 0); 56870 }, 56871 56872 /** 56873 * Returns object representation of an instance 56874 * @return {Object} Object representation of an instance 56875 */ 56876 toObject: function() { 56877 return extend(this.callSuper('toObject'), { 56878 noise: this.noise 56879 }); 56880 } 56881 }); 56882 56883 /** 56884 * Returns filter instance from an object representation 56885 * @static 56886 * @param {Object} object Object to create an instance from 56887 * @return {fabric.Image.filters.Noise} Instance of fabric.Image.filters.Noise 56888 */ 56889 fabric.Image.filters.Noise.fromObject = function(object) { 56890 return new fabric.Image.filters.Noise(object); 56891 }; 56892 56893})(typeof exports !== 'undefined' ? exports : this); 56894 56895 56896(function(global) { 56897 56898 "use strict"; 56899 56900 var fabric = global.fabric || (global.fabric = { }), 56901 extend = fabric.util.object.extend; 56902 56903 /** 56904 * Pixelate filter class 56905 * @class fabric.Image.filters.Pixelate 56906 * @memberOf fabric.Image.filters 56907 * @extends fabric.Image.filters.BaseFilter 56908 */ 56909 fabric.Image.filters.Pixelate = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.Pixelate.prototype */ { 56910 56911 /** 56912 * Filter type 56913 * @param {String} type 56914 * @default 56915 */ 56916 type: 'Pixelate', 56917 56918 /** 56919 * Constructor 56920 * @memberOf fabric.Image.filters.Pixelate.prototype 56921 * @param {Object} [options] Options object 56922 * @param {Number} [options.blocksize=4] Blocksize for pixelate 56923 */ 56924 initialize: function(options) { 56925 options = options || { }; 56926 this.blocksize = options.blocksize || 4; 56927 }, 56928 56929 /** 56930 * Applies filter to canvas element 56931 * @param {Object} canvasEl Canvas element to apply filter to 56932 */ 56933 applyTo: function(canvasEl) { 56934 var context = canvasEl.getContext('2d'), 56935 imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), 56936 data = imageData.data, 56937 iLen = imageData.height, 56938 jLen = imageData.width, 56939 index, i, j, r, g, b, a; 56940 56941 for (i = 0; i < iLen; i += this.blocksize) { 56942 for (j = 0; j < jLen; j += this.blocksize) { 56943 56944 index = (i * 4) * jLen + (j * 4); 56945 56946 r = data[index]; 56947 g = data[index+1]; 56948 b = data[index+2]; 56949 a = data[index+3]; 56950 56951 /* 56952 blocksize: 4 56953 56954 [1,x,x,x,1] 56955 [x,x,x,x,1] 56956 [x,x,x,x,1] 56957 [x,x,x,x,1] 56958 [1,1,1,1,1] 56959 */ 56960 56961 for (var _i = i, _ilen = i + this.blocksize; _i < _ilen; _i++) { 56962 for (var _j = j, _jlen = j + this.blocksize; _j < _jlen; _j++) { 56963 index = (_i * 4) * jLen + (_j * 4); 56964 data[index] = r; 56965 data[index + 1] = g; 56966 data[index + 2] = b; 56967 data[index + 3] = a; 56968 } 56969 } 56970 } 56971 } 56972 56973 context.putImageData(imageData, 0, 0); 56974 }, 56975 56976 /** 56977 * Returns object representation of an instance 56978 * @return {Object} Object representation of an instance 56979 */ 56980 toObject: function() { 56981 return extend(this.callSuper('toObject'), { 56982 blocksize: this.blocksize 56983 }); 56984 } 56985 }); 56986 56987 /** 56988 * Returns filter instance from an object representation 56989 * @static 56990 * @param {Object} object Object to create an instance from 56991 * @return {fabric.Image.filters.Pixelate} Instance of fabric.Image.filters.Pixelate 56992 */ 56993 fabric.Image.filters.Pixelate.fromObject = function(object) { 56994 return new fabric.Image.filters.Pixelate(object); 56995 }; 56996 56997})(typeof exports !== 'undefined' ? exports : this); 56998 56999 57000(function(global) { 57001 57002 "use strict"; 57003 57004 var fabric = global.fabric || (global.fabric = { }), 57005 extend = fabric.util.object.extend; 57006 57007 /** 57008 * Remove white filter class 57009 * @class fabric.Image.filters.RemoveWhite 57010 * @memberOf fabric.Image.filters 57011 * @extends fabric.Image.filters.BaseFilter 57012 */ 57013 fabric.Image.filters.RemoveWhite = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.RemoveWhite.prototype */ { 57014 57015 /** 57016 * Filter type 57017 * @param {String} type 57018 * @default 57019 */ 57020 type: 'RemoveWhite', 57021 57022 /** 57023 * Constructor 57024 * @memberOf fabric.Image.filters.RemoveWhite.prototype 57025 * @param {Object} [options] Options object 57026 * @param {Number} [options.threshold=30] Threshold value 57027 * @param {Number} [options.distance=20] Distance value 57028 */ 57029 initialize: function(options) { 57030 options = options || { }; 57031 this.threshold = options.threshold || 30; 57032 this.distance = options.distance || 20; 57033 }, 57034 57035 /** 57036 * Applies filter to canvas element 57037 * @param {Object} canvasEl Canvas element to apply filter to 57038 */ 57039 applyTo: function(canvasEl) { 57040 var context = canvasEl.getContext('2d'), 57041 imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), 57042 data = imageData.data, 57043 threshold = this.threshold, 57044 distance = this.distance, 57045 limit = 255 - threshold, 57046 abs = Math.abs, 57047 r, g, b; 57048 57049 for (var i = 0, len = data.length; i < len; i += 4) { 57050 r = data[i]; 57051 g = data[i+1]; 57052 b = data[i+2]; 57053 57054 if (r > limit && 57055 g > limit && 57056 b > limit && 57057 abs(r-g) < distance && 57058 abs(r-b) < distance && 57059 abs(g-b) < distance 57060 ) { 57061 data[i+3] = 1; 57062 } 57063 } 57064 57065 context.putImageData(imageData, 0, 0); 57066 }, 57067 57068 /** 57069 * Returns object representation of an instance 57070 * @return {Object} Object representation of an instance 57071 */ 57072 toObject: function() { 57073 return extend(this.callSuper('toObject'), { 57074 threshold: this.threshold, 57075 distance: this.distance 57076 }); 57077 } 57078 }); 57079 57080 /** 57081 * Returns filter instance from an object representation 57082 * @static 57083 * @param {Object} object Object to create an instance from 57084 * @return {fabric.Image.filters.RemoveWhite} Instance of fabric.Image.filters.RemoveWhite 57085 */ 57086 fabric.Image.filters.RemoveWhite.fromObject = function(object) { 57087 return new fabric.Image.filters.RemoveWhite(object); 57088 }; 57089 57090})(typeof exports !== 'undefined' ? exports : this); 57091 57092 57093(function(global) { 57094 57095 "use strict"; 57096 57097 var fabric = global.fabric || (global.fabric = { }); 57098 57099 /** 57100 * Sepia filter class 57101 * @class fabric.Image.filters.Sepia 57102 * @memberOf fabric.Image.filters 57103 * @extends fabric.Image.filters.BaseFil
57103ter 57104 */ 57105 fabric.Image.filters.Sepia = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.Sepia.prototype */ { 57106 57107 /** 57108 * Filter type 57109 * @param {String} type 57110 * @default 57111 */ 57112 type: 'Sepia', 57113 57114 /** 57115 * Applies filter to canvas element 57116 * @memberOf fabric.Image.filters.Sepia.prototype 57117 * @param {Object} canvasEl Canvas element to apply filter to 57118 */ 57119 applyTo: function(canvasEl) { 57120 var context = canvasEl.getContext('2d'), 57121 imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), 57122 data = imageData.data, 57123 iLen = data.length, i, avg; 57124 57125 for (i = 0; i < iLen; i+=4) { 57126 avg = 0.3 * data[i] + 0.59 * data[i + 1] + 0.11 * data[i + 2]; 57127 data[i] = avg + 100; 57128 data[i + 1] = avg + 50; 57129 data[i + 2] = avg + 255; 57130 } 57131 57132 context.putImageData(imageData, 0, 0); 57133 } 57134 }); 57135 57136 /** 57137 * Returns filter instance from an object representation 57138 * @static 57139 * @return {fabric.Image.filters.Sepia} Instance of fabric.Image.filters.Sepia 57140 */ 57141 fabric.Image.filters.Sepia.fromObject = function() { 57142 return new fabric.Image.filters.Sepia(); 57143 }; 57144 57145})(typeof exports !== 'undefined' ? exports : this); 57146 57147 57148(function(global) { 57149 57150 "use strict"; 57151 57152 var fabric = global.fabric || (global.fabric = { }); 57153 57154 /** 57155 * Sepia2 filter class 57156 * @class fabric.Image.filters.Sepia2 57157 * @memberOf fabric.Image.filters 57158 * @extends fabric.Image.filters.BaseFilter 57159 */ 57160 fabric.Image.filters.Sepia2 = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.Sepia2.prototype */ { 57161 57162 /** 57163 * Filter type 57164 * @param {String} type 57165 * @default 57166 */ 57167 type: 'Sepia2', 57168 57169 /** 57170 * Applies filter to canvas element 57171 * @memberOf fabric.Image.filters.Sepia.prototype 57172 * @param {Object} canvasEl Canvas element to apply filter to 57173 */ 57174 applyTo: function(canvasEl) { 57175 var context = canvasEl.getContext('2d'), 57176 imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), 57177 data = imageData.data, 57178 iLen = data.length, i, r, g, b; 57179 57180 for (i = 0; i < iLen; i+=4) { 57181 r = data[i]; 57182 g = data[i + 1]; 57183 b = data[i + 2]; 57184 57185 data[i] = (r * 0.393 + g * 0.769 + b * 0.189 ) / 1.351; 57186 data[i + 1] = (r * 0.349 + g * 0.686 + b * 0.168 ) / 1.203; 57187 data[i + 2] = (r * 0.272 + g * 0.534 + b * 0.131 ) / 2.140; 57188 } 57189 57190 context.putImageData(imageData, 0, 0); 57191 } 57192 }); 57193 57194 /** 57195 * Returns filter instance from an object representation 57196 * @static 57197 * @return {fabric.Image.filters.Sepia2} Instance of fabric.Image.filters.Sepia2 57198 */ 57199 fabric.Image.filters.Sepia2.fromObject = function() { 57200 return new fabric.Image.filters.Sepia2(); 57201 }; 57202 57203})(typeof exports !== 'undefined' ? exports : this); 57204 57205 57206(function(global) { 57207 57208 "use strict"; 57209 57210 var fabric = global.fabric || (global.fabric = { }), 57211 extend = fabric.util.object.extend; 57212 57213 /** 57214 * Tint filter class 57215 * Adapted from <a href="https://github.com/mezzoblue/PaintbrushJS">https://github.com/mezzoblue/PaintbrushJS</a> 57216 * @class fabric.Image.filters.Tint 57217 * @memberOf fabric.Image.filters 57218 * @extends fabric.Image.filters.BaseFilter 57219 */ 57220 fabric.Image.filters.Tint = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.Tint.prototype */ { 57221 57222 /** 57223 * Filter type 57224 * @param {String} type 57225 * @default 57226 */ 57227 type: 'Tint', 57228 57229 /** 57230 * Constructor 57231 * @memberOf fabric.Image.filters.Tint.prototype 57232 * @param {Object} [options] Options object 57233 * @param {String} [options.color=#000000] Color to tint the image with 57234 * @param {Number} [options.opacity] Opacity value that controls the tint effect's transparency (0..1) 57235 */ 57236 initialize: function(options) { 57237 options = options || { }; 57238 57239 this.color = options.color || '#000000'; 57240 this.opacity = typeof options.opacity !== 'undefined' 57241 ? options.opacity 57242 : new fabric.Color(this.color).getAlpha(); 57243 }, 57244 57245 /** 57246 * Applies filter to canvas element 57247 * @param {Object} canvasEl Canvas element to apply filter to 57248 */ 57249 applyTo: function(canvasEl) { 57250 var context = canvasEl.getContext('2d'), 57251 imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), 57252 data = imageData.data, 57253 iLen = data.length, i, 57254 tintR, tintG, tintB, 57255 r, g, b, alpha1, 57256 source; 57257 57258 source = new fabric.Color(this.color).getSource(); 57259 57260 tintR = source[0] * this.opacity; 57261 tintG = source[1] * this.opacity; 57262 tintB = source[2] * this.opacity; 57263 57264 alpha1 = 1 - this.opacity; 57265 57266 for (i = 0; i < iLen; i+=4) { 57267 r = data[i]; 57268 g = data[i + 1]; 57269 b = data[i + 2]; 57270 57271 // alpha compositing 57272 data[i] = tintR + r * alpha1; 57273 data[i + 1] = tintG + g * alpha1; 57274 data[i + 2] = tintB + b * alpha1; 57275 } 57276 57277 context.putImageData(imageData, 0, 0); 57278 }, 57279 57280 /** 57281 * Returns object representation of an instance 57282 * @return {Object} Object representation of an instance 57283 */ 57284 toObject: function() { 57285 return extend(this.callSuper('toObject'), { 57286 color: this.color, 57287 opacity: this.opacity 57288 }); 57289 } 57290 }); 57291 57292 /** 57293 * Returns filter instance from an object representation 57294 * @static 57295 * @param {Object} object Object to create an instance from 57296 * @return {fabric.Image.filters.Tint} Instance of fabric.Image.filters.Tint 57297 */ 57298 fabric.Image.filters.Tint.fromObject = function(object) { 57299 return new fabric.Image.filters.Tint(object); 57300 }; 57301 57302})(typeof exports !== 'undefined' ? exports : this); 57303 57304 57305(function(global) { 57306 57307 "use strict"; 57308 57309 var fabric = global.fabric || (global.fabric = { }), 57310 extend = fabric.util.object.extend, 57311 clone = fabric.util.object.clone, 57312 toFixed = fabric.util.toFixed, 57313 supportsLineDash = fabric.StaticCanvas.supports('setLineDash'); 57314 57315 if (fabric.Text) { 57316 fabric.warn('fabric.Text is already defined'); 57317 return; 57318 } 57319 57320 var stateProperties = fabric.Object.prototype.stateProperties.concat(); 57321 stateProperties.push( 57322 'fontFamily', 57323 'fontWeight', 57324 'fontSize', 57325 'text', 57326 'textDecoration', 57327 'textAlign', 57328 'fontStyle', 57329 'lineHeight',
57330 'textBackgroundColor', 57331 'useNative', 57332 'path' 57333 ); 57334 57335 /** 57336 * Text class 57337 * @class fabric.Text 57338 * @extends fabric.Object 57339 * @return {fabric.Text} thisArg 57340 * @tutorial {@link http://fabricjs.com/fabric-intro-part-2/#text} 57341 */ 57342 fabric.Text = fabric.util.createClass(fabric.Object, /** @lends fabric.Text.prototype */ { 57343 57344 /** 57345 * Properties which when set cause object to change dimensions 57346 * @type Object 57347 * @private 57348 */ 57349 _dimensionAffectingProps: { 57350 fontSize: true, 57351 fontWeight: true, 57352 fontFamily: true, 57353 textDecoration: true, 57354 fontStyle: true, 57355 lineHeight: true, 57356 stroke: true, 57357 strokeWidth: true, 57358 text: true 57359 }, 57360 57361 /** 57362 * Retrieves object's fontSize 57363 * @method getFontSize 57364 * @memberOf fabric.Text.prototype 57365 * @return {String} Font size (in pixels) 57366 */ 57367 57368 /** 57369 * Sets object's fontSize 57370 * @method setFontSize 57371 * @memberOf fabric.Text.prototype 57372 * @param {Number} fontSize Font size (in pixels) 57373 * @return {fabric.Text} 57374 * @chainable 57375 */ 57376 57377 /** 57378 * Retrieves object's fontWeight 57379 * @method getFontWeight 57380 * @memberOf fabric.Text.prototype 57381 * @return {(String|Number)} Font weight 57382 */ 57383 57384 /** 57385 * Sets object's fontWeight 57386 * @method setFontWeight 57387 * @memberOf fabric.Text.prototype 57388 * @param {(Number|String)} fontWeight Font weight 57389 * @return {fabric.Text} 57390 * @chainable 57391 */ 57392 57393 /** 57394 * Retrieves object's fontFamily 57395 * @method getFontFamily 57396 * @memberOf fabric.Text.prototype 57397 * @return {String} Font family 57398 */ 57399 57400 /** 57401 * Sets object's fontFamily 57402 * @method setFontFamily 57403 * @memberOf fabric.Text.prototype 57404 * @param {String} fontFamily Font family 57405 * @return {fabric.Text} 57406 * @chainable 57407 */ 57408 57409 /** 57410 * Retrieves object's text 57411 * @method getText 57412 * @memberOf fabric.Text.prototype 57413 * @return {String} text 57414 */ 57415 57416 /** 57417 * Sets object's text 57418 * @method setText 57419 * @memberOf fabric.Text.prototype 57420 * @param {String} text Text 57421 * @return {fabric.Text} 57422 * @chainable 57423 */ 57424 57425 /** 57426 * Retrieves object's textDecoration 57427 * @method getTextDecoration 57428 * @memberOf fabric.Text.prototype 57429 * @return {String} Text decoration 57430 */ 57431 57432 /** 57433 * Sets object's textDecoration 57434 * @method setTextDecoration 57435 * @memberOf fabric.Text.prototype 57436 * @param {String} textDecoration Text decoration 57437 * @return {fabric.Text} 57438 * @chainable 57439 */ 57440 57441 /** 57442 * Retrieves object's fontStyle 57443 * @method getFontStyle 57444 * @memberOf fabric.Text.prototype 57445 * @return {String} Font style 57446 */ 57447 57448 /** 57449 * Sets object's fontStyle 57450 * @method setFontStyle 57451 * @memberOf fabric.Text.prototype 57452 * @param {String} fontStyle Font style 57453 * @return {fabric.Text} 57454 * @chainable 57455 */ 57456 57457 /** 57458 * Retrieves object's lineHeight 57459 * @method getLineHeight 57460 * @memberOf fabric.Text.prototype 57461 * @return {Number} Line height 57462 */ 57463 57464 /** 57465 * Sets object's lineHeight 57466 * @method setLineHeight 57467 * @memberOf fabric.Text.prototype 57468 * @param {Number} lineHeight Line height 57469 * @return {fabric.Text} 57470 * @chainable 57471 */ 57472 57473 /** 57474 * Retrieves object's textAlign 57475 * @method getTextAlign 57476 * @memberOf fabric.Text.prototype 57477 * @return {String} Text alignment 57478 */ 57479 57480 /** 57481 * Sets object's textAlign 57482 * @method setTextAlign 57483 * @memberOf fabric.Text.prototype 57484 * @param {String} textAlign Text alignment 57485 * @return {fabric.Text} 57486 * @chainable 57487 */ 57488 57489 /** 57490 * Retrieves object's textBackgroundColor 57491 * @method getTextBackgroundColor 57492 * @memberOf fabric.Text.prototype 57493 * @return {String} Text background color 57494 */ 57495 57496 /** 57497 * Sets object's textBackgroundColor 57498 * @method setTextBackgroundColor 57499 * @memberOf fabric.Text.prototype 57500 * @param {String} textBackgroundColor Text background color 57501 * @return {fabric.Text} 57502 * @chainable 57503 */ 57504 57505 /** 57506 * Type of an object
57507 * @type String 57508 * @default 57509 */ 57510 type: 'text', 57511 57512 /** 57513 * Font size (in pixels) 57514 * @type Number 57515 * @default 57516 */ 57517 fontSize: 40, 57518 57519 /** 57520 * Font weight (e.g. bold, normal, 400, 600, 800) 57521 * @type {(Number|String)} 57522 * @default 57523 */ 57524 fontWeight: 'normal', 57525 57526 /** 57527 * Font family 57528 * @type String 57529 * @default 57530 */ 57531 fontFamily: 'Times New Roman', 57532 57533 /** 57534 * Text decoration Possible values: "", "underline", "overline" or "line-through". 57535 * @type String 57536 * @default 57537 */ 57538 textDecoration: '', 57539 57540 /** 57541 * Text alignment. Possible values: "left", "center", or "right". 57542 * @type String 57543 * @default 57544 */ 57545 textAlign: 'left', 57546 57547 /** 57548 * Font style . Possible values: "", "normal", "italic" or "oblique". 57549 * @type String 57550 * @default 57551 */ 57552 fontStyle: '', 57553 57554 /** 57555 * Line height 57556 * @type Number 57557 * @default 57558 */ 57559 lineHeight: 1.3, 57560 57561 /** 57562 * Background color of text lines
57563 * @type String 57564 * @default 57565 */ 57566 textBackgroundColor: '', 57567 57568 /** 57569 * URL of a font file, when using Cufon 57570 * @type String | null 57571 * @default 57572 */ 57573 path: null, 57574 57575 /** 57576 * Indicates whether canvas native text methods should be used to render text (otherwise, Cufon is used) 57577 * @type Boolean 57578 * @default 57579 */ 57580 useNative: true, 57581 57582 /** 57583 * List of properties to consider when checking if state of an object is changed ({@link fabric.Object#hasStateChanged}) 57584 * as well as for history (undo/redo) purposes 57585 * @type Array 57586 */ 57587 stateProperties: stateProperties, 57588 57589 /** 57590 * When defined, an object is rendered via stroke and this property specifies its color. 57591 * <b>Backwards incompatibility note:</b> This property was named "strokeStyle" until v1.1.6 57592 * @type String 57593 * @default 57594 */ 57595 stroke: null, 57596 57597 /** 57598 * Shadow object representing shadow of this shape. 57599 * <b>Backwards incompatibility note:</b> This property was named "textShadow" (String) until v1.2.11 57600 * @type fabric.Shadow 57601 * @default 57602 */ 57603 shadow: null, 57604 57605 /** 57606 * Constructor 57607 * @param {String} text Text string 57608 * @param {Object} [options] Options object 57609 * @return {fabric.Text} thisArg 57610 */ 57611 initialize: function(text, options) { 57612 options = options || { }; 57613 57614 this.text = text; 57615 this.__skipDimension = true; 57616 this.setOptions(options); 57617 this.__skipDimension = false; 57618 this._initDimensions(); 57619 this.setCoords(); 57620 }, 57621 57622 /** 57623 * Renders text object on offscreen canvas, so that it would get dimensions 57624 * @private 57625 */ 57626 _initDimensions: function() { 57627 if (this.__skipDimension) return; 57628 var canvasEl = fabric.util.createCanvasElement(); 57629 this._render(canvasEl.getContext('2d')); 57630 }, 57631 57632 /** 57633 * Returns string representation of an instance 57634 * @return {String} String representation of text object 57635 */ 57636 toString: function() { 57637 return '#<fabric.Text (' + this.complexity() + 57638 '): { "text": "' + this.text + '", "fontFamily": "' + this.fontFamily + '" }>'; 57639 }, 57640 57641 /** 57642 * @private 57643 * @param {CanvasRenderingContext2D} ctx Context to render on 57644 */ 57645 _render: function(ctx) { 57646 57647 var isInPathGroup = this.group && this.group.type !== 'group'; 57648 if (isInPathGroup && !this.transformMatrix) { 57649 ctx.translate(-this.group.width/2 + this.left, -this.group.height / 2 + this.top); 57650 } 57651 else if (isInPathGroup && this.transformMatrix) { 57652 ctx.translate(-this.group.width/2, -this.group.height/2); 57653 } 57654 57655 if (typeof Cufon === 'undefined' || this.useNative === true) { 57656 this._renderViaNative(ctx); 57657 } 57658 else { 57659 this._renderViaCufon(ctx); 57660 } 57661 }, 57662 57663 /** 57664 * @private 57665 * @param {CanvasRenderingContext2D} ctx Context to render on 57666 */ 57667 _renderViaNative: function(ctx) { 57668 57669 this.transform(ctx, fabric.isLikelyNode); 57670 57671 this._setTextStyles(ctx); 57672 57673 var textLines = this.text.split(/\r?\n/); 57674 57675 this.width = this._getTextWidth(ctx, textLines); 57676 this.height = this._getTextHeight(ctx, textLines); 57677 57678 this.clipTo && fabric.util.clipContext(this, ctx); 57679 57680 this._renderTextBackground(ctx, textLines); 57681 57682 if (this.textAlign !== 'left' && this.textAlign !== 'justify') { 57683 ctx.save(); 57684 ctx.translate(this.textAlign === 'center' ? (this.width / 2) : this.width, 0); 57685 } 57686 57687 ctx.save(); 57688 this._setShadow(ctx); 57689 this._renderTextFill(ctx, textLines); 57690 this._renderTextStroke(ctx, textLines); 57691 this._removeShadow(ctx); 57692 ctx.restore(); 57693 57694 if (this.textAlign !== 'left' && this.textAlign !== 'justify') { 57695 ctx.restore(); 57696 } 57697 57698 this._renderTextDecoration(ctx, textLines); 57699 this.clipTo && ctx.restore(); 57700 57701 this._setBoundaries(ctx, textLines); 57702 this._totalLineHeight = 0; 57703 }, 57704 57705 /** 57706 * @private 57707 * @param {CanvasRenderingContext2D} ctx Context to render on 57708 * @param {Array} textLines Array of all text lines 57709 */ 57710 _setBoundaries: function(ctx, textLines) { 57711 this._boundaries = [ ]; 57712 57713 for (var i = 0, len = textLines.length; i < len; i++) { 57714 57715 var lineWidth = this._getLineWidth(ctx, textLines[i]); 57716 var lineLeftOffset = this._getLineLeftOffset(lineWidth); 57717 57718 this._boundaries.push({ 57719 height: this.fontSize * this.lineHeight, 57720 width: lineWidth, 57721 left: lineLeftOffset 57722 }); 57723 } 57724 }, 57725 57726 /** 57727 * @private 57728 * @param {CanvasRenderingContext2D} ctx Context to render on 57729 */ 57730 _setTextStyles: function(ctx) { 57731 if (this.fill) { 57732 ctx.fillStyle = this.fill.toLive 57733 ? this.fill.toLive(ctx) 57734 : this.fill; 57735 } 57736 if (this.stroke) { 57737 ctx.lineWidth = this.strokeWidth; 57738 ctx.lineCap = this.strokeLineCap; 57739 ctx.lineJoin = this.strokeLineJoin; 57740 ctx.miterLimit = this.strokeMiterLimit; 57741 ctx.strokeStyle = this.stroke.toLive 57742 ? this.stroke.toLive(ctx) 57743 : this.stroke; 57744 } 57745 ctx.textBaseline = 'alphabetic'; 57746 ctx.textAlign = this.textAlign; 57747 ctx.font = this._getFontDeclaration(); 57748 }, 57749 57750 /** 57751 * @private 57752 * @param {CanvasRenderingContext2D} ctx Context to render on 57753 * @param {Array} textLines Array of all text lines 57754 * @return {Number} Height of fabric.Text object 57755 */ 57756 _getTextHeight: function(ctx, textLines) { 57757 return this.fontSize * textLines.length * this.lineHeight; 57758 }, 57759 57760 /** 57761 * @private 57762 * @param {CanvasRenderingContext2D} ctx Context to render on 57763 * @param {Array} textLines Array of all text lines 57764 * @return {Number} Maximum width of fabric.Text object 57765 */ 57766 _getTextWidth: function(ctx, textLines) { 57767 var maxWidth = ctx.measureText(textLines[0]).width; 57768 57769 for (var i = 1, len = textLines.length; i < len; i++) { 57770 var currentLineWidth = ctx.measureText(textLines[i]).width; 57771 if (currentLineWidth > maxWidth) { 57772 maxWidth = currentLineWidth; 57773 } 57774 } 57775 return maxWidth; 57776 }, 57777 57778 /** 57779 * @private 57780 * @param {String} method Method name ("fillText" or "strokeText") 57781 * @param {CanvasRenderingContext2D} ctx Context to render on 57782 * @param {String} line Chars to render 57783 * @param {Number} left Left position of text 57784 * @param {Number} top Top position of text 57785 */ 57786 _drawChars: function(method, ctx, chars, left, top) { 57787 ctx[method](chars, left, top); 57788 }, 57789 57790 /** 57791 * @private 57792 * @param {String} method Method name ("fillText" or "strokeText") 57793 * @param {CanvasRenderingContext2D} ctx Context to render on 57794 * @param {String} line Text to render 57795 * @param {Number} left Left position of text 57796 * @param {Number} top Top position of text 57797 * @param {Number} lineIndex Index of a line in a text 57798 */ 57799 _drawTextLine: function(method, ctx, line, left, top, lineIndex) { 57800 // lift the line by quarter of fontSize 57801 top -= this.fontSize / 4; 57802 57803 // short-circuit 57804 if (this.textAlign !== 'justify') { 57805 this._drawChars(method, ctx, line, left, top, lineIndex); 57806 return; 57807 } 57808 57809 var lineWidth = ctx.measureText(line).width; 57810 var totalWidth = this.width; 57811 57812 if (totalWidth > lineWidth) { 57813 // stretch the line 57814 var words = line.split(/\s+/); 57815 var wordsWidth = ctx.measureText(line.replace(/\s+/g, '')).width; 57816 var widthDiff = totalWidth - wordsWidth; 57817 var numSpaces = words.length - 1; 57818 var spaceWidth = widthDiff / numSpaces; 57819 57820 var leftOffset = 0; 57821 for (var i = 0, len = words.length; i < len; i++) { 57822 this._drawChars(method, ctx, words[i], left + leftOffset, top, lineIndex); 57823 leftOffset += ctx.measureText(words[i]).width + spaceWi
57823dth; 57824 } 57825 } 57826 else { 57827 this._drawChars(method, ctx, line, left, top, lineIndex); 57828 } 57829 }, 57830 57831 /** 57832 * @private 57833 * @return {Number} Left offset 57834 */ 57835 _getLeftOffset: function() { 57836 if (fabric.isLikelyNode) { 57837 return 0; 57838 } 57839 return -this.width / 2; 57840 }, 57841 57842 /** 57843 * @private 57844 * @return {Number} Top offset 57845 */ 57846 _getTopOffset: function() { 57847 return -this.height / 2; 57848 }, 57849 57850 /** 57851 * @private 57852 * @param {CanvasRenderingContext2D} ctx Context to render on 57853 * @param {Array} textLines Array of all text lines 57854 */ 57855 _renderTextFill: function(ctx, textLines) { 57856 if (!this.fill && !this.skipFillStrokeCheck) return; 57857 57858 this._boundaries = [ ]; 57859 var lineHeights = 0; 57860 57861 for (var i = 0, len = textLines.length; i < len; i++) { 57862 var heightOfLine = this._getHeightOfLine(ctx, i, textLines); 57863 lineHeights += heightOfLine; 57864 57865 this._drawTextLine( 57866 'fillText', 57867 ctx, 57868 textLines[i], 57869 this._getLeftOffset(), 57870 this._getTopOffset() + lineHeights, 57871 i 57872 ); 57873 } 57874 }, 57875 57876 /** 57877 * @private 57878 * @param {CanvasRenderingContext2D} ctx Context to render on 57879 * @param {Array} textLines Array of all text lines 57880 */ 57881 _renderTextStroke: function(ctx, textLines) { 57882 if (!this.stroke && !this.skipFillStrokeCheck) return; 57883 57884 var lineHeights = 0; 57885 57886 ctx.save(); 57887 if (this.strokeDashArray) { 57888 // Spec requires the concatenation of two copies the dash list when the number of elements is odd 57889 if (1 & this.strokeDashArray.length) { 57890 this.strokeDashArray.push.apply(this.strokeDashArray, this.strokeDashArray); 57891 } 57892 supportsLineDash && ctx.setLineDash(this.strokeDashArray); 57893 } 57894 57895 ctx.beginPath(); 57896 for (var i = 0, len = textLines.length; i < len; i++) { 57897 var heightOfLine = this._getHeightOfLine(ctx, i, textLines); 57898 lineHeights += heightOfLine; 57899 57900 this._drawTextLine( 57901 'strokeText', 57902 ctx, 57903 textLines[i], 57904 this._getLeftOffset(), 57905 this._getTopOffset() + lineHeights, 57906 i 57907 ); 57908 } 57909 ctx.closePath(); 57910 ctx.restore(); 57911 }, 57912 57913 _getHeightOfLine: function() { 57914 return this.fontSize * this.lineHeight; 57915 }, 57916 57917 /** 57918 * @private 57919 * @param {CanvasRenderingContext2D} ctx Context to render on 57920 * @param {Array} textLines Array of all text lines 57921 */ 57922 _renderTextBackground: function(ctx, textLines) { 57923 this._renderTextBoxBackground(ctx); 57924 this._renderTextLinesBackground(ctx, textLines); 57925 }, 57926 57927 /** 57928 * @private 57929 * @param {CanvasRenderingContext2D} ctx Context to render on 57930 */ 57931 _renderTextBoxBackground: function(ctx) { 57932 if (!this.backgroundColor) return; 57933 57934 ctx.save(); 57935 ctx.fillStyle = this.backgroundColor; 57936 57937 ctx.fillRect( 57938 this._getLeftOffset(), 57939 this._getTopOffset(), 57940 this.width, 57941 this.height 57942 ); 57943 57944 ctx.restore(); 57945 }, 57946 57947 /** 57948 * @private 57949 * @param {CanvasRenderingContext2D} ctx Context to render on 57950 * @param {Array} textLines Array of all text lines 57951 */ 57952 _renderTextLinesBackground: function(ctx, textLines) { 57953 if (!this.textBackgroundColor) return; 57954 57955 ctx.save(); 57956 ctx.fillStyle = this.textBackgroundColor; 57957 57958 for (var i = 0, len = textLines.length; i < len; i++) { 57959 57960 if (textLines[i] !== '') { 57961 57962 var lineWidth = this._getLineWidth(ctx, textLines[i]); 57963 var lineLeftOffset = this._getLineLeftOffset(lineWidth); 57964 57965 ctx.fillRect( 57966 this._getLeftOffset() + lineLeftOffset, 57967 this._getTopOffset() + (i * this.fontSize * this.lineHeight), 57968 lineWidth, 57969 this.fontSize * this.lineHeight 57970 ); 57971 } 57972 } 57973 ctx.restore(); 57974 }, 57975 57976 /** 57977 * @private 57978 * @param {Number} lineWidth Width of text line 57979 * @return {Number} Line left offset 57980 */ 57981 _getLineLeftOffset: function(lineWidth) { 57982 if (this.textAlign === 'center') { 57983 return (this.width - lineWidth) / 2; 57984 } 57985 if (this.textAlign === 'right') { 57986 return this.width - lineWidth; 57987 } 57988 return 0; 57989 }, 57990 57991 /** 57992 * @private 57993 * @param {CanvasRenderingContext2D} ctx Context to render on 57994 * @param {String} line Text line 57995 * @return {Number} Line width 57996 */ 57997 _getLineWidth: function(ctx, line) { 57998 return this.textAlign === 'justify' 57999 ? this.width 58000 : ctx.measureText(line).width; 58001 }, 58002 58003 /** 58004 * @private 58005 * @param {CanvasRenderingContext2D} ctx Context to render on 58006 * @param {Array} textLines Array of all text lines 58007 */ 58008 _renderTextDecoration: function(ctx, textLines) { 58009 if (!this.textDecoration) return; 58010 58011 // var halfOfVerticalBox = this.originY === 'top' ? 0 : this._getTextHeight(ctx, textLines) / 2; 58012 var halfOfVerticalBox = this._getTextHeight(ctx, textLines) / 2; 58013 var _this = this; 58014 58015 /** @ignore */ 58016 function renderLinesAtOffset(offset) { 58017 for (var i = 0, len = textLines.length; i < len; i++) { 58018 58019 var lineWidth = _this._getLineWidth(ctx, textLines[i]); 58020 var lineLeftOffset = _this._getLineLeftOffset(lineWidth); 58021 58022 ctx.fillRect( 58023 _this._getLeftOffset() + lineLeftOffset, 58024 ~~((offset + (i * _this._getHeightOfLine(ctx, i, textLines))) - halfOfVerticalBox), 58025 lineWidth, 58026 1); 58027 } 58028 } 58029 58030 if (this.textDecoration.indexOf('underline') > -1) { 58031 renderLinesAtOffset(this.fontSize * this.lineHeight); 58032 } 58033 if (this.textDecoration.indexOf('line-through') > -1) { 58034 renderLinesAtOffset(this.fontSize * this.lineHeight - this.fontSize / 2); 58035 } 58036 if (this.textDecoration.indexOf('overline') > -1) { 58037 renderLinesAtOffset(this.fontSize * this.lineHeight - this.fontSize); 58038 } 58039 }, 58040 58041 /** 58042 * @private 58043 */ 58044 _getFontDeclaration: function() { 58045 return [ 58046 // node-canvas needs "weight style", while browsers need "style weight" 58047 (fabric.isLikelyNode ? this.fontWeight : this.fontStyle), 58048 (fabric.isLikelyNode ? this.fontStyle : this.fontWeight), 58049 this.fontSize + 'px', 58050 (fabric.isLikelyNode ? ('"' + this.fontFamily + '"') : this.fontFamily) 58051 ].join(' '); 58052 }, 58053 58054 /**
58055 * Renders text instance on a specified context 58056 * @param {CanvasRenderingContext2D} ctx Context to render on 58057 * @param {Boolean} [noTransform] When true, context is not transformed 58058 */ 58059 render: function(ctx, noTransform) { 58060 // do not render if object is not visible 58061 if (!this.visible) return; 58062 58063 ctx.save(); 58064 this._render(ctx); 58065 if (!noTransform && this.active) { 58066 this.drawBorders(ctx); 58067 this.drawControls(ctx); 58068 } 58069 ctx.restore(); 58070 }, 58071 58072 /** 58073 * Returns object representation of an instance 58074 * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output 58075 * @return {Object} Object representation of an instance 58076 */ 58077 toObject: function(propertiesToInclude) { 58078 var object = extend(this.callSuper('toObject', propertiesToInclude), { 58079 text: this.text, 58080 fontSize: this.fontSize, 58081 fontWeight: this.fontWeight, 58082 fontFamily: this.fontFamily, 58083 fontStyle: this.fontStyle, 58084 lineHeight: this.lineHeight, 58085 textDecoration: this.textDecoration, 58086 textAlign: this.textAlign, 58087 path: this.path, 58088 textBackgroundColor: this.textBackgroundColor, 58089 useNative: this.useNative 58090 }); 58091 if (!this.includeDefaultValues) { 58092 this._removeDefaultValues(object); 58093 } 58094 return object; 58095 }, 58096 58097 /* _TO_SVG_START_ */ 58098 /** 58099 * Returns SVG representation of an instance 58100 * @param {Function} [reviver] Method for further parsing of svg representation. 58101 * @return {String} svg representation of an instance 58102 */ 58103 toSVG: function(reviver) { 58104 var markup = [ ], 58105 textLines = this.text.split(/\r?\n/), 58106 lineTopOffset = this.useNative 58107 ? this.fontSize * this.lineHeight 58108 : (-this._fontAscent - ((this._fontAscent / 5) * this.lineHeight)), 58109 58110 textLeftOffset = -(this.width/2), 58111 textTopOffset = this.useNative 58112 ? this.fontSize - 1 58113 : (this.height/2) - (textLines.length * this.fontSize) - this._totalLineHeight, 58114 58115 textAndBg = this._getSVGTextAndBg(lineTopOffset, textLeftOffset, textLines), 58116 shadowSpans = this._getSVGShadows(lineTopOffset, textLines); 58117 58118 // move top offset by an ascent 58119 textTopOffset += (this._fontAscent ? ((this._fontAscent / 5) * this.lineHeight) : 0); 58120 58121 markup.push( 58122 '<g transform="', this.getSvgTransform(), '">', 58123 textAndBg.textBgRects.join(''), 58124 '<text ', 58125 (this.fontFamily ? 'font-family="' + this.fontFamily.replace(/"/g,'\'') + '" ': ''), 58126 (this.fontSize ? 'font-size="' + this.fontSize + '" ': ''), 58127 (this.fontStyle ? 'font-style="' + this.fontStyle + '" ': ''), 58128 (this.fontWeight ? 'font-weight="' + this.fontWeight + '" ': ''), 58129 (this.textDecoration ? 'text-decoration="' + this.textDecoration + '" ': ''), 58130 'style="', this.getSvgStyles(), '" ', 58131 /* svg starts from left/bottom corner so we normalize height */ 58132 'transform="translate(', toFixed(textLeftOffset, 2), ' ', toFixed(textTopOffset, 2), ')">', 58133 shadowSpans.join(''), 58134 textAndBg.textSpans.join(''), 58135 '</text>', 58136 '</g>' 58137 ); 58138 58139 return reviver ? reviver(markup.join('')) : markup.join(''); 58140 }, 58141 58142 /** 58143 * @private 58144 * @param {Number} lineTopOffset Line top offset 58145 * @param {Array} textLines Array of all text lines 58146 * @return {Array} 58147 */ 58148 _getSVGShadows: function(lineTopOffset, textLines) { 58149 var shadowSpans = [], 58150 i, len, 58151 lineTopOffsetMultiplier = 1; 58152 58153 if (!this.shadow || !this._boundaries) { 58154 return shadowSpans; 58155 } 58156 58157 for (i = 0, len = textLines.length; i < len; i++) { 58158 if (textLines[i] !== '') { 58159 var lineLeftOffset = (this._boundaries && this._boundaries[i]) ? this._boundaries[i].left : 0; 58160 shadowSpans.push( 58161 '<tspan x="', 58162 toFixed((lineLeftOffset + lineTopOffsetMultiplier) + this.shadow.offsetX, 2), 58163 ((i === 0 || this.useNative) ? '" y' : '" dy'), '="', 58164 toFixed(this.useNative 58165 ? ((lineTopOffset * i) - this.height / 2 + this.shadow.offsetY) 58166 : (lineTopOffset + (i === 0 ? this.shadow.offsetY : 0)), 2), 58167 '" ', 58168 this._getFillAttributes(this.shadow.color), '>', 58169 fabric.util.string.escapeXml(textLines[i]), 58170 '</tspan>'); 58171 lineTopOffsetMultiplier = 1; 58172 } else { 58173 // in some environments (e.g. IE 7 & 8) empty tspans are completely ignored, using a lineTopOffsetMultiplier 58174 // prevents empty tspans 58175 lineTopOffsetMultiplier++; 58176 } 58177 } 58178 58179 return shadowSpans; 58180 }, 58181 58182 /** 58183 * @private 58184 * @param {Number} lineTopOffset Line top offset 58185 * @param {Number} textLeftOffset Text left offset 58186 * @param {Array} textLines Array of all text lines 58187 * @return {Object} 58188 */ 58189 _getSVGTextAndBg: function(lineTopOffset, textLeftOffset, textLines) { 58190 var textSpans = [ ], textBgRects = [ ], i, lineLeftOffset, len, lineTopOffsetMultiplier = 1; 58191 58192 // bounding-box background 58193 if (this.backgroundColor && this._boundaries) { 58194 textBgRects.push( 58195 '<rect ', 58196 this._getFillAttributes(this.backgroundColor), 58197 ' x="', 58198 toFixed(-this.width / 2, 2), 58199 '" y="', 58200 toFixed(-this.height / 2, 2), 58201 '" width="', 58202 toFixed(this.width, 2), 58203 '" height="', 58204 toFixed(this.height, 2), 58205 '"></rect>'); 58206 } 58207 58208 // text and text-background 58209 for (i = 0, len = textLines.length; i < len; i++) { 58210 if (textLines[i] !== '') { 58211 lineLeftOffset = (this._boundaries && this._boundaries[i]) ? toFixed(this._boundaries[i].left, 2) : 0; 58212 textSpans.push( 58213 '<tspan x="', 58214 lineLeftOffset, '" ', 58215 (i === 0 || this.useNative ? 'y' : 'dy'), '="', 58216 toFixed(this.useNative ? ((lineTopOffset * i) - this.height / 2) : (lineTopOffset * lineTopOffsetMultiplier), 2) , '" ', 58217 // doing this on <tspan> elements since setting opacity on containing <text> one doesn't work in Illustrator 58218 this._getFillAttributes(this.fill), '>', 58219 fabric.util.string.escapeXml(textLines[i]), 58220 '</tspan>' 58221 ); 58222 lineTopOffsetMultiplier = 1; 58223 } 58224 else { 58225 // in some environments (e.g. IE 7 & 8) empty tspans are completely ignored, using a lineTopOffsetMultiplier 58226 // prevents empty tspans 58227 lineTopOffsetMultiplier++; 58228 } 58229
58230 if (!this.textBackgroundColor || !this._boundaries) continue; 58231 58232 textBgRects.push( 58233 '<rect ', 58234 this._getFillAttributes(this.textBackgroundColor), 58235 ' x="', 58236 toFixed(textLeftOffset + this._boundaries[i].left, 2), 58237 '" y="', 58238 /* an offset that seems to straighten things out */ 58239 toFixed((lineTopOffset * i) - this.height / 2, 2), 58240 '" width="', 58241 toFixed(this._boundaries[i].width, 2), 58242 '" height="', 58243 toFixed(this._boundaries[i].height, 2), 58244 '"></rect>'); 58245 } 58246 return { 58247 textSpans: textSpans, 58248 textBgRects: textBgRects 58249 }; 58250 }, 58251 58252 /** 58253 * Adobe Illustrator (at least CS5) is unable to render rgba()-based fill values 58254 * we work around it by "moving" alpha channel into opacity attribute and setting fill's alpha to 1 58255 * 58256 * @private 58257 * @param {Any} value 58258 * @return {String} 58259 */ 58260 _getFillAttributes: function(value) { 58261 var fillColor = (value && typeof value === 'string') ? new fabric.Color(value) : ''; 58262 if (!fillColor || !fillColor.getSource() || fillColor.getAlpha() === 1) { 58263 return 'fill="' + value + '"'; 58264 } 58265 return 'opacity="' + fillColor.getAlpha() + '" fill="' + fillColor.setAlpha(1).toRgb() + '"'; 58266 }, 58267 /* _TO_SVG_END_ */ 58268 58269 /** 58270 * Sets specified property to a specified value 58271 * @param {String} key 58272 * @param {Any} value 58273 * @return {fabric.Text} thisArg 58274 * @chainable 58275 */ 58276 _set: function(key, value) { 58277 if (key === 'fontFamily' && this.path) { 58278 this.path = this.path.replace(/(.*?)([^\/]*)(\.font\.js)/, '$1' + value + '$3'); 58279 } 58280 this.callSuper('_set', key, value); 58281 58282 if (key in this._dimensionAffectingProps) { 58283 this._initDimensions(); 58284 this.setCoords(); 58285 } 58286 }, 58287 58288 /** 58289 * Returns complexity of an instance 58290 * @return {Number} complexity 58291 */ 58292 complexity: function() { 58293 return 1; 58294 } 58295 }); 58296 58297 /* _FROM_SVG_START_ */ 58298 /** 58299 * List of attribute names to account for when parsing SVG element (used by {@link fabric.Text.fromElement}) 58300 * @static 58301 * @memberOf fabric.Text 58302 * @see: http://www.w3.org/TR/SVG/text.html#TextElement 58303 */ 58304 fabric.Text.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat( 58305 'x y font-family font-style font-weight font-size text-decoration'.split(' ')); 58306 58307 /** 58308 * Returns fabric.Text instance from an SVG element (<b>not yet implemented</b>) 58309 * @static 58310 * @memberOf fabric.Text 58311 * @param {SVGElement} element Element to parse 58312 * @param {Object} [options] Options object 58313 * @return {fabric.Text} Instance of fabric.Text 58314 */ 58315 fabric.Text.fromElement = function(element, options) { 58316 if (!element) { 58317 return null; 58318 } 58319 58320 var parsedAttributes = fabric.parseAttributes(element, fabric.Text.ATTRIBUTE_NAMES); 58321 options = fabric.util.object.extend((options ? fabric.util.object.clone(options) : { }), parsedAttributes); 58322 58323 var text = new fabric.Text(element.textContent, options); 58324 58325 /* 58326 Adjust positioning: 58327 x/y attributes in SVG correspond to the bottom-left corner of text bounding box 58328 top/left properties in Fabric correspond to center point of text bounding box 58329 */ 58330 58331 text.set({ 58332 left: text.getLeft() + text.getWidth() / 2, 58333 top: text.getTop() - text.getHeight() / 2 58334 }); 58335 58336 return text; 58337 }; 58338 /* _FROM_SVG_END_ */ 58339 58340 /** 58341 * Returns fabric.Text instance from an object representation 58342 * @static 58343 * @memberOf fabric.Text 58344 * @param object {Object} object Object to create an instance from 58345 * @return {fabric.Text} Instance of fabric.Text 58346 */ 58347 fabric.Text.fromObject = function(object) { 58348 return new fabric.Text(object.text, clone(object)); 58349 }; 58350 58351 fabric.util.createAccessors(fabric.Text); 58352 58353})(typeof exports !== 'undefined' ? exports : this); 58354 58355 58356/** 58357 * @private 58358 * @param {CanvasRenderingContext2D} ctx Context to render on 58359 */ 58360fabric.util.object.extend(fabric.Text.prototype, { 58361 _renderViaCufon: function(ctx) { 58362 58363 var o = Cufon.textOptions || (Cufon.textOptions = { }); 58364 58365 // export options to be used by cufon.js 58366 o.left = this.left; 58367 o.top = this.top; 58368 o.context = ctx; 58369 o.color = this.fill; 58370 58371 var el = this._initDummyElementForCufon(); 58372 58373 // set "cursor" to top/left corner 58374 this.transform(ctx); 58375 58376 // draw text 58377 Cufon.replaceElement(el, { 58378 engine: 'canvas', 58379 separate: 'none', 58380 fontFamily: this.fontFamily, 58381 fontWeight: this.fontWeight, 58382 textDecoration: this.textDecoration, 58383 textShadow: this.shadow && this.shadow.toString(), 58384 textAlign: this.textAlign, 58385 fontStyle: this.fontStyle, 58386 lineHeight: this.lineHeight, 58387 stroke: this.stroke, 58388 strokeWidth: this.strokeWidth, 58389 backgroundColor: this.backgroundColor,
58390 textBackgroundColor: this.textBackgroundColor 58391 }); 58392 58393 // update width, height 58394 this.width = o.width; 58395 this.height = o.height; 58396 58397 this._totalLineHeight = o.totalLineHeight; 58398 this._fontAscent = o.fontAscent; 58399 this._boundaries = o.boundaries; 58400 58401 el = null; 58402 58403 // need to set coords _after_ the width/height was retreived from Cufon 58404 this.setCoords(); 58405 }, 58406 58407 /** 58408 * @private 58409 */ 58410 _initDummyElementForCufon: function() { 58411 var el = fabric.document.createElement('pre'), 58412 container = fabric.document.createElement('div'); 58413 58414 // Cufon doesn't play nice with textDecoration=underline if element doesn't have a parent 58415 container.appendChild(el); 58416 58417 if (typeof G_vmlCanvasManager === 'undefined') { 58418 el.innerHTML = this.text; 58419 } 58420 else { 58421 // IE 7 & 8 drop newlines and white space on text nodes 58422 // see: http://web.student.tuwien.ac.at/~e0226430/innerHtmlQuirk.html 58423 // see: http://www.w3schools.com/dom/dom_mozilla_vs_ie.asp 58424 el.innerText = this.text.replace(/\r?\n/gi, '\r'); 58425 } 58426 58427 el.style.fontSize = this.fontSize + 'px'; 58428 el.style.letterSpacing = 'normal'; 58429 58430 return el; 58431 } 58432}); 58433 58434 58435(function() { 58436 58437 if (typeof document !== 'undefined' && typeof window !== 'undefined') { 58438 return; 58439 } 58440 58441 var DOMParser = new require('xmldom').DOMParser, 58442 URL = require('url'), 58443 HTTP = require('http'), 58444 HTTPS = require('https'), 58445 58446 Canvas = require('canvas'), 58447 Image = require('canvas').Image; 58448 58449 /** @private */ 58450 function request(url, encoding, callback) { 58451 var oURL = URL.parse(url); 58452 58453 // detect if http or https is used 58454 if ( !oURL.port ) { 58455 oURL.port = ( oURL.protocol.indexOf('https:') === 0 ) ? 443 : 80; 58456 } 58457 58458 // assign request handler based on protocol 58459 var reqHandler = ( oURL.port === 443 ) ? HTTPS : HTTP; 58460 58461 var req = reqHandler.request({ 58462 hostname: oURL.hostname, 58463 port: oURL.port, 58464 path: oURL.path, 58465 method: 'GET' 58466 }, function(response){ 58467 var body = ""; 58468 if (encoding) { 58469 response.setEncoding(encoding); 58470 } 58471 response.on('end', function () { 58472 callback(body); 58473 }); 58474 response.on('data', function (chunk) { 58475 if (response.statusCode === 200) { 58476 body += chunk; 58477 } 58478 }); 58479 }); 58480 58481 req.on('error', function(err) { 58482 if (err.errno === process.ECONNREFUSED) { 58483 fabric.log('ECONNREFUSED: connection refused to ' + oURL.hostname + ':' + oURL.port); 58484 } 58485 else { 58486 fabric.log(err.message); 58487 } 58488 }); 58489 58490 req.end(); 58491 } 58492 58493 /** @private */ 58494 function request_fs(path, callback){ 58495 var fs = require('fs'); 58496 fs.readFile(path, function (err, data) { 58497 if (err) { 58498 fabric.log(err); 58499 throw err; 58500 } else { 58501 callback(data); 58502 } 58503 }); 58504 } 58505 58506 fabric.util.loadImage = function(url, callback, context) { 58507 var createImageAndCallBack = function(data){ 58508 img.src = new Buffer(data, 'binary'); 58509 // preserving original url, which seems to be lost in node-canvas 58510 img._src = url; 58511 callback && callback.call(context, img); 58512 }; 58513 var img = new Image(); 58514 if (url && (url instanceof Buffer || url.indexOf('data') === 0)) { 58515 img.src = img._src = url; 58516 callback && callback.call(context, img); 58517 } 58518 else if (url && url.indexOf('http') !== 0) { 58519 request_fs(url, createImageAndCallBack); 58520 } 58521 else if (url) { 58522 request(url, 'binary', createImageAndCallBack); 58523 } 58524 }; 58525 58526 fabric.loadSVGFromURL = function(url, callback, reviver) { 58527 url = url.replace(/^\n\s*/, '').replace(/\?.*$/, '').trim(); 58528 if (url.indexOf('http') !== 0) { 58529 request_fs(url, function(body) { 58530 fabric.loadSVGFromString(body, callback, reviver); 58531 }); 58532 } 58533 else { 58534 request(url, '', function(body) { 58535 fabric.loadSVGFromString(body, callback, reviver); 58536 }); 58537 } 58538 }; 58539 58540 fabric.loadSVGFromString = function(string, callback, reviver) { 58541 var doc = new DOMParser().parseFromString(string); 58542 fabric.parseSVGDocument(doc.documentElement, function(results, options) { 58543 callback && callback(results, options); 58544 }, reviver); 58545 }; 58546 58547 fabric.util.getScript = function(url, callback) { 58548 request(url, '', function(body) { 58549 eval(body); 58550 callback && callback(); 58551 }); 58552 }; 58553 58554 fabric.Image.fromObject = function(object, callback) { 58555 fabric.util.loadImage(object.src, function(img) { 58556 var oImg = new fabric.Image(img); 58557 58558 oImg._initConfig(object); 58559 oImg._initFilters(object, function(filters) { 58560 oImg.filters = filters || [ ]; 58561 callback && callback(oImg); 58562 }); 58563 }); 58564 }; 58565 58566 /** 58567 * Only available when running fabric on node.js 58568 * @param width Canvas width 58569 * @param height Canvas height 58570 * @return {Object} wrapped canvas instance 58571 */ 58572 fabric.createCanvasForNode = function(width, height) { 58573 58574 var canvasEl = fabric.document.createElement('canvas'),
58575 nodeCanvas = new Canvas(width || 600, height || 600); 58576 58577 // jsdom doesn't create style on canvas element, so here be temp. workaround 58578 canvasEl.style = { }; 58579 58580 canvasEl.width = nodeCanvas.width; 58581 canvasEl.height = nodeCanvas.height; 58582 58583 var FabricCanvas = fabric.Canvas || fabric.StaticCanvas; 58584 var fabricCanvas = new FabricCanvas(canvasEl); 58585 fabricCanvas.contextContainer = nodeCanvas.getContext('2d'); 58586 fabricCanvas.nodeCanvas = nodeCanvas; 58587 fabricCanvas.Font = Canvas.Font; 58588 58589 return fabricCanvas; 58590 }; 58591 58592 /** @ignore */ 58593 fabric.StaticCanvas.prototype.createPNGStream = function() { 58594 return this.nodeCanvas.createPNGStream(); 58595 }; 58596 58597 fabric.StaticCanvas.prototype.createJPEGStream = function(opts) { 58598 return this.nodeCanvas.createJPEGStream(opts); 58599 }; 58600 58601 var origSetWidth = fabric.StaticCanvas.prototype.setWidth; 58602 fabric.StaticCanvas.prototype.setWidth = function(width) { 58603 origSetWidth.call(this, width); 58604 this.nodeCanvas.width = width; 58605 return this; 58606 }; 58607 if (fabric.Canvas) { 58608 fabric.Canvas.prototype.setWidth = fabric.StaticCanvas.prototype.setWidth; 58609 } 58610 58611 var origSetHeight = fabric.StaticCanvas.prototype.setHeight; 58612 fabric.StaticCanvas.prototype.setHeight = function(height) { 58613 origSetHeight.call(this, height); 58614 this.nodeCanvas.height = height; 58615 return this; 58616 }; 58617 if (fabric.Canvas) { 58618 fabric.Canvas.prototype.setHeight = fabric.StaticCanvas.prototype.setHeight; 58619 } 58620 58621})(); 58622 58623 58624define("fabric", function(){}); 58625 58626/*!! 58627 * Hasher <http://github.com/millermedeiros/hasher> 58628 * @author Miller Medeiros 58629 * @version 1.2.0 (2013/11/11 03:18 PM) 58630 * Released under the MIT License 58631 */ 58632 58633;(function () { 58634var factory = function(signals){ 58635 58636/*jshint white:false*/ 58637/*global signals:false, window:false*/ 58638 58639/** 58640 * Hasher 58641 * @namespace History Manager for rich-media applications. 58642 * @name hasher 58643 */ 58644var hasher = (function(window){ 58645 58646 //-------------------------------------------------------------------------------------- 58647 // Private Vars 58648 //-------------------------------------------------------------------------------------- 58649 58650 var 58651 58652 // frequency that it will check hash value on IE 6-7 since it doesn't 58653 // support the hashchange event 58654 POOL_INTERVAL = 25, 58655 58656 // local storage for brevity and better compression -------------------------------- 58657 58658 document = window.document, 58659 history = window.history, 58660 Signal = signals.Signal, 58661 58662 // local vars ---------------------------------------------------------------------- 58663 58664 hasher, 58665 _hash, 58666 _checkInterval, 58667 _isActive, 58668 _frame, //iframe used for legacy IE (6-7) 58669 _checkHistory, 58670 _hashValRegexp = /#(.*)$/, 58671 _baseUrlRegexp = /(\?.*)|(\#.*)/, 58672 _hashRegexp = /^\#/, 58673 58674 // sniffing/feature detection ------------------------------------------------------- 58675 58676 //hack based on this: http://webreflection.blogspot.com/2009/01/32-bytes-to-know-if-your-browser-is-ie.html 58677 _isIE = (!+"\v1"), 58678 // hashchange is supported by FF3.6+, IE8+, Chrome 5+, Safari 5+ but 58679 // feature detection fails on IE compatibility mode, so we need to 58680 // check documentMode 58681 _isHashChangeSupported = ('onhashchange' in window) && document.documentMode !== 7, 58682 //check if is IE6-7 since hash change is only supported on IE8+ and 58683 //changing hash value on IE6-7 doesn't generate history record. 58684 _isLegacyIE = _isIE && !_isHashChangeSupported, 58685 _isLocal = (location.protocol === 'file:'); 58686 58687 58688 //-------------------------------------------------------------------------------------- 58689 // Private Methods 58690 //-------------------------------------------------------------------------------------- 58691 58692 function _escapeRegExp(str){ 58693 return String(str || '').replace(/\W/g, "\\$&"); 58694 } 58695 58696 function _trimHash(hash){ 58697 if (!hash) return ''; 58698 var regexp = new RegExp('^' + _escapeRegExp(hasher.prependHash) + '|' + _escapeRegExp(hasher.appendHash) + '$', 'g'); 58699 return hash.replace(regexp, ''); 58700 } 58701 58702 function _getWindowHash(){ 58703 //parsed full URL instead of getting window.location.hash because Firefox decode hash value (and all the other browsers don't) 58704 //also because of IE8 bug with hash query in local file [issue #6] 58705 var result = _hashValRegexp.exec( hasher.getURL() ); 58706 var path = (result && result[1]) || ''; 58707 try { 58708 return hasher.raw? path : decodeURIComponent(path); 58709 } catch (e) { 58710 // in case user did not set `hasher.raw` and decodeURIComponent 58711 // throws an error (see #57) 58712 return path; 58713 } 58714 } 58715 58716 function _getFrameHash(){ 58717 return (_frame)? _frame.contentWindow.frameHash : null; 58718 } 58719 58720 function _createFrame(){ 58721 _frame = document.createElement('iframe'); 58722 _frame.src = 'about:blank'; 58723 _frame.style.display = 'none'; 58724 document.body.appendChild(_frame); 58725 } 58726 58727 function _updateFrame(){ 58728 if(_frame && _hash !== _getFrameHash()){ 58729 var frameDoc = _frame.contentWindow.document; 58730 frameDoc.open(); 58731 //update iframe content to force new history record. 58732 //based on Really Simple History, SWFAddress and YUI.history. 58733 frameDoc.write('<html><head><title>' + document.title + '</title><script type="text/javascript">var frameHash="' + _hash + '";</script></head><body> </body></html>'); 58734 frameDoc.close(); 58735 } 58736 } 58737 58738 function _registerChange(newHash, isReplace){ 58739 if(_hash !== newHash){ 58740 var oldHash = _hash; 58741 _hash = newHash; //should come before event dispatch to make sure user can get proper value inside event handler 58742 if(_isLegacyIE){ 58743 if(!isReplace){ 58744 _updateFrame(); 58745 } else { 58746 _frame.contentWindow.frameHash = newHash; 58747 } 58748 } 58749 hasher.changed.dispatch(_trimHash(newHash), _trimHash(oldHash)); 58750 } 58751 } 58752 58753 if (_isLegacyIE) { 58754 /** 58755 * @private 58756 */ 58757 _checkHistory = function(){ 58758 var windowHash = _getWindowHash(), 58759 frameHash = _getFrameHash(); 58760 if(frameHash !== _hash && frameHash !== windowHash){ 58761 //detect changes made pressing browser history buttons. 58762 //Workaround since history.back() and history.forward() doesn't 58763 //update hash value on IE6/7 but updates content of the iframe. 58764 //needs to trim hash since value stored already have 58765 //prependHash + appendHash for fast check. 58766 hasher.setHash(_trimHash(frameHash)); 58767 } else if (windowHash !== _hash){ 58768 //detect if hash changed (manually or using setHash) 58769 _registerChange(windowHash); 58770 } 58771 }; 58772 } else { 58773 /** 58774 * @private 58775 */ 58776 _checkHistory = function(){ 58777 var windowHash = _getWindowHash(); 58778 if(windowHash !== _hash){ 58779 _registerChange(windowHash); 58780 } 58781 }; 58782 } 58783
58784 function _addListener(elm, eType, fn){ 58785 if(elm.addEventListener){ 58786 elm.addEventListener(eType, fn, false); 58787 } else if (elm.attachEvent){ 58788 elm.attachEvent('on' + eType, fn); 58789 } 58790 } 58791 58792 function _removeListener(elm, eType, fn){ 58793 if(elm.removeEventListener){ 58794 elm.removeEventListener(eType, fn, false); 58795 } else if (elm.detachEvent){ 58796 elm.detachEvent('on' + eType, fn); 58797 } 58798 } 58799 58800 function _makePath(paths){ 58801 paths = Array.prototype.slice.call(arguments); 58802 58803 var path = paths.join(hasher.separator); 58804 path = path? hasher.prependHash + path.replace(_hashRegexp, '') + hasher.appendHash : path; 58805 return path; 58806 } 58807 58808 function _encodePath(path){ 58809 //used encodeURI instead of encodeURIComponent to preserve '?', '/', 58810 //'#'. Fixes Safari bug [issue #8] 58811 path = encodeURI(path); 58812 if(_isIE && _isLocal){ 58813 //fix IE8 local file bug [issue #6] 58814 path = path.replace(/\?/, '%3F'); 58815 } 58816 return path; 58817 } 58818 58819 //-------------------------------------------------------------------------------------- 58820 // Public (API) 58821 //-------------------------------------------------------------------------------------- 58822 58823 hasher = /** @lends hasher */ { 58824 58825 /** 58826 * hasher Version Number 58827 * @type string 58828 * @constant 58829 */ 58830 VERSION : '1.2.0', 58831 58832 /** 58833 * Boolean deciding if hasher encodes/decodes the hash or not. 58834 * <ul> 58835 * <li>default value: false;</li> 58836 * </ul> 58837 * @type boolean 58838 */ 58839 raw : false, 58840 58841 /** 58842 * String that should always be added to the end of Hash value. 58843 * <ul> 58844 * <li>default value: '';</li> 58845 * <li>will be automatically removed from `hasher.getHash()`</li> 58846 * <li>avoid conflicts with elements that contain ID equal to hash value;</li> 58847 * </ul> 58848 * @type string 58849 */ 58850 appendHash : '', 58851 58852 /** 58853 * String that should always be added to the beginning of Hash value. 58854 * <ul> 58855 * <li>default value: '/';</li> 58856 * <li>will be automatically removed from `hasher.getHash()`</li> 58857 * <li>avoid conflicts with elements that contain ID equal to hash value;</li> 58858 * </ul> 58859 * @type string 58860 */ 58861 prependHash : '/', 58862 58863 /** 58864 * String used to split hash paths; used by `hasher.getHashAsArray()` to split paths. 58865 * <ul> 58866 * <li>default value: '/';</li> 58867 * </ul> 58868 * @type string 58869 */ 58870 separator : '/', 58871 58872 /** 58873 * Signal dispatched when hash value changes. 58874 * - pass current hash as 1st parameter to listeners and previous hash value as 2nd parameter. 58875 * @type signals.Signal 58876 */ 58877 changed : new Signal(), 58878 58879 /** 58880 * Signal dispatched when hasher is stopped. 58881 * - pass current hash as first parameter to listeners 58882 * @type signals.Signal 58883 */ 58884 stopped : new Signal(), 58885 58886 /** 58887 * Signal dispatched when hasher is initialized. 58888 * - pass current hash as first parameter to listeners. 58889 * @type signals.Signal 58890 */ 58891 initialized : new Signal(), 58892 58893 /** 58894 * Start listening/dispatching changes in the hash/history. 58895 * <ul> 58896 * <li>hasher won't dispatch CHANGE events by manually typing a new value or pressing the back/forward buttons before calling this method.</li> 58897 * </ul> 58898 */ 58899 init : function(){ 58900 if(_isActive) return; 58901 58902 _hash = _getWindowHash(); 58903 58904 //thought about branching/overloading hasher.init() to avoid checking multiple times but 58905 //don't think worth doing it since it probably won't be called multiple times. 58906 if(_isHashChangeSupported){ 58907 _addListener(window, 'hashchange', _checkHistory); 58908 }else { 58909 if(_isLegacyIE){ 58910 if(! _frame){ 58911 _createFrame(); 58912 } 58913 _updateFrame(); 58914 } 58915 _checkInterval = setInterval(_checkHistory, POOL_INTERVAL); 58916 } 58917 58918 _isActive = true; 58919 hasher.initialized.dispatch(_trimHash(_hash)); 58920 }, 58921 58922 /** 58923 * Stop listening/dispatching changes in the hash/history. 58924 * <ul> 58925 * <li>hasher won't dispatch CHANGE events by manually typing a new value or pressing the back/forward buttons after calling this method, unless you call hasher.init() again.</li> 58926 * <li>hasher will still dispatch changes made programatically by calling hasher.setHash();</li> 58927 * </ul> 58928 */ 58929 stop : function(){ 58930 if(! _isActive) return; 58931 58932 if(_isHashChangeSupported){ 58933 _removeListener(window, 'hashchange', _checkHistory); 58934 }else{ 58935 clearInterval(_checkInterval); 58936 _checkInterval = null; 58937 } 58938 58939 _isActive = false;
58940 hasher.stopped.dispatch(_trimHash(_hash)); 58941 }, 58942 58943 /** 58944 * @return {boolean} If hasher is listening to changes on the browser history and/or hash value. 58945 */ 58946 isActive : function(){ 58947 return _isActive; 58948 }, 58949 58950 /** 58951 * @return {string} Full URL. 58952 */ 58953 getURL : function(){ 58954 return window.location.href; 58955 }, 58956 58957 /** 58958 * @return {string} Retrieve URL without query string and hash. 58959 */ 58960 getBaseURL : function(){ 58961 return hasher.getURL().replace(_baseUrlRegexp, ''); //removes everything after '?' and/or '#' 58962 }, 58963 58964 /** 58965 * Set Hash value, generating a new history record. 58966 * @param {...string} path Hash value without '#'. Hasher will join 58967 * path segments using `hasher.separator` and prepend/append hash value 58968 * with `hasher.appendHash` and `hasher.prependHash` 58969 * @example hasher.setHash('lorem', 'ipsum', 'dolor') -> '#/lorem/ipsum/dolor' 58970 */ 58971 setHash : function(path){ 58972 path = _makePath.apply(null, arguments); 58973 if(path !== _hash){ 58974 // we should store raw value 58975 _registerChange(path); 58976 if (path === _hash) { 58977 // we check if path is still === _hash to avoid error in 58978 // case of multiple consecutive redirects [issue #39] 58979 if (! hasher.raw) { 58980 path = _encodePath(path); 58981 } 58982 window.location.hash = '#' + path; 58983 } 58984 } 58985 }, 58986 58987 /** 58988 * Set Hash value without keeping previous hash on the history record. 58989 * Similar to calling `window.location.replace("#/hash")` but will also work on IE6-7. 58990 * @param {...string} path Hash value without '#'. Hasher will join 58991 * path segments using `hasher.separator` and prepend/append hash value 58992 * with `hasher.appendHash` and `hasher.prependHash` 58993 * @example hasher.replaceHash('lorem', 'ipsum', 'dolor') -> '#/lorem/ipsum/dolor' 58994 */ 58995 replaceHash : function(path){ 58996 path = _makePath.apply(null, arguments); 58997 if(path !== _hash){ 58998 // we should store raw value 58999 _registerChange(path, true); 59000 if (path === _hash) { 59001 // we check if path is still === _hash to avoid error in 59002 // case of multiple consecutive redirects [issue #39] 59003 if (! hasher.raw) { 59004 path = _encodePath(path); 59005 } 59006 window.location.replace('#' + path); 59007 } 59008 } 59009 }, 59010 59011 /** 59012 * @return {string} Hash value without '#', `hasher.appendHash` and `hasher.prependHash`. 59013 */ 59014 getHash : function(){ 59015 //didn't used actual value of the `window.location.hash` to avoid breaking the application in case `window.location.hash` isn't available and also because value should always be synched. 59016 return _trimHash(_hash); 59017 }, 59018 59019 /** 59020 * @return {Array.<string>} Hash value split into an Array. 59021 */ 59022 getHashAsArray : function(){ 59023 return hasher.getHash().split(hasher.separator); 59024 }, 59025 59026 /** 59027 * Removes all event listeners, stops hasher and destroy hasher object. 59028 * - IMPORTANT: hasher won't work after calling this method, hasher Object will be deleted. 59029 */ 59030 dispose : function(){ 59031 hasher.stop(); 59032 hasher.initialized.dispose(); 59033 hasher.stopped.dispose(); 59034 hasher.changed.dispose(); 59035 _frame = hasher = window.hasher = null; 59036 }, 59037 59038 /** 59039 * @return {string} A string representation of the object. 59040 */ 59041 toString : function(){ 59042 return '[hasher version="'+ hasher.VERSION +'" hash="'+ hasher.getHash() +'"]'; 59043 } 59044 59045 }; 59046 59047 hasher.initialized.memorize = true; //see #33 59048 59049 return hasher; 59050 59051}(window)); 59052 59053 59054 return hasher; 59055}; 59056 59057if (typeof define === 'function' && define.amd) { 59058 define('hasher',['signals'], factory); 59059} else if (typeof exports === 'object') { 59060 module.exports = factory(require('signals')); 59061} else { 59062 /*jshint sub:true */ 59063 window['hasher'] = factory(window['signals']); 59064} 59065 59066}()); 59067 59068/*! 59069 * iCheck v1.0.3, http://git.io/arlzeA 59070 * =================================== 59071 * Powerful jQuery and Zepto plugin for checkboxes and radio buttons customization 59072 * 59073 * (c) 2013 Damir Sultanov, http://fronteed.com 59074 * MIT Licensed 59075 */ 59076 59077(function($) { 59078 59079 // Cached vars 59080 var _iCheck = 'iCheck', 59081 _iCheckHelper = _iCheck + '-helper', 59082 _checkbox = 'checkbox', 59083 _radio = 'radio', 59084 _checked = 'checked', 59085 _unchecked = 'un' + _checked, 59086 _disabled = 'disabled', 59087 _determinate = 'determinate',
vendor: 15,628 bytes, lines 59088-59609
59088 _indeterminate = 'in' + _determinate, 59089 _update = 'update', 59090 _type = 'type', 59091 _click = 'click', 59092 _touch = 'touchbegin.i touchend.i', 59093 _add = 'addClass', 59094 _remove = 'removeClass', 59095 _callback = 'trigger', 59096 _label = 'label', 59097 _cursor = 'cursor', 59098 _mobile = /ip(hone|od|ad)|android|blackberry|windows phone|opera mini|silk/i.test(navigator.userAgent) || (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1); 59099 59100 // Plugin init 59101 $.fn[_iCheck] = function(options, fire) { 59102 59103 // Walker 59104 var handle = 'input[type="' + _checkbox + '"], input[type="' + _radio + '"]', 59105 stack = $(), 59106 walker = function(object) { 59107 object.each(function() { 59108 var self = $(this); 59109 59110 if (self.is(handle)) { 59111 stack = stack.add(self); 59112 } else { 59113 stack = stack.add(self.find(handle)); 59114 } 59115 }); 59116 }; 59117 59118 // Check if we should operate with some method 59119 if (/^(check|uncheck|toggle|indeterminate|determinate|disable|enable|update|destroy)$/i.test(options)) { 59120 59121 // Normalize method's name 59122 options = options.toLowerCase(); 59123 59124 // Find checkboxes and radio buttons 59125 walker(this); 59126 59127 return stack.each(function() { 59128 var self = $(this); 59129 59130 if (options == 'destroy') { 59131 tidy(self, 'ifDestroyed'); 59132 } else { 59133 operate(self, true, options); 59134 } 59135 59136 // Fire method's callback 59137 if ($.isFunction(fire)) { 59138 fire(); 59139 } 59140 }); 59141 59142 // Customization 59143 } else if (typeof options == 'object' || !options) { 59144 59145 // Check if any options were passed 59146 var settings = $.extend({ 59147 checkedClass: _checked, 59148 disabledClass: _disabled, 59149 indeterminateClass: _indeterminate, 59150 labelHover: true 59151 }, options), 59152 59153 selector = settings.handle, 59154 hoverClass = settings.hoverClass || 'hover', 59155 focusClass = settings.focusClass || 'focus', 59156 activeClass = settings.activeClass || 'active', 59157 labelHover = !!settings.labelHover, 59158 labelHoverClass = settings.labelHoverClass || 'hover', 59159 59160 // Setup clickable area 59161 area = ('' + settings.increaseArea).replace('%', '') | 0; 59162 59163 // Selector limit 59164 if (selector == _checkbox || selector == _radio) { 59165 handle = 'input[type="' + selector + '"]'; 59166 } 59167 59168 // Clickable area limit 59169 if (area < -50) { 59170 area = -50; 59171 } 59172 59173 // Walk around the selector 59174 walker(this); 59175 59176 return stack.each(function() { 59177 var self = $(this); 59178 59179 // If already customized 59180 tidy(self); 59181 59182 var node = this, 59183 id = node.id, 59184 59185 // Layer styles 59186 offset = -area + '%', 59187 size = 100 + (area * 2) + '%', 59188 layer = { 59189 position: 'absolute', 59190 top: offset, 59191 left: offset, 59192 display: 'block', 59193 width: size, 59194 height: size, 59195 margin: 0, 59196 padding: 0, 59197 background: '#fff', 59198 border: 0, 59199 opacity: 0 59200 }, 59201 59202 // Choose how to hide input 59203 hide = _mobile ? { 59204 position: 'absolute', 59205 visibility: 'hidden' 59206 } : area ? layer : { 59207 position: 'absolute', 59208 opacity: 0 59209 }, 59210 59211 // Get proper class 59212 className = node[_type] == _checkbox ? settings.checkboxClass || 'i' + _checkbox : settings.radioClass || 'i' + _radio, 59213 59214 // Find assigned labels 59215 label = $(_label + '[for="' + id + '"]').add(self.closest(_label)), 59216 59217 // Check ARIA option 59218 aria = !!settings.aria, 59219 59220 // Set ARIA placeholder 59221 ariaID = _iCheck + '-' + Math.random().toString(36).substr(2,6), 59222 59223 // Parent & helper 59224 parent = '<div class="' + className + '" ' + (aria ? 'role="' + node[_type] + '" ' : ''), 59225 helper; 59226 59227 // Set ARIA "labelledby" 59228 if (aria) { 59229 label.each(function() { 59230 parent += 'aria-labelledby="'; 59231 59232 if (this.id) { 59233 parent += this.id; 59234 } else { 59235 this.id = ariaID; 59236 parent += ariaID; 59237 } 59238 59239 parent += '"'; 59240 }); 59241 } 59242 59243 // Wrap input 59244 parent = self.wrap(parent + '/>')[_callback]('ifCreated').parent().append(settings.insert); 59245 59246 // Layer addition 59247 helper = $('<ins class="' + _iCheckHelper + '"/>').css(layer).appendTo(parent); 59248 59249 // Finalize customization 59250 self.data(_iCheck, {o: settings, s: self.attr('style')}).css(hide); 59251 !!settings.inheritClass && parent[_add](node.className || ''); 59252 !!settings.inheritID && id && parent.attr('id', _iCheck + '-' + id); 59253 parent.css('position') == 'static' && parent.css('position', 'relative'); 59254 operate(self, true, _update); 59255 59256 // Label events 59257 if (label.length) { 59258 label.on(_click + '.i mouseover.i mouseout.i ' + _touch, function(event) { 59259 var type = event[_type], 59260 item = $(this); 59261 59262 // Do nothing if input is disabled 59263 if (!node[_disabled]) { 59264 59265 // Click 59266 if (type == _click) { 59267 if ($(event.target).is('a')) { 59268 return; 59269 } 59270 operate(self, false, true); 59271 59272 // Hover state 59273 } else if (labelHover) { 59274 59275 // mouseout|touchend 59276 if (/ut|nd/.test(type)) { 59277 parent[_remove](hoverClass); 59278 item[_remove](labelHoverClass); 59279 } else { 59280 parent[_add](hoverClass); 59281 item[_add](labelHoverClass); 59282 } 59283 } 59284 59285 if (_mobile) { 59286 event.stopPropagation(); 59287 } else { 59288 return false; 59289 } 59290 } 59291 }); 59292 } 59293 59294 // Input events 59295 self.on(_click + '.i focus.i blur.i keyup.i keydown.i keypress.i', function(event) { 59296 var type = event[_type], 59297 key = event.keyCode; 59298 59299 // Click 59300 if (type == _click) { 59301 return false; 59302 59303 // Keydown 59304 } else if (type == 'keydown' && key == 32) { 59305 if (!(node[_type] == _radio && node[_checked])) { 59306 if (node[_checked]) { 59307 off(self, _checked); 59308 } else { 59309 on(self, _checked); 59310 } 59311 } 59312 59313 return false; 59314 59315 // Keyup 59316 } else if (type == 'keyup' && node[_type] == _radio) { 59317 !node[_checked] && on(self, _checked); 59318 59319 // Focus/blur 59320 } else if (/us|ur/.test(type)) { 59321 parent[type == 'blur' ? _remove : _add](focusClass); 59322 } 59323 }); 59324 59325 // Helper events 59326 helper.on(_click + ' mousedown mouseup mouseover mouseout ' + _touch, function(event) { 59327 var type = event[_type], 59328 59329 // mousedown|mouseup 59330 toggle = /wn|up/.test(type) ? activeClass : hoverClass; 59331 59332 // Do nothing if input is disabled 59333 if (!node[_disabled]) { 59334 59335 // Click 59336 if (type == _click) { 59337 operate(self, false, true); 59338 59339 // Active and hover states 59340 } else { 59341 59342 // State is on 59343 if (/wn|er|in/.test(type)) { 59344 59345 // mousedown|mouseover|touchbegin 59346 parent[_add](toggle); 59347 59348 // State is off 59349 } else { 59350 parent[_remove](toggle + ' ' + activeClass); 59351 } 59352 59353 // Label hover 59354 if (label.length && labelHover && toggle == hoverClass) { 59355 59356 // mouseout|touchend 59357 label[/ut|nd/.test(type) ? _remove : _add](labelHoverClass); 59358 } 59359 } 59360 59361 if (_mobile) { 59362 event.stopPropagation(); 59363 } else { 59364 return false; 59365 } 59366 } 59367 }); 59368 }); 59369 } else { 59370 return this; 59371 } 59372 }; 59373 59374 // Do something with inputs 59375 function operate(input, direct, method) { 59376 var node = input[0], 59377 state = /er/.test(method) ? _indeterminate : /bl/.test(method) ? _disabled : _checked, 59378 active = method == _update ? { 59379 checked: node[_checked], 59380 disabled: node[_disabled], 59381 indeterminate: input.attr(_indeterminate) == 'true' || input.attr(_determinate) == 'false' 59382 } : node[state]; 59383 59384 // Check, disable or indeterminate 59385 if (/^(ch|di|in)/.test(method) && !active) { 59386 on(input, state); 59387 59388 // Uncheck, enable or determinate 59389 } else if (/^(un|en|de)/.test(method) && active) { 59390 off(input, state); 59391 59392 // Update 59393 } else if (method == _update) { 59394 59395 // Handle states 59396 for (var each in active) { 59397 if (active[each]) { 59398 on(input, each, true); 59399 } else { 59400 off(input, each, true); 59401 } 59402 } 59403 59404 } else if (!direct || method == 'toggle') { 59405 59406 // Helper or label was clicked 59407 if (!direct) { 59408 input[_callback]('ifClicked'); 59409 } 59410 59411 // Toggle checked state 59412 if (active) { 59413 if (node[_type] !== _radio) { 59414 off(input, state); 59415 } 59416 } else { 59417 on(input, state); 59418 } 59419 } 59420 } 59421 59422 // Add checked, disabled or indeterminate state 59423 function on(input, state, keep) { 59424 var node = input[0], 59425 parent = input.parent(), 59426 checked = state == _checked, 59427 indeterminate = state == _indeterminate, 59428 disabled = state == _disabled, 59429 callback = indeterminate ? _determinate : checked ? _unchecked : 'enabled', 59430 regular = option(input, callback + capitalize(node[_type])), 59431 specific = option(input, state + capitalize(node[_type])); 59432 59433 // Prevent unnecessary actions 59434 if (node[state] !== true) { 59435 59436 // Toggle assigned radio buttons 59437 if (!keep && state == _checked && node[_type] == _radio && node.name) { 59438 var form = input.closest('form'), 59439 inputs = 'input[name="' + node.name + '"]'; 59440 59441 inputs = form.length ? form.find(inputs) : $(inputs); 59442 59443 inputs.each(function() { 59444 if (this !== node && $(this).data(_iCheck)) { 59445 off($(this), state); 59446 } 59447 }); 59448 } 59449 59450 // Indeterminate state 59451 if (indeterminate) { 59452 59453 // Add indeterminate state 59454 node[state] = true; 59455 59456 // Remove checked state 59457 if (node[_checked]) { 59458 off(input, _checked, 'force'); 59459 } 59460 59461 // Checked or disabled state 59462 } else { 59463 59464 // Add checked or disabled state 59465 if (!keep) { 59466 node[state] = true; 59467 } 59468 59469 // Remove indeterminate state 59470 if (checked && node[_indeterminate]) { 59471 off(input, _indeterminate, false); 59472 } 59473 } 59474 59475 // Trigger callbacks 59476 callbacks(input, checked, state, keep); 59477 } 59478 59479 // Add proper cursor 59480 if (node[_disabled] && !!option(input, _cursor, true)) { 59481 parent.find('.' + _iCheckHelper).css(_cursor, 'default'); 59482 } 59483 59484 // Add state class 59485 parent[_add](specific || option(input, state) || ''); 59486 59487 // Set ARIA attribute 59488 if (!!parent.attr('role') && !indeterminate) { 59489 parent.attr('aria-' + (disabled ? _disabled : _checked), 'true'); 59490 } 59491 59492 // Remove regular state class 59493 parent[_remove](regular || option(input, callback) || ''); 59494 } 59495 59496 // Remove checked, disabled or indeterminate state 59497 function off(input, state, keep) { 59498 var node = input[0], 59499 parent = input.parent(), 59500 checked = state == _checked, 59501 indeterminate = state == _indeterminate, 59502 disabled = state == _disabled, 59503 callback = indeterminate ? _determinate : checked ? _unchecked : 'enabled', 59504 regular = option(input, callback + capitalize(node[_type])), 59505 specific = option(input, state + capitalize(node[_type])); 59506 59507 // Prevent unnecessary actions 59508 if (node[state] !== false) { 59509 59510 // Toggle state 59511 if (indeterminate || !keep || keep == 'force') { 59512 node[state] = false; 59513 } 59514 59515 // Trigger callbacks 59516 callbacks(input, checked, callback, keep); 59517 } 59518 59519 // Add proper cursor 59520 if (!node[_disabled] && !!option(input, _cursor, true)) { 59521 parent.find('.' + _iCheckHelper).css(_cursor, 'pointer'); 59522 } 59523 59524 // Remove state class 59525 parent[_remove](specific || option(input, state) || ''); 59526 59527 // Set ARIA attribute 59528 if (!!parent.attr('role') && !indeterminate) { 59529 parent.attr('aria-' + (disabled ? _disabled : _checked), 'false'); 59530 } 59531 59532 // Add regular state class 59533 parent[_add](regular || option(input, callback) || ''); 59534 } 59535 59536 // Remove all traces 59537 function tidy(input, callback) { 59538 if (input.data(_iCheck)) { 59539 59540 // Remove everything except input 59541 input.parent().html(input.attr('style', input.data(_iCheck).s || '')); 59542 59543 // Callback 59544 if (callback) { 59545 input[_callback](callback); 59546 } 59547 59548 // Unbind events 59549 input.off('.i').unwrap(); 59550 $(_label + '[for="' + input[0].id + '"]').add(input.closest(_label)).off('.i'); 59551 } 59552 } 59553 59554 // Get some option 59555 function option(input, state, regular) { 59556 if (input.data(_iCheck)) { 59557 return input.data(_iCheck).o[state + (regular ? '' : 'Class')]; 59558 } 59559 } 59560 59561 // Capitalize some string 59562 function capitalize(string) { 59563 return string.charAt(0).toUpperCase() + string.slice(1); 59564 } 59565 59566 // Executable handlers 59567 function callbacks(input, checked, callback, keep) { 59568 if (!keep) { 59569 if (checked) { 59570 input[_callback]('ifToggled'); 59571 } 59572 59573 input[_callback]('change')[_callback]('ifChanged')[_callback]('if' + capitalize(callback)); 59574 } 59575 } 59576})(window.jQuery || window.Zepto); 59577 59578define("icheck", function(){}); 59579 59580/** 59581 * isMobile.js v0.4.1 59582 * 59583 * A simple library to detect Apple phones and tablets, 59584 * Android phones and tablets, other mobile devices (like blackberry, mini-opera and windows phone), 59585 * and any kind of seven inch device, via user agent sniffing. 59586 * 59587 * @author: Kai Mallea ([email protected]) 59588 * 59589 * @license: http://creativecommons.org/publicdomain/zero/1.0/ 59590 */ 59591(function (global) { 59592 59593 var apple_phone = /iPhone/i, 59594 apple_ipod = /iPod/i, 59595 apple_tablet = /iPad/i, 59596 android_phone = /(?=.*\bAndroid\b)(?=.*\bMobile\b)/i, // Match 'Android' AND 'Mobile' 59597 android_tablet = /Android/i, 59598 amazon_phone = /(?=.*\bAndroid\b)(?=.*\bSD4930UR\b)/i, 59599 amazon_tablet = /(?=.*\bAndroid\b)(?=.*\b(?:KFOT|KFTT|KFJWI|KFJWA|KFSOWI|KFTHWI|KFTHWA|KFAPWI|KFAPWA|KFARWI|KFASWI|KFSAWI|KFSAWA)\b)/i, 59600 windows_phone = /Windows Phone/i, 59601 windows_tablet = /(?=.*\bWindows\b)(?=.*\bARM\b)/i, // Match 'Windows' AND 'ARM' 59602 other_blackberry = /BlackBerry/i, 59603 other_blackberry_10 = /BB10/i, 59604 other_opera = /Opera Mini/i, 59605 other_chrome = /(CriOS|Chrome)(?=.*\bMobile\b)/i, 59606 other_firefox = /(?=.*\bFirefox\b)(?=.*\bMobile\b)/i, // Match 'Firefox' AND 'Mobile' 59607 seven_inch = new RegExp( 59608 '(?:' + // Non-capturing group 59609
59610 'Nexus 7' + // Nexus 7 59611 59612 '|' + // OR 59613 59614 'BNTV250' + // B&N Nook Tablet 7 inch 59615 59616 '|' + // OR 59617 59618 'Kindle Fire' + // Kindle Fire 59619 59620 '|' + // OR 59621 59622 'Silk' + // Kindle Fire, Silk Accelerated 59623 59624 '|' + // OR 59625 59626 'GT-P1000' + // Galaxy Tab 7 inch 59627 59628 ')', // End non-capturing group 59629 59630 'i'); // Case-insensitive matching 59631 59632 var match = function(regex, userAgent) { 59633 return regex.test(userAgent); 59634 }; 59635 59636 var IsMobileClass = function(userAgent) { 59637 var ua = userAgent || navigator.userAgent; 59638 59639 // Facebook mobile app's integrated browser adds a bunch of strings that 59640 // match everything. Strip it out if it exists. 59641 var tmp = ua.split('[FBAN'); 59642 if (typeof tmp[1] !== 'undefined') { 59643 ua = tmp[0]; 59644 } 59645 59646 // Twitter mobile app's integrated browser on iPad adds a "Twitter for 59647 // iPhone" string. Same probable happens on other tablet platforms. 59648 // This will confuse detection so strip it out if it exists. 59649 tmp = ua.split('Twitter'); 59650 if (typeof tmp[1] !== 'undefined') { 59651 ua = tmp[0]; 59652 } 59653 59654 this.apple = { 59655 phone: match(apple_phone, ua), 59656 ipod: match(apple_ipod, ua), 59657 tablet: !match(apple_phone, ua) && match(apple_tablet, ua), 59658 device: match(apple_phone, ua) || match(apple_ipod, ua) || match(apple_tablet, ua) 59659 }; 59660 this.amazon = { 59661 phone: match(amazon_phone, ua), 59662 tablet: !match(amazon_phone, ua) && match(amazon_tablet, ua), 59663 device: match(amazon_phone, ua) || match(amazon_tablet, ua) 59664 }; 59665 this.android = { 59666 phone: match(amazon_phone, ua) || match(android_phone, ua), 59667 tablet: !match(amazon_phone, ua) && !match(android_phone, ua) && (match(amazon_tablet, ua) || match(android_tablet, ua)), 59668 device: match(amazon_phone, ua) || match(amazon_tablet, ua) || match(android_phone, ua) || match(android_tablet, ua) 59669 }; 59670 this.windows = { 59671 phone: match(windows_phone, ua), 59672 tablet: match(windows_tablet, ua), 59673 device: match(windows_phone, ua) || match(windows_tablet, ua) 59674 }; 59675 this.other = { 59676 blackberry: match(other_blackberry, ua), 59677 blackberry10: match(other_blackberry_10, ua), 59678 opera: match(other_opera, ua), 59679 firefox: match(other_firefox, ua), 59680 chrome: match(other_chrome, ua), 59681 device: match(other_blackberry, ua) || match(other_blackberry_10, ua) || match(other_opera, ua) || match(other_firefox, ua) || match(other_chrome, ua) 59682 }; 59683 this.seven_inch = match(seven_inch, ua); 59684 this.any = this.apple.device || this.android.device || this.windows.device || this.other.device || this.seven_inch; 59685 59686 // excludes 'other' devices and ipods, targeting touchscreen phones 59687 this.phone = this.apple.phone || this.android.phone || this.windows.phone; 59688 59689 // excludes 7 inch devices, classifying as phone or tablet is left to the user 59690 this.tablet = this.apple.tablet || this.android.tablet || this.windows.tablet; 59691 59692 if (typeof window === 'undefined') { 59693 return this; 59694 } 59695 }; 59696 59697 var instantiate = function() { 59698 var IM = new IsMobileClass(); 59699 IM.Class = IsMobileClass; 59700 return IM; 59701 }; 59702 59703 if (typeof module !== 'undefined' && module.exports && typeof window === 'undefined') { 59704 //node 59705 module.exports = IsMobileClass; 59706 } else if (typeof module !== 'undefined' && module.exports && typeof window !== 'undefined') { 59707 //browserify 59708 module.exports = instantiate(); 59709 } else if (typeof define === 'function' && define.amd) { 59710 //AMD 59711 define('isMobile', [], global.isMobile = instantiate()); 59712 } else { 59713 global.isMobile = instantiate(); 59714 } 59715 59716})(this); 59717 59718/*! 59719 Autosize v1.17.8 - 2013-09-07 59720 Automatically adjust textarea height based on user input. 59721 (c) 2013 Jack Moore - http://www.jacklmoore.com/autosize 59722 license: http://www.opensource.org/licenses/mit-license.php 59723*/ 59724(function (factory) { 59725 if (typeof define === 'function' && define.amd) { 59726 // AMD. Register as an anonymous module. 59727 define('jqueryAutosize',['jquery'], factory); 59728 } else { 59729 // Browser globals: jQuery or jQuery-like library, such as Zepto 59730 factory(window.jQuery || window.$); 59731 } 59732}(function ($) { 59733 var 59734 defaults = { 59735 className: 'autosizejs', 59736 append: '', 59737 callback: false, 59738 resizeDelay: 10 59739 }, 59740 59741 // border:0 is unnecessary, but avoids a bug in FireFox on OSX 59742 copy = '<textarea tabindex="-1" style="position:absolute; top:-999px; left:0; right:auto; bottom:auto; border:0; padding: 0; -moz-box-sizing:content-box; -webkit-box-sizing:content-box; box-sizing:content-box; word-wrap:break-word; height:0 !important; min-height:0 !important; overflow:hidden; transition:none; -webkit-transition:none; -moz-transition:none;"/>', 59743 59744 // line-height is conditionally included because IE7/IE8/old Opera do not return the correct value. 59745 typographyStyles = [ 59746 'fontFamily', 59747 'fontSize', 59748 'fontWeight', 59749 'fontStyle', 59750 'letterSpacing', 59751 'textTransform', 59752 'wordSpacing', 59753 'textIndent' 59754 ], 59755 59756 // to keep track which textarea is being mirrored when adjust() is called. 59757 mirrored, 59758 59759 // the mirror element, which is used to calculate what size the mirrored element should be. 59760 mirror = $(copy).data('autosize', true)[0]; 59761 59762 // test that line-height can be accurately copied. 59763 mirror.style.lineHeight = '99px'; 59764 if ($(mirror).css('lineHeight') === '99px') {
59765 typographyStyles.push('lineHeight'); 59766 } 59767 mirror.style.lineHeight = ''; 59768 59769 $.fn.autosize = function (options) { 59770 if (!this.length) { 59771 return this; 59772 } 59773 59774 options = $.extend({}, defaults, options || {}); 59775 59776 if (mirror.parentNode !== document.body) { 59777 $(document.body).append(mirror); 59778 } 59779 59780 return this.each(function () { 59781 var 59782 ta = this, 59783 $ta = $(ta), 59784 maxHeight, 59785 minHeight, 59786 boxOffset = 0, 59787 callback = $.isFunction(options.callback), 59788 originalStyles = { 59789 height: ta.style.height, 59790 overflow: ta.style.overflow, 59791 overflowY: ta.style.overflowY, 59792 wordWrap: ta.style.wordWrap, 59793 resize: ta.style.resize 59794 }, 59795 timeout, 59796 width = $ta.width(); 59797 59798 if ($ta.data('autosize')) { 59799 // exit if autosize has already been applied, or if the textarea is the mirror element. 59800 return; 59801 } 59802 $ta.data('autosize', true); 59803 59804 if ($ta.css('box-sizing') === 'border-box' || $ta.css('-moz-box-sizing') === 'border-box' || $ta.css('-webkit-box-sizing') === 'border-box'){ 59805 boxOffset = $ta.outerHeight() - $ta.height(); 59806 } 59807 59808 // IE8 and lower return 'auto', which parses to NaN, if no min-height is set. 59809 minHeight = Math.max(parseInt($ta.css('minHeight'), 10) - boxOffset || 0, $ta.height()); 59810 59811 $ta.css({ 59812 overflow: 'hidden', 59813 overflowY: 'hidden', 59814 wordWrap: 'break-word', // horizontal overflow is hidden, so break-word is necessary for handling words longer than the textarea width 59815 resize: ($ta.css('resize') === 'none' || $ta.css('resize') === 'vertical') ? 'none' : 'horizontal' 59816 }); 59817 59818 // The mirror width must exactly match the textarea width, so using getBoundingClientRect because it doesn't round the sub-pixel value. 59819 function setWidth() { 59820 var style, width; 59821 59822 if ('getComputedStyle' in window) { 59823 style = window.getComputedStyle(ta); 59824 width = ta.getBoundingClientRect().width; 59825 59826 $.each(['paddingLeft', 'paddingRight', 'borderLeftWidth', 'borderRightWidth'], function(i,val){ 59827 width -= parseInt(style[val],10); 59828 }); 59829 59830 mirror.style.width = width + 'px'; 59831 } 59832 else { 59833 // window.getComputedStyle, getBoundingClientRect returning a width are unsupported and unneeded in IE8 and lower. 59834 mirror.style.width = Math.max($ta.width(), 0) + 'px'; 59835 } 59836 } 59837 59838 function initMirror() { 59839 var styles = {}; 59840 59841 mirrored = ta; 59842 mirror.className = options.className; 59843 maxHeight = parseInt($ta.css('maxHeight'), 10); 59844 59845 // mirror is a duplicate textarea located off-screen that 59846 // is automatically updated to contain the same text as the 59847 // original textarea. mirror always has a height of 0. 59848 // This gives a cross-browser supported way getting the actual 59849 // height of the text, through the scrollTop property. 59850 $.each(typographyStyles, function(i,val){ 59851 styles[val] = $ta.css(val); 59852 }); 59853 $(mirror).css(styles); 59854 59855 setWidth(); 59856 59857 // Chrome-specific fix: 59858 // When the textarea y-overflow is hidden, Chrome doesn't reflow the text to account for the space 59859 // made available by removing the scrollbar. This workaround triggers the reflow for Chrome. 59860 if (window.chrome) { 59861 var width = ta.style.width; 59862 ta.style.width = '0px'; 59863 var ignore = ta.offsetWidth; 59864 ta.style.width = width; 59865 } 59866 } 59867 59868 // Using mainly bare JS in this function because it is going 59869 // to fire very often while typing, and needs to very efficient. 59870 function adjust() { 59871 var height, original; 59872 59873 if (mirrored !== ta) { 59874 initMirror(); 59875 } else { 59876 setWidth(); 59877 } 59878 59879 mirror.value = ta.value + options.append; 59880 mirror.style.overflowY = ta.style.overflowY; 59881 original = parseInt(ta.style.height,10); 59882 59883 // Setting scrollTop to zero is needed in IE8 and lower for the next step to be accurately applied 59884 mirror.scrollTop = 0; 59885 59886 mirror.scrollTop = 9e4; 59887 59888 // Using scrollTop rather than scrollHeight because scrollHeight is non-standard and includes padding. 59889 height = mirror.scrollTop; 59890 59891 if (maxHeight && height > maxHeight) { 59892 ta.style.overflowY = 'scroll'; 59893 height = maxHeight; 59894 } else { 59895 ta.style.overflowY = 'hidden'; 59896 if (height < minHeight) { 59897 height = minHeight; 59898 } 59899 } 59900 59901 height += boxOffset; 59902 59903 if (original !== height) { 59904 ta.style.height = height + 'px'; 59905 if (callback) { 59906 options.callback.call(ta,ta); 59907 } 59908 } 59909 } 59910 59911 function resize () { 59912 clearTimeout(timeout); 59913 timeout = setTimeout(function(){ 59914 var newWidth = $ta.width(); 59915 59916 if (newWidth !== width) { 59917 width = newWidth; 59918 adjust(); 59919 } 59920 }, parseInt(options.resizeDelay,10)); 59921 } 59922 59923 if ('onpropertychange' in ta) { 59924 if ('oninput' in ta) { 59925 // Detects IE9. IE9 does not fire onpropertychange or oninput for deleti
59925ons, 59926 // so binding to onkeyup to catch most of those occasions. There is no way that I 59927 // know of to detect something like 'cut' in IE9. 59928 $ta.on('input.autosize keyup.autosize', adjust); 59929 } else { 59930 // IE7 / IE8 59931 $ta.on('propertychange.autosize', function(){ 59932 if(event.propertyName === 'value'){ 59933 adjust(); 59934 } 59935 }); 59936 } 59937 } else { 59938 // Modern Browsers 59939 $ta.on('input.autosize', adjust); 59940 } 59941 59942 // Set options.resizeDelay to false if using fixed-width textarea elements. 59943 // Uses a timeout and width check to reduce the amount of times adjust needs to be called after window resize. 59944 59945 if (options.resizeDelay !== false) { 59946 $(window).on('resize.autosize', resize); 59947 } 59948 59949 // Event for manual triggering if needed. 59950 // Should only be needed when the value of the textarea is changed through JavaScript rather than user input. 59951 $ta.on('autosize.resize', adjust); 59952 59953 // Event for manual triggering that also forces the styles to update as well. 59954 // Should only be needed if one of typography styles of the textarea change, and the textarea is already the target of the adjust method. 59955 $ta.on('autosize.resizeIncludeStyle', function() { 59956 mirrored = null; 59957 adjust(); 59958 }); 59959 59960 $ta.on('autosize.destroy', function(){ 59961 mirrored = null; 59962 clearTimeout(timeout); 59963 $(window).off('resize', resize); 59964 $ta 59965 .off('autosize') 59966 .off('.autosize') 59967 .css(originalStyles) 59968 .removeData('autosize'); 59969 }); 59970 59971 // Call adjust in case the textarea already contains text. 59972 adjust(); 59973 }); 59974 }; 59975})); 59976 59977(function() { 59978 var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, 59979 __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; }; 59980 59981 (function($) { 59982 /* 59983 $(".my-pagination").pagination(); 59984 59985 $(".my-pagination").pagination({total_pages: 3, current_page: 1}); 59986 59987 $(".my-pagination").pagination({ 59988 total_pages: 3, 59989 current_page: 1, 59990 callback: function(event, page) { 59991 alert("Clicked: " + page); 59992 } 59993 }); 59994 */ 59995 59996 var PaginationView; 59997 59998 $.fn.pagination = function(options) { 59999 return this.each(function() { 60000 return new PaginationView($(this), options).render(); 60001 }); 60002 }; 60003 return PaginationView = (function() { 60004 function PaginationView(el, options) { 60005 var defaults; 60006 60007 this.el = el; 60008 this.change = __bind(this.change, this); 60009 this.clicked = __bind(this.clicked, this); 60010 this.isValidPage = __bind(this.isValidPage, this); 60011 this.render = __bind(this.render, this); 60012 this.pages = __bind(this.pages, this); 60013 this.buildLink = __bind(this.buildLink, this); 60014 this.buildLi = __bind(this.buildLi, this); 60015 this.buildLinks = __bind(this.buildLinks, this); 60016 defaults = { 60017 current_page: 1, 60018 total_pages: 1, 60019 next: "<svg height=\"14px\" width=\"14px\" xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" x=\"0\" y=\"0\" viewBox=\"0 0 60 60\" enable-background=\"new 0 0 36 36\" xml:space=\"preserve\"><polygon points=\"15.3 60 13.8 58.2 43 30 13.8 1.7 15.3 0 46.3 30 \"/></svg>", 60020 prev: "<svg height=\"14px\" width=\"14px\" xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" x=\"0\" y=\"0\" viewBox=\"0 0 60 60\" enable-background=\"new 0 0 36 36\" xml:space=\"preserve\"><polygon points=\"13.8 30 44.8 0 46.3 1.7 17 30 46.3 58.3 44.8 60 \"/></svg>", 60021 first: false, 60022 last: false, 60023 display_max: 2, 60024 ignore_single_page: true, 60025 no_turbolink: false 60026 }; 60027 this.settings = $.extend(defaults, options); 60028 if ($(document).on) { 60029 $(this.el).on("click", "a", this.clicked); 60030 } else { 60031 $("a", this.el).live("click", this.clicked); 60032 } 60033 this.el.data("paginationView", this); 60034 } 60035 60036 PaginationView.prototype.buildLinks = function() { 60037 var current_page, links, page, _i, _len, _ref; 60038 60039 current_page = this.settings.current_page; 60040 links = []; 60041 if (this.settings.first) { 60042 links.push(this.buildLi(1, this.settings.first)); 60043 } 60044 if (this.settings.prev) { 60045 links.push(this.buildLi(current_page - 1, this.settings.prev)); 60046 } 60047 _ref = this.pages();
60048 for (_i = 0, _len = _ref.length; _i < _len; _i++) { 60049 page = _ref[_i]; 60050 links.push(this.buildLi(page, page)); 60051 } 60052 if (this.settings.next) { 60053 links.push(this.buildLi(current_page + 1, this.settings.next)); 60054 } 60055 if (this.settings.last) { 60056 links.push(this.buildLi(this.settings.total_pages, this.settings.last)); 60057 } 60058 return links; 60059 }; 60060 60061 PaginationView.prototype.buildLi = function(page, text) { 60062 if (text == null) { 60063 text = page; 60064 } 60065 return "<li>" + (this.buildLink(page, text)) + "</li>"; 60066 }; 60067 60068 PaginationView.prototype.buildLink = function(page, text) { 60069 var data_attr; 60070 60071 if (text == null) { 60072 text = page; 60073 } 60074 if (this.settings.no_turbolink) { 60075 data_attr = " data-no-turbolink='1'"; 60076 } else { 60077 data_attr = ""; 60078 } 60079 return "<a href='#' data-page='" + page + "'" + data_attr + ">" + text + "</a>"; 60080 }; 60081 60082 PaginationView.prototype.pages = function() { 60083 var buf, current_page, max, page, pages, total_pages, _i, _j, _k, _l, _m, _ref, _ref1, _ref2, _ref3; 60084 60085 total_pages = this.settings.total_pages; 60086 current_page = this.settings.current_page; 60087 pages = []; 60088 max = this.settings.display_max; 60089 if (total_pages > 10) { 60090 pages.push(1); 60091 if (current_page > max - 1) { 60092 pages.push(".."); 60093 } 60094 if (current_page === total_pages) { 60095 for (page = _i = _ref = total_pages - max; _ref <= total_pages ? _i <= total_pages : _i >= total_pages; page = _ref <= total_pages ? ++_i : --_i) { 60096 pages.push(page); 60097 } 60098 } 60099 if (total_pages - current_page < max - 1) { 60100 for (page = _j = _ref1 = total_pages - max; _ref1 <= total_pages ? _j <= total_pages : _j >= total_pages; page = _ref1 <= total_pages ? ++_j : --_j) { 60101 pages.push(page); 60102 } 60103 } else if (current_page > max - 1) { 60104 buf = max / 2; 60105 for (page = _k = _ref2 = current_page - buf, _ref3 = current_page + buf; _ref2 <= _ref3 ? _k <= _ref3 : _k >= _ref3; page = _ref2 <= _ref3 ? ++_k : --_k) { 60106 pages.push(page); 60107 } 60108 } else if (current_page <= max - 1) { 60109 for (page = _l = 2; 2 <= max ? _l <= max : _l >= max; page = 2 <= max ? ++_l : --_l) { 60110 pages.push(page); 60111 } 60112 } 60113 pages = $.grep(pages, function(v, k) { 60114 return $.inArray(v, pages) === k; 60115 }); 60116 if (__indexOf.call(pages, total_pages) < 0) { 60117 if (!((total_pages - current_page) < max - 1)) { 60118 pages.push(".."); 60119 } 60120 pages.push(total_pages); 60121 } 60122 } else { 60123 for (page = _m = 1; 1 <= total_pages ? _m <= total_pages : _m >= total_pages; page = 1 <= total_pages ? ++_m : --_m) { 60124 pages.push(page); 60125 } 60126 } 60127 return pages; 60128 }; 60129 60130 PaginationView.prototype.render = function() { 60131 var html, link, _i, _len, _ref; 60132 60133 this.el.html(""); 60134 if (this.settings.total_pages === 1 && this.settings.ignore_single_page) { 60135 return; 60136 } 60137 html = ["<div class='jquery-bootstrap-pagination'>"]; 60138 html.push("<ul class='pagination'>"); 60139 _ref = this.buildLinks(); 60140 for (_i = 0, _len = _ref.length; _i < _len; _i++) { 60141 link = _ref[_i]; 60142 html.push(link); 60143 } 60144 html.push("</ul>"); 60145 html.push("</div>"); 60146 this.el.html(html.join("\n")); 60147 $("[data-page=" + this.settings.current_page + "]", this.el).closest("li").addClass("active"); 60148 $("[data-page='..']", this.el).closest("li").addClass("disabled"); 60149 $("[data-page='0']", this.el).closest("li").addClass("disabled"); 60150 $("[data-page='" + (this.settings.total_pages + 1) + "']", this.el).closest("li").addClass("disabled"); 60151 if (this.settings.current_page === 1 && this.settings.first) { 60152 $("li:first", this.el).removeClass("active").addClass("disabled"); 60153 } 60154 if (this.settings.current_page === this.settings.total_pages && this.settings.last) { 60155 return $("li:last", this.el).removeClass("active").addClass("disabled"); 60156 } 60157 }; 60158 60159 PaginationView.prototype.isValidPage = function(page) { 60160 return page > 0 && page !== this.settings.current_page && page <= this.settings.total_pages; 60161 }; 60162 60163 PaginationView.prototype.clicked = function(event) { 60164 var page; 60165 60166 page = parseInt($(event.target).attr("data-page")); 60167 if (!this.isValidPage(page)) { 60168 return; 60169 } 60170 if (this.settings.callback != null) { 60171 this.settings.callback(event, page); 60172 } 60173 return this.change(page); 60174 }; 60175 60176 PaginationView.prototype.change = function(page) { 60177 page = parseInt(page); 60178 if (!this.isValidPage(page)) { 60179 return; 60180 } 60181 this.settings.current_page = page; 60182 return this.render(); 60183 }; 60184 60185 return PaginationView; 60186 60187 })(); 60188 })(jQuery); 60189 60190}).call(this); 60191 60192define("jqueryBootstrapPagination", ["jquery"], function(){}); 60193 60194/*! jQuery UI - v1.11.4+CommonJS - 2015-08-28 60195* http://jqueryui.com 60196* Includes: widget.js 60197* Copyright 2015 jQuery Foundation and other contributors; Licensed MIT */ 60198 60199(function( factory ) { 60200 if ( typeof define === "function" && define.amd ) { 60201 60202 // AMD. Register as an anonymous module. 60203 define('jquery.ui.widget',[ "jquery" ], factory ); 60204 60205 } else if ( typeof exports === "object" ) { 60206 60207 // Node/CommonJS 60208 factory( require( "jquery" ) ); 60209 60210 } else { 60211 60212 // Browser globals 60213 factory( jQuery ); 60214 } 60215}(function( $ ) {
vendor: 15,589 bytes, lines 60215-60763
60215 60216/*! 60217 * jQuery UI Widget 1.11.4 60218 * http://jqueryui.com 60219 * 60220 * Copyright jQuery Foundation and other contributors 60221 * Released under the MIT license. 60222 * http://jquery.org/license 60223 * 60224 * http://api.jqueryui.com/jQuery.widget/ 60225 */ 60226 60227 60228var widget_uuid = 0, 60229 widget_slice = Array.prototype.slice; 60230 60231$.cleanData = (function( orig ) { 60232 return function( elems ) { 60233 var events, elem, i; 60234 for ( i = 0; (elem = elems[i]) != null; i++ ) { 60235 try { 60236 60237 // Only trigger remove when necessary to save time 60238 events = $._data( elem, "events" ); 60239 if ( events && events.remove ) { 60240 $( elem ).triggerHandler( "remove" ); 60241 } 60242 60243 // http://bugs.jquery.com/ticket/8235 60244 } catch ( e ) {} 60245 } 60246 orig( elems ); 60247 }; 60248})( $.cleanData ); 60249 60250$.widget = function( name, base, prototype ) { 60251 var fullName, existingConstructor, constructor, basePrototype, 60252 // proxiedPrototype allows the provided prototype to remain unmodified 60253 // so that it can be used as a mixin for multiple widgets (#8876) 60254 proxiedPrototype = {}, 60255 namespace = name.split( "." )[ 0 ]; 60256 60257 name = name.split( "." )[ 1 ]; 60258 fullName = namespace + "-" + name; 60259 60260 if ( !prototype ) { 60261 prototype = base; 60262 base = $.Widget; 60263 } 60264 60265 // create selector for plugin 60266 $.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) { 60267 return !!$.data( elem, fullName ); 60268 }; 60269 60270 $[ namespace ] = $[ namespace ] || {}; 60271 existingConstructor = $[ namespace ][ name ]; 60272 constructor = $[ namespace ][ name ] = function( options, element ) { 60273 // allow instantiation without "new" keyword 60274 if ( !this._createWidget ) { 60275 return new constructor( options, element ); 60276 } 60277 60278 // allow instantiation without initializing for simple inheritance 60279 // must use "new" keyword (the code above always passes args) 60280 if ( arguments.length ) { 60281 this._createWidget( options, element ); 60282 } 60283 }; 60284 // extend with the existing constructor to carry over any static properties 60285 $.extend( constructor, existingConstructor, { 60286 version: prototype.version, 60287 // copy the object used to create the prototype in case we need to 60288 // redefine the widget later 60289 _proto: $.extend( {}, prototype ), 60290 // track widgets that inherit from this widget in case this widget is 60291 // redefined after a widget inherits from it 60292 _childConstructors: [] 60293 }); 60294 60295 basePrototype = new base(); 60296 // we need to make the options hash a property directly on the new instance 60297 // otherwise we'll modify the options hash on the prototype that we're 60298 // inheriting from 60299 basePrototype.options = $.widget.extend( {}, basePrototype.options ); 60300 $.each( prototype, function( prop, value ) { 60301 if ( !$.isFunction( value ) ) { 60302 proxiedPrototype[ prop ] = value; 60303 return; 60304 } 60305 proxiedPrototype[ prop ] = (function() { 60306 var _super = function() { 60307 return base.prototype[ prop ].apply( this, arguments ); 60308 }, 60309 _superApply = function( args ) { 60310 return base.prototype[ prop ].apply( this, args ); 60311 }; 60312 return function() { 60313 var __super = this._super, 60314 __superApply = this._superApply, 60315 returnValue; 60316 60317 this._super = _super; 60318 this._superApply = _superApply; 60319 60320 returnValue = value.apply( this, arguments ); 60321 60322 this._super = __super; 60323 this._superApply = __superApply; 60324 60325 return returnValue; 60326 }; 60327 })(); 60328 }); 60329 constructor.prototype = $.widget.extend( basePrototype, { 60330 // TODO: remove support for widgetEventPrefix 60331 // always use the name + a colon as the prefix, e.g., draggable:start 60332 // don't prefix for widgets that aren't DOM-based 60333 widgetEventPrefix: existingConstructor ? (basePrototype.widgetEventPrefix || name) : name 60334 }, proxiedPrototype, { 60335 constructor: constructor, 60336 namespace: namespace, 60337 widgetName: name, 60338 widgetFullName: fullName 60339 }); 60340 60341 // If this widget is being redefined then we need to find all widgets that 60342 // are inheriting from it and redefine all of them so that they inherit from 60343 // the new version of this widget. We're essentially trying to replace one 60344 // level in the prototype chain. 60345 if ( existingConstructor ) { 60346 $.each( existingConstructor._childConstructors, function( i, child ) { 60347 var childPrototype = child.prototype; 60348 60349 // redefine the child widget using the same prototype that was 60350 // originally used, but inherit from the new version of the base 60351 $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto ); 60352 }); 60353 // remove the list of existing child constructors from the old constructor 60354 // so the old child constructors can be garbage collected 60355 delete existingConstructor._childConstructors; 60356 } else { 60357 base._childConstructors.push( constructor ); 60358 } 60359 60360 $.widget.bridge( name, constructor ); 60361 60362 return constructor; 60363}; 60364 60365$.widget.extend = function( target ) { 60366 var input = widget_slice.call( arguments, 1 ), 60367 inputIndex = 0, 60368 inputLength = input.length, 60369 key, 60370 value; 60371 for ( ; inputIndex < inputLength; inputIndex++ ) { 60372 for ( key in input[ inputIndex ] ) { 60373 value = input[ inputIndex ][ key ]; 60374 if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) { 60375 // Clone objects 60376 if ( $.isPlainObject( value ) ) { 60377 target[ key ] = $.isPlainObject( target[ key ] ) ? 60378 $.widget.extend( {}, target[ key ], value ) : 60379 // Don't extend strings, arrays, etc. with objects 60380 $.widget.extend( {}, value ); 60381 // Copy everything else by reference 60382 } else { 60383 target[ key ] = value; 60384 } 60385 } 60386 } 60387 } 60388 return target; 60389}; 60390 60391$.widget.bridge = function( name, object ) { 60392 var fullName = object.prototype.widgetFullName || name; 60393 $.fn[ name ] = function( options ) { 60394 var isMethodCall = typeof options === "string", 60395 args = widget_slice.call( arguments, 1 ), 60396 returnValue = this; 60397 60398 if ( isMethodCall ) { 60399 this.each(function() { 60400 var methodValue, 60401 instance = $.data( this, fullName ); 60402 if ( options === "instance" ) { 60403 returnValue = instance; 60404 return false; 60405 } 60406 if ( !instance ) { 60407 return $.error( "cannot call methods on " + name + " prior to initialization; " + 60408 "attempted to call method '" + options + "'" ); 60409 } 60410 if ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) { 60411 return $.error( "no such method '" + options + "' for " + name + " widget instance" ); 60412 } 60413 methodValue = instance[ options ].apply( instance, args ); 60414 if ( methodValue !== instance && methodValue !== undefined ) { 60415 returnValue = methodValue && methodValue.jquery ? 60416 returnValue.pushStack( methodValue.get() ) : 60417 methodValue; 60418 return false; 60419 } 60420 }); 60421 } else { 60422 60423 // Allow multiple hashes to be passed on init 60424 if ( args.length ) { 60425 options = $.widget.extend.apply( null, [ options ].concat(args) ); 60426 } 60427 60428 this.each(function() { 60429 var instance = $.data( this, fullName ); 60430 if ( instance ) { 60431 instance.option( options || {} ); 60432 if ( instance._init ) { 60433 instance._init(); 60434 } 60435 } else { 60436 $.data( this, fullName, new object( options, this ) ); 60437 } 60438 }); 60439 } 60440 60441 return returnValue; 60442 }; 60443}; 60444 60445$.Widget = function( /* options, element */ ) {}; 60446$.Widget._childConstructors = []; 60447 60448$.Widget.prototype = { 60449 widgetName: "widget", 60450 widgetEventPrefix: "", 60451 defaultElement: "<div>", 60452 options: { 60453 disabled: false, 60454 60455 // callbacks 60456 create: null 60457 }, 60458 _createWidget: function( options, element ) { 60459 element = $( element || this.defaultElement || this )[ 0 ]; 60460 this.element = $( element ); 60461 this.uuid = widget_uuid++; 60462 this.eventNamespace = "." + this.widgetName + this.uuid; 60463 60464 this.bindings = $(); 60465 this.hoverable = $(); 60466 this.focusable = $(); 60467 60468 if ( element !== this ) { 60469 $.data( element, this.widgetFullName, this ); 60470 this._on( true, this.element, { 60471 remove: function( event ) { 60472 if ( event.target === element ) { 60473 this.destroy(); 60474 } 60475 } 60476 }); 60477 this.document = $( element.style ? 60478 // element within the document 60479 element.ownerDocument : 60480 // element is window or document 60481 element.document || element ); 60482 this.window = $( this.document[0].defaultView || this.document[0].parentWindow ); 60483 } 60484 60485 this.options = $.widget.extend( {}, 60486 this.options, 60487 this._getCreateOptions(), 60488 options ); 60489 60490 this._create(); 60491 this._trigger( "create", null, this._getCreateEventData() ); 60492 this._init(); 60493 }, 60494 _getCreateOptions: $.noop, 60495 _getCreateEventData: $.noop, 60496 _create: $.noop, 60497 _init: $.noop, 60498 60499 destroy: function() { 60500 this._destroy(); 60501 // we can probably remove the unbind calls in 2.0 60502 // all event bindings should go through this._on() 60503 this.element 60504 .unbind( this.eventNamespace ) 60505 .removeData( this.widgetFullName ) 60506 // support: jquery <1.6.3 60507 // http://bugs.jquery.com/ticket/9413 60508 .removeData( $.camelCase( this.widgetFullName ) ); 60509 this.widget() 60510 .unbind( this.eventNamespace ) 60511 .removeAttr( "aria-disabled" ) 60512 .removeClass( 60513 this.widgetFullName + "-disabled " + 60514 "ui-state-disabled" ); 60515 60516 // clean up events and states 60517 this.bindings.unbind( this.eventNamespace ); 60518 this.hoverable.removeClass( "ui-state-hover" ); 60519 this.focusable.removeClass( "ui-state-focus" ); 60520 }, 60521 _destroy: $.noop, 60522 60523 widget: function() { 60524 return this.element; 60525 }, 60526 60527 option: function( key, value ) { 60528 var options = key, 60529 parts, 60530 curOption, 60531 i; 60532 60533 if ( arguments.length === 0 ) { 60534 // don't return a reference to the internal hash 60535 return $.widget.extend( {}, this.options ); 60536 } 60537 60538 if ( typeof key === "string" ) { 60539 // handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } } 60540 options = {}; 60541 parts = key.split( "." ); 60542 key = parts.shift(); 60543 if ( parts.length ) { 60544 curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] ); 60545 for ( i = 0; i < parts.length - 1; i++ ) { 60546 curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {}; 60547 curOption = curOption[ parts[ i ] ]; 60548 } 60549 key = parts.pop(); 60550 if ( arguments.length === 1 ) { 60551 return curOption[ key ] === undefined ? null : curOption[ key ]; 60552 } 60553 curOption[ key ] = value; 60554 } else { 60555 if ( arguments.length === 1 ) { 60556 return this.options[ key ] === undefined ? null : this.options[ key ]; 60557 } 60558 options[ key ] = value; 60559 } 60560 } 60561 60562 this._setOptions( options ); 60563 60564 return this; 60565 }, 60566 _setOptions: function( options ) { 60567 var key; 60568 60569 for ( key in options ) { 60570 this._setOption( key, options[ key ] ); 60571 } 60572 60573 return this; 60574 }, 60575 _setOption: function( key, value ) { 60576 this.options[ key ] = value; 60577 60578 if ( key === "disabled" ) { 60579 this.widget() 60580 .toggleClass( this.widgetFullName + "-disabled", !!value ); 60581 60582 // If the widget is becoming disabled, then nothing is interactive 60583 if ( value ) { 60584 this.hoverable.removeClass( "ui-state-hover" ); 60585 this.focusable.removeClass( "ui-state-focus" ); 60586 } 60587 } 60588 60589 return this; 60590 }, 60591 60592 enable: function() { 60593 return this._setOptions({ disabled: false }); 60594 }, 60595 disable: function() { 60596 return this._setOptions({ disabled: true }); 60597 }, 60598 60599 _on: function( suppressDisabledCheck, element, handlers ) { 60600 var delegateElement, 60601 instance = this; 60602 60603 // no suppressDisabledCheck flag, shuffle arguments 60604 if ( typeof suppressDisabledCheck !== "boolean" ) { 60605 handlers = element; 60606 element = suppressDisabledCheck; 60607 suppressDisabledCheck = false; 60608 } 60609 60610 // no element argument, shuffle and use this.element 60611 if ( !handlers ) { 60612 handlers = element; 60613 element = this.element; 60614 delegateElement = this.widget(); 60615 } else { 60616 element = delegateElement = $( element ); 60617 this.bindings = this.bindings.add( element ); 60618 } 60619 60620 $.each( handlers, function( event, handler ) { 60621 function handlerProxy() { 60622 // allow widgets to customize the disabled handling 60623 // - disabled as an array instead of boolean 60624 // - disabled class as method for disabling individual parts 60625 if ( !suppressDisabledCheck && 60626 ( instance.options.disabled === true || 60627 $( this ).hasClass( "ui-state-disabled" ) ) ) { 60628 return; 60629 } 60630 return ( typeof handler === "string" ? instance[ handler ] : handler ) 60631 .apply( instance, arguments ); 60632 } 60633 60634 // copy the guid so direct unbinding works 60635 if ( typeof handler !== "string" ) { 60636 handlerProxy.guid = handler.guid = 60637 handler.guid || handlerProxy.guid || $.guid++; 60638 } 60639 60640 var match = event.match( /^([\w:-]*)\s*(.*)$/ ), 60641 eventName = match[1] + instance.eventNamespace, 60642 selector = match[2]; 60643 if ( selector ) { 60644 delegateElement.delegate( selector, eventName, handlerProxy ); 60645 } else { 60646 element.bind( eventName, handlerProxy ); 60647 } 60648 }); 60649 }, 60650 60651 _off: function( element, eventName ) { 60652 eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) + 60653 this.eventNamespace; 60654 element.unbind( eventName ).undelegate( eventName ); 60655 60656 // Clear the stack to avoid memory leaks (#10056) 60657 this.bindings = $( this.bindings.not( element ).get() ); 60658 this.focusable = $( this.focusable.not( element ).get() ); 60659 this.hoverable = $( this.hoverable.not( element ).get() ); 60660 }, 60661 60662 _delay: function( handler, delay ) { 60663 function handlerProxy() { 60664 return ( typeof handler === "string" ? instance[ handler ] : handler ) 60665 .apply( instance, arguments ); 60666 } 60667 var instance = this; 60668 return setTimeout( handlerProxy, delay || 0 ); 60669 }, 60670 60671 _hoverable: function( element ) { 60672 this.hoverable = this.hoverable.add( element ); 60673 this._on( element, { 60674 mouseenter: function( event ) { 60675 $( event.currentTarget ).addClass( "ui-state-hover" ); 60676 }, 60677 mouseleave: function( event ) { 60678 $( event.currentTarget ).removeClass( "ui-state-hover" ); 60679 } 60680 }); 60681 }, 60682 60683 _focusable: function( element ) { 60684 this.focusable = this.focusable.add( element ); 60685 this._on( element, { 60686 focusin: function( event ) { 60687 $( event.currentTarget ).addClass( "ui-state-focus" ); 60688 }, 60689 focusout: function( event ) { 60690 $( event.currentTarget ).removeClass( "ui-state-focus" ); 60691 } 60692 }); 60693 }, 60694 60695 _trigger: function( type, event, data ) { 60696 var prop, orig, 60697 callback = this.options[ type ]; 60698 60699 data = data || {}; 60700 event = $.Event( event ); 60701 event.type = ( type === this.widgetEventPrefix ? 60702 type : 60703 this.widgetEventPrefix + type ).toLowerCase(); 60704 // the original event may come from any element 60705 // so we need to reset the target on the new event 60706 event.target = this.element[ 0 ]; 60707 60708 // copy original event properties over to the new event 60709 orig = event.originalEvent; 60710 if ( orig ) { 60711 for ( prop in orig ) { 60712 if ( !( prop in event ) ) { 60713 event[ prop ] = orig[ prop ]; 60714 } 60715 } 60716 } 60717 60718 this.element.trigger( event, data ); 60719 return !( $.isFunction( callback ) && 60720 callback.apply( this.element[0], [ event ].concat( data ) ) === false || 60721 event.isDefaultPrevented() ); 60722 } 60723}; 60724 60725$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) { 60726 $.Widget.prototype[ "_" + method ] = function( element, options, callback ) { 60727 if ( typeof options === "string" ) { 60728 options = { effect: options }; 60729 } 60730 var hasOptions, 60731 effectName = !options ? 60732 method : 60733 options === true || typeof options === "number" ? 60734 defaultEffect : 60735 options.effect || defaultEffect; 60736 options = options || {}; 60737 if ( typeof options === "number" ) { 60738 options = { duration: options }; 60739 } 60740 hasOptions = !$.isEmptyObject( options ); 60741 options.complete = callback; 60742 if ( options.delay ) { 60743 element.delay( options.delay ); 60744 } 60745 if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) { 60746 element[ method ]( options ); 60747 } else if ( effectName !== method && element[ effectName ] ) { 60748 element[ effectName ]( options.duration, options.easing, callback ); 60749 } else { 60750 element.queue(function( next ) { 60751 $( this )[ method ](); 60752 if ( callback ) { 60753 callback.call( element[ 0 ] ); 60754 } 60755 next(); 60756 }); 60757 } 60758 }; 60759}); 60760 60761var widget = $.widget; 60762 60763
60764 60765})); 60766 60767/* 60768 * jQuery File Upload Plugin 60769 * https://github.com/blueimp/jQuery-File-Upload 60770 * 60771 * Copyright 2010, Sebastian Tschan 60772 * https://blueimp.net 60773 * 60774 * Licensed under the MIT license: 60775 * http://www.opensource.org/licenses/MIT 60776 */ 60777 60778/* jshint nomen:false */ 60779/* global define, require, window, document, location, Blob, FormData */ 60780 60781;(function (factory) { 60782 'use strict'; 60783 if (typeof define === 'function' && define.amd) { 60784 // Register as an anonymous AMD module: 60785 define('jquery.fileupload',[ 60786 'jquery', 60787 'jquery-ui/widget' 60788 ], factory); 60789 } else if (typeof exports === 'object') { 60790 // Node/CommonJS: 60791 factory( 60792 require('jquery'), 60793 require('./vendor/jquery.ui.widget') 60794 ); 60795 } else { 60796 // Browser globals: 60797 factory(window.jQuery); 60798 } 60799}(function ($) { 60800 'use strict'; 60801 60802 // Detect file input support, based on 60803 // http://viljamis.com/blog/2012/file-upload-support-on-mobile/ 60804 $.support.fileInput = !(new RegExp( 60805 // Handle devices which give false positives for the feature detection: 60806 '(Android (1\\.[0156]|2\\.[01]))' + 60807 '|(Windows Phone (OS 7|8\\.0))|(XBLWP)|(ZuneWP)|(WPDesktop)' + 60808 '|(w(eb)?OSBrowser)|(webOS)' + 60809 '|(Kindle/(1\\.0|2\\.[05]|3\\.0))' 60810 ).test(window.navigator.userAgent) || 60811 // Feature detection for all other devices: 60812 $('<input type="file">').prop('disabled')); 60813 60814 // The FileReader API is not actually used, but works as feature detection, 60815 // as some Safari versions (5?) support XHR file uploads via the FormData API, 60816 // but not non-multipart XHR file uploads. 60817 // window.XMLHttpRequestUpload is not available on IE10, so we check for 60818 // window.ProgressEvent instead to detect XHR2 file upload capability: 60819 $.support.xhrFileUpload = !!(window.ProgressEvent && window.FileReader); 60820 $.support.xhrFormDataFileUpload = !!window.FormData; 60821 60822 // Detect support for Blob slicing (required for chunked uploads): 60823 $.support.blobSlice = window.Blob && (Blob.prototype.slice || 60824 Blob.prototype.webkitSlice || Blob.prototype.mozSlice); 60825 60826 // Helper function to create drag handlers for dragover/dragenter/dragleave: 60827 function getDragHandler(type) { 60828 var isDragOver = type === 'dragover'; 60829 return function (e) { 60830 e.dataTransfer = e.originalEvent && e.originalEvent.dataTransfer; 60831 var dataTransfer = e.dataTransfer; 60832 if (dataTransfer && $.inArray('Files', dataTransfer.types) !== -1 && 60833 this._trigger( 60834 type, 60835 $.Event(type, {delegatedEvent: e}) 60836 ) !== false) { 60837 e.preventDefault(); 60838 if (isDragOver) { 60839 dataTransfer.dropEffect = 'copy'; 60840 } 60841 } 60842 }; 60843 } 60844 60845 // The fileupload widget listens for change events on file input fields defined 60846 // via fileInput setting and paste or drop events of the given dropZone. 60847 // In addition to the default jQuery Widget methods, the fileupload widget 60848 // exposes the "add" and "send" methods, to add or directly send files using 60849 // the fileupload API. 60850 // By default, files added via file input selection, paste, drag & drop or 60851 // "add" method are uploaded immediately, but it is possible to override 60852 // the "add" callback option to queue file uploads. 60853 $.widget('blueimp.fileupload', { 60854 60855 options: { 60856 // The drop target element(s), by the default the complete document. 60857 // Set to null to disable drag & drop support: 60858 dropZone: $(document), 60859 // The paste target element(s), by the default undefined. 60860 // Set to a DOM node or jQuery object to enable file pasting: 60861 pasteZone: undefined, 60862 // The file input field(s), that are listened to for change events. 60863 // If undefined, it is set to the file input fields inside 60864 // of the widget element on plugin initialization. 60865 // Set to null to disable the change listener. 60866 fileInput: undefined, 60867 // By default, the file input field is replaced with a clone after 60868 // each input field change event. This is required for iframe transport 60869 // queues and allows change events to be fired for the same file 60870 // selection, but can be disabled by setting the following option to fal
60870se: 60871 replaceFileInput: true, 60872 // The parameter name for the file form data (the request argument name). 60873 // If undefined or empty, the name property of the file input field is 60874 // used, or "files[]" if the file input name property is also empty, 60875 // can be a string or an array of strings: 60876 paramName: undefined, 60877 // By default, each file of a selection is uploaded using an individual 60878 // request for XHR type uploads. Set to false to upload file 60879 // selections in one request each: 60880 singleFileUploads: true, 60881 // To limit the number of files uploaded with one XHR request, 60882 // set the following option to an integer greater than 0: 60883 limitMultiFileUploads: undefined, 60884 // The following option limits the number of files uploaded with one 60885 // XHR request to keep the request size under or equal to the defined 60886 // limit in bytes: 60887 limitMultiFileUploadSize: undefined, 60888 // Multipart file uploads add a number of bytes to each uploaded file, 60889 // therefore the following option adds an overhead for each file used 60890 // in the limitMultiFileUploadSize configuration: 60891 limitMultiFileUploadSizeOverhead: 512, 60892 // Set the following option to true to issue all file upload requests 60893 // in a sequential order: 60894 sequentialUploads: false, 60895 // To limit the number of concurrent uploads, 60896 // set the following option to an integer greater than 0: 60897 limitConcurrentUploads: undefined, 60898 // Set the following option to true to force iframe transport uploads: 60899 forceIframeTransport: false, 60900 // Set the following option to the location of a redirect url on the 60901 // origin server, for cross-domain iframe transport uploads: 60902 redirect: undefined, 60903 // The parameter name for the redirect url, sent as part of the form 60904 // data and set to 'redirect' if this option is empty: 60905 redirectParamName: undefined, 60906 // Set the following option to the location of a postMessage window, 60907 // to enable postMessage transport uploads: 60908 postMessage: undefined, 60909 // By default, XHR file uploads are sent as multipart/form-data. 60910 // The iframe transport is always using multipart/form-data. 60911 // Set to false to enable non-multipart XHR uploads: 60912 multipart: true, 60913 // To upload large files in smaller chunks, set the following option 60914 // to a preferred maximum chunk size. If set to 0, null or undefined, 60915 // or the browser does not support the required Blob API, files will 60916 // be uploaded as a whole. 60917 maxChunkSize: undefined, 60918 // When a non-multipart upload or a chunked multipart upload has been 60919 // aborted, this option can be used to resume the upload by setting 60920 // it to the size of the already uploaded bytes. This option is most 60921 // useful when modifying the options object inside of the "add" or 60922 // "send" callbacks, as the options are cloned for each file upload. 60923 uploadedBytes: undefined, 60924 // By default, failed (abort or error) file uploads are removed from the 60925 // global progress calculation. Set the following option to false to 60926 // prevent recalculating the global progress data: 60927 recalculateProgress: true, 60928 // Interval in milliseconds to calculate and trigger progress events: 60929 progressInterval: 100, 60930 // Interval in milliseconds to calculate progress bitrate: 60931 bitrateInterval: 500, 60932 // By default, uploads are started automatically when adding files: 60933 autoUpload: true, 60934 60935 // Error and info messages: 60936 messages: { 60937 uploadedBytes: 'Uploaded bytes exceed file size' 60938 }, 60939
60940 // Translation function, gets the message key to be translated 60941 // and an object with context specific data as arguments: 60942 i18n: function (message, context) { 60943 message = this.messages[message] || message.toString(); 60944 if (context) { 60945 $.each(context, function (key, value) { 60946 message = message.replace('{' + key + '}', value); 60947 }); 60948 } 60949 return message; 60950 }, 60951 60952 // Additional form data to be sent along with the file uploads can be set 60953 // using this option, which accepts an array of objects with name and 60954 // value properties, a function returning such an array, a FormData 60955 // object (for XHR file uploads), or a simple object. 60956 // The form of the first fileInput is given as parameter to the function: 60957 formData: function (form) { 60958 return form.serializeArray(); 60959 }, 60960 60961 // The add callback is invoked as soon as files are added to the fileupload 60962 // widget (via file input selection, drag & drop, paste or add API call). 60963 // If the singleFileUploads option is enabled, this callback will be 60964 // called once for each file in the selection for XHR file uploads, else 60965 // once for each file selection. 60966 // 60967 // The upload starts when the submit method is invoked on the data parameter. 60968 // The data object contains a files property holding the added files 60969 // and allows you to override plugin options as well as define ajax settings. 60970 // 60971 // Listeners for this callback can also be bound the following way: 60972 // .bind('fileuploadadd', func); 60973 // 60974 // data.submit() returns a Promise object and allows to attach additional 60975 // handlers using jQuery's Deferred callbacks: 60976 // data.submit().done(func).fail(func).always(func); 60977 add: function (e, data) { 60978 if (e.isDefaultPrevented()) { 60979 return false; 60980 } 60981 if (data.autoUpload || (data.autoUpload !== false && 60982 $(this).fileupload('option', 'autoUpload'))) { 60983 data.process().done(function () { 60984 data.submit(); 60985 }); 60986 } 60987 }, 60988 60989 // Other callbacks: 60990 60991 // Callback for the submit event of each file upload: 60992 // submit: function (e, data) {}, // .bind('fileuploadsubmit', func); 60993 60994 // Callback for the start of each file upload request: 60995 // send: function (e, data) {}, // .bind('fileuploadsend', func); 60996 60997 // Callback for successful uploads: 60998 // done: function (e, data) {}, // .bind('fileuploaddone', func); 60999 61000 // Callback for failed (abort or error) uploads: 61001 // fail: function (e, data) {}, // .bind('fileuploadfail', func); 61002 61003 // Callback for completed (success, abort or error) requests: 61004 // always: function (e, data) {}, // .bind('fileuploadalways', func); 61005 61006 // Callback for upload progress events: 61007 // progress: function (e, data) {}, // .bind('fileuploadprogress', func); 61008 61009 // Callback for global upload progress events: 61010 // progressall: function (e, data) {}, // .bind('fileuploadprogressall', func); 61011 61012 // Callback for uploads start, equivalent to the global ajaxStart event: 61013 // start: function (e) {}, // .bind('fileuploadstart', func); 61014 61015 // Callback for uploads stop, equivalent to the global ajaxStop event: 61016 // stop: function (e) {}, // .bind('fileuploadstop', func); 61017 61018 // Callback for change events of the fileInput(s): 61019 // change: function (e, data) {}, // .bind('fileuploadchange', func); 61020 61021 // Callback for paste events to the pasteZone(s): 61022 // paste: function (e, data) {}, // .bind('fileuploadpaste', func); 61023 61024 // Callback for drop events of the dropZone(s): 61025 // drop: function (e, data) {}, // .bind('fileuploaddrop', func); 61026 61027 // Callback for dragover events of the dropZone(s): 61028 // dragover: function (e) {}, // .bind('fileuploaddragover', func); 61029 61030 // Callback for the start of each chunk upload request: 61031 // chunksend: function (e, data) {}, // .bind('fileuploadchunksend', func); 61032 61033 // Callback for successful chunk uploads: 61034 // chunkdone: function (e, data) {}, // .bind('fileuploadchunkdone', func); 61035 61036 // Callback for failed (abort or error) chunk uploads: 61037 // chunkfail: function (e, data) {}, // .bind('fileuploadchunkfail', func); 61038 61039 // Callback for completed (success, abort or error) chunk upload requests: 61040 // chunkalways: function (e, data) {}, // .bind('fileuploadchunkalways', func); 61041 61042 // The plugin options are used as settings object for the ajax calls. 61043 // The following are jQuery ajax settings required for the file uploads: 61044 processData: false, 61045 contentType: false, 61046 cache: false, 61047 timeout: 0 61048 }, 61049 61050 // A list of options that require reinitializing event listeners and/or 61051 // special initialization code: 61052 _specialOptions: [ 61053 'fileInput', 61054 'dropZone', 61055 'pasteZone', 61056 'multipart', 61057 'forceIframeTransport' 61058 ], 61059 61060 _blobSlice: $.support.blobSlice && function () { 61061 var slice = this.slice || this.webkitSlice || this.mozSlice; 61062 return slice.apply(this, arguments); 61063 }, 61064 61065 _BitrateTimer: function () { 61066 this.timestamp = ((Date.now) ? Date.now() : (new Date()).getTime()); 61067 this.loaded = 0; 61068 this.bitrate = 0; 61069 this.getBitrate = function (now, loaded, interval) { 61070 var timeDiff = now - this.timestamp; 61071 if (!this.bitrate || !interval || timeDiff > interval) { 61072 this.bitrate = (loaded - this.loaded) * (1000 / timeDiff) * 8; 61073 this.loaded = loaded; 61074 this.timestamp = now; 61075 } 61076 return this.bitrate; 61077 }; 61078 }, 61079 61080 _isXHRUpload: function (options) { 61081 return !options.forceIframeTransport && 61082 ((!options.multipart && $.support.xhrFileUpload) || 61083 $.support.xhrFormDataFileUpload); 61084 }, 61085 61086 _getFormData: function (options) { 61087 var formData; 61088 if ($.type(options.formData) === 'function') { 61089 return options.formData(options.form); 61090 } 61091 if ($.isArray(options.formData)) { 61092 return options.formData; 61093 } 61094 if ($.type(options.formData) === 'object') { 61095 formData = []; 61096 $.each(options.formData, function (name, value) { 61097 formData.push({name: name, value: value}); 61098 }); 61099 return formData; 61100 } 61101 return []; 61102 }, 61103 61104 _getTotal: function (files) { 61105 var total = 0; 61106 $.each(files, function (index, file) { 61107 total += file.size || 1; 61108 }); 61109 return total; 61110 }, 61111 61112 _initProgressObject: function (obj) { 61113 var progress = { 61114 loaded: 0, 61115 total: 0, 61116 bitrate: 0 61117 }; 61118 if (obj._progress) { 61119 $.extend(obj._progress, progress); 61120 } else { 61121 obj._progress = progress; 61122 } 61123 }, 61124 61125 _initResponseObject: function (obj) { 61126 var prop; 61127 if (obj._response) { 61128 for (prop in obj._response) { 61129 if (obj._response.hasOwnProperty(prop)) { 61130 delete obj._response[prop]; 61131 } 61132 } 61133 } else { 61134 obj._response = {}; 61135 } 61136 }, 61137 61138 _onProgress: function (e, data) { 61139 if (e.lengthComputable) { 61140 var now = ((Date.now) ? Date.now() : (new Date()).getTime()), 61141 loaded; 61142 if (data._time && data.progressInterval && 61143 (now - data._time < data.progressInterval) && 61144 e.loaded !== e.total) { 61145 return; 61146 } 61147 data._time = now; 61148 loaded = Math.floor( 61149 e.loaded / e.total * (data.chunkSize || data._progress.total) 61150 ) + (data.uploadedBytes || 0); 61151 // Add the difference from the previously loaded state 61152 // to the global loaded counter: 61153 this._progress.loaded += (loaded - data._progress.loaded); 61154 this._progress.bitrate = this._bitrateTimer.getBitrate( 61155 now, 61156 this._progress.loaded, 61157 data.bitrateInterval 61158 ); 61159 data._progress.loaded = data.loaded = loaded; 61160 data._progress.bitrate = data.bitrate = data._bitrateTimer.getBitrate( 61161 now, 61162 loaded, 61163 data.bitrateInterval 61164 ); 61165 // Trigger a custom progress event with a total data property set 61166 // to the file size(s) of the current upload and a loaded data 61167 // property calculated accordingly: 61168 this._trigger( 61169 'progress', 61170 $.Event('progress', {delegatedEvent: e}), 61171 data 61172 ); 61173 // Trigger a global progress event for all current file uploads, 61174 // including ajax calls queued for sequential file uploads: 61175 this._trigger( 61176 'progressall', 61177 $.Event('progressall', {delegatedEvent: e}), 61178 this._progress 61179 ); 61180 } 61181 }, 61182 61183 _initProgressListener: function (options) { 61184 var that = this, 61185 xhr = options.xhr ? options.xhr() : $.ajaxSettings.xhr(); 61186 // Accesss to the native XHR object is required to add event listeners 61187 // for the upload progress event: 61188 if (xhr.upload) { 61189 $(xhr.upload).bind('progress', function (e) { 61190 var oe = e.originalEvent; 61191 // Make sure the progress event properties get copied over: 61192 e.lengthComputable = oe.lengthComputable; 61193 e.loaded = oe.loaded; 61194 e.total = oe.total; 61195 that._onProgress(e, options); 61196 }); 61197 options.xhr = function () { 61198 return xhr; 61199 }; 61200 } 61201 }, 61202 61203 _isInstanceOf: function (type, obj) { 61204 // Cross-frame instanceof check 61205 return Object.prototype.toString.call(obj) === '[object ' + type + ']'; 61206 }, 61207 61208 _initXHRData: function (options) { 61209 var that = this, 61210 formData, 61211 file = options.files[0], 61212 // Ignore non-multipart setting if not supported:
61213 multipart = options.multipart || !$.support.xhrFileUpload, 61214 paramName = $.type(options.paramName) === 'array' ? 61215 options.paramName[0] : options.paramName; 61216 options.headers = $.extend({}, options.headers); 61217 if (options.contentRange) { 61218 options.headers['Content-Range'] = options.contentRange; 61219 } 61220 if (!multipart || options.blob || !this._isInstanceOf('File', file)) { 61221 options.headers['Content-Disposition'] = 'attachment; filename="' + 61222 encodeURI(file.name) + '"'; 61223 } 61224 if (!multipart) { 61225 options.contentType = file.type || 'application/octet-stream'; 61226 options.data = options.blob || file; 61227 } else if ($.support.xhrFormDataFileUpload) { 61228 if (options.postMessage) { 61229 // window.postMessage does not allow sending FormData 61230 // objects, so we just add the File/Blob objects to 61231 // the formData array and let the postMessage window 61232 // create the FormData object out of this array: 61233 formData = this._getFormData(options); 61234 if (options.blob) { 61235 formData.push({ 61236 name: paramName, 61237 value: options.blob 61238 }); 61239 } else { 61240 $.each(options.files, function (index, file) { 61241 formData.push({ 61242 name: ($.type(options.paramName) === 'array' && 61243 options.paramName[index]) || paramName, 61244 value: file 61245 }); 61246 }); 61247 } 61248 } else { 61249 if (that._isInstanceOf('FormData', options.formData)) { 61250 formData = options.formData; 61251 } else { 61252 formData = new FormData(); 61253 $.each(this._getFormData(options), function (index, field) { 61254 formData.append(field.name, field.value); 61255 }); 61256 } 61257 if (options.blob) { 61258 formData.append(paramName, options.blob, file.name); 61259 } else { 61260 $.each(options.files, function (index, file) { 61261 // This check allows the tests to run with 61262 // dummy objects: 61263 if (that._isInstanceOf('File', file) || 61264 that._isInstanceOf('Blob', file)) { 61265 formData.append( 61266 ($.type(options.paramName) === 'array' && 61267 options.paramName[index]) || paramName, 61268 file, 61269 file.uploadName || file.name 61270 ); 61271 } 61272 }); 61273 } 61274 } 61275 options.data = formData; 61276 } 61277 // Blob reference is not needed anymore, free memory: 61278 options.blob = null; 61279 }, 61280 61281 _initIframeSettings: function (options) { 61282 var targetHost = $('<a></a>').prop('href', options.url).prop('host'); 61283 // Setting the dataType to iframe enables the iframe transport: 61284 options.dataType = 'iframe ' + (options.dataType || ''); 61285 // The iframe transport accepts a serialized array as form data: 61286 options.formData = this._getFormData(options); 61287 // Add redirect url to form data on cross-domain uploads: 61288 if (options.redirect && targetHost && targetHost !== location.host) { 61289 options.formData.push({ 61290 name: options.redirectParamName || 'redirect', 61291 value: options.redirect 61292 }); 61293 } 61294 }, 61295 61296 _initDataSettings: function (options) { 61297 if (this._isXHRUpload(options)) { 61298 if (!this._chunkedUpload(options, true)) { 61299 if (!options.data) { 61300 this._initXHRData(options); 61301 } 61302 this._initProgressListener(options); 61303 } 61304 if (options.postMessage) { 61305 // Setting the dataType to postmessage enables the 61306 // postMessage transport: 61307 options.dataType = 'postmessage ' + (options.dataType || ''); 61308 } 61309 } else { 61310 this._initIframeSettings(options); 61311 } 61312 }, 61313 61314 _getParamName: function (options) { 61315 var fileInput = $(options.fileInput), 61316 paramName = options.paramName; 61317 if (!paramName) { 61318 paramName = []; 61319 fileInput.each(function () { 61320 var input = $(this), 61321 name = input.prop('name') || 'files[]', 61322 i = (input.prop('files') || [1]).length; 61323 while (i) { 61324 paramName.push(name); 61325 i -= 1; 61326 } 61327 }); 61328 if (!paramName.length) { 61329 paramName = [fileInput.prop('name') || 'files[]']; 61330 } 61331 } else if (!$.isArray(paramName)) { 61332 paramName = [paramName]; 61333 } 61334 return paramName; 61335 }, 61336 61337 _initFormSettings: function (options) { 61338 // Retrieve missing options from the input field and the 61339 // associated form, if available: 61340 if (!options.form || !options.form.length) { 61341 options.form = $(options.fileInput.prop('form')); 61342 // If the given file input doesn't have an associated form, 61343 // use the default widget file input's form: 61344 if (!options.form.length) { 61345 options.form = $(this.options.fileInput.prop('form')); 61346 } 61347 } 61348 options.paramName = this._getParamName(options); 61349 if (!options.url) { 61350 options.url = options.form.prop('action') || location.href; 61351 } 61352 // The HTTP request method must be "POST" or "PUT": 61353 options.type = (options.type || 61354 ($.type(options.form.prop('method')) === 'string' && 61355 options.form.prop('method')) || '' 61356 ).toUpperCase(); 61357 if (options.type !== 'POST' && options.type !== 'PUT' && 61358 options.type !== 'PATCH') { 61359 options.type = 'POST'; 61360 } 61361 if (!options.formAcceptCharset) { 61362 options.formAcceptCharset = options.form.attr('accept-charset'); 61363 } 61364 }, 61365 61366 _getAJAXSettings: function (data) { 61367 var options = $.extend({}, this.options, data); 61368 this._initFormSettings(options); 61369 this._initDataSettings(options); 61370 return options; 61371 }, 61372 61373 // jQuery 1.6 doesn't provide .state(), 61374 // while jQuery 1.8+ removed .isRejected() and .isResolved(): 61375 _getDeferredState: function (deferred) { 61376 if (deferred.state) { 61377 return deferred.state(); 61378 } 61379 if (deferred.isResolved()) { 61380 return 'resolved'; 61381 } 61382 if (deferred.isRejected()) { 61383 return 'rejected'; 61384 } 61385 return 'pending'; 61386 }, 61387 61388 // Maps jqXHR callbacks to the equivalent 61389 // methods of the given Promise object: 61390 _enhancePromise: function (promise) { 61391 promise.success = promise.done; 61392 promise.error = promise.fail; 61393 promise.complete = promise.always; 61394 return promise; 61395 }, 61396 61397 // Creates and returns a Promise object enhanced with 61398 // the jqXHR methods abort, success, error and complete: 61399 _getXHRPromise: function (resolveOrReject, context, args
61399) { 61400 var dfd = $.Deferred(), 61401 promise = dfd.promise(); 61402 context = context || this.options.context || promise; 61403 if (resolveOrReject === true) { 61404 dfd.resolveWith(context, args); 61405 } else if (resolveOrReject === false) { 61406 dfd.rejectWith(context, args); 61407 } 61408 promise.abort = dfd.promise; 61409 return this._enhancePromise(promise); 61410 }, 61411 61412 // Adds convenience methods to the data callback argument: 61413 _addConvenienceMethods: function (e, data) { 61414 var that = this, 61415 getPromise = function (args) { 61416 return $.Deferred().resolveWith(that, args).promise(); 61417 }; 61418 data.process = function (resolveFunc, rejectFunc) { 61419 if (resolveFunc || rejectFunc) { 61420 data._processQueue = this._processQueue = 61421 (this._processQueue || getPromise([this])).then( 61422 function () { 61423 if (data.errorThrown) { 61424 return $.Deferred() 61425 .rejectWith(that, [data]).promise(); 61426 } 61427 return getPromise(arguments); 61428 } 61429 ).then(resolveFunc, rejectFunc); 61430 } 61431 return this._processQueue || getPromise([this]); 61432 }; 61433 data.submit = function () { 61434 if (this.state() !== 'pending') { 61435 data.jqXHR = this.jqXHR = 61436 (that._trigger( 61437 'submit', 61438 $.Event('submit', {delegatedEvent: e}), 61439 this 61440 ) !== false) && that._onSend(e, this); 61441 } 61442 return this.jqXHR || that._getXHRPromise(); 61443 }; 61444 data.abort = function () { 61445 if (this.jqXHR) { 61446 return this.jqXHR.abort(); 61447 } 61448 this.errorThrown = 'abort'; 61449 that._trigger('fail', null, this); 61450 return that._getXHRPromise(false); 61451 }; 61452 data.state = function () { 61453 if (this.jqXHR) { 61454 return that._getDeferredState(this.jqXHR); 61455 } 61456 if (this._processQueue) { 61457 return that._getDeferredState(this._processQueue); 61458 } 61459 }; 61460 data.processing = function () { 61461 return !this.jqXHR && this._processQueue && that 61462 ._getDeferredState(this._processQueue) === 'pending'; 61463 }; 61464 data.progress = function () { 61465 return this._progress; 61466 }; 61467 data.response = function () { 61468 return this._response; 61469 }; 61470 }, 61471 61472 // Parses the Range header from the server response 61473 // and returns the uploaded bytes: 61474 _getUploadedBytes: function (jqXHR) { 61475 var range = jqXHR.getResponseHeader('Range'), 61476 parts = range && range.split('-'), 61477 upperBytesPos = parts && parts.length > 1 && 61478 parseInt(parts[1], 10); 61479 return upperBytesPos && upperBytesPos + 1; 61480 }, 61481 61482 // Uploads a file in multiple, sequential requests 61483 // by splitting the file up in multiple blob chunks. 61484 // If the second parameter is true, only tests if the file 61485 // should be uploaded in chunks, but does not invoke any 61486 // upload requests: 61487 _chunkedUpload: function (options, testOnly) { 61488 options.uploadedBytes = options.uploadedBytes || 0; 61489 var that = this, 61490 file = options.files[0], 61491 fs = file.size, 61492 ub = options.uploadedBytes, 61493 mcs = options.maxChunkSize || fs, 61494 slice = this._blobSlice, 61495 dfd = $.Deferred(), 61496 promise = dfd.promise(), 61497 jqXHR, 61498 upload; 61499 if (!(this._isXHRUpload(options) && slice && (ub || mcs < fs)) || 61500 options.data) { 61501 return false;
61502 } 61503 if (testOnly) { 61504 return true; 61505 } 61506 if (ub >= fs) { 61507 file.error = options.i18n('uploadedBytes'); 61508 return this._getXHRPromise( 61509 false, 61510 options.context, 61511 [null, 'error', file.error] 61512 ); 61513 } 61514 // The chunk upload method: 61515 upload = function () { 61516 // Clone the options object for each chunk upload: 61517 var o = $.extend({}, options), 61518 currentLoaded = o._progress.loaded; 61519 o.blob = slice.call( 61520 file, 61521 ub, 61522 ub + mcs, 61523 file.type 61524 ); 61525 // Store the current chunk size, as the blob itself 61526 // will be dereferenced after data processing: 61527 o.chunkSize = o.blob.size; 61528 // Expose the chunk bytes position range: 61529 o.contentRange = 'bytes ' + ub + '-' + 61530 (ub + o.chunkSize - 1) + '/' + fs; 61531 // Process the upload data (the blob and potential form data): 61532 that._initXHRData(o); 61533 // Add progress listeners for this chunk upload: 61534 that._initProgressListener(o); 61535 jqXHR = ((that._trigger('chunksend', null, o) !== false && $.ajax(o)) || 61536 that._getXHRPromise(false, o.context)) 61537 .done(function (result, textStatus, jqXHR) { 61538 ub = that._getUploadedBytes(jqXHR) || 61539 (ub + o.chunkSize); 61540 // Create a progress event if no final progress event 61541 // with loaded equaling total has been triggered 61542 // for this chunk: 61543 if (currentLoaded + o.chunkSize - o._progress.loaded) { 61544 that._onProgress($.Event('progress', { 61545 lengthComputable: true, 61546 loaded: ub - o.uploadedBytes, 61547 total: ub - o.uploadedBytes 61548 }), o); 61549 } 61550 options.uploadedBytes = o.uploadedBytes = ub; 61551 o.result = result; 61552 o.textStatus = textStatus; 61553 o.jqXHR = jqXHR; 61554 that._trigger('chunkdone', null, o); 61555 that._trigger('chunkalways', null, o); 61556 if (ub < fs) { 61557 // File upload not yet complete, 61558 // continue with the next chunk: 61559 upload(); 61560 } else { 61561 dfd.resolveWith( 61562 o.context, 61563 [result, textStatus, jqXHR] 61564 ); 61565 } 61566 }) 61567 .fail(function (jqXHR, textStatus, errorThrown) { 61568 o.jqXHR = jqXHR; 61569 o.textStatus = textStatus; 61570 o.errorThrown = errorThrown; 61571 that._trigger('chunkfail', null, o); 61572 that._trigger('chunkalways', null, o); 61573 dfd.rejectWith( 61574 o.context, 61575 [jqXHR, textStatus, errorThrown] 61576 ); 61577 }); 61578 }; 61579 this._enhancePromise(promise); 61580 promise.abort = function () { 61581 return jqXHR.abort(); 61582 }; 61583 upload(); 61584 return promise; 61585 }, 61586 61587 _beforeSend: function (e, data) { 61588 if (this._active === 0) { 61589 // the start callback is triggered when an upload starts 61590 // and no other uploads are currently running, 61591 // equivalent to the global ajaxStart event: 61592 this._trigger('start'); 61593 // Set timer for global bitrate progress calculation: 61594 this._bitrateTimer = new this._BitrateTimer(); 61595 // Reset the global progress values: 61596 this._progress.loaded = this._progress.total = 0; 61597 this._progress.bitrate = 0; 61598 } 61599 // Make sure the container objects for the .response() and 61600 // .progress() methods on the data object are available 61601 // and reset to their initial state: 61602 this._initResponseObject(data); 61603 this._initProgressObject(data); 61604 data._progress.loaded = data.loaded = data.uploadedBytes || 0; 61605 data._progress.total = data.total = this._getTotal(data.files) || 1; 61606 data._progress.bitrate = data.bitrate = 0; 61607 this._active += 1; 61608 // Initialize the global progress values: 61609 this._progress.loaded += data.loaded; 61610 this._progress.total += data.total; 61611 }, 61612 61613 _onDone: function (result, textStatus, jqXHR, options) { 61614 var total = options._progress.total, 61615 response = options._response; 61616 if (options._progress.loaded < total) { 61617 // Create a progress event if no final progress event 61618 // with loaded equaling total has been triggered: 61619 this._onProgress($.Event('progress', { 61620 lengthComputable: true, 61621 loaded: total, 61622 total: total 61623 }), options); 61624 } 61625 response.result = options.result = result; 61626 response.textStatus = options.textStatus = textStatus; 61627 response.jqXHR = options.jqXHR = jqXHR; 61628 this._trigger('done', null, options); 61629 }, 61630 61631 _onFail: function (jqXHR, textStatus, errorThrown, options) { 61632 var response = options._response; 61633 if (options.recalculateProgress) { 61634 // Remove the failed (error or abort) file upload from 61635 // the global progress calculation: 61636 this._progress.loaded -= options._progress.loaded;
61637 this._progress.total -= options._progress.total; 61638 } 61639 response.jqXHR = options.jqXHR = jqXHR; 61640 response.textStatus = options.textStatus = textStatus; 61641 response.errorThrown = options.errorThrown = errorThrown; 61642 this._trigger('fail', null, options); 61643 }, 61644 61645 _onAlways: function (jqXHRorResult, textStatus, jqXHRorError, options) { 61646 // jqXHRorResult, textStatus and jqXHRorError are added to the 61647 // options object via done and fail callbacks 61648 this._trigger('always', null, options); 61649 }, 61650 61651 _onSend: function (e, data) { 61652 if (!data.submit) { 61653 this._addConvenienceMethods(e, data); 61654 } 61655 var that = this, 61656 jqXHR, 61657 aborted, 61658 slot, 61659 pipe, 61660 options = that._getAJAXSettings(data), 61661 send = function () { 61662 that._sending += 1; 61663 // Set timer for bitrate progress calculation: 61664 options._bitrateTimer = new that._BitrateTimer(); 61665 jqXHR = jqXHR || ( 61666 ((aborted || that._trigger( 61667 'send', 61668 $.Event('send', {delegatedEvent: e}), 61669 options 61670 ) === false) && 61671 that._getXHRPromise(false, options.context, aborted)) || 61672 that._chunkedUpload(options) || $.ajax(options) 61673 ).done(function (result, textStatus, jqXHR) { 61674 that._onDone(result, textStatus, jqXHR, options); 61675 }).fail(function (jqXHR, textStatus, errorThrown) { 61676 that._onFail(jqXHR, textStatus, errorThrown, options); 61677 }).always(function (jqXHRorResult, textStatus, jqXHRorError) { 61678 that._onAlways( 61679 jqXHRorResult, 61680 textStatus, 61681 jqXHRorError, 61682 options 61683 ); 61684 that._sending -= 1; 61685 that._active -= 1; 61686 if (options.limitConcurrentUploads && 61687 options.limitConcurrentUploads > that._sending) { 61688 // Start the next queued upload, 61689 // that has not been aborted: 61690 var nextSlot = that._slots.shift(); 61691 while (nextSlot) { 61692 if (that._getDeferredState(nextSlot) === 'pending') { 61693 nextSlot.resolve(); 61694 break; 61695 } 61696 nextSlot = that._slots.shift(); 61697 } 61698 } 61699 if (that._active === 0) { 61700 // The stop callback is triggered when all uploads have 61701 // been completed, equivalent to the global ajaxStop event: 61702 that._trigger('stop'); 61703 } 61704 }); 61705 return jqXHR; 61706 }; 61707 this._beforeSend(e, options); 61708 if (this.options.sequentialUploads || 61709 (this.options.limitConcurrentUploads && 61710 this.options.limitConcurrentUploads <= this._sending)) { 61711 if (this.options.limitConcurrentUploads > 1) { 61712 slot = $.Deferred(); 61713 this._slots.push(slot); 61714 pipe = slot.then(send); 61715 } else { 61716 this._sequence = this._sequence.then(send, send); 61717 pipe = this._sequence; 61718 } 61719 // Return the piped Promise object, enhanced with an abort method, 61720 // which is delegated to the jqXHR object of the current upload, 61721 // and jqXHR callbacks mapped to the equivalent Promise methods: 61722 pipe.abort = function () { 61723 aborted = [undefined, 'abort', 'abort']; 61724 if (!jqXHR) { 61725 if (slot) { 61726 slot.rejectWith(options.context, aborted); 61727 } 61728 return send(); 61729 } 61730 return jqXHR.abort(); 61731 }; 61732 return this._enhancePromise(pipe); 61733 } 61734 return send(); 61735 }, 61736 61737 _onAdd: function (e, data) { 61738 var that = this, 61739 result = true, 61740 options = $.extend({}, this.options, data), 61741 files = data.files, 61742 filesLength = files.length, 61743 limit = options.limitMultiFileUploads, 61744 limitSize = options.limitMultiFileUploadSize, 61745 overhead = options.limitMultiFileUploadSizeOverhead, 61746 batchSize = 0, 61747 paramName = this._getParamName(options), 61748 paramNameSet, 61749 paramNameSlice, 61750 fileSet, 61751 i, 61752 j = 0; 61753 if (!filesLength) { 61754 return false;
61755 } 61756 if (limitSize && files[0].size === undefined) { 61757 limitSize = undefined; 61758 } 61759 if (!(options.singleFileUploads || limit || limitSize) || 61760 !this._isXHRUpload(options)) { 61761 fileSet = [files]; 61762 paramNameSet = [paramName]; 61763 } else if (!(options.singleFileUploads || limitSize) && limit) { 61764 fileSet = []; 61765 paramNameSet = []; 61766 for (i = 0; i < filesLength; i += limit) { 61767 fileSet.push(files.slice(i, i + limit)); 61768 paramNameSlice = paramName.slice(i, i + limit); 61769 if (!paramNameSlice.length) { 61770 paramNameSlice = paramName; 61771 } 61772 paramNameSet.push(paramNameSlice); 61773 } 61774 } else if (!options.singleFileUploads && limitSize) { 61775 fileSet = []; 61776 paramNameSet = []; 61777 for (i = 0; i < filesLength; i = i + 1) { 61778 batchSize += files[i].size + overhead; 61779 if (i + 1 === filesLength || 61780 ((batchSize + files[i + 1].size + overhead) > limitSize) || 61781 (limit && i + 1 - j >= limit)) { 61782 fileSet.push(files.slice(j, i + 1)); 61783 paramNameSlice = paramName.slice(j, i + 1); 61784 if (!paramNameSlice.length) { 61785 paramNameSlice = paramName; 61786 } 61787 paramNameSet.push(paramNameSlice); 61788 j = i + 1; 61789 batchSize = 0; 61790 } 61791 } 61792 } else { 61793 paramNameSet = paramName; 61794 } 61795 data.originalFiles = files; 61796 $.each(fileSet || files, function (index, element) { 61797 var newData = $.extend({}, data); 61798 newData.files = fileSet ? element : [element]; 61799 newData.paramName = paramNameSet[index]; 61800 that._initResponseObject(newData); 61801 that._initProgressObject(newData); 61802 that._addConvenienceMethods(e, newData); 61803 result = that._trigger( 61804 'add', 61805 $.Event('add', {delegatedEvent: e}), 61806 newData 61807 ); 61808 return result; 61809 }); 61810 return result; 61811 }, 61812 61813 _replaceFileInput: function (data) { 61814 var input = data.fileInput, 61815 inputClone = input.clone(true), 61816 restoreFocus = input.is(document.activeElement); 61817 // Add a reference for the new cloned file input to the data argument: 61818 data.fileInputClone = inputClone; 61819 $('<form></form>').append(inputClone)[0].reset(); 61820 // Detaching allows to insert the fileInput on another form 61821 // without loosing the file input value: 61822 input.after(inputClone).detach(); 61823 // If the fileInput had focus before it was detached, 61824 // restore focus to the inputClone. 61825 if (restoreFocus) { 61826 inputClone.focus(); 61827 } 61828 // Avoid memory leaks with the detached file input: 61829 $.cleanData(input.unbind('remove')); 61830 // Replace the original file input element in the fileInput 61831 // elements set with the clone, which has been copied including 61832 // event handlers: 61833 this.options.fileInput = this.options.fileInput.map(function (i, el) { 61834 if (el === input[0]) { 61835 return inputClone[0]; 61836 } 61837 return el; 61838 }); 61839 // If the widget has been initialized on the file input itself, 61840 // override this.element with the file input clone: 61841 if (input[0] === this.element[0]) { 61842 this.element = inputClone; 61843 } 61844 }, 61845 61846 _handleFileTreeEntry: function (entry, path) { 61847 var that = this, 61848 dfd = $.Deferred(),
61849 entries = [], 61850 dirReader, 61851 errorHandler = function (e) { 61852 if (e && !e.entry) { 61853 e.entry = entry; 61854 } 61855 // Since $.when returns immediately if one 61856 // Deferred is rejected, we use resolve instead. 61857 // This allows valid files and invalid items 61858 // to be returned together in one set: 61859 dfd.resolve([e]); 61860 }, 61861 successHandler = function (entries) { 61862 that._handleFileTreeEntries( 61863 entries, 61864 path + entry.name + '/' 61865 ).done(function (files) { 61866 dfd.resolve(files); 61867 }).fail(errorHandler); 61868 }, 61869 readEntries = function () { 61870 dirReader.readEntries(function (results) { 61871 if (!results.length) { 61872 successHandler(entries); 61873 } else { 61874 entries = entries.concat(results); 61875 readEntries(); 61876 } 61877 }, errorHandler); 61878 }; 61879 path = path || ''; 61880 if (entry.isFile) { 61881 if (entry._file) { 61882 // Workaround for Chrome bug #149735 61883 entry._file.relativePath = path; 61884 dfd.resolve(entry._file); 61885 } else { 61886 entry.file(function (file) { 61887 file.relativePath = path; 61888 dfd.resolve(file); 61889 }, errorHandler); 61890 } 61891 } else if (entry.isDirectory) { 61892 dirReader = entry.createReader(); 61893 readEntries(); 61894 } else { 61895 // Return an empy list for file system items 61896 // other than files or directories: 61897 dfd.resolve([]); 61898 } 61899 return dfd.promise(); 61900 }, 61901 61902 _handleFileTreeEntries: function (entries, path) { 61903 var that = this; 61904 return $.when.apply( 61905 $, 61906 $.map(entries, function (entry) { 61907 return that._handleFileTreeEntry(entry, path); 61908 }) 61909 ).then(function () { 61910 return Array.prototype.concat.apply( 61911 [], 61912 arguments 61913 ); 61914 }); 61915 }, 61916 61917 _getDroppedFiles: function (dataTransfer) { 61918 dataTransfer = dataTransfer || {}; 61919 var items = dataTransfer.items; 61920 if (items && items.length && (items[0].webkitGetAsEntry || 61921 items[0].getAsEntry)) { 61922 return this._handleFileTreeEntries( 61923 $.map(items, function (item) { 61924 var entry; 61925 if (item.webkitGetAsEntry) { 61926 entry = item.webkitGetAsEntry(); 61927 if (entry) { 61928 // Workaround for Chrome bug #149735: 61929 entry._file = item.getAsFile(); 61930 } 61931 return entry; 61932 } 61933 return item.getAsEntry(); 61934 }) 61935 ); 61936 } 61937 return $.Deferred().resolve( 61938 $.makeArray(dataTransfer.files) 61939 ).promise(); 61940 }, 61941 61942 _getSingleFileInputFiles: function (fileInput) { 61943 fileInput = $(fileInput); 61944 var entries = fileInput.prop('webkitEntries') || 61945 fileInput.prop('entries'), 61946 files, 61947 value; 61948 if (entries && entries.length) { 61949 return this._handleFileTreeEntries(entries); 61950 } 61951 files = $.makeArray(fileInput.prop('files')); 61952 if (!files.length) { 61953 value = fileInput.prop('value'); 61954 if (!value) { 61955 return $.Deferred().resolve([]).promise(); 61956 } 61957 // If the files property is not available, the browser does not 61958 // support the File API and we add a pseudo File object with 61959 // the input value as name with path information removed: 61960 files = [{name: value.replace(/^.*\\/, '')}]; 61961 } else if (files[0].name === undefined && files[0].fileName) { 61962 // File normalization for Safari 4 and Firefox 3: 61963 $.each(files, function (index, file) { 61964 file.name = file.fileName; 61965 file.size = file.fileSize; 61966 }); 61967 } 61968 return $.Deferred().resolve(files).promise(); 61969 }, 61970 61971 _getFileInputFiles: function (fileInput) { 61972 if (!(fileInput instanceof $) || fileInput.length === 1) { 61973 return this._getSingleFileInputFiles(fileInput); 61974 } 61975 return $.when.apply( 61976 $, 61977 $.map(fileInput, this._getSingleFileInputFiles) 61978 ).then(function () { 61979 return Array.prototype.concat.apply( 61980 [], 61981 arguments 61982 ); 61983 }); 61984 }, 61985 61986 _onChange: function (e) { 61987 var that = this, 61988 data = { 61989 fileInput: $(e.target), 61990 form: $(e.target.form) 61991 }; 61992 this._getFileInputFiles(data.fileInput).always(function (files) { 61993 data.files = files; 61994 if (that.options.replaceFileInput) { 61995 that._replaceFileInput(data); 61996 } 61997 if (that._trigger( 61998 'change', 61999 $.Event('change', {delegatedEvent: e}), 62000 data 62001 ) !== false) { 62002 that._onAdd(e, data); 62003 } 62004 }); 62005 }, 62006 62007 _onPaste: function (e) { 62008 var items = e.originalEvent && e.originalEvent.clipboardData && 62009 e.originalEvent.clipboardData.items, 62010 data = {files: []}; 62011 if (items && items.length) { 62012 $.each(items, function (index, item) { 62013 var file = item.getAsFile && item.getAsFile(); 62014 if (file) { 62015 data.files.push(file); 62016 } 62017 }); 62018 if (this._trigger( 62019 'paste', 62020 $.Event('paste', {delegatedEvent: e}), 62021 data 62022 ) !== false) { 62023 this._onAdd(e, data); 62024 } 62025 } 62026 }, 62027 62028 _onDrop: function (e) { 62029 e.dataTransfer = e.originalEvent && e.originalEvent.dataTransfer; 62030 var that = this, 62031 dataTransfer = e.dataTransfer, 62032 data = {}; 62033 if (dataTransfer && dataTransfer.files && dataTransfer.files.length) { 62034 e.preventDefault(); 62035 this._getDroppedFiles(dataTransfer).always(function (files) { 62036 data.files = files; 62037 if (that._trigger( 62038 'drop', 62039 $.Event('drop', {delegatedEvent: e}), 62040 data 62041 ) !== false) { 62042 that._onAdd(e, data); 62043 } 62044 }); 62045 } 62046 }, 62047 62048 _onDragOver: getDragHandler('dragover'), 62049 62050 _onDragEnter: getDragHandler('dragenter'), 62051 62052 _onDragLeave: getDragHandler('dragleave'), 62053 62054 _initEventHandlers: function () { 62055 if (this._isXHRUpload(this.options)) { 62056 this._on(this.options.dropZone, { 62057 dragover: this._onDragOver, 62058 drop: this._onDrop, 62059 // event.preventDefault() on dragenter is required for IE10+: 62060 dragenter: this._onDragEnter, 62061 // dragleave is not required, but added for c
62061ompleteness: 62062 dragleave: this._onDragLeave 62063 }); 62064 this._on(this.options.pasteZone, { 62065 paste: this._onPaste 62066 }); 62067 } 62068 if ($.support.fileInput) { 62069 this._on(this.options.fileInput, { 62070 change: this._onChange 62071 }); 62072 } 62073 }, 62074 62075 _destroyEventHandlers: function () { 62076 this._off(this.options.dropZone, 'dragenter dragleave dragover drop'); 62077 this._off(this.options.pasteZone, 'paste'); 62078 this._off(this.options.fileInput, 'change'); 62079 }, 62080 62081 _destroy: function () { 62082 this._destroyEventHandlers(); 62083 }, 62084 62085 _setOption: function (key, value) { 62086 var reinit = $.inArray(key, this._specialOptions) !== -1; 62087 if (reinit) { 62088 this._destroyEventHandlers(); 62089 } 62090 this._super(key, value); 62091 if (reinit) { 62092 this._initSpecialOptions(); 62093 this._initEventHandlers(); 62094 } 62095 }, 62096 62097 _initSpecialOptions: function () { 62098 var options = this.options; 62099 if (options.fileInput === undefined) { 62100 options.fileInput = this.element.is('input[type="file"]') ? 62101 this.element : this.element.find('input[type="file"]'); 62102 } else if (!(options.fileInput instanceof $)) { 62103 options.fileInput = $(options.fileInput); 62104 } 62105 if (!(options.dropZone instanceof $)) { 62106 options.dropZone = $(options.dropZone); 62107 } 62108 if (!(options.pasteZone instanceof $)) { 62109 options.pasteZone = $(options.pasteZone); 62110 } 62111 }, 62112 62113 _getRegExp: function (str) { 62114 var parts = str.split('/'), 62115 modifiers = parts.pop(); 62116 parts.shift(); 62117 return new RegExp(parts.join('/'), modifiers); 62118 }, 62119 62120 _isRegExpOption: function (key, value) { 62121 return key !== 'url' && $.type(value) === 'string' && 62122 /^\/.*\/[igm]{0,3}$/.test(value); 62123 }, 62124 62125 _initDataAttributes: function () { 62126 var that = this, 62127 options = this.options, 62128 data = this.element.data(); 62129 // Initialize options set via HTML5 data-attributes: 62130 $.each( 62131 this.element[0].attributes, 62132 function (index, attr) { 62133 var key = attr.name.toLowerCase(), 62134 value; 62135 if (/^data-/.test(key)) { 62136 // Convert hyphen-ated key to camelCase: 62137 key = key.slice(5).replace(/-[a-z]/g, function (str) { 62138 return str.charAt(1).toUpperCase(); 62139 }); 62140 value = data[key]; 62141 if (that._isRegExpOption(key, value)) { 62142 value = that._getRegExp(value); 62143 } 62144 options[key] = value; 62145 } 62146 } 62147 ); 62148 }, 62149 62150 _create: function () { 62151 this._initDataAttributes(); 62152 this._initSpecialOptions(); 62153 this._slots = []; 62154 this._sequence = this._getXHRPromise(true); 62155 this._sending = this._active = 0; 62156 this._initProgressObject(this); 62157 this._initEventHandlers(); 62158 }, 62159 62160 // This method is exposed to the widget API and allows to query 62161 // the number of active uploads: 62162 active: function () { 62163 return this._active; 62164 }, 62165 62166 // This method is exposed to the widget API and allows to query 62167 // the widget upload progress. 62168 // It returns an object with loaded, total and bitrate properties 62169 // for the running uploads: 62170 progress: function () { 62171 return this._progress; 62172 }, 62173 62174 // This method is exposed to the widget API and allows adding files 62175 // using the fileupload API. The data parameter accepts an object which 62176 // must have a files property and can contain additional options: 62177 // .fileupload('add', {files: filesList}); 62178 add: function (data) { 62179 var that = this; 62180 if (!data || this.options.disabled) { 62181 return; 62182 } 62183 if (data.fileInput && !data.files) { 62184 this._getFileInputFiles(data.fileInput).always(function (files) { 62185 data.files = files; 62186 that._onAdd(null, data); 62187 }); 62188 } else { 62189 data.files = $.makeArray(data.files); 62190 this._onAdd(null, data); 62191 } 62192 }, 62193 62194 // This method is exposed to the widget API and allows sending files 62195 // using the fileupload API. The data parameter accepts an object which 62196 // must have a files or fileInput property and can contain additional options: 62197 // .fileupload('send', {files: filesList}); 62198 // The method returns a Promise object for the file upload call. 62199 send: function (data) { 62200 if (data && !this.options.disabled) { 62201 if (data.fileInput && !data.files) { 62202 var that = this, 62203 dfd = $.Deferred(), 62204 promise = dfd.promise(), 62205 jqXHR, 62206 aborted; 62207 promise.abort = function () { 62208 aborted = true; 62209 if (jqXHR) { 62210 return jqXHR.abort(); 62211 } 62212 dfd.reject(null, 'abort', 'abort'); 62213 return promise; 62214 }; 62215 this._getFileInputFiles(data.fileInput).always( 62216 function (files) { 62217 if (aborted) { 62218 return; 62219 } 62220 if (!files.length) { 62221 dfd.reject(); 62222 return; 62223 } 62224 data.files = files; 62225 jqXHR = that._onSend(null, data); 62226 jqXHR.then( 62227 function (result, textStatus, jqXHR) { 62228 dfd.resolve(result, textStatus, jqXHR); 62229 }, 62230 function (jqXHR, textStatus, errorThrown) { 62231 dfd.reject(jqXHR, textStatus, errorThrown); 62232 } 62233 ); 62234 } 62235 ); 62236 return this._enhancePromise(promise); 62237 } 62238 data.files = $.makeArray(data.files); 62239 if (data.files.length) { 62240 return this._onSend(null, data); 62241 } 62242 } 62243 return this._getXHRPromise(false, data && data.context); 62244 } 62245 62246 }); 62247 62248})); 62249 62250/* 62251 * jQuery File Upload Processing Plugin 62252 * https://github.com/blueimp/jQuery-File-Upload 62253 * 62254 * Copyright 2012, Sebastian Tschan 62255 * https://blueimp.net 62256 * 62257 * Licensed under the MIT license: 62258 * http://www.opensource.org/licenses/MIT 62259 */ 62260 62261/* jshint nomen:false */ 62262/* global define, require, window */ 62263 62264;(function (factory) { 62265 'use strict'; 62266 if (typeof define === 'function' && define.amd) { 62267 // Register as an anonymous AMD module: 62268 define('jquery.fileupload-process',[ 62269 'jquery', 62270 './jquery.fileupload' 62271 ], factory); 62272 } else if (typeof exports === 'object') { 62273 // Node/CommonJS: 62274 factory(require('jquery')); 62275 } else { 62276 // Browser globals: 62277 factory( 62278 window.jQuery 62279 ); 62280 } 62281}(function ($) { 62282 'use strict'; 62283 62284 var originalAdd = $.blueimp.fileupload.prototype.options.add; 62285 62286 // The File Upload Processing plugin extends the fileupload widget 62287 // with file processing functionality: 62288 $.widget('blueimp.fileupload', $.blueimp.fileupload, { 62289 62290 options: { 62291 // The list of processing actions: 62292 processQueue: [ 62293 /* 62294 { 62295 action: 'log', 62296 type: 'debug' 62297 } 62298 */ 62299 ], 62300 add: function (e, data) { 62301 var $this = $(this); 62302 data.process(function () { 62303 return $this.fileupload('process', data); 62304 }); 62305 originalAdd.call(this, e, data); 62306 } 62307 }, 62308 62309 processActions: { 62310 /* 62311 log: function (data, options) { 62312 console[options.type]( 62313 'Processing "' + data.files[data.index].name + '"' 62314 ); 62315 } 62316 */ 62317 }, 62318 62319 _processFile: function (data, originalData) { 62320 var that = this, 62321 dfd = $.Deferred().resolveWith(that, [data]), 62322 chain = dfd.promise(); 62323 this._trigger('process', null, data); 62324 $.each(data.processQueue, function (i, settings) { 62325 var func = function (data) { 62326 if (originalData.errorThrown) { 62327 return $.Deferred() 62328 .rejectWith(that, [originalData]).promise(); 62329 } 62330 return that.processActions[settings.action].call( 62331 that, 62332 data, 62333 settings 62334 ); 62335 }; 62336 chain = chain.then(func, settings.always && func); 62337 }); 62338 chain 62339 .done(function () { 62340 that._trigger('processdone', null, data); 62341 that._trigger('processalways', null, data); 62342 }) 62343 .fail(function () { 62344 that._trigger('processfail', null, data); 62345 that._trigger('processalways', null, data); 62346 }); 62347 return chain; 62348 }, 62349 62350 // Replaces the settings of each processQueue item that 62351 // are strings starting with an "@", using the remaining 62352 // substring as key for the option map, 62353 // e.g. "@autoUpload" is replaced with options.autoUpload: 62354 _transformProcessQueue: function (options) { 62355 var processQueue = []; 62356 $.each(options.processQueue, function () { 62357 var settings = {}, 62358 action = this.action, 62359 prefix = this.prefix === true ? action : this.prefix; 62360 $.each(this, function (key, value) { 62361 if ($.type(value) === 'string' && 62362 value.charAt(0) === '@') { 62363 settings[key] = options[ 62364 value.slice(1) || (prefix ? prefix + 62365 key.charAt(0).toUpperCase() + key.slice(1) : key) 62366 ]; 62367 } else { 62368 settings[key] = value; 62369 } 62370 62371 }); 62372 processQueue.push(settings); 62373 }); 62374 options.processQueue = processQueue; 62375 }, 62376 62377 // Returns the number of files currently in the processsing queue: 62378 processing: function () { 62379 return this._processing; 62380 }, 62381 62382 // Processes the files given as files property of the data parameter, 62383 // returns a Promise object that allows to bind callbacks: 62384 process: function (data) { 62385 var that = this, 62386 options = $.extend({}, this.options, data); 62387 if (options.processQueue && options.processQueue.length) { 62388 this._transformProcessQueue(options); 62389 if (this._processing === 0) { 62390 this._trigger('processstart'); 62391 } 62392 $.each(data.files, function (index) { 62393 var opts = index ? $.extend({}, options) : options, 62394 func = function () { 62395 if (data.errorThrown) { 62396 return $.Deferred() 62397 .rejectWith(that, [data]).promise(); 62398 } 62399 return that._processFile(opts, data); 62400 }; 62401 opts.index = index;
62402 that._processing += 1; 62403 that._processingQueue = that._processingQueue.then(func, func) 62404 .always(function () { 62405 that._processing -= 1; 62406 if (that._processing === 0) { 62407 that._trigger('processstop'); 62408 } 62409 }); 62410 }); 62411 } 62412 return this._processingQueue; 62413 }, 62414 62415 _create: function () { 62416 this._super(); 62417 this._processing = 0; 62418 this._processingQueue = $.Deferred().resolveWith(this) 62419 .promise(); 62420 } 62421 62422 }); 62423 62424})); 62425 62426/* 62427 * JavaScript Load Image 62428 * https://github.com/blueimp/JavaScript-Load-Image 62429 * 62430 * Copyright 2011, Sebastian Tschan 62431 * https://blueimp.net 62432 * 62433 * Licensed under the MIT license: 62434 * http://www.opensource.org/licenses/MIT 62435 */ 62436 62437/*global define, module, window, document, URL, webkitURL, FileReader */ 62438 62439;(function ($) { 62440 'use strict' 62441 62442 // Loads an image for a given File object. 62443 // Invokes the callback with an img or optional canvas 62444 // element (if supported by the browser) as parameter: 62445 var loadImage = function (file, callback, options) { 62446 var img = document.createElement('img') 62447 var url 62448 var oUrl 62449 img.onerror = callback 62450 img.onload = function () { 62451 if (oUrl && !(options && options.noRevoke)) { 62452 loadImage.revokeObjectURL(oUrl) 62453 } 62454 if (callback) { 62455 callback(loadImage.scale(img, options)) 62456 } 62457 } 62458 if (loadImage.isInstanceOf('Blob', file) || 62459 // Files are also Blob instances, but some browsers 62460 // (Firefox 3.6) support the File API but not Blobs: 62461 loadImage.isInstanceOf('File', file)) { 62462 url = oUrl = loadImage.createObjectURL(file) 62463 // Store the file type for resize processing: 62464 img._type = file.type 62465 } else if (typeof file === 'string') { 62466 url = file 62467 if (options && options.crossOrigin) { 62468 img.crossOrigin = options.crossOrigin 62469 } 62470 } else { 62471 return false 62472 } 62473 if (url) { 62474 img.src = url 62475 return img 62476 } 62477 return loadImage.readFile(file, function (e) { 62478 var target = e.target 62479 if (target && target.result) { 62480 img.src = target.result 62481 } else { 62482 if (callback) { 62483 callback(e) 62484 } 62485 } 62486 }) 62487 } 62488 // The check for URL.revokeObjectURL fixes an issue with Opera 12, 62489 // which provides URL.createObjectURL but doesn't properly implement it: 62490 var urlAPI = (window.createObjectURL && window) || 62491 (window.URL && URL.revokeObjectURL && URL) || 62492 (window.webkitURL && webkitURL) 62493 62494 loadImage.isInstanceOf = function (type, obj) { 62495 // Cross-frame instanceof check 62496 return Object.prototype.toString.call(obj) === '[object ' + type + ']' 62497 } 62498 62499 // Transform image coordinates, allows to override e.g. 62500 // the canvas orientation based on the orientation option, 62501 // gets canvas, options passed as arguments: 62502 loadImage.transformCoordinates = function () { 62503 return 62504 } 62505 62506 // Returns transformed options, allows to override e.g. 62507 // maxWidth, maxHeight and crop options based on the aspectRatio. 62508 // gets img, options passed as arguments: 62509 loadImage.getTransformedOptions = function (img, options) { 62510 var aspectRatio = options.aspectRatio 62511 var newOptions 62512 var i 62513 var width 62514 var height 62515 if (!aspectRatio) { 62516 return options 62517 } 62518 newOptions = {} 62519 for (i in options) { 62520 if (options.hasOwnProperty(i)) { 62521 newOptions[i] = options[i] 62522 } 62523 } 62524 newOptions.crop = true 62525 width = img.naturalWidth || img.width 62526 height = img.naturalHeight || img.height 62527 if (width / height > aspectRatio) { 62528 newOptions.maxWidth = height * aspectRatio 62529 newOptions.maxHeight = height 62530 } else { 62531 newOptions.maxWidth = width 62532 newOptions.maxHeight = width / aspectRatio 62533 } 62534 return newOptions 62535 } 62536 62537 // Canvas render method, allows to implement a different rendering algorithm: 62538 loadImage.renderImageToCanvas = function ( 62539 canvas, 62540 img, 62541 sourceX, 62542 sourceY, 62543 sourceWidth, 62544 sourceHeight, 62545 destX, 62546 destY, 62547 destWidth, 62548 destHeight 62549 ) { 62550 canvas.getContext('2d').drawImage( 62551 img, 62552 sourceX, 62553 sourceY, 62554 sourceWidth, 62555 sourceHeight, 62556 destX, 62557 destY, 62558 destWidth, 62559 destHeight 62560 ) 62561 return canvas 62562 } 62563 62564 // This method is used to determine if the target image 62565 // should be a canvas element: 62566 loadImage.hasCanvasOption = function (options) { 62567 return options.canvas || options.crop || !!options.aspectRatio 62568 } 62569 62570 // Scales and/or crops the given image (img or canvas HTML element) 62571 // using the given options. 62572 // Returns a canvas object if the browser supports canvas 62573 // and the hasCanvasOption method returns true or a canvas 62574 // object is passed as image, else the scaled image: 62575 loadImage.scale = function (img, options) { 62576 options = options || {} 62577 var canvas = document.createElement('canvas') 62578 var useCanvas = img.getContext || 62579 (loadImage.hasCanvasOption(options) && canvas.getContext)
62580 var width = img.naturalWidth || img.width 62581 var height = img.naturalHeight || img.height 62582 var destWidth = width 62583 var destHeight = height 62584 var maxWidth 62585 var maxHeight 62586 var minWidth 62587 var minHeight 62588 var sourceWidth 62589 var sourceHeight 62590 var sourceX 62591 var sourceY 62592 var pixelRatio 62593 var downsamplingRatio 62594 var tmp 62595 function scaleUp () { 62596 var scale = Math.max( 62597 (minWidth || destWidth) / destWidth, 62598 (minHeight || destHeight) / destHeight 62599 ) 62600 if (scale > 1) { 62601 destWidth *= scale 62602 destHeight *= scale 62603 } 62604 } 62605 function scaleDown () { 62606 var scale = Math.min( 62607 (maxWidth || destWidth) / destWidth, 62608 (maxHeight || destHeight) / destHeight 62609 ) 62610 if (scale < 1) { 62611 destWidth *= scale 62612 destHeight *= scale 62613 } 62614 } 62615 if (useCanvas) { 62616 options = loadImage.getTransformedOptions(img, options) 62617 sourceX = options.left || 0 62618 sourceY = options.top || 0 62619 if (options.sourceWidth) { 62620 sourceWidth = options.sourceWidth 62621 if (options.right !== undefined && options.left === undefined) { 62622 sourceX = width - sourceWidth - options.right 62623 } 62624 } else { 62625 sourceWidth = width - sourceX - (options.right || 0) 62626 } 62627 if (options.sourceHeight) { 62628 sourceHeight = options.sourceHeight 62629 if (options.bottom !== undefined && options.top === undefined) { 62630 sourceY = height - sourceHeight - options.bottom 62631 } 62632 } else { 62633 sourceHeight = height - sourceY - (options.bottom || 0) 62634 } 62635 destWidth = sourceWidth 62636 destHeight = sourceHeight 62637 } 62638 maxWidth = options.maxWidth 62639 maxHeight = options.maxHeight 62640 minWidth = options.minWidth 62641 minHeight = options.minHeight 62642 if (useCanvas && maxWidth && maxHeight && options.crop) { 62643 destWidth = maxWidth 62644 destHeight = maxHeight 62645 tmp = sourceWidth / sourceHeight - maxWidth / maxHeight 62646 if (tmp < 0) { 62647 sourceHeight = maxHeight * sourceWidth / maxWidth 62648 if (options.top === undefined && options.bottom === undefined) { 62649 sourceY = (height - sourceHeight) / 2 62650 } 62651 } else if (tmp > 0) { 62652 sourceWidth = maxWidth * sourceHeight / maxHeight 62653 if (options.left === undefined && options.right === undefined) { 62654 sourceX = (width - sourceWidth) / 2 62655 } 62656 } 62657 } else { 62658 if (options.contain || options.cover) { 62659 minWidth = maxWidth = maxWidth || minWidth 62660 minHeight = maxHeight = maxHeight || minHeight 62661 } 62662 if (options.cover) { 62663 scaleDown() 62664 scaleUp() 62665 } else { 62666 scaleUp() 62667 scaleDown() 62668 } 62669 } 62670 if (useCanvas) { 62671 pixelRatio = options.pixelRatio 62672 if (pixelRatio > 1) { 62673 canvas.style.width = destWidth + 'px' 62674 canvas.style.height = destHeight + 'px' 62675 destWidth *= pixelRatio 62676 destHeight *= pixelRatio 62677 canvas.getContext('2d').scale(pixelRatio, pixelRatio) 62678 } 62679 downsamplingRatio = options.downsamplingRatio 62680 if (downsamplingRatio > 0 && downsamplingRatio < 1 && 62681 destWidth < sourceWidth && destHeight < sourceHeight) { 62682 while (sourceWidth * downsamplingRatio > destWidth) { 62683 canvas.width = sourceWidth * downsamplingRatio 62684 canvas.height = sourceHeight * downsamplingRatio 62685 loadImage.renderImageToCanvas( 62686 canvas, 62687 img, 62688 sourceX, 62689 sourceY, 62690 sourceWidth, 62691 sourceHeight, 62692 0, 62693 0, 62694 canvas.width, 62695 canvas.height 62696 ) 62697 sourceWidth = canvas.width 62698 sourceHeight = canvas.height 62699 img = document.createElement('canvas') 62700 img.width = sourceWidth 62701 img.height = sourceHeight 62702 loadImage.renderImageToCanvas( 62703 img, 62704 canvas, 62705 0, 62706 0, 62707 sourceWidth, 62708 sourceHeight, 62709 0, 62710 0, 62711 sourceWidth, 62712 sourceHeight 62713 ) 62714 } 62715 } 62716 canvas.width = destWidth 62717 canvas.height = destHeight 62718 loadImage.transformCoordinates( 62719 canvas, 62720 options 62721 ) 62722 return loadImage.renderImageToCanvas( 62723 canvas, 62724 img, 62725 sourceX, 62726 sourceY, 62727 sourceWidth, 62728 sourceHeight, 62729 0, 62730 0, 62731 destWidth, 62732 destHeight 62733 ) 62734 } 62735 img.width = destWidth 62736 img.height = destHeight 62737 return img 62738 } 62739 62740 loadImage.createObjectURL = function (file) { 62741 return urlAPI ? urlAPI.createObjectURL(file) : false 62742 } 62743 62744 loadImage.revokeObjectURL = function (url) { 62745 return urlAPI ? urlAPI.revokeObjectURL(url) : false 62746 } 62747 62748 // Loads a given File object via FileReader interface, 62749 // invokes the callback with the event object (load or error). 62750 // The result can be read via event.target.result: 62751 loadImage.readFile = function (file, callback, method) { 62752 if (window.FileReader) { 62753 var fileReader = new FileReader() 62754 fileReader.onload = fileReader.onerror = callback
62755 method = method || 'readAsDataURL' 62756 if (fileReader[method]) { 62757 fileReader[method](file) 62758 return fileReader 62759 } 62760 } 62761 return false 62762 } 62763 62764 if (typeof define === 'function' && define.amd) { 62765 define('load-image',[],function () { 62766 return loadImage 62767 }) 62768 } else if (typeof module === 'object' && module.exports) { 62769 module.exports = loadImage 62770 } else { 62771 $.loadImage = loadImage 62772 } 62773}(window)) 62774; 62775/* 62776 * JavaScript Load Image Meta 62777 * https://github.com/blueimp/JavaScript-Load-Image 62778 * 62779 * Copyright 2013, Sebastian Tschan 62780 * https://blueimp.net 62781 * 62782 * Image meta data handling implementation 62783 * based on the help and contribution of 62784 * Achim Stöhr. 62785 * 62786 * Licensed under the MIT license: 62787 * http://www.opensource.org/licenses/MIT 62788 */ 62789 62790/*global define, module, require, window, DataView, Blob, Uint8Array, console */ 62791 62792;(function (factory) { 62793 'use strict' 62794 if (typeof define === 'function' && define.amd) { 62795 // Register as an anonymous AMD module: 62796 define('load-image-meta',['./load-image'], factory) 62797 } else if (typeof module === 'object' && module.exports) { 62798 factory(require('./load-image')) 62799 } else { 62800 // Browser globals: 62801 factory(window.loadImage) 62802 } 62803}(function (loadImage) { 62804 'use strict' 62805 62806 var hasblobSlice = window.Blob && (Blob.prototype.slice || 62807 Blob.prototype.webkitSlice || Blob.prototype.mozSlice) 62808 62809 loadImage.blobSlice = hasblobSlice && function () { 62810 var slice = this.slice || this.webkitSlice || this.mozSlice 62811 return slice.apply(this, arguments) 62812 } 62813 62814 loadImage.metaDataParsers = { 62815 jpeg: { 62816 0xffe1: [] // APP1 marker 62817 } 62818 } 62819 62820 // Parses image meta data and calls the callback with an object argument 62821 // with the following properties: 62822 // * imageHead: The complete image head as ArrayBuffer (Uint8Array for IE10) 62823 // The options arguments accepts an object and supports the following properties: 62824 // * maxMetaDataSize: Defines the maximum number of bytes to parse. 62825 // * disableImageHead: Disables creating the imageHead property. 62826 loadImage.parseMetaData = function (file, callback, options) { 62827 options = options || {} 62828 var that = this 62829 // 256 KiB should contain all EXIF/ICC/IPTC segments: 62830 var maxMetaDataSize = options.maxMetaDataSize || 262144 62831 var data = {} 62832 var noMetaData = !(window.DataView && file && file.size >= 12 && 62833 file.type === 'image/jpeg' && loadImage.blobSlice) 62834 if (noMetaData || !loadImage.readFile( 62835 loadImage.blobSlice.call(file, 0, maxMetaDataSize), 62836 function (e) { 62837 if (e.target.error) { 62838 // FileReader error 62839 console.log(e.target.error) 62840 callback(data) 62841 return 62842 } 62843 // Note on endianness: 62844 // Since the marker and length bytes in JPEG files are always 62845 // stored in big endian order, we can leave the endian parameter 62846 // of the DataView methods undefined, defaulting to big endian. 62847 var buffer = e.target.result 62848 var dataView = new DataView(buffer) 62849 var offset = 2 62850 var maxOffset = dataView.byteLength - 4 62851 var headLength = offset 62852 var markerBytes 62853 var markerLength 62854 var parsers 62855 var i 62856 // Check for the JPEG marker (0xffd8): 62857 if (dataView.getUint16(0) === 0xffd8) { 62858 while (offset < maxOffset) { 62859 markerBytes = dataView.getUint16(offset) 62860 // Search for APPn (0xffeN) and COM (0xfffe) markers, 62861 // which contain application-specific meta-data like 62862 // Exif, ICC and IPTC data and text comments: 62863 if ((markerBytes >= 0xffe0 && markerBytes <= 0xffef) || 62864 markerBytes === 0xfffe) { 62865 // The marker bytes (2) are always followed by 62866 // the length bytes (2), indicating the length of the 62867 // marker segment, which includes the length bytes, 62868 // but not the marker bytes, so we add 2: 62869 markerLength = dataView.getUint16(offset + 2) + 2 62870 if (offset + markerLength > dataView.byteLength) { 62871 console.log('Invalid meta data: Invalid segment size.') 62872 break 62873 } 62874 parsers = loadImage.metaDataParsers.jpeg[markerBytes] 62875 if (parsers) { 62876 for (i = 0; i < parsers.length; i += 1) { 62877 parsers[i].call( 62878 that, 62879 dataView, 62880 offset, 62881 markerLength, 62882 data, 62883 options 62884 ) 62885 } 62886 } 62887 offset += markerLength 62888 headLength = offset 62889 } else { 62890 // Not an APPn or COM marker, probably safe to 62891 // assume that this is the end of the meta data 62892 break 62893 } 62894 } 62895 // Meta length must be longer than JPEG marker (2) 62896 // plus APPn marker (2), followed by length bytes (2): 62897 if (!options.disableImageHead && headLength > 6) { 62898 if (buffer.slice) { 62899 data.imageHead = buffer.slice(0, headLength) 62900 } else { 62901 // Workaround for IE10, which does not yet
62902 // support ArrayBuffer.slice: 62903 data.imageHead = new Uint8Array(buffer) 62904 .subarray(0, headLength) 62905 } 62906 } 62907 } else { 62908 console.log('Invalid JPEG file: Missing JPEG marker.') 62909 } 62910 callback(data) 62911 }, 62912 'readAsArrayBuffer' 62913 )) { 62914 callback(data) 62915 } 62916 } 62917})) 62918; 62919/* 62920 * JavaScript Load Image Exif Parser 62921 * https://github.com/blueimp/JavaScript-Load-Image 62922 * 62923 * Copyright 2013, Sebastian Tschan 62924 * https://blueimp.net 62925 * 62926 * Licensed under the MIT license: 62927 * http://www.opensource.org/licenses/MIT 62928 */ 62929 62930/*global define, module, require, window, console */ 62931 62932;(function (factory) { 62933 'use strict' 62934 if (typeof define === 'function' && define.amd) { 62935 // Register as an anonymous AMD module: 62936 define('load-image-exif',['./load-image', './load-image-meta'], factory) 62937 } else if (typeof module === 'object' && module.exports) { 62938 factory(require('./load-image'), require('./load-image-meta')) 62939 } else { 62940 // Browser globals: 62941 factory(window.loadImage) 62942 } 62943}(function (loadImage) { 62944 'use strict' 62945 62946 loadImage.ExifMap = function () { 62947 return this 62948 } 62949 62950 loadImage.ExifMap.prototype.map = { 62951 'Orientation': 0x0112 62952 } 62953 62954 loadImage.ExifMap.prototype.get = function (id) { 62955 return this[id] || this[this.map[id]] 62956 } 62957 62958 loadImage.getExifThumbnail = function (dataView, offset, length) { 62959 var hexData, 62960 i, 62961 b 62962 if (!length || offset + length > dataView.byteLength) { 62963 console.log('Invalid Exif data: Invalid thumbnail data.') 62964 return 62965 } 62966 hexData = [] 62967 for (i = 0; i < length; i += 1) { 62968 b = dataView.getUint8(offset + i) 62969 hexData.push((b < 16 ? '0' : '') + b.toString(16)) 62970 } 62971 return 'data:image/jpeg,%' + hexData.join('%') 62972 } 62973 62974 loadImage.exifTagTypes = { 62975 // byte, 8-bit unsigned int: 62976 1: { 62977 getValue: function (dataView, dataOffset) { 62978 return dataView.getUint8(dataOffset) 62979 }, 62980 size: 1 62981 }, 62982 // ascii, 8-bit byte: 62983 2: { 62984 getValue: function (dataView, dataOffset) { 62985 return String.fromCharCode(dataView.getUint8(dataOffset)) 62986 }, 62987 size: 1, 62988 ascii: true 62989 }, 62990 // short, 16 bit int: 62991 3: { 62992 getValue: function (dataView, dataOffset, littleEndian) { 62993 return dataView.getUint16(dataOffset, littleEndian) 62994 }, 62995 size: 2 62996 }, 62997 // long, 32 bit int: 62998 4: { 62999 getValue: function (dataView, dataOffset, littleEndian) { 63000 return dataView.getUint32(dataOffset, littleEndian) 63001 }, 63002 size: 4 63003 }, 63004 // rational = two long values, first is numerator, second is denominator: 63005 5: { 63006 getValue: function (dataView, dataOffset, littleEndian) { 63007 return dataView.getUint32(dataOffset, littleEndian) / 63008 dataView.getUint32(dataOffset + 4, littleEndian) 63009 }, 63010 size: 8 63011 }, 63012 // slong, 32 bit signed int: 63013 9: { 63014 getValue: function (dataView, dataOffset, littleEndian) { 63015 return dataView.getInt32(dataOffset, littleEndian) 63016 }, 63017 size: 4 63018 }, 63019 // srational, two slongs, first is numerator, second is denominator: 63020 10: { 63021 getValue: function (dataView, dataOffset, littleEndian) { 63022 return dataView.getInt32(dataOffset, littleEndian) / 63023 dataView.getInt32(dataOffset + 4, littleEndian) 63024 }, 63025 size: 8 63026 } 63027 } 63028 // undefined, 8-bit byte, value depending on field: 63029 loadImage.exifTagTypes[7] = loadImage.exifTagTypes[1] 63030 63031 loadImage.getExifValue = function (dataView, tiffOffset, offset, type, length, littleEndian) { 63032 var tagType = loadImage.exifTagTypes[type] 63033 var tagSize 63034 var dataOffset 63035 var values 63036 var i 63037 var str 63038 var c 63039 if (!tagType) { 63040 console.log('Invalid Exif data: Invalid tag type.') 63041 return 63042 } 63043 tagSize = tagType.size * length 63044 // Determine if the value is contained in the dataOffset bytes, 63045 // or if the value at the dataOffset is a pointer to the actual data: 63046 dataOffset = tagSize > 4 63047 ? tiffOffset + dataView.getUint32(offset + 8, littleEndian) 63048 : (offset + 8) 63049 if (dataOffset + tagSize > dataView.byteLength) { 63050 console.log('Invalid Exif data: Invalid data offset.') 63051 return 63052 } 63053 if (length === 1) { 63054 return tagType.getValue(dataView, dataOffset, littleEndian) 63055 } 63056 values = [] 63057 for (i = 0; i < length; i += 1) { 63058 values[i] = tagType.getValue(dataView, dataOffset + i * tagType.size, littleEndian) 63059 } 63060 if (tagType.ascii) { 63061 str = '' 63062 // Concatenate the chars: 63063 for (i = 0; i < values.length; i += 1) { 63064 c = values[i] 63065 // Ignore the terminating NULL byte(s): 63066 if (c === '\u0000') { 63067 break 63068 } 63069 str += c 63070 } 63071 return str 63072 } 63073 return values 63074 } 63075 63076 loadImage.parseExifTag = function (dataView, tiffOffset, offset, littleEndian, data) { 63077 var tag = dataView.getUint16(offset, littleEndian) 63078 data.exif[tag] = loadImage.getExifValue( 63079 dataView, 63080 tiffOffset, 63081 offset, 63082 dataView.getUint16(offset + 2, littleEndian), // tag type 63083 dataView.getUint32(offset + 4, littleEndian), // tag length 63084 littleEndian 63085 ) 63086 } 63087 63088 loadImage.parseExifTags = function (dataView, tiffOffset, dirOffset, littleEndian, data) { 63089 var tagsNumber, 63090 dirEndOffset, 63091 i 63092 if (dirOffset + 6 > dataView.byteLength) { 63093 console.log('Invalid Exif data: Invalid directory offset.') 63094 return 63095 }
63096 tagsNumber = dataView.getUint16(dirOffset, littleEndian) 63097 dirEndOffset = dirOffset + 2 + 12 * tagsNumber 63098 if (dirEndOffset + 4 > dataView.byteLength) { 63099 console.log('Invalid Exif data: Invalid directory size.') 63100 return 63101 } 63102 for (i = 0; i < tagsNumber; i += 1) { 63103 this.parseExifTag( 63104 dataView, 63105 tiffOffset, 63106 dirOffset + 2 + 12 * i, // tag offset 63107 littleEndian, 63108 data 63109 ) 63110 } 63111 // Return the offset to the next directory: 63112 return dataView.getUint32(dirEndOffset, littleEndian) 63113 } 63114 63115 loadImage.parseExifData = function (dataView, offset, length, data, options) { 63116 if (options.disableExif) { 63117 return 63118 } 63119 var tiffOffset = offset + 10 63120 var littleEndian 63121 var dirOffset 63122 var thumbnailData 63123 // Check for the ASCII code for "Exif" (0x45786966): 63124 if (dataView.getUint32(offset + 4) !== 0x45786966) { 63125 // No Exif data, might be XMP data instead 63126 return 63127 } 63128 if (tiffOffset + 8 > dataView.byteLength) { 63129 console.log('Invalid Exif data: Invalid segment size.') 63130 return 63131 } 63132 // Check for the two null bytes: 63133 if (dataView.getUint16(offset + 8) !== 0x0000) { 63134 console.log('Invalid Exif data: Missing byte alignment offset.') 63135 return 63136 } 63137 // Check the byte alignment: 63138 switch (dataView.getUint16(tiffOffset)) { 63139 case 0x4949: 63140 littleEndian = true 63141 break 63142 case 0x4D4D: 63143 littleEndian = false 63144 break 63145 default: 63146 console.log('Invalid Exif data: Invalid byte alignment marker.') 63147 return 63148 } 63149 // Check for the TIFF tag marker (0x002A): 63150 if (dataView.getUint16(tiffOffset + 2, littleEndian) !== 0x002A) { 63151 console.log('Invalid Exif data: Missing TIFF marker.') 63152 return 63153 } 63154 // Retrieve the directory offset bytes, usually 0x00000008 or 8 decimal: 63155 dirOffset = dataView.getUint32(tiffOffset + 4, littleEndian) 63156 // Create the exif object to store the tags: 63157 data.exif = new loadImage.ExifMap() 63158 // Parse the tags of the main image directory and retrieve the 63159 // offset to the next directory, usually the thumbnail directory: 63160 dirOffset = loadImage.parseExifTags( 63161 dataView, 63162 tiffOffset, 63163 tiffOffset + dirOffset, 63164 littleEndian, 63165 data 63166 ) 63167 if (dirOffset && !options.disableExifThumbnail) { 63168 thumbnailData = {exif: {}} 63169 dirOffset = loadImage.parseExifTags( 63170 dataView, 63171 tiffOffset, 63172 tiffOffset + dirOffset, 63173 littleEndian, 63174 thumbnailData 63175 ) 63176 // Check for JPEG Thumbnail offset: 63177 if (thumbnailData.exif[0x0201]) { 63178 data.exif.Thumbnail = loadImage.getExifThumbnail( 63179 dataView, 63180 tiffOffset + thumbnailData.exif[0x0201], 63181 thumbnailData.exif[0x0202] // Thumbnail data length 63182 ) 63183 } 63184 }
63185 // Check for Exif Sub IFD Pointer: 63186 if (data.exif[0x8769] && !options.disableExifSub) { 63187 loadImage.parseExifTags( 63188 dataView, 63189 tiffOffset, 63190 tiffOffset + data.exif[0x8769], // directory offset 63191 littleEndian, 63192 data 63193 ) 63194 } 63195 // Check for GPS Info IFD Pointer: 63196 if (data.exif[0x8825] && !options.disableExifGps) { 63197 loadImage.parseExifTags( 63198 dataView, 63199 tiffOffset, 63200 tiffOffset + data.exif[0x8825], // directory offset 63201 littleEndian, 63202 data 63203 ) 63204 } 63205 } 63206 63207 // Registers the Exif parser for the APP1 JPEG meta data segment: 63208 loadImage.metaDataParsers.jpeg[0xffe1].push(loadImage.parseExifData) 63209 63210 // Adds the following properties to the parseMetaData callback data: 63211 // * exif: The exif tags, parsed by the parseExifData method 63212 63213 // Adds the following options to the parseMetaData method: 63214 // * disableExif: Disables Exif parsing. 63215 // * disableExifThumbnail: Disables parsing of the Exif Thumbnail. 63216 // * disableExifSub: Disables parsing of the Exif Sub IFD. 63217 // * disableExifGps: Disables parsing of the Exif GPS Info IFD. 63218})) 63219; 63220/* 63221 * jQuery File Upload Image Preview & Resize Plugin 63222 * https://github.com/blueimp/jQuery-File-Upload 63223 * 63224 * Copyright 2013, Sebastian Tschan 63225 * https://blueimp.net 63226 * 63227 * Licensed under the MIT license: 63228 * http://www.opensource.org/licenses/MIT 63229 */ 63230 63231/* jshint nomen:false */ 63232/* global define, require, window, Blob */ 63233 63234;(function (factory) { 63235 'use strict'; 63236 if (typeof define === 'function' && define.amd) { 63237 // Register as an anonymous AMD module: 63238 define('jquery.fileupload-image',[ 63239 'jquery', 63240 'load-image', 63241 'load-image-meta', 63242 'load-image-exif', 63243 'canvas-to-blob', 63244 './jquery.fileupload-process' 63245 ], factory); 63246 } else if (typeof exports === 'object') { 63247 // Node/CommonJS: 63248 factory( 63249 require('jquery'), 63250 require('blueimp-load-image/js/load-image'), 63251 require('blueimp-load-image/js/load-image-meta'), 63252 require('blueimp-load-image/js/load-image-exif'), 63253 require('blueimp-canvas-to-blob'), 63254 require('./jquery.fileupload-process') 63255 ); 63256 } else { 63257 // Browser globals: 63258 factory( 63259 window.jQuery, 63260 window.loadImage 63261 ); 63262 } 63263}(function ($, loadImage) { 63264 'use strict'; 63265 63266 // Prepend to the default processQueue: 63267 $.blueimp.fileupload.prototype.options.processQueue.unshift( 63268 { 63269 action: 'loadImageMetaData', 63270 disableImageHead: '@', 63271 disableExif: '@', 63272 disableExifThumbnail: '@', 63273 disableExifSub: '@', 63274 disableExifGps: '@', 63275 disabled: '@disableImageMetaDataLoad' 63276 }, 63277 { 63278 action: 'loadImage', 63279 // Use the action as prefix for the "@" options: 63280 prefix: true, 63281 fileTypes: '@', 63282 maxFileSize: '@', 63283 noRevoke: '@', 63284 disabled: '@disableImageLoad' 63285 }, 63286 { 63287 action: 'resizeImage', 63288 // Use "image" as prefix for the "@" options: 63289 prefix: 'image', 63290 maxWidth: '@', 63291 maxHeight: '@', 63292 minWidth: '@', 63293 minHeight: '@', 63294 crop: '@', 63295 orientation: '@', 63296 forceResize: '@', 63297 disabled: '@disableImageResize' 63298 }, 63299 { 63300 action: 'saveImage', 63301 quality: '@imageQuality', 63302 type: '@imageType', 63303 disabled: '@disableImageResize' 63304 }, 63305 { 63306 action: 'saveImageMetaData', 63307 disabled: '@disableImageMetaDataSave' 63308 }, 63309 { 63310 action: 'resizeImage', 63311 // Use "preview" as prefix for the "@" options: 63312 prefix: 'preview', 63313 maxWidth: '@', 63314 maxHeight: '@', 63315 minWidth: '@', 63316 minHeight: '@', 63317 crop: '@', 63318 orientation: '@', 63319 thumbnail: '@', 63320 canvas: '@', 63321 disabled: '@disableImagePreview' 63322 }, 63323 { 63324 action: 'setImage', 63325 name: '@imagePreviewName', 63326 disabled: '@disableImagePreview' 63327 }, 63328 { 63329 action: 'deleteImageReferences', 63330 disabled: '@disableImageReferencesDeletion' 63331 } 63332 ); 63333 63334 // The File Upload Resize plugin extends the fileupload widget 63335 // with image resize functionality: 63336 $.widget('blueimp.fileupload', $.blueimp.fileupload, { 63337 63338 options: { 63339 // The regular expression for the types of images to load: 63340 // matched against the file type: 63341 loadImageFileTypes: /^image\/(gif|jpeg|png|svg\+xml)$/, 63342 // The maximum file size of images to load: 63343 loadImageMaxFileSize: 10000000, // 10MB 63344 // The maximum width of resized images: 63345 imageMaxWidth: 1920, 63346 // The maximum height of resized images: 63347 imageMaxHeight: 1080, 63348 // Defines the image orientation (1-8) or takes the orientation 63349 // value from Exif data if set to true: 63350 imageOrientation: false, 63351 // Define if resized images should be cropped or only scaled: 63352 imageCrop: false, 63353 // Disable the resize image functionality by default: 63354 disableImageResize: true, 63355 // The maximum width of the preview images: 63356 previewMaxWidth: 80, 63357 // The maximum height of the preview images: 63358 previewMaxHeight: 80, 63359 // Defines the preview orientation (1-8) or takes the orientation 63360 // value from Exif data if set to true: 63361 previewOrientation: true, 63362 // Create the preview using the Exif data thumbnail: 63363 previewThumbnail: true, 63364 // Define if preview images should be cropped or only scaled: 63365 previewCrop: false, 63366 // Define if preview images should be resized as canvas elements: 63367 previewCanvas: true 63368 }, 63369 63370 processActions: { 63371 63372 // Loads the image given via data.files and data.index 63373 // as img element, if the browser supports the File API. 63374 // Accepts the options fileTypes (regular expression) 63375 // and maxFileSize (integer) to limit the files to load: 63376 loadImage: function (data, options) { 63377 if (options.disabled) { 63378 return data; 63379 } 63380 var that = this, 63381 file = data.files[data.index], 63382 dfd = $.Deferred(); 63383 if (($.type(options.maxFileSize) === 'number' && 63384 file.size > options.maxFileSize) || 63385 (options.fileTypes && 63386 !options.fileTypes.test(file.type)) || 63387 !loadImage( 63388 file, 63389 function (img) { 63390 if (img.src) { 63391 data.img = img; 63392 } 63393 dfd.resolveWith(that, [data]); 63394 }, 63395 options 63396 )) { 63397 return data; 63398 } 63399 return dfd.promise(); 63400 }, 63401 63402 // Resizes the image given as data.canvas or data.img 63403 // and updates data.canvas or data.img with the resized image. 63404 // Also stores the resized image as preview property. 63405 // Accepts the options maxWidth, maxHeight, minWidth, 63406 // minHeight, canvas and crop: 63407 resizeImage: function (data, options) { 63408 if (options.disabled || !(data.canvas || data.img)) { 63409 return data; 63410 } 63411 options = $.extend({canvas: true}, options); 63412 var that = this, 63413 dfd = $.Deferred(), 63414 img = (options.canvas && data.canvas) || data.img, 63415 resolve = function (newImg) { 63416 if (newImg && (newImg.width !== img.width ||
63417 newImg.height !== img.height || 63418 options.forceResize)) { 63419 data[newImg.getContext ? 'canvas' : 'img'] = newImg; 63420 } 63421 data.preview = newImg; 63422 dfd.resolveWith(that, [data]); 63423 }, 63424 thumbnail; 63425 if (data.exif) { 63426 if (options.orientation === true) { 63427 options.orientation = data.exif.get('Orientation'); 63428 } 63429 if (options.thumbnail) { 63430 thumbnail = data.exif.get('Thumbnail'); 63431 if (thumbnail) { 63432 loadImage(thumbnail, resolve, options); 63433 return dfd.promise(); 63434 } 63435 } 63436 // Prevent orienting the same image twice: 63437 if (data.orientation) { 63438 delete options.orientation; 63439 } else { 63440 data.orientation = options.orientation; 63441 } 63442 } 63443 if (img) { 63444 resolve(loadImage.scale(img, options)); 63445 return dfd.promise(); 63446 } 63447 return data; 63448 }, 63449 63450 // Saves the processed image given as data.canvas 63451 // inplace at data.index of data.files: 63452 saveImage: function (data, options) { 63453 if (!data.canvas || options.disabled) { 63454 return data; 63455 } 63456 var that = this, 63457 file = data.files[data.index], 63458 dfd = $.Deferred(); 63459 if (data.canvas.toBlob) { 63460 data.canvas.toBlob( 63461 function (blob) { 63462 if (!blob.name) { 63463 if (file.type === blob.type) { 63464 blob.name = file.name; 63465 } else if (file.name) { 63466 blob.name = file.name.replace( 63467 /\.\w+$/, 63468 '.' + blob.type.substr(6) 63469 ); 63470 } 63471 } 63472 // Don't restore invalid meta data: 63473 if (file.type !== blob.type) { 63474 delete data.imageHead; 63475 } 63476 // Store the created blob at the position 63477 // of the original file in the files list: 63478 data.files[data.index] = blob; 63479 dfd.resolveWith(that, [data]); 63480 }, 63481 options.type || file.type, 63482 options.quality 63483 ); 63484 } else { 63485 return data; 63486 } 63487 return dfd.promise(); 63488 }, 63489 63490 loadImageMetaData: function (data, options) { 63491 if (options.disabled) { 63492 return data; 63493 } 63494 var that = this, 63495 dfd = $.Deferred(); 63496 loadImage.parseMetaData(data.files[data.index], function (result) { 63497 $.extend(data, result); 63498 dfd.resolveWith(that, [data]); 63499 }, options); 63500 return dfd.promise(); 63501 }, 63502 63503 saveImageMetaData: function (data, options) { 63504 if (!(data.imageHead && data.canvas && 63505 data.canvas.toBlob && !options.disabled)) { 63506 return data; 63507 } 63508 var file = data.files[data.index], 63509 blob = new Blob([ 63510 data.imageHead, 63511 // Resized images always have a head size of 20 bytes, 63512 // including the JPEG marker and a minimal JFIF header: 63513 this._blobSlice.call(file, 20) 63514 ], {type: file.type}); 63515 blob.name = file.name; 63516 data.files[data.index] = blob; 63517 return data; 63518 }, 63519
63520 // Sets the resized version of the image as a property of the 63521 // file object, must be called after "saveImage": 63522 setImage: function (data, options) { 63523 if (data.preview && !options.disabled) { 63524 data.files[data.index][options.name || 'preview'] = data.preview; 63525 } 63526 return data; 63527 }, 63528 63529 deleteImageReferences: function (data, options) { 63530 if (!options.disabled) { 63531 delete data.img; 63532 delete data.canvas; 63533 delete data.preview; 63534 delete data.imageHead; 63535 } 63536 return data; 63537 } 63538 63539 } 63540 63541 }); 63542 63543})); 63544 63545/* 63546 * jQuery Iframe Transport Plugin 63547 * https://github.com/blueimp/jQuery-File-Upload 63548 * 63549 * Copyright 2011, Sebastian Tschan 63550 * https://blueimp.net 63551 * 63552 * Licensed under the MIT license: 63553 * http://www.opensource.org/licenses/MIT 63554 */ 63555 63556/* global define, require, window, document */ 63557 63558;(function (factory) { 63559 'use strict'; 63560 if (typeof define === 'function' && define.amd) { 63561 // Register as an anonymous AMD module: 63562 define('jqueryIFrameTransport',['jquery'], factory); 63563 } else if (typeof exports === 'object') { 63564 // Node/CommonJS: 63565 factory(require('jquery')); 63566 } else { 63567 // Browser globals: 63568 factory(window.jQuery); 63569 } 63570}(function ($) { 63571 'use strict'; 63572 63573 // Helper variable to create unique names for the transport iframes: 63574 var counter = 0; 63575 63576 // The iframe transport accepts four additional options: 63577 // options.fileInput: a jQuery collection of file input fields 63578 // options.paramName: the parameter name for the file form data, 63579 // overrides the name property of the file input field(s), 63580 // can be a string or an array of strings. 63581 // options.formData: an array of objects with name and value properties, 63582 // equivalent to the return data of .serializeArray(), e.g.: 63583 // [{name: 'a', value: 1}, {name: 'b', value: 2}] 63584 // options.initialIframeSrc: the URL of the initial iframe src, 63585 // by default set to "javascript:false;" 63586 $.ajaxTransport('iframe', function (options) { 63587 if (options.async) { 63588 // javascript:false as initial iframe src 63589 // prevents warning popups on HTTPS in IE6: 63590 /*jshint scripturl: true */ 63591 var initialIframeSrc = options.initialIframeSrc || 'javascript:false;', 63592 /*jshint scripturl: false */ 63593 form, 63594 iframe, 63595 addParamChar; 63596 return { 63597 send: function (_, completeCallback) { 63598 form = $('<form style="display:none;"></form>'); 63599 form.attr('accept-charset', options.formAcceptCharset); 63600 addParamChar = /\?/.test(options.url) ? '&' : '?'; 63601 // XDomainRequest only supports GET and POST: 63602 if (options.type === 'DELETE') { 63603 options.url = options.url + addParamChar + '_method=DELETE'; 63604 options.type = 'POST'; 63605 } else if (options.type === 'PUT') { 63606 options.url = options.url + addParamChar + '_method=PUT'; 63607 options.type = 'POST'; 63608 } else if (options.type === 'PATCH') { 63609 options.url = options.url + addParamChar + '_method=PATCH'; 63610 options.type = 'POST'; 63611 } 63612 // IE versions below IE8 cannot set the name property of 63613 // elements that have already been added to the DOM, 63614 // so we set the name along with the iframe HTML markup: 63615 counter += 1; 63616 iframe = $( 63617 '<iframe src="' + initialIframeSrc + 63618 '" name="iframe-transport-' + counter + '"></iframe>' 63619 ).bind('load', function () { 63620 var fileInputClones, 63621 paramNames = $.isArray(options.paramName) ? 63622 options.paramName : [options.paramName]; 63623 iframe 63624 .unbind('load') 63625 .bind('load', function () { 63626 var response; 63627 // Wrap in a try/catch block to catch exceptions thrown 63628 // when trying to access cross-domain iframe contents: 63629 try { 63630 response = iframe.contents(); 63631 // Google Chrome and Firefox do not throw an 63632 // exception when calling iframe.contents() on 63633 // cross-domain requests, so we unify the response: 63634 if (!response.length || !response[0].firstChild) { 63635 throw new Error(); 63636 } 63637 } catch (e) { 63638 response = undefined; 63639 } 63640 // The complete callback returns the 63641 // iframe content document as response object: 63642 completeCallback( 63643 200, 63644 'success', 63645 {'iframe': response} 63646 ); 63647 // Fix for IE endless progress bar activity bug 63648 // (happens on form submits to iframe targets): 63649 $('<iframe src="' + initialIframeSrc + '"></iframe>') 63650 .appendTo(form); 63651 window.setTimeout(function () { 63652 // Removing the form in a setTimeout call 63653 // allows Chrome's developer tools to display 63654 // the response result 63655 form.remove(); 63656 }, 0); 63657 }); 63658 form 63659 .prop('target', iframe.prop('name')) 63660 .prop('action', options.url) 63661 .prop('method', options.type); 63662 if (options.formData) { 63663 $.each(options.formData, function (index, field) { 63664 $('<input type="hidden"/>') 63665 .prop('name', field.name) 63666 .val(field.value) 63667 .appendTo(form); 63668 }); 63669 } 63670 if (options.fileInput && options.fileInput.length && 63671 options.type === 'POST') { 63672 fileInputClones = options.fileInput.clone(); 63673 // Insert a clone for each file input field: 63674 options.fileInput.after(function (index) { 63675 return fileInputClones[index]; 63676 }); 63677 if (options.paramName) { 63678 options.fileInput.each(function (index) { 63679 $(this).prop( 63680 'name', 63681 paramNames[index] || options.paramName 63682 ); 63683 }); 63684 } 63685 // Appending the file input fields to the hidden form 63686 // removes them from their original location: 63687 form 63688 .append(options.fileInput) 63689 .prop('enctype', 'multipart/form-data') 63690 // enctype must be set as encoding for IE: 63691 .prop('encoding', 'multipart/form-data'); 63692 // Remove the HTML5 form attribute from the input(s): 63693 options.fileInput.removeAttr('form'); 63694 } 63695 form.submit(); 63696 // Insert the file input fields at their original location 63697 // by replacing the clones with the originals: 63698 if (fileInputClones && fileInputClones.length) { 63699 options.fileInput.each(function (index, input) { 63700 var clone = $(fileInputClones[index]); 63701 // Restore the original name and form properties: 63702 $(input) 63703 .prop('name', clone.prop('name')) 63704 .attr('form', clone.attr('form')); 63705 clone.replaceWith(input); 63706 }); 63707 } 63708 }); 63709 form.append(iframe).appendTo(document.body); 63710 }, 63711 abort: function () { 63712 if (iframe) { 63713 // javascript:false as iframe src aborts the request 63714 // and prevents warning popups on HTTPS in IE6. 63715 // concat is used to avoid the "Script URL" JSLint error: 63716 iframe 63717 .unbind('load') 63718 .prop('src', initialIframeSrc); 63719 } 63720 if (form) { 63721 form.remove(); 63722 } 63723 } 63724 }; 63725 } 63726 }); 63727 63728 // The iframe transport returns the iframe content document as response. 63729 // The following adds converters from iframe to text, json, html, xml 63730 // and script. 63731 // Please note that the Content-Type for JSON responses has to be text/plain 63732 // or text/html, if the browser doesn't include application/json in the 63733 // Accept header, else IE will show a download dialog. 63734 // The Content-Type for XML responses on the other hand has to be al
63734ways 63735 // application/xml or text/xml, so IE properly parses the XML response. 63736 // See also 63737 // https://github.com/blueimp/jQuery-File-Upload/wiki/Setup#content-type-negotiation 63738 $.ajaxSetup({ 63739 converters: { 63740 'iframe text': function (iframe) { 63741 return iframe && $(iframe[0].body).text(); 63742 }, 63743 'iframe json': function (iframe) { 63744 return iframe && $.parseJSON($(iframe[0].body).text()); 63745 }, 63746 'iframe html': function (iframe) { 63747 return iframe && $(iframe[0].body).html(); 63748 }, 63749 'iframe xml': function (iframe) { 63750 var xmlDoc = iframe && iframe[0]; 63751 return xmlDoc && $.isXMLDoc(xmlDoc) ? xmlDoc : 63752 $.parseXML((xmlDoc.XMLDocument && xmlDoc.XMLDocument.xml) || 63753 $(xmlDoc.body).html()); 63754 }, 63755 'iframe script': function (iframe) { 63756 return iframe && $.globalEval($(iframe[0].body).text()); 63757 } 63758 } 63759 }); 63760 63761})); 63762 63763 63764 63765(function($){ 63766 63767$.fn.sendkeys = function (x){ 63768 return this.each( function(){ 63769 bililiteRange(this).bounds('selection').sendkeys(x).select(); 63770 this.focus(); 63771 }); 63772}; // sendkeys 63773 63774// add a default handler for keydowns so that we can send keystrokes, even though code-generated events 63775// are untrusted (http://www.w3.org/TR/DOM-Level-3-Events/#trusted-events) 63776// documentation of special event handlers is at http://learn.jquery.com/events/event-extensions/ 63777$.event.special.keydown = $.event.special.keydown || {}; 63778$.event.special.keydown._default = function (evt){ 63779 if (evt.isTrusted) return false; 63780 if (evt.key == null) return false; // nothing to print. Use the keymap plugin to set this 63781 if (evt.ctrlKey || evt.altKey || evt.metaKey) return false; // only deal with printable characters. 63782 var target = evt.target; 63783 if (target.isContentEditable || target.nodeName == 'INPUT' || target.nodeName == 'TEXTAREA') { 63784 // only insert into editable elements 63785 var key = evt.key; 63786 if (key.length > 1 && key.charAt(0) != '{') key = '{'+key+'}'; // sendkeys notation 63787 $(target).sendkeys(key); 63788 return true; 63789 } 63790 return false; 63791} 63792})(jQuery); 63793define("jquerySendkeys", ["jquery","bililiteRange"], function(){}); 63794 63795/** 63796 * Timeago is a jQuery plugin that makes it easy to support automatically 63797 * updating fuzzy timestamps (e.g. "4 minutes ago" or "about 1 day ago"). 63798 * 63799 * @name timeago 63800 * @version 1.3.2 63801 * @requires jQuery v1.2.3+ 63802 * @author Ryan McGeary 63803 * @license MIT License - http://www.opensource.org/licenses/mit-license.php 63804 * 63805 * For usage and examples, visit: 63806 * http://timeago.yarp.com/ 63807 * 63808 * Copyright (c) 2008-2013, Ryan McGeary (ryan -[at]- mcgeary [*dot*] org) 63809 */ 63810 63811(function (factory) { 63812 if (typeof define === 'function' && define.amd) { 63813 // AMD. Register as an anonymous module. 63814 define('jquery-timeago',['jquery'], factory); 63815 } else { 63816 // Browser globals 63817 factory(jQuery); 63818 } 63819}(function ($) { 63820 $.timeago = function(timestamp) { 63821 if (timestamp instanceof Date) { 63822 return inWords(timestamp); 63823 } else if (typeof timestamp === "string") { 63824 return inWords($.timeago.parse(timestamp)); 63825 } else if (typeof timestamp === "number") { 63826 return inWords(new Date(timestamp)); 63827 } else { 63828 return inWords($.timeago.datetime(timestamp)); 63829 } 63830 }; 63831 var $t = $.timeago; 63832 63833 $.extend($.timeago, { 63834 settings: { 63835 refreshMillis: 60000, 63836 allowFuture: false, 63837 localeTitle: false, 63838 cutoff: 0, 63839 strings: { 63840 prefixAgo: null, 63841 prefixFromNow: null, 63842 suffixAgo: "ago", 63843 suffixFromNow: "from now", 63844 seconds: "less than a minute", 63845 minute: "about a minute", 63846 minutes: "%d minutes", 63847 hour: "about an hour", 63848 hours: "about %d hours", 63849 day: "a day", 63850 days: "%d days", 63851 month: "about a month", 63852 months: "%d months", 63853 year: "about a year", 63854 years: "%d years", 63855 wordSeparator: " ", 63856 numbers: [] 63857 } 63858 }, 63859 inWords: function(distanceMillis) { 63860 var $l = this.settings.strings; 63861 var prefix = $l.prefixAgo; 63862 var suffix = $l.suffixAgo; 63863 if (this.settings.allowFuture) { 63864 if (distanceMillis < 0) { 63865 prefix = $l.prefixFromNow; 63866 suffix = $l.suffixFromNow; 63867 } 63868 } 63869 63870 var seconds = Math.abs(distanceMillis) / 1000; 63871 var minutes = seconds / 60; 63872 var hours = minutes / 60; 63873 var days = hours / 24; 63874 var years = days / 365; 63875 63876 function substitute(stringOrFunction, number) { 63877 var string = $.isFunction(stringOrFunction) ? stringOrFunction(number, distanceMillis) : stringOrFunction; 63878 var value = ($l.numbers && $l.numbers[number]) || number; 63879 return string.replace(/%d/i, value); 63880 } 63881 63882 var words = seconds < 45 && substitute($l.seconds, Math.round(seconds)) || 63883 seconds < 90 && substitute($l.minute, 1) || 63884 minutes < 45 && substitute($l.minutes, Math.round(minutes)) || 63885 minutes < 90 && substitute($l.hour, 1) || 63886 hours < 24 && substitute($l.hours, Math.round(hours)) || 63887 hours < 42 && substitute($l.day, 1) || 63888 days < 30 && substitute($l.days, Math.round(days)) || 63889 days < 45 && substitute($l.month, 1) || 63890 days < 365 && substitute($l.months, Math.round(days / 30)) || 63891 years < 1.5 && substitute($l.year, 1) || 63892 substitute($l.years, Math.round(years)); 63893 63894 var separator = $l.wordSeparator || ""; 63895 if ($l.wordSeparator === undefined) { separator = " "; } 63896 return $.trim([prefix, words, suffix].join(separator)); 63897 }, 63898 parse: function(iso8601) { 63899 var s = $.trim(iso8601); 63900 s = s.replace(/\.\d+/,""); // remove milliseconds 63901 s = s.replace(/-/,"/").replace(/-/,"/"); 63902 s = s.replace(/T/," ").replace(/Z/," UTC"); 63903 s = s.replace(/([\+\-]\d\d)\:?(\d\d)/," $1$2"); // -04:00 -> -0400 63904 s = s.replace(/([\+\-]\d\d)$/," $100"); // +09 -> +0900 63905 return new Date(s); 63906 }, 63907 datetime: function(elem) { 63908 var iso8601 = $t.isTime(elem) ? $(elem).attr("datetime") : $(elem).attr("title"); 63909 return $t.parse(iso8601); 63910 }, 63911 isTime: function(elem) { 63912 // jQuery's `is()` doesn't play well with HTML5 in IE 63913 return $(elem).get(0).tagName.toLowerCase() === "time"; // $(elem).is("time"); 63914 } 63915 }); 63916 63917 // functions that can be called via $(el).timeago('action') 63918 // init is default when no action is given 63919 // functions are called with context of a single element 63920 var functions = { 63921 init: function(){ 63922 var refresh_el = $.proxy(refresh, this); 63923 refresh_el(); 63924 var $s = $t.settings; 63925 if ($s.refreshMillis > 0) { 63926 this._timeagoInterval = setInterval(refresh_el, $s.refreshMillis); 63927 } 63928 }, 63929 update: function(time){ 63930 var parsedTime = $t.parse(time); 63931 $(this).data('timeago', { datetime: parsedTime }); 63932 if($t.settings.localeTitle) $(this).attr("title", parsedTime.toLocaleStr
63932ing()); 63933 refresh.apply(this); 63934 }, 63935 updateFromDOM: function(){ 63936 $(this).data('timeago', { datetime: $t.parse( $t.isTime(this) ? $(this).attr("datetime") : $(this).attr("title") ) }); 63937 refresh.apply(this); 63938 }, 63939 dispose: function () { 63940 if (this._timeagoInterval) { 63941 window.clearInterval(this._timeagoInterval); 63942 this._timeagoInterval = null; 63943 } 63944 } 63945 }; 63946 63947 $.fn.timeago = function(action, options) { 63948 var fn = action ? functions[action] : functions.init; 63949 if(!fn){ 63950 throw new Error("Unknown function name '"+ action +"' for timeago"); 63951 } 63952 // each over objects here and call the requested function 63953 this.each(function(){ 63954 fn.call(this, options); 63955 }); 63956 return this; 63957 }; 63958 63959 function refresh() { 63960 var data = prepareData(this); 63961 var $s = $t.settings; 63962 63963 if (!isNaN(data.datetime)) { 63964 if ( $s.cutoff == 0 || distance(data.datetime) < $s.cutoff) { 63965 $(this).text(inWords(data.datetime)); 63966 } 63967 } 63968 return this; 63969 } 63970 63971 function prepareData(element) { 63972 element = $(element); 63973 if (!element.data("timeago")) { 63974 element.data("timeago", { datetime: $t.datetime(element) }); 63975 var text = $.trim(element.text()); 63976 if ($t.settings.localeTitle) { 63977 element.attr("title", element.data('timeago').datetime.toLocaleString()); 63978 } else if (text.length > 0 && !($t.isTime(element) && element.attr("title"))) { 63979 element.attr("title", text); 63980 } 63981 } 63982 return element.data("timeago"); 63983 } 63984 63985 function inWords(date) { 63986 return $t.inWords(distance(date)); 63987 } 63988 63989 function distance(date) { 63990 return (new Date().getTime() - date.getTime()); 63991 } 63992 63993 // fix for IE6 suckage 63994 document.createElement("abbr"); 63995 document.createElement("time"); 63996})); 63997 63998/* NUGET: BEGIN LICENSE TEXT 63999 * 64000 * Microsoft grants you the right to use these script files for the sole 64001 * purpose of either: (i) interacting through your browser with the Microsoft 64002 * website or online service, subject to the applicable licensing or use 64003 * terms; or (ii) using the files as included with a Microsoft product subject 64004 * to that product's license terms. Microsoft reserves all other rights to the 64005 * files not expressly granted by Microsoft, whether by implication, estoppel 64006 * or otherwise. Insofar as a script file is dual licensed under GPL, 64007 * Microsoft neither took the code under GPL nor distributes it thereunder but 64008 * under the terms set out in this paragraph. All notices and licenses 64009 * below are for informational purposes only. 64010 * 64011 * NUGET: END LICENSE TEXT */ 64012/*! 64013** Unobtrusive Ajax support library for jQuery 64014** Copyright (C) Microsoft Corporation. All rights reserved. 64015*/ 64016 64017/*jslint white: true, browser: true, onevar: true, undef: true, nomen: true, eqeqeq: true, plusplus: true, bitwise: true, regexp: true, newcap: true, immed: true, strict: false */ 64018/*global window: false, jQuery: false */ 64019 64020(function ($) { 64021 var data_click = "unobtrusiveAjaxClick", 64022 data_target = "unobtrusiveAjaxClickTarget" 64023 data_validation = "unobtrusiveValidation"; 64024 64025 function getFunction(code, argNames) { 64026 var fn = window, parts = (code || "").split("."); 64027 while (fn && parts.length) { 64028 fn = fn[parts.shift()]; 64029 } 64030 if (typeof (fn) === "function") { 64031 return fn; 64032 } 64033 argNames.push(code); 64034 return Function.constructor.apply(null, argNames); 64035 } 64036 64037 function isMethodProxySafe(method) { 64038 return method === "GET" || method === "POST"; 64039 } 64040 64041 function asyncOnBeforeSend(xhr, method) { 64042 if (!isMethodProxySafe(method)) { 64043 xhr.setRequestHeader("X-HTTP-Method-Override", method); 64044 } 64045 } 64046 64047 function asyncOnSuccess(element, data, contentType) { 64048 var mode; 64049 64050 if (contentType.indexOf("application/x-javascript") !== -1) { // jQuery already executes JavaScript for us 64051 return; 64052 } 64053 64054 mode = (element.getAttribute("data-ajax-mode") || "").toUpperCase(); 64055 $(element.getAttribute("data-ajax-update")).each(function (i, update) { 64056 var top; 64057 64058 switch (mode) { 64059 case "BEFORE": 64060 top = update.firstChild; 64061 $("<div />").html(data).contents().each(function () { 64062 update.insertBefore(this, top); 64063 }); 64064 break; 64065 case "AFTER": 64066 $("<div />").html(data).contents().each(function () { 64067 update.appendChild(this); 64068 }); 64069 break; 64070 default: 64071 $(update).html(data); 64072 break; 64073 } 64074 }); 64075 } 64076 64077 function asyncRequest(element, options) { 64078 var confirm, loading, method, duration; 64079 64080 confirm = element.getAttribute("data-ajax-confirm"); 64081 if (confirm && !window.confirm(confirm)) { 64082 return; 64083 } 64084 64085 loading = $(element.getAttribute("data-ajax-loading")); 64086 duration = parseInt(element.getAttribute("data-ajax-loading-duration"), 10) || 0; 64087 64088 $.extend(options, { 64089 context: element, 64090 type: element.getAttribute("data-ajax-method") || undefined, 64091 url: element.getAttribute("data-ajax-url") || undefined, 64092 beforeSend: function (xhr) { 64093 var result; 64094 asyncOnBeforeSend(xhr, method); 64095 result = getFunction(element.getAttribute("data-ajax-begin"), ["xhr"]).apply(this, arguments); 64096 if (result !== false) { 64097 loading.show(duration); 64098 } 64099 return result; 64100 }, 64101 complete: function () { 64102 loading.hide(duration); 64103 getFunction(element.getAttribute("data-ajax-complete"), ["xhr", "status"]).apply(this, arguments); 64104 }, 64105 success: function (data, status, xhr) { 64106 asyncOnSuccess(element, data, xhr.getResponseHeader("Content-Type") || "text/html"); 64107 getFunction(element.getAttribute("data-ajax-success"), ["data", "status", "xhr"]).apply(this, arguments); 64108 }, 64109 error: getFunction(element.getAttribute("data-ajax-failure"), ["xhr", "status", "error"]) 64110 }); 64111 64112 options.data.push({ name: "X-Requested-With", value: "XMLHttpRequest" }); 64113 64114 method = options.type.toUpperCase(); 64115 if (!isMethodProxySafe(method)) { 64116 options.type = "POST"; 64117 options.data.push({ name: "X-HTTP-Method-Override", value: method }); 64118 } 64119 64120 $.ajax(options); 64121 } 64122 64123 function validate(form) {
64124 var validationInfo = $(form).data(data_validation); 64125 return !validationInfo || !validationInfo.validate || validationInfo.validate(); 64126 } 64127 64128 $(document).on("click", "a[data-ajax=true]", function (evt) { 64129 evt.preventDefault(); 64130 asyncRequest(this, { 64131 url: this.href, 64132 type: "GET", 64133 data: [] 64134 }); 64135 }); 64136 64137 $(document).on("click", "form[data-ajax=true] input[type=image]", function (evt) { 64138 var name = evt.target.name, 64139 target = $(evt.target), 64140 form = $(target.parents("form")[0]), 64141 offset = target.offset(); 64142 64143 form.data(data_click, [ 64144 { name: name + ".x", value: Math.round(evt.pageX - offset.left) }, 64145 { name: name + ".y", value: Math.round(evt.pageY - offset.top) } 64146 ]); 64147 64148 setTimeout(function () { 64149 form.removeData(data_click); 64150 }, 0); 64151 }); 64152 64153 $(document).on("click", "form[data-ajax=true] :submit", function (evt) { 64154 var name = evt.currentTarget.name, 64155 target = $(evt.target), 64156 form = $(target.parents("form")[0]); 64157 64158 form.data(data_click, name ? [{ name: name, value: evt.currentTarget.value }] : []); 64159 form.data(data_target, target); 64160 64161 setTimeout(function () { 64162 form.removeData(data_click); 64163 form.removeData(data_target); 64164 }, 0); 64165 }); 64166 64167 $(document).on("submit", "form[data-ajax=true]", function (evt) { 64168 var clickInfo = $(this).data(data_click) || [], 64169 clickTarget = $(this).data(data_target), 64170 isCancel = clickTarget && clickTarget.hasClass("cancel"); 64171 evt.preventDefault(); 64172 if (!isCancel && !validate(this)) { 64173 return; 64174 } 64175 asyncRequest(this, { 64176 url: this.action, 64177 type: this.method || "GET", 64178 data: clickInfo.concat($(this).serializeArray()) 64179 }); 64180 }); 64181}(jQuery)); 64182define("jqueryUnobstrusive", ["jquery"], (function (global) { 64183 return function () { 64184 var ret, fn; 64185 return ret || global.$; 64186 }; 64187}(this))); 64188 64189/*! 64190 * jQuery Validation Plugin v1.12.0 64191 * 64192 * http://jqueryvalidation.org/ 64193 * 64194 * Copyright (c) 2014 Jörn Zaefferer 64195 * Released under the MIT license 64196 */ 64197(function($) { 64198 64199$.extend($.fn, { 64200 // http://jqueryvalidation.org/validate/ 64201 validate: function( options ) { 64202 64203 // if nothing is selected, return nothing; can't chain anyway 64204 if ( !this.length ) { 64205 if ( options && options.debug && window.console ) { 64206 console.warn( "Nothing selected, can't validate, returning nothing." ); 64207 } 64208 return; 64209 } 64210 64211 // check if a validator for this form was already created 64212 var validator = $.data( this[0], "validator" ); 64213 if ( validator ) { 64214 return validator; 64215 } 64216 64217 // Add novalidate tag if HTML5. 64218 this.attr( "novalidate", "novalidate" ); 64219 64220 validator = new $.validator( options, this[0] ); 64221 $.data( this[0], "validator", validator ); 64222 64223 if ( validator.settings.onsubmit ) { 64224 64225 this.validateDelegate( ":submit", "click", function( event ) { 64226 if ( validator.settings.submitHandler ) { 64227 validator.submitButton = event.target; 64228 } 64229 // allow suppressing validation by adding a cancel class to the submit button 64230 if ( $(event.target).hasClass("cancel") ) { 64231 validator.cancelSubmit = true; 64232 } 64233 64234 // allow suppressing validation by adding the html5 formnovalidate attribute to the submit button 64235 if ( $(event.target).attr("formnovalidate") !== undefined ) { 64236 validator.cancelSubmit = true; 64237 } 64238 }); 64239 64240 // validate the form on submit 64241 this.submit( function( event ) { 64242 if ( validator.settings.debug ) { 64243 // prevent form submit to be able to see console output 64244 event.preventDefault(); 64245 } 64246 function handle() { 64247 var hidden; 64248 if ( validator.settings.submitHandler ) { 64249 if ( validator.submitButton ) { 64250 // insert a hidden input as a replacement for the missing submit button 64251 hidden = $("<input type='hidden'/>").attr("name", validator.submitButton.name).val( $(validator.submitButton).val() ).appendTo(validator.currentForm); 64252 } 64253 validator.settings.submitHandler.call( validator, validator.currentForm, event ); 64254 if ( validator.submitButton ) { 64255 // and clean up afterwards; thanks to no-block-scope, hidden can be referenced 64256 hidden.remove(); 64257 } 64258 return false; 64259 } 64260 return true; 64261 } 64262 64263 // prevent submit for invalid forms or custom submit handlers 64264 if ( validator.cancelSubmit ) { 64265 validator.cancelSubmit = false; 64266 return handle(); 64267 } 64268 if ( validator.form() ) {
vendor: 4,582 bytes, lines 64269-64433
64269 if ( validator.pendingRequest ) { 64270 validator.formSubmitted = true; 64271 return false; 64272 } 64273 return handle(); 64274 } else { 64275 validator.focusInvalid(); 64276 return false; 64277 } 64278 }); 64279 } 64280 64281 return validator; 64282 }, 64283 // http://jqueryvalidation.org/valid/ 64284 valid: function() { 64285 var valid, validator; 64286 64287 if ( $(this[0]).is("form")) { 64288 valid = this.validate().form(); 64289 } else { 64290 valid = true; 64291 validator = $(this[0].form).validate(); 64292 this.each(function() { 64293 valid = validator.element(this) && valid; 64294 }); 64295 } 64296 return valid; 64297 }, 64298 // attributes: space separated list of attributes to retrieve and remove 64299 removeAttrs: function( attributes ) { 64300 var result = {}, 64301 $element = this; 64302 $.each(attributes.split(/\s/), function( index, value ) { 64303 result[value] = $element.attr(value); 64304 $element.removeAttr(value); 64305 }); 64306 return result; 64307 }, 64308 // http://jqueryvalidation.org/rules/ 64309 rules: function( command, argument ) { 64310 var element = this[0], 64311 settings, staticRules, existingRules, data, param, filtered; 64312 64313 if ( command ) { 64314 settings = $.data(element.form, "validator").settings; 64315 staticRules = settings.rules; 64316 existingRules = $.validator.staticRules(element); 64317 switch (command) { 64318 case "add": 64319 $.extend(existingRules, $.validator.normalizeRule(argument)); 64320 // remove messages from rules, but allow them to be set separately 64321 delete existingRules.messages; 64322 staticRules[element.name] = existingRules; 64323 if ( argument.messages ) { 64324 settings.messages[element.name] = $.extend( settings.messages[element.name], argument.messages ); 64325 } 64326 break; 64327 case "remove": 64328 if ( !argument ) { 64329 delete staticRules[element.name]; 64330 return existingRules; 64331 } 64332 filtered = {}; 64333 $.each(argument.split(/\s/), function( index, method ) { 64334 filtered[method] = existingRules[method]; 64335 delete existingRules[method]; 64336 if ( method === "required" ) { 64337 $(element).removeAttr("aria-required"); 64338 } 64339 }); 64340 return filtered; 64341 } 64342 } 64343 64344 data = $.validator.normalizeRules( 64345 $.extend( 64346 {}, 64347 $.validator.classRules(element), 64348 $.validator.attributeRules(element), 64349 $.validator.dataRules(element), 64350 $.validator.staticRules(element) 64351 ), element); 64352 64353 // make sure required is at front 64354 if ( data.required ) { 64355 param = data.required; 64356 delete data.required; 64357 data = $.extend({ required: param }, data ); 64358 $(element).attr( "aria-required", "true" ); 64359 } 64360 64361 // make sure remote is at back 64362 if ( data.remote ) { 64363 param = data.remote; 64364 delete data.remote; 64365 data = $.extend( data, { remote: param }); 64366 } 64367 64368 return data; 64369 } 64370}); 64371 64372// Custom selectors 64373$.extend($.expr[":"], { 64374 // http://jqueryvalidation.org/blank-selector/ 64375 blank: function( a ) { return !$.trim("" + $(a).val()); }, 64376 // http://jqueryvalidation.org/filled-selector/ 64377 filled: function( a ) { return !!$.trim("" + $(a).val()); }, 64378 // http://jqueryvalidation.org/unchecked-selector/ 64379 unchecked: function( a ) { return !$(a).prop("checked"); } 64380}); 64381 64382// constructor for validator 64383$.validator = function( options, form ) { 64384 this.settings = $.extend( true, {}, $.validator.defaults, options ); 64385 this.currentForm = form; 64386 this.init(); 64387}; 64388 64389// http://jqueryvalidation.org/jQuery.validator.format/ 64390$.validator.format = function( source, params ) { 64391 if ( arguments.length === 1 ) { 64392 return function() { 64393 var args = $.makeArray(arguments); 64394 args.unshift(source); 64395 return $.validator.format.apply( this, args ); 64396 }; 64397 } 64398 if ( arguments.length > 2 && params.constructor !== Array ) { 64399 params = $.makeArray(arguments).slice(1); 64400 } 64401 if ( params.constructor !== Array ) { 64402 params = [ params ]; 64403 } 64404 $.each(params, function( i, n ) { 64405 source = source.replace( new RegExp("\\{" + i + "\\}", "g"), function() { 64406 return n; 64407 }); 64408 }); 64409 return source; 64410}; 64411 64412$.extend($.validator, { 64413 64414 defaults: { 64415 messages: {}, 64416 groups: {}, 64417 rules: {}, 64418 errorClass: "error", 64419 validClass: "valid", 64420 errorElement: "label", 64421 focusInvalid: true, 64422 errorContainer: $([]), 64423 errorLabelContainer: $([]), 64424 onsubmit: true, 64425 ignore: ":hidden", 64426 ignoreTitle: false, 64427 onfocusin: function( element ) { 64428 this.lastActive = element; 64429 64430 // hide error label and remove error class on focus if enabled 64431 if ( this.settings.focusCleanup && !this.blockFocusCleanup ) { 64432 if ( this.settings.unhighlight ) { 64433 this.settings.unhighlight.call( this, element, this.settings.errorClass, this.settings.val
64433idClass ); 64434 } 64435 this.addWrapper(this.errorsFor(element)).hide(); 64436 } 64437 }, 64438 onfocusout: function( element ) { 64439 if ( !this.checkable(element) && (element.name in this.submitted || !this.optional(element)) ) { 64440 this.element(element); 64441 } 64442 }, 64443 onkeyup: function( element, event ) { 64444 if ( event.which === 9 && this.elementValue(element) === "" ) { 64445 return; 64446 } else if ( element.name in this.submitted || element === this.lastElement ) { 64447 this.element(element); 64448 } 64449 }, 64450 onclick: function( element ) { 64451 // click on selects, radiobuttons and checkboxes 64452 if ( element.name in this.submitted ) { 64453 this.element(element); 64454 64455 // or option elements, check parent select in that case 64456 } else if ( element.parentNode.name in this.submitted ) { 64457 this.element(element.parentNode); 64458 } 64459 }, 64460 highlight: function( element, errorClass, validClass ) { 64461 if ( element.type === "radio" ) { 64462 this.findByName(element.name).addClass(errorClass).removeClass(validClass); 64463 } else { 64464 $(element).addClass(errorClass).removeClass(validClass); 64465 } 64466 }, 64467 unhighlight: function( element, errorClass, validClass ) { 64468 if ( element.type === "radio" ) { 64469 this.findByName(element.name).removeClass(errorClass).addClass(validClass); 64470 } else { 64471 $(element).removeClass(errorClass).addClass(validClass); 64472 } 64473 } 64474 }, 64475 64476 // http://jqueryvalidation.org/jQuery.validator.setDefaults/ 64477 setDefaults: function( settings ) { 64478 $.extend( $.validator.defaults, settings ); 64479 }, 64480 64481 messages: { 64482 required: "This field is required.", 64483 remote: "Please fix this field.", 64484 email: "Please enter a valid email address.", 64485 url: "Please enter a valid URL.", 64486 date: "Please enter a valid date.", 64487 dateISO: "Please enter a valid date (ISO).", 64488 number: "Please enter a valid number.", 64489 digits: "Please enter only digits.", 64490 creditcard: "Please enter a valid credit card number.", 64491 equalTo: "Please enter the same value again.", 64492 maxlength: $.validator.format("Please enter no more than {0} characters."), 64493 minlength: $.validator.format("Please enter at least {0} characters."), 64494 rangelength: $.validator.format("Please enter a value between {0} and {1} characters long."), 64495 range: $.validator.format("Please enter a value between {0} and {1}."), 64496 max: $.validator.format("Please enter a value less than or equal to {0}."), 64497 min: $.validator.format("Please enter a value greater than or equal to {0}.") 64498 }, 64499 64500 autoCreateRanges: false, 64501 64502 prototype: { 64503 64504 init: function() { 64505 this.labelContainer = $(this.settings.errorLabelContainer); 64506 this.errorContext = this.labelContainer.length && this.labelContainer || $(this.currentForm); 64507 this.containers = $(this.settings.errorContainer).add( this.settings.errorLabelContainer ); 64508 this.submitted = {}; 64509 this.valueCache = {}; 64510 this.pendingRequest = 0; 64511 this.pending = {}; 64512 this.invalid = {}; 64513 this.reset(); 64514 64515 var groups = (this.groups = {}), 64516 rules; 64517 $.each(this.settings.groups, function( key, value ) { 64518 if ( typeof value === "string" ) { 64519 value = value.split(/\s/); 64520 } 64521 $.each(value, function( index, name ) { 64522 groups[name] = key; 64523 }); 64524 }); 64525 rules = this.settings.rules; 64526 $.each(rules, function( key, value ) { 64527 rules[key] = $.validator.normalizeRule(value); 64528 }); 64529 64530 function delegate(event) { 64531 var validator = $.data(this[0].form, "validator"), 64532 eventType = "on" + event.type.replace(/^validate/, ""), 64533 settings = validator.settings; 64534 if ( settings[eventType] && !this.is( settings.ignore ) ) { 64535 settings[eventType].call(validator, this[0], event); 64536 } 64537 } 64538 $(this.currentForm) 64539 .validateDelegate(":text, [type='password'], [type='file'], select, textarea, " + 64540 "[type='number'], [type='search'] ,[type='tel'], [type='url'], " + 64541 "[type='email'], [type='datetime'], [type='date'], [type='month'], " + 64542 "[type='week'], [type='time'], [type='datetime-local'], " + 64543 "[type='range'], [type='color'] ", 64544 "focusin focusout keyup", delegate) 64545 .validateDelegate("[type='radio'], [type='checkbox'], select, option", "click", delegate); 64546 64547 if ( this.settings.invalidHandler ) { 64548 $(this.currentForm).bind("invalid-form.validate", this.settings.invalidHandler); 64549 } 64550 64551 // Add aria-required to any Static/Data/Class required fields before first validation 64552 // Screen readers require this attribute to be present before the initial submission http://www.w3.org/TR/WCAG-TECHS/ARIA2.html 64553 $(this.currentForm).find("[required], [data-rule-required], .required").attr("aria-required", "true"); 64554 }, 64555 64556 // http://jqueryvalidation.org/Validator.form/ 64557 form: function() { 64558 this.checkForm(); 64559 $.extend(this.submitted, this.errorMap); 64560 this.invalid = $.extend({}, this.errorMap); 64561 if ( !this.valid() ) { 64562 $(this.currentForm).triggerHandler("invalid-form", [ this ]); 64563 } 64564 this.showErrors(); 64565 return this.valid(); 64566 }, 64567 64568 checkForm: function() { 64569 this.prepareForm(); 64570 for ( var i = 0, elements = (this.currentElements = this.elements()); elements[i]; i++ ) { 64571 this.check( elements[i] ); 64572 } 64573 return this.valid(); 64574 }, 64575 64576 // http://jqueryvalidation.org/Validator.element/ 64577 element: function( element ) { 64578 var cleanElement = this.clean( element ), 64579 checkElement = this.validationTargetFor( cleanElement ), 64580 result = true; 64581 64582 this.lastElement = checkElement; 64583 64584 if ( checkElement === undefined ) { 64585 delete this.invalid[ cleanElement.name ]; 64586 } else { 64587 this.prepareElement( checkElement ); 64588 this.currentElements = $( checkElement ); 64589 64590 result = this.check( checkElement ) !== false; 64591 if (result) { 64592 delete this.invalid[checkElement.name]; 64593 } else { 64594 this.invalid[checkElement.name] = true; 64595 } 64596 } 64597 // Add aria-invalid status for screen readers 64598 $( element ).attr( "aria-invalid", !result ); 64599 64600 if ( !this.numberOfInvalids() ) { 64601 // Hide error containers on last error 64602 this.toHide = this.toHide.add( this.containers ); 64603 } 64604 this.showErrors(); 64605 return result; 64606 }, 64607 64608 // http://jqueryvalidation.org/Validator.showErrors/ 64609 showErrors: function( errors ) { 64610 if ( errors ) { 64611 // add items to error list and map 64612 $.extend( this.errorMap, errors ); 64613 this.errorList = []; 64614 for ( var name in errors ) { 64615 this.errorList.push({ 64616 message: errors[name], 64617 element: this.findByName(name)[0] 64618 });
vendor: 4,846 bytes, lines 64619-64798
64619 } 64620 // remove items from success list 64621 this.successList = $.grep( this.successList, function( element ) { 64622 return !(element.name in errors); 64623 }); 64624 } 64625 if ( this.settings.showErrors ) { 64626 this.settings.showErrors.call( this, this.errorMap, this.errorList ); 64627 } else { 64628 this.defaultShowErrors(); 64629 } 64630 }, 64631 64632 // http://jqueryvalidation.org/Validator.resetForm/ 64633 resetForm: function() { 64634 if ( $.fn.resetForm ) { 64635 $(this.currentForm).resetForm(); 64636 } 64637 this.submitted = {}; 64638 this.lastElement = null; 64639 this.prepareForm(); 64640 this.hideErrors(); 64641 this.elements() 64642 .removeClass( this.settings.errorClass ) 64643 .removeData( "previousValue" ) 64644 .removeAttr( "aria-invalid" ); 64645 }, 64646 64647 numberOfInvalids: function() { 64648 return this.objectLength(this.invalid); 64649 }, 64650 64651 objectLength: function( obj ) { 64652 /* jshint unused: false */ 64653 var count = 0, 64654 i; 64655 for ( i in obj ) { 64656 count++; 64657 } 64658 return count; 64659 }, 64660 64661 hideErrors: function() { 64662 this.addWrapper( this.toHide ).hide(); 64663 }, 64664 64665 valid: function() { 64666 return this.size() === 0; 64667 }, 64668 64669 size: function() { 64670 return this.errorList.length; 64671 }, 64672 64673 focusInvalid: function() { 64674 if ( this.settings.focusInvalid ) { 64675 try { 64676 $(this.findLastActive() || this.errorList.length && this.errorList[0].element || []) 64677 .filter(":visible") 64678 .focus() 64679 // manually trigger focusin event; without it, focusin handler isn't called, findLastActive won't have anything to find 64680 .trigger("focusin"); 64681 } catch(e) { 64682 // ignore IE throwing errors when focusing hidden elements 64683 } 64684 } 64685 }, 64686 64687 findLastActive: function() { 64688 var lastActive = this.lastActive; 64689 return lastActive && $.grep(this.errorList, function( n ) { 64690 return n.element.name === lastActive.name; 64691 }).length === 1 && lastActive; 64692 }, 64693 64694 elements: function() { 64695 var validator = this, 64696 rulesCache = {}; 64697 64698 // select all valid inputs inside the form (no submit or reset buttons) 64699 return $(this.currentForm) 64700 .find("input, select, textarea") 64701 .not(":submit, :reset, :image, [disabled]") 64702 .not( this.settings.ignore ) 64703 .filter(function() { 64704 if ( !this.name && validator.settings.debug && window.console ) { 64705 console.error( "%o has no name assigned", this); 64706 } 64707 64708 // select only the first element for each name, and only those with rules specified 64709 if ( this.name in rulesCache || !validator.objectLength($(this).rules()) ) { 64710 return false; 64711 } 64712 64713 rulesCache[this.name] = true; 64714 return true; 64715 }); 64716 }, 64717 64718 clean: function( selector ) { 64719 return $(selector)[0]; 64720 }, 64721 64722 errors: function() { 64723 var errorClass = this.settings.errorClass.split(" ").join("."); 64724 return $(this.settings.errorElement + "." + errorClass, this.errorContext); 64725 }, 64726 64727 reset: function() { 64728 this.successList = []; 64729 this.errorList = []; 64730 this.errorMap = {}; 64731 this.toShow = $([]); 64732 this.toHide = $([]); 64733 this.currentElements = $([]); 64734 }, 64735 64736 prepareForm: function() { 64737 this.reset(); 64738 this.toHide = this.errors().add( this.containers ); 64739 }, 64740 64741 prepareElement: function( element ) { 64742 this.reset(); 64743 this.toHide = this.errorsFor(element); 64744 }, 64745 64746 elementValue: function( element ) { 64747 var val, 64748 $element = $(element), 64749 type = $element.attr("type"); 64750 64751 if ( type === "radio" || type === "checkbox" ) { 64752 return $("input[name='" + $element.attr("name") + "']:checked").val(); 64753 } 64754 64755 val = $element.val(); 64756 if ( typeof val === "string" ) { 64757 return val.replace(/\r/g, ""); 64758 } 64759 return val; 64760 }, 64761 64762 check: function( element ) { 64763 element = this.validationTargetFor( this.clean( element ) ); 64764 64765 var rules = $(element).rules(), 64766 rulesCount = $.map( rules, function(n, i) { 64767 return i; 64768 }).length, 64769 dependencyMismatch = false, 64770 val = this.elementValue(element), 64771 result, method, rule; 64772 64773 for (method in rules ) { 64774 rule = { method: method, parameters: rules[method] }; 64775 try { 64776 64777 result = $.validator.methods[method].call( this, val, element, rule.parameters ); 64778 64779 // if a method indicates that the field is optional and therefore valid, 64780 // don't mark it as valid when there are no other rules 64781 if ( result === "dependency-mismatch" && rulesCount === 1 ) { 64782 dependencyMismatch = true; 64783 continue; 64784 } 64785 dependencyMismatch = false; 64786 64787 if ( result === "pending" ) { 64788 this.toHide = this.toHide.not( this.errorsFor(element) ); 64789 return; 64790 } 64791 64792 if ( !result ) { 64793 this.formatAndAdd( element, rule ); 64794 return false; 64795 } 64796 } catch(e) { 64797 if ( this.settings.debug && window.console ) { 64798 console.log( "Exception occurred when checking element " + element.i
64798d + ", check the '" + rule.method + "' method.", e ); 64799 } 64800 throw e; 64801 } 64802 } 64803 if ( dependencyMismatch ) { 64804 return; 64805 } 64806 if ( this.objectLength(rules) ) { 64807 this.successList.push(element); 64808 } 64809 return true; 64810 }, 64811 64812 // return the custom message for the given element and validation method 64813 // specified in the element's HTML5 data attribute 64814 // return the generic message if present and no method specific message is present 64815 customDataMessage: function( element, method ) { 64816 return $( element ).data( "msg" + method[ 0 ].toUpperCase() + 64817 method.substring( 1 ).toLowerCase() ) || $( element ).data("msg"); 64818 }, 64819 64820 // return the custom message for the given element name and validation method 64821 customMessage: function( name, method ) { 64822 var m = this.settings.messages[name]; 64823 return m && (m.constructor === String ? m : m[method]); 64824 }, 64825 64826 // return the first defined argument, allowing empty strings 64827 findDefined: function() { 64828 for (var i = 0; i < arguments.length; i++) { 64829 if ( arguments[i] !== undefined ) { 64830 return arguments[i]; 64831 } 64832 } 64833 return undefined; 64834 }, 64835 64836 defaultMessage: function( element, method ) { 64837 return this.findDefined( 64838 this.customMessage( element.name, method ), 64839 this.customDataMessage( element, method ), 64840 // title is never undefined, so handle empty string as undefined 64841 !this.settings.ignoreTitle && element.title || undefined, 64842 $.validator.messages[method], 64843 "<strong>Warning: No message defined for " + element.name + "</strong>" 64844 ); 64845 }, 64846 64847 formatAndAdd: function( element, rule ) { 64848 var message = this.defaultMessage( element, rule.method ), 64849 theregex = /\$?\{(\d+)\}/g; 64850 if ( typeof message === "function" ) { 64851 message = message.call(this, rule.parameters, element); 64852 } else if (theregex.test(message)) { 64853 message = $.validator.format(message.replace(theregex, "{$1}"), rule.parameters); 64854 } 64855 this.errorList.push({ 64856 message: message, 64857 element: element, 64858 method: rule.method 64859 }); 64860 64861 this.errorMap[element.name] = message; 64862 this.submitted[element.name] = message; 64863 }, 64864 64865 addWrapper: function( toToggle ) { 64866 if ( this.settings.wrapper ) { 64867 toToggle = toToggle.add( toToggle.parent( this.settings.wrapper ) ); 64868 } 64869 return toToggle; 64870 }, 64871 64872 defaultShowErrors: function() { 64873 var i, elements, error; 64874 for ( i = 0; this.errorList[i]; i++ ) { 64875 error = this.errorList[i]; 64876 if ( this.settings.highlight ) { 64877 this.settings.highlight.call( this, error.element, this.settings.errorClass, this.settings.validClass ); 64878 } 64879 this.showLabel( error.element, error.message ); 64880 } 64881 if ( this.errorList.length ) { 64882 this.toShow = this.toShow.add( this.containers ); 64883 } 64884 if ( this.settings.success ) { 64885 for ( i = 0; this.successList[i]; i++ ) { 64886 this.showLabel( this.successList[i] ); 64887 } 64888 } 64889 if ( this.settings.unhighlight ) { 64890 for ( i = 0, elements = this.validElements(); elements[i]; i++ ) { 64891 this.settings.unhighlight.call( this, elements[i], this.settings.errorClass, this.settings.validClass ); 64892 } 64893 } 64894 this.toHide = this.toHide.not( this.toShow ); 64895 this.hideErrors(); 64896 this.addWrapper( this.toShow ).show(); 64897 }, 64898 64899 validElements: function() { 64900 return this.currentElements.not(this.invalidElements()); 64901 }, 64902 64903 invalidElements: function() { 64904 return $(this.errorList).map(function() { 64905 return this.element; 64906 }); 64907 }, 64908 64909 showLabel: function( element, message ) { 64910 var label = this.errorsFor( element ); 64911 if ( label.length ) { 64912 // refresh error/success class 64913 label.removeClass( this.settings.validClass ).addClass( this.settings.errorClass ); 64914 // replace message on existing label 64915 label.html(message); 64916 } else { 64917 // create label 64918 label = $("<" + this.settings.errorElement + ">") 64919 .attr("for", this.idOrName(element)) 64920 .addClass(this.settings.errorClass) 64921 .html(message || ""); 64922 if ( this.settings.wrapper ) { 64923 // make sure the element is visible, even in IE 64924 // actually showing the wrapped element is handled elsewhere 64925 label = label.hide().show().wrap("<" + this.settings.wrapper + "/>").parent(); 64926 } 64927 if ( !this.labelContainer.append(label).length ) { 64928 if ( this.settings.errorPlacement ) { 64929 this.settings.errorPlacement(label, $(element) ); 64930 } else { 64931 label.insertAfter(element); 64932 } 64933 } 64934 } 64935 if ( !message && this.settings.success ) { 64936 label.text(""); 64937 if ( typeof this.settings.success === "string" ) { 64938 label.addClass( this.settings.success ); 64939 } else { 64940 this.settings.success( label, element ); 64941 } 64942 } 64943 this.toShow = this.toShow.add(label); 64944 }, 64945 64946 errorsFor: function( element ) { 64947 var name = this.idOrName(element); 64948 return this.errors().filter(function() { 64949 return $(this).attr("for") === name; 64950 }); 64951 }, 64952 64953 idOrName: function( element ) { 64954 return this.groups[element.name] || (this.checkable(element) ? element.name : element.i
vendor: 7,023 bytes, lines 64954-65204
64954d || element.name); 64955 }, 64956 64957 validationTargetFor: function( element ) { 64958 // if radio/checkbox, validate first element in group instead 64959 if ( this.checkable(element) ) { 64960 element = this.findByName( element.name ).not(this.settings.ignore)[0]; 64961 } 64962 return element; 64963 }, 64964 64965 checkable: function( element ) { 64966 return (/radio|checkbox/i).test(element.type); 64967 }, 64968 64969 findByName: function( name ) { 64970 return $(this.currentForm).find("[name='" + name + "']"); 64971 }, 64972 64973 getLength: function( value, element ) { 64974 switch ( element.nodeName.toLowerCase() ) { 64975 case "select": 64976 return $("option:selected", element).length; 64977 case "input": 64978 if ( this.checkable( element) ) { 64979 return this.findByName(element.name).filter(":checked").length; 64980 } 64981 } 64982 return value.length; 64983 }, 64984 64985 depend: function( param, element ) { 64986 return this.dependTypes[typeof param] ? this.dependTypes[typeof param](param, element) : true; 64987 }, 64988 64989 dependTypes: { 64990 "boolean": function( param ) { 64991 return param; 64992 }, 64993 "string": function( param, element ) { 64994 return !!$(param, element.form).length; 64995 }, 64996 "function": function( param, element ) { 64997 return param(element); 64998 } 64999 }, 65000 65001 optional: function( element ) { 65002 var val = this.elementValue(element); 65003 return !$.validator.methods.required.call(this, val, element) && "dependency-mismatch"; 65004 }, 65005 65006 startRequest: function( element ) { 65007 if ( !this.pending[element.name] ) { 65008 this.pendingRequest++; 65009 this.pending[element.name] = true; 65010 } 65011 }, 65012 65013 stopRequest: function( element, valid ) { 65014 this.pendingRequest--; 65015 // sometimes synchronization fails, make sure pendingRequest is never < 0 65016 if ( this.pendingRequest < 0 ) { 65017 this.pendingRequest = 0; 65018 } 65019 delete this.pending[element.name]; 65020 if ( valid && this.pendingRequest === 0 && this.formSubmitted && this.form() ) { 65021 $(this.currentForm).submit(); 65022 this.formSubmitted = false; 65023 } else if (!valid && this.pendingRequest === 0 && this.formSubmitted) { 65024 $(this.currentForm).triggerHandler("invalid-form", [ this ]); 65025 this.formSubmitted = false; 65026 } 65027 }, 65028 65029 previousValue: function( element ) { 65030 return $.data(element, "previousValue") || $.data(element, "previousValue", { 65031 old: null, 65032 valid: true, 65033 message: this.defaultMessage( element, "remote" ) 65034 }); 65035 } 65036 65037 }, 65038 65039 classRuleSettings: { 65040 required: { required: true }, 65041 email: { email: true }, 65042 url: { url: true }, 65043 date: { date: true }, 65044 dateISO: { dateISO: true }, 65045 number: { number: true }, 65046 digits: { digits: true }, 65047 creditcard: { creditcard: true } 65048 }, 65049 65050 addClassRules: function( className, rules ) { 65051 if ( className.constructor === String ) { 65052 this.classRuleSettings[className] = rules; 65053 } else { 65054 $.extend(this.classRuleSettings, className); 65055 } 65056 }, 65057 65058 classRules: function( element ) { 65059 var rules = {}, 65060 classes = $(element).attr("class"); 65061 65062 if ( classes ) { 65063 $.each(classes.split(" "), function() { 65064 if ( this in $.validator.classRuleSettings ) { 65065 $.extend(rules, $.validator.classRuleSettings[this]); 65066 } 65067 }); 65068 } 65069 return rules; 65070 }, 65071 65072 attributeRules: function( element ) { 65073 var rules = {}, 65074 $element = $(element), 65075 type = element.getAttribute("type"), 65076 method, value; 65077 65078 for (method in $.validator.methods) { 65079 65080 // support for <input required> in both html5 and older browsers 65081 if ( method === "required" ) { 65082 value = element.getAttribute(method); 65083 // Some browsers return an empty string for the required attribute 65084 // and non-HTML5 browsers might have required="" markup 65085 if ( value === "" ) { 65086 value = true; 65087 } 65088 // force non-HTML5 browsers to return bool 65089 value = !!value; 65090 } else { 65091 value = $element.attr(method); 65092 } 65093 65094 // convert the value to a number for number inputs, and for text for backwards compability 65095 // allows type="date" and others to be compared as strings 65096 if ( /min|max/.test( method ) && ( type === null || /number|range|text/.test( type ) ) ) { 65097 value = Number(value); 65098 } 65099 65100 if ( value || value === 0 ) { 65101 rules[method] = value; 65102 } else if ( type === method && type !== "range" ) { 65103 // exception: the jquery validate 'range' method 65104 // does not test for the html5 'range' type 65105 rules[method] = true; 65106 } 65107 } 65108 65109 // maxlength may be returned as -1, 2147483647 (IE) and 524288 (safari) for text inputs 65110 if ( rules.maxlength && /-1|2147483647|524288/.test(rules.maxlength) ) { 65111 delete rules.maxlength; 65112 } 65113 65114 return rules; 65115 }, 65116 65117 dataRules: function( element ) { 65118 var method, value, 65119 rules = {}, $element = $( element ); 65120 for ( method in $.validator.methods ) { 65121 value = $element.data( "rule" + method[ 0 ].toUpperCase() + method.substring( 1 ).toLowerCase() ); 65122 if ( value !== undefined ) { 65123 rules[ method ] = value; 65124 } 65125 } 65126 return rules; 65127 }, 65128 65129 staticRules: function( element ) { 65130 var rules = {}, 65131 validator = $.data(element.form, "validator"); 65132 65133 if ( validator.settings.rules ) { 65134 rules = $.validator.normalizeRule(validator.settings.rules[element.name]) || {}; 65135 } 65136 return rules; 65137 }, 65138 65139 normalizeRules: function( rules, element ) { 65140 // handle dependency check 65141 $.each(rules, function( prop, val ) { 65142 // ignore rule when param is explicitly false, eg. required:false 65143 if ( val === false ) { 65144 delete rules[prop]; 65145 return; 65146 } 65147 if ( val.param || val.depends ) { 65148 var keepRule = true; 65149 switch (typeof val.depends) { 65150 case "string": 65151 keepRule = !!$(val.depends, element.form).length; 65152 break; 65153 case "function": 65154 keepRule = val.depends.call(element, element); 65155 break; 65156 } 65157 if ( keepRule ) { 65158 rules[prop] = val.param !== undefined ? val.param : true; 65159 } else { 65160 delete rules[prop]; 65161 } 65162 } 65163 }); 65164 65165 // evaluate parameters 65166 $.each(rules, function( rule, parameter ) { 65167 rules[rule] = $.isFunction(parameter) ? parameter(element) : parameter; 65168 }); 65169 65170 // clean number parameters 65171 $.each([ "minlength", "maxlength" ], function() { 65172 if ( rules[this] ) { 65173 rules[this] = Number(rules[this]); 65174 } 65175 }); 65176 $.each([ "rangelength", "range" ], function() { 65177 var parts; 65178 if ( rules[this] ) { 65179 if ( $.isArray(rules[this]) ) { 65180 rules[this] = [ Number(rules[this][0]), Number(rules[this][1]) ]; 65181 } else if ( typeof rules[this] === "string" ) { 65182 parts = rules[this].split(/[\s,]+/); 65183 rules[this] = [ Number(parts[0]), Number(parts[1]) ]; 65184 } 65185 } 65186 }); 65187 65188 if ( $.validator.autoCreateRanges ) { 65189 // auto-create ranges 65190 if ( rules.min && rules.max ) { 65191 rules.range = [ rules.min, rules.max ]; 65192 delete rules.min; 65193 delete rules.max; 65194 } 65195 if ( rules.minlength && rules.maxlength ) { 65196 rules.rangelength = [ rules.minlength, rules.maxlength ]; 65197 delete rules.minlength; 65198 delete rules.maxlength; 65199 } 65200 } 65201 65202 return rules; 65203 }, 65204
65205 // Converts a simple string to a {string: true} rule, e.g., "required" to {required:true} 65206 normalizeRule: function( data ) { 65207 if ( typeof data === "string" ) { 65208 var transformed = {}; 65209 $.each(data.split(/\s/), function() { 65210 transformed[this] = true; 65211 }); 65212 data = transformed; 65213 } 65214 return data; 65215 }, 65216 65217 // http://jqueryvalidation.org/jQuery.validator.addMethod/ 65218 addMethod: function( name, method, message ) { 65219 $.validator.methods[name] = method; 65220 $.validator.messages[name] = message !== undefined ? message : $.validator.messages[name]; 65221 if ( method.length < 3 ) { 65222 $.validator.addClassRules(name, $.validator.normalizeRule(name)); 65223 } 65224 }, 65225 65226 methods: { 65227 65228 // http://jqueryvalidation.org/required-method/ 65229 required: function( value, element, param ) { 65230 // check if dependency is met 65231 if ( !this.depend(param, element) ) { 65232 return "dependency-mismatch"; 65233 } 65234 if ( element.nodeName.toLowerCase() === "select" ) { 65235 // could be an array for select-multiple or a string, both are fine this way 65236 var val = $(element).val(); 65237 return val && val.length > 0; 65238 } 65239 if ( this.checkable(element) ) { 65240 return this.getLength(value, element) > 0; 65241 } 65242 return $.trim(value).length > 0; 65243 }, 65244 65245 // http://jqueryvalidation.org/email-method/ 65246 email: function( value, element ) { 65247 // From http://www.whatwg.org/specs/web-apps/current-work/multipage/states-of-the-type-attribute.html#e-mail-state-%28type=email%29 65248 // Retrieved 2014-01-14 65249 // If you have a problem with this implementation, report a bug against the above spec 65250 // Or use custom methods to implement your own email validation 65251 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); 65252 }, 65253 65254 // http://jqueryvalidation.org/url-method/ 65255 url: function( value, element ) { 65256 // contributed by Scott Gonzalez: http://projects.scottsplayground.com/iri/ 65257 return this.optional(element) || /^(https?|s?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); 65258 }, 65259 65260 // http://jqueryvalidation.org/date-method/ 65261 date: function( value, element ) { 65262 return this.optional(element) || !/Invalid|NaN/.test(new Date(value).toString()); 65263 }, 65264 65265 // http://jqueryvalidation.org/dateISO-method/ 65266 dateISO: function( value, element ) { 65267 return this.optional(element) || /^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}$/.test(value); 65268 }, 65269 65270 // http://jqueryvalidation.org/number-method/ 65271 number: function( value, element ) { 65272 return this.optional(element) || /^-?(?:\d+|\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test(value); 65273 }, 65274 65275 // http://jqueryvalidation.org/digits-method/ 65276 digits: function( value, element ) { 65277 return this.optional(element) || /^\d+$/.test(value); 65278 }, 65279 65280 // http://jqueryvalidation.org/creditcard-method/ 65281 // based on http://en.wikipedia.org/wiki/Luhn/ 65282 creditcard: function( value, element ) { 65283 if ( this.optional(element) ) { 65284 return "dependency-mismatch"; 65285 } 65286 // accept only spaces, digits and dashes 65287 if ( /[^0-9 \-]+/.test(value) ) { 65288 return false; 65289 } 65290 var nCheck = 0, 65291 nDigit = 0, 65292 bEven = false, 65293 n, cDigit; 65294 65295 value = value.replace(/\D/g, ""); 65296 65297 // Basing min and max length on 65298 // http://developer.ean.com/general_info/Valid_Credit_Card_Types 65299 if ( value.length < 13 || value.length > 19 ) { 65300 return false; 65301 } 65302 65303 for ( n = value.length - 1; n >= 0; n--) { 65304 cDigit = value.charAt(n); 65305 nDigit = parseInt(cDigit, 10);
65306 if ( bEven ) { 65307 if ( (nDigit *= 2) > 9 ) { 65308 nDigit -= 9; 65309 } 65310 } 65311 nCheck += nDigit; 65312 bEven = !bEven; 65313 } 65314 65315 return (nCheck % 10) === 0; 65316 }, 65317 65318 // http://jqueryvalidation.org/minlength-method/ 65319 minlength: function( value, element, param ) { 65320 var length = $.isArray( value ) ? value.length : this.getLength($.trim(value), element); 65321 return this.optional(element) || length >= param; 65322 }, 65323 65324 // http://jqueryvalidation.org/maxlength-method/ 65325 maxlength: function( value, element, param ) { 65326 var length = $.isArray( value ) ? value.length : this.getLength($.trim(value), element); 65327 return this.optional(element) || length <= param; 65328 }, 65329 65330 // http://jqueryvalidation.org/rangelength-method/ 65331 rangelength: function( value, element, param ) { 65332 var length = $.isArray( value ) ? value.length : this.getLength($.trim(value), element); 65333 return this.optional(element) || ( length >= param[0] && length <= param[1] ); 65334 }, 65335 65336 // http://jqueryvalidation.org/min-method/ 65337 min: function( value, element, param ) { 65338 return this.optional(element) || value >= param; 65339 }, 65340 65341 // http://jqueryvalidation.org/max-method/ 65342 max: function( value, element, param ) { 65343 return this.optional(element) || value <= param; 65344 }, 65345 65346 // http://jqueryvalidation.org/range-method/ 65347 range: function( value, element, param ) { 65348 return this.optional(element) || ( value >= param[0] && value <= param[1] ); 65349 }, 65350 65351 // http://jqueryvalidation.org/equalTo-method/ 65352 equalTo: function( value, element, param ) {
65353 // bind to the blur event of the target in order to revalidate whenever the target field is updated 65354 // TODO find a way to bind the event just once, avoiding the unbind-rebind overhead 65355 var target = $(param); 65356 if ( this.settings.onfocusout ) { 65357 target.unbind(".validate-equalTo").bind("blur.validate-equalTo", function() { 65358 $(element).valid(); 65359 }); 65360 } 65361 return value === target.val(); 65362 }, 65363 65364 // http://jqueryvalidation.org/remote-method/ 65365 remote: function( value, element, param ) { 65366 if ( this.optional(element) ) { 65367 return "dependency-mismatch"; 65368 } 65369 65370 var previous = this.previousValue(element), 65371 validator, data; 65372 65373 if (!this.settings.messages[element.name] ) { 65374 this.settings.messages[element.name] = {}; 65375 } 65376 previous.originalMessage = this.settings.messages[element.name].remote; 65377 this.settings.messages[element.name].remote = previous.message; 65378 65379 param = typeof param === "string" && { url: param } || param; 65380 65381 if ( previous.old === value ) { 65382 return previous.valid; 65383 } 65384 65385 previous.old = value; 65386 validator = this; 65387 this.startRequest(element); 65388 data = {}; 65389 data[element.name] = value; 65390 $.ajax($.extend(true, { 65391 url: param, 65392 mode: "abort", 65393 port: "validate" + element.name, 65394 dataType: "json", 65395 data: data, 65396 context: validator.currentForm, 65397 success: function( response ) { 65398 var valid = response === true || response === "true", 65399 errors, message, submitted; 65400 65401 validator.settings.messages[element.name].remote = previous.originalMessage; 65402 if ( valid ) { 65403 submitted = validator.formSubmitted; 65404 validator.prepareElement(element); 65405 validator.formSubmitted = submitted; 65406 validator.successList.push(element); 65407 delete validator.invalid[element.name]; 65408 validator.showErrors(); 65409 } else { 65410 errors = {}; 65411 message = response || validator.defaultMessage( element, "remote" ); 65412 errors[element.name] = previous.message = $.isFunction(message) ? message(value) : message; 65413 validator.invalid[element.name] = true; 65414 validator.showErrors(errors); 65415 } 65416 previous.valid = valid; 65417 validator.stopRequest(element, valid); 65418 } 65419 }, param)); 65420 return "pending"; 65421 } 65422 65423 } 65424 65425}); 65426 65427$.format = function deprecated() { 65428 throw "$.format has been deprecated. Please use $.validator.format instead."; 65429}; 65430 65431}(jQuery)); 65432 65433// ajax mode: abort 65434// usage: $.ajax({ mode: "abort"[, port: "uniqueport"]}); 65435// if mode:"abort" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort() 65436(function($) { 65437 var pendingRequests = {}, 65438 ajax; 65439 // Use a prefilter if available (1.5+) 65440 if ( $.ajaxPrefilter ) { 65441 $.ajaxPrefilter(function( settings, _, xhr ) { 65442 var port = settings.port; 65443 if ( settings.mode === "abort" ) { 65444 if ( pendingRequests[port] ) { 65445 pendingRequests[port].abort(); 65446 } 65447 pendingRequests[port] = xhr; 65448 } 65449 }); 65450 } else { 65451 // Proxy ajax 65452 ajax = $.ajax; 65453 $.ajax = function( settings ) { 65454 var mode = ( "mode" in settings ? settings : $.ajaxSettings ).mode, 65455 port = ( "port" in settings ? settings : $.ajaxSettings ).port; 65456 if ( mode === "abort" ) { 65457 if ( pendingRequests[port] ) { 65458 pendingRequests[port].abort(); 65459 } 65460 pendingRequests[port] = ajax.apply(this, arguments); 65461 return pendingRequests[port]; 65462 } 65463 return ajax.apply(this, arguments); 65464 }; 65465 } 65466}(jQuery)); 65467 65468// provides delegate(type: String, delegate: Selector, handler: Callback) plugin for easier event delegation 65469// handler is only called when $(event.target).is(delegate), in the scope of the jquery-object for event.target 65470(function($) { 65471 $.extend($.fn, { 65472 validateDelegate: function( delegate, type, handler ) { 65473 return this.bind(type, function( event ) { 65474 var target = $(event.target); 65475 if ( target.is(delegate) ) { 65476 return handler.apply(target, arguments); 65477 } 65478 }); 65479 } 65480 }); 65481}(jQuery)); 65482 65483define("jqueryValidate", ["jquery"], (function (global) { 65484 return function () { 65485 var ret, fn; 65486 return ret || global.$; 65487 }; 65488}(this))); 65489 65490/*! 65491 * JavaScript Cookie v2.1.4 65492 * https://github.com/js-cookie/js-cookie 65493 * 65494 * Copyright 2006, 2015 Klaus Hartl & Fagner Brack 65495 * Released under the MIT license 65496 */ 65497;(function (factory) { 65498 var registeredInModuleLoader = false;
65499 if (typeof define === 'function' && define.amd) { 65500 define('jscookie',factory); 65501 registeredInModuleLoader = true; 65502 } 65503 if (typeof exports === 'object') { 65504 module.exports = factory(); 65505 registeredInModuleLoader = true; 65506 } 65507 if (!registeredInModuleLoader) { 65508 var OldCookies = window.Cookies; 65509 var api = window.Cookies = factory(); 65510 api.noConflict = function () { 65511 window.Cookies = OldCookies; 65512 return api; 65513 }; 65514 } 65515}(function () { 65516 function extend () { 65517 var i = 0; 65518 var result = {}; 65519 for (; i < arguments.length; i++) { 65520 var attributes = arguments[ i ]; 65521 for (var key in attributes) { 65522 result[key] = attributes[key]; 65523 } 65524 } 65525 return result; 65526 } 65527 65528 function init (converter) { 65529 function api (key, value, attributes) { 65530 var result; 65531 if (typeof document === 'undefined') { 65532 return; 65533 } 65534 65535 // Write 65536 65537 if (arguments.length > 1) { 65538 attributes = extend({ 65539 path: '/' 65540 }, api.defaults, attributes); 65541 65542 if (typeof attributes.expires === 'number') { 65543 var expires = new Date(); 65544 expires.setMilliseconds(expires.getMilliseconds() + attributes.expires * 864e+5); 65545 attributes.expires = expires; 65546 } 65547 65548 // We're using "expires" because "max-age" is not supported by IE 65549 attributes.expires = attributes.expires ? attributes.expires.toUTCString() : ''; 65550 65551 try { 65552 result = JSON.stringify(value); 65553 if (/^[\{\[]/.test(result)) { 65554 value = result; 65555 } 65556 } catch (e) {} 65557 65558 if (!converter.write) { 65559 value = encodeURIComponent(String(value)) 65560 .replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g, decodeURIComponent); 65561 } else { 65562 value = converter.write(value, key); 65563 } 65564 65565 key = encodeURIComponent(String(key)); 65566 key = key.replace(/%(23|24|26|2B|5E|60|7C)/g, decodeURIComponent); 65567 key = key.replace(/[\(\)]/g, escape); 65568 65569 var stringifiedAttributes = ''; 65570 65571 for (var attributeName in attributes) { 65572 if (!attributes[attributeName]) { 65573 continue; 65574 } 65575 stringifiedAttributes += '; ' + attributeName; 65576 if (attributes[attributeName] === true) { 65577 continue; 65578 } 65579 stringifiedAttributes += '=' + attributes[attributeName]; 65580 } 65581 return (document.cookie = key + '=' + value + stringifiedAttributes); 65582 } 65583 65584 // Read 65585 65586 if (!key) { 65587 result = {}; 65588 } 65589 65590 // To prevent the for loop in the first place assign an empty array 65591 // in case there are no cookies at all. Also prevents odd result when 65592 // calling "get()" 65593 var cookies = document.cookie ? document.cookie.split('; ') : []; 65594 var rdecode = /(%[0-9A-Z]{2})+/g; 65595 var i = 0; 65596 65597 for (; i < cookies.length; i++) { 65598 var parts = cookies[i].split('='); 65599 var cookie = parts.slice(1).join('='); 65600 65601 if (cookie.charAt(0) === '"') { 65602 cookie = cookie.slice(1, -1); 65603 } 65604 65605 try { 65606 var name = parts[0].replace(rdecode, decodeURIComponent); 65607 cookie = converter.read ? 65608 converter.read(cookie, name) : converter(cookie, name) || 65609 cookie.replace(rdecode, decodeURIComponent); 65610 65611 if (this.json) { 65612 try { 65613 cookie = JSON.parse(cookie); 65614 } catch (e) {} 65615 } 65616 65617 if (key === name) { 65618 result = cookie; 65619 break; 65620 } 65621 65622 if (!key) { 65623 result[name] = cookie; 65624 } 65625 } catch (e) {} 65626 } 65627 65628 return result; 65629 } 65630 65631 api.set = api; 65632 api.get = function (key) { 65633 return api.call(api, key); 65634 }; 65635 api.getJSON = function () { 65636 return api.apply({ 65637 json: true 65638 }, [].slice.call(arguments)); 65639 }; 65640 api.defaults = {}; 65641 65642 api.remove = function (key, attributes) { 65643 api(key, '', extend(attributes, { 65644 expires: -1 65645 })); 65646 }; 65647 65648 api.withConverter = init; 65649 65650 return api; 65651 } 65652 65653 return init(function () {}); 65654})); 65655 65656/*! 65657 * Knockout JavaScript library v3.2.0 65658 * (c) Steven Sanderson - http://knockoutjs.com/ 65659 * License: MIT (http://www.opensource.org/licenses/mit-license.php) 65660 */ 65661 65662(function() {(function(p){var s=this||(0,eval)("this"),v=s.document,L=s.navigator,w=s.jQuery,D=s.JSON;(function(p){"function"===typeof require&&"object"===typeof exports&&"object"===typeof module?p(module.exports||exports,require):"function"===typeof define&&define.amd?define('knockout',["exports","require"],p):p(s.ko={})})(function(M,N){function H(a,d){return null===a||typeof a in R?a===d:!1}function S(a,d){var c;return function(){c||(c=setTimeout(function(){c=p;a()},d))}}function T(a,d){var c;return function(){clearTimeout(c); 65663c=setTimeout(a,d)}}function I(b,d,c,e){a.d[b]={init:function(b,h,k,f,m){var l,q;a.s(function(){var f=a.a.c(h()),k=!c!==!f,z=!q;if(z||d||k!==l)z&&a.Y.la()&&(q=a.a.ia(a.f.childNodes(b),!0)),k?(z||a.f.T(b,a.a.ia(q)),a.Ca(e?e(m,f):m,b)):a.f.j
vendor: 4,243 bytes, lines 65663-65671
65663a(b),l=k},null,{o:b});return{controlsDescendantBindings:!0}}};a.h.ha[b]=!1;a.f.Q[b]=!0}var a="undefined"!==typeof M?M:{};a.b=function(b,d){for(var c=b.split("."),e=a,g=0;g<c.length-1;g++)e=e[c[g]];e[c[c.length-1]]=d};a.A=function(a,d,c){a[d]=c};a.version="3.2.0"; 65664a.b("version",a.version);a.a=function(){function b(a,b){for(var c in a)a.hasOwnProperty(c)&&b(c,a[c])}function d(a,b){if(b)for(var c in b)b.hasOwnProperty(c)&&(a[c]=b[c]);return a}function c(a,b){a.__proto__=b;return a}var e={__proto__:[]}instanceof Array,g={},h={};g[L&&/Firefox\/2/i.test(L.userAgent)?"KeyboardEvent":"UIEvents"]=["keyup","keydown","keypress"];g.MouseEvents="click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave".split(" ");b(g,function(a,b){if(b.length)for(var c= 656650,d=b.length;c<d;c++)h[b[c]]=a});var k={propertychange:!0},f=v&&function(){for(var a=3,b=v.createElement("div"),c=b.getElementsByTagName("i");b.innerHTML="\x3c!--[if gt IE "+ ++a+"]><i></i><![endif]--\x3e",c[0];);return 4<a?a:p}();return{vb:["authenticity_token",/^__RequestVerificationToken(_.*)?$/],u:function(a,b){for(var c=0,d=a.length;c<d;c++)b(a[c],c)},m:function(a,b){if("function"==typeof Array.prototype.indexOf)return Array.prototype.indexOf.call(a,b);for(var c=0,d=a.length;c<d;c++)if(a[c]=== 65666b)return c;return-1},qb:function(a,b,c){for(var d=0,f=a.length;d<f;d++)if(b.call(c,a[d],d))return a[d];return null},ua:function(m,b){var c=a.a.m(m,b);0<c?m.splice(c,1):0===c&&m.shift()},rb:function(m){m=m||[];for(var b=[],c=0,d=m.length;c<d;c++)0>a.a.m(b,m[c])&&b.push(m[c]);return b},Da:function(a,b){a=a||[];for(var c=[],d=0,f=a.length;d<f;d++)c.push(b(a[d],d));return c},ta:function(a,b){a=a||[];for(var c=[],d=0,f=a.length;d<f;d++)b(a[d],d)&&c.push(a[d]);return c},ga:function(a,b){if(b instanceof 65667Array)a.push.apply(a,b);else for(var c=0,d=b.length;c<d;c++)a.push(b[c]);return a},ea:function(b,c,d){var f=a.a.m(a.a.Xa(b),c);0>f?d&&b.push(c):d||b.splice(f,1)},xa:e,extend:d,za:c,Aa:e?c:d,G:b,na:function(a,b){if(!a)return a;var c={},d;for(d in a)a.hasOwnProperty(d)&&(c[d]=b(a[d],d,a));return c},Ka:function(b){for(;b.firstChild;)a.removeNode(b.firstChild)},oc:function(b){b=a.a.S(b);for(var c=v.createElement("div"),d=0,f=b.length;d<f;d++)c.appendChild(a.R(b[d]));return c},ia:function(b,c){for(var d= 656680,f=b.length,e=[];d<f;d++){var k=b[d].cloneNode(!0);e.push(c?a.R(k):k)}return e},T:function(b,c){a.a.Ka(b);if(c)for(var d=0,f=c.length;d<f;d++)b.appendChild(c[d])},Lb:function(b,c){var d=b.nodeType?[b]:b;if(0<d.length){for(var f=d[0],e=f.parentNode,k=0,g=c.length;k<g;k++)e.insertBefore(c[k],f);k=0;for(g=d.length;k<g;k++)a.removeNode(d[k])}},ka:function(a,b){if(a.length){for(b=8===b.nodeType&&b.parentNode||b;a.length&&a[0].parentNode!==b;)a.shift();if(1<a.length){var c=a[0],d=a[a.length-1];for(a.length= 656690;c!==d;)if(a.push(c),c=c.nextSibling,!c)return;a.push(d)}}return a},Nb:function(a,b){7>f?a.setAttribute("selected",b):a.selected=b},cb:function(a){return null===a||a===p?"":a.trim?a.trim():a.toString().replace(/^[\s\xa0]+|[\s\xa0]+$/g,"")},vc:function(a,b){a=a||"";return b.length>a.length?!1:a.substring(0,b.length)===b},cc:function(a,b){if(a===b)return!0;if(11===a.nodeType)return!1;if(b.contains)return b.contains(3===a.nodeType?a.parentNode:a);if(b.compareDocumentPosition)return 16==(b.compareDocumentPosition(a)& 6567016);for(;a&&a!=b;)a=a.parentNode;return!!a},Ja:function(b){return a.a.cc(b,b.ownerDocument.documentElement)},ob:function(b){return!!a.a.qb(b,a.a.Ja)},t:function(a){return a&&a.tagName&&a.tagName.toLowerCase()},n:function(b,c,d){var e=f&&k[c];if(!e&&w)w(b).bind(c,d);else if(e||"function"!=typeof b.addEventListener)if("undefined"!=typeof b.attachEvent){var g=function(a){d.call(b,a)},h="on"+c;b.attachEvent(h,g);a.a.w.da(b,function(){b.detachEvent(h,g)})}else throw Error("Browser doesn't support addEventListener or attachEvent"); 65671else b.addEventListener(c,d,!1)},oa:function(b,c){if(!b||!b.nodeType)throw Error("element must be a DOM node when calling triggerEvent");var d;"input"===a.a.t(b)&&b.type&&"click"==c.toLowerCase()?(d=b.type,d="checkbox"==d||"radio"==d):d=!1;if(w&&!d)w(b).trigger(c);else if("function"==typeof v.createEvent)if("function"==typeof b.dispatchEvent)d=v.createEvent(h[c]||"HTMLEvents"),d.initEvent(c,
vendor: 4,454 bytes, lines 65671-65680
65671!0,!0,s,0,0,0,0,0,!1,!1,!1,!1,0,b),b.dispatchEvent(d);else throw Error("The supplied element doesn't support dispatchEvent"); 65672else if(d&&b.click)b.click();else if("undefined"!=typeof b.fireEvent)b.fireEvent("on"+c);else throw Error("Browser doesn't support triggering events");},c:function(b){return a.C(b)?b():b},Xa:function(b){return a.C(b)?b.v():b},Ba:function(b,c,d){if(c){var f=/\S+/g,e=b.className.match(f)||[];a.a.u(c.match(f),function(b){a.a.ea(e,b,d)});b.className=e.join(" ")}},bb:function(b,c){var d=a.a.c(c);if(null===d||d===p)d="";var f=a.f.firstChild(b);!f||3!=f.nodeType||a.f.nextSibling(f)?a.f.T(b,[b.ownerDocument.createTextNode(d)]): 65673f.data=d;a.a.fc(b)},Mb:function(a,b){a.name=b;if(7>=f)try{a.mergeAttributes(v.createElement("<input name='"+a.name+"'/>"),!1)}catch(c){}},fc:function(a){9<=f&&(a=1==a.nodeType?a:a.parentNode,a.style&&(a.style.zoom=a.style.zoom))},dc:function(a){if(f){var b=a.style.width;a.style.width=0;a.style.width=b}},sc:function(b,c){b=a.a.c(b);c=a.a.c(c);for(var d=[],f=b;f<=c;f++)d.push(f);return d},S:function(a){for(var b=[],c=0,d=a.length;c<d;c++)b.push(a[c]);return b},yc:6===f,zc:7===f,L:f,xb:function(b,c){for(var d= 65674a.a.S(b.getElementsByTagName("input")).concat(a.a.S(b.getElementsByTagName("textarea"))),f="string"==typeof c?function(a){return a.name===c}:function(a){return c.test(a.name)},e=[],k=d.length-1;0<=k;k--)f(d[k])&&e.push(d[k]);return e},pc:function(b){return"string"==typeof b&&(b=a.a.cb(b))?D&&D.parse?D.parse(b):(new Function("return "+b))():null},eb:function(b,c,d){if(!D||!D.stringify)throw Error("Cannot find JSON.stringify(). Some browsers (e.g., IE < 8) don't support it natively, but you can overcome this by adding a script reference to json2.js, downloadable from http://www.json.org/json2.js"); 65675return D.stringify(a.a.c(b),c,d)},qc:function(c,d,f){f=f||{};var e=f.params||{},k=f.includeFields||this.vb,g=c;if("object"==typeof c&&"form"===a.a.t(c))for(var g=c.action,h=k.length-1;0<=h;h--)for(var r=a.a.xb(c,k[h]),E=r.length-1;0<=E;E--)e[r[E].name]=r[E].value;d=a.a.c(d);var y=v.createElement("form");y.style.display="none";y.action=g;y.method="post";for(var p in d)c=v.createElement("input"),c.type="hidden",c.name=p,c.value=a.a.eb(a.a.c(d[p])),y.appendChild(c);b(e,function(a,b){var c=v.createElement("input"); 65676c.type="hidden";c.name=a;c.value=b;y.appendChild(c)});v.body.appendChild(y);f.submitter?f.submitter(y):y.submit();setTimeout(function(){y.parentNode.removeChild(y)},0)}}}();a.b("utils",a.a);a.b("utils.arrayForEach",a.a.u);a.b("utils.arrayFirst",a.a.qb);a.b("utils.arrayFilter",a.a.ta);a.b("utils.arrayGetDistinctValues",a.a.rb);a.b("utils.arrayIndexOf",a.a.m);a.b("utils.arrayMap",a.a.Da);a.b("utils.arrayPushAll",a.a.ga);a.b("utils.arrayRemoveItem",a.a.ua);a.b("utils.extend",a.a.extend);a.b("utils.fieldsIncludedWithJsonPost", 65677a.a.vb);a.b("utils.getFormFields",a.a.xb);a.b("utils.peekObservable",a.a.Xa);a.b("utils.postJson",a.a.qc);a.b("utils.parseJson",a.a.pc);a.b("utils.registerEventHandler",a.a.n);a.b("utils.stringifyJson",a.a.eb);a.b("utils.range",a.a.sc);a.b("utils.toggleDomNodeCssClass",a.a.Ba);a.b("utils.triggerEvent",a.a.oa);a.b("utils.unwrapObservable",a.a.c);a.b("utils.objectForEach",a.a.G);a.b("utils.addOrRemoveItem",a.a.ea);a.b("unwrap",a.a.c);Function.prototype.bind||(Function.prototype.bind=function(a){var d= 65678this,c=Array.prototype.slice.call(arguments);a=c.shift();return function(){return d.apply(a,c.concat(Array.prototype.slice.call(arguments)))}});a.a.e=new function(){function a(b,h){var k=b[c];if(!k||"null"===k||!e[k]){if(!h)return p;k=b[c]="ko"+d++;e[k]={}}return e[k]}var d=0,c="__ko__"+(new Date).getTime(),e={};return{get:function(c,d){var e=a(c,!1);return e===p?p:e[d]},set:function(c,d,e){if(e!==p||a(c,!1)!==p)a(c,!0)[d]=e},clear:function(a){var b=a[c];return b?(delete e[b],a[c]=null,!0):!1},F:function(){return d++ + 65679c}}};a.b("utils.domData",a.a.e);a.b("utils.domData.clear",a.a.e.clear);a.a.w=new function(){function b(b,d){var f=a.a.e.get(b,c);f===p&&d&&(f=[],a.a.e.set(b,c,f));return f}function d(c){var e=b(c,!1);if(e)for(var e=e.slice(0),f=0;f<e.length;f++)e[f](c);a.a.e.clear(c);a.a.w.cleanExternalData(c);if(g[c.nodeType])for(e=c.firstChild;c=e;)e=c.nextSibling,8===c.nodeType&&d(c)}var c=a.a.e.F(),e={1:!0,8:!0,9:!0},g={1:!0,9:!0};return{da:function(a,c){if("function"!=typeof c)throw Error("Callback must be a function"); 65680b(a,!0).push(c)},Kb:function(d,e){var f=b(d,!1);f&&(a.a.ua(f,e),0==f.length&&a.a.e.set(d,c,p))}
65680,R:function(b){if(e[b.nodeType]&&(d(b),g[b.nodeType])){var c=[];a.a.ga(c,b.getElementsByTagName("*"));for(var f=0,m=c.length;f<m;f++)d(c[f])}return b},removeNode:function(b){a.R(b);b.parentNode&&b.parentNode.removeChild(b)},cleanExternalData:function(a){w&&"function"==typeof w.cleanData&&w.cleanData([a])}}};a.R=a.a.w.R;a.removeNode=a.a.w.removeNode;a.b("cleanNode",a.R);a.b("removeNode",a.removeNode);a.b("utils.domNodeDisposal", 65681a.a.w);a.b("utils.domNodeDisposal.addDisposeCallback",a.a.w.da);a.b("utils.domNodeDisposal.removeDisposeCallback",a.a.w.Kb);(function(){a.a.ba=function(b){var d;if(w)if(w.parseHTML)d=w.parseHTML(b)||[];else{if((d=w.clean([b]))&&d[0]){for(b=d[0];b.parentNode&&11!==b.parentNode.nodeType;)b=b.parentNode;b.parentNode&&b.parentNode.removeChild(b)}}else{var c=a.a.cb(b).toLowerCase();d=v.createElement("div");c=c.match(/^<(thead|tbody|tfoot)/)&&[1,"<table>","</table>"]||!c.indexOf("<tr")&&[2,"<table><tbody>", 65682"</tbody></table>"]||(!c.indexOf("<td")||!c.indexOf("<th"))&&[3,"<table><tbody><tr>","</tr></tbody></table>"]||[0,"",""];b="ignored<div>"+c[1]+b+c[2]+"</div>";for("function"==typeof s.innerShiv?d.appendChild(s.innerShiv(b)):d.innerHTML=b;c[0]--;)d=d.lastChild;d=a.a.S(d.lastChild.childNodes)}return d};a.a.$a=function(b,d){a.a.Ka(b);d=a.a.c(d);if(null!==d&&d!==p)if("string"!=typeof d&&(d=d.toString()),w)w(b).html(d);else for(var c=a.a.ba(d),e=0;e<c.length;e++)b.appendChild(c[e])}})();a.b("utils.parseHtmlFragment", 65683a.a.ba);a.b("utils.setHtml",a.a.$a);a.D=function(){function b(c,d){if(c)if(8==c.nodeType){var g=a.D.Gb(c.nodeValue);null!=g&&d.push({bc:c,mc:g})}else if(1==c.nodeType)for(var g=0,h=c.childNodes,k=h.length;g<k;g++)b(h[g],d)}var d={};return{Ua:function(a){if("function"!=typeof a)throw Error("You can only pass a function to ko.memoization.memoize()");var b=(4294967296*(1+Math.random())|0).toString(16).substring(1)+(4294967296*(1+Math.random())|0).toString(16).substring(1);d[b]=a;return"\x3c!--[ko_memo:"+ 65684b+"]--\x3e"},Rb:function(a,b){var g=d[a];if(g===p)throw Error("Couldn't find any memo with ID "+a+". Perhaps it's already been unmemoized.");try{return g.apply(null,b||[]),!0}finally{delete d[a]}},Sb:function(c,d){var g=[];b(c,g);for(var h=0,k=g.length;h<k;h++){var f=g[h].bc,m=[f];d&&a.a.ga(m,d);a.D.Rb(g[h].mc,m);f.nodeValue="";f.parentNode&&f.parentNode.removeChild(f)}},Gb:function(a){return(a=a.match(/^\[ko_memo\:(.*?)\]$/))?a[1]:null}}}();a.b("memoization",a.D);a.b("memoization.memoize",a.D.Ua); 65685a.b("memoization.unmemoize",a.D.Rb);a.b("memoization.parseMemoText",a.D.Gb);a.b("memoization.unmemoizeDomNodeAndDescendants",a.D.Sb);a.La={throttle:function(b,d){b.throttleEvaluation=d;var c=null;return a.j({read:b,write:function(a){clearTimeout(c);c=setTimeout(function(){b(a)},d)}})},rateLimit:function(a,d){var c,e,g;"number"==typeof d?c=d:(c=d.timeout,e=d.method);g="notifyWhenChangesStop"==e?T:S;a.Ta(function(a){return g(a,c)})},notify:function(a,d){a.equalityComparer="always"==d?null:H}};var R= 65686{undefined:1,"boolean":1,number:1,string:1};a.b("extenders",a.La);a.Pb=function(b,d,c){this.target=b;this.wa=d;this.ac=c;this.Cb=!1;a.A(this,"dispose",this.K)};a.Pb.prototype.K=function(){this.Cb=!0;this.ac()};a.P=function(){a.a.Aa(this,a.P.fn);this.M={}};var G="change",A={U:function(b,d,c){var e=this;c=c||G;var g=new a.Pb(e,d?b.bind(d):b,function(){a.a.ua(e.M[c],g);e.nb&&e.nb()});e.va&&e.va(c);e.M[c]||(e.M[c]=[]);e.M[c].push(g);return g},notifySubscribers:function(b,d){d=d||G;if(this.Ab(d))try{a.k.Ea(); 65687for(var c=this.M[d].slice(0),e=0,g;g=c[e];++e)g.Cb||g.wa(b)}finally{a.k.end()}},Ta:function(b){var d=this,c=a.C(d),e,g,h;d.qa||(d.qa=d.notifySubscribers,d.notifySubscribers=function(a,b){b&&b!==G?"beforeChange"===b?d.kb(a):d.qa(a,b):d.lb(a)});var k=b(function(){c&&h===d&&(h=d());e=!1;d.Pa(g,h)&&d.qa(g=h)});d.lb=function(a){e=!0;h=a;k()};d.kb=function(a){e||(g=a,d.qa(a,"beforeChange"))}},Ab:function(a){return this.M[a]&&this.M[a].length},yb:function(){var b=0;a.a.G(this.M,function(a,c){b+=c.length}); 65688return b},Pa:function(a,d){return!this.equalityComparer||!this.equalityComparer(a,d)},extend:function(b){var d=this;b&&a.a.G(b,function(b,e){var g=a.La[b];"function"==typeof g&&(d=g(d,e)||d)});return d}};a.A(A,"subscribe",A.U);a.A(A,"extend",A.extend);a.A(A,"getSubscriptionsCount",A.yb);a.a.xa&&a.a.za(A,Function.prototype);a.P.fn=A;a.Db=function(a){return null!=a&&"function"==typeof a.U&&"function"==typeof a.notifySubscribers};a.b("subscribable",a.P);a.b("isSubscribable",a.Db);a.Y=a.k=function(){function b(a){c.push(e); 65689e=a}function d(){e=c.pop()}var c=[],e,g=0;return{Ea:b,end:d,Jb:function(b){if(e){if(!a.Db(b))throw Error("Only subscribable things can act as dependencies");e.wa(b,b.Vb||(b.Vb=++g))}},B:function(a,c,f){try{return b(),a.apply(c,f||[])}finally{d()}},la:function(){if(e)return e.s.la()},ma:function(){if(e)return e.ma}}}();a.b("computedContext",a.Y);a.b("computedContext.getDependenciesCount",a.Y.la);a.b("computedContext.isInitial",a.Y.ma);a.b("computedContext.isSleeping",a.Y.Ac);a.p=function(b){function d(){if(0< 65690arguments.length)return d.Pa(c,arguments[0])&&(d.X(),c=arguments[0],d.W()),this;a.k.Jb(d);return c}var c=b;a.P.call(d);a.a.Aa(d,a.p.fn);d.v=function(){return c};d.W=function(){d.notifySubscribers(c)};d.X=function(){d.notifySubscribers(c,"beforeChange")};a.A(d,"peek",d.v);a.A(d,"valueHasMutated",d.W);a.A(d,"valueWillMutate",d.X);return d};a.p.fn={equalityComparer:H};var F=a.p.rc="__ko_proto__";a.p.fn[F]=a.p;a.a.xa&&a.a.za(a.p.fn,a.P.fn);a.Ma=function(b,d){return null===b||b===p||b[F]===p?!1:b[F]=== 65691d?!0:a.Ma(b[F],d)};a.C=function(b){return a.Ma(b,a.p)};a.Ra=function(b){return"function"==typeof b&&b[F]===a.p||"function"==typeof b&&b[F]===a.j&&b.hc?!0:!1};a.b("observable",a.p);a.b("isObservable",a.C);a.b("isWriteableObservable",a.Ra);a.b("isWritableObservable",a.Ra);a.aa=function(b){b=b||[];if("object"!=typeof b||!("length"in b))throw Error("The argument passed when initializing an observable array must be an array, or null, or undefined.");b=a.p(b);a.a.Aa(b,a.aa.fn);return b.extend({trackArrayChanges:!0})}; 65692a.aa.fn={remove:function(b){for(var d=this.v(),c=[],e="function"!=typeof b||a.C(b)?function(a){return a===b}:b,g=0;g<d.length;g++){var h=d[g];e(h)&&(0===c.length&&this.X(),c.push(h),d.splice(g,1),g--)}c.length&&this.W();return c},removeAll:function(b){if(b===p){var d=this.v(),c=d.slice(0);this.X();d.splice(0,d.length);this.W();return c}return b?this.remove(function(c){return 0<=a.a.m(b,c)}):[]},destroy:function(b){var d=this.v(),c="function"!=typeof b||a.C(b)?function(a){return a===b}:b;this.X(); 65693for(var e=d.length-1;0<=e;e--)c(d[e])&&(d[e]._destroy=!0);this.W()},destroyAll:function(b){return b===p?this.destroy(function(){return!0}):b?this.destroy(function(d){return 0<=a.a.m(b,d)}):[]},indexOf:function(b){var d=this();return a.a.m(d,b)},replace:function(a,d){var c=this.indexOf(a);0<=c&&(this.X(),this.v()[c]=d,this.W())}};a.a.u("pop push reverse shift sort splice unshift".split(" "),function(b){a.aa.fn[b]=function(){var a=this.v();this.X();this.sb(a,b,arguments);a=a[b].apply(a,arguments);this.W(); 65694return a}});a.a.u(["slice"],function(b){a.aa.fn[b]=function(){var a=this();return a[b].apply(a,arguments)}});a.a.xa&&a.a.za(a.aa.fn,a.p.fn);a.b("observableArray",a.aa);var J="arrayChange";a.La.trackArrayChanges=function(b){function d(){if(!c){c=!0;var d=b.notifySubscribers;b.notifySubscribers=function(a,b){b&&b!==G||++g;return d.apply(this,arguments)};var f=[].concat(b.v()||[]);e=null;b.U(function(c){c=[].concat(c||[]);if(b.Ab(J)){var d;if(!e||1<g)e=a.a.Fa(f,c,{sparse:!0});d=e;d.length&&b.notifySubscribers(d, 65695J)}f=c;e=null;g=0})}}if(!b.sb){var c=!1,e=null,g=0,h=b.U;b.U=b.subscribe=function(a,b,c){c===J&&d();return h.apply(this,arguments)};b.sb=function(b,d,m){function l(a,b,c){return q[q.length]={status:a,value:b,index:c}}if(c&&!g){var q=[],h=b.length,t=m.length,z=0;switch(d){case "push":z=h;case "unshift":for(d=0;d<t;d++)l("added",m[d],z+d);break;case "pop":z=h-1;case "shift":h&&l("deleted",b[z],z);break;case "splice":d=Math.min(Math.max(0,0>m[0]?h+m[0]:m[0]),h);for(var h=1===t?h:Math.min(d+(m[1]||0), 65696h),t=d+t-2,z=Math.max(h,t),u=[],r=[],E=2;d<z;++d,++E)d<h&&r.push(l("deleted",b[d],d)),d<t&&u.push(l("added",m[E],d));a.a.wb(r,u);break;default:return}e=q}}}};a.s=a.j=function(b,d,c){function e(){a.a.G(v,function(a,b){b.K()});v={}}function g(){e();C=0;u=!0;n=!1}function h(){var a=f.throttleEvaluation;a&&0<=a?(clearTimeout(P),P=setTimeout(k,a)):f.ib?f.ib():k()}function k(b){if(t){if(E)throw Error("A 'pure' computed must not be called recursively");}else if(!u){if(w&&w()){if(!z){s();return}}else z=!1; 65697t=!0;if(y)try{var c={};a.k.Ea({wa:function(a,b){c[b]||(c[b]=1,++C)},s:f,ma:p});C=0;q=r.call(d)}finally{a.k.end(),t=!1}else try{var e=v,m=C;a.k.Ea({wa:function(a,b){u||(m&&e[b]?(v[b]=e[b],++C,delete e[b],--m):v[b]||(v[b]=a.U(h),++C))},s:f,ma:E?p:!C});v={};C=0;try{var l=d?r.call(d):r()}finally{a.k.end(),m&&a.a.G(e,function(a,b){b.K()}),n=!1}f.Pa(q,l)&&(f.notifySubscribers(q,"beforeChange"),q=l,!0!==b&&f.notifySubscribers(q))}finally{t=!1}C||s()}}function f(){if(0<arguments.length){if("function"===typeof O)O.apply(d, 65698arguments);else throw Error("Cannot write a value to a ko.computed unless you specify a 'write' option. If you wish to read the current value, don't pass any parameters.");return this}a.k.Jb(f);n&&k(!0);return q}function m(){n&&!C&&k(!0);return q}function l(){return n||0<C}var q,n=!0,t=!1,z=!1,u=!1,r=b,E=!1,y=!1;r&&"object"==typeof r?(c=r,r=c.read):(c=c||{},r||(r=c.read));if("function"!=typeof r)throw Error("Pass a function that returns the value of the ko.computed");var O=c.write,x=c.disposeWhenNodeIsRemoved|| 65699c.o||null,B=c.disposeWhen||c.Ia,w=B,s=g,v={},C=0,P=null;d||(d=c.owner);a.P.call(f);a.a.Aa(f,a.j.fn);f.v=m;f.la=function(){return C};f.hc="function"===typeof c.write;f.K=function(){s()};f.Z=l;var A=f.Ta;f.Ta=function(a){A.call(f,a);f.ib=function(){f.kb(q);n=!0;f.lb(f)}};c.pure?(y=E=!0,f.va=function(){y&&(y=!1,k(!0))},f.nb=function(){f.yb()||(e(),y=n=!0)}):c.deferEvaluation&&(f.va=function(){m();delete f.va});a.A(f,"peek",f.v);a.A(f,"dispose",f.K);a.A(f,"isActive",f.Z);a.A(f,"getDependenciesCount", 65700f.la);x&&(z=!0,x.nodeType&&(w=function(){return!a.a.Ja(x)||B&&B()}));y||c.deferEvaluation||k();x&&l()&&x.nodeType&&(s=function(){a.a.w.Kb(x,s);g()},a.a.w.da(x,s));return f};a.jc=function(b){return a.Ma(b,a.j)};A=a.p.rc;a.j[A]=a.p;a.j.fn={equalityComparer:H};a.j.fn[A]=a.j;a.a.xa&&a.a.za(a.j.fn,a.P.fn);a.b("dependentObservable",a.j);a.b("computed",a.j);a.b("isComputed",a.jc);a.Ib=function(b,d){if("function"===typeof b)return a.s(b,d,{pure:!0});b=a.a.extend({},b);b.pure=!0;return a.s(b,d)};a.b("pureComputed", 65701a.Ib);(function(){function b(a,g,h){h=h||new c;a=g(a);if("object"!=typeof a||null===a||a===p||a instanceof Date||a instanceof String||a instanceof Number||a instanceof Boolean)return a;var k=a instanceof Array?[]:{};h.save(a,k);d(a,function(c){var d=g(a[c]);switch(typeof d){case "boolean":case "number":case "string":case "function":k[c]=d;break;case "object":case "undefined":var l=h.get(d);k[c]=l!==p?l:b(d,g,h)}});return k}function d(a,b){if(a instanceof Array){for(var c=0;c<a.length;c++)b(c);"function"== 65702typeof a.toJSON&&b("toJSON")}else for(c in a)b(c)}function c(){this.keys=[];this.hb=[]}a.Qb=function(c){if(0==arguments.length)throw Error("When calling ko.toJS, pass the object you want to convert.");return b(c,function(b){for(var c=0;a.C(b)&&10>c;c++)b=b();return b})};a.toJSON=function(b,c,d){b=a.Qb(b);return a.a.eb(b,c,d)};c.prototype={save:function(b,c){var d=a.a.m(this.keys,b);0<=d?this.hb[d]=c:(this.keys.push(b),this.hb.push(c))},get:function(b){b=a.a.m(this.keys,b);return 0<=b?this.hb[b]:p}}})(); 65703a.b("toJS",a.Qb);a.b("toJSON",a.toJSON);(function(){a.i={q:function(b){switch(a.a.t(b)){case "option":return!0===b.__ko__hasDomDataOptionValue__?a.a.e.get(b,a.d.options.Va):7>=a.a.L?b.getAttributeNode("value")&&b.getAttributeNode("value").specified?b.value:b.text:b.value;case "select":return 0<=b.selectedIndex?a.i.q(b.options[b.selectedIndex]):p;default:return b.value}}
vendor: 6,520 bytes, lines 65703-65716
65703,ca:function(b,d,c){switch(a.a.t(b)){case "option":switch(typeof d){case "string":a.a.e.set(b,a.d.options.Va,p);"__ko__hasDomDataOptionValue__"in 65704b&&delete b.__ko__hasDomDataOptionValue__;b.value=d;break;default:a.a.e.set(b,a.d.options.Va,d),b.__ko__hasDomDataOptionValue__=!0,b.value="number"===typeof d?d:""}break;case "select":if(""===d||null===d)d=p;for(var e=-1,g=0,h=b.options.length,k;g<h;++g)if(k=a.i.q(b.options[g]),k==d||""==k&&d===p){e=g;break}if(c||0<=e||d===p&&1<b.size)b.selectedIndex=e;break;default:if(null===d||d===p)d="";b.value=d}}}})();a.b("selectExtensions",a.i);a.b("selectExtensions.readValue",a.i.q);a.b("selectExtensions.writeValue", 65705a.i.ca);a.h=function(){function b(b){b=a.a.cb(b);123===b.charCodeAt(0)&&(b=b.slice(1,-1));var c=[],d=b.match(e),k,n,t=0;if(d){d.push(",");for(var z=0,u;u=d[z];++z){var r=u.charCodeAt(0);if(44===r){if(0>=t){k&&c.push(n?{key:k,value:n.join("")}:{unknown:k});k=n=t=0;continue}}else if(58===r){if(!n)continue}else if(47===r&&z&&1<u.length)(r=d[z-1].match(g))&&!h[r[0]]&&(b=b.substr(b.indexOf(u)+1),d=b.match(e),d.push(","),z=-1,u="/");else if(40===r||123===r||91===r)++t;else if(41===r||125===r||93===r)--t; 65706else if(!k&&!n){k=34===r||39===r?u.slice(1,-1):u;continue}n?n.push(u):n=[u]}}return c}var d=["true","false","null","undefined"],c=/^(?:[$_a-z][$\w]*|(.+)(\.\s*[$_a-z][$\w]*|\[.+\]))$/i,e=RegExp("\"(?:[^\"\\\\]|\\\\.)*\"|'(?:[^'\\\\]|\\\\.)*'|/(?:[^/\\\\]|\\\\.)*/w*|[^\\s:,/][^,\"'{}()/:[\\]]*[^\\s,\"'{}()/:[\\]]|[^\\s]","g"),g=/[\])"'A-Za-z0-9_$]+$/,h={"in":1,"return":1,"typeof":1},k={};return{ha:[],V:k,Wa:b,ya:function(f,m){function e(b,m){var f;if(!z){var u=a.getBindingHandler(b);if(u&&u.preprocess&& 65707!(m=u.preprocess(m,b,e)))return;if(u=k[b])f=m,0<=a.a.m(d,f)?f=!1:(u=f.match(c),f=null===u?!1:u[1]?"Object("+u[1]+")"+u[2]:f),u=f;u&&h.push("'"+b+"':function(_z){"+f+"=_z}")}t&&(m="function(){return "+m+" }");g.push("'"+b+"':"+m)}m=m||{};var g=[],h=[],t=m.valueAccessors,z=m.bindingParams,u="string"===typeof f?b(f):f;a.a.u(u,function(a){e(a.key||a.unknown,a.value)});h.length&&e("_ko_property_writers","{"+h.join(",")+" }");return g.join(",")},lc:function(a,b){for(var c=0;c<a.length;c++)if(a[c].key== 65708b)return!0;return!1},pa:function(b,c,d,e,k){if(b&&a.C(b))!a.Ra(b)||k&&b.v()===e||b(e);else if((b=c.get("_ko_property_writers"))&&b[d])b[d](e)}}}();a.b("expressionRewriting",a.h);a.b("expressionRewriting.bindingRewriteValidators",a.h.ha);a.b("expressionRewriting.parseObjectLiteral",a.h.Wa);a.b("expressionRewriting.preProcessBindings",a.h.ya);a.b("expressionRewriting._twoWayBindings",a.h.V);a.b("jsonExpressionRewriting",a.h);a.b("jsonExpressionRewriting.insertPropertyAccessorsIntoJson",a.h.ya);(function(){function b(a){return 8== 65709a.nodeType&&h.test(g?a.text:a.nodeValue)}function d(a){return 8==a.nodeType&&k.test(g?a.text:a.nodeValue)}function c(a,c){for(var f=a,e=1,k=[];f=f.nextSibling;){if(d(f)&&(e--,0===e))return k;k.push(f);b(f)&&e++}if(!c)throw Error("Cannot find closing comment tag to match: "+a.nodeValue);return null}function e(a,b){var d=c(a,b);return d?0<d.length?d[d.length-1].nextSibling:a.nextSibling:null}var g=v&&"\x3c!--test--\x3e"===v.createComment("test").text,h=g?/^\x3c!--\s*ko(?:\s+([\s\S]+))?\s*--\x3e$/:/^\s*ko(?:\s+([\s\S]+))?\s*$/, 65710k=g?/^\x3c!--\s*\/ko\s*--\x3e$/:/^\s*\/ko\s*$/,f={ul:!0,ol:!0};a.f={Q:{},childNodes:function(a){return b(a)?c(a):a.childNodes},ja:function(c){if(b(c)){c=a.f.childNodes(c);for(var d=0,f=c.length;d<f;d++)a.removeNode(c[d])}else a.a.Ka(c)},T:function(c,d){if(b(c)){a.f.ja(c);for(var f=c.nextSibling,e=0,k=d.length;e<k;e++)f.parentNode.insertBefore(d[e],f)}else a.a.T(c,d)},Hb:function(a,c){b(a)?a.parentNode.insertBefore(c,a.nextSibling):a.firstChild?a.insertBefore(c,a.firstChild):a.appendChild(c)},Bb:function(c, 65711d,f){f?b(c)?c.parentNode.insertBefore(d,f.nextSibling):f.nextSibling?c.insertBefore(d,f.nextSibling):c.appendChild(d):a.f.Hb(c,d)},firstChild:function(a){return b(a)?!a.nextSibling||d(a.nextSibling)?null:a.nextSibling:a.firstChild},nextSibling:function(a){b(a)&&(a=e(a));return a.nextSibling&&d(a.nextSibling)?null:a.nextSibling},gc:b,xc:function(a){return(a=(g?a.text:a.nodeValue).match(h))?a[1]:null},Fb:function(c){if(f[a.a.t(c)]){var k=c.firstChild;if(k){do if(1===k.nodeType){var g;g=k.firstChild; 65712var h=null;if(g){do if(h)h.push(g);else if(b(g)){var t=e(g,!0);t?g=t:h=[g]}else d(g)&&(h=[g]);while(g=g.nextSibling)}if(g=h)for(h=k.nextSibling,t=0;t<g.length;t++)h?c.insertBefore(g[t],h):c.appendChild(g[t])}while(k=k.nextSibling)}}}}})();a.b("virtualElements",a.f);a.b("virtualElements.allowedBindings",a.f.Q);a.b("virtualElements.emptyNode",a.f.ja);a.b("virtualElements.insertAfter",a.f.Bb);a.b("virtualElements.prepend",a.f.Hb);a.b("virtualElements.setDomNodeChildren",a.f.T);(function(){a.J=function(){this.Yb= 65713{}};a.a.extend(a.J.prototype,{nodeHasBindings:function(b){switch(b.nodeType){case 1:return null!=b.getAttribute("data-bind")||a.g.getComponentNameForNode(b);case 8:return a.f.gc(b);default:return!1}},getBindings:function(b,d){var c=this.getBindingsString(b,d),c=c?this.parseBindingsString(c,d,b):null;return a.g.mb(c,b,d,!1)},getBindingAccessors:function(b,d){var c=this.getBindingsString(b,d),c=c?this.parseBindingsString(c,d,b,{valueAccessors:!0}):null;return a.g.mb(c,b,d,!0)},getBindingsString:function(b){switch(b.nodeType){case 1:return b.getAttribute("data-bind"); 65714case 8:return a.f.xc(b);default:return null}},parseBindingsString:function(b,d,c,e){try{var g=this.Yb,h=b+(e&&e.valueAccessors||""),k;if(!(k=g[h])){var f,m="with($context){with($data||{}){return{"+a.h.ya(b,e)+"}}}";f=new Function("$context","$element",m);k=g[h]=f}return k(d,c)}catch(l){throw l.message="Unable to parse bindings.\nBindings value: "+b+"\nMessage: "+l.message,l;}}});a.J.instance=new a.J})();a.b("bindingProvider",a.J);(function(){function b(a){return function(){return a}}function d(a){return a()} 65715function c(b){return a.a.na(a.k.B(b),function(a,c){return function(){return b()[c]}})}function e(a,b){return c(this.getBindings.bind(this,a,b))}function g(b,c,d){var f,e=a.f.firstChild(c),k=a.J.instance,g=k.preprocessNode;if(g){for(;f=e;)e=a.f.nextSibling(f),g.call(k,f);e=a.f.firstChild(c)}for(;f=e;)e=a.f.nextSibling(f),h(b,f,d)}function h(b,c,d){var e=!0,k=1===c.nodeType;k&&a.f.Fb(c);if(k&&d||a.J.instance.nodeHasBindings(c))e=f(c,null,b,d).shouldBindDescendants;e&&!l[a.a.t(c)]&&g(b,c,!k)}function k(b){var c= 65716[],d={},f=[];a.a.G(b,function y(e){if(!d[e]){var k=a.getBindingHandler(e);k&&(k.after&&(f.push(e),a.a.u(k.after,function(c){if(b[c]){if(-1!==a.a.m(f,c)
65716)throw Error("Cannot combine the following bindings, because they have a cyclic dependency: "+f.join(", "));y(c)}}),f.length--),c.push({key:e,zb:k}));d[e]=!0}});return c}function f(b,c,f,g){var m=a.a.e.get(b,q);if(!c){if(m)throw Error("You cannot apply bindings multiple times to the same element.");a.a.e.set(b,q,!0)}!m&&g&&a.Ob(b,f);var l;if(c&&"function"!== 65717typeof c)l=c;else{var h=a.J.instance,n=h.getBindingAccessors||e,s=a.j(function(){(l=c?c(f,b):n.call(h,b,f))&&f.I&&f.I();return l},null,{o:b});l&&s.Z()||(s=null)}var v;if(l){var w=s?function(a){return function(){return d(s()[a])}}:function(a){return l[a]},A=function(){return a.a.na(s?s():l,d)};A.get=function(a){return l[a]&&d(w(a))};A.has=function(a){return a in l};g=k(l);a.a.u(g,function(c){var d=c.zb.init,e=c.zb.update,k=c.key;if(8===b.nodeType&&!a.f.Q[k])throw Error("The binding '"+k+"' cannot be used with virtual elements"); 65718try{"function"==typeof d&&a.k.B(function(){var a=d(b,w(k),A,f.$data,f);if(a&&a.controlsDescendantBindings){if(v!==p)throw Error("Multiple bindings ("+v+" and "+k+") are trying to control descendant bindings of the same element. You cannot use these bindings together on the same element.");v=k}}),"function"==typeof e&&a.j(function(){e(b,w(k),A,f.$data,f)},null,{o:b})}catch(g){throw g.message='Unable to process binding "'+k+": "+l[k]+'"\nMessage: '+g.message,g;}})}return{shouldBindDescendants:v===p}} 65719function m(b){return b&&b instanceof a.N?b:new a.N(b)}a.d={};var l={script:!0};a.getBindingHandler=function(b){return a.d[b]};a.N=function(b,c,d,f){var e=this,k="function"==typeof b&&!a.C(b),g,m=a.j(function(){var g=k?b():b,l=a.a.c(g);c?(c.I&&c.I(),a.a.extend(e,c),m&&(e.I=m)):(e.$parents=[],e.$root=l,e.ko=a);e.$rawData=g;e.$data=l;d&&(e[d]=l);f&&f(e,c,l);return e.$data},null,{Ia:function(){return g&&!a.a.ob(g)},o:!0});m.Z()&&(e.I=m,m.equalityComparer=null,g=[],m.Tb=function(b){g.push(b);a.a.w.da(b, 65720function(b){a.a.ua(g,b);g.length||(m.K(),e.I=m=p)})})};a.N.prototype.createChildContext=function(b,c,d){return new a.N(b,this,c,function(a,b){a.$parentContext=b;a.$parent=b.$data;a.$parents=(b.$parents||[]).slice(0);a.$parents.unshift(a.$parent);d&&d(a)})};a.N.prototype.extend=function(b){return new a.N(this.I||this.$data,this,null,function(c,d){c.$rawData=d.$rawData;a.a.extend(c,"function"==typeof b?b():b)})};var q=a.a.e.F(),n=a.a.e.F();a.Ob=function(b,c){if(2==arguments.length)a.a.e.set(b,n,c), 65721c.I&&c.I.Tb(b);else return a.a.e.get(b,n)};a.ra=function(b,c,d){1===b.nodeType&&a.f.Fb(b);return f(b,c,m(d),!0)};a.Wb=function(d,f,e){e=m(e);return a.ra(d,"function"===typeof f?c(f.bind(null,e,d)):a.a.na(f,b),e)};a.Ca=function(a,b){1!==b.nodeType&&8!==b.nodeType||g(m(a),b,!0)};a.pb=function(a,b){!w&&s.jQuery&&(w=s.jQuery);if(b&&1!==b.nodeType&&8!==b.nodeType)throw Error("ko.applyBindings: first parameter should be your view model; second parameter should be a DOM node");b=b||s.document.body;h(m(a), 65722b,!0)};a.Ha=function(b){switch(b.nodeType){case 1:case 8:var c=a.Ob(b);if(c)return c;if(b.parentNode)return a.Ha(b.parentNode)}return p};a.$b=function(b){return(b=a.Ha(b))?b.$data:p};a.b("bindingHandlers",a.d);a.b("applyBindings",a.pb);a.b("applyBindingsToDescendants",a.Ca);a.b("applyBindingAccessorsToNode",a.ra);a.b("applyBindingsToNode",a.Wb);a.b("contextFor",a.Ha);a.b("dataFor",a.$b)})();(function(b){function d(d,f){var e=g.hasOwnProperty(d)?g[d]:b,l;e||(e=g[d]=new a.P,c(d,function(a){h[d]=a;delete g[d]; 65723l?e.notifySubscribers(a):setTimeout(function(){e.notifySubscribers(a)},0)}),l=!0);e.U(f)}function c(a,b){e("getConfig",[a],function(c){c?e("loadComponent",[a,c],function(a){b(a)}):b(null)})}function e(c,d,g,l){l||(l=a.g.loaders.slice(0));var h=l.shift();if(h){var n=h[c];if(n){var t=!1;if(n.apply(h,d.concat(function(a){t?g(null):null!==a?g(a):e(c,d,g,l)}))!==b&&(t=!0,!h.suppressLoaderExceptions))throw Error("Component loaders must supply values by invoking the callback, not by returning values synchronously."); 65724}else e(c,d,g,l)}else g(null)}var g={},h={};a.g={get:function(a,c){var e=h.hasOwnProperty(a)?h[a]:b;e?setTimeout(function(){c(e)},0):d(a,c)},tb:function(a){delete h[a]},jb:e};a.g.loaders=[];a.b("components",a.g);a.b("components.get",a.g.get);a.b("components.clearCachedDefinition",a.g.tb)})();(function(){function b(b,c,d,e){function k(){0===--u&&e(h)}var h={},u=2,r=d.template;d=d.viewModel;r?g(c,r,function(c){a.g.jb("loadTemplate",[b,c],function(a){h.template=a;k()})}):k();d?g(c,d,function(c){a.g.jb("loadViewModel", 65725[b,c],function(a){h[f]=a;k()})}):k()}function d(a,b,c){if("function"===typeof b)c(function(a){return new b(a)});else if("function"===typeof b[f])c(b[f]);else if("instance"in b){var e=b.instance;c(function(){return e})}else"viewModel"in b?d(a,b.viewModel,c):a("Unknown viewModel value: "+b)}function c(b){switch(a.a.t(b)){case "script":return a.a.ba(b.text);case "textarea":return a.a.ba(b.value);case "template":if(e(b.content))return a.a.ia(b.content.childNodes)}return a.a.ia(b.childNodes)}function e(a){return s.DocumentFragment? 65726a instanceof DocumentFragment:a&&11===a.nodeType}function g(a,b,c){"string"===typeof b.require?N||s.require?(N||s.require)([b.require],c):a("Uses require, but no AMD loader is present"):c(b)}function h(a){return function(b){throw Error("Component '"+a+"': "+b);}}var k={};a.g.tc=function(b,c){if(!c)throw Error("Invalid configuration for "+b);if(a.g.Qa(b))throw Error("Component "+b+" is already registered");k[b]=c};a.g.Qa=function(a){return a in k};a.g.wc=function(b){delete k[b];a.g.tb(b)};a.g.ub={getConfig:function(a, 65727b){b(k.hasOwnProperty(a)?k[a]:null)},loadComponent:function(a,c,d){var e=h(a);g(e,c,function(c){b(a,e,c,d)})},loadTemplate:function(b,d,f){b=h(b);if("string"===typeof d)f(a.a.ba(d));else if(d instanceof Array)f(d);
65727else if(e(d))f(a.a.S(d.childNodes));else if(d.element)if(d=d.element,s.HTMLElement?d instanceof HTMLElement:d&&d.tagName&&1===d.nodeType)f(c(d));else if("string"===typeof d){var k=v.getElementById(d);k?f(c(k)):b("Cannot find element with ID "+d)}else b("Unknown element type: "+d);else b("Unknown template value: "+ 65728d)},loadViewModel:function(a,b,c){d(h(a),b,c)}};var f="createViewModel";a.b("components.register",a.g.tc);a.b("components.isRegistered",a.g.Qa);a.b("components.unregister",a.g.wc);a.b("components.defaultLoader",a.g.ub);a.g.loaders.push(a.g.ub);a.g.Ub=k})();(function(){function b(b,e){var g=b.getAttribute("params");if(g){var g=d.parseBindingsString(g,e,b,{valueAccessors:!0,bindingParams:!0}),g=a.a.na(g,function(d){return a.s(d,null,{o:b})}),h=a.a.na(g,function(d){return d.Z()?a.s(function(){return a.a.c(d())}, 65729null,{o:b}):d.v()});h.hasOwnProperty("$raw")||(h.$raw=g);return h}return{$raw:{}}}a.g.getComponentNameForNode=function(b){b=a.a.t(b);return a.g.Qa(b)&&b};a.g.mb=function(c,d,g,h){if(1===d.nodeType){var k=a.g.getComponentNameForNode(d);if(k){c=c||{};if(c.component)throw Error('Cannot use the "component" binding on a custom element matching a component');var f={name:k,params:b(d,g)};c.component=h?function(){return f}:f}}return c};var d=new a.J;9>a.a.L&&(a.g.register=function(a){return function(b){v.createElement(b); 65730return a.apply(this,arguments)}}(a.g.register),v.createDocumentFragment=function(b){return function(){var d=b(),g=a.g.Ub,h;for(h in g)g.hasOwnProperty(h)&&d.createElement(h);return d}}(v.createDocumentFragment))})();(function(){var b=0;a.d.component={init:function(d,c,e,g,h){function k(){var a=f&&f.dispose;"function"===typeof a&&a.call(f);m=null}var f,m;a.a.w.da(d,k);a.s(function(){var e=a.a.c(c()),g,n;"string"===typeof e?g=e:(g=a.a.c(e.name),n=a.a.c(e.params));if(!g)throw Error("No component name specified"); 65731var t=m=++b;a.g.get(g,function(b){if(m===t){k();if(!b)throw Error("Unknown component '"+g+"'");var c=b.template;if(!c)throw Error("Component '"+g+"' has no template");c=a.a.ia(c);a.f.T(d,c);var c=n,e=b.createViewModel;b=e?e.call(b,c,{element:d}):c;c=h.createChildContext(b);f=b;a.Ca(c,d)}})},null,{o:d});return{controlsDescendantBindings:!0}}};a.f.Q.component=!0})();var Q={"class":"className","for":"htmlFor"};a.d.attr={update:function(b,d){var c=a.a.c(d())||{};a.a.G(c,function(c,d){d=a.a.c(d);var h= 65732!1===d||null===d||d===p;h&&b.removeAttribute(c);8>=a.a.L&&c in Q?(c=Q[c],h?b.removeAttribute(c):b[c]=d):h||b.setAttribute(c,d.toString());"name"===c&&a.a.Mb(b,h?"":d.toString())})}};(function(){a.d.checked={after:["value","attr"],init:function(b,d,c){function e(){var e=b.checked,k=q?h():e;if(!a.Y.ma()&&(!f||e)){var g=a.k.B(d);m?l!==k?(e&&(a.a.ea(g,k,!0),a.a.ea(g,l,!1)),l=k):a.a.ea(g,k,e):a.h.pa(g,c,"checked",k,!0)}}function g(){var c=a.a.c(d());b.checked=m?0<=a.a.m(c,h()):k?c:h()===c}var h=a.Ib(function(){return c.has("checkedValue")? 65733a.a.c(c.get("checkedValue")):c.has("value")?a.a.c(c.get("value")):b.value}),k="checkbox"==b.type,f="radio"==b.type;if(k||f){var m=k&&a.a.c(d())instanceof Array,l=m?h():p,q=f||m;f&&!b.name&&a.d.uniqueName.init(b,function(){return!0});a.s(e,null,{o:b});a.a.n(b,"click",e);a.s(g,null,{o:b})}}};a.h.V.checked=!0;a.d.checkedValue={update:function(b,d){b.value=a.a.c(d())}}})();a.d.css={update:function(b,d){var c=a.a.c(d());"object"==typeof c?a.a.G(c,function(c,d){d=a.a.c(d);a.a.Ba(b,c,d)}):(c=String(c||""), 65734a.a.Ba(b,b.__ko__cssValue,!1),b.__ko__cssValue=c,a.a.Ba(b,c,!0))}};a.d.enable={update:function(b,d){var c=a.a.c(d());c&&b.disabled?b.removeAttribute("disabled"):c||b.disabled||(b.disabled=!0)}};a.d.disable={update:function(b,d){a.d.enable.update(b,function(){return!a.a.c(d())})}};a.d.event={init:function(b,d,c,e,g){var h=d()||{};a.a.G(h,function(k){"string"==typeof k&&a.a.n(b,k,function(b){var h,l=d()[k];if(l){try{var q=a.a.S(arguments);e=g.$data;q.unshift(e);h=l.apply(e,q)}finally{!0!==h&&(b.preventDefault? 65735b.preventDefault():b.returnValue=!1)}!1===c.get(k+"Bubble")&&(b.cancelBubble=!0,b.stopPropagation&&b.stopPropagation())}})})}};a.d.foreach={Eb:function(b){return function(){var d=b(),c=a.a.Xa(d);if(!c||"number"==typeof c.length)return{foreach:d,templateEngine:a.O.Oa};a.a.c(d);return{foreach:c.data,as:c.as,includeDestroyed:c.includeDestroyed,afterAdd:c.afterAdd,beforeRemove:c.beforeRemove,afterRe
vendor: 13,701 bytes, lines 65735-65762
65735nder:c.afterRender,beforeMove:c.beforeMove,afterMove:c.afterMove,templateEngine:a.O.Oa}}},init:function(b, 65736d){return a.d.template.init(b,a.d.foreach.Eb(d))},update:function(b,d,c,e,g){return a.d.template.update(b,a.d.foreach.Eb(d),c,e,g)}};a.h.ha.foreach=!1;a.f.Q.foreach=!0;a.d.hasfocus={init:function(b,d,c){function e(e){b.__ko_hasfocusUpdating=!0;var f=b.ownerDocument;if("activeElement"in f){var g;try{g=f.activeElement}catch(h){g=f.body}e=g===b}f=d();a.h.pa(f,c,"hasfocus",e,!0);b.__ko_hasfocusLastValue=e;b.__ko_hasfocusUpdating=!1}var g=e.bind(null,!0),h=e.bind(null,!1);a.a.n(b,"focus",g);a.a.n(b,"focusin", 65737g);a.a.n(b,"blur",h);a.a.n(b,"focusout",h)},update:function(b,d){var c=!!a.a.c(d());b.__ko_hasfocusUpdating||b.__ko_hasfocusLastValue===c||(c?b.focus():b.blur(),a.k.B(a.a.oa,null,[b,c?"focusin":"focusout"]))}};a.h.V.hasfocus=!0;a.d.hasFocus=a.d.hasfocus;a.h.V.hasFocus=!0;a.d.html={init:function(){return{controlsDescendantBindings:!0}},update:function(b,d){a.a.$a(b,d())}};I("if");I("ifnot",!1,!0);I("with",!0,!1,function(a,d){return a.createChildContext(d)});var K={};a.d.options={init:function(b){if("select"!== 65738a.a.t(b))throw Error("options binding applies only to SELECT elements");for(;0<b.length;)b.remove(0);return{controlsDescendantBindings:!0}},update:function(b,d,c){function e(){return a.a.ta(b.options,function(a){return a.selected})}function g(a,b,c){var d=typeof b;return"function"==d?b(a):"string"==d?a[b]:c}function h(c,d){if(q.length){var e=0<=a.a.m(q,a.i.q(d[0]));a.a.Nb(d[0],e);n&&!e&&a.k.B(a.a.oa,null,[b,"change"])}}var k=0!=b.length&&b.multiple?b.scrollTop:null,f=a.a.c(d()),m=c.get("optionsIncludeDestroyed"); 65739d={};var l,q;q=b.multiple?a.a.Da(e(),a.i.q):0<=b.selectedIndex?[a.i.q(b.options[b.selectedIndex])]:[];f&&("undefined"==typeof f.length&&(f=[f]),l=a.a.ta(f,function(b){return m||b===p||null===b||!a.a.c(b._destroy)}),c.has("optionsCaption")&&(f=a.a.c(c.get("optionsCaption")),null!==f&&f!==p&&l.unshift(K)));var n=!1;d.beforeRemove=function(a){b.removeChild(a)};f=h;c.has("optionsAfterRender")&&(f=function(b,d){h(0,d);a.k.B(c.get("optionsAfterRender"),null,[d[0],b!==K?b:p])});a.a.Za(b,l,function(d,e,f){f.length&& 65740(q=f[0].selected?[a.i.q(f[0])]:[],n=!0);e=b.ownerDocument.createElement("option");d===K?(a.a.bb(e,c.get("optionsCaption")),a.i.ca(e,p)):(f=g(d,c.get("optionsValue"),d),a.i.ca(e,a.a.c(f)),d=g(d,c.get("optionsText"),f),a.a.bb(e,d));return[e]},d,f);a.k.B(function(){c.get("valueAllowUnset")&&c.has("value")?a.i.ca(b,a.a.c(c.get("value")),!0):(b.multiple?q.length&&e().length<q.length:q.length&&0<=b.selectedIndex?a.i.q(b.options[b.selectedIndex])!==q[0]:q.length||0<=b.selectedIndex)&&a.a.oa(b,"change")}); 65741a.a.dc(b);k&&20<Math.abs(k-b.scrollTop)&&(b.scrollTop=k)}};a.d.options.Va=a.a.e.F();a.d.selectedOptions={after:["options","foreach"],init:function(b,d,c){a.a.n(b,"change",function(){var e=d(),g=[];a.a.u(b.getElementsByTagName("option"),function(b){b.selected&&g.push(a.i.q(b))});a.h.pa(e,c,"selectedOptions",g)})},update:function(b,d){if("select"!=a.a.t(b))throw Error("values binding applies only to SELECT elements");var c=a.a.c(d());c&&"number"==typeof c.length&&a.a.u(b.getElementsByTagName("option"), 65742function(b){var d=0<=a.a.m(c,a.i.q(b));a.a.Nb(b,d)})}};a.h.V.selectedOptions=!0;a.d.style={update:function(b,d){var c=a.a.c(d()||{});a.a.G(c,function(c,d){d=a.a.c(d);if(null===d||d===p||!1===d)d="";b.style[c]=d})}};a.d.submit={init:function(b,d,c,e,g){if("function"!=typeof d())throw Error("The value for a submit binding must be a function");a.a.n(b,"submit",function(a){var c,e=d();try{c=e.call(g.$data,b)}finally{!0!==c&&(a.preventDefault?a.preventDefault():a.returnValue=!1)}})}};a.d.text={init:function(){return{controlsDescendantBindings:!0}}, 65743update:function(b,d){a.a.bb(b,d())}};a.f.Q.text=!0;(function(){if(s&&s.navigator)var b=function(a){if(a)return parseFloat(a[1])},d=s.opera&&s.opera.version&&parseInt(s.opera.version()),c=s.navigator.userAgent,e=b(c.match(/^(?:(?!chrome).)*version\/([^ ]*) safari/i)),g=b(c.match(/Firefox\/([^ ]*)/));if(10>a.a.L)var h=a.a.e.F(),k=a.a.e.F(),f=function(b){var c=this.activeElement;(c=c&&a.a.e.get(c,k))&&c(b)},m=function(b,c){var d=b.ownerDocument;a.a.e.get(d,h)||(a.a.e.set(d,h,!0),a.a.n(d,"selectionchange", 65744f));a.a.e.set(b,k,c)};a.d.textInput={init:function(b,c,f){function k(c,d){a.a.n(b,c,d)}function h(){var d=a.a.c(c());if(null===d||d===p)d="";v!==p&&d===v?setTimeout(h,4):b.value!==d&&(s=d,b.value=d)}function u(){y||(v=b.value,y=setTimeout(r,4))}function r(){clearTimeout(y);v=y=p;var d=b.value;s!==d&&(s=d,a.h.pa(c(),f,"textInput",d))}var s=b.value,y,v;10>a.a.L?(k("propertychange",function(a){"value"===a.propertyName&&r()}),8==a.a.L&&(k("keyup",r),k("keydown",r)),8<=a.a.L&&(m(b,r),k("dragend",u))): 65745(k("input",r),5>e&&"textarea"===a.a.t(b)?(k("keydown",u),k("paste",u),k("cut",u)):11>d?k("keydown",u):4>g&&(k("DOMAutoComplete",r),k("dragdrop",r),k("drop",r)));k("change",r);a.s(h,null,{o:b})}};a.h.V.textInput=!0;a.d.textinput={preprocess:function(a,b,c){c("textInput",a)}}})();a.d.uniqueName={init:function(b,d){if(d()){var c="ko_unique_"+ ++a.d.uniqueName.Zb;a.a.Mb(b,c)}}};a.d.uniqueName.Zb=0;a.d.value={after:["options","foreach"],init:function(b,d,c){if("input"!=b.tagName.toLowerCase()||"checkbox"!= 65746b.type&&"radio"!=b.type){var e=["change"],g=c.get("valueUpdate"),h=!1,k=null;g&&("string"==typeof g&&(g=[g]),a.a.ga(e,g),e=a.a.rb(e));var f=function(){k=null;h=!1;var e=d(),f=a.i.q(b);a.h.pa(e,c,"value",f)};!a.a.L||"input"!=b.tagName.toLowerCase()||"text"!=b.type||"off"==b.autocomplete||b.form&&"off"==b.form.autocomplete||-1!=a.a.m(e,"propertychange")||(a.a.n(b,"propertychange",function(){h=!0}),a.a.n(b,"focus",function(){h=!1}),a.a.n(b,"blur",function(){h&&f()}));a.a.u(e,function(c){var d=f;a.a.vc(c, 65747"after")&&(d=function(){k=a.i.q(b);setTimeout(f,0)},c=c.substring(5));a.a.n(b,c,d)});var m=function(){var e=a.a.c(d()),f=a.i.q(b);if(null!==k&&e===k)setTimeout(m,0);else if(e!==f)if("select"===a.a.t(b)){var g=c.get("valueAllowUnset"),f=function(){a.i.ca(b,e,g)};f();g||e===a.i.q(b)?setTimeout(f,0):a.k.B(a.a.oa,null,[b,"change"])}else a.i.ca(b,e)};a.s(m,null,{o:b})}else a.ra(b,{checkedValue:d})},update:function(){}};a.h.V.value=!0;a.d.visible={update:function(b,d){var c=a.a.c(d()),e="none"!=b.style.display; 65748c&&!e?b.style.display="":!c&&e&&(b.style.display="none")}};(function(b){a.d[b]={init:function(d,c,e,g,h){return a.d.event.init.call(this,d,function(){var a={};a[b]=c();return a},e,g,h)}}})("click");a.H=function(){};a.H.prototype.renderTemplateSource=function(){throw Error("Override renderTemplateSource");};a.H.prototype.createJavaScriptEvaluatorBlock=function(){throw Error("Override createJavaScriptEvaluatorBlock");};a.H.prototype.makeTemplateSource=function(b,d){if("string"==typeof b){d=d||v;var c= 65749d.getElementById(b);if(!c)throw Error("Cannot find template with ID "+b);return new a.r.l(c)}if(1==b.nodeType||8==b.nodeType)return new a.r.fa(b);throw Error("Unknown template type: "+b);};a.H.prototype.renderTemplate=function(a,d,c,e){a=this.makeTemplateSource(a,e);return this.renderTemplateSource(a,d,c)};a.H.prototype.isTemplateRewritten=function(a,d){return!1===this.allowTemplateRewriting?!0:this.makeTemplateSource(a,d).data("isRewritten")};a.H.prototype.rewriteTemplate=function(a,d,c){a=this.makeTemplateSource(a, 65750c);d=d(a.text());a.text(d);a.data("isRewritten",!0)};a.b("templateEngine",a.H);a.fb=function(){function b(b,c,d,k){b=a.h.Wa(b);for(var f=a.h.ha,m=0;m<b.length;m++){var l=b[m].key;if(f.hasOwnProperty(l)){var q=f[l];if("function"===typeof q){if(l=q(b[m].value))throw Error(l);}else if(!q)throw Error("This template engine does not support the '"+l+"' binding within its templates");}}d="ko.__tr_ambtns(function($context,$element){return(function(){return{ "+a.h.ya(b,{valueAccessors:!0})+" } })()},'"+d.toLowerCase()+ 65751"')";return k.createJavaScriptEvaluatorBlock(d)+c}var d=/(<([a-z]+\d*)(?:\s+(?!data-bind\s*=\s*)[a-z0-9\-]+(?:=(?:\"[^\"]*\"|\'[^\']*\'))?)*\s+)data-bind\s*=\s*(["'])([\s\S]*?)\3/gi,c=/\x3c!--\s*ko\b\s*([\s\S]*?)\s*--\x3e/g;return{ec:function(b,c,d){c.isTemplateRewritten(b,d)||c.rewriteTemplate(b,function(b){return a.fb.nc(b,c)},d)},nc:function(a,g){return a.replace(d,function(a,c,d,e,l){return b(l,c,d,g)}).replace(c,function(a,c){return b(c,"\x3c!-- ko --\x3e","#comment",g)})},Xb:function(b,c){return a.D.Ua(function(d, 65752k){var f=d.nextSibling;f&&f.nodeName.toLowerCase()===c&&a.ra(f,b,k)})}}}();a.b("__tr_ambtns",a.fb.Xb);(function(){a.r={};a.r.l=function(a){this.l=a};a.r.l.prototype.text=function(){var b=a.a.t(this.l),b="script"===b?"text":"textarea"===b?"value":"innerHTML";if(0==arguments.length)return this.l[b];var d=arguments[0];"innerHTML"===b?a.a.$a(this.l,d):this.l[b]=d};var b=a.a.e.F()+"_";a.r.l.prototype.data=function(c){if(1===arguments.length)return a.a.e.get(this.l,b+c);a.a.e.set(this.l,b+c,arguments[1])}; 65753var d=a.a.e.F();a.r.fa=function(a){this.l=a};a.r.fa.prototype=new a.r.l;a.r.fa.prototype.text=function(){if(0==arguments.length){var b=a.a.e.get(this.l,d)||{};b.gb===p&&b.Ga&&(b.gb=b.Ga.innerHTML);return b.gb}a.a.e.set(this.l,d,{gb:arguments[0]})};a.r.l.prototype.nodes=function(){if(0==arguments.length)return(a.a.e.get(this.l,d)||{}).Ga;a.a.e.set(this.l,d,{Ga:arguments[0]})};a.b("templateSources",a.r);a.b("templateSources.domElement",a.r.l);a.b("templateSources.anonymousTemplate",a.r.fa)})();(function(){function b(b, 65754c,d){var e;for(c=a.f.nextSibling(c);b&&(e=b)!==c;)b=a.f.nextSibling(e),d(e,b)}function d(c,d){if(c.length){var e=c[0],g=c[c.length-1],h=e.parentNode,n=a.J.instance,t=n.preprocessNode;if(t){b(e,g,function(a,b){var c=a.previousSibling,d=t.call(n,a);d&&(a===e&&(e=d[0]||b),a===g&&(g=d[d.length-1]||c))});c.length=0;if(!e)return;e===g?c.push(e):(c.push(e,g),a.a.ka(c,h))}b(e,g,function(b){1!==b.nodeType&&8!==b.nodeType||a.pb(d,b)});b(e,g,function(b){1!==b.nodeType&&8!==b.nodeType||a.D.Sb(b,[d])});a.a.ka(c, 65755h)}}function c(a){return a.nodeType?a:0<a.length?a[0]:null}function e(b,e,h,l,q){q=q||{};var n=b&&c(b),n=n&&n.ownerDocument,t=q.templateEngine||g;a.fb.ec(h,t,n);h=t.renderTemplate(h,l,q,n);if("number"!=typeof h.length||0<h.length&&"number"!=typeof h[0].nodeType)throw Error("Template engine must return an array of DOM nodes");n=!1;switch(e){case "replaceChildren":a.f.T(b,h);n=!0;break;case "replaceNode":a.a.Lb(b,h);n=!0;break;case "ignoreTargetNode":break;default:throw Error("Unknown renderMode: "+ 65756e);}n&&(d(h,l),q.afterRender&&a.k.B(q.afterRender,null,[h,l.$data]));return h}var g;a.ab=function(b){if(b!=p&&!(b instanceof a.H))throw Error("templateEngine must inherit from ko.templateEngine");g=b};a.Ya=function(b,d,h,l,q){h=h||{};if((h.templateEngine||g)==p)throw Error("Set a template engine before calling renderTemplate");q=q||"replaceChildren";if(l){var n=c(l);return a.j(function(){var g=d&&d instanceof a.N?d:new a.N(a.a.c(d)),p=a.C(b)?b():"function"===typeof b?b(g.$data,g):b,g=e(l,q,p,g,h); 65757"replaceNode"==q&&(l=g,n=c(l))},null,{Ia:function(){return!n||!a.a.Ja(n)},o:n&&"replaceNode"==q?n.parentNode:n})}return a.D.Ua(function(c){a.Ya(b,d,h,c,"replaceNode")})};a.uc=function(b,c,g,h,q){function n(a,b){d(b,s);g.afterRender&&g.afterRender(b,a)}function t(c,d){s=q.createChildContext(c,g.as,function(a){a.$index=d});var f=a.C(b)?b():"function"===typeof b?b(c,s):b;return e(null,"ignoreTargetNode",f,s,g)}var s;return a.j(function(){var b=a.a.c(c)||[];"undefined"==typeof b.length&&(b=[b]);b=a.a.ta(b, 65758function(b){return g.includeDestroyed||b===p||null===b||!a.a.c(b._destroy)});a.k.B(a.a.Za,null,[h,b,t,g,n])},null,{o:h})};var h=a.a.e.F();a.d.template={init:function(b,c){var d=a.a.c(c());"string"==typeof d||d.name?a.f.ja(b):(d=a.f.childNodes(b),d=a.a.oc(d),(new a.r.fa(b)).nodes(d));return{controlsDescendantBindings:!0}},update:function(b,c,d,e,g){var n=c(),t;c=a.a.c(n);d=!0;e=null;"string"==typeof c?c={}:(n=c.name,"if"in c&&(d=a.a.c(c["if"])),d&&"ifnot"in c&&(d=!a.a.c(c.ifnot)),t=a.a.c(c.data)); 65759"foreach"in c?e=a.uc(n||b,d&&c.foreach||[],c,b,g):d?(g="data"in c?g.createChildContext(t,c.as):g,e=a.Ya(n||b,g,c,b)):a.f.ja(b);g=e;(t=a.a.e.get(b,h))&&"function"==typeof t.K&&t.K();a.a.e.set(b,h,g&&g.Z()?g:p)}};a.h.ha.template=function(b){b=a.h.Wa(b);return 1==b.length&&b[0].unknown||a.h.lc(b,"name")?null:"This template engine does not support anonymous templates nested within its templates"};a.f.Q.template=!0})();a.b("setTemplateEngine",a.ab);a.b("renderTemplate",a.Ya);a.a.wb=function(a,d,c){if(a.length&& 65760d.length){var e,g,h,k,f;for(e=g=0;(!c||e<c)&&(k=a[g]);++g){for(h=0;f=d[h];++h)if(k.value===f.value){k.moved=f.index;f.moved=k.index;d.splice(h,1);e=h=0;break}e+=h}}};a.a.Fa=function(){function b(b,c,e,g,h){var k=Math.min,f=Math.max,m=[],l,q=b.length,n,p=c.length,s=p-q||1,u=q+p+1,r,v,w;for(l=0;l<=q;l++)for(v=r,m.push(r=[]),w=k(p,l+s),n=f(0,l-1);n<=w;n++)r[n]=n?l?b[l-1]===c[n-1]?v[n-1]:k(v[n]||u,r[n-1]||u)+1:n+1:l+1;k=[];f=[];s=[];l=q;for(n=p;l||n;)p=m[l][n]-1,n&&p===m[l][n-1]?f.push(k[k.length]={status:e, 65761value:c[--n],index:n}):l&&p===m[l-1][n]?s.push(k[k.length]={status:g,value:b[--l],index:l}):(--n,--l,h.sparse||k.push({status:"retained",value:c[n]}));a.a.wb(f,s,10*q);return k.reverse()}return function(a,c,e){e="boolean"===typeof e?{dontLimitMoves:e}:e||{};a=a||[];c=c||[];return a.length<=c.length?b(a,c,"added","deleted",e):b(c,a,"deleted","added",e)}}();a.b("utils.compareArrays",a.a.Fa);(function(){function b(b,d,g,h,k){var f=[],m=a.j(function(){var l=d(g,k,a.a.ka(f,b))||[];0<f.length&&(a.a.Lb(f, 65762l),h&&a.k.B(h,null,[g,l,k]));f.length=0;a.a.ga(f,l)},null,{o:b,Ia:function(){return!a.a.ob(f)}});return{$:f,j:m.Z()?m:p}}var d=a.a.e.F();a.a.Za=function(c,e,g,h,k){function f(b,d){x=q[d];r!==d&&(A[b]=x);x.Na(r++);a.a.ka(x.$,c);s.push(x);w.push(x)}function m(b,c){if(b)for(var d=0,e=c.length;d<e;
vendor: 2,888 bytes, lines 65762-65785
65762d++)c[d]&&a.a.u(c[d].$,function(a){b(a,d,c[d].sa)})}e=e||[];h=h||{};var l=a.a.e.get(c,d)===p,q=a.a.e.get(c,d)||[],n=a.a.Da(q,function(a){return a.sa}),t=a.a.Fa(n,e,h.dontLimitMoves),s=[],u=0,r=0,v=[],w=[];e= 65763[];for(var A=[],n=[],x,B=0,D,F;D=t[B];B++)switch(F=D.moved,D.status){case "deleted":F===p&&(x=q[u],x.j&&x.j.K(),v.push.apply(v,a.a.ka(x.$,c)),h.beforeRemove&&(e[B]=x,w.push(x)));u++;break;case "retained":f(B,u++);break;case "added":F!==p?f(B,F):(x={sa:D.value,Na:a.p(r++)},s.push(x),w.push(x),l||(n[B]=x))}m(h.beforeMove,A);a.a.u(v,h.beforeRemove?a.R:a.removeNode);for(var B=0,l=a.f.firstChild(c),G;x=w[B];B++){x.$||a.a.extend(x,b(c,g,x.sa,k,x.Na));for(u=0;t=x.$[u];l=t.nextSibling,G=t,u++)t!==l&&a.f.Bb(c, 65764t,G);!x.ic&&k&&(k(x.sa,x.$,x.Na),x.ic=!0)}m(h.beforeRemove,e);m(h.afterMove,A);m(h.afterAdd,n);a.a.e.set(c,d,s)}})();a.b("utils.setDomNodeChildrenFromArrayMapping",a.a.Za);a.O=function(){this.allowTemplateRewriting=!1};a.O.prototype=new a.H;a.O.prototype.renderTemplateSource=function(b){var d=(9>a.a.L?0:b.nodes)?b.nodes():null;if(d)return a.a.S(d.cloneNode(!0).childNodes);b=b.text();return a.a.ba(b)};a.O.Oa=new a.O;a.ab(a.O.Oa);a.b("nativeTemplateEngine",a.O);(function(){a.Sa=function(){var a=this.kc= 65765function(){if(!w||!w.tmpl)return 0;try{if(0<=w.tmpl.tag.tmpl.open.toString().indexOf("__"))return 2}catch(a){}return 1}();this.renderTemplateSource=function(b,e,g){g=g||{};if(2>a)throw Error("Your version of jQuery.tmpl is too old. Please upgrade to jQuery.tmpl 1.0.0pre or later.");var h=b.data("precompiled");h||(h=b.text()||"",h=w.template(null,"{{ko_with $item.koBindingContext}}"+h+"{{/ko_with}}"),b.data("precompiled",h));b=[e.$data];e=w.extend({koBindingContext:e},g.templateOptions);e=w.tmpl(h, 65766b,e);e.appendTo(v.createElement("div"));w.fragments={};return e};this.createJavaScriptEvaluatorBlock=function(a){return"{{ko_code ((function() { return "+a+" })()) }}"};this.addTemplate=function(a,b){v.write("<script type='text/html' id='"+a+"'>"+b+"\x3c/script>")};0<a&&(w.tmpl.tag.ko_code={open:"__.push($1 || '');"},w.tmpl.tag.ko_with={open:"with($1) {",close:"} "})};a.Sa.prototype=new a.H;var b=new a.Sa;0<b.kc&&a.ab(b);a.b("jqueryTmplTemplateEngine",a.Sa)})()})})();})(); 65767 65768/*! 65769 * Knockout Mapping plugin v2.6.0 65770 * (c) 2013 Steven Sanderson, Roy Jacobs - http://knockoutjs.com/ 65771 * License: MIT (http://www.opensource.org/licenses/mit-license.php) 65772 */ 65773(function(factory) { 65774 'use strict'; 65775 65776 /*jshint sub:true,curly:false*/ 65777 /*global ko,require,exports,define,module*/ 65778 65779 if (typeof require === "function" && typeof exports === "object" && typeof module === "object") { 65780 // CommonJS or Node: hard-coded dependency on "knockout" 65781 factory(require("knockout"), exports); 65782 } 65783 else if (typeof define === "function" && define["amd"]) { 65784 // AMD anonymous module with hard-coded dependency on "knockout" 65785 define('komapping',
vendor: 34,206 bytes, lines 65785-66641
65785["knockout", "exports"], factory); 65786 } 65787 else { 65788 // <script> tag: use the global `ko` object, attaching a `mapping` property 65789 if (typeof ko === 'undefined') { 65790 throw new Error('Knockout is required, please ensure it is loaded before loading this mapping plug-in'); 65791 } 65792 factory(ko, ko.mapping = {}); 65793 } 65794}(function(ko, exports) { 65795 /*jshint sub:true,curly:false*/ 65796 'use strict'; 65797 65798 ko.mapping = exports; 65799 65800 var DEBUG=true; 65801 var mappingProperty = "__ko_mapping__"; 65802 var realKoDependentObservable = ko.dependentObservable; 65803 var mappingNesting = 0; 65804 var dependentObservables; 65805 var visitedObjects; 65806 var recognizedRootProperties = ["create", "update", "key", "arrayChanged"]; 65807 var emptyReturn = {}; 65808 65809 var _defaultOptions = { 65810 include: ["_destroy"], 65811 ignore: [], 65812 copy: [], 65813 observe: [] 65814 }; 65815 var defaultOptions = _defaultOptions; 65816 65817 function unionArrays() { 65818 var args = arguments, 65819 l = args.length, 65820 obj = {}, 65821 res = [], 65822 i, j, k; 65823 65824 while (l--) { 65825 k = args[l]; 65826 i = k.length; 65827 65828 while (i--) { 65829 j = k[i]; 65830 if (!obj[j]) { 65831 obj[j] = 1; 65832 res.push(j); 65833 } 65834 } 65835 } 65836 65837 return res; 65838 } 65839 65840 function extendObject(destination, source) { 65841 var destType; 65842 65843 for (var key in source) { 65844 if (source.hasOwnProperty(key) && source[key]) { 65845 destType = exports.getType(destination[key]); 65846 if (key && destination[key] && destType !== "array" && destType !== "string") { 65847 extendObject(destination[key], source[key]); 65848 } 65849 else { 65850 var bothArrays = exports.getType(destination[key]) === "array" && exports.getType(source[key]) === "array"; 65851 if (bothArrays) { 65852 destination[key] = unionArrays(destination[key], source[key]); 65853 } 65854 else { 65855 destination[key] = source[key]; 65856 } 65857 } 65858 } 65859 } 65860 } 65861 65862 function merge(obj1, obj2) { 65863 var merged = {}; 65864 extendObject(merged, obj1); 65865 extendObject(merged, obj2); 65866 65867 return merged; 65868 } 65869 65870 exports.isMapped = function(viewModel) { 65871 var unwrapped = ko.utils.unwrapObservable(viewModel); 65872 return unwrapped && unwrapped[mappingProperty]; 65873 }; 65874 65875 exports.fromJS = function(jsObject /*, inputOptions, target*/) { 65876 if (arguments.length === 0) { 65877 throw new Error("When calling ko.fromJS, pass the object you want to convert."); 65878 } 65879 try { 65880 if (!mappingNesting) { 65881 dependentObservables = []; 65882 visitedObjects = new ObjectLookup(); 65883 } 65884 mappingNesting++; 65885 65886 var options; 65887 var target; 65888 65889 if (arguments.length === 2) { 65890 if (arguments[1][mappingProperty]) { 65891 target = arguments[1]; 65892 } 65893 else { 65894 options = arguments[1]; 65895 } 65896 } 65897 if (arguments.length === 3) { 65898 options = arguments[1]; 65899 target = arguments[2]; 65900 } 65901 65902 if (target) { 65903 options = merge(options, target[mappingProperty]); 65904 } 65905 options = fillOptions(options); 65906 65907 var result = updateViewModel(target, jsObject, options); 65908 if (target) { 65909 result = target; 65910 } 65911 65912 // Evaluate any dependent observables that were proxied. 65913 // Do this after the model's observables have been created 65914 if (!--mappingNesting) { 65915 while (dependentObservables.length) { 65916 var DO = dependentObservables.pop(); 65917 if (DO) { 65918 DO(); 65919 // Move this magic property to the underlying dependent observable 65920 DO.__DO["throttleEvaluation"] = DO["throttleEvaluation"]; 65921 } 65922 } 65923 } 65924 65925 // Save any new mapping options in the view model, so that updateFromJS can use them later. 65926 result[mappingProperty] = merge(result[mappingProperty], options); 65927 65928 return result; 65929 } 65930 catch (e) { 65931 mappingNesting = 0; 65932 throw e; 65933 } 65934 }; 65935 65936 exports.fromJSON = function(jsonString /*, options, target*/) { 65937 var args = Array.prototype.slice.call(arguments, 0); 65938 args[0] = ko.utils.parseJson(jsonString); 65939 return exports.fromJS.apply(this, args); 65940 }; 65941 65942 exports.toJS = function(rootObject, options) { 65943 if (!defaultOptions) exports.resetDefaultOptions(); 65944 65945 if (arguments.length === 0) throw new Error("When calling ko.mapping.toJS, pass the object you want to convert."); 65946 if (exports.getType(defaultOptions.ignore) !== "array") throw new Error("ko.mapping.defaultOptions().ignore should be an array."); 65947 if (exports.getType(defaultOptions.include) !== "array") throw new Error("ko.mapping.defaultOptions().include should be an array."); 65948 if (exports.getType(defaultOptions.copy) !== "array") throw new Error("ko.mapping.defaultOptions().copy should be an array."); 65949 65950 // Merge in the options used in fromJS 65951 options = fillOptions(options, rootObject[mappingProperty]); 65952 65953 // We just unwrap everything at every level in the object graph 65954 return exports.visitModel(rootObject, function(x) { 65955 return ko.utils.unwrapObservable(x); 65956 }, options); 65957 }; 65958 65959 exports.toJSON = function(rootObject, options, replacer, space) { 65960 var plainJavaScriptObject = exports.toJS(rootObject, options); 65961 return ko.utils.stringifyJson(plainJavaScriptObject, replacer, space); 65962 }; 65963 65964 exports.defaultOptions = function() { 65965 if (arguments.length > 0) { 65966 defaultOptions = arguments[0]; 65967 } 65968 else { 65969 return defaultOptions; 65970 } 65971 }; 65972 65973 exports.resetDefaultOptions = function() { 65974 defaultOptions = { 65975 include: _defaultOptions.include.slice(0), 65976 ignore: _defaultOptions.ignore.slice(0), 65977 copy: _defaultOptions.copy.slice(0), 65978 observe: _defaultOptions.observe.slice(0) 65979 }; 65980 }; 65981 65982 exports.getType = function(x) { 65983 if ((x) && (typeof (x) === "object")) { 65984 if (x.constructor === Date) return "date"; 65985 if (x.constructor === Array) return "array"; 65986 } 65987 return typeof x; 65988 }; 65989 65990 function fillOptions(rawOptions, otherOptions) { 65991 var options = merge({}, rawOptions); 65992 65993 // Move recognized root-level properties into a root namespace 65994 for (var i = recognizedRootProperties.length - 1; i >= 0; i--) { 65995 var property = recognizedRootProperties[i]; 65996 65997 // Carry on, unless this property is present 65998 if (!options[property]) continue; 65999 66000 // Move the property into the root namespace 66001 if (!(options[""] instanceof Object)) options[""] = {}; 66002 options[""][property] = options[property]; 66003 delete options[property]; 66004 } 66005 66006 if (otherOptions) { 66007 options.ignore = mergeArrays(otherOptions.ignore, options.ignore); 66008 options.include = mergeArrays(otherOptions.include, options.include); 66009 options.copy = mergeArrays(otherOptions.copy, options.copy); 66010 options.observe = mergeArrays(otherOptions.observe, options.observe); 66011 } 66012 options.ignore = mergeArrays(options.ignore, defaultOptions.ignore); 66013 options.include = mergeArrays(options.include, defaultOptions.include); 66014 options.copy = mergeArrays(options.copy, defaultOptions.copy); 66015 options.observe = mergeArrays(options.observe, defaultOptions.observe); 66016 66017 options.mappedProperties = options.mappedProperties || {}; 66018 options.copiedProperties = options.copiedProperties || {}; 66019 return options; 66020 } 66021 66022 function mergeArrays(a, b) { 66023 if (a === undefined) { 66024 a = []; 66025 } 66026 else if (exports.getType(a) !== "array") { 66027 a = [a]; 66028 } 66029 66030 if (b === undefined) { 66031 b = []; 66032 } 66033 else if (exports.getType(b) !== "array") { 66034 b = [b]; 66035 } 66036 66037 return ko.utils.arrayGetDistinctValues(a.concat(b)); 66038 } 66039 66040 // When using a 'create' callback, we proxy the dependent observable so that it doesn't immediately evaluate on creation. 66041 // The reason is that the dependent observables in the user-specified callback may contain references to properties that have not been mapped yet. 66042 function withProxyDependentObservable(dependentObservables, callback) { 66043 var localDO = ko.dependentObservable; 66044 ko.dependentObservable = function(read, owner, options) { 66045 options = options || {}; 66046 66047 if (read && typeof read === "object") { // mirrors condition in knockout implementation of DO's 66048 options = read; 66049 } 66050 66051 var realDeferEvaluation = options.deferEvaluation; 66052 var realIsPure = options.pure; 66053 66054 var isRemoved = false; 66055 66056 // We wrap the original dependent observable so that we can remove it from the 'dependentObservables' list we need to evaluate after mapping has 66057 // completed if the user already evaluated the DO themselves in the meantime. 66058 var wrap = function(DO) { 66059 // Temporarily revert ko.dependentObservable, since it is used in ko.isWriteableObservable 66060 var tmp = ko.dependentObservable; 66061 ko.dependentObservable = realKoDependentObservable; 66062 var isWriteable = ko.isWriteableObservable(DO); 66063 ko.dependentObservable = tmp; 66064 66065 var wrapped = realKoDependentObservable({ 66066 read: function() { 66067 if (!isRemoved) { 66068 ko.utils.arrayRemoveItem(dependentObservables, DO); 66069 isRemoved = true; 66070 } 66071 return DO.apply(DO, arguments); 66072 }, 66073 write: isWriteable && function(val) { 66074 return DO(val); 66075 }, 66076 deferEvaluation: true 66077 }); 66078 if (DEBUG) wrapped._wrapper = true; 66079 wrapped.__DO = DO; 66080 return wrapped; 66081 }; 66082 66083 options.deferEvaluation = true; // will either set for just options, or both read/options. 66084 var realDependentObservable = realKoDependentObservable(read, owner, options); 66085 66086 if (!realDeferEvaluation && !realIsPure) { 66087 realDependentObservable = wrap(realDependentObservable); 66088 dependentObservables.push(realDependentObservable); 66089 } 66090 66091 return realDependentObservable; 66092 }; 66093 ko.dependentObservable.fn = realKoDependentObservable.fn; 66094 ko.computed = ko.dependentObservable; 66095 var result = callback(); 66096 ko.dependentObservable = localDO; 66097 ko.computed = ko.dependentObservable; 66098 return result; 66099 } 66100 66101 function updateViewModel(mappedRootObject, rootObject, options, parentName, parent, parentPropertyName, mappedParent) { 66102 var isArray = exports.getType(ko.utils.unwrapObservable(rootObject)) === "array"; 66103 66104 parentPropertyName = parentPropertyName || ""; 66105 66106 // If this object was already mapped previously, take the options from there and merge them with our existing ones. 66107 if (exports.isMapped(mappedRootObject)) { 66108 var previousMapping = ko.utils.unwrapObservable(mappedRootObject)[mappingProperty]; 66109 options = merge(previousMapping, options); 66110 } 66111 66112 var callbackParams = { 66113 data: rootObject, 66114 parent: mappedParent || parent 66115 }; 66116 66117 var hasCreateCallback = function() { 66118 return options[parentName] && options[parentName].create instanceof Function; 66119 }; 66120 66121 var createCallback = function(data) { 66122 return withProxyDependentObservable(dependentObservables, function() { 66123 66124 if (ko.utils.unwrapObservable(parent) instanceof Array) { 66125 return options[parentName].create({ 66126 data: data || callbackParams.data, 66127 parent: callbackParams.parent, 66128 skip: emptyReturn 66129 }); 66130 } 66131 else { 66132 return options[parentName].create({ 66133 data: data || callbackParams.data, 66134 parent: callbackParams.parent 66135 }); 66136 } 66137 }); 66138 }; 66139 66140 var hasUpdateCallback = function() { 66141 return options[parentName] && options[parentName].update instanceof Function; 66142 }; 66143 66144 var updateCallback = function(obj, data) { 66145 var params = { 66146 data: data || callbackParams.data, 66147 parent: callbackParams.parent, 66148 target: ko.utils.unwrapObservable(obj) 66149 }; 66150 66151 if (ko.isWriteableObservable(obj)) { 66152 params.observable = obj; 66153 } 66154 66155 return options[parentName].update(params); 66156 }; 66157 66158 var alreadyMapped = visitedObjects.get(rootObject); 66159 if (alreadyMapped) { 66160 return alreadyMapped; 66161 } 66162 66163 parentName = parentName || ""; 66164 66165 if (!isArray) { 66166 // For atomic types, do a direct update on the observable 66167 if (!canHaveProperties(rootObject)) { 66168 switch (exports.getType(rootObject)) { 66169 case "function": 66170 if (hasUpdateCallback()) { 66171 if (ko.isWriteableObservable(rootObject)) { 66172 rootObject(updateCallback(rootObject)); 66173 mappedRootObject = rootObject; 66174 } 66175 else { 66176 mappedRootObject = updateCallback(rootObject); 66177 } 66178 } 66179 else { 66180 mappedRootObject = rootObject; 66181 } 66182 break; 66183 default: 66184 if (ko.isWriteableObservable(mappedRootObject)) { 66185 var valueToWrite; 66186 if (hasUpdateCallback()) { 66187 valueToWrite = updateCallback(mappedRootObject); 66188 mappedRootObject(valueToWrite); 66189 return valueToWrite; 66190 } 66191 else { 66192 valueToWrite = ko.utils.unwrapObservable(rootObject); 66193 mappedRootObject(valueToWrite); 66194 return valueToWrite; 66195 } 66196 } 66197 else { 66198 var hasCreateOrUpdateCallback = hasCreateCallback() || hasUpdateCallback(); 66199 66200 if (hasCreateCallback()) { 66201 mappedRootObject = createCallback(); 66202 } 66203 else { 66204 mappedRootObject = ko.observable(ko.utils.unwrapObservable(rootObject)); 66205 } 66206 66207 if (hasUpdateCallback()) { 66208 mappedRootObject(updateCallback(mappedRootObject)); 66209 } 66210 66211 if (hasCreateOrUpdateCallback) return mappedRootObject; 66212 } 66213 } 66214 66215 } 66216 else { 66217 mappedRootObject = ko.utils.unwrapObservable(mappedRootObject); 66218 if (!mappedRootObject) { 66219 if (hasCreateCallback()) { 66220 var result = createCallback(); 66221 66222 if (hasUpdateCallback()) { 66223 result = updateCallback(result); 66224 } 66225 return result; 66226 } 66227 else { 66228 if (hasUpdateCallback()) { 66229 //Removed ambiguous parameter result 66230 return updateCallback(); 66231 } 66232 mappedRootObject = {}; 66233 } 66234 } 66235 66236 if (hasUpdateCallback()) { 66237 mappedRootObject = updateCallback(mappedRootObject); 66238 } 66239 66240 visitedObjects.save(rootObject, mappedRootObject); 66241 if (hasUpdateCallback()) return mappedRootObject; 66242 66243 // For non-atomic types, visit all properties and update recursively 66244 visitPropertiesOrArrayEntries(rootObject, function(indexer) { 66245 var fullPropertyName = parentPropertyName.length ? parentPropertyName + "." + escapePropertyNameComponent(indexer) : escapePropertyNameComponent(indexer); 66246 66247 if (ko.utils.arrayIndexOf(options.ignore, fullPropertyName) !== -1) { 66248 return; 66249 } 66250 66251 if (ko.utils.arrayIndexOf(options.copy, fullPropertyName) !== -1) { 66252 mappedRootObject[indexer] = rootObject[indexer]; 66253 return; 66254 } 66255 66256 if (typeof rootObject[indexer] !== "object" && exports.getType(rootObject[indexer]) !== "array" && options.observe.length > 0 && ko.utils.arrayIndexOf(options.observe, fullPropertyName) === -1) { 66257 mappedRootObject[indexer] = rootObject[indexer]; 66258 options.copiedProperties[fullPropertyName] = true; 66259 return; 66260 } 66261 66262 // In case we are adding an already mapped property, fill it with the previously mapped property value to prevent recursion. 66263 // If this is a property that was generated by fromJS, we should use the options specified there 66264 var prevMappedProperty = visitedObjects.get(rootObject[indexer]); 66265 var retval = updateViewModel(mappedRootObject[indexer], rootObject[indexer], options, indexer, mappedRootObject, fullPropertyName, mappedRootObject); 66266 var value = prevMappedProperty || retval; 66267 66268 if (options.observe.length > 0 && ko.utils.arrayIndexOf(options.observe, fullPropertyName) === -1) { 66269 mappedRootObject[indexer] = ko.utils.unwrapObservable(value); 66270 options.copiedProperties[fullPropertyName] = true; 66271 return; 66272 } 66273 66274 if (ko.isWriteableObservable(mappedRootObject[indexer])) { 66275 value = ko.utils.unwrapObservable(value); 66276 if (mappedRootObject[indexer]() !== value) { 66277 mappedRootObject[indexer](value); 66278 } 66279 } 66280 else { 66281 value = mappedRootObject[indexer] === undefined ? value : ko.utils.unwrapObservable(value); 66282 mappedRootObject[indexer] = value; 66283 } 66284 66285 options.mappedProperties[fullPropertyName] = true; 66286 }); 66287 } 66288 } 66289 else { //mappedRootObject is an array 66290 var changes = []; 66291 66292 var hasKeyCallback = false; 66293 var keyCallback = function(x) { 66294 return x; 66295 }; 66296 if (options[parentName] && options[parentName].key) { 66297 keyCallback = options[parentName].key; 66298 hasKeyCallback = true; 66299 } 66300 66301 if (!ko.isObservable(mappedRootObject)) { 66302 // When creating the new observable array, also add a bunch of utility functions that take the 'key' of the array items into account. 66303 mappedRootObject = ko.observableArray([]); 66304 66305 mappedRootObject.mappedRemove = function(valueOrPredicate) { 66306 var predicate = typeof valueOrPredicate === "function" ? valueOrPredicate : function(value) { 66307 return value === keyCallback(valueOrPredicate); 66308 }; 66309 return mappedRootObject.remove(function(item) { 66310 return predicate(keyCallback(item)); 66311 }); 66312 }; 66313 66314 mappedRootObject.mappedRemoveAll = function(arrayOfValues) { 66315 var arrayOfKeys = filterArrayByKey(arrayOfValues, keyCallback); 66316 return mappedRootObject.remove(function(item) { 66317 return ko.utils.arrayIndexOf(arrayOfKeys, keyCallback(item)) !== -1; 66318 }); 66319 }; 66320 66321 mappedRootObject.mappedDestroy = function(valueOrPredicate) { 66322 var predicate = typeof valueOrPredicate === "function" ? valueOrPredicate : function(value) { 66323 return value === keyCallback(valueOrPredicate); 66324 }; 66325 return mappedRootObject.destroy(function(item) { 66326 return predicate(keyCallback(item)); 66327 }); 66328 }; 66329 66330 mappedRootObject.mappedDestroyAll = function(arrayOfValues) { 66331 var arrayOfKeys = filterArrayByKey(arrayOfValues, keyCallback); 66332 return mappedRootObject.destroy(function(item) { 66333 return ko.utils.arrayIndexOf(arrayOfKeys, keyCallback(item)) !== -1; 66334 }); 66335 }; 66336 66337 mappedRootObject.mappedIndexOf = function(item) { 66338 var keys = filterArrayByKey(mappedRootObject(), keyCallback); 66339 var key = keyCallback(item); 66340 return ko.utils.arrayIndexOf(keys, key); 66341 }; 66342 66343 mappedRootObject.mappedGet = function(item) { 66344 return mappedRootObject()[mappedRootObject.mappedIndexOf(item)]; 66345 }; 66346 66347 mappedRootObject.mappedCreate = function(value) { 66348 if (mappedRootObject.mappedIndexOf(value) !== -1) { 66349 throw new Error("There already is an object with the key that you specified."); 66350 } 66351 var item = hasCreateCallback() ? createCallback(value) : value; 66352 if (hasUpdateCallback()) { 66353 var newValue = updateCallback(item, value); 66354 if (ko.isWriteableObservable(item)) { 66355 item(newValue); 66356 } 66357 else { 66358 item = newValue; 66359 } 66360 } 66361 mappedRootObject.push(item); 66362 return item; 66363 }; 66364 } 66365 66366 var currentArrayKeys = filterArrayByKey(ko.utils.unwrapObservable(mappedRootObject), keyCallback).sort(); 66367 var newArrayKeys = filterArrayByKey(rootObject, keyCallback); 66368 if (hasKeyCallback) newArrayKeys.sort(); 66369 var editScript = ko.utils.compareArrays(currentArrayKeys, newArrayKeys); 66370 66371 var ignoreIndexOf = {}; 66372 66373 var i, j, key; 66374 66375 var unwrappedRootObject = ko.utils.unwrapObservable(rootObject); 66376 var itemsByKey = {}; 66377 var optimizedKeys = true; 66378 for (i = 0, j = unwrappedRootObject.length; i < j; i++) { 66379 key = keyCallback(unwrappedRootObject[i]); 66380 if (key === undefined || key instanceof Object) { 66381 optimizedKeys = false; 66382 break; 66383 } 66384 itemsByKey[key] = unwrappedRootObject[i]; 66385 } 66386 66387 var newContents = []; 66388 var passedOver = 0; 66389 var item, index; 66390 66391 for (i = 0, j = editScript.length; i < j; i++) { 66392 key = editScript[i]; 66393 var mappedItem; 66394 var fullPropertyName = parentPropertyName + "[" + escapePropertyNameComponent(i) + "]"; 66395 66396 switch (key.status) { 66397 case "added": 66398 item = optimizedKeys ? itemsByKey[key.value] : getItemByKey(ko.utils.unwrapObservable(rootObject), key.value, keyCallback); 66399 mappedItem = updateViewModel(undefined, item, options, parentName, mappedRootObject, fullPropertyName, parent); 66400 if (!hasCreateCallback()) { 66401 mappedItem = ko.utils.unwrapObservable(mappedItem); 66402 } 66403 66404 index = ignorableIndexOf(ko.utils.unwrapObservable(rootObject), item, ignoreIndexOf); 66405 66406 if (mappedItem === emptyReturn) { 66407 passedOver++; 66408 } 66409 else { 66410 newContents[index - passedOver] = mappedItem; 66411 } 66412 66413 ignoreIndexOf[index] = true; 66414 break; 66415 case "retained": 66416 item = optimizedKeys ? itemsByKey[key.value] : getItemByKey(ko.utils.unwrapObservable(rootObject), key.value, keyCallback); 66417 mappedItem = getItemByKey(mappedRootObject, key.value, keyCallback); 66418 updateViewModel(mappedItem, item, options, parentName, mappedRootObject, fullPropertyName, parent); 66419 66420 index = ignorableIndexOf(ko.utils.unwrapObservable(rootObject), item, ignoreIndexOf); 66421 newContents[index] = mappedItem; 66422 ignoreIndexOf[index] = true; 66423 break; 66424 case "deleted": 66425 mappedItem = getItemByKey(mappedRootObject, key.value, keyCallback); 66426 break; 66427 } 66428 66429 changes.push({ 66430 event: key.status, 66431 item: mappedItem 66432 }); 66433 } 66434 66435 mappedRootObject(newContents); 66436 66437 if (options[parentName] && options[parentName].arrayChanged) { 66438 ko.utils.arrayForEach(changes, function(change) { 66439 options[parentName].arrayChanged(change.event, change.item); 66440 }); 66441 } 66442 } 66443 66444 return mappedRootObject; 66445 } 66446 66447 function ignorableIndexOf(array, item, ignoreIndices) { 66448 for (var i = 0, j = array.length; i < j; i++) { 66449 if (ignoreIndices[i] === true) continue; 66450 if (array[i] === item) return i; 66451 } 66452 return null; 66453 } 66454 66455 function mapKey(item, callback) { 66456 var mappedItem; 66457 if (callback) mappedItem = callback(item); 66458 if (exports.getType(mappedItem) === "undefined") mappedItem = item; 66459 66460 return ko.utils.unwrapObservable(mappedItem); 66461 } 66462 66463 function getItemByKey(array, key, callback) { 66464 array = ko.utils.unwrapObservable(array); 66465 for (var i = 0, j = array.length; i < j; i++) { 66466 var item = array[i]; 66467 if (mapKey(item, callback) === key) return item; 66468 } 66469 66470 throw new Error("When calling ko.update*, the key '" + key + "' was not found!"); 66471 } 66472 66473 function filterArrayByKey(array, callback) { 66474 return ko.utils.arrayMap(ko.utils.unwrapObservable(array), function(item) { 66475 if (callback) { 66476 return mapKey(item, callback); 66477 } 66478 else { 66479 return item; 66480 } 66481 }); 66482 } 66483 66484 function visitPropertiesOrArrayEntries(rootObject, visitorCallback) { 66485 if (exports.getType(rootObject) === "array") { 66486 for (var i = 0; i < rootObject.length; i++) 66487 visitorCallback(i); 66488 } 66489 else { 66490 for (var propertyName in rootObject) { 66491 if (rootObject.hasOwnProperty(propertyName)) { 66492 visitorCallback(propertyName); 66493 } 66494 } 66495 } 66496 } 66497 66498 function canHaveProperties(object) { 66499 if (object === null) { 66500 return false; 66501 } 66502 var type = exports.getType(object); 66503 return (type === "object") || (type === "array"); 66504 } 66505 66506 // Based on the parentName, this creates a fully classified name of a property 66507 66508 function getPropertyName(parentName, parent, indexer) { 66509 var propertyName = parentName || ""; 66510 if (exports.getType(parent) === "array") { 66511 if (parentName) { 66512 propertyName += "[" + escapePropertyNameComponent(indexer) + "]"; 66513 } 66514 } 66515 else { 66516 if (parentName) { 66517 propertyName += "."; 66518 } 66519 propertyName += escapePropertyNameComponent(indexer); 66520 } 66521 return propertyName; 66522 } 66523 66524 function escapePropertyNameComponent(indexer) { 66525 var escapedIndexer = (''+indexer) 66526 .replace(/~/g, '~~') 66527 .replace(/\[/g, '~[') 66528 .replace(/]/g, '~]') 66529 .replace(/\./g, '~.'); 66530 return escapedIndexer; 66531 } 66532 66533 66534 exports.visitModel = function(rootObject, callback, options) { 66535 options = options || {}; 66536 options.visitedObjects = options.visitedObjects || new ObjectLookup(); 66537 66538 var mappedRootObject; 66539 var unwrappedRootObject = ko.utils.unwrapObservable(rootObject); 66540 66541 if (!canHaveProperties(unwrappedRootObject)) { 66542 return callback(rootObject, options.parentName); 66543 } 66544 else { 66545 options = fillOptions(options, unwrappedRootObject[mappingProperty]); 66546 66547 // Only do a callback, but ignore the results 66548 callback(rootObject, options.parentName); 66549 mappedRootObject = exports.getType(unwrappedRootObject) === "array" ? [] : {}; 66550 } 66551 66552 options.visitedObjects.save(rootObject, mappedRootObject); 66553 66554 var parentName = options.parentName; 66555 visitPropertiesOrArrayEntries(unwrappedRootObject, function(indexer) { 66556 var escapedIndexer = escapePropertyNameComponent(indexer); 66557 if (options.ignore && ko.utils.arrayIndexOf(options.ignore, escapedIndexer) !== -1) return; 66558 66559 var propertyValue = unwrappedRootObject[indexer]; 66560 options.parentName = getPropertyName(parentName, unwrappedRootObject, indexer); 66561 66562 // If we don't want to explicitly copy the unmapped property... 66563 if (ko.utils.arrayIndexOf(options.copy, escapedIndexer) === -1) { 66564 // ...find out if it's a property we want to explicitly include 66565 if (ko.utils.arrayIndexOf(options.include, escapedIndexer) === -1) { 66566 // The mapped properties object contains all the properties that were part of the original object. 66567 // If a property does not exist, and it is not because it is part of an array (e.g. "myProp[3]"), then it should not be unmapped. 66568 var unwrappedRootMappingProperty = unwrappedRootObject[mappingProperty]; 66569 if (unwrappedRootMappingProperty) { 66570 var mappedProperties = unwrappedRootMappingProperty.mappedProperties; 66571 if (mappedProperties && !mappedProperties[escapedIndexer]) { 66572 var copiedProperties = unwrappedRootMappingProperty.copiedProperties; 66573 if (copiedProperties && !copiedProperties[escapedIndexer] && (exports.getType(unwrappedRootObject) !== "array")) { 66574 return; 66575 } 66576 } 66577 } 66578 } 66579 } 66580 66581 switch (exports.getType(ko.utils.unwrapObservable(propertyValue))) { 66582 case "object": 66583 case "array": 66584 case "undefined": 66585 var previouslyMappedValue = options.visitedObjects.get(propertyValue); 66586 mappedRootObject[indexer] = (exports.getType(previouslyMappedValue) !== "undefined") ? previouslyMappedValue : exports.visitModel(propertyValue, callback, options); 66587 break; 66588 default: 66589 mappedRootObject[indexer] = callback(propertyValue, options.parentName); 66590 } 66591 }); 66592 66593 return mappedRootObject; 66594 }; 66595 66596 function SimpleObjectLookup() { 66597 var keys = []; 66598 var values = []; 66599 this.save = function(key, value) { 66600 var existingIndex = ko.utils.arrayIndexOf(keys, key); 66601 if (existingIndex >= 0) values[existingIndex] = value; 66602 else { 66603 keys.push(key); 66604 values.push(value); 66605 } 66606 }; 66607 this.get = function(key) { 66608 var existingIndex = ko.utils.arrayIndexOf(keys, key); 66609 var value = (existingIndex >= 0) ? values[existingIndex] : undefined; 66610 return value; 66611 }; 66612 } 66613 66614 function ObjectLookup() { 66615 var buckets = {}; 66616 66617 var findBucket = function(key) { 66618 var bucketKey; 66619 try { 66620 bucketKey = key;//JSON.stringify(key); 66621 } 66622 catch (e) { 66623 bucketKey = "$$$"; 66624 } 66625 66626 var bucket = buckets[bucketKey]; 66627 if (!buckets.hasOwnProperty(bucketKey)) { 66628 bucket = new SimpleObjectLookup(); 66629 buckets[bucketKey] = bucket; 66630 } 66631 return bucket; 66632 }; 66633 66634 this.save = function(key, value) { 66635 findBucket(key).save(key, value); 66636 }; 66637 this.get = function(key) { 66638 return findBucket(key).get(key); 66639 }; 66640 } 66641}));
66642 66643/*============================================================================= 66644 Author: Eric M. Barnard - @ericmbarnard 66645 License: MIT (http://opensource.org/licenses/mit-license.php) 66646 66647 Description: Validation Library for KnockoutJS 66648 Version: 2.0.0-pre.3 66649=============================================================================== 66650*/ 66651/*globals require: false, exports: false, define: false, ko: false */ 66652 66653(function (factory) { 66654 // Module systems magic dance. 66655 66656 if (typeof require === "function" && typeof exports === "object" && typeof module === "object") { 66657 // CommonJS or Node: hard-coded dependency on "knockout"
vendor: 15,685 bytes, lines 66658-67162
66658 factory(require("knockout"), exports); 66659 } else if (typeof define === "function" && define["amd"]) { 66660 // AMD anonymous module with hard-coded dependency on "knockout" 66661 define('knockoutValidation',["knockout", "exports"], factory); 66662 } else { 66663 // <script> tag: use the global `ko` object, attaching a `mapping` property 66664 factory(ko, ko.validation = {}); 66665 } 66666}(function ( ko, exports ) { 66667 66668 if (typeof (ko) === 'undefined') { throw 'Knockout is required, please ensure it is loaded before loading this validation plug-in'; } 66669 66670 // create our namespace object 66671 ko.validation = exports; 66672 66673 var kv = ko.validation, 66674 koUtils = ko.utils, 66675 unwrap = koUtils.unwrapObservable, 66676 forEach = koUtils.arrayForEach, 66677 extend = koUtils.extend; 66678;/*global ko: false*/ 66679 66680var defaults = { 66681 registerExtenders: true, 66682 messagesOnModified: true, 66683 errorsAsTitle: true, // enables/disables showing of errors as title attribute of the target element. 66684 errorsAsTitleOnModified: false, // shows the error when hovering the input field (decorateElement must be true) 66685 messageTemplate: null, 66686 insertMessages: true, // automatically inserts validation messages as <span></span> 66687 parseInputAttributes: false, // parses the HTML5 validation attribute from a form element and adds that to the object 66688 writeInputAttributes: false, // adds HTML5 input validation attributes to form elements that ko observable's are bound to 66689 decorateInputElement: false, // false to keep backward compatibility 66690 decorateElementOnModified: true,// true to keep backward compatibility 66691 errorClass: null, // single class for error message and element 66692 errorElementClass: 'validationElement', // class to decorate error element 66693 errorMessageClass: 'validationMessage', // class to decorate error message 66694 allowHtmlMessages: false, // allows HTML in validation messages 66695 grouping: { 66696 deep: false, //by default grouping is shallow 66697 observable: true, //and using observables 66698 live: false //react to changes to observableArrays if observable === true 66699 }, 66700 validate: { 66701 // throttle: 10 66702 } 66703}; 66704 66705// make a copy so we can use 'reset' later 66706var configuration = extend({}, defaults); 66707 66708configuration.html5Attributes = ['required', 'pattern', 'min', 'max', 'step']; 66709configuration.html5InputTypes = ['email', 'number', 'date']; 66710 66711configuration.reset = function () { 66712 extend(configuration, defaults); 66713}; 66714 66715kv.configuration = configuration; 66716;kv.utils = (function () { 66717 var seedId = new Date().getTime(); 66718 66719 var domData = {}; //hash of data objects that we reference from dom elements 66720 var domDataKey = '__ko_validation__'; 66721 66722 return { 66723 isArray: function (o) { 66724 return o.isArray || Object.prototype.toString.call(o) === '[object Array]'; 66725 }, 66726 isObject: function (o) { 66727 return o !== null && typeof o === 'object'; 66728 }, 66729 isNumber: function(o) { 66730 return !isNaN(o); 66731 }, 66732 isObservableArray: function(instance) { 66733 return !!instance && 66734 typeof instance["remove"] === "function" && 66735 typeof instance["removeAll"] === "function" && 66736 typeof instance["destroy"] === "function" && 66737 typeof instance["destroyAll"] === "function" && 66738 typeof instance["indexOf"] === "function" && 66739 typeof instance["replace"] === "function"; 66740 }, 66741 values: function (o) { 66742 var r = []; 66743 for (var i in o) { 66744 if (o.hasOwnProperty(i)) { 66745 r.push(o[i]); 66746 } 66747 } 66748 return r; 66749 }, 66750 getValue: function (o) { 66751 return (typeof o === 'function' ? o() : o); 66752 }, 66753 hasAttribute: function (node, attr) { 66754 return node.getAttribute(attr) !== null; 66755 }, 66756 getAttribute: function (element, attr) { 66757 return element.getAttribute(attr); 66758 }, 66759 setAttribute: function (element, attr, value) { 66760 return element.setAttribute(attr, value); 66761 }, 66762 isValidatable: function (o) { 66763 return !!(o && o.rules && o.isValid && o.isModified); 66764 }, 66765 insertAfter: function (node, newNode) { 66766 node.parentNode.insertBefore(newNode, node.nextSibling); 66767 }, 66768 newId: function () { 66769 return seedId += 1; 66770 }, 66771 getConfigOptions: function (element) { 66772 var options = kv.utils.contextFor(element); 66773 66774 return options || kv.configuration; 66775 }, 66776 setDomData: function (node, data) { 66777 var key = node[domDataKey]; 66778 66779 if (!key) { 66780 node[domDataKey] = key = kv.utils.newId(); 66781 } 66782 66783 domData[key] = data; 66784 }, 66785 getDomData: function (node) { 66786 var key = node[domDataKey]; 66787 66788 if (!key) { 66789 return undefined; 66790 } 66791 66792 return domData[key]; 66793 }, 66794 contextFor: function (node) { 66795 switch (node.nodeType) { 66796 case 1: 66797 case 8: 66798 var context = kv.utils.getDomData(node); 66799 if (context) { return context; } 66800 if (node.parentNode) { return kv.utils.contextFor(node.parentNode); } 66801 break; 66802 } 66803 return undefined; 66804 }, 66805 isEmptyVal: function (val) { 66806 if (val === undefined) { 66807 return true; 66808 } 66809 if (val === null) { 66810 return true; 66811 } 66812 if (val === "") { 66813 return true; 66814 } 66815 }, 66816 getOriginalElementTitle: function (element) { 66817 var savedOriginalTitle = kv.utils.getAttribute(element, 'data-orig-title'), 66818 currentTitle = element.title, 66819 hasSavedOriginalTitle = kv.utils.hasAttribute(element, 'data-orig-title'); 66820 66821 return hasSavedOriginalTitle ? 66822 savedOriginalTitle : currentTitle; 66823 }, 66824 async: function (expr) { 66825 if (window.setImmediate) { window.setImmediate(expr); } 66826 else { window.setTimeout(expr, 0); } 66827 }, 66828 forEach: function (object, callback) { 66829 if (kv.utils.isArray(object)) { 66830 return forEach(object, callback); 66831 } 66832 for (var prop in object) { 66833 if (object.hasOwnProperty(prop)) { 66834 callback(object[prop], prop); 66835 } 66836 } 66837 } 66838 }; 66839}());;var api = (function () { 66840 66841 var isInitialized = 0, 66842 configuration = kv.configuration, 66843 utils = kv.utils; 66844 66845 function cleanUpSubscriptions(context) { 66846 forEach(context.subscriptions, function (subscription) { 66847 subscription.dispose(); 66848 }); 66849 context.subscriptions = []; 66850 } 66851 66852 function dispose(context) { 66853 if (context.options.deep) { 66854 forEach(context.flagged, function (obj) { 66855 delete obj.__kv_traversed; 66856 }); 66857 context.flagged.length = 0; 66858 } 66859 66860 if (!context.options.live) { 66861 cleanUpSubscriptions(context); 66862 } 66863 } 66864 66865 function runTraversal(obj, context) { 66866 context.validatables = []; 66867 cleanUpSubscriptions(context); 66868 traverseGraph(obj, context); 66869 dispose(context); 66870 } 66871 66872 function traverseGraph(obj, context, level) { 66873 var objValues = [], 66874 val = obj.peek ? obj.peek() : obj; 66875 66876 if (obj.__kv_traversed === true) { 66877 return; 66878 } 66879 66880 if (context.options.deep) { 66881 obj.__kv_traversed = true; 66882 context.flagged.push(obj); 66883 } 66884 66885 //default level value depends on deep option. 66886 level = (level !== undefined ? level : context.options.deep ? 1 : -1); 66887 66888 // if object is observable then add it to the list 66889 if (ko.isObservable(obj)) { 66890 // ensure it's validatable but don't extend validatedObservable because it 66891 // would overwrite isValid property. 66892 if (!obj.errors && !utils.isValidatable(obj)) { 66893 obj.extend({ validatable: true }); 66894 } 66895 context.validatables.push(obj); 66896 66897 if (context.options.live && utils.isObservableArray(obj)) { 66898 context.subscriptions.push(obj.subscribe(function () { 66899 context.graphMonitor.valueHasMutated(); 66900 })); 66901 } 66902 } 66903 66904 //get list of values either from array or object but ignore non-objects 66905 // and destroyed objects 66906 if (val && !val._destroy) { 66907 if (utils.isArray(val)) { 66908 objValues = val; 66909 } 66910 else if (utils.isObject(val)) { 66911 objValues = utils.values(val); 66912 } 66913 } 66914 66915 //process recursively if it is deep grouping 66916 if (level !== 0) { 66917 utils.forEach(objValues, function (observable) { 66918 //but not falsy things and not HTML Elements 66919 if (observable && !observable.nodeType && (!ko.isComputed(observable) || observable.rules)) { 66920 traverseGraph(observable, context, level + 1); 66921 } 66922 }); 66923 } 66924 } 66925 66926 function collectErrors(array) { 66927 var errors = []; 66928 forEach(array, function (observable) { 66929 // Do not collect validatedObservable errors 66930 if (utils.isValidatable(observable) && !observable.isValid()) { 66931 // Use peek because we don't want a dependency for 'error' property because it 66932 // changes before 'isValid' does. (Issue #99) 66933 errors.push(observable.error.peek()); 66934 } 66935 }); 66936 return errors; 66937 } 66938 66939 return { 66940 //Call this on startup 66941 //any config can be overridden with the passed in options 66942 init: function (options, force) { 66943 //done run this multiple times if we don't really want to 66944 if (isInitialized > 0 && !force) { 66945 return; 66946 } 66947 66948 //because we will be accessing options properties it has to be an object at least 66949 options = options || {}; 66950 //if specific error classes are not provided then apply generic errorClass 66951 //it has to be done on option so that options.errorClass can override default 66952 //errorElementClass and errorMessage class but not those provided in options 66953 options.errorElementClass = options.errorElementClass || options.errorClass || configuration.errorElementClass; 66954 options.errorMessageClass = options.errorMessageClass || options.errorClass || configuration.errorMessageClass; 66955 66956 extend(configuration, options); 66957 66958 if (configuration.registerExtenders) { 66959 kv.registerExtenders(); 66960 } 66961 66962 isInitialized = 1; 66963 }, 66964 // backwards compatibility 66965 configure: function (options) { kv.init(options); }, 66966 66967 // resets the config back to its original state 66968 reset: kv.configuration.reset, 66969 66970 // recursively walks a viewModel and creates an object that 66971 // provides validation information for the entire viewModel 66972 // obj -> the viewModel to walk 66973 // options -> { 66974 // deep: false, // if true, will walk past the first level of viewModel properties 66975 // observable: false // if true, returns a computed observable indicating if the viewModel is valid 66976 // } 66977 group: function group(obj, options) { // array of observables or viewModel 66978 options = extend(extend({}, configuration.grouping), options); 66979 66980 var context = { 66981 options: options, 66982 graphMonitor: ko.observable(), 66983 flagged: [], 66984 subscriptions: [], 66985 validatables: [] 66986 }; 66987 66988 var result = null; 66989 66990 //if using observables then traverse structure once and add observables 66991 if (options.observable) { 66992 result = ko.computed(function () { 66993 context.graphMonitor(); //register dependency 66994 runTraversal(obj, context); 66995 return collectErrors(context.validatables); 66996 }); 66997 } 66998 else { //if not using observables then every call to error() should traverse the structure 66999 result = function () { 67000 runTraversal(obj, context); 67001 return collectErrors(context.validatables); 67002 }; 67003 } 67004 67005 result.showAllMessages = function (show) { // thanks @heliosPortal 67006 if (show === undefined) {//default to true 67007 show = true; 67008 } 67009 67010 result.forEach(function (observable) { 67011 if (utils.isValidatable(observable)) { 67012 observable.isModified(show); 67013 } 67014 }); 67015 }; 67016 67017 result.isAnyMessageShown = function () { 67018 var invalidAndModifiedPresent; 67019 67020 invalidAndModifiedPresent = !!result.find(function (observable) { 67021 return utils.isValidatable(observable) && !observable.isValid() && observable.isModified(); 67022 }); 67023 return invalidAndModifiedPresent; 67024 }; 67025 67026 result.filter = function(predicate) { 67027 predicate = predicate || function () { return true; }; 67028 // ensure we have latest changes 67029 result(); 67030 67031 return koUtils.arrayFilter(context.validatables, predicate); 67032 }; 67033 67034 result.find = function(predicate) { 67035 predicate = predicate || function () { return true; }; 67036 // ensure we have latest changes 67037 result(); 67038 67039 return koUtils.arrayFirst(context.validatables, predicate); 67040 }; 67041 67042 result.forEach = function(callback) { 67043 callback = callback || function () { }; 67044 // ensure we have latest changes 67045 result(); 67046 67047 forEach(context.validatables, callback); 67048 }; 67049 67050 result.map = function(mapping) { 67051 mapping = mapping || function (item) { return item; }; 67052 // ensure we have latest changes 67053 result(); 67054 67055 return koUtils.arrayMap(context.validatables, mapping); 67056 }; 67057 67058 /** 67059 * @private You should not rely on this method being here. 67060 * It's a private method and it may change in the future. 67061 * 67062 * @description Updates the validated object and collects errors from it. 67063 */ 67064 result._updateState = function(newValue) { 67065 if (!utils.isObject(newValue)) { 67066 throw new Error('An object is required.'); 67067 } 67068 obj = newValue; 67069 if (options.observable) { 67070 context.graphMonitor.valueHasMutated(); 67071 } 67072 else { 67073 runTraversal(newValue, context); 67074 return collectErrors(context.validatables); 67075 } 67076 }; 67077 return result; 67078 }, 67079 67080 formatMessage: function (message, params, observable) { 67081 if (utils.isObject(params) && params.typeAttr) { 67082 params = params.value; 67083 } 67084 if (typeof (message) === 'function') { 67085 return message(params, observable); 67086 } 67087 var replacements = unwrap(params) || []; 67088 if (!utils.isArray(replacements)) { 67089 replacements = [replacements]; 67090 } 67091 return message.replace(/{(\d+)}/gi, function(match, index) { 67092 if (typeof replacements[index] !== 'undefined') { 67093 return replacements[index]; 67094 } 67095 return match; 67096 }); 67097 }, 67098 67099 // addRule: 67100 // This takes in a ko.observable and a Rule Context - which is just a rule name and params to supply to the validator 67101 // ie: kv.addRule(myObservable, { 67102 // rule: 'required', 67103 // params: true 67104 // }); 67105 // 67106 addRule: function (observable, rule) { 67107 observable.extend({ validatable: true }); 67108 67109 var hasRule = !!koUtils.arrayFirst(observable.rules(), function(item) { 67110 return item.rule && item.rule === rule.rule; 67111 }); 67112 67113 if (!hasRule) { 67114 //push a Rule Context to the observables local array of Rule Contexts 67115 observable.rules.push(rule); 67116 } 67117 return observable; 67118 }, 67119 67120 // addAnonymousRule: 67121 // Anonymous Rules essentially have all the properties of a Rule, but are only specific for a certain property 67122 // and developers typically are wanting to add them on the fly or not register a rule with the 'kv.rules' object 67123 // 67124 // Example: 67125 // var test = ko.observable('something').extend{( 67126 // validation: { 67127 // validator: function(val, someOtherVal){ 67128 // return true; 67129 // }, 67130 // message: "Something must be really wrong!', 67131 // params: true 67132 // } 67133 // )}; 67134 addAnonymousRule: function (observable, ruleObj) { 67135 if (ruleObj['message'] === undefined) { 67136 ruleObj['message'] = 'Error'; 67137 } 67138 67139 //make sure onlyIf is honoured 67140 if (ruleObj.onlyIf) { 67141 ruleObj.condition = ruleObj.onlyIf; 67142 } 67143 67144 //add the anonymous rule to the observable 67145 kv.addRule(observable, ruleObj); 67146 }, 67147 67148 addExtender: function (ruleName) { 67149 ko.extenders[ruleName] = function (observable, params) { 67150 //params can come in a few flavors 67151 // 1. Just the params to be passed to the validator 67152 // 2. An object containing the Message to be used and the Params to pass to the validator 67153 // 3. A condition when the validation rule to be applied 67154 // 67155 // Example: 67156 // var test = ko.observable(3).extend({ 67157 // max: { 67158 // message: 'This special field has a Max of {0}', 67159 // params: 2, 67160 // onlyIf: function() { 67161 // return specialField.IsVisible(); 67162 //
vendor: 7,170 bytes, lines 67162-67397
67162 } 67163 // } 67164 // )}; 67165 // 67166 if (params && (params.message || params.onlyIf)) { //if it has a message or condition object, then its an object literal to use 67167 return kv.addRule(observable, { 67168 rule: ruleName, 67169 message: params.message, 67170 params: utils.isEmptyVal(params.params) ? true : params.params, 67171 condition: params.onlyIf 67172 }); 67173 } else { 67174 return kv.addRule(observable, { 67175 rule: ruleName, 67176 params: params 67177 }); 67178 } 67179 }; 67180 }, 67181 67182 // loops through all kv.rules and adds them as extenders to 67183 // ko.extenders 67184 registerExtenders: function () { // root extenders optional, use 'validation' extender if would cause conflicts 67185 if (configuration.registerExtenders) { 67186 for (var ruleName in kv.rules) { 67187 if (kv.rules.hasOwnProperty(ruleName)) { 67188 if (!ko.extenders[ruleName]) { 67189 kv.addExtender(ruleName); 67190 } 67191 } 67192 } 67193 } 67194 }, 67195 67196 //creates a span next to the @element with the specified error class 67197 insertValidationMessage: function (element) { 67198 var span = document.createElement('SPAN'); 67199 span.className = utils.getConfigOptions(element).errorMessageClass; 67200 utils.insertAfter(element, span); 67201 return span; 67202 }, 67203 67204 // if html-5 validation attributes have been specified, this parses 67205 // the attributes on @element 67206 parseInputValidationAttributes: function (element, valueAccessor) { 67207 forEach(kv.configuration.html5Attributes, function (attr) { 67208 if (utils.hasAttribute(element, attr)) { 67209 67210 var params = element.getAttribute(attr) || true; 67211 67212 if (attr === 'min' || attr === 'max') 67213 { 67214 // If we're validating based on the min and max attributes, we'll 67215 // need to know what the 'type' attribute is set to 67216 var typeAttr = element.getAttribute('type'); 67217 if (typeof typeAttr === "undefined" || !typeAttr) 67218 { 67219 // From http://www.w3.org/TR/html-markup/input: 67220 // An input element with no type attribute specified represents the 67221 // same thing as an input element with its type attribute set to "text". 67222 typeAttr = "text"; 67223 } 67224 params = {typeAttr: typeAttr, value: params}; 67225 } 67226 67227 kv.addRule(valueAccessor(), { 67228 rule: attr, 67229 params: params 67230 }); 67231 } 67232 }); 67233 67234 var currentType = element.getAttribute('type'); 67235 forEach(kv.configuration.html5InputTypes, function (type) { 67236 if (type === currentType) { 67237 kv.addRule(valueAccessor(), { 67238 rule: (type === 'date') ? 'dateISO' : type, 67239 params: true 67240 }); 67241 } 67242 }); 67243 }, 67244 67245 // writes html5 validation attributes on the element passed in 67246 writeInputValidationAttributes: function (element, valueAccessor) { 67247 var observable = valueAccessor(); 67248 67249 if (!observable || !observable.rules) { 67250 return; 67251 } 67252 67253 var contexts = observable.rules(); // observable array 67254 67255 // loop through the attributes and add the information needed 67256 forEach(kv.configuration.html5Attributes, function (attr) { 67257 var ctx = koUtils.arrayFirst(contexts, function (ctx) { 67258 return ctx.rule && ctx.rule.toLowerCase() === attr.toLowerCase(); 67259 }); 67260 67261 if (!ctx) { 67262 return; 67263 } 67264 67265 // we have a rule matching a validation attribute at this point 67266 // so lets add it to the element along with the params 67267 ko.computed({ 67268 read: function() { 67269 var params = ko.unwrap(ctx.params); 67270 67271 // we have to do some special things for the pattern validation 67272 if (ctx.rule === "pattern" && params instanceof RegExp) { 67273 // we need the pure string representation of the RegExpr without the //gi stuff 67274 params = params.source; 67275 } 67276 67277 element.setAttribute(attr, params); 67278 }, 67279 disposeWhenNodeIsRemoved: element 67280 }); 67281 }); 67282 67283 contexts = null; 67284 }, 67285 67286 //take an existing binding handler and make it cause automatic validations 67287 makeBindingHandlerValidatable: function (handlerName) { 67288 var init = ko.bindingHandlers[handlerName].init; 67289 67290 ko.bindingHandlers[handlerName].init = function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { 67291 67292 init(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext); 67293 67294 return ko.bindingHandlers['validationCore'].init(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext); 67295 }; 67296 }, 67297 67298 // visit an objects properties and apply validation rules from a definition 67299 setRules: function (target, definition) { 67300 var setRules = function (target, definition) { 67301 if (!target || !definition) { return; } 67302 67303 for (var prop in definition) { 67304 if (!definition.hasOwnProperty(prop)) { continue; } 67305 var ruleDefinitions = definition[prop]; 67306 67307 //check the target property exists and has a value 67308 if (!target[prop]) { continue; } 67309 var targetValue = target[prop], 67310 unwrappedTargetValue = unwrap(targetValue), 67311 rules = {}, 67312 nonRules = {}; 67313 67314 for (var rule in ruleDefinitions) { 67315 if (!ruleDefinitions.hasOwnProperty(rule)) { continue; } 67316 if (kv.rules[rule]) { 67317 rules[rule] = ruleDefinitions[rule]; 67318 } else { 67319 nonRules[rule] = ruleDefinitions[rule]; 67320 } 67321 } 67322 67323 //apply rules 67324 if (ko.isObservable(targetValue)) { 67325 targetValue.extend(rules); 67326 } 67327 67328 //then apply child rules 67329 //if it's an array, apply rules to all children 67330 if (unwrappedTargetValue && utils.isArray(unwrappedTargetValue)) { 67331 for (var i = 0; i < unwrappedTargetValue.length; i++) { 67332 setRules(unwrappedTargetValue[i], nonRules); 67333 } 67334 //otherwise, just apply to this property 67335 } else { 67336 setRules(unwrappedTargetValue, nonRules); 67337 } 67338 } 67339 }; 67340 setRules(target, definition); 67341 } 67342 }; 67343 67344}()); 67345 67346// expose api publicly 67347extend(ko.validation, api); 67348;//Validation Rules: 67349// You can view and override messages or rules via: 67350// kv.rules[ruleName] 67351// 67352// To implement a custom Rule, simply use this template: 67353// kv.rules['<custom rule name>'] = { 67354// validator: function (val, param) { 67355// <custom logic> 67356// return <true or false>; 67357// }, 67358// message: '<custom validation message>' //optionally you can also use a '{0}' to denote a placeholder that will be replaced with your 'param' 67359// }; 67360// 67361// Example: 67362// kv.rules['mustEqual'] = { 67363// validator: function( val, mustEqualVal ){ 67364// return val === mustEqualVal; 67365// }, 67366// message: 'This field must equal {0}' 67367// }; 67368// 67369kv.rules = {}; 67370kv.rules['required'] = { 67371 validator: function (val, required) { 67372 var testVal; 67373 67374 if (val === undefined || val === null) { 67375 return !required; 67376 } 67377 67378 testVal = val; 67379 if (typeof (val) === 'string') { 67380 if (String.prototype.trim) { 67381 testVal = val.trim(); 67382 } 67383 else { 67384 testVal = val.replace(/^\s+|\s+$/g, ''); 67385 } 67386 } 67387 67388 if (!required) {// if they passed: { required: false }, then don't require this 67389 return true; 67390 } 67391 67392 return ((testVal + '').length > 0); 67393 }, 67394 message: 'This field is required.' 67395}; 67396 67397function minMaxValidatorFactory(validatorName) {
vendor: 21,121 bytes, lines 67398-67968
67398 var isMaxValidation = validatorName === "max"; 67399 67400 return function (val, options) { 67401 if (kv.utils.isEmptyVal(val)) { 67402 return true; 67403 } 67404 67405 var comparisonValue, type; 67406 if (options.typeAttr === undefined) { 67407 // This validator is being called from javascript rather than 67408 // being bound from markup 67409 type = "text"; 67410 comparisonValue = options; 67411 } else { 67412 type = options.typeAttr; 67413 comparisonValue = options.value; 67414 } 67415 67416 // From http://www.w3.org/TR/2012/WD-html5-20121025/common-input-element-attributes.html#attr-input-min, 67417 // if the value is parseable to a number, then the minimum should be numeric 67418 if (!isNaN(comparisonValue) && !(comparisonValue instanceof Date)) { 67419 type = "number"; 67420 } 67421 67422 var regex, valMatches, comparisonValueMatches; 67423 switch (type.toLowerCase()) { 67424 case "week": 67425 regex = /^(\d{4})-W(\d{2})$/; 67426 valMatches = val.match(regex); 67427 if (valMatches === null) { 67428 throw "Invalid value for " + validatorName + " attribute for week input. Should look like " + 67429 "'2000-W33' http://www.w3.org/TR/html-markup/input.week.html#input.week.attrs.min"; 67430 } 67431 comparisonValueMatches = comparisonValue.match(regex); 67432 // If no regex matches were found, validation fails 67433 if (!comparisonValueMatches) { 67434 return false; 67435 } 67436 67437 if (isMaxValidation) { 67438 return (valMatches[1] < comparisonValueMatches[1]) || // older year 67439 // same year, older week 67440 ((valMatches[1] === comparisonValueMatches[1]) && (valMatches[2] <= comparisonValueMatches[2])); 67441 } else { 67442 return (valMatches[1] > comparisonValueMatches[1]) || // newer year 67443 // same year, newer week 67444 ((valMatches[1] === comparisonValueMatches[1]) && (valMatches[2] >= comparisonValueMatches[2])); 67445 } 67446 break; 67447 67448 case "month": 67449 regex = /^(\d{4})-(\d{2})$/; 67450 valMatches = val.match(regex); 67451 if (valMatches === null) { 67452 throw "Invalid value for " + validatorName + " attribute for month input. Should look like " + 67453 "'2000-03' http://www.w3.org/TR/html-markup/input.month.html#input.month.attrs.min"; 67454 } 67455 comparisonValueMatches = comparisonValue.match(regex); 67456 // If no regex matches were found, validation fails 67457 if (!comparisonValueMatches) { 67458 return false; 67459 } 67460 67461 if (isMaxValidation) { 67462 return ((valMatches[1] < comparisonValueMatches[1]) || // older year 67463 // same year, older month 67464 ((valMatches[1] === comparisonValueMatches[1]) && (valMatches[2] <= comparisonValueMatches[2]))); 67465 } else { 67466 return (valMatches[1] > comparisonValueMatches[1]) || // newer year 67467 // same year, newer month 67468 ((valMatches[1] === comparisonValueMatches[1]) && (valMatches[2] >= comparisonValueMatches[2])); 67469 } 67470 break; 67471 67472 case "number": 67473 case "range": 67474 if (isMaxValidation) { 67475 return (!isNaN(val) && parseFloat(val) <= parseFloat(comparisonValue)); 67476 } else { 67477 return (!isNaN(val) && parseFloat(val) >= parseFloat(comparisonValue)); 67478 } 67479 break; 67480 67481 default: 67482 if (isMaxValidation) { 67483 return val <= comparisonValue; 67484 } else { 67485 return val >= comparisonValue; 67486 } 67487 } 67488 }; 67489} 67490 67491kv.rules['min'] = { 67492 validator: minMaxValidatorFactory("min"), 67493 message: 'Please enter a value greater than or equal to {0}.' 67494}; 67495 67496kv.rules['max'] = { 67497 validator: minMaxValidatorFactory("max"), 67498 message: 'Please enter a value less than or equal to {0}.' 67499}; 67500 67501kv.rules['minLength'] = { 67502 validator: function (val, minLength) { 67503 if(kv.utils.isEmptyVal(val)) { return true; } 67504 var normalizedVal = kv.utils.isNumber(val) ? ('' + val) : val; 67505 return normalizedVal.length >= minLength; 67506 }, 67507 message: 'Please enter at least {0} characters.' 67508}; 67509 67510kv.rules['maxLength'] = { 67511 validator: function (val, maxLength) { 67512 if(kv.utils.isEmptyVal(val)) { return true; } 67513 var normalizedVal = kv.utils.isNumber(val) ? ('' + val) : val; 67514 return normalizedVal.length <= maxLength; 67515 }, 67516 message: 'Please enter no more than {0} characters.' 67517}; 67518 67519kv.rules['pattern'] = { 67520 validator: function (val, regex) { 67521 return kv.utils.isEmptyVal(val) || val.toString().match(regex) !== null; 67522 }, 67523 message: 'Please check this value.' 67524}; 67525 67526kv.rules['step'] = { 67527 validator: function (val, step) { 67528 67529 // in order to handle steps of .1 & .01 etc.. Modulus won't work 67530 // if the value is a decimal, so we have to correct for that 67531 if (kv.utils.isEmptyVal(val) || step === 'any') { return true; } 67532 var dif = (val * 100) % (step * 100); 67533 return Math.abs(dif) < 0.00001 || Math.abs(1 - dif) < 0.00001; 67534 }, 67535 message: 'The value must increment by {0}.' 67536}; 67537 67538kv.rules['email'] = { 67539 validator: function (val, validate) { 67540 if (!validate) { return true; } 67541 67542 //I think an empty email address is also a valid entry 67543 //if one want's to enforce entry it should be done with 'required: true' 67544 return kv.utils.isEmptyVal(val) || ( 67545 // jquery validate regex - thanks Scott Gonzalez 67546 validate && /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([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])))$/i.test(val) 67547 ); 67548 }, 67549 message: 'Please enter a proper email address.' 67550}; 67551 67552kv.rules['date'] = { 67553 validator: function (value, validate) { 67554 if (!validate) { return true; } 67555 return kv.utils.isEmptyVal(value) || (validate && !/Invalid|NaN/.test(new Date(value))); 67556 }, 67557 message: 'Please enter a proper date.' 67558}; 67559 67560kv.rules['dateISO'] = { 67561 validator: function (value, validate) { 67562 if (!validate) { return true; } 67563 return kv.utils.isEmptyVal(value) || (validate && /^\d{4}[-/](?:0?[1-9]|1[012])[-/](?:0?[1-9]|[12][0-9]|3[01])$/.test(value)); 67564 }, 67565 message: 'Please enter a proper date.' 67566}; 67567 67568kv.rules['number'] = { 67569 validator: function (value, validate) { 67570 if (!validate) { return true; } 67571 return kv.utils.isEmptyVal(value) || (validate && /^-?(?:\d+|\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test(value)); 67572 }, 67573 message: 'Please enter a number.' 67574}; 67575 67576kv.rules['digit'] = { 67577 validator: function (value, validate) { 67578 if (!validate) { return true; } 67579 return kv.utils.isEmptyVal(value) || (validate && /^\d+$/.test(value)); 67580 }, 67581 message: 'Please enter a digit.' 67582}; 67583 67584kv.rules['phoneUS'] = { 67585 validator: function (phoneNumber, validate) { 67586 if (!validate) { return true; } 67587 if (kv.utils.isEmptyVal(phoneNumber)) { return true; } // makes it optional, use 'required' rule if it should be required 67588 if (typeof (phoneNumber) !== 'string') { return false; } 67589 phoneNumber = phoneNumber.replace(/\s+/g, ""); 67590 return validate && phoneNumber.length > 9 && phoneNumber.match(/^(1-?)?(\([2-9]\d{2}\)|[2-9]\d{2})-?[2-9]\d{2}-?\d{4}$/); 67591 }, 67592 message: 'Please specify a valid phone number.' 67593}; 67594 67595kv.rules['equal'] = { 67596 validator: function (val, params) { 67597 var otherValue = params; 67598 return val === kv.utils.getValue(otherValue); 67599 }, 67600 message: 'Values must equal.' 67601}; 67602 67603kv.rules['notEqual'] = { 67604 validator: function (val, params) { 67605 var otherValue = params; 67606 return val !== kv.utils.getValue(otherValue); 67607 }, 67608 message: 'Please choose another value.' 67609}; 67610 67611//unique in collection 67612// options are: 67613// collection: array or function returning (observable) array 67614// in which the value has to be unique 67615// valueAccessor: function that returns value from an object stored in collection 67616// if it is null the value is compared directly 67617// external: set to true when object you are validating is automatically updating collection 67618kv.rules['unique'] = { 67619 validator: function (val, options) { 67620 var c = kv.utils.getValue(options.collection), 67621 external = kv.utils.getValue(options.externalValue), 67622 counter = 0; 67623 67624 if (!val || !c) { return true; } 67625 67626 koUtils.arrayFilter(c, function (item) { 67627 if (val === (options.valueAccessor ? options.valueAccessor(item) : item)) { counter++; } 67628 }); 67629 // if value is external even 1 same value in collection means the value is not unique 67630 return counter < (!!external ? 1 : 2); 67631 }, 67632 message: 'Please make sure the value is unique.' 67633}; 67634 67635 67636//now register all of these! 67637(function () { 67638 kv.registerExtenders(); 67639}()); 67640;// The core binding handler 67641// this allows us to setup any value binding that internally always 67642// performs the same functionality 67643ko.bindingHandlers['validationCore'] = (function () { 67644 67645 return { 67646 init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { 67647 var config = kv.utils.getConfigOptions(element); 67648 var observable = valueAccessor(); 67649 67650 // parse html5 input validation attributes, optional feature 67651 if (config.parseInputAttributes) { 67652 kv.utils.async(function () { kv.parseInputValidationAttributes(element, valueAccessor); }); 67653 } 67654 67655 // if requested insert message element and apply bindings 67656 if (config.insertMessages && kv.utils.isValidatable(observable)) { 67657 67658 // insert the <span></span> 67659 var validationMessageElement = kv.insertValidationMessage(element); 67660 67661 // if we're told to use a template, make sure that gets rendered 67662 if (config.messageTemplate) { 67663 ko.renderTemplate(config.messageTemplate, { field: observable }, null, validationMessageElement, 'replaceNode'); 67664 } else { 67665 ko.applyBindingsToNode(validationMessageElement, { validationMessage: observable }); 67666 } 67667 } 67668 67669 // write the html5 attributes if indicated by the config 67670 if (config.writeInputAttributes && kv.utils.isValidatable(observable)) { 67671 67672 kv.writeInputValidationAttributes(element, valueAccessor); 67673 } 67674 67675 // if requested, add binding to decorate element 67676 if (config.decorateInputElement && kv.utils.isValidatable(observable)) { 67677 ko.applyBindingsToNode(element, { validationElement: observable }); 67678 } 67679 } 67680 }; 67681 67682}()); 67683 67684// override for KO's default 'value', 'checked', 'textInput' and selectedOptions bindings 67685kv.makeBindingHandlerValidatable("value"); 67686kv.makeBindingHandlerValidatable("checked"); 67687if (ko.bindingHandlers.textInput) { 67688 kv.makeBindingHandlerValidatable("textInput"); 67689} 67690kv.makeBindingHandlerValidatable("selectedOptions"); 67691 67692 67693ko.bindingHandlers['validationMessage'] = { // individual error message, if modified or post binding 67694 update: function (element, valueAccessor) { 67695 var obsv = valueAccessor(), 67696 config = kv.utils.getConfigOptions(element), 67697 val = unwrap(obsv), 67698 msg = null, 67699 isModified = false, 67700 isValid = false; 67701 67702 if (obsv === null || typeof obsv === 'undefined') { 67703 throw new Error('Cannot bind validationMessage to undefined value. data-bind expression: ' + 67704 element.getAttribute('data-bind')); 67705 } 67706 67707 if (!obsv.isValid || !obsv.isModified) { 67708 throw new Error("Observable is not validatable"); 67709 } 67710 67711 isModified = obsv.isModified(); 67712 isValid = obsv.isValid(); 67713 67714 var error = null; 67715 if (!config.messagesOnModified || isModified) { 67716 error = isValid ? null : obsv.error; 67717 } 67718 67719 var isVisible = !config.messagesOnModified || isModified ? !isValid : false; 67720 var isCurrentlyVisible = element.style.display !== "none"; 67721 67722 if (config.allowHtmlMessages) { 67723 koUtils.setHtml(element, error); 67724 } else { 67725 ko.bindingHandlers.text.update(element, function () { return error; }); 67726 } 67727 67728 if (isCurrentlyVisible && !isVisible) { 67729 element.style.display = 'none'; 67730 } else if (!isCurrentlyVisible && isVisible) { 67731 element.style.display = ''; 67732 } 67733 } 67734}; 67735 67736ko.bindingHandlers['validationElement'] = { 67737 update: function (element, valueAccessor, allBindingsAccessor) { 67738 var obsv = valueAccessor(), 67739 config = kv.utils.getConfigOptions(element), 67740 val = unwrap(obsv), 67741 msg = null, 67742 isModified = false, 67743 isValid = false; 67744 67745 if (obsv === null || typeof obsv === 'undefined') { 67746 throw new Error('Cannot bind validationElement to undefined value. data-bind expression: ' + 67747 element.getAttribute('data-bind')); 67748 } 67749 67750 if (!obsv.isValid || !obsv.isModified) { 67751 throw new Error("Observable is not validatable"); 67752 } 67753 67754 isModified = obsv.isModified(); 67755 isValid = obsv.isValid(); 67756 67757 // create an evaluator function that will return something like: 67758 // css: { validationElement: true } 67759 var cssSettingsAccessor = function () { 67760 var css = {}; 67761 67762 var shouldShow = ((!config.decorateElementOnModified || isModified) ? !isValid : false); 67763 67764 // css: { validationElement: false } 67765 css[config.errorElementClass] = shouldShow; 67766 67767 return css; 67768 }; 67769 67770 //add or remove class on the element; 67771 ko.bindingHandlers.css.update(element, cssSettingsAccessor, allBindingsAccessor); 67772 if (!config.errorsAsTitle) { return; } 67773 67774 ko.bindingHandlers.attr.update(element, function () { 67775 var 67776 hasModification = !config.errorsAsTitleOnModified || isModified, 67777 title = kv.utils.getOriginalElementTitle(element); 67778 67779 if (hasModification && !isValid) { 67780 return { title: obsv.error, 'data-orig-title': title }; 67781 } else if (!hasModification || isValid) { 67782 return { title: title, 'data-orig-title': null }; 67783 } 67784 }); 67785 } 67786}; 67787 67788// ValidationOptions: 67789// This binding handler allows you to override the initial config by setting any of the options for a specific element or context of elements 67790// 67791// Example: 67792// <div data-bind="validationOptions: { insertMessages: true, messageTemplate: 'customTemplate', errorMessageClass: 'mySpecialClass'}"> 67793// <input type="text" data-bind="value: someValue"/> 67794// <input type="text" data-bind="value: someValue2"/> 67795// </div> 67796ko.bindingHandlers['validationOptions'] = (function () { 67797 return { 67798 init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { 67799 var options = unwrap(valueAccessor()); 67800 if (options) { 67801 var newConfig = extend({}, kv.configuration); 67802 extend(newConfig, options); 67803 67804 //store the validation options on the node so we can retrieve it later 67805 kv.utils.setDomData(element, newConfig); 67806 } 67807 } 67808 }; 67809}()); 67810;// Validation Extender: 67811// This is for creating custom validation logic on the fly 67812// Example: 67813// var test = ko.observable('something').extend{( 67814// validation: { 67815// validator: function(val, someOtherVal){ 67816// return true; 67817// }, 67818// message: "Something must be really wrong!', 67819// params: true 67820// } 67821// )}; 67822ko.extenders['validation'] = function (observable, rules) { // allow single rule or array 67823 forEach(kv.utils.isArray(rules) ? rules : [rules], function (rule) { 67824 // the 'rule' being passed in here has no name to identify a core Rule, 67825 // so we add it as an anonymous rule 67826 // If the developer is wanting to use a core Rule, but use a different message see the 'addExtender' logic for examples 67827 kv.addAnonymousRule(observable, rule); 67828 }); 67829 return observable; 67830}; 67831 67832//This is the extender that makes a Knockout Observable also 'Validatable' 67833//examples include: 67834// 1. var test = ko.observable('something').extend({validatable: true}); 67835// this will ensure that the Observable object is setup properly to respond to rules 67836// 67837// 2. test.extend({validatable: false}); 67838// this will remove the validation properties from the Observable object should you need to do that. 67839ko.extenders['validatable'] = function (observable, options) { 67840 if (!kv.utils.isObject(options)) { 67841 options = { enable: options }; 67842 } 67843 67844 if (!('enable' in options)) { 67845 options.enable = true; 67846 } 67847 67848 if (options.enable && !kv.utils.isValidatable(observable)) { 67849 var config = kv.configuration.validate || {}; 67850 var validationOptions = { 67851 throttleEvaluation : options.throttle || config.throttle 67852 }; 67853 67854 observable.error = ko.observable(null); // holds the error message, we only need one since we stop processing validators when one is invalid 67855 67856 // observable.rules: 67857 // ObservableArray of Rule Contexts, where a Rule Context is simply the name of a rule and the params to supply to it 67858 // 67859 // Rule Context = { rule: '<rule name>', params: '<passed in params>', message: '<Override of default Message>' } 67860 observable.rules = ko.observableArray(); //holds the rule Contexts to use as part of validation 67861 67862 //in case async validation is occurring 67863 observable.isValidating = ko.observable(false); 67864 67865 //the true holder of whether the observable is valid or not 67866 observable.__valid__ = ko.observable(true); 67867 67868 observable.isModified = ko.observable(false); 67869 67870 // a semi-protected observable 67871 observable.isValid = ko.computed(observable.__valid__); 67872 67873 //manually set error state 67874 observable.setError = function (error) { 67875 var previousError = observable.error.peek(); 67876 var previousIsValid = observable.__valid__.peek(); 67877 67878 observable.error(error); 67879 observable.__valid__(false); 67880 67881 if (previousError !== error && !previousIsValid) { 67882 // if the observable was not valid before then isValid will not mutate, 67883 // hence causing any grouping to not display the latest error. 67884 observable.isValid.notifySubscribers(); 67885 } 67886 }; 67887 67888 //manually clear error state 67889 observable.clearError = function () { 67890 observable.error(null); 67891 observable.__valid__(true); 67892 return observable; 67893 }; 67894 67895 //subscribe to changes in the observable 67896 var h_change = observable.subscribe(function () { 67897 observable.isModified(true); 67898 }); 67899 67900 // we use a computed here to ensure that anytime a dependency changes, the 67901 // validation logic evaluates 67902 var h_obsValidationTrigger = ko.computed(extend({ 67903 read: function () { 67904 var obs = observable(), 67905 ruleContexts = observable.rules(); 67906 67907 kv.validateObservable(observable); 67908 67909 return true; 67910 } 67911 }, validationOptions)); 67912 67913 extend(h_obsValidationTrigger, validationOptions); 67914 67915 observable._disposeValidation = function () { 67916 //first dispose of the subscriptions 67917 observable.isValid.dispose(); 67918 observable.rules.removeAll(); 67919 if (observable.isModified.getSubscriptionsCount() > 0) { 67920 observable.isModified._subscriptions['change'] = []; 67921 } 67922 if (observable.isValidating.getSubscriptionsCount() > 0) { 67923 observable.isValidating._subscriptions['change'] = []; 67924 } 67925 if (observable.__valid__.getSubscriptionsCount() > 0) { 67926 observable.__valid__._subscriptions['change'] = []; 67927 } 67928 h_change.dispose(); 67929 h_obsValidationTrigger.dispose(); 67930 67931 delete observable['rules']; 67932 delete observable['error']; 67933 delete observable['isValid']; 67934 delete observable['isValidating']; 67935 delete observable['__valid__']; 67936 delete observable['isModified']; 67937 }; 67938 } else if (options.enable === false && observable._disposeValidation) { 67939 observable._disposeValidation(); 67940 } 67941 return observable; 67942}; 67943 67944function validateSync(observable, rule, ctx) { 67945 //Execute the validator and see if its valid 67946 if (!rule.validator(observable(), (ctx.params === undefined ? true : unwrap(ctx.params)))) { // default param is true, eg. required = true 67947 67948 //not valid, so format the error message and stick it in the 'error' variable 67949 observable.setError(kv.formatMessage( 67950 ctx.message || rule.message, 67951 unwrap(ctx.params), 67952 observable)); 67953 return false; 67954 } else { 67955 return true; 67956 } 67957} 67958 67959function validateAsync(observable, rule, ctx) { 67960 observable.isValidating(true); 67961 67962 var callBack = function (valObj) { 67963 var isValid = false, 67964 msg = ''; 67965 67966 if (!observable.__valid__()) { 67967 67968 // since we're returning early, make sure we turn this off
67969 observable.isValidating(false); 67970 67971 return; //if its already NOT valid, don't add to that 67972 } 67973 67974 //we were handed back a complex object 67975 if (valObj['message']) { 67976 isValid = valObj.isValid; 67977 msg = valObj.message; 67978 } else { 67979 isValid = valObj; 67980 } 67981 67982 if (!isValid) { 67983 //not valid, so format the error message and stick it in the 'error' variable 67984 observable.error(kv.formatMessage( 67985 msg || ctx.message || rule.message, 67986 unwrap(ctx.params), 67987 observable)); 67988 observable.__valid__(isValid); 67989 } 67990 67991 // tell it that we're done 67992 observable.isValidating(false); 67993 }; 67994 67995 //fire the validator and hand it the callback 67996 rule.validator(observable(), unwrap(ctx.params || true), callBack); 67997} 67998 67999kv.validateObservable = function (observable) { 68000 var i = 0, 68001 rule, // the rule validator to execute 68002 ctx, // the current Rule Context for the loop 68003 ruleContexts = observable.rules(), //cache for iterator 68004 len = ruleContexts.length; //cache for iterator 68005 68006 for (; i < len; i++) { 68007 68008 //get the Rule Context info to give to the core Rule 68009 ctx = ruleContexts[i]; 68010 68011 // checks an 'onlyIf' condition 68012 if (ctx.condition && !ctx.condition()) { 68013 continue; 68014 } 68015 68016 //get the core Rule to use for validation 68017 rule = ctx.rule ? kv.rules[ctx.rule] : ctx; 68018 68019 if (rule['async'] || ctx['async']) { 68020 //run async validation 68021 validateAsync(observable, rule, ctx); 68022 68023 } else { 68024 //run normal sync validation 68025 if (!validateSync(observable, rule, ctx)) { 68026 return false; //break out of the loop 68027 } 68028 } 68029 } 68030 //finally if we got this far, make the observable valid again! 68031 observable.clearError(); 68032 return true; 68033}; 68034; 68035//quick function to override rule messages 68036kv.localize = function (msgTranslations) { 68037 68038 var msg, rule; 68039 68040 //loop the properties in the object and assign the msg to the rule 68041 for (rule in msgTranslations) { 68042 if (kv.rules.hasOwnProperty(rule)) { 68043 kv.rules[rule].message = msgTranslations[rule]; 68044 } 68045 } 68046};;/** 68047 * Possible invocations: 68048 * applyBindingsWithValidation(viewModel) 68049 * applyBindingsWithValidation(viewModel, options) 68050 * applyBindingsWithValidation(viewModel, rootNode) 68051 * applyBindingsWithValidation(viewModel, rootNode, options) 68052 */ 68053ko.applyBindingsWithValidation = function (viewModel, rootNode, options) { 68054 var node = document.body, 68055 config; 68056 68057 if (rootNode && rootNode.nodeType) { 68058 node = rootNode; 68059 config = options; 68060 } 68061 else { 68062 config = rootNode; 68063 } 68064 68065 kv.init(); 68066 68067 if (config) { 68068 config = extend(extend({}, kv.configuration), config); 68069 kv.utils.setDomData(node, config); 68070 } 68071 68072 ko.applyBindings(viewModel, node); 68073}; 68074 68075//override the original applyBindings so that we can ensure all new rules and what not are correctly registered 68076var origApplyBindings = ko.applyBindings; 68077ko.applyBindings = function (viewModel, rootNode) { 68078 68079 kv.init(); 68080 68081 origApplyBindings(viewModel, rootNode); 68082}; 68083 68084ko.validatedObservable = function (initialValue, options) { 68085 if (!options && !kv.utils.isObject(initialValue)) { 68086 return ko.observable(initialValue).extend({ validatable: true }); 68087 } 68088 68089 var obsv = ko.observable(initialValue); 68090 obsv.errors = kv.group(kv.utils.isObject(initialValue) ? initialValue : {}, options); 68091 obsv.isValid = ko.observable(obsv.errors().length === 0); 68092 68093 if (ko.isObservable(obsv.errors)) { 68094 obsv.errors.subscribe(function(errors) { 68095 obsv.isValid(errors.length === 0); 68096 }); 68097 } 68098 else { 68099 ko.computed(obsv.errors).subscribe(function (errors) { 68100 obsv.isValid(errors.length === 0); 68101 }); 68102 } 68103 68104 obsv.subscribe(function(newValue) { 68105 if (!kv.utils.isObject(newValue)) { 68106 /* 68107 * The validation group works on objects. 68108 * Since the new value is a primitive (scalar, null or undefined) we need 68109 * to create an empty object to pass along. 68110 */ 68111 newValue = {}; 68112 } 68113 // Force the group to refresh 68114 obsv.errors._updateState(newValue); 68115 obsv.isValid(obsv.errors().length === 0); 68116 }); 68117 68118 return obsv; 68119}; 68120;})); 68121(function(window, factory) { 68122 var lazySizes = factory(window, window.document); 68123 window.lazySizes = lazySizes; 68124 if(typeof module == 'object' && module.exports){ 68125 module.exports = lazySizes; 68126 } else if (typeof define == 'function' && define.amd) { 68127 define('lazysizes',lazySizes); 68128 } 68129}(window, function(window, document) { 68130 'use strict'; 68131 /*jshint eqnull:true */ 68132 if(!document.getElementsByClassName){return;} 68133 68134 var lazySizesConfig; 68135 68136 var docElem = document.documentElement; 68137 68138 var addEventListener = window.addEventListener; 68139 68140 var regPicture = /^picture$/i; 68141 68142 var loadEvents = ['load', 'error', 'lazyincluded', '_lazyloaded']; 68143 68144 var hasClass = function(ele, cls) { 68145 var reg = new RegExp('(\\s|^)'+cls+'(\\s|$)'); 68146 return ele.className.match(reg) && reg;
68147 }; 68148 68149 var addClass = function(ele, cls) { 68150 if (!hasClass(ele, cls)){ 68151 ele.className += ' '+cls; 68152 } 68153 }; 68154 68155 var removeClass = function(ele, cls) { 68156 var reg; 68157 if ((reg = hasClass(ele,cls))) { 68158 ele.className = ele.className.replace(reg, ' '); 68159 } 68160 }; 68161 68162 var addRemoveLoadEvents = function(dom, fn, add){ 68163 var action = add ? 'addEventListener' : 'removeEventListener'; 68164 if(add){ 68165 addRemoveLoadEvents(dom, fn); 68166 } 68167 loadEvents.forEach(function(evt){ 68168 dom[action](evt, fn); 68169 }); 68170 }; 68171 68172 var triggerEvent = function(elem, name, details, noBubbles, noCanceable){ 68173 var event = document.createEvent('Event'); 68174 68175 event.initEvent(name, !noBubbles, !noCanceable); 68176 68177 event.details = details || {}; 68178 68179 elem.dispatchEvent(event); 68180 return event; 68181 }; 68182 68183 var updatePolyfill = function (el, full){ 68184 var polyfill; 68185 if(!window.HTMLPictureElement){ 68186 if( ( polyfill = (window.picturefill || window.respimage || lazySizesConfig.pf) ) ){ 68187 polyfill({reevaluate: true, reparse: true, elements: [el]}); 68188 } else if(full && full.src){ 68189 el.src = full.src; 68190 } 68191 } 68192 }; 68193 68194 var getCSS = function (elem, style){ 68195 return getComputedStyle(elem, null)[style]; 68196 }; 68197 68198 var getWidth = function(elem, parent){ 68199 var width = elem.offsetWidth; 68200 68201 while(width < lazySizesConfig.minSize && parent && !elem._lazysizesWidth){ 68202 width = parent.offsetWidth; 68203 parent = parent.parentNode; 68204 } 68205 68206 return width; 68207 }; 68208 68209 var throttle = function(fn){ 68210 var run, timer; 68211 var main = function(){ 68212 if(run){ 68213 run = false; 68214 fn(); 68215 } 68216 }; 68217 var handleVisibility = function(){ 68218 clearInterval(timer); 68219 if(!document.hidden){ 68220 main(); 68221 timer = setInterval(main, 51); 68222 } 68223 }; 68224 68225 document.addEventListener('visibilitychange', handleVisibility); 68226 handleVisibility(); 68227 68228 return function(force){ 68229 run = true; 68230 if(force === true){ 68231 main(); 68232 } 68233 }; 68234 }; 68235 68236 var loader = (function(){ 68237 var lazyloadElems, preloadElems, isCompleted, resetPreloadingTimer, loadMode; 68238 68239 var eLvW, elvH, eLtop, eLleft, eLright, eLbottom; 68240 68241 var defaultExpand, preloadExpand; 68242 68243 var regImg = /^img$/i; 68244 var regIframe = /^iframe$/i; 68245 68246 var supportScroll = ('onscroll' in window) && !(/glebot/.test(navigator.userAgent)); 68247 68248 var shrinkExpand = 0; 68249 var currentExpand = 0; 68250 var lowRuns = 0; 68251 68252 var isLoading = 0; 68253 68254 var checkElementsIndex = 0; 68255 68256 var resetPreloading = function(e){ 68257 isLoading--; 68258 if(e && e.target){ 68259 addRemoveLoadEvents(e.target, resetPreloading); 68260 } 68261 68262 if(!e || isLoading < 0 || !e.target){ 68263 isLoading = 0; 68264 } 68265 }; 68266 68267 var isNestedVisible = function(elem, elemExpand){ 68268 var outerRect; 68269 var parent = elem; 68270 var visible = getCSS(elem, 'visibility') != 'hidden'; 68271 68272 eLtop -= elemExpand; 68273 eLbottom += elemExpand; 68274 eLleft -= elemExpand; 68275 eLright += elemExpand; 68276 68277 while(visible && (parent = parent.offsetParent)){ 68278 visible = (isCompleted && isLoading < 2) || ((getCSS(parent, 'opacity') || 1) > 0); 68279 68280 if(visible && getCSS(parent, 'overflow') != 'visible'){ 68281 outerRect = parent.getBoundingClientRect(); 68282 visible = eLright > outerRect.left && 68283 eLleft < outerRect.right && 68284 eLbottom > outerRect.top - 1 && 68285 eLtop < outerRect.bottom + 1 68286 ; 68287 } 68288 } 68289 return visible; 68290 }; 68291 68292 var checkElements = function() { 68293 var i, start, rect, autoLoadElem, loadedSomething, elemExpand, elemNegativeExpand, elemExpandVal, beforeExpandVal; 68294 68295 var eLlen = lazyloadElems.length; 68296 68297 if(eLlen && (loadMode = lazySizesConfig.loadMode)){ 68298 start = Date.now(); 68299 68300 i = checkElementsIndex; 68301 68302 lowRuns++; 68303 68304 if(currentExpand < preloadExpand && isLoading < 1 && lowRuns > 5 && loadMode > 2){ 68305 currentExpand = preloadExpand; 68306 lowRuns = 0; 68307 } else if(currentExpand != defaultExpand && loadMode > 1 && lowRuns > 4){ 68308 currentExpand = defaultExpand; 68309 } else { 68310 currentExpand = shrinkExpand; 68311 } 68312 68313 for(; i < eLlen; i++, checkElementsIndex++){ 68314 68315 if(!lazyloadElems[i] || lazyloadElems[i]._lazyRace){continue;} 68316 68317 if(!supportScroll){unveilElement(lazyloadElems[i]);continue;} 68318 68319 if(!(elemExpandVal = lazyloadElems[i].getAttribute('data-expand')) || !(elemExpand = elemExpandVal * 1)){ 68320 elemExpand = currentExpand; 68321 } 68322 68323 if(isLoading > 6 && (!elemExpandVal || ('src' in lazyloadElems[i]))){continue;} 68324
68325 if(elemExpand > shrinkExpand && (loadMode < 2 || isLoading > 3)){ 68326 elemExpand = shrinkExpand; 68327 } 68328 68329 if(beforeExpandVal !== elemExpand){ 68330 eLvW = innerWidth + elemExpand; 68331 elvH = innerHeight + elemExpand; 68332 elemNegativeExpand = elemExpand * -1; 68333 beforeExpandVal = elemExpand; 68334 } 68335 68336 rect = lazyloadElems[i].getBoundingClientRect(); 68337 68338 if ((eLbottom = rect.bottom) >= elemNegativeExpand && 68339 (eLtop = rect.top) <= elvH && 68340 (eLright = rect.right) >= elemNegativeExpand && 68341 (eLleft = rect.left) <= eLvW && 68342 (eLbottom || eLright || eLleft || eLtop) && 68343 ((isCompleted && currentExpand < preloadExpand && isLoading < 3 && lowRuns < 4 && !elemExpandVal && loadMode > 2) || isNestedVisible(lazyloadElems[i], elemExpand))){ 68344 checkElementsIndex--; 68345 start += 2; 68346 unveilElement(lazyloadElems[i]); 68347 loadedSomething = true; 68348 } else { 68349 if(Date.now() - start > 3){ 68350 checkElementsIndex++; 68351 throttledCheckElements(); 68352 return; 68353 } 68354 68355 if(!loadedSomething && isCompleted && !autoLoadElem && 68356 isLoading < 3 && lowRuns < 4 && loadMode > 2 && 68357 (preloadElems[0] || lazySizesConfig.preloadAfterLoad) && 68358 (preloadElems[0] || (!elemExpandVal && ((eLbottom || eLright || eLleft || eLtop) || lazyloadElems[i].getAttribute(lazySizesConfig.sizesAttr) != 'auto')))){ 68359 autoLoadElem = preloadElems[0] || lazyloadElems[i]; 68360 } 68361 } 68362 } 68363 68364 checkElementsIndex = 0; 68365 68366 if(autoLoadElem && !loadedSomething){ 68367 unveilElement(autoLoadElem); 68368 } 68369 } 68370 }; 68371 68372 var throttledCheckElements = throttle(checkElements); 68373 68374 var switchLoadingClass = function(e){ 68375 addClass(e.target, lazySizesConfig.loadedClass); 68376 removeClass(e.target, lazySizesConfig.loadingClass); 68377 addRemoveLoadEvents(e.target, switchLoadingClass); 68378 }; 68379 68380 var changeIframeSrc = function(elem, src){ 68381 try { 68382 elem.contentWindow.location.replace(src); 68383 } catch(e){ 68384 elem.setAttribute('src', src); 68385 } 68386 }; 68387 68388 var unveilElement = function (elem, force){ 68389 var sources, i, len, sourceSrcset, src, srcset, parent, isPicture, event, firesLoad, customMedia; 68390 68391 var curSrc = elem.currentSrc || elem.src; 68392 var isImg = regImg.test(elem.nodeName); 68393 68394 //allow using sizes="auto", but don't use. it's invalid. Use data-sizes="auto" or a valid value for sizes instead (i.e.: sizes="80vw") 68395 var sizes = elem.getAttribute(lazySizesConfig.sizesAttr) || elem.getAttribute('sizes'); 68396 var isAuto = sizes == 'auto'; 68397 68398 if( (isAuto || !isCompleted) && isImg && curSrc && !elem.complete && !hasClass(elem, lazySizesConfig.errorClass)){return;} 68399 68400 elem._lazyRace = true; 68401 68402 if(!(event = triggerEvent(elem, 'lazybeforeunveil', {force: !!force})).defaultPrevented){ 68403 68404 if(sizes){ 68405 if(isAuto){ 68406 autoSizer.updateElem(elem, true); 68407 } else { 68408 elem.setAttribute('sizes', sizes); 68409 } 68410 } 68411 68412 srcset = elem.getAttribute(lazySizesConfig.srcsetAttr); 68413 src = elem.getAttribute(lazySizesConfig.srcAttr); 68414 68415 if(isImg) { 68416 parent = elem.parentNode; 68417 isPicture = regPicture.test(parent.nodeName || ''); 68418 } 68419 68420 firesLoad = event.details.firesLoad || (('src' in elem) && (srcset || src || isPicture)); 68421 68422 if(firesLoad){ 68423 isLoading++; 68424 addRemoveLoadEvents(elem, resetPreloading, true); 68425 clearTimeout(resetPreloadingTimer); 68426 resetPreloadingTimer = setTimeout(resetPreloading, 3000); 68427 } 68428 68429 if(isPicture){ 68430 sources = parent.getElementsByTagName('source'); 68431 for(i = 0, len = sources.length; i < len; i++){ 68432 if( (customMedia = lazySizesConfig.customMedia[sources[i].getAttribute('data-media') || sources[i].getAttribute('media')]) ){ 68433 sources[i].setAttribute('media', customMedia); 68434 } 68435 sourceSrcset = sources[i].getAttribute(lazySizesConfig.srcsetAttr); 68436 if(sourceSrcset){ 68437 sources[i].setAttribute('srcset', sourceSrcset); 68438 } 68439 } 68440 } 68441 68442 if(srcset){ 68443 elem.setAttribute('srcset', srcset); 68444 } else if(src){ 68445 if(regIframe.test(elem.nodeName)){ 68446 changeIframeSrc(elem, src); 68447 } else { 68448 elem.setAttribute('src', src); 68449 } 68450 } 68451 68452 addClass(elem, lazySizesConfig.loadingClass); 68453 addRemoveLoadEvents(elem, switchLoadingClass, true); 68454 } 68455 68456 setTimeout(function(){ 68457 if(elem._lazyRace){ 68458 delete elem._lazyRace; 68459 } 68460 68461 if(sizes == 'auto'){ 68462 addClass(elem, lazySizesConfig.autosizesClass); 68463 } 68464 68465 if(srcset || isPicture){ 68466 updatePolyfill(elem, {src: src}); 68467 } 68468 68469 removeClass(elem, lazySizesConfig.lazyClass); 68470 68471 //remove curSrc == (elem.currentSrc || elem.src) it's a workaround for FF. see: https://bugzilla.mozilla.org/show_bug.cgi?id=608261 68472 if( !firesLoad || (elem.complete && curSrc == (elem.currentSrc || elem.src)) ){ 68473 if(firesLoad){ 68474 resetPreloading(event); 68475 } 68476 switchLoadingClass(event); 68477 } 68478 elem = null; 68479 }); 68480 }; 68481 68482 var onload = function(){ 68483 var scrollTimer; 68484 var afterScroll = function(){ 68485 lazySizesConfig.loadMode = 3; 68486 throttledCheckElements(); 68487 }; 68488 68489 isCompleted = true; 68490 lowRuns += 8; 68491 68492 lazySizesConfig.loadMode = 3; 68493 throttledCheckElements(true); 68494 68495 addEventListener('scroll', function(){ 68496 if(lazySizesConfig.loadMode == 3){ 68497 lazySizesConfig.loadMode = 2; 68498 } 68499 clearTimeout(scrollTimer); 68500 scrollTimer = setTimeout(afterScroll, 66); 68501 }, true); 68502 }; 68503 68504 return { 68505 _: function(){ 68506 68507 lazyloadElems = document.getElementsByClassName(lazySizesConfig.lazyClass); 68508 preloadElems = document.getElementsByClassName(lazySizesConfig.lazyClass + ' ' + lazySizesConfig.preloadClass); 68509 68510 defaultExpand = lazySizesConfig.expand; 68511 preloadExpand = defaultExpand * lazySizesConfig.expFactor; 68512 68513 addEventListener('scroll', throttledCheckElements, true); 68514 68515 addEventListener('resize', throttledCheckElements, true); 68516 68517 if(window.MutationObserver){ 68518 new MutationObserver( throttledCheckElements ).observe( docElem, {childList: true, subtree: true, attributes: true} ); 68519 } else { 68520 docElem.addEventListener('DOMNodeInserted', throttledCheckElements, true); 68521 docElem.addEventListener('DOMAttrModified', throttledCheckElements, true); 68522 setInterval(throttledCheckElements, 3000); 68523 } 68524 68525 addEventListener('hashchange', throttledCheckElements, true); 68526 68527 ['transitionstart', 'transitionend', 'load', 'focus', 'mouseover', 'animationend', 'click'].forEach(function(name){ 68528 document.addEventListener(name, throttledCheckElements, true); 68529 }); 68530 68531 if(!(isCompleted = /d$|^c/.test(document.readyState))){ 68532 addEventListener('load', onload); 68533 document.addEventListener('DOMContentLoaded', throttledCheckElements); 68534 } else { 68535 onload(); 68536 } 68537 68538 throttledCheckElements(lazyloadElems.length > 0); 68539 }, 68540 checkElems: throttledCheckElements, 68541 unveil: unveilElement 68542 }; 68543 })(); 68544 68545 68546 var autoSizer = (function(){ 68547 var autosizesElems; 68548 68549 var sizeElement = function (elem, dataAttr){ 68550 var width, sources, i, len, event; 68551 var parent = elem.parentNode; 68552 68553 if(parent){ 68554 width = getWidth(elem, parent); 68555 event = triggerEvent(elem, 'lazybeforesizes', {width: width, dataAttr: !!dataAttr}); 68556 68557 if(!event.defaultPrevented){ 68558 width = event.details.width; 68559 68560 if(width && width !== elem._lazysizesWidth){ 68561 elem._lazysizesWidth = width; 68562 width += 'px'; 68563 elem.setAttribute('sizes', width); 68564 68565 if(regPicture.test(parent.nodeName || '')){ 68566 sources = parent.getElementsByTagName('source'); 68567 for(i = 0, len = sources.length; i < len; i++){ 68568 sources[i].setAttribute('sizes', width); 68569 } 68570 } 68571 68572 if(!event.details.dataAttr){ 68573 updatePolyfill(elem, event.details); 68574 } 68575 } 68576 } 68577 } 68578 }; 68579 68580 var updateElementsSizes = function(){ 68581 var i; 68582 var len = autosizesElems.length; 68583 if(len){ 68584 i = 0; 68585
68586 for(; i < len; i++){ 68587 sizeElement(autosizesElems[i]); 68588 } 68589 } 68590 }; 68591 68592 var throttledUpdateElementsSizes = throttle(updateElementsSizes); 68593 68594 return { 68595 _: function(){ 68596 autosizesElems = document.getElementsByClassName(lazySizesConfig.autosizesClass); 68597 addEventListener('resize', throttledUpdateElementsSizes); 68598 }, 68599 checkElems: throttledUpdateElementsSizes, 68600 updateElem: sizeElement 68601 }; 68602 })(); 68603 68604 var init = function(){ 68605 if(!init.i){ 68606 init.i = true; 68607 autoSizer._(); 68608 loader._(); 68609 } 68610 }; 68611 68612 (function(){ 68613 var prop; 68614 var lazySizesDefaults = { 68615 lazyClass: 'lazyload', 68616 loadedClass: 'lazyloaded', 68617 loadingClass: 'lazyloading', 68618 preloadClass: 'lazypreload', 68619 errorClass: 'lazyerror', 68620 autosizesClass: 'lazyautosizes', 68621 srcAttr: 'data-src', 68622 srcsetAttr: 'data-srcset', 68623 sizesAttr: 'data-sizes', 68624 //preloadAfterLoad: false, 68625 minSize: 50, 68626 customMedia: {}, 68627 init: true, 68628 expFactor: 2, 68629 expand: 300, 68630 loadMode: 2 68631 }; 68632 68633 lazySizesConfig = window.lazySizesConfig || {}; 68634 68635 for(prop in lazySizesDefaults){ 68636 if(!(prop in lazySizesConfig)){ 68637 lazySizesConfig[prop] = lazySizesDefaults[prop]; 68638 } 68639 } 68640 68641 window.lazySizesConfig = lazySizesConfig; 68642 68643 setTimeout(function(){ 68644 if(lazySizesConfig.init){ 68645 init(); 68646 } 68647 }); 68648 })(); 68649 68650 return { 68651 cfg: lazySizesConfig, 68652 autoSizer: autoSizer, 68653 loader: loader, 68654 init: init, 68655 uP: updatePolyfill, 68656 aC: addClass, 68657 rC: removeClass, 68658 hC: hasClass, 68659 fire: triggerEvent, 68660 gW: getWidth 68661 }; 68662})); 68663 68664/*! 68665 * Modernizr v2.7.2 68666 * www.modernizr.com 68667 * 68668 * Copyright (c) Faruk Ates, Paul Irish, Alex Sexton 68669 * Available under the BSD and MIT licenses: www.modernizr.com/license/ 68670 */ 68671 68672/* 68673 * Modernizr tests which native CSS3 and HTML5 features are available in 68674 * the current UA and makes the results available to you in two ways: 68675 * as properties on a global Modernizr object, and as classes on the 68676 * <html> element. This information allows you to progressively enhance 68677 * your pages with a granular level of control over the experience. 68678 * 68679 * Modernizr has an optional (not included) conditional resource loader 68680 * called Modernizr.load(), based on Yepnope.js (yepnopejs.com). 68681 * To get a build that includes Modernizr.load(), as well as choosing 68682 * which tests to include, go to www.modernizr.com/download/ 68683 * 68684 * Authors Faruk Ates, Paul Irish, Alex Sexton 68685 * Contributors Ryan Seddon, Ben Alman 68686 */ 68687 68688window.Modernizr = (function( window, document, undefined ) { 68689 68690 var version = '2.7.2', 68691 68692 Modernizr = {}, 68693 68694 /*>>cssclasses*/ 68695 // option for enabling the HTML classes to be added 68696 enableClasses = true, 68697 /*>>cssclasses*/ 68698 68699 docElement = document.documentElement, 68700 68701 /** 68702 * Create our "modernizr" element that we do most feature tests on. 68703 */ 68704 mod = 'modernizr', 68705 modElem = document.createElement(mod), 68706 mStyle = modElem.style, 68707 68708 /** 68709 * Create the input element for various Web Forms feature tests. 68710 */ 68711 inputElem /*>>inputelem*/ = document.createElement('input') /*>>inputelem*/ , 68712 68713 /*>>smile*/ 68714 smile = ':)', 68715 /*>>smile*/ 68716 68717 toString = {}.toString, 68718 68719 // TODO :: make the prefixes more granular 68720 /*>>prefixes*/ 68721 // List of property values to set for css tests. See ticket #21 68722 prefixes = ' -webkit- -moz- -o- -ms- '.split(' '), 68723 /*>>prefixes*/ 68724 68725 /*>>domprefixes*/ 68726 // Following spec is to expose vendor-specific style properties as: 68727 // elem.style.WebkitBorderRadius 68728 // and the following would be incorrect: 68729 // elem.style.webkitBorderRadius 68730 68731 // Webkit ghosts their properties in lowercase but Opera & Moz do not. 68732 // Microsoft uses a lowercase `ms` instead of the correct `Ms` in IE8+ 68733 // erik.eae.net/archives/2008/03/10/21.48.10/ 68734 68735 // More here: github.com/Modernizr/Modernizr/issues/issue/21 68736 omPrefixes = 'Webkit Moz O ms', 68737 68738 cssomPrefixes = omPrefixes.split(' '), 68739 68740 domPrefixes = omPrefixes.toLowerCase().split(' '), 68741 /*>>domprefixes*/ 68742 68743 /*>>ns*/ 68744 ns = {'svg': 'http://www.w3.org/2000/svg'}, 68745 /*>>ns*/ 68746 68747 tests = {}, 68748 inputs = {}, 68749 attrs = {}, 68750 68751 classes = [], 68752 68753 slice = classes.slice, 68754 68755 featureName, // used in testing loop 68756 68757 68758 /*>>
vendor: 21,732 bytes, lines 68758-69367
68758teststyles*/ 68759 // Inject element with style element and some CSS rules 68760 injectElementWithStyles = function( rule, callback, nodes, testnames ) { 68761 68762 var style, ret, node, docOverflow, 68763 div = document.createElement('div'), 68764 // After page load injecting a fake body doesn't work so check if body exists 68765 body = document.body, 68766 // IE6 and 7 won't return offsetWidth or offsetHeight unless it's in the body element, so we fake it. 68767 fakeBody = body || document.createElement('body'); 68768 68769 if ( parseInt(nodes, 10) ) { 68770 // In order not to give false positives we create a node for each test 68771 // This also allows the method to scale for unspecified uses 68772 while ( nodes-- ) { 68773 node = document.createElement('div'); 68774 node.id = testnames ? testnames[nodes] : mod + (nodes + 1); 68775 div.appendChild(node); 68776 } 68777 } 68778 68779 // <style> elements in IE6-9 are considered 'NoScope' elements and therefore will be removed 68780 // when injected with innerHTML. To get around this you need to prepend the 'NoScope' element 68781 // with a 'scoped' element, in our case the soft-hyphen entity as it won't mess with our measurements. 68782 // msdn.microsoft.com/en-us/library/ms533897%28VS.85%29.aspx 68783 // Documents served as xml will throw if using ­ so use xml friendly encoded version. See issue #277 68784 style = ['­','<style id="s', mod, '">', rule, '</style>'].join(''); 68785 div.id = mod; 68786 // IE6 will false positive on some tests due to the style element inside the test div somehow interfering offsetHeight, so insert it into body or fakebody. 68787 // Opera will act all quirky when injecting elements in documentElement when page is served as xml, needs fakebody too. #270 68788 (body ? div : fakeBody).innerHTML += style; 68789 fakeBody.appendChild(div); 68790 if ( !body ) { 68791 //avoid crashing IE8, if background image is used 68792 fakeBody.style.background = ''; 68793 //Safari 5.13/5.1.4 OSX stops loading if ::-webkit-scrollbar is used and scrollbars are visible 68794 fakeBody.style.overflow = 'hidden'; 68795 docOverflow = docElement.style.overflow; 68796 docElement.style.overflow = 'hidden'; 68797 docElement.appendChild(fakeBody); 68798 } 68799 68800 ret = callback(div, rule); 68801 // If this is done after page load we don't want to remove the body so check if body exists 68802 if ( !body ) { 68803 fakeBody.parentNode.removeChild(fakeBody); 68804 docElement.style.overflow = docOverflow; 68805 } else { 68806 div.parentNode.removeChild(div); 68807 } 68808 68809 return !!ret; 68810 68811 }, 68812 /*>>teststyles*/ 68813 68814 /*>>mq*/ 68815 // adapted from matchMedia polyfill 68816 // by Scott Jehl and Paul Irish 68817 // gist.github.com/786768 68818 testMediaQuery = function( mq ) { 68819 68820 var matchMedia = window.matchMedia || window.msMatchMedia; 68821 if ( matchMedia ) { 68822 return matchMedia(mq).matches; 68823 } 68824 68825 var bool; 68826 68827 injectElementWithStyles('@media ' + mq + ' { #' + mod + ' { position: absolute; } }', function( node ) { 68828 bool = (window.getComputedStyle ? 68829 getComputedStyle(node, null) : 68830 node.currentStyle)['position'] == 'absolute'; 68831 }); 68832 68833 return bool; 68834 68835 }, 68836 /*>>mq*/ 68837 68838 68839 /*>>hasevent*/ 68840 // 68841 // isEventSupported determines if a given element supports the given event 68842 // kangax.github.com/iseventsupported/ 68843 // 68844 // The following results are known incorrects: 68845 // Modernizr.hasEvent("webkitTransitionEnd", elem) // false negative 68846 // Modernizr.hasEvent("textInput") // in Webkit. github.com/Modernizr/Modernizr/issues/333 68847 // ... 68848 isEventSupported = (function() { 68849 68850 var TAGNAMES = { 68851 'select': 'input', 'change': 'input', 68852 'submit': 'form', 'reset': 'form', 68853 'error': 'img', 'load': 'img', 'abort': 'img' 68854 }; 68855 68856 function isEventSupported( eventName, element ) { 68857 68858 element = element || document.createElement(TAGNAMES[eventName] || 'div'); 68859 eventName = 'on' + eventName; 68860 68861 // When using `setAttribute`, IE skips "unload", WebKit skips "unload" and "resize", whereas `in` "catches" those 68862 var isSupported = eventName in element; 68863 68864 if ( !isSupported ) { 68865 // If it has no `setAttribute` (i.e. doesn't implement Node interface), try generic element 68866 if ( !element.setAttribute ) { 68867 element = document.createElement('div'); 68868 } 68869 if ( element.setAttribute && element.removeAttribute ) { 68870 element.setAttribute(eventName, ''); 68871 isSupported = is(element[eventName], 'function'); 68872 68873 // If property was created, "remove it" (by setting value to `undefined`) 68874 if ( !is(element[eventName], 'undefined') ) { 68875 element[eventName] = undefined; 68876 } 68877 element.removeAttribute(eventName); 68878 } 68879 } 68880 68881 element = null; 68882 return isSupported; 68883 } 68884 return isEventSupported; 68885 })(), 68886 /*>>hasevent*/ 68887 68888 // TODO :: Add flag for hasownprop ? didn't last time 68889 68890 // hasOwnProperty shim by kangax needed for Safari 2.0 support 68891 _hasOwnProperty = ({}).hasOwnProperty, hasOwnProp; 68892 68893 if ( !is(_hasOwnProperty, 'undefined') && !is(_hasOwnProperty.call, 'undefined') ) { 68894 hasOwnProp = function (object, property) { 68895 return _hasOwnProperty.call(object, property); 68896 }; 68897 } 68898 else { 68899 hasOwnProp = function (object, property) { /* yes, this can give false positives/negatives, but most of the time we don't care about those */ 68900 return ((property in object) && is(object.constructor.prototype[property], 'undefined')); 68901 }; 68902 } 68903 68904 // Adapted from ES5-shim https://github.com/kriskowal/es5-shim/blob/master/es5-shim.js 68905 // es5.github.com/#x15.3.4.5 68906 68907 if (!Function.prototype.bind) { 68908 Function.prototype.bind = function bind(that) { 68909 68910 var target = this; 68911 68912 if (typeof target != "function") { 68913 throw new TypeError(); 68914 } 68915 68916 var args = slice.call(arguments, 1), 68917 bound = function () { 68918 68919 if (this instanceof bound) { 68920 68921 var F = function(){}; 68922 F.prototype = target.prototype; 68923 var self = new F(); 68924 68925 var result = target.apply( 68926 self, 68927 args.concat(slice.call(arguments)) 68928 ); 68929 if (Object(result) === result) { 68930 return result; 68931 } 68932 return self; 68933 68934 } else { 68935 68936 return target.apply( 68937 that, 68938 args.concat(slice.call(arguments)) 68939 ); 68940 68941 } 68942 68943 }; 68944 68945 return bound; 68946 }; 68947 } 68948 68949 /** 68950 * setCss applies given styles to the Modernizr DOM node. 68951 */ 68952 function setCss( str ) { 68953 mStyle.cssText = str; 68954 } 68955 68956 /** 68957 * setCssAll extrapolates all vendor-specific css strings. 68958 */ 68959 function setCssAll( str1, str2 ) { 68960 return setCss(prefixes.join(str1 + ';') + ( str2 || '' )); 68961 } 68962 68963 /** 68964 * is returns a boolean for if typeof obj is exactly type. 68965 */ 68966 function is( obj, type ) { 68967 return typeof obj === type; 68968 } 68969 68970 /** 68971 * contains returns a boolean for if substr is found within str. 68972 */ 68973 function contains( str, substr ) { 68974 return !!~('' + str).indexOf(substr); 68975 } 68976 68977 /*>>testprop*/ 68978 68979 // testProps is a generic CSS / DOM property test. 68980 68981 // In testing support for a given CSS property, it's legit to test: 68982 // `elem.style[styleName] !== undefined` 68983 // If the property is supported it will return an empty string, 68984 // if unsupported it will return undefined. 68985 68986 // We'll take advantage of this quick test and skip setting a style 68987 // on our modernizr element, but instead just testing undefined vs 68988 // empty string. 68989 68990 // Because the testing of the CSS property names (with "-", as 68991 // opposed to the camelCase DOM properties) is non-portable and 68992 // non-standard but works in WebKit and IE (but not Gecko or Opera), 68993 // we explicitly reject properties with dashes so that authors 68994 // developing in WebKit or IE first don't end up with 68995 // browser-specific content by accident. 68996 68997 function testProps( props, prefixed ) { 68998 for ( var i in props ) { 68999 var prop = props[i]; 69000 if ( !contains(prop, "-") && mStyle[prop] !== undefined ) { 69001 return prefixed == 'pfx' ? prop : true; 69002 } 69003 } 69004 return false; 69005 } 69006 /*>>testprop*/ 69007 69008 // TODO :: add testDOMProps 69009 /** 69010 * testDOMProps is a generic DOM property test; if a browser supports 69011 * a certain property, it won't return undefined for it. 69012 */ 69013 function testDOMProps( props, obj, elem ) { 69014 for ( var i in props ) { 69015 var item = obj[props[i]]; 69016 if ( item !== undefined) { 69017 69018 // return the property name as a string 69019 if (elem === false) return props[i]; 69020 69021 // let's bind a function 69022 if (is(item, 'function')){ 69023 // default to autobind unless override 69024 return item.bind(elem || obj); 69025 } 69026 69027 // return the unbound function or obj or value 69028 return item; 69029 } 69030 } 69031 return false; 69032 } 69033 69034 /*>>testallprops*/ 69035 /** 69036 * testPropsAll tests a list of DOM properties we want to check against. 69037 * We specify literally ALL possible (known and/or likely) properties on 69038 * the element including the non-vendor prefixed one, for forward- 69039 * compatibility. 69040 */ 69041 function testPropsAll( prop, prefixed, elem ) { 69042 69043 var ucProp = prop.charAt(0).toUpperCase() + prop.slice(1), 69044 props = (prop + ' ' + cssomPrefixes.join(ucProp + ' ') + ucProp).split(' '); 69045 69046 // did they call .prefixed('boxSizing') or are we just testing a prop? 69047 if(is(prefixed, "string") || is(prefixed, "undefined")) { 69048 return testProps(props, prefixed); 69049 69050 // otherwise, they called .prefixed('requestAnimationFrame', window[, elem]) 69051 } else { 69052 props = (prop + ' ' + (domPrefixes).join(ucProp + ' ') + ucProp).split(' '); 69053 return testDOMProps(props, prefixed, elem); 69054 } 69055 } 69056 /*>>testallprops*/ 69057 69058 69059 /** 69060 * Tests 69061 * ----- 69062 */ 69063 69064 // The *new* flexbox 69065 // dev.w3.org/csswg/css3-flexbox 69066 69067 tests['flexbox'] = function() { 69068 return testPropsAll('flexWrap'); 69069 }; 69070 69071 // The *old* flexbox 69072 // www.w3.org/TR/2009/WD-css3-flexbox-20090723/ 69073 69074 tests['flexboxlegacy'] = function() { 69075 return testPropsAll('boxDirection'); 69076 }; 69077 69078 // On the S60 and BB Storm, getContext exists, but always returns undefined 69079 // so we actually have to call getContext() to verify 69080 // github.com/Modernizr/Modernizr/issues/issue/97/ 69081 69082 tests['canvas'] = function() { 69083 var elem = document.createElement('canvas'); 69084 return !!(elem.getContext && elem.getContext('2d')); 69085 }; 69086 69087 tests['canvastext'] = function() { 69088 return !!(Modernizr['canvas'] && is(document.createElement('canvas').getContext('2d').fillText, 'function')); 69089 }; 69090 69091 // webk.it/70117 is tracking a legit WebGL feature detect proposal 69092 69093 // We do a soft detect which may false positive in order to avoid 69094 // an expensive context creation: bugzil.la/732441 69095 69096 tests['webgl'] = function() { 69097 return !!window.WebGLRenderingContext; 69098 }; 69099 69100 /* 69101 * The Modernizr.touch test only indicates if the browser supports 69102 * touch events, which does not necessarily reflect a touchscreen 69103 * device, as evidenced by tablets running Windows 7 or, alas, 69104 * the Palm Pre / WebOS (touch) phones. 69105 * 69106 * Additionally, Chrome (desktop) used to lie about its support on this, 69107 * but that has since been rectified: crbug.com/36415 69108 * 69109 * We also test for Firefox 4 Multitouch Support. 69110 * 69111 * For more info, see: modernizr.github.com/Modernizr/touch.html 69112 */ 69113 69114 tests['touch'] = function() { 69115 var bool; 69116 69117 if(('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch) { 69118 bool = true; 69119 } else { 69120 injectElementWithStyles(['@media (',prefixes.join('touch-enabled),('),mod,')','{#modernizr{top:9px;position:absolute}}'].join(''), function( node ) { 69121 bool = node.offsetTop === 9; 69122 }); 69123 } 69124 69125 return bool; 69126 }; 69127 69128 69129 // geolocation is often considered a trivial feature detect... 69130 // Turns out, it's quite tricky to get right: 69131 // 69132 // Using !!navigator.geolocation does two things we don't want. It: 69133 // 1. Leaks memory in IE9: github.com/Modernizr/Modernizr/issues/513 69134 // 2. Disables page caching in WebKit: webk.it/43956 69135 // 69136 // Meanwhile, in Firefox < 8, an about:config setting could expose 69137 // a false positive that would throw an exception: bugzil.la/688158 69138 69139 tests['geolocation'] = function() { 69140 return 'geolocation' in navigator; 69141 }; 69142 69143 69144 tests['postmessage'] = function() { 69145 return !!window.postMessage; 69146 }; 69147 69148 69149 // Chrome incognito mode used to throw an exception when using openDatabase 69150 // It doesn't anymore. 69151 tests['websqldatabase'] = function() { 69152 return !!window.openDatabase; 69153 }; 69154 69155 // Vendors had inconsistent prefixing with the experimental Indexed DB: 69156 // - Webkit's implementation is accessible through webkitIndexedDB 69157 // - Firefox shipped moz_indexedDB before FF4b9, but since then has been mozIndexedDB 69158 // For speed, we don't test the legacy (and beta-only) indexedDB 69159 tests['indexedDB'] = function() { 69160 return !!testPropsAll("indexedDB", window); 69161 }; 69162 69163 // documentMode logic from YUI to filter out IE8 Compat Mode 69164 // which false positives. 69165 tests['hashchange'] = function() { 69166 return isEventSupported('hashchange', window) && (document.documentMode === undefined || document.documentMode > 7); 69167 }; 69168 69169 // Per 1.6: 69170 // This used to be Modernizr.historymanagement but the longer 69171 // name has been deprecated in favor of a shorter and property-matching one. 69172 // The old API is still available in 1.6, but as of 2.0 will throw a warning, 69173 // and in the first release thereafter disappear entirely. 69174 tests['history'] = function() { 69175 return !!(window.history && history.pushState); 69176 }; 69177 69178 tests['draganddrop'] = function() { 69179 var div = document.createElement('div'); 69180 return ('draggable' in div) || ('ondragstart' in div && 'ondrop' in div); 69181 }; 69182 69183 // FF3.6 was EOL'ed on 4/24/12, but the ESR version of FF10 69184 // will be supported until FF19 (2/12/13), at which time, ESR becomes FF17. 69185 // FF10 still uses prefixes, so check for it until then. 69186 // for more ESR info, see: mozilla.org/en-US/firefox/organizations/faq/ 69187 tests['websockets'] = function() { 69188 return 'WebSocket' in window || 'MozWebSocket' in window; 69189 }; 69190 69191 69192 // css-tricks.com/rgba-browser-support/ 69193 tests['rgba'] = function() { 69194 // Set an rgba() color and check the returned value 69195 69196 setCss('background-color:rgba(150,255,150,.5)'); 69197 69198 return contains(mStyle.backgroundColor, 'rgba'); 69199 }; 69200 69201 tests['hsla'] = function() { 69202 // Same as rgba(), in fact, browsers re-map hsla() to rgba() internally, 69203 // except IE9 who retains it as hsla 69204 69205 setCss('background-color:hsla(120,40%,100%,.5)'); 69206 69207 return contains(mStyle.backgroundColor, 'rgba') || contains(mStyle.backgroundColor, 'hsla'); 69208 }; 69209 69210 tests['multiplebgs'] = function() { 69211 // Setting multiple images AND a color on the background shorthand property 69212 // and then querying the style.background property value for the number of 69213 // occurrences of "url(" is a reliable method for detecting ACTUAL support for this! 69214 69215 setCss('background:url(https://),url(https://),red url(https://)'); 69216 69217 // If the UA supports multiple backgrounds, there should be three occurrences 69218 // of the string "url(" in the return value for elemStyle.background 69219 69220 return (/(url\s*\(.*?){3}/).test(mStyle.background); 69221 }; 69222 69223 69224 69225 // this will false positive in Opera Mini 69226 // github.com/Modernizr/Modernizr/issues/396 69227 69228 tests['backgroundsize'] = function() { 69229 return testPropsAll('backgroundSize'); 69230 }; 69231 69232 tests['borderimage'] = function() { 69233 return testPropsAll('borderImage'); 69234 }; 69235 69236 69237 // Super comprehensive table about all the unique implementations of 69238 // border-radius: muddledramblings.com/table-of-css3-border-radius-compliance 69239 69240 tests['borderradius'] = function() { 69241 return testPropsAll('borderRadius'); 69242 }; 69243 69244 // WebOS unfortunately false positives on this test. 69245 tests['boxshadow'] = function() { 69246 return testPropsAll('boxShadow'); 69247 }; 69248 69249 // FF3.0 will false positive on this test 69250 tests['textshadow'] = function() { 69251 return document.createElement('div').style.textShadow === ''; 69252 }; 69253 69254 69255 tests['opacity'] = function() { 69256 // Browsers that actually have CSS Opacity implemented have done so 69257 // according to spec, which means their return values are within the 69258 // range of [0.0,1.0] - including the leading zero. 69259 69260 setCssAll('opacity:.55'); 69261 69262 // The non-literal . in this regex is intentional: 69263 // German Chrome returns this value as 0,55 69264 // github.com/Modernizr/Modernizr/issues/#issue/59/comment/516632 69265 return (/^0.55$/).test(mStyle.opacity); 69266 }; 69267 69268 69269 // Note, Android < 4 will pass this test, but can only animate 69270 // a single property at a time 69271 // goo.gl/v3V4Gp 69272 tests['cssanimations'] = function() { 69273 return testPropsAll('animationName'); 69274 }; 69275 69276 69277 tests['csscolumns'] = function() { 69278 return testPropsAll('columnCount'); 69279 }; 69280 69281 69282 tests['cssgradients'] = function() { 69283 /** 69284 * For CSS Gradients syntax, please see: 69285 * webkit.org/blog/175/introducing-css-gradients/ 69286 * developer.mozilla.org/en/CSS/-moz-linear-gradient 69287 * developer.mozilla.org/en/CSS/-moz-radial-gradient 69288 * dev.w3.org/csswg/css3-images/#gradients- 69289 */ 69290 69291 var str1 = 'background-image:', 69292 str2 = 'gradient(linear,left top,right bottom,from(#9f9),to(white));', 69293 str3 = 'linear-gradient(left top,#9f9, white);'; 69294 69295 setCss( 69296 // legacy webkit syntax (FIXME: remove when syntax not in use anymore) 69297 (str1 + '-webkit- '.split(' ').join(str2 + str1) + 69298 // standard syntax // trailing 'background-image:' 69299 prefixes.join(str3 + str1)).slice(0, -str1.length) 69300 ); 69301 69302 return contains(mStyle.backgroundImage, 'gradient'); 69303 }; 69304 69305 69306 tests['cssreflections'] = function() { 69307 return testPropsAll('boxReflect'); 69308 }; 69309 69310 69311 tests['csstransforms'] = function() { 69312 return !!testPropsAll('transform'); 69313 }; 69314 69315 69316 tests['csstransforms3d'] = function() { 69317 69318 var ret = !!testPropsAll('perspective'); 69319 69320 // Webkit's 3D transforms are passed off to the browser's own graphics renderer. 69321 // It works fine in Safari on Leopard and Snow Leopard, but not in Chrome in 69322 // some conditions. As a result, Webkit typically recognizes the syntax but 69323 // will sometimes throw a false positive, thus we must do a more thorough check: 69324 if ( ret && 'webkitPerspective' in docElement.style ) { 69325 69326 // Webkit allows this media query to succeed only if the feature is enabled. 69327 // `@media (transform-3d),(-webkit-transform-3d){ ... }` 69328 injectElementWithStyles('@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}', function( node, rule ) { 69329 ret = node.offsetLeft === 9 && node.offsetHeight === 3; 69330 }); 69331 } 69332 return ret; 69333 }; 69334 69335 69336 tests['csstransitions'] = function() { 69337 return testPropsAll('transition'); 69338 }; 69339 69340 69341 /*>>fontface*/ 69342 // @font-face detection routine by Diego Perini 69343 // javascript.nwbox.com/CSSSupport/ 69344 69345 // false positives: 69346 // WebOS github.com/Modernizr/Modernizr/issues/342 69347 // WP7 github.com/Modernizr/Modernizr/issues/538 69348 tests['fontface'] = function() { 69349 var bool; 69350 69351 injectElementWithStyles('@font-face {font-family:"font";src:url("https://")}', function( node, rule ) { 69352 var style = document.getElementById('smodernizr'), 69353 sheet = style.sheet || style.styleSheet, 69354 cssText = sheet ? (sheet.cssRules && sheet.cssRules[0] ? sheet.cssRules[0].cssText : sheet.cssText || '') : ''; 69355 69356 bool = /src/i.test(cssText) && cssText.indexOf(rule.split(' ')[0]) === 0; 69357 }); 69358 69359 return bool; 69360 }; 69361 /*>>fontface*/ 69362 69363 // CSS generated content detection 69364 tests['generatedcontent'] = function() { 69365 var bool; 69366 69367 injectElementWithStyles(['#',mod,'{font:0/0 a}
69367#',mod,':after{content:"',smile,'";visibility:hidden;font:3px/1 a}'].join(''), function( node ) { 69368 bool = node.offsetHeight >= 3; 69369 }); 69370 69371 return bool; 69372 }; 69373 69374 69375 69376 // These tests evaluate support of the video/audio elements, as well as 69377 // testing what types of content they support. 69378 // 69379 // We're using the Boolean constructor here, so that we can extend the value 69380 // e.g. Modernizr.video // true 69381 // Modernizr.video.ogg // 'probably' 69382 // 69383 // Codec values from : github.com/NielsLeenheer/html5test/blob/9106a8/index.html#L845 69384 // thx to NielsLeenheer and zcorpan 69385 69386 // Note: in some older browsers, "no" was a return value instead of empty string. 69387 // It was live in FF3.5.0 and 3.5.1, but fixed in 3.5.2 69388 // It was also live in Safari 4.0.0 - 4.0.4, but fixed in 4.0.5 69389 69390 tests['video'] = function() { 69391 var elem = document.createElement('video'), 69392 bool = false; 69393 69394 // IE9 Running on Windows Server SKU can cause an exception to be thrown, bug #224 69395 try { 69396 if ( bool = !!elem.canPlayType ) { 69397 bool = new Boolean(bool); 69398 bool.ogg = elem.canPlayType('video/ogg; codecs="theora"') .replace(/^no$/,''); 69399
vendor: 14,978 bytes, lines 69400-69774
69400 // Without QuickTime, this value will be `undefined`. github.com/Modernizr/Modernizr/issues/546 69401 bool.h264 = elem.canPlayType('video/mp4; codecs="avc1.42E01E"') .replace(/^no$/,''); 69402 69403 bool.webm = elem.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/^no$/,''); 69404 } 69405 69406 } catch(e) { } 69407 69408 return bool; 69409 }; 69410 69411 tests['audio'] = function() { 69412 var elem = document.createElement('audio'), 69413 bool = false; 69414 69415 try { 69416 if ( bool = !!elem.canPlayType ) { 69417 bool = new Boolean(bool); 69418 bool.ogg = elem.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,''); 69419 bool.mp3 = elem.canPlayType('audio/mpeg;') .replace(/^no$/,''); 69420 69421 // Mimetypes accepted: 69422 // developer.mozilla.org/En/Media_formats_supported_by_the_audio_and_video_elements 69423 // bit.ly/iphoneoscodecs 69424 bool.wav = elem.canPlayType('audio/wav; codecs="1"') .replace(/^no$/,''); 69425 bool.m4a = ( elem.canPlayType('audio/x-m4a;') || 69426 elem.canPlayType('audio/aac;')) .replace(/^no$/,''); 69427 } 69428 } catch(e) { } 69429 69430 return bool; 69431 }; 69432 69433 69434 // In FF4, if disabled, window.localStorage should === null. 69435 69436 // Normally, we could not test that directly and need to do a 69437 // `('localStorage' in window) && ` test first because otherwise Firefox will 69438 // throw bugzil.la/365772 if cookies are disabled 69439 69440 // Also in iOS5 Private Browsing mode, attempting to use localStorage.setItem 69441 // will throw the exception: 69442 // QUOTA_EXCEEDED_ERRROR DOM Exception 22. 69443 // Peculiarly, getItem and removeItem calls do not throw. 69444 69445 // Because we are forced to try/catch this, we'll go aggressive. 69446 69447 // Just FWIW: IE8 Compat mode supports these features completely: 69448 // www.quirksmode.org/dom/html5.html 69449 // But IE8 doesn't support either with local files 69450 69451 tests['localstorage'] = function() { 69452 try { 69453 localStorage.setItem(mod, mod); 69454 localStorage.removeItem(mod); 69455 return true; 69456 } catch(e) { 69457 return false; 69458 } 69459 }; 69460 69461 tests['sessionstorage'] = function() { 69462 try { 69463 sessionStorage.setItem(mod, mod); 69464 sessionStorage.removeItem(mod); 69465 return true; 69466 } catch(e) { 69467 return false; 69468 } 69469 }; 69470 69471 69472 tests['webworkers'] = function() { 69473 return !!window.Worker; 69474 }; 69475 69476 69477 tests['applicationcache'] = function() { 69478 return !!window.applicationCache; 69479 }; 69480 69481 69482 // Thanks to Erik Dahlstrom 69483 tests['svg'] = function() { 69484 return !!document.createElementNS && !!document.createElementNS(ns.svg, 'svg').createSVGRect; 69485 }; 69486 69487 // specifically for SVG inline in HTML, not within XHTML 69488 // test page: paulirish.com/demo/inline-svg 69489 tests['inlinesvg'] = function() { 69490 var div = document.createElement('div'); 69491 div.innerHTML = '<svg/>'; 69492 return (div.firstChild && div.firstChild.namespaceURI) == ns.svg; 69493 }; 69494 69495 // SVG SMIL animation 69496 tests['smil'] = function() { 69497 return !!document.createElementNS && /SVGAnimate/.test(toString.call(document.createElementNS(ns.svg, 'animate'))); 69498 }; 69499 69500 // This test is only for clip paths in SVG proper, not clip paths on HTML content 69501 // demo: srufaculty.sru.edu/david.dailey/svg/newstuff/clipPath4.svg 69502 69503 // However read the comments to dig into applying SVG clippaths to HTML content here: 69504 // github.com/Modernizr/Modernizr/issues/213#issuecomment-1149491 69505 tests['svgclippaths'] = function() { 69506 return !!document.createElementNS && /SVGClipPath/.test(toString.call(document.createElementNS(ns.svg, 'clipPath'))); 69507 }; 69508 69509 /*>>webforms*/ 69510 // input features and input types go directly onto the ret object, bypassing the tests loop. 69511 // Hold this guy to execute in a moment. 69512 function webforms() { 69513 /*>>input*/ 69514 // Run through HTML5's new input attributes to see if the UA understands any. 69515 // We're using f which is the <input> element created early on 69516 // Mike Taylr has created a comprehensive resource for testing these attributes 69517 // when applied to all input types: 69518 // miketaylr.com/code/input-type-attr.html 69519 // spec: www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html#input-type-attr-summary 69520 69521 // Only input placeholder is tested while textarea's placeholder is not. 69522 // Currently Safari 4 and Opera 11 have support only for the input placeholder 69523 // Both tests are available in feature-detects/forms-placeholder.js 69524 Modernizr['input'] = (function( props ) { 69525 for ( var i = 0, len = props.length; i < len; i++ ) { 69526 attrs[ props[i] ] = !!(props[i] in inputElem); 69527 } 69528 if (attrs.list){ 69529 // safari false positive's on datalist: webk.it/74252 69530 // see also github.com/Modernizr/Modernizr/issues/146 69531 attrs.list = !!(document.createElement('datalist') && window.HTMLDataListElement); 69532 } 69533 return attrs; 69534 })('autocomplete autofocus list placeholder max min multiple pattern required step'.split(' ')); 69535 /*>>input*/ 69536 69537 /*>>inputtypes*/ 69538 // Run through HTML5's new input types to see if the UA understands any. 69539 // This is put behind the tests runloop because it doesn't return a 69540 // true/false like all the other tests; instead, it returns an object 69541 // containing each input type with its corresponding true/false value 69542 69543 // Big thanks to @miketaylr for the html5 forms expertise. miketaylr.com/ 69544 Modernizr['inputtypes'] = (function(props) { 69545 69546 for ( var i = 0, bool, inputElemType, defaultView, len = props.length; i < len; i++ ) { 69547 69548 inputElem.setAttribute('type', inputElemType = props[i]); 69549 bool = inputElem.type !== 'text'; 69550 69551 // We first check to see if the type we give it sticks.. 69552 // If the type does, we feed it a textual value, which shouldn't be valid. 69553 // If the value doesn't stick, we know there's input sanitization which infers a custom UI 69554 if ( bool ) { 69555 69556 inputElem.value = smile; 69557 inputElem.style.cssText = 'position:absolute;visibility:hidden;'; 69558 69559 if ( /^range$/.test(inputElemType) && inputElem.style.WebkitAppearance !== undefined ) { 69560 69561 docElement.appendChild(inputElem); 69562 defaultView = document.defaultView; 69563 69564 // Safari 2-4 allows the smiley as a value, despite making a slider 69565 bool = defaultView.getComputedStyle && 69566 defaultView.getComputedStyle(inputElem, null).WebkitAppearance !== 'textfield' && 69567 // Mobile android web browser has false positive, so must 69568 // check the height to see if the widget is actually there. 69569 (inputElem.offsetHeight !== 0); 69570 69571 docElement.removeChild(inputElem); 69572 69573 } else if ( /^(search|tel)$/.test(inputElemType) ){ 69574 // Spec doesn't define any special parsing or detectable UI 69575 // behaviors so we pass these through as true 69576 69577 // Interestingly, opera fails the earlier test, so it doesn't 69578 // even make it here. 69579 69580 } else if ( /^(url|email)$/.test(inputElemType) ) { 69581 // Real url and email support comes with prebaked validation. 69582 bool = inputElem.checkValidity && inputElem.checkValidity() === false; 69583 69584 } else { 69585 // If the upgraded input compontent rejects the :) text, we got a winner 69586 bool = inputElem.value != smile; 69587 } 69588 } 69589 69590 inputs[ props[i] ] = !!bool; 69591 } 69592 return inputs; 69593 })('search tel url email datetime date month week time datetime-local number range color'.split(' ')); 69594 /*>>inputtypes*/ 69595 } 69596 /*>>webforms*/ 69597 69598 69599 // End of test definitions 69600 // ----------------------- 69601 69602 69603 69604 // Run through all tests and detect their support in the current UA. 69605 // todo: hypothetically we could be doing an array of tests and use a basic loop here. 69606 for ( var feature in tests ) { 69607 if ( hasOwnProp(tests, feature) ) { 69608 // run the test, throw the return value into the Modernizr, 69609 // then based on that boolean, define an appropriate className 69610 // and push it into an array of classes we'll join later. 69611 featureName = feature.toLowerCase(); 69612 Modernizr[featureName] = tests[feature](); 69613 69614 classes.push((Modernizr[featureName] ? '' : 'no-') + featureName); 69615 } 69616 } 69617 69618 /*>>webforms*/ 69619 // input tests need to run. 69620 Modernizr.input || webforms(); 69621 /*>>webforms*/ 69622 69623 69624 /** 69625 * addTest allows the user to define their own feature tests 69626 * the result will be added onto the Modernizr object, 69627 * as well as an appropriate className set on the html element 69628 * 69629 * @param feature - String naming the feature 69630 * @param test - Function returning true if feature is supported, false if not 69631 */ 69632 Modernizr.addTest = function ( feature, test ) { 69633 if ( typeof feature == 'object' ) { 69634 for ( var key in feature ) { 69635 if ( hasOwnProp( feature, key ) ) { 69636 Modernizr.addTest( key, feature[ key ] ); 69637 } 69638 } 69639 } else { 69640 69641 feature = feature.toLowerCase(); 69642 69643 if ( Modernizr[feature] !== undefined ) { 69644 // we're going to quit if you're trying to overwrite an existing test 69645 // if we were to allow it, we'd do this: 69646 // var re = new RegExp("\\b(no-)?" + feature + "\\b"); 69647 // docElement.className = docElement.className.replace( re, '' ); 69648 // but, no rly, stuff 'em. 69649 return Modernizr; 69650 } 69651 69652 test = typeof test == 'function' ? test() : test; 69653 69654 if (typeof enableClasses !== "undefined" && enableClasses) { 69655 docElement.className += ' ' + (test ? '' : 'no-') + feature; 69656 } 69657 Modernizr[feature] = test; 69658 69659 } 69660 69661 return Modernizr; // allow chaining. 69662 }; 69663 69664 69665 // Reset modElem.cssText to nothing to reduce memory footprint. 69666 setCss(''); 69667 modElem = inputElem = null; 69668 69669 /*>>shiv*/ 69670 /** 69671 * @preserve HTML5 Shiv prev3.7.1 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed 69672 */ 69673 ;(function(window, document) { 69674 /*jshint evil:true */ 69675 /** version */ 69676 var version = '3.7.0'; 69677 69678 /** Preset options */ 69679 var options = window.html5 || {}; 69680 69681 /** Used to skip problem elements */ 69682 var reSkip = /^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i; 69683 69684 /** Not all elements can be cloned in IE **/ 69685 var saveClones = /^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i; 69686 69687 /** Detect whether the browser supports default html5 styles */ 69688 var supportsHtml5Styles; 69689 69690 /** Name of the expando, to work with multiple documents or to re-shiv one document */ 69691 var expando = '_html5shiv'; 69692 69693 /** The id for the the documents expando */ 69694 var expanID = 0; 69695 69696 /** Cached data for each document */ 69697 var expandoData = {}; 69698 69699 /** Detect whether the browser supports unknown elements */ 69700 var supportsUnknownElements; 69701 69702 (function() { 69703 try { 69704 var a = document.createElement('a'); 69705 a.innerHTML = '<xyz></xyz>'; 69706 //if the hidden property is implemented we can assume, that the browser supports basic HTML5 Styles 69707 supportsHtml5Styles = ('hidden' in a); 69708 69709 supportsUnknownElements = a.childNodes.length == 1 || (function() { 69710 // assign a false positive if unable to shiv 69711 (document.createElement)('a'); 69712 var frag = document.createDocumentFragment(); 69713 return ( 69714 typeof frag.cloneNode == 'undefined' || 69715 typeof frag.createDocumentFragment == 'undefined' || 69716 typeof frag.createElement == 'undefined' 69717 ); 69718 }()); 69719 } catch(e) { 69720 // assign a false positive if detection fails => unable to shiv 69721 supportsHtml5Styles = true; 69722 supportsUnknownElements = true; 69723 } 69724 69725 }()); 69726 69727 /*--------------------------------------------------------------------------*/ 69728 69729 /** 69730 * Creates a style sheet with the given CSS text and adds it to the document. 69731 * @private 69732 * @param {Document} ownerDocument The document. 69733 * @param {String} cssText The CSS text. 69734 * @returns {StyleSheet} The style element. 69735 */ 69736 function addStyleSheet(ownerDocument, cssText) { 69737 var p = ownerDocument.createElement('p'), 69738 parent = ownerDocument.getElementsByTagName('head')[0] || ownerDocument.documentElement; 69739 69740 p.innerHTML = 'x<style>' + cssText + '</style>'; 69741 return parent.insertBefore(p.lastChild, parent.firstChild); 69742 } 69743 69744 /** 69745 * Returns the value of `html5.elements` as an array. 69746 * @private 69747 * @returns {Array} An array of shived element node names. 69748 */ 69749 function getElements() { 69750 var elements = html5.elements; 69751 return typeof elements == 'string' ? elements.split(' ') : elements; 69752 } 69753 69754 /** 69755 * Returns the data associated to the given document 69756 * @private 69757 * @param {Document} ownerDocument The document. 69758 * @returns {Object} An object of data. 69759 */ 69760 function getExpandoData(ownerDocument) { 69761 var data = expandoData[ownerDocument[expando]]; 69762 if (!data) { 69763 data = {}; 69764 expanID++; 69765 ownerDocument[expando] = expanID; 69766 expandoData[expanID] = data; 69767 } 69768 return data; 69769 } 69770 69771 /** 69772 * returns a shived element for the given nodeName and document 69773 * @memberOf html5 69774 * @param {String}
vendor: 4,707 bytes, lines 69774-69885
69774 nodeName name of the element 69775 * @param {Document} ownerDocument The context document. 69776 * @returns {Object} The shived element. 69777 */ 69778 function createElement(nodeName, ownerDocument, data){ 69779 if (!ownerDocument) { 69780 ownerDocument = document; 69781 } 69782 if(supportsUnknownElements){ 69783 return ownerDocument.createElement(nodeName); 69784 } 69785 if (!data) { 69786 data = getExpandoData(ownerDocument); 69787 } 69788 var node; 69789 69790 if (data.cache[nodeName]) { 69791 node = data.cache[nodeName].cloneNode(); 69792 } else if (saveClones.test(nodeName)) { 69793 node = (data.cache[nodeName] = data.createElem(nodeName)).cloneNode(); 69794 } else { 69795 node = data.createElem(nodeName); 69796 } 69797 69798 // Avoid adding some elements to fragments in IE < 9 because 69799 // * Attributes like `name` or `type` cannot be set/changed once an element 69800 // is inserted into a document/fragment 69801 // * Link elements with `src` attributes that are inaccessible, as with 69802 // a 403 response, will cause the tab/window to crash 69803 // * Script elements appended to fragments will execute when their `src` 69804 // or `text` property is set 69805 return node.canHaveChildren && !reSkip.test(nodeName) && !node.tagUrn ? data.frag.appendChild(node) : node; 69806 } 69807 69808 /** 69809 * returns a shived DocumentFragment for the given document 69810 * @memberOf html5 69811 * @param {Document} ownerDocument The context document. 69812 * @returns {Object} The shived DocumentFragment. 69813 */ 69814 function createDocumentFragment(ownerDocument, data){ 69815 if (!ownerDocument) { 69816 ownerDocument = document; 69817 } 69818 if(supportsUnknownElements){ 69819 return ownerDocument.createDocumentFragment(); 69820 } 69821 data = data || getExpandoData(ownerDocument); 69822 var clone = data.frag.cloneNode(), 69823 i = 0, 69824 elems = getElements(), 69825 l = elems.length; 69826 for(;i<l;i++){ 69827 clone.createElement(elems[i]); 69828 } 69829 return clone; 69830 } 69831 69832 /** 69833 * Shivs the `createElement` and `createDocumentFragment` methods of the document. 69834 * @private 69835 * @param {Document|DocumentFragment} ownerDocument The document. 69836 * @param {Object} data of the document. 69837 */ 69838 function shivMethods(ownerDocument, data) { 69839 if (!data.cache) { 69840 data.cache = {}; 69841 data.createElem = ownerDocument.createElement; 69842 data.createFrag = ownerDocument.createDocumentFragment; 69843 data.frag = data.createFrag(); 69844 } 69845 69846 69847 ownerDocument.createElement = function(nodeName) { 69848 //abort shiv 69849 if (!html5.shivMethods) { 69850 return data.createElem(nodeName); 69851 } 69852 return createElement(nodeName, ownerDocument, data); 69853 }; 69854 69855 ownerDocument.createDocumentFragment = Function('h,f', 'return function(){' + 69856 'var n=f.cloneNode(),c=n.createElement;' + 69857 'h.shivMethods&&(' + 69858 // unroll the `createElement` calls 69859 getElements().join().replace(/[\w\-]+/g, function(nodeName) { 69860 data.createElem(nodeName); 69861 data.frag.createElement(nodeName); 69862 return 'c("' + nodeName + '")'; 69863 }) + 69864 ');return n}' 69865 )(html5, data.frag); 69866 } 69867 69868 /*--------------------------------------------------------------------------*/ 69869 69870 /** 69871 * Shivs the given document. 69872 * @memberOf html5 69873 * @param {Document} ownerDocument The document to shiv. 69874 * @returns {Document} The shived document. 69875 */ 69876 function shivDocument(ownerDocument) { 69877 if (!ownerDocument) { 69878 ownerDocument = document; 69879 } 69880 var data = getExpandoData(ownerDocument); 69881 69882 if (html5.shivCSS && !supportsHtml5Styles && !data.hasCSS) { 69883 data.hasCSS = !!addStyleSheet(ownerDocument, 69884 // corrects block display not defined in IE6/7/8/9 69885 'article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{dis
69885play:block}' + 69886 // adds styling not present in IE6/7/8/9 69887 'mark{background:#FF0;color:#000}' + 69888 // hides non-rendered elements 69889 'template{display:none}' 69890 ); 69891 } 69892 if (!supportsUnknownElements) { 69893 shivMethods(ownerDocument, data); 69894 } 69895 return ownerDocument; 69896 } 69897 69898 /*--------------------------------------------------------------------------*/ 69899 69900 /** 69901 * The `html5` object is exposed so that more elements can be shived and 69902 * existing shiving can be detected on iframes. 69903 * @type Object 69904 * @example 69905 * 69906 * // options can be changed before the script is included 69907 * html5 = { 'elements': 'mark section', 'shivCSS': false, 'shivMethods': false }; 69908 */ 69909 var html5 = { 69910 69911 /** 69912 * An array or space separated string of node names of the elements to shiv. 69913 * @memberOf html5 69914 * @type Array|String 69915 */ 69916 'elements': options.elements || 'abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output progress section summary template time video', 69917 69918 /** 69919 * current version of html5shiv 69920 */ 69921 'version': version, 69922 69923 /** 69924 * A flag to indicate that the HTML5 style sheet should be inserted. 69925 * @memberOf html5 69926 * @type Boolean 69927 */ 69928 'shivCSS': (options.shivCSS !== false), 69929 69930 /** 69931 * Is equal to true if a browser supports creating unknown/HTML5 elements 69932 * @memberOf html5 69933 * @type boolean 69934 */ 69935 'supportsUnknownElements': supportsUnknownElements, 69936 69937 /** 69938 * A flag to indicate that the document's `createElement` and `createDocumentFragment` 69939 * methods should be overwritten. 69940 * @memberOf html5 69941 * @type Boolean 69942 */ 69943 'shivMethods': (options.shivMethods !== false), 69944 69945 /** 69946 * A string to describe the type of `html5` object ("default" or "default print"). 69947 * @memberOf html5
69948 * @type String 69949 */ 69950 'type': 'default', 69951 69952 // shivs the document according to the specified `html5` object options 69953 'shivDocument': shivDocument, 69954 69955 //creates a shived element 69956 createElement: createElement, 69957 69958 //creates a shived documentFragment 69959 createDocumentFragment: createDocumentFragment 69960 }; 69961 69962 /*--------------------------------------------------------------------------*/ 69963 69964 // expose html5 69965 window.html5 = html5; 69966 69967 // shiv the document 69968 shivDocument(document); 69969 69970 }(this, document)); 69971 /*>>shiv*/ 69972 69973 // Assign private properties to the return object with prefix 69974 Modernizr._version = version; 69975 69976 // expose these for the plugin API. Look in the source for how to join() them against your input 69977 /*>>prefixes*/ 69978 Modernizr._prefixes = prefixes; 69979 /*>>prefixes*/ 69980 /*>>domprefixes*/ 69981 Modernizr._domPrefixes = domPrefixes; 69982 Modernizr._cssomPrefixes = cssomPrefixes; 69983 /*>>domprefixes*/ 69984 69985 /*>>mq*/ 69986 // Modernizr.mq tests a given media query, live against the current state of the window 69987 // A few important notes: 69988 // * If a browser does not support media queries at all (eg. oldIE) the mq() will always return false 69989 // * A max-width or orientation query will be evaluated against the current state, which may change later. 69990 // * You must specify values. Eg. If you are testing support for the min-width media query use: 69991 // Modernizr.mq('(min-width:0)') 69992 // usage: 69993 // Modernizr.mq('only screen and (max-width:768)') 69994 Modernizr.mq = testMediaQuery; 69995 /*>>mq*/ 69996 69997 /*>>hasevent*/ 69998 // Modernizr.hasEvent() detects support for a given event, with an optional element to test on 69999 // Modernizr.hasEvent('gesturestart', elem) 70000 Modernizr.hasEvent = isEventSupported; 70001 /*>>hasevent*/ 70002 70003 /*>>testprop*/ 70004 // Modernizr.testProp() investigates whether a given style property is recognized 70005 // Note that the property names must be provided in the camelCase variant. 70006 // Modernizr.testProp('pointerEvents') 70007 Modernizr.testProp = function(prop){ 70008 return testProps([prop]); 70009 }; 70010 /*>>testprop*/ 70011 70012 /*>>testallprops*/ 70013 // Modernizr.testAllProps() investigates whether a given style property, 70014 // or any of its vendor-prefixed variants, is recognized 70015 // Note that the property names must be provided in the camelCase variant. 70016 // Modernizr.testAllProps('boxSizing') 70017 Modernizr.testAllProps = testPropsAll; 70018 /*>>testallprops*/ 70019 70020 70021 /*>>teststyles*/ 70022 // Modernizr.testStyles() allows you to add custom styles to the document and test an element afterwards 70023 // Modernizr.testStyles('#modernizr { position:absolute }', function(elem, rule){ ... }) 70024 Modernizr.testStyles = injectElementWithStyles; 70025 /*>>teststyles*/ 70026 70027 70028 /*>>prefixed*/ 70029 // Modernizr.prefixed() returns the prefixed or nonprefixed property name variant of your input 70030 // Modernizr.prefixed('boxSizing') // 'MozBoxSizing' 70031 70032 // Properties must be passed as dom-style camelcase, rather than `box-sizing` hypentated style. 70033 // Return values will also be the camelCase variant, if you need to translate that to hypenated style use: 70034 // 70035 // str.replace(/([A-Z])/g, function(str,m1){ return '-' + m1.toLowerCase(); }).replace(/^ms-/,'-ms-'); 70036 70037 // If you're trying to ascertain which transition end event to bind to, you might do something like... 70038 // 70039 // var transEndEventNames = { 70040 // 'WebkitTransition' : 'webkitTransitionEnd', 70041 // 'MozTransition' : 'transitionend', 70042 // 'OTransition' : 'oTransitionEnd', 70043 // 'msTransition' : 'MSTransitionEnd', 70044 // 'transition' : 'transitionend' 70045 // }, 70046 // transEndEventName = transEndEventNames[ Modernizr.prefixed('transition') ]; 70047 70048 Modernizr.prefixed = function(prop, obj, elem){ 70049 if(!obj) { 70050 return testPropsAll(prop, 'pfx'); 70051 } else { 70052 // Testing DOM property e.g. Modernizr.prefixed('requestAnimationFrame', window) // 'mozRequestAnimationFrame' 70053 return testPropsAll(prop, obj, elem); 70054 } 70055 }; 70056 /*>>prefixed*/ 70057 70058 70059 /*>>cssclasses*/ 70060 // Remove "no-js" class from <html> element, if it exists: 70061 docElement.className = docElement.className.replace(/(^|\s)no-js(\s|$)/, '$1$2') + 70062 70063 // Add the new classes to the <html> element. 70064 (enableClasses ? ' js ' + classes.join(' ') : ''); 70065 /*>>cssclasses*/ 70066 70067 return Modernizr; 70068 70069})(this, this.document); 70070 70071define("modernizr", function(){}); 70072 70073/*global define:false */ 70074/** 70075 * Copyright 2013 Craig Campbell 70076 * 70077 * Licensed under the Apache License, Version 2.0 (the "License");
70078 * you may not use this file except in compliance with the License. 70079 * You may obtain a copy of the License at 70080 * 70081 * http://www.apache.org/licenses/LICENSE-2.0 70082 * 70083 * Unless required by applicable law or agreed to in writing, software 70084 * distributed under the License is distributed on an "AS IS" BASIS, 70085 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 70086 * See the License for the specific language governing permissions and 70087 * limitations under the License. 70088 * 70089 * Mousetrap is a simple keyboard shortcut library for Javascript with 70090 * no external dependencies 70091 * 70092 * @version 1.4.6 70093 * @url craig.is/killing/mice 70094 */ 70095(function(window, document, undefined) { 70096 70097 /** 70098 * mapping of special keycodes to their corresponding keys 70099 * 70100 * everything in this dictionary cannot use keypress events 70101 * so it has to be here to map to the correct keycodes for 70102 * keyup/keydown events 70103 * 70104 * @type {Object} 70105 */ 70106 var _MAP = { 70107 8: 'backspace', 70108 9: 'tab', 70109 13: 'enter', 70110 16: 'shift', 70111 17: 'ctrl', 70112 18: 'alt', 70113 20: 'capslock', 70114 27: 'esc', 70115 32: 'space', 70116 33: 'pageup', 70117 34: 'pagedown', 70118 35: 'end', 70119 36: 'home', 70120 37: 'left', 70121 38: 'up', 70122 39: 'right', 70123 40: 'down', 70124 45: 'ins', 70125 46: 'del', 70126 91: 'meta', 70127 93: 'meta', 70128 224: 'meta' 70129 }, 70130 70131 /** 70132 * mapping for special characters so they can support 70133 * 70134 * this dictionary is only used incase you want to bind a 70135 * keyup or keydown event to one of these keys 70136 * 70137 * @type {Object} 70138 */ 70139 _KEYCODE_MAP = { 70140 106: '*', 70141 107: '+', 70142 109: '-', 70143 110: '.', 70144 111 : '/', 70145 186: ';', 70146 187: '=', 70147 188: ',', 70148 189: '-', 70149 190: '.', 70150 191: '/', 70151 192: '`', 70152 219: '[', 70153 220: '\\', 70154 221: ']', 70155 222: '\'' 70156 }, 70157 70158 /** 70159 * this is a mapping of keys that require shift on a US keypad 70160 * back to the non shift equivelents 70161 * 70162 * this is so you can use keyup events with these keys 70163 * 70164 * note that this will only work reliably on US keyboards 70165 * 70166 * @type {Object} 70167 */ 70168 _SHIFT_MAP = { 70169 '~': '`', 70170 '!': '1', 70171 '@': '2', 70172 '#': '3', 70173 '$': '4', 70174 '%': '5', 70175 '^': '6', 70176 '&': '7', 70177 '*': '8', 70178 '(': '9', 70179 ')': '0', 70180 '_': '-', 70181 '+': '=', 70182 ':': ';', 70183 '\"': '\'', 70184 '<': ',', 70185 '>': '.', 70186 '?': '/', 70187 '|': '\\' 70188 }, 70189 70190 /** 70191 * this is a list of special strings you can use to map 70192 * to modifier keys when you specify your keyboard shortcuts 70193 * 70194 * @type {Object} 70195 */ 70196 _SPECIAL_ALIASES = { 70197 'option': 'alt', 70198 'command': 'meta', 70199 'return': 'enter', 70200 'escape': 'esc', 70201 'mod': /Mac|iPod|iPhone|iPad/.test(navigator.platform) ? 'meta' : 'ctrl' 70202 }, 70203 70204 /** 70205 * variable to store the flipped version of _MAP from above 70206 * needed to check if we should use keypress or not when no action 70207 * is specified 70208 * 70209 * @type {Object|undefined} 70210 */ 70211 _REVERSE_MAP, 70212 70213 /** 70214 * a list of all the callbacks setup via Mousetrap.bind() 70215 * 70216 * @type {Object} 70217 */ 70218 _callbacks = {}, 70219 70220 /** 70221 * direct map of string combinations to callbacks used for trigger() 70222 * 70223 * @type {Object} 70224 */ 70225 _directMap = {}, 70226 70227 /** 70228 * keeps track of what level each sequence is at since multiple 70229 * sequences can start out with the same sequence 70230 * 70231 * @type {Object} 70232 */ 70233 _sequenceLevels = {}, 70234 70235 /** 70236 * variable to store the setTimeout call 70237 * 70238 * @type {null|number} 70239 */ 70240 _resetTimer, 70241 70242 /** 70243 * temporary state where we will ignore the next keyup 70244 * 70245 * @type {boolean|string} 70246 */ 70247 _ignoreNextKeyup = false, 70248 70249 /** 70250 * temporary state where we will ignore the next keypress 70251 * 70252 * @type {boolean} 70253 */ 70254 _ignoreNextKeypress = false, 70255 70256 /** 70257 * are we currently inside of a sequence? 70258 * type of action ("keyup" or "keydown" or "keypress") or false 70259 * 70260 * @type {boolean|string} 70261 */ 70262 _nextExpectedAction = false;
vendor: 5,466 bytes, lines 70263-70432
70263 70264 /** 70265 * loop through the f keys, f1 to f19 and add them to the map 70266 * programatically 70267 */ 70268 for (var i = 1; i < 20; ++i) { 70269 _MAP[111 + i] = 'f' + i; 70270 } 70271 70272 /** 70273 * loop through to map numbers on the numeric keypad 70274 */ 70275 for (i = 0; i <= 9; ++i) { 70276 _MAP[i + 96] = i; 70277 } 70278 70279 /** 70280 * cross browser add event method 70281 * 70282 * @param {Element|HTMLDocument} object 70283 * @param {string} type 70284 * @param {Function} callback 70285 * @returns void 70286 */ 70287 function _addEvent(object, type, callback) { 70288 if (object.addEventListener) { 70289 object.addEventListener(type, callback, false); 70290 return; 70291 } 70292 70293 object.attachEvent('on' + type, callback); 70294 } 70295 70296 /** 70297 * takes the event and returns the key character 70298 * 70299 * @param {Event} e 70300 * @return {string} 70301 */ 70302 function _characterFromEvent(e) { 70303 70304 // for keypress events we should return the character as is 70305 if (e.type == 'keypress') { 70306 var character = String.fromCharCode(e.which); 70307 70308 // if the shift key is not pressed then it is safe to assume 70309 // that we want the character to be lowercase. this means if 70310 // you accidentally have caps lock on then your key bindings 70311 // will continue to work 70312 // 70313 // the only side effect that might not be desired is if you 70314 // bind something like 'A' cause you want to trigger an 70315 // event when capital A is pressed caps lock will no longer 70316 // trigger the event. shift+a will though. 70317 if (!e.shiftKey) { 70318 character = character.toLowerCase(); 70319 } 70320 70321 return character; 70322 } 70323 70324 // for non keypress events the special maps are needed 70325 if (_MAP[e.which]) { 70326 return _MAP[e.which]; 70327 } 70328 70329 if (_KEYCODE_MAP[e.which]) { 70330 return _KEYCODE_MAP[e.which]; 70331 } 70332 70333 // if it is not in the special map 70334 70335 // with keydown and keyup events the character seems to always 70336 // come in as an uppercase character whether you are pressing shift 70337 // or not. we should make sure it is always lowercase for comparisons 70338 return String.fromCharCode(e.which).toLowerCase(); 70339 } 70340 70341 /** 70342 * checks if two arrays are equal 70343 * 70344 * @param {Array} modifiers1 70345 * @param {Array} modifiers2 70346 * @returns {boolean} 70347 */ 70348 function _modifiersMatch(modifiers1, modifiers2) { 70349 return modifiers1.sort().join(',') === modifiers2.sort().join(','); 70350 } 70351 70352 /** 70353 * resets all sequence counters except for the ones passed in 70354 * 70355 * @param {Object} doNotReset 70356 * @returns void 70357 */ 70358 function _resetSequences(doNotReset) { 70359 doNotReset = doNotReset || {}; 70360 70361 var activeSequences = false, 70362 key; 70363 70364 for (key in _sequenceLevels) { 70365 if (doNotReset[key]) { 70366 activeSequences = true; 70367 continue; 70368 } 70369 _sequenceLevels[key] = 0; 70370 } 70371 70372 if (!activeSequences) { 70373 _nextExpectedAction = false; 70374 } 70375 } 70376 70377 /** 70378 * finds all callbacks that match based on the keycode, modifiers, 70379 * and action 70380 * 70381 * @param {string} character 70382 * @param {Array} modifiers 70383 * @param {Event|Object} e 70384 * @param {string=} sequenceName - name of the sequence we are looking for 70385 * @param {string=} combination 70386 * @param {number=} level 70387 * @returns {Array} 70388 */ 70389 function _getMatches(character, modifiers, e, sequenceName, combination, level) { 70390 var i, 70391 callback, 70392 matches = [], 70393 action = e.type; 70394 70395 // if there are no events related to this keycode 70396 if (!_callbacks[character]) { 70397 return []; 70398 } 70399 70400 // if a modifier key is coming up on its own we should allow it 70401 if (action == 'keyup' && _isModifier(character)) { 70402 modifiers = [character]; 70403 } 70404 70405 // loop through all callbacks for the key that was pressed 70406 // and see if any of them match 70407 for (i = 0; i < _callbacks[character].length; ++i) { 70408 callback = _callbacks[character][i]; 70409 70410 // if a sequence name is not specified, but this is a sequence at 70411 // the wrong level then move onto the next match 70412 if (!sequenceName && callback.seq && _sequenceLevels[callback.seq] != callback.level) { 70413 continue; 70414 } 70415 70416 // if the action we are looking for doesn't match the action we got 70417 // then we should keep going 70418 if (action != callback.action) { 70419 continue; 70420 } 70421 70422 // if this is a keypress event and the meta key and control key 70423 // are not pressed that means that we need to only look at the 70424 // character, otherwise check the modifiers as well 70425 // 70426 // chrome will not fire a keypress if meta or control is down 70427 // safari will fire a keypress if meta or meta+shift is down 70428 // firefox will fire a keypress if meta or control is down 70429 if ((action == 'keypress' && !e.metaKey && !e.ctrlKey) || _modifiersMatch(modifiers, callback.modifiers)) { 70430 70431 // when you bind a combination or sequence a second time it 70432 // should overwrite the first one. if a sequenceName or
vendor: 13,975 bytes, lines 70433-70869
70433 // combination is specified in this call it does just that 70434 // 70435 // @todo make deleting its own method? 70436 var deleteCombo = !sequenceName && callback.combo == combination; 70437 var deleteSequence = sequenceName && callback.seq == sequenceName && callback.level == level; 70438 if (deleteCombo || deleteSequence) { 70439 _callbacks[character].splice(i, 1); 70440 } 70441 70442 matches.push(callback); 70443 } 70444 } 70445 70446 return matches; 70447 } 70448 70449 /** 70450 * takes a key event and figures out what the modifiers are 70451 * 70452 * @param {Event} e 70453 * @returns {Array} 70454 */ 70455 function _eventModifiers(e) { 70456 var modifiers = []; 70457 70458 if (e.shiftKey) { 70459 modifiers.push('shift'); 70460 } 70461 70462 if (e.altKey) { 70463 modifiers.push('alt'); 70464 } 70465 70466 if (e.ctrlKey) { 70467 modifiers.push('ctrl'); 70468 } 70469 70470 if (e.metaKey) { 70471 modifiers.push('meta'); 70472 } 70473 70474 return modifiers; 70475 } 70476 70477 /** 70478 * prevents default for this event 70479 * 70480 * @param {Event} e 70481 * @returns void 70482 */ 70483 function _preventDefault(e) { 70484 if (e.preventDefault) { 70485 e.preventDefault(); 70486 return; 70487 } 70488 70489 e.returnValue = false; 70490 } 70491 70492 /** 70493 * stops propogation for this event 70494 * 70495 * @param {Event} e 70496 * @returns void 70497 */ 70498 function _stopPropagation(e) { 70499 if (e.stopPropagation) { 70500 e.stopPropagation(); 70501 return; 70502 } 70503 70504 e.cancelBubble = true; 70505 } 70506 70507 /** 70508 * actually calls the callback function 70509 * 70510 * if your callback function returns false this will use the jquery 70511 * convention - prevent default and stop propogation on the event 70512 * 70513 * @param {Function} callback 70514 * @param {Event} e 70515 * @returns void 70516 */ 70517 function _fireCallback(callback, e, combo, sequence) { 70518 70519 // if this event should not happen stop here 70520 if (Mousetrap.stopCallback(e, e.target || e.srcElement, combo, sequence)) { 70521 return; 70522 } 70523 70524 if (callback(e, combo) === false) { 70525 _preventDefault(e); 70526 _stopPropagation(e); 70527 } 70528 } 70529 70530 /** 70531 * handles a character key event 70532 * 70533 * @param {string} character 70534 * @param {Array} modifiers 70535 * @param {Event} e 70536 * @returns void 70537 */ 70538 function _handleKey(character, modifiers, e) { 70539 var callbacks = _getMatches(character, modifiers, e), 70540 i, 70541 doNotReset = {}, 70542 maxLevel = 0, 70543 processedSequenceCallback = false; 70544 70545 // Calculate the maxLevel for sequences so we can only execute the longest callback sequence 70546 for (i = 0; i < callbacks.length; ++i) { 70547 if (callbacks[i].seq) { 70548 maxLevel = Math.max(maxLevel, callbacks[i].level); 70549 } 70550 } 70551 70552 // loop through matching callbacks for this key event 70553 for (i = 0; i < callbacks.length; ++i) { 70554 70555 // fire for all sequence callbacks 70556 // this is because if for example you have multiple sequences 70557 // bound such as "g i" and "g t" they both need to fire the 70558 // callback for matching g cause otherwise you can only ever 70559 // match the first one 70560 if (callbacks[i].seq) { 70561 70562 // only fire callbacks for the maxLevel to prevent 70563 // subsequences from also firing 70564 // 70565 // for example 'a option b' should not cause 'option b' to fire 70566 // even though 'option b' is part of the other sequence 70567 // 70568 // any sequences that do not match here will be discarded 70569 // below by the _resetSequences call 70570 if (callbacks[i].level != maxLevel) { 70571 continue; 70572 } 70573 70574 processedSequenceCallback = true; 70575 70576 // keep a list of which sequences were matches for later 70577 doNotReset[callbacks[i].seq] = 1; 70578 _fireCallback(callbacks[i].callback, e, callbacks[i].combo, callbacks[i].seq); 70579 continue; 70580 } 70581 70582 // if there were no sequence matches but we are still here 70583 // that means this is a regular match so we should fire that 70584 if (!processedSequenceCallback) { 70585 _fireCallback(callbacks[i].callback, e, callbacks[i].combo); 70586 } 70587 } 70588 70589 // if the key you pressed matches the type of sequence without 70590 // being a modifier (ie "keyup" or "keypress") then we should 70591 // reset all sequences that were not matched by this event 70592 // 70593 // this is so, for example, if you have the sequence "h a t" and you 70594 // type "h e a r t" it does not match. in this case the "e" will 70595 // cause the sequence to reset 70596 // 70597 // modifier keys are ignored because you can have a sequence 70598 // that contains modifiers such as "enter ctrl+space" and in most 70599 // cases the modifier key will be pressed before the next key 70600 // 70601 // also if you have a sequence such as "ctrl+b a" then pressing the 70602 // "b" key will trigger a "keypress" and a "keydown" 70603 // 70604 // the "keydown" is expected when there is a modifier, but the 70605 // "keypress" ends up matching the _nextExpectedAction since it occurs 70606 // after and that causes the sequence to reset 70607 // 70608 // we ignore keypresses in a sequence that directly follow a keydown 70609 // for the same character 70610 var ignoreThisKeypress = e.type == 'keypress' && _ignoreNextKeypress; 70611 if (e.type == _nextExpectedAction && !_isModifier(character) && !ignoreThisKeypress) { 70612 _resetSequences(doNotReset); 70613 } 70614 70615 _ignoreNextKeypress = processedSequenceCallback && e.type == 'keydown'; 70616 } 70617 70618 /** 70619 * handles a keydown event 70620 * 70621 * @param {Event} e 70622 * @returns void 70623 */ 70624 function _handleKeyEvent(e) { 70625 70626 // normalize e.which for key events 70627 // @see http://stackoverflow.com/questions/4285627/javascript-keycode-vs-charcode-utter-confusion 70628 if (typeof e.which !== 'number') { 70629 e.which = e.keyCode; 70630 } 70631 70632 var character = _characterFromEvent(e); 70633 70634 // no character found then stop 70635 if (!character) { 70636 return; 70637 } 70638 70639 // need to use === for the character check because the character can be 0 70640 if (e.type == 'keyup' && _ignoreNextKeyup === character) { 70641 _ignoreNextKeyup = false; 70642 return; 70643 } 70644 70645 Mousetrap.handleKey(character, _eventModifiers(e), e); 70646 } 70647 70648 /** 70649 * determines if the keycode specified is a modifier key or not 70650 * 70651 * @param {string} key 70652 * @returns {boolean} 70653 */ 70654 function _isModifier(key) { 70655 return key == 'shift' || key == 'ctrl' || key == 'alt' || key == 'meta'; 70656 } 70657 70658 /** 70659 * called to set a 1 second timeout on the specified sequence 70660 * 70661 * this is so after each key press in the sequence you have 1 second 70662 * to press the next key before you have to start over 70663 * 70664 * @returns void 70665 */ 70666 function _resetSequenceTimer() { 70667 clearTimeout(_resetTimer); 70668 _resetTimer = setTimeout(_resetSequences, 1000); 70669 } 70670 70671 /** 70672 * reverses the map lookup so that we can look for specific keys 70673 * to see what can and can't use keypress 70674 * 70675 * @return {Object} 70676 */ 70677 function _getReverseMap() { 70678 if (!_REVERSE_MAP) { 70679 _REVERSE_MAP = {}; 70680 for (var key in _MAP) { 70681 70682 // pull out the numeric keypad from here cause keypress should 70683 // be able to detect the keys from the character 70684 if (key > 95 && key < 112) { 70685 continue; 70686 } 70687 70688 if (_MAP.hasOwnProperty(key)) { 70689 _REVERSE_MAP[_MAP[key]] = key; 70690 } 70691 } 70692 } 70693 return _REVERSE_MAP; 70694 } 70695 70696 /** 70697 * picks the best action based on the key combination 70698 * 70699 * @param {string} key - character for key 70700 * @param {Array} modifiers 70701 * @param {string=} action passed in 70702 */ 70703 function _pickBestAction(key, modifiers, action) { 70704 70705 // if no action was picked in we should try to pick the one 70706 // that we think would work best for this key 70707 if (!action) { 70708 action = _getReverseMap()[key] ? 'keydown' : 'keypress'; 70709 } 70710 70711 // modifier keys don't work as expected with keypress, 70712 // switch to keydown 70713 if (action == 'keypress' && modifiers.length) { 70714 action = 'keydown'; 70715 } 70716 70717 return action; 70718 } 70719 70720 /** 70721 * binds a key sequence to an event 70722 * 70723 * @param {string} combo - combo specified in bind call 70724 * @param {Array} keys 70725 * @param {Function} callback 70726 * @param {string=} action 70727 * @returns void 70728 */ 70729 function _bindSequence(combo, keys, callback, action) { 70730 70731 // start off by adding a sequence level record for this combination 70732 // and setting the level to 0 70733 _sequenceLevels[combo] = 0; 70734 70735 /** 70736 * callback to increase the sequence level for this sequence and reset 70737 * all other sequences that were active 70738 * 70739 * @param {string} nextAction 70740 * @returns {Function} 70741 */ 70742 function _increaseSequence(nextAction) { 70743 return function() { 70744 _nextExpectedAction = nextAction; 70745 ++_sequenceLevels[combo]; 70746 _resetSequenceTimer(); 70747 }; 70748 } 70749 70750 /** 70751 * wraps the specified callback inside of another function in order 70752 * to reset all sequence counters as soon as this sequence is done 70753 * 70754 * @param {Event} e 70755 * @returns void 70756 */ 70757 function _callbackAndReset(e) { 70758 _fireCallback(callback, e, combo); 70759 70760 // we should ignore the next key up if the action is key down 70761 // or keypress. this is so if you finish a sequence and 70762 // release the key the final key will not trigger a keyup 70763 if (action !== 'keyup') { 70764 _ignoreNextKeyup = _characterFromEvent(e); 70765 } 70766 70767 // weird race condition if a sequence ends with the key 70768 // another sequence begins with 70769 setTimeout(_resetSequences, 10); 70770 } 70771 70772 // loop through keys one at a time and bind the appropriate callback 70773 // function. for any key leading up to the final one it should 70774 // increase the sequence. after the final, it should reset all sequences 70775 // 70776 // if an action is specified in the original bind call then that will 70777 // be used throughout. otherwise we will pass the action that the 70778 // next key in the sequence should match. this allows a sequence 70779 // to mix and match keypress and keydown events depending on which 70780 // ones are better suited to the key provided 70781 for (var i = 0; i < keys.length; ++i) { 70782 var isFinal = i + 1 === keys.length; 70783 var wrappedCallback = isFinal ? _callbackAndReset : _increaseSequence(action || _getKeyInfo(keys[i + 1]).action); 70784 _bindSingle(keys[i], wrappedCallback, action, combo, i); 70785 } 70786 } 70787 70788 /** 70789 * Converts from a string key combination to an array 70790 * 70791 * @param {string} combination like "command+shift+l" 70792 * @return {Array} 70793 */ 70794 function _keysFromString(combination) { 70795 if (combination === '+') { 70796 return ['+']; 70797 } 70798 70799 return combination.split('+'); 70800 } 70801 70802 /** 70803 * Gets info for a specific key combination 70804 * 70805 * @param {string} combination key combination ("command+s" or "a" or "*") 70806 * @param {string=} action 70807 * @returns {Object} 70808 */ 70809 function _getKeyInfo(combination, action) { 70810 var keys, 70811 key, 70812 i, 70813 modifiers = []; 70814 70815 // take the keys from this pattern and figure out what the actual 70816 // pattern is all about 70817 keys = _keysFromString(combination); 70818 70819 for (i = 0; i < keys.length; ++i) { 70820 key = keys[i]; 70821 70822 // normalize key names 70823 if (_SPECIAL_ALIASES[key]) { 70824 key = _SPECIAL_ALIASES[key]; 70825 } 70826 70827 // if this is not a keypress event then we should 70828 // be smart about using shift keys 70829 // this will only work for US keyboards however 70830 if (action && action != 'keypress' && _SHIFT_MAP[key]) { 70831 key = _SHIFT_MAP[key]; 70832 modifiers.push('shift'); 70833 } 70834 70835 // if this key is a modifier then add it to the list of modifiers 70836 if (_isModifier(key)) { 70837 modifiers.push(key); 70838 } 70839 } 70840 70841 // depending on what the key combination is 70842 // we will try to pick the best event for it 70843 action = _pickBestAction(key, modifiers, action); 70844 70845 return { 70846 key: key, 70847 modifiers: modifiers, 70848 action: action 70849 }; 70850 } 70851 70852 /** 70853 * binds a single keyboard combination 70854 * 70855 * @param {string} combination 70856 * @param {Function} callback 70857 * @param {string=} action 70858 * @param {string=} sequenceName - name of sequence if part of sequence 70859 * @param {number=} level - what part of the sequence the command is 70860 * @returns void 70861 */ 70862 function _bindSingle(combination, callback, action, sequenceName, level) { 70863 70864 // store a direct mapped reference for use with Mousetrap.trigger 70865 _directMap[combination + ':' + action] = callback; 70866 70867 // make sure multiple spaces in a row become a single space 70868 combination = combination.replace(/\s+/g, ' '); 70869
70870 var sequence = combination.split(' '), 70871 info; 70872 70873 // if this pattern is a sequence of keys then run through this method 70874 // to reprocess each pattern one key at a time 70875 if (sequence.length > 1) { 70876 _bindSequence(combination, sequence, callback, action); 70877 return; 70878 } 70879 70880 info = _getKeyInfo(combination, action); 70881 70882 // make sure to initialize array if this is the first time 70883 // a callback is added for this key 70884 _callbacks[info.key] = _callbacks[info.key] || []; 70885 70886 // remove an existing match if there is one 70887 _getMatches(info.key, info.modifiers, {type: info.action}, sequenceName, combination, level); 70888 70889 // add this call back to the array 70890 // if it is a sequence put it at the beginning 70891 // if not put it at the end 70892 // 70893 // this is important because the way these are processed expects 70894 // the sequence ones to come first 70895 _callbacks[info.key][sequenceName ? 'unshift' : 'push']({ 70896 callback: callback, 70897 modifiers: info.modifiers, 70898 action: info.action, 70899 seq: sequenceName, 70900 level: level, 70901 combo: combination 70902 }); 70903 } 70904 70905 /** 70906 * binds multiple combinations to the same callback 70907 * 70908 * @param {Array} combinations 70909 * @param {Function} callback 70910 * @param {string|undefined} action 70911 * @returns void 70912 */ 70913 function _bindMultiple(combinations, callback, action) { 70914 for (var i = 0;
70914 i < combinations.length; ++i) { 70915 _bindSingle(combinations[i], callback, action); 70916 } 70917 } 70918 70919 // start! 70920 _addEvent(document, 'keypress', _handleKeyEvent); 70921 _addEvent(document, 'keydown', _handleKeyEvent); 70922 _addEvent(document, 'keyup', _handleKeyEvent); 70923 70924 var Mousetrap = { 70925 70926 /** 70927 * binds an event to mousetrap 70928 * 70929 * can be a single key, a combination of keys separated with +, 70930 * an array of keys, or a sequence of keys separated by spaces 70931 * 70932 * be sure to list the modifier keys first to make sure that the 70933 * correct key ends up getting bound (the last key in the pattern) 70934 * 70935 * @param {string|Array} keys 70936 * @param {Function} callback 70937 * @param {string=} action - 'keypress', 'keydown', or 'keyup' 70938 * @returns void 70939 */ 70940 bind: function(keys, callback, action) { 70941 keys = keys instanceof Array ? keys : [keys]; 70942 _bindMultiple(keys, callback, action); 70943 return this; 70944 }, 70945 70946 /** 70947 * unbinds an event to mousetrap 70948 * 70949 * the unbinding sets the callback function of the specified key combo 70950 * to an empty function and deletes the corresponding key in the 70951 * _directMap dict. 70952 * 70953 * TODO: actually remove this from the _callbacks dictionary instead 70954 * of binding an empty function 70955 * 70956 * the keycombo+action has to be exactly the same as 70957 * it was defined in the bind method 70958 * 70959 * @param {string|Array} keys 70960 * @param {string} action 70961 * @returns void 70962 */ 70963 unbind: function(keys, action) { 70964 return Mousetrap.bind(keys, function() {}, action); 70965 }, 70966 70967 /** 70968 * triggers an event that has already been bound 70969 * 70970 * @param {string} keys 70971 * @param {string=} action 70972 * @returns void 70973 */ 70974 trigger: function(keys, action) { 70975 if (_directMap[keys + ':' + action]) { 70976 _directMap[keys + ':' + action]({}, keys); 70977 } 70978 return this; 70979 }, 70980 70981 /** 70982 * resets the library back to its initial state. this is useful 70983 * if you want to clear out the current keyboard shortcuts and bind 70984 * new ones - for example if you switch to another page 70985 * 70986 * @returns void 70987 */ 70988 reset: function() { 70989 _callbacks = {}; 70990 _directMap = {}; 70991 return this; 70992 }, 70993 70994 /** 70995 * should we stop this event before firing off callbacks 70996 * 70997 * @param {Event} e 70998 * @param {Element} element 70999 * @return {boolean} 71000 */ 71001 stopCallback: function(e, element) { 71002 71003 // if the element has the class "mousetrap" then no need to stop 71004 if ((' ' + element.className + ' ').indexOf(' mousetrap ') > -1) { 71005 return false; 71006 } 71007 71008 // stop for input, select, and textarea 71009 return element.tagName == 'INPUT' || element.tagName == 'SELECT' || element.tagName == 'TEXTAREA' || element.isContentEditable; 71010 }, 71011 71012 /** 71013 * exposes _handleKey publicly so it can be overwritten by extensions 71014 */ 71015 handleKey: _handleKey 71016 }; 71017 71018 // expose mousetrap to the global object 71019 window.Mousetrap = Mousetrap; 71020 71021 // expose mousetrap as an AMD module 71022 if (typeof define === 'function' && define.amd) { 71023 define('mousetrap',Mousetrap); 71024 } 71025}) (window, document); 71026 71027/* ----------------------------------------------- 71028/* Author : Vincent Garreau - vincentgarreau.com 71029/* MIT license: http://opensource.org/licenses/MIT 71030/* Demo / Generator : vincentgarreau.com/particles.js 71031/* GitHub : github.com/VincentGarreau/particles.js 71032/* How to use? : Check the GitHub README 71033/* v2.0.0 71034/* ----------------------------------------------- */ 71035 71036var pJS = function(tag_id, params){ 71037 71038 var canvas_el = document.querySelector('#'+tag_id+' > .particles-js-canvas-el'); 71039 71040 /* particles.js variables with default values */ 71041 this.pJS = { 71042 canvas: { 71043 el: canvas_el, 71044 w: canvas_el.offsetWidth, 71045 h: canvas_el.offsetHeight 71046 }, 71047 particles: { 71048 number: { 71049 value: 400, 71050 density: { 71051 enable: true, 71052 value_area: 800 71053 } 71054 }, 71055 color: { 71056 value: '#fff' 71057 }, 71058 shape: { 71059 type: 'circle', 71060 stroke: { 71061 width: 0, 71062 color: '#ff0000' 71063 }, 71064 polygon: { 71065 nb_sides: 5 71066 }, 71067 image: { 71068 src: '', 71069 src_list: [], 71070 width: 100, 71071 height: 100 71072 } 71073 }, 71074 opacity: { 71075 value: 1, 71076 random: false, 71077 anim: { 71078 enable: false, 71079 speed: 2, 71080 opacity_min: 0, 71081 sync: false 71082 } 71083 }, 71084 size: { 71085 value: 20, 71086 random: false, 71087 anim: { 71088 enable: false, 71089 speed: 20, 71090 size_min: 0, 71091 sync: false 71092 } 71093 }, 71094 line_linked: { 71095 enable: true, 71096 distance: 100, 71097 color: '#fff', 71098 opacity: 1, 71099 width: 1 71100 }, 71101 move: { 71102 enable: true, 71103 speed: 2, 71104 direction: 'none', 71105 random: false, 71106 straight: false, 71107 out_mode: 'out', 71108 bounce: false, 71109 attract: { 71110 enable: false, 71111 rotateX: 3000, 71112 rotateY: 3000 71113 } 71114 }, 71115 array: [] 71116 }, 71117 interactivity: { 71118 detect_on: 'canvas', 71119 events: { 71120 onhover: { 71121 enable: true, 71122 mode: 'grab' 71123 }, 71124 onclick: { 71125 enable: true, 71126 mode: 'push' 71127 }, 71128 resize: true 71129 }, 71130 modes: { 71131 grab:{ 71132 distance: 100, 71133 line_linked:{ 71134 opacity: 1 71135 } 71136 }, 71137 bubble:{ 71138 distance: 200, 71139 size: 80, 71140 duration: 0.4 71141 }, 71142 repulse:{ 71143 distance: 200, 71144 duration: 0.4 71145 }, 71146 push:{ 71147 particles_nb: 4 71148 }, 71149 remove:{ 71150 particles_nb: 2 71151 } 71152 }, 71153 mouse:{} 71154 }, 71155 retina_detect: false, 71156 fn: { 71157 interact: {}, 71158 modes: {}, 71159 vendors:{} 71160 }, 71161 tmp: {} 71162 }; 71163 71164 var pJS = this.pJS; 71165 71166 /* params settings */ 71167 if(params){
vendor: 33,566 bytes, lines 71168-72262
71168 Object.deepExtend(pJS, params); 71169 } 71170 71171 pJS.tmp.obj = { 71172 size_value: pJS.particles.size.value, 71173 size_anim_speed: pJS.particles.size.anim.speed, 71174 move_speed: pJS.particles.move.speed, 71175 line_linked_distance: pJS.particles.line_linked.distance, 71176 line_linked_width: pJS.particles.line_linked.width, 71177 mode_grab_distance: pJS.interactivity.modes.grab.distance, 71178 mode_bubble_distance: pJS.interactivity.modes.bubble.distance, 71179 mode_bubble_size: pJS.interactivity.modes.bubble.size, 71180 mode_repulse_distance: pJS.interactivity.modes.repulse.distance 71181 }; 71182 71183 pJS.tmp.source_svg_list = [] 71184 pJS.tmp.count_svg = 0 71185 71186 pJS.fn.retinaInit = function(){ 71187 71188 if(pJS.retina_detect && window.devicePixelRatio > 1){ 71189 pJS.canvas.pxratio = window.devicePixelRatio; 71190 pJS.tmp.retina = true; 71191 } 71192 else{ 71193 pJS.canvas.pxratio = 1; 71194 pJS.tmp.retina = false; 71195 } 71196 71197 pJS.canvas.w = pJS.canvas.el.offsetWidth * pJS.canvas.pxratio; 71198 pJS.canvas.h = pJS.canvas.el.offsetHeight * pJS.canvas.pxratio; 71199 71200 pJS.particles.size.value = pJS.tmp.obj.size_value * pJS.canvas.pxratio; 71201 pJS.particles.size.anim.speed = pJS.tmp.obj.size_anim_speed * pJS.canvas.pxratio; 71202 pJS.particles.move.speed = pJS.tmp.obj.move_speed * pJS.canvas.pxratio; 71203 pJS.particles.line_linked.distance = pJS.tmp.obj.line_linked_distance * pJS.canvas.pxratio; 71204 pJS.interactivity.modes.grab.distance = pJS.tmp.obj.mode_grab_distance * pJS.canvas.pxratio; 71205 pJS.interactivity.modes.bubble.distance = pJS.tmp.obj.mode_bubble_distance * pJS.canvas.pxratio; 71206 pJS.particles.line_linked.width = pJS.tmp.obj.line_linked_width * pJS.canvas.pxratio; 71207 pJS.interactivity.modes.bubble.size = pJS.tmp.obj.mode_bubble_size * pJS.canvas.pxratio; 71208 pJS.interactivity.modes.repulse.distance = pJS.tmp.obj.mode_repulse_distance * pJS.canvas.pxratio; 71209 71210 }; 71211 71212 71213 71214 /* ---------- pJS functions - canvas ------------ */ 71215 71216 pJS.fn.canvasInit = function(){ 71217 pJS.canvas.ctx = pJS.canvas.el.getContext('2d'); 71218 }; 71219 71220 pJS.fn.canvasSize = function(){ 71221 71222 pJS.canvas.el.width = pJS.canvas.w; 71223 pJS.canvas.el.height = pJS.canvas.h; 71224 71225 if(pJS && pJS.interactivity.events.resize){ 71226 71227 window.addEventListener('resize', function(){ 71228 71229 pJS.canvas.w = pJS.canvas.el.offsetWidth; 71230 pJS.canvas.h = pJS.canvas.el.offsetHeight; 71231 71232 /* resize canvas */ 71233 if(pJS.tmp.retina){ 71234 pJS.canvas.w *= pJS.canvas.pxratio; 71235 pJS.canvas.h *= pJS.canvas.pxratio; 71236 } 71237 71238 pJS.canvas.el.width = pJS.canvas.w; 71239 pJS.canvas.el.height = pJS.canvas.h; 71240 71241 /* repaint canvas on anim disabled */ 71242 if(!pJS.particles.move.enable){ 71243 pJS.fn.particlesEmpty(); 71244 pJS.fn.particlesCreate(); 71245 pJS.fn.particlesDraw(); 71246 pJS.fn.vendors.densityAutoParticles(); 71247 } 71248 71249 /* density particles enabled */ 71250 pJS.fn.vendors.densityAutoParticles(); 71251 71252 }); 71253 71254 } 71255 71256 }; 71257 71258 71259 pJS.fn.canvasPaint = function(){ 71260 pJS.canvas.ctx.fillRect(0, 0, pJS.canvas.w, pJS.canvas.h); 71261 }; 71262 71263 pJS.fn.canvasClear = function(){ 71264 pJS.canvas.ctx.clearRect(0, 0, pJS.canvas.w, pJS.canvas.h); 71265 }; 71266 71267 71268 /* --------- pJS functions - particles ----------- */ 71269 71270 pJS.fn.particle = function(color, opacity, position){ 71271 71272 /* size */ 71273 this.radius = (pJS.particles.size.random ? Math.random() : 1) * pJS.particles.size.value; 71274 if(pJS.particles.size.anim.enable){ 71275 this.size_status = false; 71276 this.vs = pJS.particles.size.anim.speed / 100; 71277 if(!pJS.particles.size.anim.sync){ 71278 this.vs = this.vs * Math.random(); 71279 } 71280 } 71281 71282 /* position */ 71283 this.x = position ? position.x : Math.random() * pJS.canvas.w; 71284 this.y = position ? position.y : Math.random() * pJS.canvas.h; 71285 71286 /* check position - into the canvas */ 71287 if(this.x > pJS.canvas.w - this.radius*2) this.x = this.x - this.radius; 71288 else if(this.x < this.radius*2) this.x = this.x + this.radius; 71289 if(this.y > pJS.canvas.h - this.radius*2) this.y = this.y - this.radius; 71290 else if(this.y < this.radius*2) this.y = this.y + this.radius; 71291 71292 /* check position - avoid overlap */ 71293 if(pJS.particles.move.bounce){ 71294 pJS.fn.vendors.checkOverlap(this, position); 71295 } 71296 71297 /* color */ 71298 this.color = {}; 71299 if(typeof(color.value) == 'object'){ 71300 71301 if(color.value instanceof Array){ 71302 var color_selected = color.value[Math.floor(Math.random() * pJS.particles.color.value.length)]; 71303 this.color.rgb = hexToRgb(color_selected); 71304 }else{ 71305 if(color.value.r != undefined && color.value.g != undefined && color.value.b != undefined){ 71306 this.color.rgb = { 71307 r: color.value.r, 71308 g: color.value.g, 71309 b: color.value.b 71310 } 71311 } 71312 if(color.value.h != undefined && color.value.s != undefined && color.value.l != undefined){ 71313 this.color.hsl = { 71314 h: color.value.h, 71315 s: color.value.s, 71316 l: color.value.l 71317 } 71318 } 71319 } 71320 71321 } 71322 else if(color.value == 'random'){ 71323 this.color.rgb = { 71324 r: (Math.floor(Math.random() * (255 - 0 + 1)) + 0), 71325 g: (Math.floor(Math.random() * (255 - 0 + 1)) + 0), 71326 b: (Math.floor(Math.random() * (255 - 0 + 1)) + 0) 71327 } 71328 } 71329 else if(typeof(color.value) == 'string'){ 71330 this.color = color; 71331 this.color.rgb = hexToRgb(this.color.value); 71332 } 71333 71334 /* opacity */ 71335 this.opacity = (pJS.particles.opacity.random ? Math.random() : 1) * pJS.particles.opacity.value; 71336 if(pJS.particles.opacity.anim.enable){ 71337 this.opacity_status = false; 71338 this.vo = pJS.particles.opacity.anim.speed / 100; 71339 if(!pJS.particles.opacity.anim.sync){ 71340 this.vo = this.vo * Math.random(); 71341 } 71342 } 71343 71344 /* animation - velocity for speed */ 71345 var velbase = {} 71346 switch(pJS.particles.move.direction){ 71347 case 'top': 71348 velbase = { x:0, y:-1 }; 71349 break; 71350 case 'top-right': 71351 velbase = { x:0.5, y:-0.5 }; 71352 break; 71353 case 'right': 71354 velbase = { x:1, y:-0 }; 71355 break; 71356 case 'bottom-right': 71357 velbase = { x:0.5, y:0.5 }; 71358 break; 71359 case 'bottom': 71360 velbase = { x:0, y:1 }; 71361 break; 71362 case 'bottom-left': 71363 velbase = { x:-0.5, y:1 }; 71364 break; 71365 case 'left': 71366 velbase = { x:-1, y:0 }; 71367 break; 71368 case 'top-left': 71369 velbase = { x:-0.5, y:-0.5 }; 71370 break; 71371 default: 71372 velbase = { x:0, y:0 }; 71373 break; 71374 } 71375 71376 if(pJS.particles.move.straight){ 71377 this.vx = velbase.x; 71378 this.vy = velbase.y; 71379 if(pJS.particles.move.random){ 71380 this.vx = this.vx * (Math.random()); 71381 this.vy = this.vy * (Math.random()); 71382 } 71383 }else{ 71384 this.vx = velbase.x + Math.random()-0.5; 71385 this.vy = velbase.y + Math.random()-0.5; 71386 } 71387 71388 // var theta = 2.0 * Math.PI * Math.random(); 71389 // this.vx = Math.cos(theta); 71390 // this.vy = Math.sin(theta); 71391 71392 this.vx_i = this.vx; 71393 this.vy_i = this.vy; 71394 71395 71396 71397 /* if shape is image */ 71398 71399 var shape_type = pJS.particles.shape.type; 71400 if(typeof(shape_type) == 'object'){ 71401 if(shape_type instanceof Array){ 71402 var shape_selected = shape_type[Math.floor(Math.random() * shape_type.length)]; 71403 this.shape = shape_selected; 71404 } 71405 }else{ 71406 this.shape = shape_type; 71407 } 71408 71409 if(this.shape == 'image'){ 71410 var sh = pJS.particles.shape; 71411 this.img = { 71412 src: sh.image.src, 71413 ratio: sh.image.width / sh.image.height 71414 } 71415 if(!this.img.ratio) this.img.ratio = 1; 71416 if(pJS.tmp.source_svg_list.length){ 71417 var random = Math.floor(Math.random() * pJS.tmp.source_svg_list.length) 71418 this.img.src = sh.image.src_list[random] 71419 pJS.fn.vendors.createSvgImg(this, pJS.tmp.source_svg_list[random]); 71420 if(pJS.tmp.pushing){ 71421 this.img.loaded = false; 71422 } 71423 71424 } else if(pJS.tmp.img_type == 'svg' && pJS.tmp.source_svg != undefined){ 71425 pJS.fn.vendors.createSvgImg(this, pJS.tmp.source_svg); 71426 if(pJS.tmp.pushing){ 71427 this.img.loaded = false; 71428 } 71429 } 71430 } 71431 }; 71432 71433 71434 pJS.fn.particle.prototype.draw = function() { 71435 var p = this; 71436 71437 if(p.radius_bubble != undefined){ 71438 var radius = p.radius_bubble; 71439 }else{ 71440 var radius = p.radius; 71441 } 71442 71443 if(p.opacity_bubble != undefined){ 71444 var opacity = p.opacity_bubble; 71445 }else{ 71446 var opacity = p.opacity; 71447 } 71448 71449 if(p.color.rgb){ 71450 var color_value = 'rgba('+p.color.rgb.r+','+p.color.rgb.g+','+p.color.rgb.b+','+opacity+')'; 71451 }else{ 71452 var color_value = 'hsla('+p.color.hsl.h+','+p.color.hsl.s+'%,'+p.color.hsl.l+'%,'+opacity+')'; 71453 } 71454 71455 pJS.canvas.ctx.fillStyle = color_value; 71456 pJS.canvas.ctx.beginPath(); 71457 71458 switch(p.shape){ 71459 71460 case 'circle': 71461 pJS.canvas.ctx.arc(p.x, p.y, radius, 0, Math.PI * 2, false); 71462 break; 71463 71464 case 'edge': 71465 pJS.canvas.ctx.rect(p.x-radius, p.y-radius, radius*2, radius*2); 71466 break; 71467 71468 case 'triangle': 71469 pJS.fn.vendors.drawShape(pJS.canvas.ctx, p.x-radius, p.y+radius / 1.66, radius*2, 3, 2); 71470 break; 71471 71472 case 'polygon': 71473 pJS.fn.vendors.drawShape( 71474 pJS.canvas.ctx, 71475 p.x - radius / (pJS.particles.shape.polygon.nb_sides/3.5), // startX 71476 p.y - radius / (2.66/3.5), // startY 71477 radius*2.66 / (pJS.particles.shape.polygon.nb_sides/3), // sideLength 71478 pJS.particles.shape.polygon.nb_sides, // sideCountNumerator 71479 1 // sideCountDenominator 71480 ); 71481 break; 71482 71483 case 'star': 71484 pJS.fn.vendors.drawShape( 71485 pJS.canvas.ctx, 71486 p.x - radius*2 / (pJS.particles.shape.polygon.nb_sides/4), // startX 71487 p.y - radius / (2*2.66/3.5), // startY 71488 radius*2*2.66 / (pJS.particles.shape.polygon.nb_sides/3), // sideLength 71489 pJS.particles.shape.polygon.nb_sides, // sideCountNumerator 71490 2 // sideCountDenominator 71491 ); 71492 break; 71493 71494 case 'image': 71495 71496 function draw(){ 71497 pJS.canvas.ctx.drawImage( 71498 img_obj, 71499 p.x-radius, 71500 p.y-radius, 71501 radius*2, 71502 radius*2 / p.img.ratio 71503 ); 71504 } 71505 71506 if(pJS.tmp.img_type == 'svg'){ 71507 var img_obj = p.img.obj; 71508 }else{ 71509 var img_obj = pJS.tmp.img_obj; 71510 } 71511 71512 if(img_obj){ 71513 draw(); 71514 } 71515 71516 break; 71517 71518 } 71519 71520 pJS.canvas.ctx.closePath(); 71521 71522 if(pJS.particles.shape.stroke.width > 0){ 71523 pJS.canvas.ctx.strokeStyle = pJS.particles.shape.stroke.color; 71524 pJS.canvas.ctx.lineWidth = pJS.particles.shape.stroke.width; 71525 pJS.canvas.ctx.stroke(); 71526 } 71527 71528 pJS.canvas.ctx.fill(); 71529 71530 }; 71531 71532 71533 pJS.fn.particlesCreate = function(){ 71534 for(var i = 0; i < pJS.particles.number.value; i++) { 71535 pJS.particles.array.push(new pJS.fn.particle(pJS.particles.color, pJS.particles.opacity.value)); 71536 } 71537 }; 71538 71539 pJS.fn.particlesUpdate = function(){ 71540 71541 for(var i = 0; i < pJS.particles.array.length; i++){ 71542 71543 /* the particle */ 71544 var p = pJS.particles.array[i]; 71545 71546 // var d = ( dx = pJS.interactivity.mouse.click_pos_x - p.x ) * dx + ( dy = pJS.interactivity.mouse.click_pos_y - p.y ) * dy; 71547 // var f = -BANG_SIZE / d; 71548 // if ( d < BANG_SIZE ) { 71549 // var t = Math.atan2( dy, dx ); 71550 // p.vx = f * Math.cos(t); 71551 // p.vy = f * Math.sin(t); 71552 // } 71553 71554 /* move the particle */ 71555 if(pJS.particles.move.enable){ 71556 var ms = pJS.particles.move.speed/2; 71557 p.x += p.vx * ms; 71558 p.y += p.vy * ms; 71559 } 71560 71561 /* change opacity status */ 71562 if(pJS.particles.opacity.anim.enable) { 71563 if(p.opacity_status == true) { 71564 if(p.opacity >= pJS.particles.opacity.value) p.opacity_status = false; 71565 p.opacity += p.vo; 71566 }else { 71567 if(p.opacity <= pJS.particles.opacity.anim.opacity_min) p.opacity_status = true; 71568 p.opacity -= p.vo; 71569 } 71570 if(p.opacity < 0) p.opacity = 0; 71571 } 71572 71573 /* change size */ 71574 if(pJS.particles.size.anim.enable){ 71575 if(p.size_status == true){ 71576 if(p.radius >= pJS.particles.size.value) p.size_status = false; 71577 p.radius += p.vs; 71578 }else{ 71579 if(p.radius <= pJS.particles.size.anim.size_min) p.size_status = true; 71580 p.radius -= p.vs; 71581 } 71582 if(p.radius < 0) p.radius = 0; 71583 } 71584 71585 /* change particle position if it is out of canvas */ 71586 if(pJS.particles.move.out_mode == 'bounce'){ 71587 var new_pos = { 71588 x_left: p.radius, 71589 x_right: pJS.canvas.w, 71590 y_top: p.radius, 71591 y_bottom: pJS.canvas.h 71592 } 71593 }else{ 71594 var new_pos = { 71595 x_left: -p.radius, 71596 x_right: pJS.canvas.w + p.radius, 71597 y_top: -p.radius, 71598 y_bottom: pJS.canvas.h + p.radius 71599 } 71600 } 71601 71602 if(p.x - p.radius > pJS.canvas.w){ 71603 p.x = new_pos.x_left; 71604 p.y = Math.random() * pJS.canvas.h; 71605 } 71606 else if(p.x + p.radius < 0){ 71607 p.x = new_pos.x_right; 71608 p.y = Math.random() * pJS.canvas.h; 71609 } 71610 if(p.y - p.radius > pJS.canvas.h){ 71611 p.y = new_pos.y_top; 71612 p.x = Math.random() * pJS.canvas.w; 71613 } 71614 else if(p.y + p.radius < 0){ 71615 p.y = new_pos.y_bottom; 71616 p.x = Math.random() * pJS.canvas.w; 71617 } 71618 71619 /* out of canvas modes */ 71620 switch(pJS.particles.move.out_mode){ 71621 case 'bounce': 71622 if (p.x + p.radius > pJS.canvas.w) p.vx = -p.vx; 71623 else if (p.x - p.radius < 0) p.vx = -p.vx; 71624 if (p.y + p.radius > pJS.canvas.h) p.vy = -p.vy; 71625 else if (p.y - p.radius < 0) p.vy = -p.vy; 71626 break; 71627 } 71628 71629 /* events */ 71630 if(isInArray('grab', pJS.interactivity.events.onhover.mode)){ 71631 pJS.fn.modes.grabParticle(p); 71632 } 71633 71634 if(isInArray('bubble', pJS.interactivity.events.onhover.mode) || isInArray('bubble', pJS.interactivity.events.onclick.mode)){ 71635 pJS.fn.modes.bubbleParticle(p); 71636 } 71637 71638 if(isInArray('repulse', pJS.interactivity.events.onhover.mode) || isInArray('repulse', pJS.interactivity.events.onclick.mode)){ 71639 pJS.fn.modes.repulseParticle(p); 71640 } 71641 71642 /* interaction auto between particles */ 71643 if(pJS.particles.line_linked.enable || pJS.particles.move.attract.enable){ 71644 for(var j = i + 1; j < pJS.particles.array.length; j++){ 71645 var p2 = pJS.particles.array[j]; 71646 71647 /* link particles */ 71648 if(pJS.particles.line_linked.enable){ 71649 pJS.fn.interact.linkParticles(p,p2); 71650 } 71651 71652 /* attract particles */ 71653 if(pJS.particles.move.attract.enable){ 71654 pJS.fn.interact.attractParticles(p,p2); 71655 } 71656 71657 /* bounce particles */ 71658 if(pJS.particles.move.bounce){ 71659 pJS.fn.interact.bounceParticles(p,p2); 71660 } 71661 71662 } 71663 } 71664 71665 71666 } 71667 71668 }; 71669 71670 pJS.fn.particlesDraw = function(){ 71671 71672 /* clear canvas */ 71673 pJS.canvas.ctx.clearRect(0, 0, pJS.canvas.w, pJS.canvas.h); 71674 71675 /* update each particles param */ 71676 pJS.fn.particlesUpdate(); 71677 71678 /* draw each particle */ 71679 for(var i = 0; i < pJS.particles.array.length; i++){ 71680 var p = pJS.particles.array[i]; 71681 p.draw(); 71682 } 71683 71684 }; 71685 71686 pJS.fn.particlesEmpty = function(){ 71687 pJS.particles.array = []; 71688 }; 71689 71690 pJS.fn.particlesRefresh = function(){ 71691 71692 /* init all */ 71693 cancelRequestAnimFrame(pJS.fn.checkAnimFrame); 71694 cancelRequestAnimFrame(pJS.fn.drawAnimFrame); 71695 pJS.tmp.source_svg = undefined; 71696 pJS.tmp.source_svg_list = []; 71697 pJS.tmp.img_obj = undefined; 71698 pJS.tmp.count_svg = 0; 71699 pJS.fn.particlesEmpty(); 71700 pJS.fn.canvasClear(); 71701 71702 /* restart */ 71703 pJS.fn.vendors.start(); 71704 71705 }; 71706 71707 71708 /* ---------- pJS functions - particles interaction ------------ */ 71709 71710 pJS.fn.interact.linkParticles = function(p1, p2){ 71711 71712 var dx = p1.x - p2.x, 71713 dy = p1.y - p2.y, 71714 dist = Math.sqrt(dx*dx + dy*dy); 71715 71716 /* draw a line between p1 and p2 if the distance between them is under the config distance */ 71717 if(dist <= pJS.particles.line_linked.distance){ 71718 71719 var opacity_line = pJS.particles.line_linked.opacity - (dist / (1/pJS.particles.line_linked.opacity)) / pJS.particles.line_linked.distance; 71720 71721 if(opacity_line > 0){ 71722 71723 /* style */ 71724 var color_line = pJS.particles.line_linked.color_rgb_line; 71725 pJS.canvas.ctx.strokeStyle = 'rgba('+color_line.r+','+color_line.g+','+color_line.b+','+opacity_line+')'; 71726 pJS.canvas.ctx.lineWidth = pJS.particles.line_linked.width; 71727 //pJS.canvas.ctx.lineCap = 'round'; /* performance issue */ 71728 71729 /* path */ 71730 pJS.canvas.ctx.beginPath(); 71731 pJS.canvas.ctx.moveTo(p1.x, p1.y); 71732 pJS.canvas.ctx.lineTo(p2.x, p2.y); 71733 pJS.canvas.ctx.stroke(); 71734 pJS.canvas.ctx.closePath(); 71735 71736 } 71737 71738 } 71739 71740 }; 71741 71742 71743 pJS.fn.interact.attractParticles = function(p1, p2){ 71744 71745 /* condensed particles */ 71746 var dx = p1.x - p2.x, 71747 dy = p1.y - p2.y, 71748 dist = Math.sqrt(dx*dx + dy*dy); 71749 71750 if(dist <= pJS.particles.line_linked.distance){ 71751 71752 var ax = dx/(pJS.particles.move.attract.rotateX*1000), 71753 ay = dy/(pJS.particles.move.attract.rotateY*1000); 71754 71755 p1.vx -= ax; 71756 p1.vy -= ay; 71757 71758 p2.vx += ax; 71759 p2.vy += ay; 71760 71761 } 71762 71763 71764 } 71765 71766 71767 pJS.fn.interact.bounceParticles = function(p1, p2){ 71768 71769 var dx = p1.x - p2.x, 71770 dy = p1.y - p2.y, 71771 dist = Math.sqrt(dx*dx + dy*dy), 71772 dist_p = p1.radius+p2.radius; 71773 71774 if(dist <= dist_p){ 71775 p1.vx = -p1.vx; 71776 p1.vy = -p1.vy; 71777 71778 p2.vx = -p2.vx; 71779 p2.vy = -p2.vy; 71780 } 71781 71782 } 71783 71784 71785 /* ---------- pJS functions - modes events ------------ */ 71786 71787 pJS.fn.modes.pushParticles = function(nb, pos){ 71788 71789 pJS.tmp.pushing = true; 71790 71791 for(var i = 0; i < nb; i++){ 71792 pJS.particles.array.push( 71793 new pJS.fn.particle( 71794 pJS.particles.color, 71795 pJS.particles.opacity.value, 71796 { 71797 'x': pos ? pos.pos_x : Math.random() * pJS.canvas.w, 71798 'y': pos ? pos.pos_y : Math.random() * pJS.canvas.h 71799 } 71800 ) 71801 ) 71802 if(i == nb-1){ 71803 if(!pJS.particles.move.enable){ 71804 pJS.fn.particlesDraw(); 71805 } 71806 pJS.tmp.pushing = false; 71807 } 71808 } 71809 71810 }; 71811 71812 71813 pJS.fn.modes.removeParticles = function(nb){ 71814 71815 pJS.particles.array.splice(0, nb); 71816 if(!pJS.particles.move.enable){ 71817 pJS.fn.particlesDraw(); 71818 } 71819 71820 }; 71821 71822 71823 pJS.fn.modes.bubbleParticle = function(p){ 71824 71825 /* on hover event */ 71826 if(pJS.interactivity.events.onhover.enable && isInArray('bubble', pJS.interactivity.events.onhover.mode)){ 71827 71828 var dx_mouse = p.x - pJS.interactivity.mouse.pos_x, 71829 dy_mouse = p.y - pJS.interactivity.mouse.pos_y, 71830 dist_mouse = Math.sqrt(dx_mouse*dx_mouse + dy_mouse*dy_mouse), 71831 ratio = 1 - dist_mouse / pJS.interactivity.modes.bubble.distance; 71832 71833 function init(){ 71834 p.opacity_bubble = p.opacity; 71835 p.radius_bubble = p.radius; 71836 } 71837 71838 /* mousemove - check ratio */ 71839 if(dist_mouse <= pJS.interactivity.modes.bubble.distance){ 71840 71841 if(ratio >= 0 && pJS.interactivity.status == 'mousemove'){ 71842 71843 /* size */ 71844 if(pJS.interactivity.modes.bubble.size != pJS.particles.size.value){ 71845 71846 if(pJS.interactivity.modes.bubble.size > pJS.particles.size.value){ 71847 var size = p.radius + (pJS.interactivity.modes.bubble.size*ratio); 71848 if(size >= 0){ 71849 p.radius_bubble = size; 71850 } 71851 }else{ 71852 var dif = p.radius - pJS.interactivity.modes.bubble.size, 71853 size = p.radius - (dif*ratio); 71854 if(size > 0){ 71855 p.radius_bubble = size; 71856 }else{ 71857 p.radius_bubble = 0; 71858 } 71859 } 71860 71861 } 71862 71863 /* opacity */ 71864 if(pJS.interactivity.modes.bubble.opacity != pJS.particles.opacity.value){ 71865 71866 if(pJS.interactivity.modes.bubble.opacity > pJS.particles.opacity.value){ 71867 var opacity = pJS.interactivity.modes.bubble.opacity*ratio; 71868 if(opacity > p.opacity && opacity <= pJS.interactivity.modes.bubble.opacity){ 71869 p.opacity_bubble = opacity; 71870 } 71871 }else{ 71872 var opacity = p.opacity - (pJS.particles.opacity.value-pJS.interactivity.modes.bubble.opacity)*ratio; 71873 if(opacity < p.opacity && opacity >= pJS.interactivity.modes.bubble.opacity){ 71874 p.opacity_bubble = opacity; 71875 } 71876 } 71877 71878 } 71879 71880 } 71881 71882 }else{ 71883 init(); 71884 } 71885 71886 71887 /* mouseleave */ 71888 if(pJS.interactivity.status == 'mouseleave'){ 71889 init(); 71890 } 71891 71892 } 71893 71894 /* on click event */ 71895 else if(pJS.interactivity.events.onclick.enable && isInArray('bubble', pJS.interactivity.events.onclick.mode)){ 71896 71897 71898 if(pJS.tmp.bubble_clicking){ 71899 var dx_mouse = p.x - pJS.interactivity.mouse.click_pos_x, 71900 dy_mouse = p.y - pJS.interactivity.mouse.click_pos_y, 71901 dist_mouse = Math.sqrt(dx_mouse*dx_mouse + dy_mouse*dy_mouse), 71902 time_spent = (new Date().getTime() - pJS.interactivity.mouse.click_time)/1000; 71903 71904 if(time_spent > pJS.interactivity.modes.bubble.duration){ 71905 pJS.tmp.bubble_duration_end = true; 71906 } 71907 71908 if(time_spent > pJS.interactivity.modes.bubble.duration*2){ 71909 pJS.tmp.bubble_clicking = false; 71910 pJS.tmp.bubble_duration_end = false; 71911 } 71912 } 71913 71914 71915 function process(bubble_param, particles_param, p_obj_bubble, p_obj, id){ 71916 71917 if(bubble_param != particles_param){ 71918 71919 if(!pJS.tmp.bubble_duration_end){ 71920 if(dist_mouse <= pJS.interactivity.modes.bubble.distance){ 71921 if(p_obj_bubble != undefined) var obj = p_obj_bubble; 71922 else var obj = p_obj; 71923 if(obj != bubble_param){ 71924 var value = p_obj - (time_spent * (p_obj - bubble_param) / pJS.interactivity.modes.bubble.duration); 71925 if(id == 'size') p.radius_bubble = value; 71926 if(id == 'opacity') p.opacity_bubble = value; 71927 } 71928 }else{ 71929 if(id == 'size') p.radius_bubble = undefined; 71930 if(id == 'opacity') p.opacity_bubble = undefined; 71931 } 71932 }else{ 71933 if(p_obj_bubble != undefined){ 71934 var value_tmp = p_obj - (time_spent * (p_obj - bubble_param) / pJS.interactivity.modes.bubble.duration), 71935 dif = bubble_param - value_tmp; 71936 value = bubble_param + dif; 71937 if(id == 'size') p.radius_bubble = value; 71938 if(id == 'opacity') p.opacity_bubble = value; 71939 } 71940 } 71941 71942 } 71943 71944 } 71945 71946 if(pJS.tmp.bubble_clicking){ 71947 /* size */ 71948 process(pJS.interactivity.modes.bubble.size, pJS.particles.size.value, p.radius_bubble, p.radius, 'size'); 71949 /* opacity */ 71950 process(pJS.interactivity.modes.bubble.opacity, pJS.particles.opacity.value, p.opacity_bubble, p.opacity, 'opacity'); 71951 } 71952 71953 } 71954 71955 }; 71956 71957 71958 pJS.fn.modes.repulseParticle = function(p){ 71959 71960 if(pJS.interactivity.events.onhover.enable && isInArray('repulse', pJS.interactivity.events.onhover.mode) && pJS.interactivity.status == 'mousemove') { 71961 71962 var dx_mouse = p.x - pJS.interactivity.mouse.pos_x, 71963 dy_mouse = p.y - pJS.interactivity.mouse.pos_y, 71964 dist_mouse = Math.sqrt(dx_mouse*dx_mouse + dy_mouse*dy_mouse); 71965 71966 var normVec = {x: dx_mouse/dist_mouse, y: dy_mouse/dist_mouse}, 71967 repulseRadius = pJS.interactivity.modes.repulse.distance, 71968 velocity = 100, 71969 repulseFactor = clamp((1/repulseRadius)*(-1*Math.pow(dist_mouse/repulseRadius,2)+1)*repulseRadius*velocity, 0, 50); 71970 71971 var pos = { 71972 x: p.x + normVec.x * repulseFactor, 71973 y: p.y + normVec.y * repulseFactor 71974 } 71975 71976 if(pJS.particles.move.out_mode == 'bounce'){ 71977 if(pos.x - p.radius > 0 && pos.x + p.radius < pJS.canvas.w) p.x = pos.x; 71978 if(pos.y - p.radius > 0 && pos.y + p.radius < pJS.canvas.h) p.y = pos.y; 71979 }else{ 71980 p.x = pos.x; 71981 p.y = pos.y; 71982 } 71983 71984 } 71985 71986 71987 else if(pJS.interactivity.events.onclick.enable && isInArray('repulse', pJS.interactivity.events.onclick.mode)) { 71988 71989 if(!pJS.tmp.repulse_finish){ 71990 pJS.tmp.repulse_count++; 71991 if(pJS.tmp.repulse_count == pJS.particles.array.length){ 71992 pJS.tmp.repulse_finish = true; 71993 } 71994 } 71995 71996 if(pJS.tmp.repulse_clicking){ 71997 71998 var repulseRadius = Math.pow(pJS.interactivity.modes.repulse.distance/6, 3); 71999 72000 var dx = pJS.interactivity.mouse.click_pos_x - p.x, 72001 dy = pJS.interactivity.mouse.click_pos_y - p.y, 72002 d = dx*dx + dy*dy; 72003 72004 var force = -repulseRadius / d * 1; 72005 72006 function process(){ 72007 72008 var f = Math.atan2(dy,dx); 72009 p.vx = force * Math.cos(f); 72010 p.vy = force * Math.sin(f); 72011 72012 if(pJS.particles.move.out_mode == 'bounce'){ 72013 var pos = { 72014 x: p.x + p.vx, 72015 y: p.y + p.vy 72016 } 72017 if (pos.x + p.radius > pJS.canvas.w) p.vx = -p.vx; 72018 else if (pos.x - p.radius < 0) p.vx = -p.vx; 72019 if (pos.y + p.radius > pJS.canvas.h) p.vy = -p.vy; 72020 else if (pos.y - p.radius < 0) p.vy = -p.vy; 72021 } 72022 72023 } 72024 72025 // default 72026 if(d <= repulseRadius){ 72027 process(); 72028 } 72029 72030 // bang - slow motion mode 72031 // if(!pJS.tmp.repulse_finish){ 72032 // if(d <= repulseRadius){ 72033 // process(); 72034 // } 72035 // }else{ 72036 // process(); 72037 // } 72038 72039 72040 }else{ 72041 72042 if(pJS.tmp.repulse_clicking == false){ 72043 72044 p.vx = p.vx_i; 72045 p.vy = p.vy_i; 72046 72047 } 72048 72049 } 72050 72051 } 72052 72053 } 72054 72055 72056 pJS.fn.modes.grabParticle = function(p){ 72057 72058 if(pJS.interactivity.events.onhover.enable && pJS.interactivity.status == 'mousemove'){ 72059 72060 var dx_mouse = p.x - pJS.interactivity.mouse.pos_x, 72061 dy_mouse = p.y - pJS.interactivity.mouse.pos_y, 72062 dist_mouse = Math.sqrt(dx_mouse*dx_mouse + dy_mouse*dy_mouse); 72063 72064 /* draw a line between the cursor and the particle if the distance between them is under the config distance */ 72065 if(dist_mouse <= pJS.interactivity.modes.grab.distance){ 72066 72067 var opacity_line = pJS.interactivity.modes.grab.line_linked.opacity - (dist_mouse / (1/pJS.interactivity.modes.grab.line_linked.opacity)) / pJS.interactivity.modes.grab.distance; 72068 72069 if(opacity_line > 0){ 72070 72071 /* style */ 72072 var color_line = pJS.particles.line_linked.color_rgb_line; 72073 pJS.canvas.ctx.strokeStyle = 'rgba('+color_line.r+','+color_line.g+','+color_line.b+','+opacity_line+')'; 72074 pJS.canvas.ctx.lineWidth = pJS.particles.line_linked.width; 72075 //pJS.canvas.ctx.lineCap = 'round'; /* performance issue */ 72076 72077 /* path */ 72078 pJS.canvas.ctx.beginPath(); 72079 pJS.canvas.ctx.moveTo(p.x, p.y); 72080 pJS.canvas.ctx.lineTo(pJS.interactivity.mouse.pos_x, pJS.interactivity.mouse.pos_y); 72081 pJS.canvas.ctx.stroke(); 72082 pJS.canvas.ctx.closePath(); 72083 72084 } 72085 72086 } 72087 72088 } 72089 72090 }; 72091 72092 72093 72094 /* ---------- pJS functions - vendors ------------ */ 72095 72096 pJS.fn.vendors.eventsListeners = function(){ 72097 72098 /* events target element */ 72099 if(pJS.interactivity.detect_on == 'window'){ 72100 pJS.interactivity.el = window; 72101 }else{ 72102 pJS.interactivity.el = pJS.canvas.el; 72103 } 72104 72105 72106 /* detect mouse pos - on hover / click event */ 72107 if(pJS.interactivity.events.onhover.enable || pJS.interactivity.events.onclick.enable){ 72108 72109 /* el on mousemove */ 72110 pJS.interactivity.el.addEventListener('mousemove', function(e){ 72111 72112 if(pJS.interactivity.el == window){ 72113 var pos_x = e.clientX, 72114 pos_y = e.clientY; 72115 } 72116 else{ 72117 var pos_x = e.offsetX || e.clientX, 72118 pos_y = e.offsetY || e.clientY; 72119 } 72120 72121 pJS.interactivity.mouse.pos_x = pos_x; 72122 pJS.interactivity.mouse.pos_y = pos_y; 72123 72124 if(pJS.tmp.retina){ 72125 pJS.interactivity.mouse.pos_x *= pJS.canvas.pxratio; 72126 pJS.interactivity.mouse.pos_y *= pJS.canvas.pxratio; 72127 } 72128 72129 pJS.interactivity.status = 'mousemove'; 72130 72131 }); 72132 72133 /* el on onmouseleave */ 72134 pJS.interactivity.el.addEventListener('mouseleave', function(e){ 72135 72136 pJS.interactivity.mouse.pos_x = null; 72137 pJS.interactivity.mouse.pos_y = null; 72138 pJS.interactivity.status = 'mouseleave'; 72139 72140 }); 72141 72142 } 72143 72144 /* on click event */ 72145 if(pJS.interactivity.events.onclick.enable){ 72146 72147 pJS.interactivity.el.addEventListener('click', function(){ 72148 72149 pJS.interactivity.mouse.click_pos_x = pJS.interactivity.mouse.pos_x; 72150 pJS.interactivity.mouse.click_pos_y = pJS.interactivity.mouse.pos_y; 72151 pJS.interactivity.mouse.click_time = new Date().getTime(); 72152 72153 if(pJS.interactivity.events.onclick.enable){ 72154 72155 switch(pJS.interactivity.events.onclick.mode){ 72156 72157 case 'push': 72158 if(pJS.particles.move.enable){ 72159 pJS.fn.modes.pushParticles(pJS.interactivity.modes.push.particles_nb, pJS.interactivity.mouse); 72160 }else{ 72161 if(pJS.interactivity.modes.push.particles_nb == 1){ 72162 pJS.fn.modes.pushParticles(pJS.interactivity.modes.push.particles_nb, pJS.interactivity.mouse); 72163 } 72164 else if(pJS.interactivity.modes.push.particles_nb > 1){ 72165 pJS.fn.modes.pushParticles(pJS.interactivity.modes.push.particles_nb); 72166 } 72167 } 72168 break; 72169 72170 case 'remove': 72171 pJS.fn.modes.removeParticles(pJS.interactivity.modes.remove.particles_nb); 72172 break; 72173 72174 case 'bubble': 72175 pJS.tmp.bubble_clicking = true; 72176 break; 72177 72178 case 'repulse': 72179 pJS.tmp.repulse_clicking = true; 72180 pJS.tmp.repulse_count = 0; 72181 pJS.tmp.repulse_finish = false; 72182 setTimeout(function(){ 72183 pJS.tmp.repulse_clicking = false; 72184 }, pJS.interactivity.modes.repulse.duration*1000) 72185 break; 72186 72187 } 72188 72189 } 72190 72191 }); 72192 72193 } 72194 72195 72196 }; 72197 72198 pJS.fn.vendors.densityAutoParticles = function(){ 72199 72200 if(pJS.particles.number.density.enable){ 72201 72202 /* calc area */ 72203 var area = pJS.canvas.el.width * pJS.canvas.el.height / 1000; 72204 if(pJS.tmp.retina){ 72205 area = area/(pJS.canvas.pxratio*2); 72206 } 72207 72208 /* calc number of particles based on density area */ 72209 var nb_particles = area * pJS.particles.number.value / pJS.particles.number.density.value_area; 72210 72211 /* add or remove X particles */ 72212 var missing_particles = pJS.particles.array.length - nb_particles; 72213 if(missing_particles < 0) pJS.fn.modes.pushParticles(Math.abs(missing_particles)); 72214 else pJS.fn.modes.removeParticles(missing_particles); 72215 72216 } 72217 72218 }; 72219 72220 72221 pJS.fn.vendors.checkOverlap = function(p1, position){ 72222 for(var i = 0; i < pJS.particles.array.length; i++){ 72223 var p2 = pJS.particles.array[i]; 72224 72225 var dx = p1.x - p2.x, 72226 dy = p1.y - p2.y, 72227 dist = Math.sqrt(dx*dx + dy*dy); 72228 72229 if(dist <= p1.radius + p2.radius){ 72230 p1.x = position ? position.x : Math.random() * pJS.canvas.w; 72231 p1.y = position ? position.y : Math.random() * pJS.canvas.h; 72232 pJS.fn.vendors.checkOverlap(p1); 72233 } 72234 } 72235 }; 72236 72237 72238 pJS.fn.vendors.createSvgImg = function(p, source_svg){ 72239 /* set color to svg element */ 72240 var svgXml = source_svg, 72241 rgbHex = /#([0-9A-F]{3,6})/gi, 72242 coloredSvgXml = svgXml.replace(rgbHex, function (m, r, g, b) { 72243 if(p.color.rgb){ 72244 var color_value = 'rgba('+p.color.rgb.r+','+p.color.rgb.g+','+p.color.rgb.b+','+p.opacity+')'; 72245 }else{ 72246 var color_value = 'hsla('+p.color.hsl.h+','+p.color.hsl.s+'%,'+p.color.hsl.l+'%,'+p.opacity+')'; 72247 } 72248 return color_value; 72249 }); 72250 72251 /* prepare to create img with colored svg */ 72252 var svg = new Blob([coloredSvgXml], {type: 'image/svg+xml;charset=utf-8'}), 72253 DOMURL = window.URL || window.webkitURL || window, 72254 url = DOMURL.createObjectURL(svg); 72255 /* create particle img obj */ 72256 var img = new Image(); 72257 img.addEventListener('load', function(){ 72258 p.img.obj = img; 72259 p.img.loaded = true; 72260 DOMURL.revokeObjectURL(url); 72261 pJS.tmp.count_svg++; 72262 });
72263 img.src = url; 72264 }; 72265 72266 72267 pJS.fn.vendors.destroypJS = function(){ 72268 cancelAnimationFrame(pJS.fn.drawAnimFrame); 72269 canvas_el.remove(); 72270 pJSDom = null; 72271 }; 72272 72273 72274 pJS.fn.vendors.drawShape = function(c, startX, startY, sideLength, sideCountNumerator, sideCountDenominator){ 72275 72276 // By Programming Thomas - https://programmingthomas.wordpress.com/2013/04/03/n-sided-shapes/ 72277 var sideCount = sideCountNumerator * sideCountDenominator; 72278 var decimalSides = sideCountNumerator / sideCountDenominator; 72279 var interiorAngleDegrees = (180 * (decimalSides - 2)) / decimalSides; 72280 var interiorAngle = Math.PI - Math.PI * interiorAngleDegrees / 180; // convert to radians 72281 c.save(); 72282 c.beginPath(); 72283 c.translate(startX, startY); 72284 c.moveTo(0,0); 72285 for (var i = 0; i < sideCount; i++) { 72286 c.lineTo(sideLength,0); 72287 c.translate(sideLength,0); 72288 c.rotate(interiorAngle); 72289 } 72290 //c.stroke(); 72291 c.fill(); 72292 c.restore(); 72293 72294 }; 72295 72296 pJS.fn.vendors.exportImg = function(){ 72297 window.open(pJS.canvas.el.toDataURL('image/png'), '_blank'); 72298 }; 72299 72300 72301 pJS.fn.vendors.loadImg = function(type){ 72302 72303 pJS.tmp.img_error = undefined; 72304 if(pJS.particles.shape.image.src_list && pJS.particles.shape.image.src_list.length >= 2){ 72305 // type svg support only 72306 var xhrList = [] 72307 for(var i in pJS.particles.shape.image.src_list){ 72308 (function(index){ 72309 xhrList[index] = new XMLHttpRequest(); 72310 xhrList[index].open('GET', pJS.particles.shape.image.src_list[index]); 72311 xhrList[index].onreadystatechange = function(data){ 72312 if(xhrList[index].readyState == 4 && xhrList[index].status == 200){ 72313 72314 pJS.tmp.source_svg_list[index] = data.currentTarget.response 72315 72316 // Check whether all the images are loaded. You cannot 72317 // rely on the index 72318 var isLoaded = true; 72319 72320 for (var j in pJS.particles.shape.image.src_list){ 72321 if (pJS.tmp.source_svg_list[j] === undefined) { 72322 isLoaded = false; 72323 } 72324 } 72325 72326 if (isLoaded) { 72327 pJS.fn.vendors.checkBeforeDraw(); 72328 } 72329 } 72330 } 72331 xhrList[index].send() 72332 })(i) 72333 } 72334 return 72335 } 72336 72337 if(pJS.particles.shape.image.src != ''){ 72338 if(type == 'svg'){ 72339 var xhr = new XMLHttpRequest(); 72340 xhr.open('GET', pJS.particles.shape.image.src); 72341 xhr.onreadystatechange = function (data) { 72342 if(xhr.readyState == 4){ 72343 if(xhr.status == 200){ 72344 pJS.tmp.source_svg = data.currentTarget.response; 72345 pJS.fn.vendors.checkBeforeDraw(); 72346 }else{ 72347 console.log('Error pJS - Image not found'); 72348 pJS.tmp.img_error = true; 72349 } 72350 } 72351 } 72352 xhr.send(); 72353 }else{ 72354 var img = new Image(); 72355 img.addEventListener('load', function(){ 72356 pJS.tmp.img_obj = img; 72357 pJS.fn.vendors.checkBeforeDraw(); 72358 }); 72359 img.src = pJS.particles.shape.image.src; 72360 } 72361 } 72362 else{ 72363 if( ! pJS.particles.shape.image.src_list || pJS.particles.shape.image.src_list.length < 2){ 72364 console.log('Error pJS - No image.src'); 72365 pJS.tmp.img_error = true; 72366 } 72367 } 72368 72369 }; 72370 72371 72372 pJS.fn.vendors.draw = function(){ 72373 if(pJS.particles.shape.type == 'image'){ 72374 if(pJS.tmp.img_type == 'svg'){ 72375 if(pJS.tmp.count_svg >= pJS.particles.number.value){ 72376 pJS.fn.particlesDraw(); 72377 if(!pJS.particles.move.enable) cancelRequestAnimFrame(pJS.fn.drawAnimFrame); 72378 else pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw); 72379 }else{ 72380 //console.log('still loading...'); 72381 if(!pJS.tmp.img_error) pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw); 72382 } 72383 }else{ 72384 if(pJS.tmp.img_obj != undefined){ 72385 pJS.fn.particlesDraw();
vendor: 5,769 bytes, lines 72386-72592
72386 if(!pJS.particles.move.enable) cancelRequestAnimFrame(pJS.fn.drawAnimFrame); 72387 else pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw); 72388 }else{ 72389 if(!pJS.tmp.img_error) pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw); 72390 } 72391 } 72392 }else{ 72393 pJS.fn.particlesDraw(); 72394 if(!pJS.particles.move.enable) cancelRequestAnimFrame(pJS.fn.drawAnimFrame); 72395 else pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw); 72396 } 72397 72398 }; 72399 72400 72401 pJS.fn.vendors.checkBeforeDraw = function(){ 72402 72403 // if shape is image 72404 if(pJS.tmp.source_svg_list.length){ 72405 pJS.fn.vendors.init(); 72406 pJS.fn.vendors.draw(); 72407 return 72408 } 72409 if(pJS.particles.shape.type == 'image'){ 72410 if(pJS.tmp.img_type == 'svg' && pJS.tmp.source_svg == undefined){ 72411 pJS.tmp.checkAnimFrame = requestAnimFrame(check); 72412 }else{ 72413 //console.log('images loaded! cancel check'); 72414 cancelRequestAnimFrame(pJS.tmp.checkAnimFrame); 72415 if(!pJS.tmp.img_error){ 72416 pJS.fn.vendors.init(); 72417 pJS.fn.vendors.draw(); 72418 } 72419 72420 } 72421 72422 }else{ 72423 pJS.fn.vendors.init(); 72424 pJS.fn.vendors.draw(); 72425 } 72426 72427 }; 72428 72429 72430 pJS.fn.vendors.init = function(){ 72431 72432 /* init canvas + particles */ 72433 pJS.fn.retinaInit(); 72434 pJS.fn.canvasInit(); 72435 pJS.fn.canvasSize(); 72436 pJS.fn.canvasPaint(); 72437 pJS.fn.particlesCreate(); 72438 pJS.fn.vendors.densityAutoParticles(); 72439 72440 /* particles.line_linked - convert hex colors to rgb */ 72441 pJS.particles.line_linked.color_rgb_line = hexToRgb(pJS.particles.line_linked.color); 72442 72443 }; 72444 72445 72446 pJS.fn.vendors.start = function(){ 72447 72448 if(isInArray('image', pJS.particles.shape.type)){ 72449 var src_split = pJS.particles.shape.image.src.split("."); 72450 var type = src_split[ src_split.length - 1 >= 0 ? src_split.length - 1 : '' ] 72451 pJS.tmp.img_type = type ? type.toLowerCase() : 'svg'; 72452 pJS.fn.vendors.loadImg(pJS.tmp.img_type); 72453 }else{ 72454 pJS.fn.vendors.checkBeforeDraw(); 72455 } 72456 72457 }; 72458 72459 72460 72461 72462 /* ---------- pJS - start ------------ */ 72463 72464 72465 pJS.fn.vendors.eventsListeners(); 72466 72467 pJS.fn.vendors.start(); 72468 72469 72470 72471}; 72472 72473/* ---------- global functions - vendors ------------ */ 72474 72475Object.deepExtend = function(destination, source) { 72476 for (var property in source) { 72477 if (source[property] && source[property].constructor && 72478 source[property].constructor === Object) { 72479 destination[property] = destination[property] || {}; 72480 arguments.callee(destination[property], source[property]); 72481 } else { 72482 destination[property] = source[property]; 72483 } 72484 } 72485 return destination; 72486}; 72487 72488window.requestAnimFrame = (function(){ 72489 return window.requestAnimationFrame || 72490 window.webkitRequestAnimationFrame || 72491 window.mozRequestAnimationFrame || 72492 window.oRequestAnimationFrame || 72493 window.msRequestAnimationFrame || 72494 function(callback){ 72495 window.setTimeout(callback, 1000 / 60); 72496 }; 72497})(); 72498 72499window.cancelRequestAnimFrame = ( function() { 72500 return window.cancelAnimationFrame || 72501 window.webkitCancelRequestAnimationFrame || 72502 window.mozCancelRequestAnimationFrame || 72503 window.oCancelRequestAnimationFrame || 72504 window.msCancelRequestAnimationFrame || 72505 clearTimeout 72506} )(); 72507 72508function hexToRgb(hex){ 72509 // By Tim Down - http://stackoverflow.com/a/5624139/3493650 72510 // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF") 72511 var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i; 72512 hex = hex.replace(shorthandRegex, function(m, r, g, b) { 72513 return r + r + g + g + b + b; 72514 }); 72515 var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); 72516 return result ? { 72517 r: parseInt(result[1], 16), 72518 g: parseInt(result[2], 16), 72519 b: parseInt(result[3], 16) 72520 } : null; 72521}; 72522 72523function clamp(number, min, max) { 72524 return Math.min(Math.max(number, min), max); 72525}; 72526 72527function isInArray(value, array) { 72528 return array.indexOf(value) > -1; 72529} 72530 72531 72532/* ---------- particles.js functions - start ------------ */ 72533 72534window.pJSDom = []; 72535 72536window.particlesJS = function(tag_id, params){ 72537 72538 //console.log(params); 72539 72540 /* no string id? so it's object params, and set the id with default id */ 72541 if(typeof(tag_id) != 'string'){ 72542 params = tag_id; 72543 tag_id = 'particles-js'; 72544 } 72545 72546 /* no id? set the id to default id */ 72547 if(!tag_id){ 72548 tag_id = 'particles-js'; 72549 } 72550 72551 /* pJS elements */ 72552 var pJS_tag = document.getElementById(tag_id), 72553 pJS_canvas_class = 'particles-js-canvas-el', 72554 exist_canvas = pJS_tag.getElementsByClassName(pJS_canvas_class); 72555 72556 /* remove canvas if exists into the pJS target tag */ 72557 if(exist_canvas.length){ 72558 while(exist_canvas.length > 0){ 72559 pJS_tag.removeChild(exist_canvas[0]); 72560 } 72561 } 72562 72563 /* create canvas element */ 72564 var canvas_el = document.createElement('canvas'); 72565 canvas_el.className = pJS_canvas_class; 72566 72567 /* set size canvas */ 72568 canvas_el.style.width = "100%"; 72569 canvas_el.style.height = "100%"; 72570 72571 /* append canvas */ 72572 var canvas = document.getElementById(tag_id).appendChild(canvas_el); 72573 72574 /* launch particle.js */ 72575 if(canvas != null){ 72576 pJSDom.push(new pJS(tag_id, params)); 72577 } 72578 72579}; 72580 72581window.particlesJS.load = function(tag_id, path_config_json, callback){ 72582 72583 /* load json config */ 72584 var xhr = new XMLHttpRequest(); 72585 xhr.open('GET', path_config_json); 72586 xhr.onreadystatechange = function (data) { 72587 if(xhr.readyState == 4){ 72588 if(xhr.status == 200){ 72589 var params = JSON.parse(data.currentTarget.response); 72590 window.particlesJS(tag_id, params); 72591 if(callback) callback(); 72592 }else{
72593 console.log('Error pJS - XMLHttpRequest status: '+xhr.status); 72594 console.log('Error pJS - File config not found'); 72595 } 72596 } 72597 }; 72598 xhr.send(); 72599 72600}; 72601define("particles", function(){}); 72602 72603/*global ActiveXObject, window, console, define, module, jQuery */ 72604//jshint unused:false, strict: false 72605 72606/** 72607 * PDFObject v2.1.1 72608 * https://github.com/pipwerks/PDFObject 72609 * @license 72610 * Copyright (c) 2008-2018 Philip Hutchison 72611 * MIT-style license: http://pipwerks.mit-license.org/ 72612 * UMD module pattern from https://github.com/umdjs/umd/blob/master/templates/returnExports.js 72613 */ 72614 72615(function (root, factory) { 72616 if (typeof define === 'function' && define.amd) { 72617 // AMD. Register as an anonymous module. 72618 define('pdfobject',[], factory); 72619 } else if (typeof module === 'object' && module.exports) { 72620 // Node. Does not work with strict CommonJS, but 72621 // only CommonJS-like environments that support module.exports, 72622 // like Node. 72623 module.exports = factory(); 72624 } else { 72625 // Browser globals (root is window) 72626 root.PDFObject = factory(); 72627 } 72628}(this, function () { 72629 72630 "use strict"; 72631 //jshint unused:true 72632 72633 //PDFObject is designed for client-side (browsers), not server-side (node) 72634 //Will choke on undefined navigator and window vars when run on server 72635 //Return boolean false and exit function when running server-side 72636 72637 if(typeof window === "undefined" || typeof navigator === "undefined"){ return false; } 72638 72639 var pdfobjectversion = "2.1.1", 72640 ua = window.navigator.userAgent, 72641 72642 //declare booleans 72643 supportsPDFs, 72644 isIE, 72645 supportsPdfMimeType = (typeof navigator.mimeTypes !== "undefined" && typeof navigator.mimeTypes['application/pdf'] !== "undefined"), 72646 supportsPdfActiveX, 72647 isModernBrowser = (function (){ return (typeof window.Promise !== "undefined"); })(), 72648 isFirefox = (function (){ return (ua.indexOf("irefox") !== -1); } )(), 72649 isFirefoxWithPDFJS = (function (){ 72650 //Firefox started shipping PDF.js in Firefox 19. 72651 //If this is Firefox 19 or greater, assume PDF.js is available 72652 if(!isFirefox){ return false; } 72653 //parse userAgent string to get release version ("rv") 72654 //ex: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:57.0) Gecko/20100101 Firefox/57.0 72655 return (parseInt(ua.split("rv:")[1].split(".")[0], 10) > 18); 72656 })(), 72657 isIOS = (function (){ return (/iphone|ipad|ipod/i.test(ua.toLowerCase())); })(), 72658 72659 //declare functions 72660 createAXO, 72661 buildFragmentString, 72662 log, 72663 embedError, 72664 embed, 72665 getTargetElement, 72666 generatePDFJSiframe, 72667 generateEmbedElement; 72668 72669 72670 /* ---------------------------------------------------- 72671 Supporting functions 72672 ---------------------------------------------------- */ 72673 72674 createAXO = function (type){ 72675 var ax; 72676 try { 72677 ax = new ActiveXObject(type); 72678 } catch (e) { 72679 ax = null; //ensure ax remains null 72680 } 72681 return ax; 72682 }; 72683 72684 //IE11 still uses ActiveX for Adobe Reader, but IE 11 doesn't expose 72685 //window.ActiveXObject the same way previous versions of IE did 72686 //window.ActiveXObject will evaluate to false in IE 11, but "ActiveXObject" in window evaluates to true 72687 //so check the first one for older IE, and the second for IE11 72688 //FWIW, MS Edge (replacing IE11) does not support ActiveX at all, both will evaluate false 72689 //Constructed as a method (not a prop) to avoid unneccesarry overhead -- will only be evaluated if needed 72690 isIE = function (){ return !!(window.ActiveXObject || "ActiveXObject" in window); }; 72691 72692 //If either ActiveX support for "AcroPDF.PDF" or "PDF.PdfCtrl" are found, return true 72693 //Constructed as a method (not a prop) to avoid unneccesarry overhead -- will only be evaluated if needed 72694 supportsPdfActiveX = function (){ return !!(createAXO("AcroPDF.PDF") || createAXO("PDF.PdfCtrl")); }; 72695 72696 //Determines whether PDF support is available 72697 supportsPDFs = ( 72698 //as of iOS 12, inline PDF rendering is still not supported in Safari or native webview
72699 //3rd-party browsers (eg Chrome, Firefox) use Apple's webview for rendering, and thus the same result as Safari 72700 //Therefore if iOS, we shall assume that PDF support is not available 72701 !isIOS && ( 72702 //Modern versions of Firefox come bundled with PDFJS 72703 isFirefoxWithPDFJS || 72704 //Browsers that still support the original MIME type check 72705 supportsPdfMimeType || ( 72706 //Pity the poor souls still using IE 72707 isIE() && supportsPdfActiveX() 72708 ) 72709 ) 72710 ); 72711 72712 //Create a fragment identifier for using PDF Open parameters when embedding PDF 72713 buildFragmentString = function(pdfParams){ 72714 72715 var string = "", 72716 prop; 72717 72718 if(pdfParams){ 72719 72720 for (prop in pdfParams) { 72721 if (pdfParams.hasOwnProperty(prop)) { 72722 string += encodeURIComponent(prop) + "=" + encodeURIComponent(pdfParams[prop]) + "&"; 72723 } 72724 } 72725 72726 //The string will be empty if no PDF Params found 72727 if(string){ 72728 72729 string = "#" + string; 72730 72731 //Remove last ampersand 72732 string = string.slice(0, string.length - 1); 72733 72734 } 72735 72736 } 72737 72738 return string; 72739 72740 }; 72741 72742 log = function (msg){ 72743 if(typeof console !== "undefined" && console.log){ 72744 console.log("[PDFObject] " + msg); 72745 } 72746 }; 72747 72748 embedError = function (msg){ 72749 log(msg); 72750 return false; 72751 }; 72752 72753 getTargetElement = function (targetSelector){ 72754 72755 //Default to body for full-browser PDF 72756 var targetNode = document.body; 72757 72758 //If a targetSelector is specified, check to see whether 72759 //it's passing a selector, jQuery object, or an HTML element 72760 72761 if(typeof targetSelector === "string"){ 72762 72763 //Is CSS selector 72764 targetNode = document.querySelector(targetSelector); 72765 72766 } else if (typeof jQuery !== "undefined" && targetSelector instanceof jQuery && targetSelector.length) { 72767 72768 //Is jQuery element. Extract HTML node 72769 targetNode = targetSelector.get(0); 72770 72771 } else if (typeof targetSelector.nodeType !== "undefined" && targetSelector.nodeType === 1){ 72772 72773 //Is HTML element 72774 targetNode = targetSelector; 72775 72776 } 72777 72778 return targetNode; 72779 72780 }; 72781 72782 generatePDFJSiframe = function (targetNode, url, pdfOpenFragment, PDFJS_URL, id){ 72783 72784 var fullURL = PDFJS_URL + "?file=" + encodeURIComponent(url) + pdfOpenFragment; 72785 var scrollfix = (isIOS) ? "-webkit-overflow-scrolling: touch; overflow-y: scroll; " : "overflow: hidden; "; 72786 var iframe = "<div style='" + scrollfix + "position: absolute; top: 0; right: 0; bottom: 0; left: 0;'><iframe " + id + " src='" + fullURL + "' style='border: none; width: 100%; height: 100%;' frameborder='0'></iframe></div>"; 72787 targetNode.className += " pdfobject-container"; 72788 targetNode.style.position = "relative"; 72789 targetNode.style.overflow = "auto"; 72790 targetNode.innerHTML = iframe; 72791 return targetNode.getElementsByTagName("iframe")[0]; 72792 72793 }; 72794 72795 generateEmbedElement = function (targetNode, targetSelector, url, pdfOpenFragment, width, height, id){ 72796 72797 var style = ""; 72798 72799 if(targetSelector && targetSelector !== document.body){ 72800 style = "width: " + width + "; height: " + height + ";"; 72801 } else { 72802 style = "position: absolute; top: 0; right: 0; bottom: 0; left: 0; width: 100%; height: 100%;"; 72803 } 72804 72805 targetNode.className += " pdfobject-container"; 72806 targetNode.innerHTML = "<embed " + id + " class='pdfobject' src='" + url + pdfOpenFragment + "' type='application/pdf' style='overflow: auto; " + style + "'/>"; 72807 72808 return targetNode.getElementsByTagName("embed")[0]; 72809 72810 }; 72811 72812 embed = function(url, targetSelector, options){ 72813 72814 //Ensure URL is available. If not, exit now. 72815 if(typeof url !== "string"){ return embedError("URL is not valid"); } 72816 72817 //If targetSelector is not defined, convert to boolean 72818 targetSelector = (typeof targetSelector !== "undefined") ? targetSelector : false;
72819 72820 //Ensure options object is not undefined -- enables easier error checking below 72821 options = (typeof options !== "undefined") ? options : {}; 72822 72823 //Get passed options, or set reasonable defaults 72824 var id = (options.id && typeof options.id === "string") ? "id='" + options.id + "'" : "", 72825 page = (options.page) ? options.page : false, 72826 pdfOpenParams = (options.pdfOpenParams) ? options.pdfOpenParams : {}, 72827 fallbackLink = (typeof options.fallbackLink !== "undefined") ? options.fallbackLink : true, 72828 width = (options.width) ? options.width : "100%", 72829 height = (options.height) ? options.height : "100%", 72830 assumptionMode = (typeof options.assumptionMode === "boolean") ? options.assumptionMode : true, 72831 forcePDFJS = (typeof options.forcePDFJS === "boolean") ? options.forcePDFJS : false, 72832 PDFJS_URL = (options.PDFJS_URL) ? options.PDFJS_URL : false, 72833 targetNode = getTargetElement(targetSelector), 72834 fallbackHTML = "", 72835 pdfOpenFragment = "", 72836 fallbackHTML_default = "<p>This browser does not support inline PDFs. Please download the PDF to view it: <a href='[url]'>Download PDF</a></p>"; 72837 72838 //If target element is specified but is not valid, exit without doing anything 72839 if(!targetNode){ return embedError("Target element cannot be determined"); } 72840 72841 72842 //page option overrides pdfOpenParams, if found 72843 if(page){ 72844 pdfOpenParams.page = page; 72845 } 72846 72847 //Stringify optional Adobe params for opening document (as fragment identifier) 72848 pdfOpenFragment = buildFragmentString(pdfOpenParams); 72849 72850 //Do the dance 72851 72852 //If the forcePDFJS option is invoked, skip everything else and embed as directed 72853 if(forcePDFJS && PDFJS_URL){ 72854 72855 return generatePDFJSiframe(targetNode, url, pdfOpenFragment, PDFJS_URL, id); 72856 72857 //If traditional support is provided, or if this is a modern browser and not iOS (see comment for supportsPDFs declaration) 72858 } else if(supportsPDFs || (assumptionMode && isModernBrowser && !isIOS)){ 72859 72860 return generateEmbedElement(targetNode, targetSelector, url, pdfOpenFragment, width, height, id); 72861 72862 //If everything else has failed and a PDFJS fallback is provided, try to use it 72863 } else if(PDFJS_URL){ 72864 72865 return generatePDFJSiframe(targetNode, url, pdfOpenFragment, PDFJS_URL, id); 72866 72867 } else { 72868 72869 //Display the fallback link if available 72870 if(fallbackLink){ 72871 72872 fallbackHTML = (typeof fallbackLink === "string") ? fallbackLink : fallbackHTML_default; 72873 targetNode.innerHTML = fallbackHTML.replace(/\[url\]/g, url); 72874 72875 } 72876 72877 return embedError("This browser does not support embedded PDFs"); 72878 72879 } 72880 72881 }; 72882 72883 return { 72884 embed: function (a,b,c){ return embed(a,b,c); }, 72885 pdfobjectversion: (function () { return pdfobjectversion; })(), 72886 supportsPDFs: (function (){ return supportsPDFs; })() 72887 }; 72888 72889})); 72890/* perfect-scrollbar v0.6.14 */ 72891(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ 72892'use strict'; 72893 72894var ps = require('../main'); 72895var psInstances = require('../plugin/instances'); 72896 72897function mountJQuery(jQuery) { 72898 jQuery.fn.perfectScrollbar = function (settingOrCommand) { 72899 return this.each(function () { 72900 if (typeof settingOrCommand === 'object' || 72901 typeof settingOrCommand === 'undefined') { 72902 // If it's an object or none, initialize. 72903 var settings = settingOrCommand; 72904 72905 if (!psInstances.get(this)) { 72906 ps.initialize(this, settings); 72907 } 72908 } else { 72909 // Unless, it may be a command. 72910 var command = settingOrCommand; 72911 72912 if (command === 'update') { 72913 ps.update(this); 72914 } else if (command === 'destroy') { 72915 ps.destroy(this); 72916 } 72917 } 72918 }); 72919 }; 72920} 72921 72922if (typeof define === 'function' && define.amd) { 72923 // AMD. Register as an anonymous module.
72924 define('perfectScrollbarJquery',['jquery'], mountJQuery); 72925} else { 72926 var jq = window.jQuery ? window.jQuery : window.$; 72927 if (typeof jq !== 'undefined') { 72928 mountJQuery(jq); 72929 } 72930} 72931 72932module.exports = mountJQuery; 72933 72934},{"../main":7,"../plugin/instances":18}],2:[function(require,module,exports){ 72935'use strict'; 72936 72937function oldAdd(element, className) { 72938 var classes = element.className.split(' '); 72939 if (classes.indexOf(className) < 0) { 72940 classes.push(className); 72941 } 72942 element.className = classes.join(' '); 72943} 72944 72945function oldRemove(element, className) { 72946 var classes = element.className.split(' '); 72947 var idx = classes.indexOf(className); 72948 if (idx >= 0) { 72949 classes.splice(idx, 1); 72950 } 72951 element.className = classes.join(' '); 72952} 72953 72954exports.add = function (element, className) { 72955 if (element.classList) { 72956 element.classList.add(className); 72957 } else { 72958 oldAdd(element, className); 72959 } 72960}; 72961 72962exports.remove = function (element, className) { 72963 if (element.classList) { 72964 element.classList.remove(className); 72965 } else { 72966 oldRemove(element, className); 72967 } 72968}; 72969 72970exports.list = function (element) { 72971 if (element.classList) { 72972 return Array.prototype.slice.apply(element.classList); 72973 } else { 72974 return element.className.split(' '); 72975 } 72976}; 72977 72978},{}],3:[function(require,module,exports){ 72979'use strict'; 72980 72981var DOM = {}; 72982 72983DOM.e = function (tagName, className) { 72984 var element = document.createElement(tagName); 72985 element.className = className; 72986 return element; 72987}; 72988 72989DOM.appendTo = function (child, parent) { 72990 parent.appendChild(child); 72991 return child; 72992}; 72993 72994function cssGet(element, styleName) { 72995 return window.getComputedStyle(element)[styleName]; 72996} 72997 72998function cssSet(element, styleName, styleValue) { 72999 if (typeof styleValue === 'number') { 73000 styleValue = styleValue.toString() + 'px'; 73001 } 73002 element.style[styleName] = styleValue; 73003 return element; 73004} 73005 73006function cssMultiSet(element, obj) { 73007 for (var key in obj) { 73008 var val = obj[key]; 73009 if (typeof val === 'number') { 73010 val = val.toString() + 'px'; 73011 } 73012 element.style[key] = val; 73013 } 73014 return element; 73015} 73016 73017DOM.css = function (element, styleNameOrObject, styleValue) { 73018 if (typeof styleNameOrObject === 'object') { 73019 // multiple set with object 73020 return cssMultiSet(element, styleNameOrObject); 73021 } else { 73022 if (typeof styleValue === 'undefined') { 73023 return cssGet(element, styleNameOrObject); 73024 } else { 73025 return cssSet(element, styleNameOrObject, styleValue); 73026 } 73027 } 73028}; 73029 73030DOM.matches = function (element, query) { 73031 if (typeof element.matches !== 'undefined') { 73032 return element.matches(query); 73033 } else { 73034 if (typeof element.matchesSelector !== 'undefined') { 73035 return element.matchesSelector(query); 73036 } else if (typeof element.webkitMatchesSelector !== 'undefined') { 73037 return element.webkitMatchesSelector(query); 73038 } else if (typeof element.mozMatchesSelector !== 'undefined') { 73039 return element.mozMatchesSelector(query); 73040 } else if (typeof element.msMatchesSelector !== 'undefined') { 73041 return element.msMatchesSelector(query); 73042 } 73043 } 73044}; 73045 73046DOM.remove = function (element) { 73047 if (typeof element.remove !== 'undefined') { 73048 element.remove(); 73049 } else { 73050 if (element.parentNode) { 73051 element.parentNode.removeChild(element); 73052 } 73053 } 73054}; 73055 73056DOM.queryChildren = function (element, selector) { 73057 return Array.prototype.filter.call(element.childNodes, function (child) { 73058 return DOM.matches(child, selector); 73059 }); 73060}; 73061 73062module.exports = DOM; 73063 73064},{}],4:[function(require,module,exports){ 73065'use strict'; 73066 73067var EventElement = function (element) { 73068 this.element = element; 73069 this.events = {}; 73070}; 73071 73072EventElement.prototype.bind = function (eventName, handler) { 73073 if (typeof this.events[eventName] === 'undefined') { 73074 this.events[eventName] = []; 73075 } 73076 this.events[eventName].push(handler); 73077 this.element.addEventListener(eventName, handler, false); 73078}; 73079 73080EventElement.prototype.unbind = function (eventName, handler) { 73081 var isHandlerProvided = (typeof handler !== 'undefined'); 73082 this.events[eventName] = this.events[eventName].filter(function (hdlr) { 73083 if (isHandlerProvided && hdlr !== handler) { 73084 return true; 73085 } 73086 this.element.removeEventListener(eventName, hdlr, false); 73087 return false;
73088 }, this); 73089}; 73090 73091EventElement.prototype.unbindAll = function () { 73092 for (var name in this.events) { 73093 this.unbind(name); 73094 } 73095}; 73096 73097var EventManager = function () { 73098 this.eventElements = []; 73099}; 73100 73101EventManager.prototype.eventElement = function (element) { 73102 var ee = this.eventElements.filter(function (eventElement) { 73103 return eventElement.element === element; 73104 })[0]; 73105 if (typeof ee === 'undefined') { 73106 ee = new EventElement(element); 73107 this.eventElements.push(ee); 73108 } 73109 return ee; 73110}; 73111 73112EventManager.prototype.bind = function (element, eventName, handler) { 73113 this.eventElement(element).bind(eventName, handler); 73114}; 73115 73116EventManager.prototype.unbind = function (element, eventName, handler) { 73117 this.eventElement(element).unbind(eventName, handler); 73118}; 73119 73120EventManager.prototype.unbindAll = function () { 73121 for (var i = 0; i < this.eventElements.length; i++) { 73122 this.eventElements[i].unbindAll(); 73123 } 73124}; 73125 73126EventManager.prototype.once = function (element, eventName, handler) { 73127 var ee = this.eventElement(element); 73128 var onceHandler = function (e) { 73129 ee.unbind(eventName, onceHandler); 73130 handler(e); 73131 }; 73132 ee.bind(eventName, onceHandler); 73133}; 73134 73135module.exports = EventManager; 73136 73137},{}],5:[function(require,module,exports){ 73138'use strict'; 73139 73140module.exports = (function () { 73141 function s4() { 73142 return Math.floor((1 + Math.random()) * 0x10000) 73143 .toString(16) 73144 .substring(1); 73145 } 73146 return function () { 73147 return s4() + s4() + '-' + s4() + '-' + s4() + '-' + 73148 s4() + '-' + s4() + s4() + s4(); 73149 }; 73150})(); 73151 73152},{}],6:[function(require,module,exports){ 73153'use strict'; 73154 73155var cls = require('./class'); 73156var dom = require('./dom'); 73157 73158var toInt = exports.toInt = function (x) { 73159 return parseInt(x, 10) || 0; 73160}; 73161 73162var clone = exports.clone = function (obj) { 73163 if (!obj) { 73164 return null; 73165 } else if (obj.constructor === Array) { 73166 return obj.map(clone); 73167 } else if (typeof obj === 'object') { 73168 var result = {}; 73169 for (var key in obj) { 73170 result[key] = clone(obj[key]); 73171 } 73172 return result; 73173 } else { 73174 return obj; 73175 } 73176}; 73177 73178exports.extend = function (original, source) { 73179 var result = clone(original); 73180 for (var key in source) { 73181 result[key] = clone(source[key]); 73182 } 73183 return result; 73184}; 73185 73186exports.isEditable = function (el) { 73187 return dom.matches(el, "input,[contenteditable]") || 73188 dom.matches(el, "select,[contenteditable]") || 73189 dom.matches(el, "textarea,[contenteditable]") || 73190 dom.matches(el, "button,[contenteditable]"); 73191}; 73192 73193exports.removePsClasses = function (element) { 73194 var clsList = cls.list(element); 73195 for (var i = 0; i < clsList.length; i++) { 73196 var className = clsList[i]; 73197 if (className.indexOf('ps-') === 0) { 73198 cls.remove(element, className); 73199 } 73200 } 73201}; 73202 73203exports.outerWidth = function (element) { 73204 return toInt(dom.css(element, 'width')) + 73205 toInt(dom.css(element, 'paddingLeft')) + 73206 toInt(dom.css(element, 'paddingRight')) + 73207 toInt(dom.css(element, 'borderLeftWidth')) + 73208 toInt(dom.css(element, 'borderRightWidth')); 73209}; 73210 73211exports.startScrolling = function (element, axis) { 73212 cls.add(element, 'ps-in-scrolling'); 73213 if (typeof axis !== 'undefined') { 73214 cls.add(element, 'ps-' + axis); 73215 } else { 73216 cls.add(element, 'ps-x'); 73217 cls.add(element, 'ps-y'); 73218 } 73219}; 73220 73221exports.stopScrolling = function (element, axis) { 73222 cls.remove(element, 'ps-in-scrolling'); 73223 if (typeof axis !== 'undefined') { 73224 cls.remove(element, 'ps-' + axis); 73225 } else { 73226 cls.remove(element, 'ps-x'); 73227 cls.remove(element, 'ps-y'); 73228 } 73229}; 73230 73231exports.env = { 73232 isWebKit: 'WebkitAppearance' in document.documentElement.style, 73233 supportsTouch: (('ontouchstart' in window) || window.DocumentTouch && document instanceof window.DocumentTouch), 73234 supportsIePointer: window.navigator.msMaxTouchPoints !== null 73235}; 73236 73237},{"./class":2,"./dom":3}],7:[function(require,module,exports){ 73238'use strict'; 73239 73240var destroy = require('./plugin/destroy'); 73241var initialize = require('./plugin/initialize'); 73242var update = require('./plugin/update'); 73243 73244module.exports = { 73245 initialize: initialize, 73246 update: update, 73247 destroy: destroy 73248}; 73249 73250},{"./plugin/destroy":9,"./plugin/initialize":17,"./plugin/update":2
732501}],8:[function(require,module,exports){ 73251'use strict'; 73252 73253module.exports = { 73254 handlers: ['click-rail', 'drag-scrollbar', 'keyboard', 'wheel', 'touch'], 73255 maxScrollbarLength: null, 73256 minScrollbarLength: null, 73257 scrollXMarginOffset: 0, 73258 scrollYMarginOffset: 0, 73259 suppressScrollX: false, 73260 suppressScrollY: false, 73261 swipePropagation: true, 73262 useBothWheelAxes: false, 73263 wheelPropagation: false, 73264 wheelSpeed: 1, 73265 theme: 'default' 73266}; 73267 73268},{}],9:[function(require,module,exports){ 73269'use strict'; 73270 73271var _ = require('../lib/helper'); 73272var dom = require('../lib/dom'); 73273var instances = require('./instances'); 73274 73275module.exports = function (element) { 73276 var i = instances.get(element); 73277 73278 if (!i) { 73279 return; 73280 } 73281 73282 i.event.unbindAll(); 73283 dom.remove(i.scrollbarX); 73284 dom.remove(i.scrollbarY); 73285 dom.remove(i.scrollbarXRail); 73286 dom.remove(i.scrollbarYRail); 73287 _.removePsClasses(element); 73288 73289 instances.remove(element); 73290}; 73291 73292},{"../lib/dom":3,"../lib/helper":6,"./instances":18}],10:[function(require,module,exports){ 73293'use strict'; 73294 73295var instances = require('../instances'); 73296var updateGeometry = require('../update-geometry'); 73297var updateScroll = require('../update-scroll'); 73298 73299function bindClickRailHandler(element, i) { 73300 function pageOffset(el) { 73301 return el.getBoundingClientRect(); 73302 } 73303 var stopPropagation = function (e) { e.stopPropagation(); }; 73304 73305 i.event.bind(i.scrollbarY, 'click', stopPropagation); 73306 i.event.bind(i.scrollbarYRail, 'click', function (e) { 73307 var positionTop = e.pageY - window.pageYOffset - pageOffset(i.scrollbarYRail).top; 73308 var direction = positionTop > i.scrollbarYTop ? 1 : -1; 73309 73310 updateScroll(element, 'top', element.scrollTop + direction * i.containerHeight); 73311 updateGeometry(element); 73312 73313 e.stopPropagation(); 73314 }); 73315 73316 i.event.bind(i.scrollbarX, 'click', stopPropagation); 73317 i.event.bind(i.scrollbarXRail, 'click', function (e) { 73318 var positionLeft = e.pageX - window.pageXOffset - pageOffset(i.scrollbarXRail).left; 73319 var direction = positionLeft > i.scrollbarXLeft ? 1 : -1; 73320 73321 updateScroll(element, 'left', element.scrollLeft + direction * i.containerWidth); 73322 updateGeometry(element); 73323 73324 e.stopPropagation(); 73325 }); 73326} 73327 73328module.exports = function (element) { 73329 var i = instances.get(element); 73330 bindClickRailHandler(element, i); 73331}; 73332 73333},{"../instances":18,"../update-geometry":19,"../update-scroll":20}],11:[function(require,module,exports){ 73334'use strict'; 73335 73336var _ = require('../../lib/helper'); 73337var dom = require('../../lib/dom'); 73338var instances = require('../instances'); 73339var updateGeometry = require('../update-geometry'); 73340var updateScroll = require('../update-scroll'); 73341 73342function bindMouseScrollXHandler(element, i) { 73343 var currentLeft = null; 73344 var currentPageX = null; 73345 73346 function updateScrollLeft(deltaX) { 73347 var newLeft = currentLeft + (deltaX * i.railXRatio); 73348 var maxLeft = Math.max(0, i.scrollbarXRail.getBoundingClientRect().left) + (i.railXRatio * (i.railXWidth - i.scrollbarXWidth)); 73349 73350 if (newLeft < 0) { 73351 i.scrollbarXLeft = 0; 73352 } else if (newLeft > maxLeft) { 73353 i.scrollbarXLeft = maxLeft; 73354 } else { 73355 i.scrollbarXLeft = newLeft; 73356 } 73357 73358 var scrollLeft = _.toInt(i.scrollbarXLeft * (i.contentWidth - i.containerWidth) / (i.containerWidth - (i.railXRatio * i.scrollbarXWidth))) - i.negativeScrollAdjustment; 73359 updateScroll(element, 'left', scrollLeft); 73360 } 73361 73362 var mouseMoveHandler = function (e) { 73363 updateScrollLeft(e.pageX - currentPageX); 73364 updateGeometry(element); 73365 e.stopPropagation(); 73366 e.preventDefault(); 73367 }; 73368 73369 var mouseUpHandler = function () { 73370 _.stopScrolling(element, 'x'); 73371 i.event.unbind(i.ownerDocument, 'mousemove', mouseMoveHandler); 73372 }; 73373 73374 i.event.bind(i.scrollbarX, 'mousedown', function (e) { 73375 currentPageX = e.pageX; 73376 currentLeft = _.toInt(dom.css(i.scrollbarX, 'left')) * i.railXRatio; 73377 _.startScrolling(element, 'x'); 73378 73379 i.event.bind(i.ownerDocument, 'mousemove', mouseMoveHandler); 73380 i.event.once(i.ownerDocument, 'mouseup', mouseUpHandler); 73381 73382 e.stopPropagation(); 73383 e.preventDefault(); 73384 }); 73385} 73386 73387function bindMouseScrollYHandler(element, i) { 73388 var currentTop = null; 73389 var currentPageY = null; 73390 73391 function updateScrollTop(deltaY) { 73392 var newTop = currentTop + (deltaY * i.railYRatio); 73393 var maxTop = Math.max(0, i.scrollbarYRail.getBoundingClientRect().top) + (i.railYRatio * (i.railYHeight - i.scrollbarYHeight)); 73394 73395 if (newTop < 0) { 73396 i.scrollbarYTop = 0; 73397 } else if (newTop > maxTop) { 73398 i.scrollbarYTop = maxTop; 73399 } else { 73400 i.scrollbarYTop = newTop; 73401 } 73402 73403 var scrollTop = _.toInt(i.scrollbarYTop * (i.contentHeight - i.containerHeight) / (i.containerHeight - (i.railYRatio * i.scrollbarYHeight))); 73404 updateScroll(element, 'top', scrollTop); 73405 } 73406 73407 var mouseMoveHandler = function (e) { 73408 updateScrollTop(e.pageY - currentPageY); 73409 updateGeometry(element); 73410 e.stopPropagation(); 73411 e.preventDefault(); 73412 }; 73413 73414 var mouseUpHandler = function () { 73415 _.stopScrolling(element, 'y'); 73416 i.event.unbind(i.ownerDocument, 'mousemove', mouseMoveHandler); 73417 }; 73418 73419 i.event.bind(i.scrollbarY, 'mousedown', function (e) { 73420 currentPageY = e.pageY; 73421 currentTop = _.toInt(dom.css(i.scrollbarY, 'top')) * i.railYRatio; 73422 _.startScrolling(element, 'y'); 73423 73424 i.event.bind(i.ownerDocument, 'mousemove', mouseMoveHandler); 73425 i.event.once(i.ownerDocument, 'mouseup', mouseUpHandler); 73426 73427 e.stopPropagation(); 73428 e.preventDefault(); 73429 }); 73430} 73431 73432module.exports = function (element) { 73433 var i = instances.get(element); 73434 bindMouseScrollXHandler(element, i); 73435 bindMouseScrollYHandler(element, i); 73436}; 73437 73438},{"../../lib/dom":3,"../../lib/helper":6,"../instances":18,"../update-geometry":19,"../update-scroll":20}],12:[function(require,module,exports){ 73439'use strict'; 73440 73441var _ = require('../../lib/helper'); 73442var dom = require('../../lib/dom'); 73443var instances = require('../instances'); 73444var updateGeometry = require('../update-geometry'); 73445var updateScroll = require('../update-scroll'); 73446 73447function bindKeyboardHandler(element, i) { 73448 var hovered = false;
73449 i.event.bind(element, 'mouseenter', function () { 73450 hovered = true; 73451 }); 73452 i.event.bind(element, 'mouseleave', function () { 73453 hovered = false; 73454 }); 73455 73456 var shouldPrevent = false; 73457 function shouldPreventDefault(deltaX, deltaY) { 73458 var scrollTop = element.scrollTop; 73459 if (deltaX === 0) { 73460 if (!i.scrollbarYActive) { 73461 return false; 73462 } 73463 if ((scrollTop === 0 && deltaY > 0) || (scrollTop >= i.contentHeight - i.containerHeight && deltaY < 0)) { 73464 return !i.settings.wheelPropagation; 73465 } 73466 } 73467 73468 var scrollLeft = element.scrollLeft; 73469 if (deltaY === 0) { 73470 if (!i.scrollbarXActive) { 73471 return false; 73472 } 73473 if ((scrollLeft === 0 && deltaX < 0) || (scrollLeft >= i.contentWidth - i.containerWidth && deltaX > 0)) { 73474 return !i.settings.wheelPropagation; 73475 } 73476 } 73477 return true; 73478 } 73479 73480 i.event.bind(i.ownerDocument, 'keydown', function (e) { 73481 if ((e.isDefaultPrevented && e.isDefaultPrevented()) || e.defaultPrevented) { 73482 return; 73483 } 73484 73485 var focused = dom.matches(i.scrollbarX, ':focus') || 73486 dom.matches(i.scrollbarY, ':focus'); 73487 73488 if (!hovered && !focused) { 73489 return; 73490 } 73491 73492 var activeElement = document.activeElement ? document.activeElement : i.ownerDocument.activeElement; 73493 if (activeElement) { 73494 if (activeElement.tagName === 'IFRAME') { 73495 activeElement = activeElement.contentDocument.activeElement; 73496 } else { 73497 // go deeper if element is a webcomponent 73498 while (activeElement.shadowRoot) { 73499 activeElement = activeElement.shadowRoot.activeElement; 73500 } 73501 } 73502 if (_.isEditable(activeElement)) { 73503 return; 73504 } 73505 } 73506 73507 var deltaX = 0; 73508 var deltaY = 0; 73509 73510 switch (e.which) { 73511 case 37: // left 73512 if (e.metaKey) { 73513 deltaX = -i.contentWidth; 73514 } else if (e.altKey) { 73515 deltaX = -i.containerWidth; 73516 } else { 73517 deltaX = -30; 73518 } 73519 break; 73520 case 38: // up 73521 if (e.metaKey) { 73522 deltaY = i.contentHeight; 73523 } else if (e.altKey) { 73524 deltaY = i.containerHeight; 73525 } else { 73526 deltaY = 30; 73527 } 73528 break; 73529 case 39: // right 73530 if (e.metaKey) { 73531 deltaX = i.contentWidth; 73532 } else if (e.altKey) { 73533 deltaX = i.containerWidth; 73534 } else { 73535 deltaX = 30; 73536 } 73537 break; 73538 case 40: // down 73539 if (e.metaKey) { 73540 deltaY = -i.contentHeight; 73541 } else if (e.altKey) { 73542 deltaY = -i.containerHeight; 73543 } else { 73544 deltaY = -30; 73545 } 73546 break; 73547 case 33: // page up 73548 deltaY = 90; 73549 break; 73550 case 32: // space bar 73551 if (e.shiftKey) { 73552 deltaY = 90; 73553 } else { 73554 deltaY = -90; 73555 } 73556 break; 73557 case 34: // page down 73558 deltaY = -90; 73559 break; 73560 case 35: // end 73561 if (e.ctrlKey) { 73562 deltaY = -i.contentHeight; 73563 } else { 73564 deltaY = -i.containerHeight; 73565 } 73566 break; 73567 case 36: // home 73568 if (e.ctrlKey) { 73569 deltaY = element.scrollTop; 73570 } else { 73571 deltaY = i.containerHeight; 73572 } 73573 break; 73574 default: 73575 return; 73576 } 73577 73578 updateScroll(element, 'top', element.scrollTop - deltaY); 73579 updateScroll(element, 'left', element.scrollLeft + deltaX); 73580 updateGeometry(element); 73581 73582 shouldPrevent = shouldPreventDefault(deltaX, deltaY); 73583 if (shouldPrevent) { 73584 e.preventDefault(); 73585 } 73586 }); 73587} 73588 73589module.exports = function (element) { 73590 var i = instances.get(element); 73591 bindKeyboardHandler(element, i); 73592}; 73593 73594},{"../../lib/dom":3,"../../lib/helper":6,"../instances":18,"../update-geometry":19,"../update-scroll":20}],13:[function(require,module,exports){ 73595'use strict'; 73596 73597var instances = require('../instances'); 73598var updateGeometry = require('../update-geometry'); 73599var updateScroll = require('../update-scroll'); 73600 73601function bindMouseWheelHandler(element, i) { 73602 var shouldPrevent = false; 73603 73604 function shouldPreventDefault(deltaX, deltaY) { 73605 var scrollTop = element.scrollTop; 73606 if (deltaX === 0) { 73607 if (!i.scrollbarYActive) { 73608 return false; 73609 } 73610 if ((scrollTop === 0 && deltaY > 0) || (scrollTop >= i.contentHeight - i.containerHeight && deltaY < 0)) { 73611 return !i.settings.wheelPropagation; 73612 } 73613 } 73614 73615 var scrollLeft = element.scrollLeft; 73616 if (deltaY === 0) { 73617 if (!i.scrollbarXActive) { 73618 return false;
73619 } 73620 if ((scrollLeft === 0 && deltaX < 0) || (scrollLeft >= i.contentWidth - i.containerWidth && deltaX > 0)) { 73621 return !i.settings.wheelPropagation; 73622 } 73623 } 73624 return true; 73625 } 73626 73627 function getDeltaFromEvent(e) { 73628 var deltaX = e.deltaX; 73629 var deltaY = -1 * e.deltaY; 73630 73631 if (typeof deltaX === "undefined" || typeof deltaY === "undefined") { 73632 // OS X Safari 73633 deltaX = -1 * e.wheelDeltaX / 6; 73634 deltaY = e.wheelDeltaY / 6; 73635 } 73636 73637 if (e.deltaMode && e.deltaMode === 1) { 73638 // Firefox in deltaMode 1: Line scrolling 73639 deltaX *= 10; 73640 deltaY *= 10; 73641 } 73642 73643 if (deltaX !== deltaX && deltaY !== deltaY/* NaN checks */) { 73644 // IE in some mouse drivers 73645 deltaX = 0; 73646 deltaY = e.wheelDelta; 73647 } 73648 73649 if (e.shiftKey) { 73650 // reverse axis with shift key 73651 return [-deltaY, -deltaX]; 73652 } 73653 return [deltaX, deltaY]; 73654 } 73655 73656 function shouldBeConsumedByChild(deltaX, deltaY) { 73657 var child = element.querySelector('textarea:hover, select[multiple]:hover, .ps-child:hover'); 73658 if (child) { 73659 if (!window.getComputedStyle(child).overflow.match(/(scroll|auto)/)) { 73660 // if not scrollable 73661 return false; 73662 } 73663 73664 var maxScrollTop = child.scrollHeight - child.clientHeight; 73665 if (maxScrollTop > 0) { 73666 if (!(child.scrollTop === 0 && deltaY > 0) && !(child.scrollTop === maxScrollTop && deltaY < 0)) { 73667 return true; 73668 } 73669 } 73670 var maxScrollLeft = child.scrollLeft - child.clientWidth; 73671 if (maxScrollLeft > 0) { 73672 if (!(child.scrollLeft === 0 && deltaX < 0) && !(child.scrollLeft === maxScrollLeft && deltaX > 0)) { 73673 return true; 73674 } 73675 } 73676 } 73677 return false; 73678 } 73679 73680 function mousewheelHandler(e) { 73681 var delta = getDeltaFromEvent(e); 73682 73683 var deltaX = delta[0]; 73684 var deltaY = delta[1]; 73685 73686 if (shouldBeConsumedByChild(deltaX, deltaY)) { 73687 return; 73688 } 73689 73690 shouldPrevent = false; 73691 if (!i.settings.useBothWheelAxes) { 73692 // deltaX will only be used for horizontal scrolling and deltaY will 73693 // only be used for vertical scrolling - this is the default 73694 updateScroll(element, 'top', element.scrollTop - (deltaY * i.settings.wheelSpeed)); 73695 updateScroll(element, 'left', element.scrollLeft + (deltaX * i.settings.wheelSpeed)); 73696 } else if (i.scrollbarYActive && !i.scrollbarXActive) { 73697 // only vertical scrollbar is active and useBothWheelAxes option is 73698 // active, so let's scroll vertical bar using both mouse wheel axes 73699 if (deltaY) { 73700 updateScroll(element, 'top', element.scrollTop - (deltaY * i.settings.wheelSpeed)); 73701 } else { 73702 updateScroll(element, 'top', element.scrollTop + (deltaX * i.settings.wheelSpeed)); 73703 } 73704 shouldPrevent = true; 73705 } else if (i.scrollbarXActive && !i.scrollbarYActive) { 73706 // useBothWheelAxes and only horizontal bar is active, so use both 73707 // wheel axes for horizontal bar 73708 if (deltaX) { 73709 updateScroll(element, 'left', element.scrollLeft + (deltaX * i.settings.wheelSpeed)); 73710 } else { 73711 updateScroll(element, 'left', element.scrollLeft - (deltaY * i.settings.wheelSpeed)); 73712 } 73713 shouldPrevent = true; 73714 } 73715 73716 updateGeometry(element); 73717 73718 shouldPrevent = (shouldPrevent || shouldPreventDefault(deltaX, deltaY)); 73719 if (shouldPrevent) { 73720 e.stopPropagation(); 73721 e.preventDefault(); 73722 } 73723 } 73724 73725 if (typeof window.onwheel !== "undefined") { 73726 i.event.bind(element, 'wheel', mousewheelHandler); 73727 } else if (typeof window.onmousewheel !== "undefined") { 73728 i.event.bind(element, 'mousewheel', mousewheelHandler); 73729 } 73730} 73731 73732module.exports = function (element) { 73733 var i = instances.get(element); 73734 bindMouseWheelHandler(element, i); 73735}; 73736 73737},{"../instances":18,"../update-geometry":19,"../update-scroll":20}],14:[function(require,module,exports){ 73738'use strict'; 73739 73740var instances = require('../instances'); 73741var updateGeometry = require('../update-geometry'); 73742 73743function bindNativeScrollHandler(element, i) { 73744 i.event.bind(element, 'scroll', function () { 73745 updateGeometry(element); 73746 }); 73747} 73748 73749module.exports = function (element) { 73750 var i = instances.get(element); 73751 bindNativeScrollHandler(element, i); 73752}; 73753 73754},{"../instances":18,"../update-geometry":19}],15:[function(require,module,exports){ 73755'use strict'; 73756 73757var _ = require('../../lib/helper'); 73758var instances = require('../instances'); 73759var updateGeometry = require('../update-geometry'); 73760var updateScroll = require('../update-scroll'); 73761 73762function bindSelectionHandler(element, i) { 73763 function getRangeNode() { 73764 var selection = window.getSelection ? window.getSelection() : 73765 document.getSelection ? document.getSelection() : ''; 73766 if (selection.toString().length === 0) { 73767 return null; 73768 } else { 73769 return selection.getRangeAt(0).commonAncestorContainer; 73770 } 73771 } 73772 73773 var scrollingLoop = null; 73774 var scrollDiff = {top: 0, left: 0}; 73775 function startScrolling() { 73776 if (!scrollingLoop) { 73777 scrollingLoop = setInterval(function () { 73778 if (!instances.get(element)) { 73779 clearInterval(scrollingLoop); 73780 return; 73781 } 73782 73783 updateScroll(element, 'top', element.scrollTop + scrollDiff.top); 73784 updateScroll(element, 'left', element.scrollLeft + scrollDiff.left); 73785 updateGeometry(element); 73786 }, 50); // every .1 sec 73787 } 73788 } 73789 function stopScrolling() { 73790 if (scrollingLoop) { 73791 clearInterval(scrollingLoop); 73792 scrollingLoop = null; 73793 } 73794 _.stopScrolling(element); 73795 } 73796 73797 var isSelected = false;
73798 i.event.bind(i.ownerDocument, 'selectionchange', function () { 73799 if (element.contains(getRangeNode())) { 73800 isSelected = true; 73801 } else { 73802 isSelected = false; 73803 stopScrolling(); 73804 } 73805 }); 73806 i.event.bind(window, 'mouseup', function () { 73807 if (isSelected) { 73808 isSelected = false; 73809 stopScrolling(); 73810 } 73811 }); 73812 i.event.bind(window, 'keyup', function () { 73813 if (isSelected) { 73814 isSelected = false; 73815 stopScrolling(); 73816 } 73817 }); 73818 73819 i.event.bind(window, 'mousemove', function (e) { 73820 if (isSelected) { 73821 var mousePosition = {x: e.pageX, y: e.pageY}; 73822 var containerGeometry = { 73823 left: element.offsetLeft, 73824 right: element.offsetLeft + element.offsetWidth, 73825 top: element.offsetTop, 73826 bottom: element.offsetTop + element.offsetHeight 73827 }; 73828 73829 if (mousePosition.x < containerGeometry.left + 3) { 73830 scrollDiff.left = -5; 73831 _.startScrolling(element, 'x'); 73832 } else if (mousePosition.x > containerGeometry.right - 3) { 73833 scrollDiff.left = 5; 73834 _.startScrolling(element, 'x'); 73835 } else { 73836 scrollDiff.left = 0; 73837 } 73838 73839 if (mousePosition.y < containerGeometry.top + 3) { 73840 if (containerGeometry.top + 3 - mousePosition.y < 5) { 73841 scrollDiff.top = -5; 73842 } else { 73843 scrollDiff.top = -20; 73844 } 73845 _.startScrolling(element, 'y'); 73846 } else if (mousePosition.y > containerGeometry.bottom - 3) { 73847 if (mousePosition.y - containerGeometry.bottom + 3 < 5) { 73848 scrollDiff.top = 5; 73849 } else { 73850 scrollDiff.top = 20; 73851 } 73852 _.startScrolling(element, 'y'); 73853 } else { 73854 scrollDiff.top = 0; 73855 } 73856 73857 if (scrollDiff.top === 0 && scrollDiff.left === 0) { 73858 stopScrolling(); 73859 } else { 73860 startScrolling(); 73861 } 73862 } 73863 }); 73864} 73865 73866module.exports = function (element) { 73867 var i = instances.get(element); 73868 bindSelectionHandler(element, i); 73869}; 73870 73871},{"../../lib/helper":6,"../instances":18,"../update-geometry":19,"../update-scroll":20}],16:[function(require,module,exports){ 73872'use strict'; 73873 73874var _ = require('../../lib/helper'); 73875var instances = require('../instances'); 73876var updateGeometry = require('../update-geometry'); 73877var updateScroll = require('../update-scroll'); 73878 73879function bindTouchHandler(element, i, supportsTouch, supportsIePointer) { 73880 function shouldPreventDefault(deltaX, deltaY) { 73881 var scrollTop = element.scrollTop; 73882 var scrollLeft = element.scrollLeft; 73883 var magnitudeX = Math.abs(deltaX); 73884 var magnitudeY = Math.abs(deltaY); 73885 73886 if (magnitudeY > magnitudeX) { 73887 // user is perhaps trying to swipe up/down the page 73888 73889 if (((deltaY < 0) && (scrollTop === i.contentHeight - i.containerHeight)) || 73890 ((deltaY > 0) && (scrollTop === 0))) { 73891 return !i.settings.swipePropagation; 73892 } 73893 } else if (magnitudeX > magnitudeY) { 73894 // user is perhaps trying to swipe left/right across the page 73895 73896 if (((deltaX < 0) && (scrollLeft === i.contentWidth - i.containerWidth)) || 73897 ((deltaX > 0) && (scrollLeft === 0))) { 73898 return !i.settings.swipePropagation; 73899 } 73900 } 73901 73902 return true; 73903 } 73904 73905 function applyTouchMove(differenceX, differenceY) { 73906 updateScroll(element, 'top', element.scrollTop - differenceY); 73907 updateScroll(element, 'left', element.scrollLeft - differenceX); 73908 73909 updateGeometry(element); 73910 } 73911 73912 var startOffset = {}; 73913 var startTime = 0; 73914 var speed = {}; 73915 var easingLoop = null; 73916 var inGlobalTouch = false; 73917 var inLocalTouch = false; 73918 73919 function globalTouchStart() { 73920 inGlobalTouch = true; 73921 } 73922 function globalTouchEnd() { 73923 inGlobalTouch = false; 73924 } 73925 73926 function getTouch(e) { 73927 if (e.targetTouches) { 73928 return e.targetTouches[0]; 73929 } else { 73930 // Maybe IE pointer 73931 return e; 73932 } 73933 } 73934 function shouldHandle(e) { 73935 if (e.targetTouches && e.targetTouches.length === 1) { 73936 return true; 73937 } 73938 if (e.pointerType && e.pointerType !== 'mouse' && e.pointerType !== e.MSPOINTER_TYPE_MOUSE) { 73939 return true; 73940 } 73941 return false; 73942 } 73943 function touchStart(e) { 73944 if (shouldHandle(e)) { 73945 inLocalTouch = true; 73946 73947 var touch = getTouch(e); 73948 73949 startOffset.pageX = touch.pageX; 73950 startOffset.pageY = touch.pageY; 73951 73952 startTime = (new Date()).getTime(); 73953 73954 if (easingLoop !== null) { 73955 clearInterval(easingLoop); 73956 } 73957 73958 e.stopPropagation(); 73959 } 73960 } 73961 function touchMove(e) { 73962 if (!inLocalTouch && i.settings.swipePropagation) { 73963 touchStart(e); 73964 } 73965 if (!inGlobalTouch && inLocalTouch && shouldHandle(e)) { 73966 var touch = getTouch(e); 73967 73968 var currentOffset = {pageX: touch.pageX, pageY: touch.pageY}; 73969 73970 var differenceX = currentOffset.pageX - startOffset.pageX; 73971 var differenceY = currentOffset.pageY - startOffset.pageY; 73972 73973 applyTouchMove(differenceX, differenceY); 73974 startOffset = currentOffset; 73975 73976 var currentTime = (new Date()).getTime(); 73977 73978 var timeGap = currentTime - startTime; 73979 if (timeGap > 0) { 73980 speed.x = differenceX / timeGap;
73981 speed.y = differenceY / timeGap; 73982 startTime = currentTime; 73983 } 73984 73985 if (shouldPreventDefault(differenceX, differenceY)) { 73986 e.stopPropagation(); 73987 e.preventDefault(); 73988 } 73989 } 73990 } 73991 function touchEnd() { 73992 if (!inGlobalTouch && inLocalTouch) { 73993 inLocalTouch = false; 73994 73995 clearInterval(easingLoop); 73996 easingLoop = setInterval(function () { 73997 if (!instances.get(element)) { 73998 clearInterval(easingLoop); 73999 return; 74000 } 74001 74002 if (!speed.x && !speed.y) { 74003 clearInterval(easingLoop); 74004 return; 74005 } 74006 74007 if (Math.abs(speed.x) < 0.01 && Math.abs(speed.y) < 0.01) { 74008 clearInterval(easingLoop); 74009 return; 74010 } 74011 74012 applyTouchMove(speed.x * 30, speed.y * 30); 74013 74014 speed.x *= 0.8; 74015 speed.y *= 0.8; 74016 }, 10); 74017 } 74018 } 74019 74020 if (supportsTouch) { 74021 i.event.bind(window, 'touchstart', globalTouchStart); 74022 i.event.bind(window, 'touchend', globalTouchEnd); 74023 i.event.bind(element, 'touchstart', touchStart); 74024 i.event.bind(element, 'touchmove', touchMove); 74025 i.event.bind(element, 'touchend', touchEnd); 74026 } 74027 74028 if (supportsIePointer) { 74029 if (window.PointerEvent) { 74030 i.event.bind(window, 'pointerdown', globalTouchStart); 74031 i.event.bind(window, 'pointerup', globalTouchEnd); 74032 i.event.bind(element, 'pointerdown', touchStart); 74033 i.event.bind(element, 'pointermove', touchMove); 74034 i.event.bind(element, 'pointerup', touchEnd); 74035 } else if (window.MSPointerEvent) { 74036 i.event.bind(window, 'MSPointerDown', globalTouchStart); 74037 i.event.bind(window, 'MSPointerUp', globalTouchEnd); 74038 i.event.bind(element, 'MSPointerDown', touchStart); 74039 i.event.bind(element, 'MSPointerMove', touchMove); 74040 i.event.bind(element, 'MSPointerUp', touchEnd); 74041 } 74042 } 74043} 74044 74045module.exports = function (element) { 74046 if (!_.env.supportsTouch && !_.env.supportsIePointer) { 74047 return; 74048 } 74049 74050 var i = instances.get(element); 74051 bindTouchHandler(element, i, _.env.supportsTouch, _.env.supportsIePointer); 74052}; 74053 74054},{"../../lib/helper":6,"../instances":18,"../update-geometry":19,"../update-scroll":20}],17:[function(require,module,exports){ 74055'use strict'; 74056 74057var _ = require('../lib/helper'); 74058var cls = require('../lib/class'); 74059var instances = require('./instances'); 74060var updateGeometry = require('./update-geometry'); 74061 74062// Handlers 74063var handlers = { 74064 'click-rail': require('./handler/click-rail'), 74065 'drag-scrollbar': require('./handler/drag-scrollbar'), 74066 'keyboard': require('./handler/keyboard'), 74067 'wheel': require('./handler/mouse-wheel'), 74068 'touch': require('./handler/touch'), 74069 'selection': require('./handler/selection') 74070}; 74071var nativeScrollHandler = require('./handler/native-scroll'); 74072 74073module.exports = function (element, userSettings) { 74074 userSettings = typeof userSettings === 'object' ? userSettings : {}; 74075 74076 cls.add(element, 'ps-container'); 74077 74078 // Create a plugin instance. 74079 var i = instances.add(element); 74080 74081 i.settings = _.extend(i.settings, userSettings); 74082 cls.add(element, 'ps-theme-' + i.settings.theme); 74083 74084 i.settings.handlers.forEach(function (handlerName) { 74085 handlers[handlerName](element); 74086 }); 74087 74088 nativeScrollHandler(element); 74089 74090 updateGeometry(element); 74091}; 74092 74093},{"../lib/class":2,"../lib/helper":6,"./handler/click-rail":10,"./handler/drag-scrollbar":11,"./handler/keyboard":12,"./handler/mouse-wheel":13,"./handler/native-scroll":14,"./handler/selection":15,"./handler/touch":16,"./instances":18,"./update-geometry":19}],18:[function(require,module,exports){ 74094'use strict'; 74095 74096var _ = require('../lib/helper'); 74097var cls = require('../lib/class'); 74098var defaultSettings = require('./default-setting'); 74099var dom = require('../lib/dom'); 74100var EventManager = require('../lib/event-manager'); 74101var guid = require('../lib/guid'); 74102 74103var instances = {}; 74104 74105function Instance(element) { 74106 var i = this; 74107 74108 i.settings = _.clone(defaultSettings); 74109 i.containerWidth = null; 74110 i.containerHeight = null; 74111 i.contentWidth = null; 74112 i.contentHeight = null; 74113 74114 i.isRtl = dom.css(element, 'direction') === "rtl"; 74115 i.isNegativeScroll = (function () { 74116 var originalScrollLeft = element.scrollLeft; 74117 var result = null; 74118 element.scrollLeft = -1; 74119 result = element.scrollLeft < 0; 74120 element.scrollLeft = originalScrollLeft; 74121 return result; 74122 })(); 74123 i.negativeScrollAdjustment = i.isNegativeScroll ? element.scrollWidth - element.clientWidth : 0; 74124 i.event = new EventManager(); 74125 i.ownerDocument = element.ownerDocument || document; 74126 74127 function focus() { 74128 cls.add(element, 'ps-focus'); 74129 } 74130 74131 function blur() { 74132 cls.remove(element, 'ps-focus'); 74133 } 74134 74135 i.scrollbarXRail = dom.appendTo(dom.e('div', 'ps-scrollbar-x-rail'), element); 74136 i.scrollbarX = dom.appendTo(dom.e('div', 'ps-scrollbar-x'), i.scrollbarXRail); 74137 i.scrollbarX.setAttribute('tabindex', 0);
74138 i.event.bind(i.scrollbarX, 'focus', focus); 74139 i.event.bind(i.scrollbarX, 'blur', blur); 74140 i.scrollbarXActive = null; 74141 i.scrollbarXWidth = null; 74142 i.scrollbarXLeft = null; 74143 i.scrollbarXBottom = _.toInt(dom.css(i.scrollbarXRail, 'bottom')); 74144 i.isScrollbarXUsingBottom = i.scrollbarXBottom === i.scrollbarXBottom; // !isNaN 74145 i.scrollbarXTop = i.isScrollbarXUsingBottom ? null : _.toInt(dom.css(i.scrollbarXRail, 'top')); 74146 i.railBorderXWidth = _.toInt(dom.css(i.scrollbarXRail, 'borderLeftWidth')) + _.toInt(dom.css(i.scrollbarXRail, 'borderRightWidth')); 74147 // Set rail to display:block to calculate margins 74148 dom.css(i.scrollbarXRail, 'display', 'block'); 74149 i.railXMarginWidth = _.toInt(dom.css(i.scrollbarXRail, 'marginLeft')) + _.toInt(dom.css(i.scrollbarXRail, 'marginRight')); 74150 dom.css(i.scrollbarXRail, 'display', ''); 74151 i.railXWidth = null; 74152 i.railXRatio = null; 74153 74154 i.scrollbarYRail = dom.appendTo(dom.e('div', 'ps-scrollbar-y-rail'), element); 74155 i.scrollbarY = dom.appendTo(dom.e('div', 'ps-scrollbar-y'), i.scrollbarYRail); 74156 i.scrollbarY.setAttribute('tabindex', 0); 74157 i.event.bind(i.scrollbarY, 'focus', focus); 74158 i.event.bind(i.scrollbarY, 'blur', blur); 74159 i.scrollbarYActive = null; 74160 i.scrollbarYHeight = null; 74161 i.scrollbarYTop = null; 74162 i.scrollbarYRight = _.toInt(dom.css(i.scrollbarYRail, 'right')); 74163 i.isScrollbarYUsingRight = i.scrollbarYRight === i.scrollbarYRight; // !isNaN 74164 i.scrollbarYLeft = i.isScrollbarYUsingRight ? null : _.toInt(dom.css(i.scrollbarYRail, 'left')); 74165 i.scrollbarYOuterWidth = i.isRtl ? _.outerWidth(i.scrollbarY) : null; 74166 i.railBorderYWidth = _.toInt(dom.css(i.scrollbarYRail, 'borderTopWidth')) + _.toInt(dom.css(i.scrollbarYRail, 'borderBottomWidth')); 74167 dom.css(i.scrollbarYRail, 'display', 'block'); 74168 i.railYMarginHeight = _.toInt(dom.css(i.scrollbarYRail, 'marginTop')) + _.toInt(dom.css(i.scrollbarYRail, 'marginBottom')); 74169 dom.css(i.scrollbarYRail, 'display', ''); 74170 i.railYHeight = null; 74171 i.railYRatio = null; 74172} 74173 74174function getId(element) { 74175 return element.getAttribute('data-ps-id'); 74176} 74177 74178function setId(element, id) { 74179 element.setAttribute('data-ps-id', id); 74180} 74181 74182function removeId(element) { 74183 element.removeAttribute('data-ps-id'); 74184} 74185 74186exports.add = function (element) { 74187 var newId = guid(); 74188 setId(element, newId); 74189 instances[newId] = new Instance(element); 74190 return instances[newId]; 74191}; 74192 74193exports.remove = function (element) { 74194 delete instances[getId(element)]; 74195 removeId(element); 74196}; 74197 74198exports.get = function (element) { 74199 return instances[getId(element)]; 74200}; 74201 74202},{"../lib/class":2,"../lib/dom":3,"../lib/event-manager":4,"../lib/guid":5,"../lib/helper":6,"./default-setting":8}],19:[function(require,module,exports){ 74203'use strict'; 74204 74205var _ = require('../lib/helper'); 74206var cls = require('../lib/class'); 74207var dom = require('../lib/dom'); 74208var instances = require('./instances'); 74209var updateScroll = require('./update-scroll'); 74210 74211function getThumbSize(i, thumbSize) { 74212 if (i.settings.minScrollbarLength) { 74213 thumbSize = Math.max(thumbSize, i.settings.minScrollbarLength); 74214 } 74215 if (i.settings.maxScrollbarLength) { 74216 thumbSize = Math.min(thumbSize, i.settings.maxScrollbarLength); 74217 } 74218 return thumbSize; 74219} 74220 74221function updateCss(element, i) { 74222 var xRailOffset = {width: i.railXWidth}; 74223 if (i.isRtl) { 74224 xRailOffset.left = i.negativeScrollAdjustment + element.scrollLeft + i.containerWidth - i.contentWidth; 74225 } else { 74226 xRailOffset.left = element.scrollLeft; 74227 } 74228 if (i.isScrollbarXUsingBottom) { 74229 xRailOffset.bottom = i.scrollbarXBottom - element.scrollTop; 74230 } else { 74231 xRailOffset.top = i.scrollbarXTop + element.scrollTop; 74232 } 74233 dom.css(i.scrollbarXRail, xRailOffset); 74234 74235 var yRailOffset = {top: element.scrollTop, height: i.railYHeight}; 74236 if (i.isScrollbarYUsingRight) { 74237 if (i.isRtl) { 74238 yRailOffset.right = i.contentWidth - (i.negativeScrollAdjustment + element.scrollLeft) - i.scrollbarYRight - i.scrollbarYOuterWidth; 74239 } else { 74240 yRailOffset.right = i.scrollbarYRight - element.scrollLeft; 74241 } 74242 } else { 74243 if (i.isRtl) { 74244 yRailOffset.left = i.negativeScrollAdjustment + element.scrollLeft + i.containerWidth * 2 - i.contentWidth - i.scrollbarYLeft - i.scrollbarYOuterWidth; 74245 } else { 74246 yRailOffset.left = i.scrollbarYLeft + element.scrollLeft; 74247 } 74248 } 74249 dom.css(i.scrollbarYRail, yRailOffset); 74250 74251 dom.css(i.scrollbarX, {left: i.scrollbarXLeft, width: i.scrollbarXWidth - i.railBorderXWidth}); 74252 dom.css(i.scrollbarY, {top: i.scrollbarYTop, height: i.scrollbarYHeight - i.railBorderYWidth}); 74253} 74254 74255module.exports = function (element) { 74256 var i = instances.get(element); 74257 74258 i.containerWidth = element.clientWidth; 74259 i.containerHeight = element.clientHeight; 74260 i.contentWidth = element.scrollWidth; 74261 i.contentHeight = element.scrollHeight; 74262 74263 var existingRails; 74264 if (!element.contains(i.scrollbarXRail)) { 74265 existingRails = dom.queryChildren(element, '.ps-scrollbar-x-rail'); 74266 if (existingRails.length > 0) {
74267 existingRails.forEach(function (rail) { 74268 dom.remove(rail); 74269 }); 74270 } 74271 dom.appendTo(i.scrollbarXRail, element); 74272 } 74273 if (!element.contains(i.scrollbarYRail)) { 74274 existingRails = dom.queryChildren(element, '.ps-scrollbar-y-rail'); 74275 if (existingRails.length > 0) { 74276 existingRails.forEach(function (rail) { 74277 dom.remove(rail); 74278 }); 74279 } 74280 dom.appendTo(i.scrollbarYRail, element); 74281 } 74282 74283 if (!i.settings.suppressScrollX && i.containerWidth + i.settings.scrollXMarginOffset < i.contentWidth) { 74284 i.scrollbarXActive = true; 74285 i.railXWidth = i.containerWidth - i.railXMarginWidth; 74286 i.railXRatio = i.containerWidth / i.railXWidth; 74287 i.scrollbarXWidth = getThumbSize(i, _.toInt(i.railXWidth * i.containerWidth / i.contentWidth)); 74288 i.scrollbarXLeft = _.toInt((i.negativeScrollAdjustment + element.scrollLeft) * (i.railXWidth - i.scrollbarXWidth) / (i.contentWidth - i.containerWidth)); 74289 } else { 74290 i.scrollbarXActive = false; 74291 } 74292 74293 if (!i.settings.suppressScrollY && i.containerHeight + i.settings.scrollYMarginOffset < i.contentHeight) { 74294 i.scrollbarYActive = true; 74295 i.railYHeight = i.containerHeight - i.railYMarginHeight; 74296 i.railYRatio = i.containerHeight / i.railYHeight; 74297 i.scrollbarYHeight = getThumbSize(i, _.toInt(i.railYHeight * i.containerHeight / i.contentHeight)); 74298 i.scrollbarYTop = _.toInt(element.scrollTop * (i.railYHeight - i.scrollbarYHeight) / (i.contentHeight - i.containerHeight)); 74299 } else { 74300 i.scrollbarYActive = false; 74301 } 74302 74303 if (i.scrollbarXLeft >= i.railXWidth - i.scrollbarXWidth) { 74304 i.scrollbarXLeft = i.railXWidth - i.scrollbarXWidth; 74305 } 74306 if (i.scrollbarYTop >= i.railYHeight - i.scrollbarYHeight) { 74307 i.scrollbarYTop = i.railYHeight - i.scrollbarYHeight; 74308 } 74309 74310 updateCss(element, i); 74311 74312 if (i.scrollbarXActive) { 74313 cls.add(element, 'ps-active-x'); 74314 } else { 74315 cls.remove(element, 'ps-active-x'); 74316 i.scrollbarXWidth = 0; 74317 i.scrollbarXLeft = 0; 74318 updateScroll(element, 'left', 0); 74319 } 74320 if (i.scrollbarYActive) { 74321 cls.add(element, 'ps-active-y'); 74322 } else { 74323 cls.remove(element, 'ps-active-y'); 74324 i.scrollbarYHeight = 0; 74325 i.scrollbarYTop = 0; 74326 updateScroll(element, 'top', 0); 74327 } 74328}; 74329 74330},{"../lib/class":2,"../lib/dom":3,"../lib/helper":6,"./instances":18,"./update-scroll":20}],20:[function(require,module,exports){ 74331'use strict'; 74332 74333var instances = require('./instances'); 74334 74335var lastTop; 74336var lastLeft; 74337 74338var createDOMEvent = function (name) { 74339 var event = document.createEvent("Event"); 74340 event.initEvent(name, true, true); 74341 return event; 74342}; 74343 74344module.exports = function (element, axis, value) { 74345 if (typeof element === 'undefined') { 74346 throw 'You must provide an element to the update-scroll function'; 74347 } 74348 74349 if (typeof axis === 'undefined') { 74350 throw 'You must provide an axis to the update-scroll function'; 74351 } 74352 74353 if (typeof value === 'undefined') { 74354 throw 'You must provide a value to the update-scroll function'; 74355 } 74356 74357 if (axis === 'top' && value <= 0) { 74358 element.scrollTop = value = 0; // don't allow negative scroll 74359 element.dispatchEvent(createDOMEvent('ps-y-reach-start')); 74360 } 74361 74362 if (axis === 'left' && value <= 0) { 74363 element.scrollLeft = value = 0; // don't allow negative scroll 74364 element.dispatchEvent(createDOMEvent('ps-x-reach-start')); 74365 } 74366 74367 var i = instances.get(element); 74368 74369 if (axis === 'top' && value >= i.contentHeight - i.containerHeight) { 74370 // don't allow scroll past container 74371 value = i.contentHeight - i.containerHeight; 74372 if (value - element.scrollTop <= 1) { 74373 // mitigates rounding errors on non-subpixel scroll values 74374 value = element.scrollTop; 74375 } else { 74376 element.scrollTop = value; 74377 } 74378 element.dispatchEvent(createDOMEvent('ps-y-reach-end')); 74379 } 74380 74381 if (axis === 'left' && value >= i.contentWidth - i.containerWidth) { 74382 // don't allow scroll past container 74383 value = i.contentWidth - i.containerWidth; 74384 if (value - element.scrollLeft <= 1) { 74385 // mitigates rounding errors on non-subpixel scroll values 74386 value = element.scrollLeft; 74387 } else { 74388 element.scrollLeft = value; 74389 } 74390 element.dispatchEvent(createDOMEvent('ps-x-reach-end')); 74391 } 74392 74393 if (!lastTop) { 74394 lastTop = element.scrollTop; 74395 } 74396 74397 if (!lastLeft) { 74398 lastLeft = element.scrollLeft; 74399 } 74400 74401 if (axis === 'top' && value < lastTop) { 74402 element.dispatchEvent(createDOMEvent('ps-scroll-up')); 74403 } 74404 74405 if (axis === 'top' && value > lastTop) { 74406 element.dispatchEvent(createDOMEvent('ps-scroll-down')); 74407 } 74408 74409 if (axis === 'left' && value < lastLeft) { 74410 element.dispatchEvent(createDOMEvent('ps-scroll-left')); 74411 } 74412 74413 if (axis === 'left' && value > lastLeft) { 74414 element.dispatchEvent(createDOMEvent('ps-scroll-right')); 74415 } 74416 74417 if (axis === 'top') { 74418 element.scrollTop = lastTop = value; 74419 element.dispatchEvent(createDOMEvent('ps-scroll-y')); 74420 } 74421 74422 if (axis === 'left') { 74423 element.scrollLeft = lastLeft = value; 74424 element.dispatchEvent(createDOMEvent('ps-scroll-x')); 74425 } 74426 74427}; 74428 74429},{"./instances":18}],21:[function(require,module,exports){ 74430'use strict'; 74431 74432var _ = require('../lib/helper'); 74433var dom = require('../lib/dom'); 74434var instances = require('./instances'); 74435var updateGeometry = require('./update-geometry'); 74436var updateScroll = require('./update-scroll'); 74437 74438module.exports = function (element) { 74439 var i = instances.get(element); 74440 74441 if (!i) { 74442 return; 74443 } 74444 74445 // Recalcuate negative scrollLeft adjustment 74446 i.negativeScrollAdjustment = i.isNegativeScroll ? element.scrollWidth - element.clientWidth : 0; 74447 74448 // Recalculate rail margins 74449 dom.css(i.scrollbarXRail, 'display', 'block'); 74450 dom.css(i.scrollbarYRail, 'display', 'block'); 74451 i.railXMarginWidth = _.toInt(dom.css(i.scrollbarXRail, 'marginLeft')) + _.toInt(dom.css(i.scrollbarXRail, 'marginRight')); 74452 i.railYMarginHeight = _.toInt(dom.css(i.scrollbarYRail, 'marginTop')) + _.toInt(dom.css(i.scrollbarYRail, 'marginBottom')); 74453 74454 // Hide scrollbars not to affect scrollWidth and scrollHeight 74455 dom.css(i.scrollbarXRail, 'display', 'none'); 74456 dom.css(i.scrollbarYRail, 'display', 'none'); 74457 74458 updateGeometry(element); 74459 74460 // Update top/left scroll to trigger events 74461 updateScroll(element, 'top', element.scrollTop); 74462 updateScroll(element, 'left', element.scrollLeft); 74463 74464 dom.css(i.scrollbarXRail, 'display', ''); 74465 dom.css(i.scrollbarYRail, 'display', ''); 74466}; 74467 74468},{"../lib/dom":3,"../lib/helper":6,"./instances":18,"./update-geometry":19,"./update-scroll":20}]},{},[1]); 74469 74470 /** 74471 * React v15.0.2 74472 */ 74473(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define('react',[],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.React = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){ 74474/** 74475 * Copyright 2013-present, Facebook, Inc. 74476 * All rights reserved. 74477 * 74478 * This source code is licensed under the BSD-style license found in the 74479 * LICENSE file in the root directory of this source tree. An additional grant 74480 * of patent rights can be found in the PATENTS file in the same directory. 74481 * 74482 * @providesModule AutoFocusUtils 74483 */ 74484 74485 74486 74487var ReactDOMComponentTree = _dereq_(40); 74488 74489var focusNode = _dereq_(152); 74490 74491var AutoFocusUtils = { 74492 focusDOMComponent: function () { 74493 focusNode(ReactDOMComponentTree.getNodeFromInstance(this)); 74494 } 74495}; 74496 74497module.exports = AutoFocusUtils; 74498},{"152":152,"40":40}],2:[function(_dereq_,module,exports){ 74499/** 74500 * Copyright 2013-present Facebook, Inc. 74501 * All rights reserved. 74502 * 74503 * This source code is licensed under the BSD-style license found in the 74504 * LICENSE file in the root directory of this source tree. An additional grant 74505 * of patent rights can be found in the PATENTS file in the same directory. 74506 * 74507 * @providesModule BeforeInputEventPlugin 74508 */ 74509 74510 74511 74512var EventConstants = _dereq_(16); 74513var EventPropagators = _dereq_(20); 74514var ExecutionEnvironment = _dereq_(144); 74515var FallbackCompositionState = _dereq_(21); 74516var SyntheticCompositionEvent = _dereq_(101); 74517var SyntheticInputEvent = _dereq_(105); 74518 74519var keyOf = _dereq_(162); 74520 74521var END_KEYCODES = [9, 13, 27, 32]; // Tab, Return, Esc, Space 74522var START_KEYCODE = 229; 74523 74524var canUseCompositionEvent = ExecutionEnvironment.canUseDOM && 'CompositionEvent' in window; 74525 74526var documentMode = null; 74527if (ExecutionEnvironment.canUseDOM && 'documentMode' in document) { 74528 documentMode = document.documentMode; 74529} 74530 74531// Webkit offers a very useful `textInput` event that can be used to 74532// directly represent `beforeInput`. The IE `textinput` event is not as 74533// useful, so we don't use it. 74534var canUseTextInputEvent = ExecutionEnvironment.canUseDOM && 'TextEvent' in window && !documentMode && !isPresto(); 74535 74536// In IE9+, we have access to composition events, but the data supplied 74537// by the native compositionend event may be incorrect. Japanese ideographic 74538// spaces, for instance (\u3000) are not recorded correctly. 74539var useFallbackCompositionData = ExecutionEnvironment.canUseDOM && (!canUseCompositionEvent || documentMode && documentMode > 8 && documentMode <= 11); 74540 74541/** 74542 * Opera <= 12 includes TextEvent in window, but does not fire 74543 * text input events. Rely on keypress instead. 74544 */ 74545function isPresto() { 74546 var opera = window.opera; 74547 return typeof opera === 'object' && typeof opera.version === 'function' && parseInt(opera.version(), 10) <= 12; 74548} 74549 74550var SPACEBAR_CODE = 32; 74551var SPACEBAR_CHAR = String.fromCharCode(SPACEBAR_CODE); 74552
74553var topLevelTypes = EventConstants.topLevelTypes; 74554 74555// Events and their corresponding property names. 74556var eventTypes = { 74557 beforeInput: { 74558 phasedRegistrationNames: { 74559 bubbled: keyOf({ onBeforeInput: null }), 74560 captured: keyOf({ onBeforeInputCapture: null }) 74561 }, 74562 dependencies: [topLevelTypes.topCompositionEnd, topLevelTypes.topKeyPress, topLevelTypes.topTextInput, topLevelTypes.topPaste] 74563 }, 74564 compositionEnd: { 74565 phasedRegistrationNames: { 74566 bubbled: keyOf({ onCompositionEnd: null }), 74567 captured: keyOf({ onCompositionEndCapture: null }) 74568 }, 74569 dependencies: [topLevelTypes.topBlur, topLevelTypes.topCompositionEnd, topLevelTypes.topKeyDown, topLevelTypes.topKeyPress, topLevelTypes.topKeyUp, topLevelTypes.topMouseDown] 74570 }, 74571 compositionStart: { 74572 phasedRegistrationNames: { 74573 bubbled: keyOf({ onCompositionStart: null }), 74574 captured: keyOf({ onCompositionStartCapture: null }) 74575 }, 74576 dependencies: [topLevelTypes.topBlur, topLevelTypes.topCompositionStart, topLevelTypes.topKeyDown, topLevelTypes.topKeyPress, topLevelTypes.topKeyUp, topLevelTypes.topMouseDown] 74577 }, 74578 compositionUpdate: { 74579 phasedRegistrationNames: { 74580 bubbled: keyOf({ onCompositionUpdate: null }), 74581 captured: keyOf({ onCompositionUpdateCapture: null }) 74582 }, 74583 dependencies: [topLevelTypes.topBlur, topLevelTypes.topCompositionUpdate, topLevelTypes.topKeyDown, topLevelTypes.topKeyPress, topLevelTypes.topKeyUp, topLevelTypes.topMouseDown] 74584 } 74585}; 74586 74587// Track whether we've ever handled a keypress on the space key. 74588var hasSpaceKeypress = false; 74589 74590/** 74591 * Return whether a native keypress event is assumed to be a command. 74592 * This is required because Firefox fires `keypress` events for key commands 74593 * (cut, copy, select-all, etc.) even though no character is inserted. 74594 */ 74595function isKeypressCommand(nativeEvent) { 74596 return (nativeEvent.ctrlKey || nativeEvent.altKey || nativeEvent.metaKey) && 74597 // ctrlKey && altKey is equivalent to AltGr, and is not a command. 74598 !(nativeEvent.ctrlKey && nativeEvent.altKey); 74599} 74600 74601/** 74602 * Translate native top level events into event types. 74603 * 74604 * @param {string} topLevelType 74605 * @return {object} 74606 */ 74607function getCompositionEventType(topLevelType) { 74608 switch (topLevelType) { 74609 case topLevelTypes.topCompositionStart: 74610 return eventTypes.compositionStart; 74611 case topLevelTypes.topCompositionEnd: 74612 return eventTypes.compositionEnd; 74613 case topLevelTypes.topCompositionUpdate: 74614 return eventTypes.compositionUpdate; 74615 } 74616} 74617 74618/** 74619 * Does our fallback best-guess model think this event signifies that 74620 * composition has begun? 74621 * 74622 * @param {string} topLevelType 74623 * @param {object} nativeEvent 74624 * @return {boolean} 74625 */ 74626function isFallbackCompositionStart(topLevelType, nativeEvent) { 74627 return topLevelType === topLevelTypes.topKeyDown && nativeEvent.keyCode === START_KEYCODE; 74628} 74629 74630/** 74631 * Does our fallback mode think that this event is the end of composition? 74632 * 74633 * @param {string} topLevelType 74634 * @param {object} nativeEvent 74635 * @return {boolean} 74636 */ 74637function isFallbackCompositionEnd(topLevelType, nativeEvent) { 74638 switch (topLevelType) { 74639 case topLevelTypes.topKeyUp: 74640 // Command keys insert or clear IME input. 74641 return END_KEYCODES.indexOf(nativeEvent.keyCode) !== -1; 74642 case topLevelTypes.topKeyDown: 74643 // Expect IME keyCode on each keydown. If we get any other 74644 // code we must have exited earlier. 74645 return nativeEvent.keyCode !== START_KEYCODE; 74646 case topLevelTypes.topKeyPress: 74647 case topLevelTypes.topMouseDown: 74648 case topLevelTypes.topBlur: 74649 // Events are not possible without cancelling IME. 74650 return true; 74651 default: 74652 return false; 74653 } 74654} 74655 74656/** 74657 * Google Input Tools provides composition data via a CustomEvent, 74658 * with the `data` property populated in the `detail` object. If this 74659 * is available on the event object, use it. If not, this is a plain 74660 * composition event and we have nothing special to extract. 74661 * 74662 * @param {object} nativeEvent 74663 * @return {?string} 74664 */ 74665function getDataFromCustomEvent(nativeEvent) { 74666 var detail = nativeEvent.detail; 74667 if (typeof detail === 'object' && 'data' in detail) { 74668 return detail.data; 74669 } 74670 return null; 74671} 74672 74673// Track the current IME composition fallback object, if any. 74674var currentComposition = null; 74675 74676/** 74677 * @return {?object} A SyntheticCompositionEvent. 74678 */ 74679function extractCompositionEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget) { 74680 var eventType; 74681 var fallbackData; 74682 74683 if (canUseCompositionEvent) { 74684 eventType = getCompositionEventType(topLevelType); 74685 } else if (!currentComposition) { 74686 if (isFallbackCompositionStart(topLevelType, nativeEvent)) { 74687 eventType = eventTypes.compositionStart; 74688 } 74689 } else if (isFallbackCompositionEnd(topLevelType, nativeEvent)) { 74690 eventType = eventTypes.compositionEnd; 74691 } 74692 74693 if (!eventType) { 74694 return null; 74695 } 74696 74697 if (useFallbackCompositionData) { 74698 // The current composition is stored statically and must not be 74699 // overwritten while composition continues. 74700 if (!currentComposition && eventType === eventTypes.compositionStart) { 74701 currentComposition = FallbackCompositionState.getPooled(nativeEventTarget); 74702 } else if (eventType === eventTypes.compositionEnd) { 74703 if (currentComposition) { 74704 fallbackData = currentComposition.getData(); 74705 } 74706 } 74707 } 74708 74709 var event = SyntheticCompositionEvent.getPooled(eventType, targetInst, nativeEvent, nativeEventTarget); 74710 74711 if (fallbackData) { 74712 // Inject data generated from fallback path into the synthetic event. 74713 // This matches the property of native CompositionEventInterface. 74714 event.data = fallbackData; 74715 } else { 74716 var customData = getDataFromCustomEvent(nativeEvent); 74717 if (customData !== null) { 74718 event.data = customData; 74719 } 74720 } 74721 74722 EventPropagators.accumulateTwoPhaseDispatches(event); 74723 return event; 74724} 74725
74726/** 74727 * @param {string} topLevelType Record from `EventConstants`. 74728 * @param {object} nativeEvent Native browser event. 74729 * @return {?string} The string corresponding to this `beforeInput` event. 74730 */ 74731function getNativeBeforeInputChars(topLevelType, nativeEvent) { 74732 switch (topLevelType) { 74733 case topLevelTypes.topCompositionEnd: 74734 return getDataFromCustomEvent(nativeEvent); 74735 case topLevelTypes.topKeyPress: 74736 /** 74737 * If native `textInput` events are available, our goal is to make 74738 * use of them. However, there is a special case: the spacebar key. 74739 * In Webkit, preventing default on a spacebar `textInput` event 74740 * cancels character insertion, but it *also* causes the browser 74741 * to fall back to its default spacebar behavior of scrolling the 74742 * page. 74743 * 74744 * Tracking at: 74745 * https://code.google.com/p/chromium/issues/detail?id=355103 74746 * 74747 * To avoid this issue, use the keypress event as if no `textInput` 74748 * event is available. 74749 */ 74750 var which = nativeEvent.which; 74751 if (which !== SPACEBAR_CODE) { 74752 return null; 74753 } 74754 74755 hasSpaceKeypress = true; 74756 return SPACEBAR_CHAR; 74757 74758 case topLevelTypes.topTextInput: 74759 // Record the characters to be added to the DOM. 74760 var chars = nativeEvent.data; 74761 74762 // If it's a spacebar character, assume that we have already handled 74763 // it at the keypress level and bail immediately. Android Chrome 74764 // doesn't give us keycodes, so we need to blacklist it. 74765 if (chars === SPACEBAR_CHAR && hasSpaceKeypress) { 74766 return null; 74767 } 74768 74769 return chars; 74770 74771 default: 74772 // For other native event types, do nothing. 74773 return null; 74774 } 74775} 74776 74777/** 74778 * For browsers that do not provide the `textInput` event, extract the 74779 * appropriate string to use for SyntheticInputEvent. 74780 * 74781 * @param {string} topLevelType Record from `EventConstants`. 74782 * @param {object} nativeEvent Native browser event. 74783 * @return {?string} The fallback string for this `beforeInput` event. 74784 */ 74785function getFallbackBeforeInputChars(topLevelType, nativeEvent) { 74786 // If we are currently composing (IME) and using a fallback to do so, 74787 // try to extract the composed characters from the fallback object. 74788 if (currentComposition) { 74789 if (topLevelType === topLevelTypes.topCompositionEnd || isFallbackCompositionEnd(topLevelType, nativeEvent)) { 74790 var chars = currentComposition.getData(); 74791 FallbackCompositionState.release(currentComposition); 74792 currentComposition = null; 74793 return chars; 74794 } 74795 return null; 74796 } 74797 74798 switch (topLevelType) { 74799 case topLevelTypes.topPaste: 74800 // If a paste event occurs after a keypress, throw out the input 74801 // chars. Paste events should not lead to BeforeInput events. 74802 return null; 74803 case topLevelTypes.topKeyPress: 74804 /** 74805 * As of v27, Firefox may fire keypress events even when no character 74806 * will be inserted. A few possibilities: 74807 * 74808 * - `which` is `0`. Arrow keys, Esc key, etc. 74809 * 74810 * - `which` is the pressed key code, but no char is available. 74811 * Ex: 'AltGr + d` in Polish. There is no modified character for 74812 * this key combination and no character is inserted into the 74813 * document, but FF fires the keypress for char code `100` anyway. 74814 * No `input` event will occur. 74815 * 74816 * - `which` is the pressed key code, but a command combination is 74817 * being used. Ex: `Cmd+C`. No character is inserted, and no 74818 * `input` event will occur. 74819 */ 74820 if (nativeEvent.which && !isKeypressCommand(nativeEvent)) { 74821 return String.fromCharCode(nativeEvent.which); 74822 } 74823 return null; 74824 case topLevelTypes.topCompositionEnd: 74825 return useFallbackCompositionData ? null : nativeEvent.data; 74826 default: 74827 return null; 74828 } 74829} 74830 74831/** 74832 * Extract a SyntheticInputEvent for `beforeInput`, based on either native 74833 * `textInput` or fallback behavior. 74834 * 74835 * @return {?object} A SyntheticInputEvent. 74836 */ 74837function extractBeforeInputEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget) { 74838 var chars; 74839 74840 if (canUseTextInputEvent) { 74841 chars = getNativeBeforeInputChars(topLevelType, nativeEvent); 74842 } else { 74843 chars = getFallbackBeforeInputChars(topLevelType, nativeEvent); 74844 } 74845 74846 // If no characters are being inserted, no BeforeInput event should 74847 // be fired. 74848 if (!chars) { 74849 return null; 74850 } 74851 74852 var event = SyntheticInputEvent.getPooled(eventTypes.beforeInput, targetInst, nativeEvent, nativeEventTarget); 74853 74854 event.data = chars; 74855 EventPropagators.accumulateTwoPhaseDispatches(event); 74856 return event; 74857} 74858
74859/** 74860 * Create an `onBeforeInput` event to match 74861 * http://www.w3.org/TR/2013/WD-DOM-Level-3-Events-20131105/#events-inputevents. 74862 * 74863 * This event plugin is based on the native `textInput` event 74864 * available in Chrome, Safari, Opera, and IE. This event fires after 74865 * `onKeyPress` and `onCompositionEnd`, but before `onInput`. 74866 * 74867 * `beforeInput` is spec'd but not implemented in any browsers, and 74868 * the `input` event does not provide any useful information about what has 74869 * actually been added, contrary to the spec. Thus, `textInput` is the best 74870 * available event to identify the characters that have actually been inserted 74871 * into the target node. 74872 * 74873 * This plugin is also responsible for emitting `composition` events, thus 74874 * allowing us to share composition fallback code for both `beforeInput` and 74875 * `composition` event types. 74876 */ 74877var BeforeInputEventPlugin = { 74878 74879 eventTypes: eventTypes, 74880 74881 extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) { 74882 return [extractCompositionEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget), extractBeforeInputEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget)]; 74883 } 74884}; 74885 74886module.exports = BeforeInputEventPlugin; 74887},{"101":101,"105":105,"144":144,"16":16,"162":162,"20":20,"21":21}],3:[function(_dereq_,module,exports){ 74888/** 74889 * Copyright 2013-present, Facebook, Inc. 74890 * All rights reserved. 74891 * 74892 * This source code is licensed under the BSD-style license found in the 74893 * LICENSE file in the root directory of this source tree. An additional grant 74894 * of patent rights can be found in the PATENTS file in the same directory. 74895 * 74896 * @providesModule CSSProperty 74897 */ 74898 74899 74900 74901/** 74902 * CSS properties which accept numbers but are not in units of "px". 74903 */ 74904 74905var isUnitlessNumber = { 74906 animationIterationCount: true, 74907 borderImageOutset: true, 74908 borderImageSlice: true, 74909 borderImageWidth: true, 74910 boxFlex: true, 74911 boxFlexGroup: true, 74912 boxOrdinalGroup: true, 74913 columnCount: true, 74914 flex: true, 74915 flexGrow: true, 74916 flexPositive: true, 74917 flexShrink: true, 74918 flexNegative: true, 74919 flexOrder: true, 74920 gridRow: true, 74921 gridColumn: true, 74922 fontWeight: true, 74923 lineClamp: true, 74924 lineHeight: true, 74925 opacity: true, 74926 order: true, 74927 orphans: true, 74928 tabSize: true, 74929 widows: true, 74930 zIndex: true, 74931 zoom: true, 74932 74933 // SVG-related properties 74934 fillOpacity: true, 74935 floodOpacity: true, 74936 stopOpacity: true, 74937 strokeDasharray: true, 74938 strokeDashoffset: true, 74939 strokeMiterlimit: true, 74940 strokeOpacity: true, 74941 strokeWidth: true 74942}; 74943 74944/** 74945 * @param {string} prefix vendor-specific prefix, eg: Webkit 74946 * @param {string} key style name, eg: transitionDuration 74947 * @return {string} style name prefixed with `prefix`, properly camelCased, eg: 74948 * WebkitTransitionDuration 74949 */ 74950function prefixKey(prefix, key) { 74951 return prefix + key.charAt(0).toUpperCase() + key.substring(1); 74952} 74953 74954/** 74955 * Support style names that may come passed in prefixed by adding permutations 74956 * of vendor prefixes. 74957 */ 74958var prefixes = ['Webkit', 'ms', 'Moz', 'O']; 74959 74960// Using Object.keys here, or else the vanilla for-in loop makes IE8 go into an 74961// infinite loop, because it iterates over the newly added props too. 74962Object.keys(isUnitlessNumber).forEach(function (prop) { 74963 prefixes.forEach(function (prefix) { 74964 isUnitlessNumber[prefixKey(prefix, prop)] = isUnitlessNumber[prop]; 74965 }); 74966}); 74967 74968/** 74969 * Most style properties can be unset by doing .style[prop] = '' but IE8 74970 * doesn't like doing that with shorthand properties so for the properties that 74971 * IE8 breaks on, which are listed here, we instead unset each of the 74972 * individual properties. See http://bugs.jquery.com/ticket/12385. 74973 * The 4-value 'clock' properties like margin, padding, border-width seem to 74974 * behave without any problems. Curiously, list-style works too without any 74975 * special prodding. 74976 */ 74977var shorthandPropertyExpansions = { 74978 background: { 74979 backgroundAttachment: true, 74980 backgroundColor: true, 74981 backgroundImage: true, 74982 backgroundPositionX: true, 74983 backgroundPositionY: true, 74984 backgroundRepeat: true 74985 }, 74986 backgroundPosition: { 74987 backgroundPositionX: true, 74988 backgroundPositionY: true 74989 }, 74990 border: { 74991 borderWidth: true, 74992 borderStyle: true, 74993 borderColor: true 74994 }, 74995 borderBottom: { 74996 borderBottomWidth: true, 74997 borderBottomStyle: true, 74998 borderBottomColor: true 74999 }, 75000 borderLeft: { 75001 borderLeftWidth: true, 75002 borderLeftStyle: true, 75003 borderLeftColor: true 75004 }, 75005 borderRight: { 75006 borderRightWidth: true, 75007 borderRightStyle: true, 75008 borderRightColor: true 75009 }, 75010 borderTop: { 75011 borderTopWidth: true, 75012 borderTopStyle: true, 75013 borderTopColor: true 75014 }, 75015 font: { 75016 fontStyle: true, 75017 fontVariant: true, 75018 fontWeight: true, 75019 fontSize: true, 75020 lineHeight: true, 75021 fontFamily: true 75022 }, 75023 outline: { 75024 outlineWidth: true, 75025 outlineStyle: true, 75026 outlineColor: true 75027 } 75028}; 75029 75030var CSSProperty = { 75031 isUnitlessNumber: isUnitlessNumber, 75032 shorthandPropertyExpansions: shorthandPropertyExpansions 75033}; 75034 75035module.exports = CSSProperty; 75036},{}],4:[function(_dereq_,module,exports){ 75037/** 75038 * Copyright 2013-present, Facebook, Inc. 75039 * All rights reserved. 75040 * 75041 * This source code is licensed under the BSD-style license found in the 75042 * LICENSE file in the root directory of this source tree. An additional grant 75043 * of patent rights can be found in the PATENTS file in the same directory. 75044 * 75045 * @providesModule CSSPropertyOperations 75046 */ 75047 75048 75049 75050var CSSProperty = _dereq_(3); 75051var ExecutionEnvironment = _dereq_(144); 75052var ReactPerf = _dereq_(82); 75053 75054var camelizeStyleName = _dereq_(146); 75055var dangerousStyleValue = _dereq_(118); 75056var hyphenateStyleName = _dereq_(157); 75057var memoizeStringOnly = _dereq_(164); 75058var warning = _dereq_(168); 75059 75060var processStyleName = memoizeStringOnly(function (styleName) { 75061 return hyphenateStyleName(styleName); 75062}); 75063 75064var hasShorthandPropertyBug = false;
75065var styleFloatAccessor = 'cssFloat'; 75066if (ExecutionEnvironment.canUseDOM) { 75067 var tempStyle = document.createElement('div').style; 75068 try { 75069 // IE8 throws "Invalid argument." if resetting shorthand style properties. 75070 tempStyle.font = ''; 75071 } catch (e) { 75072 hasShorthandPropertyBug = true; 75073 } 75074 // IE8 only supports accessing cssFloat (standard) as styleFloat 75075 if (document.documentElement.style.cssFloat === undefined) { 75076 styleFloatAccessor = 'styleFloat'; 75077 } 75078} 75079 75080if ("development" !== 'production') { 75081 // 'msTransform' is correct, but the other prefixes should be capitalized 75082 var badVendoredStyleNamePattern = /^(?:webkit|moz|o)[A-Z]/; 75083 75084 // style values shouldn't contain a semicolon 75085 var badStyleValueWithSemicolonPattern = /;\s*$/; 75086 75087 var warnedStyleNames = {}; 75088 var warnedStyleValues = {}; 75089 var warnedForNaNValue = false; 75090 75091 var warnHyphenatedStyleName = function (name, owner) { 75092 if (warnedStyleNames.hasOwnProperty(name) && warnedStyleNames[name]) { 75093 return; 75094 } 75095 75096 warnedStyleNames[name] = true; 75097 "development" !== 'production' ? warning(false, 'Unsupported style property %s. Did you mean %s?%s', name, camelizeStyleName(name), checkRenderMessage(owner)) : void 0; 75098 }; 75099 75100 var warnBadVendoredStyleName = function (name, owner) { 75101 if (warnedStyleNames.hasOwnProperty(name) && warnedStyleNames[name]) { 75102 return; 75103 } 75104 75105 warnedStyleNames[name] = true; 75106 "development" !== 'production' ? warning(false, 'Unsupported vendor-prefixed style property %s. Did you mean %s?%s', name, name.charAt(0).toUpperCase() + name.slice(1), checkRenderMessage(owner)) : void 0; 75107 }; 75108 75109 var warnStyleValueWithSemicolon = function (name, value, owner) { 75110 if (warnedStyleValues.hasOwnProperty(value) && warnedStyleValues[value]) { 75111 return; 75112 } 75113 75114 warnedStyleValues[value] = true; 75115 "development" !== 'production' ? warning(false, 'Style property values shouldn\'t contain a semicolon.%s ' + 'Try "%s: %s" instead.', checkRenderMessage(owner), name, value.replace(badStyleValueWithSemicolonPattern, '')) : void 0; 75116 }; 75117 75118 var warnStyleValueIsNaN = function (name, value, owner) { 75119 if (warnedForNaNValue) { 75120 return; 75121 } 75122 75123 warnedForNaNValue = true; 75124 "development" !== 'production' ? warning(false, '`NaN` is an invalid value for the `%s` css style property.%s', name, checkRenderMessage(owner)) : void 0; 75125 }; 75126 75127 var checkRenderMessage = function (owner) { 75128 if (owner) { 75129 var name = owner.getName(); 75130 if (name) { 75131 return ' Check the render method of `' + name + '`.'; 75132 } 75133 } 75134 return ''; 75135 }; 75136 75137 /** 75138 * @param {string} name 75139 * @param {*} value 75140 * @param {ReactDOMComponent} component 75141 */ 75142 var warnValidStyle = function (name, value, component) { 75143 var owner; 75144 if (component) { 75145 owner = component._currentElement._owner; 75146 } 75147 if (name.indexOf('-') > -1) { 75148 warnHyphenatedStyleName(name, owner); 75149 } else if (badVendoredStyleNamePattern.test(name)) { 75150 warnBadVendoredStyleName(name, owner); 75151 } else if (badStyleValueWithSemicolonPattern.test(value)) { 75152 warnStyleValueWithSemicolon(name, value, owner); 75153 } 75154 75155 if (typeof value === 'number' && isNaN(value)) { 75156 warnStyleValueIsNaN(name, value, owner); 75157 } 75158 }; 75159} 75160 75161/** 75162 * Operations for dealing with CSS properties. 75163 */ 75164var CSSPropertyOperations = { 75165 75166 /** 75167 * Serializes a mapping of style properties for use as inline styles: 75168 * 75169 * > createMarkupForStyles({width: '200px', height: 0}) 75170 * "width:200px;height:0;" 75171 * 75172 * Undefined values are ignored so that declarative programming is easier. 75173 * The result should be HTML-escaped before insertion into the DOM. 75174 * 75175 * @param {object} styles 75176 * @param {ReactDOMComponent} component 75177 * @return {?string} 75178 */ 75179 createMarkupForStyles: function (styles, component) { 75180 var serialized = ''; 75181 for (var styleName in styles) { 75182 if (!styles.hasOwnProperty(styleName)) { 75183 continue; 75184 } 75185 var styleValue = styles[styleName]; 75186 if ("development" !== 'production') { 75187 warnValidStyle(styleName, styleValue, component); 75188 } 75189 if (styleValue != null) { 75190 serialized += processStyleName(styleName) + ':'; 75191 serialized += dangerousStyleValue(styleName, styleValue, component) + ';'; 75192 } 75193 } 75194 return serialized || null; 75195 }, 75196 75197 /** 75198 * Sets the value for multiple styles on a node. If a value is specified as 75199 * '' (empty string), the corresponding style property will be unset. 75200 * 75201 * @param {DOMElement} node 75202 * @param {object} styles 75203 * @param {ReactDOMComponent} component 75204 */ 75205 setValueForStyles: function (node, styles, component) { 75206 var style = node.style; 75207 for (var styleName in styles) { 75208 if (!styles.hasOwnProperty(styleName)) { 75209 continue; 75210 } 75211 if ("development" !== 'production') { 75212 warnValidStyle(styleName, styles[styleName], component); 75213 } 75214 var styleValue = dangerousStyleValue(styleName, styles[styleName], component); 75215 if (styleName === 'float' || styleName === 'cssFloat') { 75216 styleName = styleFloatAccessor; 75217 } 75218 if (styleValue) { 75219 style[styleName] = styleValue; 75220 } else { 75221 var expansion = hasShorthandPropertyBug && CSSProperty.shorthandPropertyExpansions[styleName]; 75222 if (expansion) { 75223 // Shorthand property that IE8 won't like unsetting, so unset each 75224 // component to placate it 75225 for (var individualStyleName in expansion) { 75226 style[individualStyleName] = ''; 75227 } 75228 } else { 75229 style[styleName] = ''; 75230 } 75231 } 75232 } 75233 } 75234 75235}; 75236 75237ReactPerf.measureMethods(CSSPropertyOperations, 'CSSPropertyOperations', { 75238 setValueForStyles: 'setValueForStyles' 75239}); 75240 75241module.exports = CSSPropertyOperations; 75242},{"118":118,"144":144,"146":146,"157":157,"164":164,"168":168,"3":3,"82":82}],5:[function(_dereq_,module,exports){ 75243/** 75244 * Copyright 2013-present, Facebook, Inc. 75245 * All rights reserved. 75246 * 75247 * This source code is licensed under the BSD-style license found in the 75248 * LICENSE file in the root directory of this source tree. An additional grant 75249 * of patent rights can be found in the PATENTS file in the same directory. 75250 * 75251 * @providesModule CallbackQueue 75252 */ 75253 75254 75255 75256var _assign = _dereq_(169); 75257 75258var PooledClass = _dereq_(25); 75259 75260var invariant = _dereq_(158); 75261 75262/** 75263 * A specialized pseudo-event module to help keep track of components waiting to 75264 * be notified when their DOM representations are available for use. 75265 * 75266 * This implements `PooledClass`, so you should never need to instantiate this. 75267 * Instead, use `CallbackQueue.getPooled()`. 75268 * 75269 * @class ReactMountReady 75270 * @implements PooledClass 75271 * @internal 75272 */ 75273function CallbackQueue() { 75274 this._callbacks = null; 75275 this._contexts = null; 75276} 75277 75278_assign(CallbackQueue.prototype, { 75279 75280 /** 75281 * Enqueues a callback to be invoked when `notifyAll` is invoked. 75282 * 75283 * @param {function} callback Invoked when `notifyAll` is invoked. 75284 * @param {?object} context Context to call `callback` with. 75285 * @internal 75286 */ 75287 enqueue: function (callback, context) { 75288 this._callbacks = this._callbacks || []; 75289 this._contexts = this._contexts || []; 75290 this._callbacks.push(callback); 75291 this._contexts.push(context); 75292 }, 75293 75294 /** 75295 * Invokes all enqueued callbacks and clears the queue. This is invoked after 75296 * the DOM representation of a component has been created or updated. 75297 * 75298 * @internal 75299 */ 75300 notifyAll: function () { 75301 var callbacks = this._callbacks; 75302 var contexts = this._contexts; 75303 if (callbacks) { 75304 !(callbacks.length === contexts.length) ? "development" !== 'production' ? invariant(false, 'Mismatched list of contexts in callback queue') : invariant(false) : void 0; 75305 this._callbacks = null; 75306 this._contexts = null; 75307 for (var i = 0; i < callbacks.length; i++) { 75308 callbacks[i].call(contexts[i]); 75309 } 75310 callbacks.length = 0; 75311 contexts.length = 0; 75312 } 75313 }, 75314 75315 checkpoint: function () { 75316 return this._callbacks ? this._callbacks.length : 0; 75317 }, 75318 75319 rollback: function (len) { 75320 if (this._callbacks) { 75321 this._callbacks.length = len; 75322 this._contexts.length = len; 75323 } 75324 }, 75325 75326 /** 75327 * Resets the internal queue. 75328 * 75329 * @internal 75330 */ 75331 reset: function () { 75332 this._callbacks = null; 75333 this._contexts = null; 75334 }, 75335 75336 /** 75337 * `PooledClass` looks for this. 75338 */ 75339 destructor: function () { 75340 this.reset(); 75341 } 75342 75343}); 75344 75345PooledClass.addPoolingTo(CallbackQueue); 75346 75347module.exports = CallbackQueue; 75348},{"158":158,"169":169,"25":25}],6:[function(_dereq_,module,exports){ 75349/** 75350 * Copyright 2013-present, Facebook, Inc. 75351 * All rights reserved. 75352 * 75353 * This source code is licensed under the BSD-style license found in the 75354 * LICENSE file in the root directory of this source tree. An additional grant 75355 * of patent rights can be found in the PATENTS file in the same directory. 75356 * 75357 * @providesModule ChangeEventPlugin 75358 */ 75359 75360 75361 75362var EventConstants = _dereq_(16); 75363var EventPluginHub = _dereq_(17); 75364var EventPropagators = _dereq_(20); 75365var ExecutionEnvironment = _dereq_(144); 75366var ReactDOMComponentTree = _dereq_(40); 75367var ReactUpdates = _dereq_(94); 75368var SyntheticEvent = _dereq_(103); 75369 75370var getEventTarget = _dereq_(126); 75371var isEventSupported = _dereq_(133); 75372var isTextInputElement = _dereq_(134); 75373var keyOf = _dereq_(162); 75374
75375var topLevelTypes = EventConstants.topLevelTypes; 75376 75377var eventTypes = { 75378 change: { 75379 phasedRegistrationNames: { 75380 bubbled: keyOf({ onChange: null }), 75381 captured: keyOf({ onChangeCapture: null }) 75382 }, 75383 dependencies: [topLevelTypes.topBlur, topLevelTypes.topChange, topLevelTypes.topClick, topLevelTypes.topFocus, topLevelTypes.topInput, topLevelTypes.topKeyDown, topLevelTypes.topKeyUp, topLevelTypes.topSelectionChange] 75384 } 75385}; 75386 75387/** 75388 * For IE shims 75389 */ 75390var activeElement = null; 75391var activeElementInst = null; 75392var activeElementValue = null; 75393var activeElementValueProp = null; 75394 75395/** 75396 * SECTION: handle `change` event 75397 */ 75398function shouldUseChangeEvent(elem) { 75399 var nodeName = elem.nodeName && elem.nodeName.toLowerCase(); 75400 return nodeName === 'select' || nodeName === 'input' && elem.type === 'file'; 75401} 75402 75403var doesChangeEventBubble = false; 75404if (ExecutionEnvironment.canUseDOM) { 75405 // See `handleChange` comment below 75406 doesChangeEventBubble = isEventSupported('change') && (!('documentMode' in document) || document.documentMode > 8); 75407} 75408 75409function manualDispatchChangeEvent(nativeEvent) { 75410 var event = SyntheticEvent.getPooled(eventTypes.change, activeElementInst, nativeEvent, getEventTarget(nativeEvent)); 75411 EventPropagators.accumulateTwoPhaseDispatches(event); 75412 75413 // If change and propertychange bubbled, we'd just bind to it like all the 75414 // other events and have it go through ReactBrowserEventEmitter. Since it 75415 // doesn't, we manually listen for the events and so we have to enqueue and 75416 // process the abstract event manually. 75417 // 75418 // Batching is necessary here in order to ensure that all event handlers run 75419 // before the next rerender (including event handlers attached to ancestor 75420 // elements instead of directly on the input). Without this, controlled 75421 // components don't work properly in conjunction with event bubbling because 75422 // the component is rerendered and the value reverted before all the event 75423 // handlers can run. See https://github.com/facebook/react/issues/708. 75424 ReactUpdates.batchedUpdates(runEventInBatch, event); 75425} 75426 75427function runEventInBatch(event) { 75428 EventPluginHub.enqueueEvents(event); 75429 EventPluginHub.processEventQueue(false); 75430} 75431 75432function startWatchingForChangeEventIE8(target, targetInst) { 75433 activeElement = target; 75434 activeElementInst = targetInst; 75435 activeElement.attachEvent('onchange', manualDispatchChangeEvent); 75436} 75437 75438function stopWatchingForChangeEventIE8() { 75439 if (!activeElement) { 75440 return; 75441 } 75442 activeElement.detachEvent('onchange', manualDispatchChangeEvent); 75443 activeElement = null; 75444 activeElementInst = null; 75445} 75446 75447function getTargetInstForChangeEvent(topLevelType, targetInst) { 75448 if (topLevelType === topLevelTypes.topChange) { 75449 return targetInst; 75450 } 75451} 75452function handleEventsForChangeEventIE8(topLevelType, target, targetInst) { 75453 if (topLevelType === topLevelTypes.topFocus) { 75454 // stopWatching() should be a noop here but we call it just in case we 75455 // missed a blur event somehow. 75456 stopWatchingForChangeEventIE8(); 75457 startWatchingForChangeEventIE8(target, targetInst); 75458 } else if (topLevelType === topLevelTypes.topBlur) { 75459 stopWatchingForChangeEventIE8(); 75460 } 75461} 75462 75463/** 75464 * SECTION: handle `input` event 75465 */ 75466var isInputEventSupported = false; 75467if (ExecutionEnvironment.canUseDOM) { 75468 // IE9 claims to support the input event but fails to trigger it when 75469 // deleting text, so we ignore its input events. 75470 // IE10+ fire input events to often, such when a placeholder 75471 // changes or when an input with a placeholder is focused. 75472 isInputEventSupported = isEventSupported('input') && (!('documentMode' in document) || document.documentMode > 11); 75473} 75474 75475/** 75476 * (For IE <=11) Replacement getter/setter for the `value` property that gets 75477 * set on the active element. 75478 */ 75479var newValueProp = { 75480 get: function () { 75481 return activeElementValueProp.get.call(this); 75482 }, 75483 set: function (val) { 75484 // Cast to a string so we can do equality checks. 75485 activeElementValue = '' + val; 75486 activeElementValueProp.set.call(this, val); 75487 } 75488}; 75489 75490/** 75491 * (For IE <=11) Starts tracking propertychange events on the passed-in element 75492 * and override the value property so that we can distinguish user events from 75493 * value changes in JS. 75494 */ 75495function startWatchingForValueChange(target, targetInst) { 75496 activeElement = target; 75497 activeElementInst = targetInst; 75498 activeElementValue = target.value; 75499 activeElementValueProp = Object.getOwnPropertyDescriptor(target.constructor.prototype, 'value'); 75500 75501 // Not guarded in a canDefineProperty check: IE8 supports defineProperty only 75502 // on DOM elements 75503 Object.defineProperty(activeElement, 'value', newValueProp); 75504 if (activeElement.attachEvent) { 75505 activeElement.attachEvent('onpropertychange', handlePropertyChange); 75506 } else { 75507 activeElement.addEventListener('propertychange', handlePropertyChange, false); 75508 } 75509} 75510 75511/** 75512 * (For IE <=11) Removes the event listeners from the currently-tracked element, 75513 * if any exists. 75514 */ 75515function stopWatchingForValueChange() { 75516 if (!activeElement) { 75517 return; 75518 } 75519 75520 // delete restores the original property definition 75521 delete activeElement.value; 75522 75523 if (activeElement.detachEvent) { 75524 activeElement.detachEvent('onpropertychange', handlePropertyChange); 75525 } else { 75526 activeElement.removeEventListener('propertychange', handlePropertyChange, false); 75527 } 75528 75529 activeElement = null; 75530 activeElementInst = null; 75531 activeElementValue = null; 75532 activeElementValueProp = null; 75533} 75534 75535/** 75536 * (For IE <=11) Handles a propertychange event, sending a `change` event if 75537 * the value of the active element has changed. 75538 */ 75539function handlePropertyChange(nativeEvent) { 75540 if (nativeEvent.propertyName !== 'value') { 75541 return; 75542 } 75543 var value = nativeEvent.srcElement.value; 75544 if (value === activeElementValue) { 75545 return; 75546 } 75547 activeElementValue = value; 75548 75549 manualDispatchChangeEvent(nativeEvent); 75550} 75551 75552/** 75553 * If a `change` event should be fired, returns the target's ID. 75554 */ 75555function getTargetInstForInputEvent(topLevelType, targetInst) { 75556 if (topLevelType === topLevelTypes.topInput) { 75557 // In modern browsers (i.e., not IE8 or IE9), the input event is exactly 75558 // what we want so fall through here and trigger an abstract event 75559 return targetInst; 75560 } 75561} 75562 75563function handleEventsForInputEventIE(topLevelType, target, targetInst) { 75564 if (topLevelType === topLevelTypes.topFocus) { 75565 // In IE8, we can capture almost all .value changes by adding a 75566 // propertychange handler and looking for events with propertyName 75567 // equal to 'value' 75568 // In IE9-11, propertychange fires for most input events but is buggy and 75569 // doesn't fire when text is deleted, but conveniently, selectionchange 75570 // appears to fire in all of the remaining cases so we catch those and 75571 // forward the event if the value has changed 75572 // In either case, we don't want to call the event handler if the value 75573 // is changed from JS so we redefine a setter for `.value` that updates 75574 // our activeElementValue variable, allowing us to ignore those changes 75575 // 75576 // stopWatching() should be a noop here but we call it just in case we 75577 // missed a blur event somehow. 75578 stopWatchingForValueChange(); 75579 startWatchingForValueChange(target, targetInst); 75580 } else if (topLevelType === topLevelTypes.topBlur) { 75581 stopWatchingForValueChange(); 75582 } 75583} 75584 75585// For IE8 and IE9. 75586function getTargetInstForInputEventIE(topLevelType, targetInst) { 75587 if (topLevelType === topLevelTypes.topSelectionChange || topLevelType === topLevelTypes.topKeyUp || topLevelType === topLevelTypes.topKeyDown) { 75588 // On the selectionchange event, the target is just document which isn't 75589 // helpful for us so just check activeElement instead. 75590 // 75591 // 99% of the time, keydown and keyup aren't necessary. IE8 fails to fire 75592 // propertychange on the first input event after setting `value` from a 75593 // script and fires only keydown, keypress, keyup. Catching keyup usually
75594 // gets it and catching keydown lets us fire an event for the first 75595 // keystroke if user does a key repeat (it'll be a little delayed: right 75596 // before the second keystroke). Other input methods (e.g., paste) seem to 75597 // fire selectionchange normally. 75598 if (activeElement && activeElement.value !== activeElementValue) { 75599 activeElementValue = activeElement.value; 75600 return activeElementInst; 75601 } 75602 } 75603} 75604 75605/** 75606 * SECTION: handle `click` event 75607 */ 75608function shouldUseClickEvent(elem) { 75609 // Use the `click` event to detect changes to checkbox and radio inputs. 75610 // This approach works across all browsers, whereas `change` does not fire 75611 // until `blur` in IE8. 75612 return elem.nodeName && elem.nodeName.toLowerCase() === 'input' && (elem.type === 'checkbox' || elem.type === 'radio'); 75613} 75614 75615function getTargetInstForClickEvent(topLevelType, targetInst) { 75616 if (topLevelType === topLevelTypes.topClick) { 75617 return targetInst; 75618 } 75619} 75620 75621/** 75622 * This plugin creates an `onChange` event that normalizes change events 75623 * across form elements. This event fires at a time when it's possible to 75624 * change the element's value without seeing a flicker. 75625 * 75626 * Supported elements are: 75627 * - input (see `isTextInputElement`) 75628 * - textarea 75629 * - select 75630 */ 75631var ChangeEventPlugin = { 75632 75633 eventTypes: eventTypes, 75634 75635 extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) { 75636 var targetNode = targetInst ? ReactDOMComponentTree.getNodeFromInstance(targetInst) : window; 75637 75638 var getTargetInstFunc, handleEventFunc; 75639 if (shouldUseChangeEvent(targetNode)) { 75640 if (doesChangeEventBubble) { 75641 getTargetInstFunc = getTargetInstForChangeEvent; 75642 } else { 75643 handleEventFunc = handleEventsForChangeEventIE8; 75644 } 75645 } else if (isTextInputElement(targetNode)) { 75646 if (isInputEventSupported) { 75647 getTargetInstFunc = getTargetInstForInputEvent; 75648 } else { 75649 getTargetInstFunc = getTargetInstForInputEventIE; 75650 handleEventFunc = handleEventsForInputEventIE; 75651 } 75652 } else if (shouldUseClickEvent(targetNode)) { 75653 getTargetInstFunc = getTargetInstForClickEvent; 75654 } 75655 75656 if (getTargetInstFunc) { 75657 var inst = getTargetInstFunc(topLevelType, targetInst); 75658 if (inst) { 75659 var event = SyntheticEvent.getPooled(eventTypes.change, inst, nativeEvent, nativeEventTarget); 75660 event.type = 'change'; 75661 EventPropagators.accumulateTwoPhaseDispatches(event); 75662 return event; 75663 } 75664 } 75665 75666 if (handleEventFunc) { 75667 handleEventFunc(topLevelType, targetNode, targetInst); 75668 } 75669 } 75670 75671}; 75672 75673module.exports = ChangeEventPlugin; 75674},{"103":103,"126":126,"133":133,"134":134,"144":144,"16":16,"162":162,"17":17,"20":20,"40":40,"94":94}],7:[function(_dereq_,module,exports){ 75675/** 75676 * Copyright 2013-present, Facebook, Inc. 75677 * All rights reserved. 75678 * 75679 * This source code is licensed under the BSD-style license found in the 75680 * LICENSE file in the root directory of this source tree. An additional grant 75681 * of patent rights can be found in the PATENTS file in the same directory. 75682 * 75683 * @providesModule DOMChildrenOperations 75684 */ 75685 75686 75687 75688var DOMLazyTree = _dereq_(8); 75689var Danger = _dereq_(12); 75690var ReactMultiChildUpdateTypes = _dereq_(77); 75691var ReactPerf = _dereq_(82); 75692 75693var createMicrosoftUnsafeLocalFunction = _dereq_(117); 75694var setInnerHTML = _dereq_(138); 75695var setTextContent = _dereq_(139); 75696 75697function getNodeAfter(parentNode, node) { 75698 // Special case for text components, which return [open, close] comments 75699 // from getNativeNode. 75700 if (Array.isArray(node)) { 75701 node = node[1]; 75702 } 75703 return node ? node.nextSibling : parentNode.firstChild; 75704} 75705 75706/** 75707 * Inserts `childNode` as a child of `parentNode` at the `index`. 75708 * 75709 * @param {DOMElement} parentNode Parent node in which to insert. 75710 * @param {DOMElement} childNode Child node to insert. 75711 * @param {number} index Index at which to insert the child. 75712 * @internal 75713 */ 75714var insertChildAt = createMicrosoftUnsafeLocalFunction(function (parentNode, childNode, referenceNode) { 75715 // We rely exclusively on `insertBefore(node, null)` instead of also using 75716 // `appendChild(node)`. (Using `undefined` is not allowed by all browsers so 75717 // we are careful to use `null`.) 75718 parentNode.insertBefore(childNode, referenceNode); 75719}); 75720 75721function insertLazyTreeChildAt(parentNode, childTree, referenceNode) { 75722 DOMLazyTree.insertTreeBefore(parentNode, childTree, referenceNode); 75723} 75724 75725function moveChild(parentNode, childNode, referenceNode) { 75726 if (Array.isArray(childNode)) { 75727 moveDelimitedText(parentNode, childNode[0], childNode[1], referenceNode); 75728 } else { 75729 insertChildAt(parentNode, childNode, referenceNode); 75730 } 75731} 75732 75733function removeChild(parentNode, childNode) { 75734 if (Array.isArray(childNode)) { 75735 var closingComment = childNode[1]; 75736 childNode = childNode[0]; 75737 removeDelimitedText(parentNode, childNode, closingComment); 75738 parentNode.removeChild(closingComment); 75739 } 75740 parentNode.removeChild(childNode); 75741} 75742 75743function moveDelimitedText(parentNode, openingComment, closingComment, referenceNode) { 75744 var node = openingComment; 75745 while (true) { 75746 var nextNode = node.nextSibling; 75747 insertChildAt(parentNode, node, referenceNode); 75748 if (node === closingComment) { 75749 break; 75750 } 75751 node = nextNode; 75752 } 75753} 75754 75755function removeDelimitedText(parentNode, startNode, closingComment) { 75756 while (true) { 75757 var node = startNode.nextSibling; 75758 if (node === closingComment) { 75759 // The closing comment is removed by ReactMultiChild. 75760 break; 75761 } else { 75762 parentNode.removeChild(node); 75763 } 75764 } 75765} 75766 75767function replaceDelimitedText(openingComment, closingComment, stringText) { 75768 var parentNode = openingComment.parentNode;
75769 var nodeAfterComment = openingComment.nextSibling; 75770 if (nodeAfterComment === closingComment) { 75771 // There are no text nodes between the opening and closing comments; insert 75772 // a new one if stringText isn't empty. 75773 if (stringText) { 75774 insertChildAt(parentNode, document.createTextNode(stringText), nodeAfterComment); 75775 } 75776 } else { 75777 if (stringText) { 75778 // Set the text content of the first node after the opening comment, and 75779 // remove all following nodes up until the closing comment. 75780 setTextContent(nodeAfterComment, stringText); 75781 removeDelimitedText(parentNode, nodeAfterComment, closingComment); 75782 } else { 75783 removeDelimitedText(parentNode, openingComment, closingComment); 75784 } 75785 } 75786} 75787 75788/** 75789 * Operations for updating with DOM children. 75790 */ 75791var DOMChildrenOperations = { 75792 75793 dangerouslyReplaceNodeWithMarkup: Danger.dangerouslyReplaceNodeWithMarkup, 75794 75795 replaceDelimitedText: replaceDelimitedText, 75796 75797 /** 75798 * Updates a component's children by processing a series of updates. The 75799 * update configurations are each expected to have a `parentNode` property. 75800 * 75801 * @param {array<object>} updates List of update configurations. 75802 * @internal 75803 */ 75804 processUpdates: function (parentNode, updates) { 75805 for (var k = 0; k < updates.length; k++) { 75806 var update = updates[k]; 75807 switch (update.type) { 75808 case ReactMultiChildUpdateTypes.INSERT_MARKUP: 75809 insertLazyTreeChildAt(parentNode, update.content, getNodeAfter(parentNode, update.afterNode)); 75810 break; 75811 case ReactMultiChildUpdateTypes.MOVE_EXISTING: 75812 moveChild(parentNode, update.fromNode, getNodeAfter(parentNode, update.afterNode)); 75813 break; 75814 case ReactMultiChildUpdateTypes.SET_MARKUP: 75815 setInnerHTML(parentNode, update.content); 75816 break; 75817 case ReactMultiChildUpdateTypes.TEXT_CONTENT: 75818 setTextContent(parentNode, update.content); 75819 break; 75820 case ReactMultiChildUpdateTypes.REMOVE_NODE: 75821 removeChild(parentNode, update.fromNode); 75822 break; 75823 } 75824 } 75825 } 75826 75827}; 75828 75829ReactPerf.measureMethods(DOMChildrenOperations, 'DOMChildrenOperations', { 75830 replaceDelimitedText: 'replaceDelimitedText' 75831}); 75832 75833module.exports = DOMChildrenOperations; 75834},{"117":117,"12":12,"138":138,"139":139,"77":77,"8":8,"82":82}],8:[function(_dereq_,module,exports){ 75835/** 75836 * Copyright 2015-present, Facebook, Inc. 75837 * All rights reserved. 75838 * 75839 * This source code is licensed under the BSD-style license found in the 75840 * LICENSE file in the root directory of this source tree. An additional grant 75841 * of patent rights can be found in the PATENTS file in the same directory. 75842 * 75843 * @providesModule DOMLazyTree 75844 */ 75845 75846 75847 75848var createMicrosoftUnsafeLocalFunction = _dereq_(117); 75849var setTextContent = _dereq_(139); 75850 75851/** 75852 * In IE (8-11) and Edge, appending nodes with no children is dramatically 75853 * faster than appending a full subtree, so we essentially queue up the 75854 * .appendChild calls here and apply them so each node is added to its parent 75855 * before any children are added. 75856 * 75857 * In other browsers, doing so is slower or neutral compared to the other order 75858 * (in Firefox, twice as slow) so we only do this inversion in IE. 75859 * 75860 * See https://github.com/spicyj/innerhtml-vs-createelement-vs-clonenode. 75861 */ 75862var enableLazy = typeof document !== 'undefined' && typeof document.documentMode === 'number' || typeof navigator !== 'undefined' && typeof navigator.userAgent === 'string' && /\bEdge\/\d/.test(navigator.userAgent); 75863 75864function insertTreeChildren(tree) { 75865 if (!enableLazy) { 75866 return; 75867 } 75868 var node = tree.node; 75869 var children = tree.children; 75870 if (children.length) { 75871 for (var i = 0; i < children.length; i++) { 75872 insertTreeBefore(node, children[i], null); 75873 } 75874 } else if (tree.html != null) { 75875 node.innerHTML = tree.html; 75876 } else if (tree.text != null) { 75877 setTextContent(node, tree.text); 75878 } 75879} 75880 75881var insertTreeBefore = createMicrosoftUnsafeLocalFunction(function (parentNode, tree, referenceNode) { 75882 // DocumentFragments aren't actually part of the DOM after insertion so 75883 // appending children won't update the DOM. We need to ensure the fragment 75884 // is properly populated first, breaking out of our lazy approach for just 75885 // this level. 75886 if (tree.node.nodeType === 11) { 75887 insertTreeChildren(tree); 75888 parentNode.insertBefore(tree.node, referenceNode); 75889 } else { 75890 parentNode.insertBefore(tree.node, referenceNode); 75891 insertTreeChildren(tree); 75892 } 75893}); 75894 75895function replaceChildWithTree(oldNode, newTree) { 75896 oldNode.parentNode.replaceChild(newTree.node, oldNode); 75897 insertTreeChildren(newTree); 75898} 75899 75900function queueChild(parentTree, childTree) { 75901 if (enableLazy) { 75902 parentTree.children.push(childTree); 75903 } else { 75904 parentTree.node.appendChild(childTree.node); 75905 } 75906} 75907 75908function queueHTML(tree, html) { 75909 if (enableLazy) { 75910 tree.html = html; 75911 } else { 75912 tree.node.innerHTML = html; 75913 } 75914} 75915 75916function queueText(tree, text) { 75917 if (enableLazy) { 75918 tree.text = text; 75919 } else { 75920 setTextContent(tree.node, text); 75921 } 75922} 75923 75924function DOMLazyTree(node) { 75925 return { 75926 node: node, 75927 children: [], 75928 html: null, 75929 text: null 75930 }; 75931} 75932 75933DOMLazyTree.insertTreeBefore = insertTreeBefore; 75934DOMLazyTree.replaceChildWithTree = replaceChildWithTree; 75935DOMLazyTree.queueChild = queueChild; 75936DOMLazyTree.queueHTML = queueHTML; 75937DOMLazyTree.queueText = queueText; 75938 75939module.exports = DOMLazyTree; 75940},{"117":117,"139":139}],9:[function(_dereq_,module,exports){ 75941/** 75942 * Copyright 2013-present, Facebook, Inc. 75943 * All rights reserved. 75944 * 75945 * This source code is licensed under the BSD-style license found in the 75946 * LICENSE file in the root directory of this source tree. An additional grant 75947 * of patent rights can be found in the PATENTS file in the same directory. 75948 * 75949 * @providesModule DOMNamespaces 75950 */ 75951 75952 75953 75954var DOMNamespaces = { 75955 html: 'http://www.w3.org/1999/xhtml', 75956 mathml: 'http://www.w3.org/1998/Math/MathML', 75957 svg: 'http://www.w3.org/2000/svg' 75958}; 75959 75960module.exports = DOMNamespaces; 75961},{}],10:[function(_dereq_,module,exports){ 75962/** 75963 * Copyright 2013-present, Facebook, Inc. 75964 * All rights reserved. 75965 * 75966 * This source code is licensed under the BSD-style license found in the 75967 * LICENSE file in the root directory of this source tree. An additional grant 75968 * of patent rights can be found in the PATENTS file in the same directory. 75969 * 75970 * @providesModule DOMProperty 75971 */ 75972 75973 75974 75975var invariant = _dereq_(158); 75976 75977function checkMask(value, bitmask) { 75978 return (value & bitmask) === bitmask; 75979} 75980 75981var DOMPropertyInjection = { 75982 /** 75983 * Mapping from normalized, camelcased property names to a configuration that 75984 * specifies how the associated DOM property should be accessed or rendered. 75985 */ 75986 MUST_USE_PROPERTY: 0x1, 75987 HAS_SIDE_EFFECTS: 0x2, 75988 HAS_BOOLEAN_VALUE: 0x4, 75989 HAS_NUMERIC_VALUE: 0x8, 75990 HAS_POSITIVE_NUMERIC_VALUE: 0x10 | 0x8, 75991 HAS_OVERLOADED_BOOLEAN_VALUE: 0x20, 75992 75993 /** 75994 * Inject some specialized knowledge about the DOM. This takes a config object 75995 * with the following properties: 75996 * 75997 * isCustomAttribute: function that given an attribute name will return true 75998 * if it can be inserted into the DOM verbatim. Useful for data-* or aria-* 75999 * attributes where it's impossible to enumerate all of the possible 76000 * attribute names, 76001 * 76002 * Properties: object mapping DOM property name to one of the 76003 * DOMPropertyInjection constants or null. If your attribute isn't in here, 76004 * it won't get written to the DOM. 76005 * 76006 * DOMAttributeNames: object mapping React attribute name to the DOM 76007 * attribute name. Attribute names not specified use the **lowercase** 76008 * normalized name. 76009 * 76010 * DOMAttributeNamespaces: object mapping React attribute name to the DOM 76011 * attribute namespace URL. (Attribute names not specified use no namespace.) 76012 * 76013 * DOMPropertyNames: similar to DOMAttributeNames but for DOM properties. 76014 * Property names not specified use the normalized name. 76015 * 76016 * DOMMutationMethods: Properties that require special mutation methods. If 76017 * `value` is undefined, the mutation method should unset the property. 76018 * 76019 * @param {object} domPropertyConfig the config as described above. 76020 */ 76021 injectDOMPropertyConfig: function (domPropertyConfig) { 76022 var Injection = DOMPropertyInjection; 76023 var Properties = domPropertyConfig.Properties || {}; 76024 var DOMAttributeNamespaces = domPropertyConfig.DOMAttributeNamespaces || {}; 76025 var DOMAttributeNames = domPropertyConfig.DOMAttributeNames || {}; 76026 var DOMPropertyNames = domPropertyConfig.DOMPropertyNames || {}; 76027 var DOMMutationMethods = domPropertyConfig.DOMMutationMethods || {}; 76028 76029 if (domPropertyConfig.isCustomAttribute) { 76030 DOMProperty._isCustomAttributeFunctions.push(domPropertyConfig.isCustomAttribute); 76031 } 76032 76033 for (var propName in Properties) { 76034 !!DOMProperty.properties.hasOwnProperty(propName) ? "development" !== 'production' ? invariant(false, 'injectDOMPropertyConfig(...): You\'re trying to inject DOM property ' + '\'%s\' which has already been injected. You may be accidentally ' + 'injecting the same DOM property config twice, or you may be ' + 'injecting two configs that have conflicting property names.', propName) : invariant(false) : void 0; 76035 76036 var lowerCased = propName.toLowerCase(); 76037 var propConfig = Properties[propName]; 76038 76039 var propertyInfo = { 76040 attributeName: lowerCased, 76041 attributeNamespace: null, 76042 propertyName: propName, 76043 mutationMethod: null, 76044 76045 mustUseProperty: checkMask(propConfig, Injection.MUST_USE_PROPERTY), 76046 hasSideEffects: checkMask(propConfig, Injection.HAS_SIDE_EFFECTS), 76047 hasBooleanValue: checkMask(propConfig, Injection.HAS_BOOLEAN_VALUE), 76048 hasNumericValue: checkMask(propConfig, Injection.HAS_NUMERIC_VALUE), 76049 hasPositiveNumericValue: checkMask(propConfig, Injection.HAS_POSITIVE_NUMERIC_VALUE), 76050 hasOverloadedBooleanValue: checkMask(propConfig, Injection.HAS_OVERLOADED_BOOLEAN_VALUE) 76051 }; 76052 76053 !(propertyInfo.mustUseProperty || !propertyInfo.hasSideEffects) ? "development" !== 'production' ? invariant(false, 'DOMProperty: Properties that have side effects must use property: %s', propName) : invariant(false) : void 0; 76054 !(propertyInfo.hasBooleanValue + propertyInfo.hasNumericValue + propertyInfo.hasOverloadedBooleanValue <= 1) ? "development" !== 'production' ? invariant(false, 'DOMProperty: Value can be one of boolean, overloaded boolean, or ' + 'numeric value, but not a combination: %s', propName) : invariant(false) : void 0; 76055 76056 if ("development" !== 'production') { 76057 DOMProperty.getPossibleStandardName[lowerCased] = propName; 76058 } 76059 76060 if (DOMAttributeNames.hasOwnProperty(propName)) { 76061 var attributeName = DOMAttributeNames[propName]; 76062 propertyInfo.attributeName = attributeName; 76063 if ("development" !== 'production') { 76064 DOMProperty.getPossibleStandardName[attributeName] = propName; 76065 } 76066 } 76067 76068 if (DOMAttributeNamespaces.hasOwnProperty(propName)) { 76069 propertyInfo.attributeNamespace = DOMAttributeNamespaces[propName]; 76070 } 76071 76072 if (DOMPropertyNames.hasOwnProperty(propName)) { 76073 propertyInfo.propertyName = DOMPropertyNames[propName]; 76074 } 76075 76076 if (DOMMutationMethods.hasOwnProperty(propName)) { 76077 propertyInfo.mutationMethod = DOMMutationMethods[propName]; 76078 } 76079 76080 DOMProperty.properties[propName] = propertyInfo; 76081 } 76082 } 76083}; 76084 76085/* eslint-disable max-len */ 76086var ATTRIBUTE_NAME_START_CHAR = ':A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u
76086037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD'; 76087/* eslint-enable max-len */ 76088 76089/** 76090 * DOMProperty exports lookup objects that can be used like functions: 76091 * 76092 * > DOMProperty.isValid['id'] 76093 * true 76094 * > DOMProperty.isValid['foobar'] 76095 * undefined 76096 * 76097 * Although this may be confusing, it performs better in general. 76098 * 76099 * @see http://jsperf.com/key-exists 76100 * @see http://jsperf.com/key-missing 76101 */ 76102var DOMProperty = { 76103 76104 ID_ATTRIBUTE_NAME: 'data-reactid', 76105 ROOT_ATTRIBUTE_NAME: 'data-reactroot', 76106 76107 ATTRIBUTE_NAME_START_CHAR: ATTRIBUTE_NAME_START_CHAR, 76108 ATTRIBUTE_NAME_CHAR: ATTRIBUTE_NAME_START_CHAR + '\\-.0-9\\uB7\\u0300-\\u036F\\u203F-\\u2040', 76109 76110 /** 76111 * Map from property "standard name" to an object with info about how to set 76112 * the property in the DOM. Each object contains: 76113 * 76114 * attributeName: 76115 * Used when rendering markup or with `*Attribute()`. 76116 * attributeNamespace 76117 * propertyName: 76118 * Used on DOM node instances. (This includes properties that mutate due to 76119 * external factors.) 76120 * mutationMethod: 76121 * If non-null, used instead of the property or `setAttribute()` after 76122 * initial render. 76123 * mustUseProperty: 76124 * Whether the property must be accessed and mutated as an object property. 76125 * hasSideEffects: 76126 * Whether or not setting a value causes side effects such as triggering 76127 * resources to be loaded or text selection changes. If true, we read from 76128 * the DOM before updating to ensure that the value is only set if it has 76129 * changed. 76130 * hasBooleanValue: 76131 * Whether the property should be removed when set to a falsey value. 76132 * hasNumericValue: 76133 * Whether the property must be numeric or parse as a numeric and should be 76134 * removed when set to a falsey value. 76135 * hasPositiveNumericValue: 76136 * Whether the property must be positive numeric or parse as a positive 76137 * numeric and should be removed when set to a falsey value. 76138 * hasOverloadedBooleanValue: 76139 * Whether the property can be used as a flag as well as with a value. 76140 * Removed when strictly equal to false; present without a value when 76141 * strictly equal to true; present with a value otherwise. 76142 */ 76143 properties: {}, 76144 76145 /** 76146 * Mapping from lowercase property names to the properly cased version, used 76147 * to warn in the case of missing properties. Available only in __DEV__. 76148 * @type {Object} 76149 */ 76150 getPossibleStandardName: "development" !== 'production' ? {} : null, 76151 76152 /** 76153 * All of the isCustomAttribute() functions that have been injected. 76154 */ 76155 _isCustomAttributeFunctions: [], 76156 76157 /** 76158 * Checks whether a property name is a custom attribute. 76159 * @method 76160 */ 76161 isCustomAttribute: function (attributeName) { 76162 for (var i = 0; i < DOMProperty._isCustomAttributeFunctions.length; i++) { 76163 var isCustomAttributeFn = DOMProperty._isCustomAttributeFunctions[i]; 76164 if (isCustomAttributeFn(attributeName)) { 76165 return true; 76166 } 76167 } 76168 return false; 76169 }, 76170 76171 injection: DOMPropertyInjection 76172}; 76173 76174module.exports = DOMProperty; 76175},{"158":158}],11:[function(_dereq_,module,exports){ 76176/** 76177 * Copyright 2013-present, Facebook, Inc. 76178 * All rights reserved. 76179 * 76180 * This source code is licensed under the BSD-style license found in the 76181 * LICENSE file in the root directory of this source tree. An additional grant 76182 * of patent rights can be found in the PATENTS file in the same directory. 76183 * 76184 * @providesModule DOMPropertyOperations 76185 */ 76186 76187 76188 76189var DOMProperty = _dereq_(10); 76190var ReactDOMInstrumentation = _dereq_(48); 76191var ReactPerf = _dereq_(82); 76192 76193var quoteAttributeValueForBrowser = _dereq_(136); 76194var warning = _dereq_(168); 76195 76196var VALID_ATTRIBUTE_NAME_REGEX = new RegExp('^[' + DOMProperty.ATTRIBUTE_NAME_START_CHAR + '][' + DOMProperty.ATTRIBUTE_NAME_CHAR + ']*$'); 76197var illegalAttributeNameCache = {}; 76198var validatedAttributeNameCache = {}; 76199 76200function isAttributeNameSafe(attributeName) { 76201 if (validatedAttributeNameCache.hasOwnProperty(attributeName)) { 76202 return true; 76203 } 76204 if (illegalAttributeNameCache.hasOwnProperty(attributeName)) { 76205 return false;
76206 } 76207 if (VALID_ATTRIBUTE_NAME_REGEX.test(attributeName)) { 76208 validatedAttributeNameCache[attributeName] = true; 76209 return true; 76210 } 76211 illegalAttributeNameCache[attributeName] = true; 76212 "development" !== 'production' ? warning(false, 'Invalid attribute name: `%s`', attributeName) : void 0; 76213 return false; 76214} 76215 76216function shouldIgnoreValue(propertyInfo, value) { 76217 return value == null || propertyInfo.hasBooleanValue && !value || propertyInfo.hasNumericValue && isNaN(value) || propertyInfo.hasPositiveNumericValue && value < 1 || propertyInfo.hasOverloadedBooleanValue && value === false; 76218} 76219 76220/** 76221 * Operations for dealing with DOM properties. 76222 */ 76223var DOMPropertyOperations = { 76224 76225 /** 76226 * Creates markup for the ID property. 76227 * 76228 * @param {string} id Unescaped ID. 76229 * @return {string} Markup string. 76230 */ 76231 createMarkupForID: function (id) { 76232 return DOMProperty.ID_ATTRIBUTE_NAME + '=' + quoteAttributeValueForBrowser(id); 76233 }, 76234 76235 setAttributeForID: function (node, id) { 76236 node.setAttribute(DOMProperty.ID_ATTRIBUTE_NAME, id); 76237 }, 76238 76239 createMarkupForRoot: function () { 76240 return DOMProperty.ROOT_ATTRIBUTE_NAME + '=""'; 76241 }, 76242 76243 setAttributeForRoot: function (node) { 76244 node.setAttribute(DOMProperty.ROOT_ATTRIBUTE_NAME, ''); 76245 }, 76246 76247 /** 76248 * Creates markup for a property. 76249 * 76250 * @param {string} name 76251 * @param {*} value 76252 * @return {?string} Markup string, or null if the property was invalid. 76253 */ 76254 createMarkupForProperty: function (name, value) { 76255 if ("development" !== 'production') { 76256 ReactDOMInstrumentation.debugTool.onCreateMarkupForProperty(name, value); 76257 } 76258 var propertyInfo = DOMProperty.properties.hasOwnProperty(name) ? DOMProperty.properties[name] : null; 76259 if (propertyInfo) { 76260 if (shouldIgnoreValue(propertyInfo, value)) { 76261 return ''; 76262 } 76263 var attributeName = propertyInfo.attributeName; 76264 if (propertyInfo.hasBooleanValue || propertyInfo.hasOverloadedBooleanValue && value === true) { 76265 return attributeName + '=""'; 76266 } 76267 return attributeName + '=' + quoteAttributeValueForBrowser(value); 76268 } else if (DOMProperty.isCustomAttribute(name)) { 76269 if (value == null) { 76270 return ''; 76271 } 76272 return name + '=' + quoteAttributeValueForBrowser(value); 76273 } 76274 return null; 76275 }, 76276 76277 /** 76278 * Creates markup for a custom property. 76279 * 76280 * @param {string} name 76281 * @param {*} value 76282 * @return {string} Markup string, or empty string if the property was invalid. 76283 */ 76284 createMarkupForCustomAttribute: function (name, value) { 76285 if (!isAttributeNameSafe(name) || value == null) { 76286 return ''; 76287 } 76288 return name + '=' + quoteAttributeValueForBrowser(value); 76289 }, 76290 76291 /** 76292 * Sets the value for a property on a node. 76293 * 76294 * @param {DOMElement} node 76295 * @param {string} name 76296 * @param {*} value 76297 */ 76298 setValueForProperty: function (node, name, value) { 76299 if ("development" !== 'production') { 76300 ReactDOMInstrumentation.debugTool.onSetValueForProperty(node, name, value); 76301 } 76302 var propertyInfo = DOMProperty.properties.hasOwnProperty(name) ? DOMProperty.properties[name] : null; 76303 if (propertyInfo) { 76304 var mutationMethod = propertyInfo.mutationMethod; 76305 if (mutationMethod) { 76306 mutationMethod(node, value); 76307 } else if (shouldIgnoreValue(propertyInfo, value)) { 76308 this.deleteValueForProperty(node, name); 76309 } else if (propertyInfo.mustUseProperty) { 76310 var propName = propertyInfo.propertyName; 76311 // Must explicitly cast values for HAS_SIDE_EFFECTS-properties to the 76312 // property type before comparing; only `value` does and is string. 76313 if (!propertyInfo.hasSideEffects || '' + node[propName] !== '' + value) { 76314 // Contrary to `setAttribute`, object properties are properly 76315 // `toString`ed by IE8/9. 76316 node[propName] = value; 76317 } 76318 } else { 76319 var attributeName = propertyInfo.attributeName; 76320 var namespace = propertyInfo.attributeNamespace; 76321 // `setAttribute` with objects becomes only `[object]` in IE8/9, 76322 // ('' + value) makes it output the correct toString()-value. 76323 if (namespace) { 76324 node.setAttributeNS(namespace, attributeName, '' + value); 76325 } else if (propertyInfo.hasBooleanValue || propertyInfo.hasOverloadedBooleanValue && value === true) { 76326 node.setAttribute(attributeName, ''); 76327 } else { 76328 node.setAttribute(attributeName, '' + value); 76329 } 76330 } 76331 } else if (DOMProperty.isCustomAttribute(name)) { 76332 DOMPropertyOperations.setValueForAttribute(node, name, value); 76333 } 76334 }, 76335 76336 setValueForAttribute: function (node, name, value) { 76337 if (!isAttributeNameSafe(name)) { 76338 return; 76339 } 76340 if (value == null) { 76341 node.removeAttribute(name); 76342 } else { 76343 node.setAttribute(name, '' + value); 76344 } 76345 }, 76346 76347 /** 76348 * Deletes the value for a property on a node. 76349 * 76350 * @param {DOMElement} node 76351 * @param {string} name 76352 */ 76353 deleteValueForProperty: function (node, name) { 76354 if ("development" !== 'production') { 76355 ReactDOMInstrumentation.debugTool.onDeleteValueForProperty(node, name); 76356 } 76357 var propertyInfo = DOMProperty.properties.hasOwnProperty(name) ? DOMProperty.properties[name] : null; 76358 if (propertyInfo) { 76359 var mutationMethod = propertyInfo.mutationMethod; 76360 if (mutationMethod) { 76361 mutationMethod(node, undefined); 76362 } else if (propertyInfo.mustUseProperty) { 76363 var propName = propertyInfo.propertyName; 76364 if (propertyInfo.hasBooleanValue) { 76365 // No HAS_SIDE_EFFECTS logic here, only `value` has it and is string. 76366 node[propName] = false;
76367 } else { 76368 if (!propertyInfo.hasSideEffects || '' + node[propName] !== '') { 76369 node[propName] = ''; 76370 } 76371 } 76372 } else { 76373 node.removeAttribute(propertyInfo.attributeName); 76374 } 76375 } else if (DOMProperty.isCustomAttribute(name)) { 76376 node.removeAttribute(name); 76377 } 76378 } 76379 76380}; 76381 76382ReactPerf.measureMethods(DOMPropertyOperations, 'DOMPropertyOperations', { 76383 setValueForProperty: 'setValueForProperty', 76384 setValueForAttribute: 'setValueForAttribute', 76385 deleteValueForProperty: 'deleteValueForProperty' 76386}); 76387 76388module.exports = DOMPropertyOperations; 76389},{"10":10,"136":136,"168":168,"48":48,"82":82}],12:[function(_dereq_,module,exports){ 76390/** 76391 * Copyright 2013-present, Facebook, Inc. 76392 * All rights reserved. 76393 * 76394 * This source code is licensed under the BSD-style license found in the 76395 * LICENSE file in the root directory of this source tree. An additional grant 76396 * of patent rights can be found in the PATENTS file in the same directory. 76397 * 76398 * @providesModule Danger 76399 */ 76400 76401 76402 76403var DOMLazyTree = _dereq_(8); 76404var ExecutionEnvironment = _dereq_(144); 76405 76406var createNodesFromMarkup = _dereq_(149); 76407var emptyFunction = _dereq_(150); 76408var getMarkupWrap = _dereq_(154); 76409var invariant = _dereq_(158); 76410 76411var OPEN_TAG_NAME_EXP = /^(<[^ \/>]+)/; 76412var RESULT_INDEX_ATTR = 'data-danger-index'; 76413 76414/** 76415 * Extracts the `nodeName` from a string of markup. 76416 * 76417 * NOTE: Extracting the `nodeName` does not require a regular expression match 76418 * because we make assumptions about React-generated markup (i.e. there are no 76419 * spaces surrounding the opening tag and there is at least one attribute). 76420 * 76421 * @param {string} markup String of markup. 76422 * @return {string} Node name of the supplied markup. 76423 * @see http://jsperf.com/extract-nodename 76424 */ 76425function getNodeName(markup) { 76426 return markup.substring(1, markup.indexOf(' ')); 76427} 76428 76429var Danger = { 76430 76431 /** 76432 * Renders markup into an array of nodes. The markup is expected to render 76433 * into a list of root nodes. Also, the length of `resultList` and 76434 * `markupList` should be the same. 76435 * 76436 * @param {array<string>} markupList List of markup strings to render. 76437 * @return {array<DOMElement>} List of rendered nodes. 76438 * @internal 76439 */ 76440 dangerouslyRenderMarkup: function (markupList) { 76441 !ExecutionEnvironment.canUseDOM ? "development" !== 'production' ? invariant(false, 'dangerouslyRenderMarkup(...): Cannot render markup in a worker ' + 'thread. Make sure `window` and `document` are available globally ' + 'before requiring React when unit testing or use ' + 'ReactDOMServer.renderToString for server rendering.') : invariant(false) : void 0; 76442 var nodeName; 76443 var markupByNodeName = {}; 76444 // Group markup by `nodeName` if a wrap is necessary, else by '*'. 76445 for (var i = 0; i < markupList.length; i++) { 76446 !markupList[i] ? "development" !== 'production' ? invariant(false, 'dangerouslyRenderMarkup(...): Missing markup.') : invariant(false) : void 0; 76447 nodeName = getNodeName(markupList[i]); 76448 nodeName = getMarkupWrap(nodeName) ? nodeName : '*'; 76449 markupByNodeName[nodeName] = markupByNodeName[nodeName] || []; 76450 markupByNodeName[nodeName][i] = markupList[i]; 76451 } 76452 var resultList = []; 76453 var resultListAssignmentCount = 0; 76454 for (nodeName in markupByNodeName) { 76455 if (!markupByNodeName.hasOwnProperty(nodeName)) { 76456 continue; 76457 } 76458 var markupListByNodeName = markupByNodeName[nodeName]; 76459 76460 // This for-in loop skips the holes of the sparse array. The order of 76461 // iteration should follow the order of assignment, which happens to match 76462 // numerical index order, but we don't rely on that. 76463 var resultIndex; 76464 for (resultIndex in markupListByNodeName) { 76465 if (markupListByNodeName.hasOwnProperty(resultIndex)) { 76466 var markup = markupListByNodeName[resultIndex]; 76467 76468 // Push the requested markup with an additional RESULT_INDEX_ATTR 76469 // attribute. If the markup does not start with a < character, it 76470 // will be discarded below (with an appropriate console.error). 76471 markupListByNodeName[resultIndex] = markup.replace(OPEN_TAG_NAME_EXP, 76472 // This index will be parsed back out below. 76473 '$1 ' + RESULT_INDEX_ATTR + '="' + resultIndex + '" '); 76474 } 76475 } 76476
76477 // Render each group of markup with similar wrapping `nodeName`. 76478 var renderNodes = createNodesFromMarkup(markupListByNodeName.join(''), emptyFunction // Do nothing special with <script> tags. 76479 ); 76480 76481 for (var j = 0; j < renderNodes.length; ++j) { 76482 var renderNode = renderNodes[j]; 76483 if (renderNode.hasAttribute && renderNode.hasAttribute(RESULT_INDEX_ATTR)) { 76484 76485 resultIndex = +renderNode.getAttribute(RESULT_INDEX_ATTR); 76486 renderNode.removeAttribute(RESULT_INDEX_ATTR); 76487 76488 !!resultList.hasOwnProperty(resultIndex) ? "development" !== 'production' ? invariant(false, 'Danger: Assigning to an already-occupied result index.') : invariant(false) : void 0; 76489 76490 resultList[resultIndex] = renderNode; 76491 76492 // This should match resultList.length and markupList.length when 76493 // we're done. 76494 resultListAssignmentCount += 1; 76495 } else if ("development" !== 'production') { 76496 console.error('Danger: Discarding unexpected node:', renderNode); 76497 } 76498 } 76499 } 76500 76501 // Although resultList was populated out of order, it should now be a dense 76502 // array. 76503 !(resultListAssignmentCount === resultList.length) ? "development" !== 'production' ? invariant(false, 'Danger: Did not assign to every index of resultList.') : invariant(false) : void 0; 76504 76505 !(resultList.length === markupList.length) ? "development" !== 'production' ? invariant(false, 'Danger: Expected markup to render %s nodes, but rendered %s.', markupList.length, resultList.length) : invariant(false) : void 0; 76506 76507 return resultList; 76508 }, 76509 76510 /** 76511 * Replaces a node with a string of markup at its current position within its 76512 * parent. The markup must render into a single root node. 76513 * 76514 * @param {DOMElement} oldChild Child node to replace. 76515 * @param {string} markup Markup to render in place of the child node. 76516 * @internal 76517 */ 76518 dangerouslyReplaceNodeWithMarkup: function (oldChild, markup) { 76519 !ExecutionEnvironment.canUseDOM ? "development" !== 'production' ? invariant(false, 'dangerouslyReplaceNodeWithMarkup(...): Cannot render markup in a ' + 'worker thread. Make sure `window` and `document` are available ' + 'globally before requiring React when unit testing or use ' + 'ReactDOMServer.renderToString() for server rendering.') : invariant(false) : void 0; 76520 !markup ? "development" !== 'production' ? invariant(false, 'dangerouslyReplaceNodeWithMarkup(...): Missing markup.') : invariant(false) : void 0; 76521 !(oldChild.nodeName !== 'HTML') ? "development" !== 'production' ? invariant(false, 'dangerouslyReplaceNodeWithMarkup(...): Cannot replace markup of the ' + '<html> node. This is because browser quirks make this unreliable ' + 'and/or slow. If you want to render to the root you must use ' + 'server rendering. See ReactDOMServer.renderToString().') : invariant(false) : void 0; 76522 76523 if (typeof markup === 'string') { 76524 var newChild = createNodesFromMarkup(markup, emptyFunction)[0]; 76525 oldChild.parentNode.replaceChild(newChild, oldChild); 76526 } else { 76527 DOMLazyTree.replaceChildWithTree(oldChild, markup); 76528 } 76529 } 76530 76531}; 76532 76533module.exports = Danger; 76534},{"144":144,"149":149,"150":150,"154":154,"158":158,"8":8}],13:[function(_dereq_,module,exports){ 76535/** 76536 * Copyright 2013-present, Facebook, Inc. 76537 * All rights reserved. 76538 * 76539 * This source code is licensed under the BSD-style license found in the 76540 * LICENSE file in the root directory of this source tree. An additional grant 76541 * of patent rights can be found in the PATENTS file in the same directory. 76542 * 76543 * @providesModule DefaultEventPluginOrder 76544 */ 76545 76546 76547 76548var keyOf = _dereq_(162); 76549 76550/** 76551 * Module that is injectable into `EventPluginHub`, that specifies a 76552 * deterministic ordering of `EventPlugin`s. A convenient way to reason about 76553 * plugins, without having to package every one of them. This is better than 76554 * having plugins be ordered in the same order that they are injected because 76555 * that ordering would be influenced by the packaging order. 76556 * `ResponderEventPlugin` must occur before `SimpleEventPlugin` so that 76557 * preventing default on events is convenient in `SimpleEventPlugin` handlers. 76558 */ 76559var DefaultEventPluginOrder = [keyOf({ ResponderEventPlugin: null }), keyOf({ SimpleEventPlugin: null }), keyOf({ TapEventPlugin: null }), keyOf({ EnterLeaveEventPlugin: null }), keyOf({ ChangeEventPlugin: null }), keyOf({ SelectEventPlugin: null }), keyOf({ BeforeInputEventPlugin: null })]; 76560 76561module.exports = DefaultEventPluginOrder; 76562},{"162":162}],14:[function(_dereq_,module,exports){ 76563/** 76564 * Copyright 2013-present, Facebook, Inc. 76565 * All rights reserved. 76566 * 76567 * This source code is licensed under the BSD-style license found in the 76568 * LICENSE file in the root directory of this source tree. An additional grant 76569 * of patent rights can be found in the PATENTS file in the same directory. 76570 * 76571 * @providesModule DisabledInputUtils 76572 */ 76573 76574 76575 76576var disableableMouseListenerNames = { 76577 onClick: true, 76578 onDoubleClick: true, 76579 onMouseDown: true, 76580 onMouseMove: true, 76581 onMouseUp: true, 76582 76583 onClickCapture: true, 76584 onDoubleClickCapture: true, 76585 onMouseDownCapture: true, 76586 onMouseMoveCapture: true, 76587 onMouseUpCapture: true 76588}; 76589 76590/** 76591 * Implements a native component that does not receive mouse events 76592 * when `disabled` is set. 76593 */ 76594var DisabledInputUtils = { 76595 getNativeProps: function (inst, props) { 76596 if (!props.disabled) { 76597 return props; 76598 } 76599 76600 // Copy the props, except the mouse listeners 76601 var nativeProps = {}; 76602 for (var key in props) { 76603 if (!disableableMouseListenerNames[key] && props.hasOwnProperty(key)) { 76604 nativeProps[key] = props[key]; 76605 } 76606 } 76607 76608 return nativeProps; 76609 } 76610}; 76611 76612module.exports = DisabledInputUtils; 76613},{}],15:[function(_dereq_,module,exports){ 76614/** 76615 * Copyright 2013-present, Facebook, Inc. 76616 * All rights reserved. 76617 * 76618 * This source code is licensed under the BSD-style license found in the 76619 * LICENSE file in the root directory of this source tree. An additional grant 76620 * of patent rights can be found in the PATENTS file in the same directory. 76621 * 76622 * @providesModule EnterLeaveEventPlugin 76623 */ 76624 76625 76626 76627var EventConstants = _dereq_(16); 76628var EventPropagators = _dereq_(20); 76629var ReactDOMComponentTree = _dereq_(40); 76630var SyntheticMouseEvent = _dereq_(107); 76631 76632var keyOf = _dereq_(162); 76633
76634var topLevelTypes = EventConstants.topLevelTypes; 76635 76636var eventTypes = { 76637 mouseEnter: { 76638 registrationName: keyOf({ onMouseEnter: null }), 76639 dependencies: [topLevelTypes.topMouseOut, topLevelTypes.topMouseOver] 76640 }, 76641 mouseLeave: { 76642 registrationName: keyOf({ onMouseLeave: null }), 76643 dependencies: [topLevelTypes.topMouseOut, topLevelTypes.topMouseOver] 76644 } 76645}; 76646 76647var EnterLeaveEventPlugin = { 76648 76649 eventTypes: eventTypes, 76650 76651 /** 76652 * For almost every interaction we care about, there will be both a top-level 76653 * `mouseover` and `mouseout` event that occurs. Only use `mouseout` so that 76654 * we do not extract duplicate events. However, moving the mouse into the 76655 * browser from outside will not fire a `mouseout` event. In this case, we use 76656 * the `mouseover` top-level event. 76657 */ 76658 extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) { 76659 if (topLevelType === topLevelTypes.topMouseOver && (nativeEvent.relatedTarget || nativeEvent.fromElement)) { 76660 return null; 76661 } 76662 if (topLevelType !== topLevelTypes.topMouseOut && topLevelType !== topLevelTypes.topMouseOver) { 76663 // Must not be a mouse in or mouse out - ignoring. 76664 return null; 76665 } 76666 76667 var win; 76668 if (nativeEventTarget.window === nativeEventTarget) { 76669 // `nativeEventTarget` is probably a window object. 76670 win = nativeEventTarget; 76671 } else { 76672 // TODO: Figure out why `ownerDocument` is sometimes undefined in IE8. 76673 var doc = nativeEventTarget.ownerDocument; 76674 if (doc) { 76675 win = doc.defaultView || doc.parentWindow; 76676 } else { 76677 win = window; 76678 } 76679 } 76680 76681 var from; 76682 var to; 76683 if (topLevelType === topLevelTypes.topMouseOut) { 76684 from = targetInst; 76685 var related = nativeEvent.relatedTarget || nativeEvent.toElement; 76686 to = related ? ReactDOMComponentTree.getClosestInstanceFromNode(related) : null; 76687 } else { 76688 // Moving to a node from outside the window. 76689 from = null; 76690 to = targetInst; 76691 } 76692 76693 if (from === to) { 76694 // Nothing pertains to our managed components. 76695 return null; 76696 } 76697 76698 var fromNode = from == null ? win : ReactDOMComponentTree.getNodeFromInstance(from); 76699 var toNode = to == null ? win : ReactDOMComponentTree.getNodeFromInstance(to); 76700 76701 var leave = SyntheticMouseEvent.getPooled(eventTypes.mouseLeave, from, nativeEvent, nativeEventTarget); 76702 leave.type = 'mouseleave'; 76703 leave.target = fromNode; 76704 leave.relatedTarget = toNode; 76705 76706 var enter = SyntheticMouseEvent.getPooled(eventTypes.mouseEnter, to, nativeEvent, nativeEventTarget); 76707 enter.type = 'mouseenter'; 76708 enter.target = toNode; 76709 enter.relatedTarget = fromNode; 76710 76711 EventPropagators.accumulateEnterLeaveDispatches(leave, enter, from, to); 76712 76713 return [leave, enter]; 76714 } 76715 76716}; 76717 76718module.exports = EnterLeaveEventPlugin; 76719},{"107":107,"16":16,"162":162,"20":20,"40":40}],16:[function(_dereq_,module,exports){ 76720/** 76721 * Copyright 2013-present, Facebook, Inc. 76722 * All rights reserved. 76723 * 76724 * This source code is licensed under the BSD-style license found in the 76725 * LICENSE file in the root directory of this source tree. An additional grant 76726 * of patent rights can be found in the PATENTS file in the same directory. 76727 * 76728 * @providesModule EventConstants 76729 */ 76730 76731 76732 76733var keyMirror = _dereq_(161); 76734 76735var PropagationPhases = keyMirror({ bubbled: null, captured: null }); 76736 76737/** 76738 * Types of raw signals from the browser caught at the top level. 76739 */ 76740var topLevelTypes = keyMirror({ 76741 topAbort: null, 76742 topAnimationEnd: null, 76743 topAnimationIteration: null, 76744 topAnimationStart: null, 76745 topBlur: null, 76746 topCanPlay: null, 76747 topCanPlayThrough: null, 76748 topChange: null, 76749 topClick: null, 76750 topCompositionEnd: null, 76751 topCompositionStart: null, 76752 topCompositionUpdate: null, 76753 topContextMenu: null, 76754 topCopy: null, 76755 topCut: null, 76756 topDoubleClick: null, 76757 topDrag: null, 76758 topDragEnd: null, 76759 topDragEnter: null, 76760 topDragExit: null, 76761 topDragLeave: null, 76762 topDragOver: null, 76763 topDragStart: null, 76764 topDrop: null, 76765 topDurationChange: null, 76766 topEmptied: null, 76767 topEncrypted: null, 76768 topEnded: null, 76769 topError: null, 76770 topFocus: null, 76771 topInput: null, 76772 topInvalid: null, 76773 topKeyDown: null, 76774 topKeyPress: null, 76775 topKeyUp: null, 76776 topLoad: null, 76777 topLoadedData: null, 76778 topLoadedMetadata: null, 76779 topLoadStart: null, 76780 topMouseDown: null, 76781 topMouseMove: null, 76782 topMouseOut: null, 76783 topMouseOver: null, 76784 topMouseUp: null, 76785 topPaste: null, 76786 topPause: null, 76787 topPlay: null, 76788 topPlaying: null, 76789 topProgress: null, 76790 topRateChange: null, 76791 topReset: null, 76792 topScroll: null, 76793 topSeeked: null, 76794 topSeeking: null, 76795 topSelectionChange: null, 76796 topStalled: null, 76797 topSubmit: null, 76798 topSuspend: null, 76799 topTextInput: null, 76800 topTimeUpdate: null, 76801 topTouchCancel: null, 76802 topTouchEnd: null, 76803 topTouchMove: null, 76804 topTouchStart: null, 76805 topTransitionEnd: null, 76806 topVolumeChange: null, 76807 topWaiting: null, 76808 topWheel: null 76809}); 76810 76811var EventConstants = { 76812 topLevelTypes: topLevelTypes, 76813 PropagationPhases: PropagationPhases 76814}; 76815
76816module.exports = EventConstants; 76817},{"161":161}],17:[function(_dereq_,module,exports){ 76818/** 76819 * Copyright 2013-present, Facebook, Inc. 76820 * All rights reserved. 76821 * 76822 * This source code is licensed under the BSD-style license found in the 76823 * LICENSE file in the root directory of this source tree. An additional grant 76824 * of patent rights can be found in the PATENTS file in the same directory. 76825 * 76826 * @providesModule EventPluginHub 76827 */ 76828 76829 76830 76831var EventPluginRegistry = _dereq_(18); 76832var EventPluginUtils = _dereq_(19); 76833var ReactErrorUtils = _dereq_(65); 76834 76835var accumulateInto = _dereq_(114); 76836var forEachAccumulated = _dereq_(122); 76837var invariant = _dereq_(158); 76838 76839/** 76840 * Internal store for event listeners 76841 */ 76842var listenerBank = {}; 76843 76844/** 76845 * Internal queue of events that have accumulated their dispatches and are 76846 * waiting to have their dispatches executed. 76847 */ 76848var eventQueue = null; 76849 76850/** 76851 * Dispatches an event and releases it back into the pool, unless persistent. 76852 * 76853 * @param {?object} event Synthetic event to be dispatched. 76854 * @param {boolean} simulated If the event is simulated (changes exn behavior) 76855 * @private 76856 */ 76857var executeDispatchesAndRelease = function (event, simulated) { 76858 if (event) { 76859 EventPluginUtils.executeDispatchesInOrder(event, simulated); 76860 76861 if (!event.isPersistent()) { 76862 event.constructor.release(event); 76863 } 76864 } 76865}; 76866var executeDispatchesAndReleaseSimulated = function (e) { 76867 return executeDispatchesAndRelease(e, true); 76868}; 76869var executeDispatchesAndReleaseTopLevel = function (e) { 76870 return executeDispatchesAndRelease(e, false); 76871}; 76872 76873/** 76874 * This is a unified interface for event plugins to be installed and configured. 76875 * 76876 * Event plugins can implement the following properties: 76877 * 76878 * `extractEvents` {function(string, DOMEventTarget, string, object): *} 76879 * Required. When a top-level event is fired, this method is expected to 76880 * extract synthetic events that will in turn be queued and dispatched. 76881 * 76882 * `eventTypes` {object} 76883 * Optional, plugins that fire events must publish a mapping of registration 76884 * names that are used to register listeners. Values of this mapping must 76885 * be objects that contain `registrationName` or `phasedRegistrationNames`. 76886 * 76887 * `executeDispatch` {function(object, function, string)} 76888 * Optional, allows plugins to override how an event gets dispatched. By 76889 * default, the listener is simply invoked. 76890 * 76891 * Each plugin that is injected into `EventsPluginHub` is immediately operable. 76892 * 76893 * @public 76894 */ 76895var EventPluginHub = { 76896 76897 /** 76898 * Methods for injecting dependencies. 76899 */ 76900 injection: { 76901 76902 /** 76903 * @param {array} InjectedEventPluginOrder 76904 * @public 76905 */ 76906 injectEventPluginOrder: EventPluginRegistry.injectEventPluginOrder, 76907 76908 /** 76909 * @param {object} injectedNamesToPlugins Map from names to plugin modules. 76910 */ 76911 injectEventPluginsByName: EventPluginRegistry.injectEventPluginsByName 76912 76913 }, 76914 76915 /** 76916 * Stores `listener` at `listenerBank[registrationName][id]`. Is idempotent. 76917 * 76918 * @param {object} inst The instance, which is the source of events. 76919 * @param {string} registrationName Name of listener (e.g. `onClick`). 76920 * @param {function} listener The callback to store. 76921 */ 76922 putListener: function (inst, registrationName, listener) { 76923 !(typeof listener === 'function') ? "development" !== 'production' ? invariant(false, 'Expected %s listener to be a function, instead got type %s', registrationName, typeof listener) : invariant(false) : void 0; 76924 76925 var bankForRegistrationName = listenerBank[registrationName] || (listenerBank[registrationName] = {}); 76926 bankForRegistrationName[inst._rootNodeID] = listener; 76927 76928 var PluginModule = EventPluginRegistry.registrationNameModules[registrationName]; 76929 if (PluginModule && PluginModule.didPutListener) { 76930 PluginModule.didPutListener(inst, registrationName, listener); 76931 } 76932 }, 76933 76934 /** 76935 * @param {object} inst The instance, which is the source of events. 76936 * @param {string} registrationName Name of listener (e.g. `onClick`). 76937 * @return {?function} The stored callback. 76938 */ 76939 getListener: function (inst, registrationName) { 76940 var bankForRegistrationName = listenerBank[registrationName]; 76941 return bankForRegistrationName && bankForRegistrationName[inst._rootNodeID]; 76942 }, 76943 76944 /** 76945 * Deletes a listener from the registration bank. 76946 * 76947 * @param {object} inst The instance, which is the source of events. 76948 * @param {string} registrationName Name of listener (e.g. `onClick`). 76949 */ 76950 deleteListener: function (inst, registrationName) { 76951 var PluginModule = EventPluginRegistry.registrationNameModules[registrationName]; 76952 if (PluginModule && PluginModule.willDeleteListener) { 76953 PluginModule.willDeleteListener(inst, registrationName); 76954 } 76955 76956 var bankForRegistrationName = listenerBank[registrationName]; 76957 // TODO: This should never be null -- when is it? 76958 if (bankForRegistrationName) { 76959 delete bankForRegistrationName[inst._rootNodeID]; 76960 } 76961 }, 76962 76963 /** 76964 * Deletes all listeners for the DOM element with the supplied ID. 76965 * 76966 * @param {object} inst The instance, which is the source of events. 76967 */ 76968 deleteAllListeners: function (inst) { 76969 for (var registrationName in listenerBank) { 76970 if (!listenerBank[registrationName][inst._rootNodeID]) { 76971 continue; 76972 } 76973 76974 var PluginModule = EventPluginRegistry.registrationNameModules[registrationName]; 76975 if (PluginModule && PluginModule.willDeleteListener) { 76976 PluginModule.willDeleteListener(inst, registrationName); 76977 } 76978 76979 delete listenerBank[registrationName][inst._rootNodeID]; 76980 } 76981 }, 76982 76983 /** 76984 * Allows registered plugins an opportunity to extract events from top-level 76985 * native browser events. 76986 * 76987 * @return {*} An accumulation of synthetic events. 76988 * @internal 76989 */ 76990 extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) { 76991 var events; 76992 var plugins = EventPluginRegistry.plugins; 76993 for (var i = 0; i < plugins.length; i++) { 76994 // Not every plugin in the ordering may be loaded at runtime. 76995 var possiblePlugin = plugins[i]; 76996 if (possiblePlugin) { 76997 var extractedEvents = possiblePlugin.extractEvents(topLevelType, targetInst, nativeEvent, nativeEventTarget); 76998 if (extractedEvents) { 76999 events = accumulateInto(events, extractedEvents); 77000 } 77001 } 77002 } 77003 return events; 77004 }, 77005 77006 /** 77007 * Enqueues a synthetic event that should be dispatched when 77008 * `processEventQueue` is invoked. 77009 * 77010 * @param {*} events An accumulation of synthetic events. 77011 * @internal 77012 */ 77013 enqueueEvents: function (events) { 77014 if (events) { 77015 eventQueue = accumulateInto(eventQueue, events); 77016 } 77017 }, 77018 77019 /** 77020 * Dispatches all synthetic events on the event queue. 77021 * 77022 * @internal 77023 */ 77024 processEventQueue: function (simulated) { 77025 // Set `eventQueue` to null before processing it so that we can tell if more
77026 // events get enqueued while processing. 77027 var processingEventQueue = eventQueue; 77028 eventQueue = null; 77029 if (simulated) { 77030 forEachAccumulated(processingEventQueue, executeDispatchesAndReleaseSimulated); 77031 } else { 77032 forEachAccumulated(processingEventQueue, executeDispatchesAndReleaseTopLevel); 77033 } 77034 !!eventQueue ? "development" !== 'production' ? invariant(false, 'processEventQueue(): Additional events were enqueued while processing ' + 'an event queue. Support for this has not yet been implemented.') : invariant(false) : void 0; 77035 // This would be a good time to rethrow if any of the event handlers threw. 77036 ReactErrorUtils.rethrowCaughtError(); 77037 }, 77038 77039 /** 77040 * These are needed for tests only. Do not use! 77041 */ 77042 __purge: function () { 77043 listenerBank = {}; 77044 }, 77045 77046 __getListenerBank: function () { 77047 return listenerBank; 77048 } 77049 77050}; 77051 77052module.exports = EventPluginHub; 77053},{"114":114,"122":122,"158":158,"18":18,"19":19,"65":65}],18:[function(_dereq_,module,exports){ 77054/** 77055 * Copyright 2013-present, Facebook, Inc. 77056 * All rights reserved. 77057 * 77058 * This source code is licensed under the BSD-style license found in the 77059 * LICENSE file in the root directory of this source tree. An additional grant 77060 * of patent rights can be found in the PATENTS file in the same directory. 77061 * 77062 * @providesModule EventPluginRegistry 77063 */ 77064 77065 77066 77067var invariant = _dereq_(158); 77068 77069/** 77070 * Injectable ordering of event plugins. 77071 */ 77072var EventPluginOrder = null; 77073 77074/** 77075 * Injectable mapping from names to event plugin modules. 77076 */ 77077var namesToPlugins = {}; 77078 77079/** 77080 * Recomputes the plugin list using the injected plugins and plugin ordering. 77081 * 77082 * @private 77083 */ 77084function recomputePluginOrdering() { 77085 if (!EventPluginOrder) { 77086 // Wait until an `EventPluginOrder` is injected. 77087 return; 77088 } 77089 for (var pluginName in namesToPlugins) { 77090 var PluginModule = namesToPlugins[pluginName]; 77091 var pluginIndex = EventPluginOrder.indexOf(pluginName); 77092 !(pluginIndex > -1) ? "development" !== 'production' ? invariant(false, 'EventPluginRegistry: Cannot inject event plugins that do not exist in ' + 'the plugin ordering, `%s`.', pluginName) : invariant(false) : void 0; 77093 if (EventPluginRegistry.plugins[pluginIndex]) { 77094 continue; 77095 } 77096 !PluginModule.extractEvents ? "development" !== 'production' ? invariant(false, 'EventPluginRegistry: Event plugins must implement an `extractEvents` ' + 'method, but `%s` does not.', pluginName) : invariant(false) : void 0; 77097 EventPluginRegistry.plugins[pluginIndex] = PluginModule; 77098 var publishedEvents = PluginModule.eventTypes; 77099 for (var eventName in publishedEvents) { 77100 !publishEventForPlugin(publishedEvents[eventName], PluginModule, eventName) ? "development" !== 'production' ? invariant(false, 'EventPluginRegistry: Failed to publish event `%s` for plugin `%s`.', eventName, pluginName) : invariant(false) : void 0; 77101 } 77102 } 77103} 77104 77105/** 77106 * Publishes an event so that it can be dispatched by the supplied plugin. 77107 * 77108 * @param {object} dispatchConfig Dispatch configuration for the event. 77109 * @param {object} PluginModule Plugin publishing the event. 77110 * @return {boolean} True if the event was successfully published. 77111 * @private 77112 */ 77113function publishEventForPlugin(dispatchConfig, PluginModule, eventName) { 77114 !!EventPluginRegistry.eventNameDispatchConfigs.hasOwnProperty(eventName) ? "development" !== 'production' ? invariant(false, 'EventPluginHub: More than one plugin attempted to publish the same ' + 'event name, `%s`.', eventName) : invariant(false) : void 0; 77115 EventPluginRegistry.eventNameDispatchConfigs[eventName] = dispatchConfig; 77116
77117 var phasedRegistrationNames = dispatchConfig.phasedRegistrationNames; 77118 if (phasedRegistrationNames) { 77119 for (var phaseName in phasedRegistrationNames) { 77120 if (phasedRegistrationNames.hasOwnProperty(phaseName)) { 77121 var phasedRegistrationName = phasedRegistrationNames[phaseName]; 77122 publishRegistrationName(phasedRegistrationName, PluginModule, eventName); 77123 } 77124 } 77125 return true; 77126 } else if (dispatchConfig.registrationName) { 77127 publishRegistrationName(dispatchConfig.registrationName, PluginModule, eventName); 77128 return true; 77129 } 77130 return false; 77131} 77132 77133/** 77134 * Publishes a registration name that is used to identify dispatched events and 77135 * can be used with `EventPluginHub.putListener` to register listeners. 77136 * 77137 * @param {string} registrationName Registration name to add. 77138 * @param {object} PluginModule Plugin publishing the event. 77139 * @private 77140 */ 77141function publishRegistrationName(registrationName, PluginModule, eventName) { 77142 !!EventPluginRegistry.registrationNameModules[registrationName] ? "development" !== 'production' ? invariant(false, 'EventPluginHub: More than one plugin attempted to publish the same ' + 'registration name, `%s`.', registrationName) : invariant(false) : void 0; 77143 EventPluginRegistry.registrationNameModules[registrationName] = PluginModule; 77144 EventPluginRegistry.registrationNameDependencies[registrationName] = PluginModule.eventTypes[eventName].dependencies; 77145 77146 if ("development" !== 'production') { 77147 var lowerCasedName = registrationName.toLowerCase(); 77148 EventPluginRegistry.possibleRegistrationNames[lowerCasedName] = registrationName; 77149 } 77150} 77151 77152/** 77153 * Registers plugins so that they can extract and dispatch events. 77154 * 77155 * @see {EventPluginHub} 77156 */ 77157var EventPluginRegistry = { 77158 77159 /** 77160 * Ordered list of injected plugins. 77161 */ 77162 plugins: [], 77163 77164 /** 77165 * Mapping from event name to dispatch config 77166 */ 77167 eventNameDispatchConfigs: {}, 77168 77169 /** 77170 * Mapping from registration name to plugin module 77171 */ 77172 registrationNameModules: {}, 77173 77174 /** 77175 * Mapping from registration name to event name 77176 */ 77177 registrationNameDependencies: {}, 77178 77179 /** 77180 * Mapping from lowercase registration names to the properly cased version, 77181 * used to warn in the case of missing event handlers. Available 77182 * only in __DEV__. 77183 * @type {Object} 77184 */ 77185 possibleRegistrationNames: "development" !== 'production' ? {} : null, 77186 77187 /** 77188 * Injects an ordering of plugins (by plugin name). This allows the ordering 77189 * to be decoupled from injection of the actual plugins so that ordering is 77190 * always deterministic regardless of packaging, on-the-fly injection, etc. 77191 * 77192 * @param {array} InjectedEventPluginOrder 77193 * @internal 77194 * @see {EventPluginHub.injection.injectEventPluginOrder} 77195 */ 77196 injectEventPluginOrder: function (InjectedEventPluginOrder) { 77197 !!EventPluginOrder ? "development" !== 'production' ? invariant(false, 'EventPluginRegistry: Cannot inject event plugin ordering more than ' + 'once. You are likely trying to load more than one copy of React.') : invariant(false) : void 0; 77198 // Clone the ordering so it cannot be dynamically mutated. 77199 EventPluginOrder = Array.prototype.slice.call(InjectedEventPluginOrder); 77200 recomputePluginOrdering(); 77201 }, 77202 77203 /** 77204 * Injects plugins to be used by `EventPluginHub`. The plugin names must be 77205 * in the ordering injected by `injectEventPluginOrder`. 77206 * 77207 * Plugins can be injected as part of page initialization or on-the-fly. 77208 * 77209 * @param {object} injectedNamesToPlugins Map from names to plugin modules. 77210 * @internal 77211 * @see {EventPluginHub.injection.injectEventPluginsByName} 77212 */ 77213 injectEventPluginsByName: function (injectedNamesToPlugins) { 77214 var isOrderingDirty = false; 77215 for (var pluginName in injectedNamesToPlugins) { 77216 if (!injectedNamesToPlugins.hasOwnProperty(pluginName)) { 77217 continue; 77218 } 77219 var PluginModule = injectedNamesToPlugins[pluginName]; 77220 if (!namesToPlugins.hasOwnProperty(pluginName) || namesToPlugins[pluginName] !== PluginModule) { 77221 !!namesToPlugins[pluginName] ? "development" !== 'production' ? invariant(false, 'EventPluginRegistry: Cannot inject two different event plugins ' + 'using the same name, `%s`.', pluginName) : invariant(false) : void 0; 77222 namesToPlugins[pluginName] = PluginModule; 77223 isOrderingDirty = true; 77224 } 77225 } 77226 if (isOrderingDirty) { 77227 recomputePluginOrdering(); 77228 } 77229 }, 77230 77231 /** 77232 * Looks up the plugin for the supplied event. 77233 * 77234 * @param {object} event A synthetic event. 77235 * @return {?object} The plugin that created the supplied event. 77236 * @internal 77237 */ 77238 getPluginModuleForEvent: function (event) { 77239 var dispatchConfig = event.dispatchConfig;
77240 if (dispatchConfig.registrationName) { 77241 return EventPluginRegistry.registrationNameModules[dispatchConfig.registrationName] || null; 77242 } 77243 for (var phase in dispatchConfig.phasedRegistrationNames) { 77244 if (!dispatchConfig.phasedRegistrationNames.hasOwnProperty(phase)) { 77245 continue; 77246 } 77247 var PluginModule = EventPluginRegistry.registrationNameModules[dispatchConfig.phasedRegistrationNames[phase]]; 77248 if (PluginModule) { 77249 return PluginModule; 77250 } 77251 } 77252 return null; 77253 }, 77254 77255 /** 77256 * Exposed for unit testing. 77257 * @private 77258 */ 77259 _resetEventPlugins: function () { 77260 EventPluginOrder = null; 77261 for (var pluginName in namesToPlugins) { 77262 if (namesToPlugins.hasOwnProperty(pluginName)) { 77263 delete namesToPlugins[pluginName]; 77264 } 77265 } 77266 EventPluginRegistry.plugins.length = 0; 77267 77268 var eventNameDispatchConfigs = EventPluginRegistry.eventNameDispatchConfigs; 77269 for (var eventName in eventNameDispatchConfigs) { 77270 if (eventNameDispatchConfigs.hasOwnProperty(eventName)) { 77271 delete eventNameDispatchConfigs[eventName]; 77272 } 77273 } 77274 77275 var registrationNameModules = EventPluginRegistry.registrationNameModules; 77276 for (var registrationName in registrationNameModules) { 77277 if (registrationNameModules.hasOwnProperty(registrationName)) { 77278 delete registrationNameModules[registrationName]; 77279 } 77280 } 77281 77282 if ("development" !== 'production') { 77283 var possibleRegistrationNames = EventPluginRegistry.possibleRegistrationNames; 77284 for (var lowerCasedName in possibleRegistrationNames) { 77285 if (possibleRegistrationNames.hasOwnProperty(lowerCasedName)) { 77286 delete possibleRegistrationNames[lowerCasedName]; 77287 } 77288 } 77289 } 77290 } 77291 77292}; 77293 77294module.exports = EventPluginRegistry; 77295},{"158":158}],19:[function(_dereq_,module,exports){ 77296/** 77297 * Copyright 2013-present, Facebook, Inc. 77298 * All rights reserved. 77299 * 77300 * This source code is licensed under the BSD-style license found in the 77301 * LICENSE file in the root directory of this source tree. An additional grant 77302 * of patent rights can be found in the PATENTS file in the same directory. 77303 * 77304 * @providesModule EventPluginUtils 77305 */ 77306 77307 77308 77309var EventConstants = _dereq_(16);
77310var ReactErrorUtils = _dereq_(65); 77311 77312var invariant = _dereq_(158); 77313var warning = _dereq_(168); 77314 77315/** 77316 * Injected dependencies: 77317 */ 77318 77319/** 77320 * - `ComponentTree`: [required] Module that can convert between React instances 77321 * and actual node references. 77322 */ 77323var ComponentTree; 77324var TreeTraversal; 77325var injection = { 77326 injectComponentTree: function (Injected) { 77327 ComponentTree = Injected; 77328 if ("development" !== 'production') { 77329 "development" !== 'production' ? warning(Injected && Injected.getNodeFromInstance && Injected.getInstanceFromNode, 'EventPluginUtils.injection.injectComponentTree(...): Injected ' + 'module is missing getNodeFromInstance or getInstanceFromNode.') : void 0; 77330 } 77331 }, 77332 injectTreeTraversal: function (Injected) { 77333 TreeTraversal = Injected; 77334 if ("development" !== 'production') { 77335 "development" !== 'production' ? warning(Injected && Injected.isAncestor && Injected.getLowestCommonAncestor, 'EventPluginUtils.injection.injectTreeTraversal(...): Injected ' + 'module is missing isAncestor or getLowestCommonAncestor.') : void 0; 77336 } 77337 } 77338}; 77339 77340var topLevelTypes = EventConstants.topLevelTypes; 77341 77342function isEndish(topLevelType) { 77343 return topLevelType === topLevelTypes.topMouseUp || topLevelType === topLevelTypes.topTouchEnd || topLevelType === topLevelTypes.topTouchCancel; 77344} 77345 77346function isMoveish(topLevelType) { 77347 return topLevelType === topLevelTypes.topMouseMove || topLevelType === topLevelTypes.topTouchMove; 77348} 77349function isStartish(topLevelType) { 77350 return topLevelType === topLevelTypes.topMouseDown || topLevelType === topLevelTypes.topTouchStart; 77351} 77352 77353var validateEventDispatches; 77354if ("development" !== 'production') { 77355 validateEventDispatches = function (event) { 77356 var dispatchListeners = event._dispatchListeners; 77357 var dispatchInstances = event._dispatchInstances; 77358 77359 var listenersIsArr = Array.isArray(dispatchListeners); 77360 var listenersLen = listenersIsArr ? dispatchListeners.length : dis
77360patchListeners ? 1 : 0; 77361 77362 var instancesIsArr = Array.isArray(dispatchInstances); 77363 var instancesLen = instancesIsArr ? dispatchInstances.length : dispatchInstances ? 1 : 0; 77364 77365 "development" !== 'production' ? warning(instancesIsArr === listenersIsArr && instancesLen === listenersLen, 'EventPluginUtils: Invalid `event`.') : void 0; 77366 }; 77367} 77368 77369/** 77370 * Dispatch the event to the listener. 77371 * @param {SyntheticEvent} event SyntheticEvent to handle 77372 * @param {boolean} simulated If the event is simulated (changes exn behavior) 77373 * @param {function} listener Application-level callback 77374 * @param {*} inst Internal component instance 77375 */ 77376function executeDispatch(event, simulated, listener, inst) { 77377 var type = event.type || 'unknown-event'; 77378 event.currentTarget = EventPluginUtils.getNodeFromInstance(inst); 77379 if (simulated) { 77380 ReactErrorUtils.invokeGuardedCallbackWithCatch(type, listener, event); 77381 } else { 77382 ReactErrorUtils.invokeGuardedCallback(type, listener, event); 77383 } 77384 event.currentTarget = null; 77385} 77386 77387/** 77388 * Standard/simple iteration through an event's collected dispatches. 77389 */ 77390function executeDispatchesInOrder(event, simulated) { 77391 var dispatchListeners = event._dispatchListeners; 77392 var dispatchInstances = event._dispatchInstances; 77393 if ("development" !== 'production') { 77394 validateEventDispatches(event); 77395 } 77396 if (Array.isArray(dispatchListeners)) { 77397 for (var i = 0; i < dispatchListeners.length; i++) { 77398 if (event.isPropagationStopped()) { 77399 break; 77400 } 77401 // Listeners and Instances are two parallel arrays that are always in sync. 77402 executeDispatch(event, simulated, dispatchListeners[i], dispatchInstances[i]); 77403 } 77404 } else if (dispatchListeners) { 77405 executeDispatch(event, simulated, dispatchListeners, dispatchInstances); 77406 } 77407 event._dispatchListeners = null; 77408 event._dispatchInstances = null; 77409} 77410 77411/** 77412 * Standard/simple iteration through an event's collected dispatches, but stops 77413 * at the first dispatch execution returning true, and returns that id. 77414 * 77415 * @return {?string} id of the first dispatch execution who's listener returns 77416 * true, or null if no listener returned true. 77417 */ 77418function executeDispatchesInOrderStopAtTrueImpl(event) { 77419 var dispatchListeners = event._dispatchListeners; 77420 var dispatchInstances = event._dispatchInstances; 77421 if ("development" !== 'production') { 77422 validateEventDispatches(event); 77423 } 77424 if (Array.isArray(dispatchListeners)) { 77425 for (var i = 0; i < dispatchListeners.length; i++) { 77426 if (event.isPropagationStopped()) { 77427 break; 77428 } 77429 // Listeners and Instances are two parallel arrays that are always in sync. 77430 if (dispatchListeners[i](event, dispatchInstances[i])) { 77431 return dispatchInstances[i]; 77432 } 77433 } 77434 } else if (dispatchListeners) { 77435 if (dispatchListeners(event, dispatchInstances)) { 77436 return dispatchInstances; 77437 } 77438 } 77439 return null; 77440} 77441 77442/** 77443 * @see executeDispatchesInOrderStopAtTrueImpl 77444 */ 77445function executeDispatchesInOrderStopAtTrue(event) { 77446 var ret = executeDispatchesInOrderStopAtTrueImpl(event); 77447 event._dispatchInstances = null; 77448 event._dispatchListeners = null; 77449 return ret; 77450} 77451 77452/** 77453 * Execution of a "direct" dispatch - there must be at most one dispatch 77454 * accumulated on the event or it is considered an error. It doesn't really make 77455 * sense for an event with multiple dispatches (bubbled) to keep track of the 77456 * return values at each dispatch execution, but it does tend to make sense when 77457 * dealing with "direct" dispatches. 77458 * 77459 * @return {*} The return value of executing the single dispatch. 77460 */ 77461function executeDirectDispatch(event) { 77462 if ("development" !== 'production') { 77463 validateEventDispatches(event); 77464 } 77465 var dispatchListener = event._dispatchListeners; 77466 var dispatchInstance = event._dispatchInstances; 77467 !!Array.isArray(dispatchListener) ? "development" !== 'production' ? invariant(false, 'executeDirectDispatch(...): Invalid `event`.') : invariant(false) : void 0; 77468 event.currentTarget = dispatchListener ? EventPluginUtils.getNodeFromInstance(dispatchInstance) : null; 77469 var res = dispatchListener ? dispatchListener(event) : null; 77470 event.currentTarget = null; 77471 event._dispatchListeners = null; 77472 event._dispatchInstances = null; 77473 return res; 77474} 77475 77476/** 77477 * @param {SyntheticEvent} event 77478 * @return {boolean} True iff number of dispatches accumulated is greater than 0. 77479 */ 77480function hasDispatches(event) { 77481 return !!event._dispatchListeners; 77482} 77483 77484/** 77485 * General utilities that are useful in creating custom Event Plugins. 77486 */ 77487var EventPluginUtils = { 77488 isEndish: isEndish, 77489 isMoveish: isMoveish, 77490 isStartish: isStartish, 77491 77492 executeDirectDispatch: executeDirectDispatch, 77493 executeDispatchesInOrder: executeDispatchesInOrder, 77494 executeDispatchesInOrderStopAtTrue: executeDispatchesInOrderStopAtTrue, 77495 hasDispatches: hasDispatches, 77496 77497 getInstanceFromNode: function (node) { 77498 return ComponentTree.getInstanceFromNode(node); 77499 }, 77500 getNodeFromInstance: function (node) { 77501 return ComponentTree.getNodeFromInstance(node); 77502 }, 77503 isAncestor: function (a, b) { 77504 return TreeTraversal.isAncestor(a, b); 77505 }, 77506 getLowestCommonAncestor: function (a, b) { 77507 return TreeTraversal.getLowestCommonAncestor(a, b); 77508 }, 77509 getParentInstance: function (inst) { 77510 return TreeTraversal.getParentInstance(inst); 77511 }, 77512 traverseTwoPhase: function (target, fn, arg) { 77513 return TreeTraversal.traverseTwoPhase(target, fn, arg); 77514 }, 77515 traverseEnterLeave: function (from, to, fn, argFrom, argTo) { 77516 return TreeTraversal.traverseEnterLeave(from, to, fn, argFrom, argTo); 77517 }, 77518 77519 injection: injection 77520}; 77521 77522module.exports = EventPluginUtils; 77523},{"158":158,"16":16,"168":168,"65":65}],20:[function(_dereq_,module,exports){ 77524/** 77525 * Copyright 2013-present, Facebook, Inc. 77526 * All rights reserved. 77527 * 77528 * This source code is licensed under the BSD-style license found in the 77529 * LICENSE file in the root directory of this source tree. An additional grant 77530 * of patent rights can be found in the PATENTS file in the same directory. 77531 * 77532 * @providesModule EventPropagators 77533 */ 77534 77535 77536 77537var EventConstants = _dereq_(16); 77538var EventPluginHub = _dereq_(17); 77539var EventPluginUtils = _dereq_(19); 77540 77541var accumulateInto = _dereq_(114);
77542var forEachAccumulated = _dereq_(122); 77543var warning = _dereq_(168); 77544 77545var PropagationPhases = EventConstants.PropagationPhases; 77546var getListener = EventPluginHub.getListener; 77547 77548/** 77549 * Some event types have a notion of different registration names for different 77550 * "phases" of propagation. This finds listeners by a given phase. 77551 */ 77552function listenerAtPhase(inst, event, propagationPhase) { 77553 var registrationName = event.dispatchConfig.phasedRegistrationNames[propagationPhase]; 77554 return getListener(inst, registrationName); 77555} 77556 77557/** 77558 * Tags a `SyntheticEvent` with dispatched listeners. Creating this function 77559 * here, allows us to not have to bind or create functions for each event. 77560 * Mutating the event's members allows us to not have to create a wrapping 77561 * "dispatch" object that pairs the event with the listener. 77562 */ 77563function accumulateDirectionalDispatches(inst, upwards, event) { 77564 if ("development" !== 'production') { 77565 "development" !== 'production' ? warning(inst, 'Dispatching inst must not be null') : void 0; 77566 } 77567 var phase = upwards ? PropagationPhases.bubbled : PropagationPhases.captured; 77568 var listener = listenerAtPhase(inst, event, phase); 77569 if (listener) { 77570 event._dispatchListeners = accumulateInto(event._dispatchListeners, listener); 77571 event._dispatchInstances = accumulateInto(event._dispatchInstances, inst); 77572 } 77573} 77574 77575/** 77576 * Collect dispatches (must be entirely collected before dispatching - see unit 77577 * tests). Lazily allocate the array to conserve memory. We must loop through 77578 * each event and perform the traversal for each one. We cannot perform a 77579 * single traversal for the entire collection of events because each event may 77580 * have a different target. 77581 */ 77582function accumulateTwoPhaseDispatchesSingle(event) {
77583 if (event && event.dispatchConfig.phasedRegistrationNames) { 77584 EventPluginUtils.traverseTwoPhase(event._targetInst, accumulateDirectionalDispatches, event); 77585 } 77586} 77587 77588/** 77589 * Same as `accumulateTwoPhaseDispatchesSingle`, but skips over the targetID. 77590 */ 77591function accumulateTwoPhaseDispatchesSingleSkipTarget(event) { 77592 if (event && event.dispatchConfig.phasedRegistrationNames) { 77593 var targetInst = event._targetInst; 77594 var parentInst = targetInst ? EventPluginUtils.getParentInstance(targetInst) : null; 77595 EventPluginUtils.traverseTwoPhase(parentInst, accumulateDirectionalDispatches, event); 77596 } 77597} 77598 77599/** 77600 * Accumulates without regard to direction, does not look for phased 77601 * registration names. Same as `accumulateDirectDispatchesSingle` but without 77602 * requiring that the `dispatchMarker` be the same as the dispatched ID. 77603 */ 77604function accumulateDispatches(inst, ignoredDirection, event) { 77605 if (event && event.dispatchConfig.registrationName) { 77606 var registrationName = event.dispatchConfig.registrationName; 77607 var listener = getListener(inst, registrationName); 77608 if (listener) { 77609 event._dispatchListeners = accumulateInto(event._dispatchListeners, listener); 77610 event._dispatchInstances = accumulateInto(event._dispatchInstances, inst); 77611 } 77612 } 77613} 77614 77615/** 77616 * Accumulates dispatches on an `SyntheticEvent`, but only for the 77617 * `dispatchMarker`. 77618 * @param {SyntheticEvent} event 77619 */ 77620function accumulateDirectDispatchesSingle(event) { 77621 if (event && event.dispatchConfig.registrationName) { 77622 accumulateDispatches(event._targetInst, null, event); 77623 } 77624} 77625 77626function accumulateTwoPhaseDispatches(events) { 77627 forEachAccumulated(events, accumulateTwoPhaseDispatchesSingle); 77628} 77629 77630function accumulateTwoPhaseDispatchesSkipTarget(events) { 77631 forEachAccumulated(events, accumulateTwoPhaseDispatchesSingleSkipTarget); 77632} 77633 77634function accumulateEnterLeaveDispatches(leave, enter, from, to) { 77635 EventPluginUtils.traverseEnterLeave(from, to, accumulateDispatches, leave, enter); 77636} 77637 77638function accumulateDirectDispatches(events) { 77639 forEachAccumulated(events, accumulateDirectDispatchesSingle); 77640} 77641 77642/** 77643 * A small set of propagation patterns, each of which will accept a small amount 77644 * of information, and generate a set of "dispatch ready event objects" - which 77645 * are sets of events that have already been annotated with a set of dispatched 77646 * listener functions/ids. The API is designed this way to discourage these 77647 * propagation strategies from actually executing the dispatches, since we 77648 * always want to collect the entire set of dispatches before executing event a 77649 * single one. 77650 * 77651 * @constructor EventPropagators 77652 */ 77653var EventPropagators = { 77654 accumulateTwoPhaseDispatches: accumulateTwoPhaseDispatches, 77655 accumulateTwoPhaseDispatchesSkipTarget: accumulateTwoPhaseDispatchesSkipTarget, 77656 accumulateDirectDispatches: accumulateDirectDispatches, 77657 accumulateEnterLeaveDispatches: accumulateEnterLeaveDispatches 77658}; 77659 77660module.exports = EventPropagators; 77661},{"114":114,"122":122,"16":16,"168":168,"17":17,"19":19}],21:[function(_dereq_,module,exports){ 77662/** 77663 * Copyright 2013-present, Facebook, Inc. 77664 * All rights reserved. 77665 * 77666 * This source code is licensed under the BSD-style license found in the 77667 * LICENSE file in the root directory of this source tree. An additional grant 77668 * of patent rights can be found in the PATENTS file in the same directory. 77669 * 77670 * @providesModule FallbackCompositionState 77671 */ 77672 77673 77674 77675var _assign = _dereq_(169); 77676 77677var PooledClass = _dereq_(25); 77678 77679var getTextContentAccessor = _dereq_(130); 77680 77681/** 77682 * This helper class stores information about text content of a target node, 77683 * allowing comparison of content before and after a given event. 77684 * 77685 * Identify the node where selection currently begins, then observe 77686 * both its text content and its current position in the DOM. Since the 77687 * browser may natively replace the target node during composition, we can 77688 * use its position to find its replacement. 77689 * 77690 * @param {DOMEventTarget} root 77691 */ 77692function FallbackCompositionState(root) { 77693 this._root = root; 77694 this._startText = this.getText(); 77695 this._fallbackText = null; 77696} 77697 77698_assign(FallbackCompositionState.prototype, { 77699 destructor: function () { 77700 this._root = null; 77701 this._startText = null; 77702 this._fallbackText = null; 77703 }, 77704 77705 /** 77706 * Get current text of input. 77707 * 77708 * @return {string} 77709 */ 77710 getText: function () { 77711 if ('value' in this._root) { 77712 return this._root.value; 77713 } 77714 return this._root[getTextContentAccessor()]; 77715 }, 77716 77717 /** 77718 * Determine the differing substring between the initially stored 77719 * text content and the current content. 77720 * 77721 * @return {string} 77722 */ 77723 getData: function () { 77724 if (this._fallbackText) { 77725 return this._fallbackText; 77726 } 77727 77728 var start; 77729 var startValue = this._startText; 77730 var startLength = startValue.length; 77731 var end; 77732 var endValue = this.getText(); 77733 var endLength = endValue.length; 77734 77735 for (start = 0; start < startLength; start++) { 77736 if (startValue[start] !== endValue[start]) { 77737 break; 77738 } 77739 } 77740 77741 var minEnd = startLength - start; 77742 for (end = 1; end <= minEnd; end++) { 77743 if (startValue[startLength - end] !== endValue[endLength - end]) { 77744 break; 77745 } 77746 } 77747 77748 var sliceTail = end > 1 ? 1 - end : undefined; 77749 this._fallbackText = endValue.slice(start, sliceTail); 77750 return this._fallbackText; 77751 } 77752}); 77753 77754PooledClass.addPoolingTo(FallbackCompositionState); 77755 77756module.exports = FallbackCompositionState; 77757},{"130":130,"169":169,"25":25}],22:[function(_dereq_,module,exports){ 77758/** 77759 * Copyright 2013-present, Facebook, Inc. 77760 * All rights reserved. 77761 * 77762 * This source code is licensed under the BSD-style license found in the 77763 * LICENSE file in the root directory of this source tree. An additional grant 77764 * of patent rights can be found in the PATENTS file in the same directory. 77765 * 77766 * @providesModule HTMLDOMPropertyConfig 77767 */ 77768 77769 77770 77771var DOMProperty = _dereq_(10); 77772 77773var MUST_USE_PROPERTY = DOMProperty.injection.MUST_USE_PROPERTY; 77774var HAS_BOOLEAN_VALUE = DOMProperty.injection.HAS_BOOLEAN_VALUE; 77775var HAS_SIDE_EFFECTS = DOMProperty.injection.HAS_SIDE_EFFECTS; 77776var HAS_NUMERIC_VALUE = DOMProperty.injection.HAS_NUMERIC_VALUE; 77777var HAS_POSITIVE_NUMERIC_VALUE = DOMProperty.injection.HAS_POSITIVE_NUMERIC_VALUE; 77778var HAS_OVERLOADED_BOOLEAN_VALUE = DOMProperty.injection.HAS_OVERLOADED_BOOLEAN_VALUE; 77779 77780var HTMLDOMPropertyConfig = { 77781 isCustomAttribute: RegExp.prototype.test.bind(new RegExp('^(data|aria)-[' + DOMProperty.ATTRIBUTE_NAME_CHAR + ']*$')), 77782 Properties: { 77783 /** 77784 * Standard Properties 77785 */ 77786 accept: 0, 77787 acceptCharset: 0, 77788 accessKey: 0, 77789 action: 0, 77790 allowFullScreen: HAS_BOOLEAN_VALUE, 77791 allowTransparency: 0, 77792 alt: 0, 77793 async: HAS_BOOLEAN_VALUE, 77794 autoComplete: 0, 77795 // autoFocus is polyfilled/normalized by AutoFocusUtils 77796 // autoFocus: HAS_BOOLEAN_VALUE, 77797 autoPlay: HAS_BOOLEAN_VALUE, 77798 capture: HAS_BOOLEAN_VALUE, 77799 cellPadding: 0, 77800 cellSpacing: 0, 77801 charSet: 0, 77802 challenge: 0, 77803 checked: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE, 77804 cite: 0, 77805 classID: 0, 77806 className: 0, 77807 cols: HAS_POSITIVE_NUMERIC_VALUE, 77808 colSpan: 0, 77809 content: 0, 77810 contentEditable: 0, 77811 contextMenu: 0, 77812 controls: HAS_BOOLEAN_VALUE, 77813 coords: 0, 77814 crossOrigin: 0, 77815 data: 0, // For `<object />` acts as `src`. 77816 dateTime: 0, 77817 'default': HAS_BOOLEAN_VALUE, 77818 defer: HAS_BOOLEAN_VALUE, 77819 dir: 0, 77820 disabled: HAS_BOOLEAN_VALUE, 77821 download: HAS_OVERLOADED_BOOLEAN_VALUE, 77822 draggable: 0, 77823 encType: 0, 77824 form: 0, 77825 formAction: 0, 77826 formEncType: 0, 77827 formMethod: 0, 77828 formNoValidate: HAS_BOOLEAN_VALUE, 77829 formTarget: 0, 77830 frameBorder: 0, 77831 headers: 0, 77832 height: 0, 77833 hidden: HAS_BOOLEAN_VALUE, 77834 high: 0, 77835 href: 0, 77836 hrefLang: 0, 77837 htmlFor: 0, 77838 httpEquiv: 0, 77839 icon: 0, 77840 id: 0, 77841 inputMode: 0, 77842 integrity: 0, 77843 is: 0, 77844 keyParams: 0, 77845 keyType: 0, 77846 kind: 0, 77847 label: 0, 77848 lang: 0, 77849 list: 0, 77850 loop: HAS_BOOLEAN_VALUE, 77851 low: 0, 77852 manifest: 0, 77853 marginHeight: 0, 77854 marginWidth: 0, 77855 max: 0, 77856 maxLength: 0, 77857 media: 0, 77858 mediaGroup: 0, 77859 method: 0, 77860 min: 0, 77861 minLength: 0, 77862 // Caution; `option.selected` is not updated if `select.multiple` is
77863 // disabled with `removeAttribute`. 77864 multiple: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE, 77865 muted: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE, 77866 name: 0, 77867 nonce: 0, 77868 noValidate: HAS_BOOLEAN_VALUE, 77869 open: HAS_BOOLEAN_VALUE, 77870 optimum: 0, 77871 pattern: 0, 77872 placeholder: 0, 77873 poster: 0, 77874 preload: 0, 77875 profile: 0, 77876 radioGroup: 0, 77877 readOnly: HAS_BOOLEAN_VALUE, 77878 rel: 0, 77879 required: HAS_BOOLEAN_VALUE, 77880 reversed: HAS_BOOLEAN_VALUE, 77881 role: 0, 77882 rows: HAS_POSITIVE_NUMERIC_VALUE, 77883 rowSpan: HAS_NUMERIC_VALUE, 77884 sandbox: 0, 77885 scope: 0, 77886 scoped: HAS_BOOLEAN_VALUE, 77887 scrolling: 0, 77888 seamless: HAS_BOOLEAN_VALUE, 77889 selected: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE, 77890 shape: 0, 77891 size: HAS_POSITIVE_NUMERIC_VALUE, 77892 sizes: 0, 77893 span: HAS_POSITIVE_NUMERIC_VALUE, 77894 spellCheck: 0, 77895 src: 0, 77896 srcDoc: 0, 77897 srcLang: 0, 77898 srcSet: 0, 77899 start: HAS_NUMERIC_VALUE, 77900 step: 0, 77901 style: 0, 77902 summary: 0, 77903 tabIndex: 0, 77904 target: 0, 77905 title: 0, 77906 // Setting .type throws on non-<input> tags 77907 type: 0, 77908 useMap: 0, 77909 value: MUST_USE_PROPERTY | HAS_SIDE_EFFECTS, 77910 width: 0, 77911 wmode: 0, 77912 wrap: 0, 77913 77914 /** 77915 * RDFa Properties 77916 */ 77917 about: 0, 77918 datatype: 0, 77919 inlist: 0, 77920 prefix: 0, 77921 // property is also supported for OpenGraph in meta tags. 77922 property: 0, 77923 resource: 0, 77924 'typeof': 0, 77925 vocab: 0, 77926 77927 /** 77928 * Non-standard Properties 77929 */ 77930 // autoCapitalize and autoCorrect are supported in Mobile Safari for 77931 // keyboard hints. 77932 autoCapitalize: 0, 77933 autoCorrect: 0, 77934 // autoSave allows WebKit/Blink to persist values of input fields on page reloads 77935 autoSave: 0, 77936 // color is for Safari mask-icon link 77937 color: 0, 77938 // itemProp, itemScope, itemType are for 77939 // Microdata support. See http://schema.org/docs/gs.html 77940 itemProp: 0, 77941 itemScope: HAS_BOOLEAN_VALUE, 77942 itemType: 0, 77943 // itemID and itemRef are for Microdata support as well but 77944 // only specified in the WHATWG spec document. See 77945 // https://html.spec.whatwg.org/multipage/microdata.html#microdata-dom-api 77946 itemID: 0, 77947 itemRef: 0, 77948 // results show looking glass icon and recent searches on input 77949 // search fields in WebKit/Blink 77950 results: 0, 77951 // IE-only attribute that specifies security restrictions on an iframe 77952 // as an alternative to the sandbox attribute on IE<10 77953 security: 0, 77954 // IE-only attribute that controls focus behavior 77955 unselectable: 0 77956 }, 77957 DOMAttributeNames: { 77958 acceptCharset: 'accept-charset', 77959 className: 'class', 77960 htmlFor: 'for', 77961 httpEquiv: 'http-equiv' 77962 }, 77963 DOMPropertyNames: {} 77964}; 77965 77966module.exports = HTMLDOMPropertyConfig; 77967},{"10":10}],23:[function(_dereq_,module,exports){ 77968/** 77969 * Copyright 2013-present, Facebook, Inc. 77970 * All rights reserved. 77971 * 77972 * This source code is licensed under the BSD-style license found in the 77973 * LICENSE file in the root directory of this source tree. An additional grant 77974 * of patent rights can be found in the PATENTS file in the same directory. 77975 * 77976 * @providesModule KeyEscapeUtils 77977 */ 77978 77979 77980 77981/** 77982 * Escape and wrap key so it is safe to use as a reactid 77983 * 77984 * @param {*} key to be escaped. 77985 * @return {string} the escaped key. 77986 */ 77987 77988function escape(key) { 77989 var escapeRegex = /[=:]/g; 77990 var escaperLookup = { 77991 '=': '=0', 77992 ':': '=2' 77993 }; 77994 var escapedString = ('' + key).replace(escapeRegex, function (match) { 77995 return escaperLookup[match]; 77996 }); 77997 77998 return '$' + escapedString; 77999} 78000 78001/** 78002 * Unescape and unwrap key for human-readable display 78003 * 78004 * @param {string} key to unescape. 78005 * @return {string} the unescaped key. 78006 */ 78007function unescape(key) { 78008 var unescapeRegex = /(=0|=2)/g; 78009 var unescaperLookup = { 78010 '=0': '=', 78011 '=2': ':' 78012 }; 78013 var keySubstring = key[0] === '.' && key[1] === '$' ? key.substring(2) : key.substring(1); 78014 78015 return ('' + keySubstring).replace(unescapeRegex, function (match) { 78016 return unescaperLookup[match]; 78017 }); 78018} 78019 78020var KeyEscapeUtils = { 78021 escape: escape, 78022 unescape: unescape 78023}; 78024 78025module.exports = KeyEscapeUtils; 78026},{}],24:[function(_dereq_,module,exports){ 78027/** 78028 * Copyright 2013-present, Facebook, Inc. 78029 * All rights reserved. 78030 * 78031 * This source code is licensed under the BSD-style license found in the 78032 * LICENSE file in the root directory of this source tree. An additional grant 78033 * of patent rights can be found in the PATENTS file in the same directory. 78034 * 78035 * @providesModule LinkedValueUtils 78036 */ 78037 78038 78039 78040var ReactPropTypes = _dereq_(85); 78041var ReactPropTypeLocations = _dereq_(84); 78042 78043var invariant = _dereq_(158); 78044var warning = _dereq_(168); 78045 78046var hasReadOnlyValue = { 78047 'button': true, 78048 'checkbox': true, 78049 'image': true, 78050 'hidden': true, 78051 'radio': true, 78052 'reset': true, 78053 'submit': true 78054}; 78055 78056function _assertSingleLink(inputProps) { 78057 !(inputProps.checkedLink == null || inputProps.valueLink == null) ? "development" !== 'production' ? invariant(false, 'Cannot provide a checkedLink and a valueLink. If you want to use ' + 'checkedLink, you probably don\'t want to use valueLink and vice versa.') : invariant(false) : void 0; 78058} 78059function _assertValueLink(inputProps) { 78060 _assertSingleLink(inputProps); 78061 !(inputProps.value == null && inputProps.onChange == null) ? "development" !== 'production' ? invariant(false, 'Cannot provide a valueLink and a value or onChange event. If you want ' + 'to use value or onChange, you probably don\'t want to use valueLink.') : invariant(false) : void 0; 78062} 78063 78064function _assertCheckedLink(inputProps) { 78065 _assertSingleLink(inputProps); 78066 !(inputProps.checked == null && inputProps.onChange == null) ? "development" !== 'production' ? invariant(false, 'Cannot provide a checkedLink and a checked property or onChange event. ' + 'If you want to use checked or onChange, you probably don\'t want to ' + 'use checkedLink') : invariant(false) : void 0; 78067} 78068 78069var propTypes = { 78070 value: function (props, propName, componentName) { 78071 if (!props[propName] || hasReadOnlyValue[props.type] || props.onChange || props.readOnly || props.disabled) { 78072 return null; 78073 } 78074 return new Error('You provided a `value` prop to a form field without an ' + '`onChange` handler. This will render a read-only field. If ' + 'the field should be mutable use `defaultValue`. Otherwise, ' + 'set either `onChange` or `readOnly`.'); 78075 }, 78076 checked: function (props, propName, componentName) { 78077 if (!props[propName] || props.onChange || props.readOnly || props.disabled) { 78078 return null; 78079 } 78080 return new Error('You provided a `checked` prop to a form field without an ' + '`onChange` handler. This will render a read-only field. If ' + 'the field should be mutable use `defaultChecked`. Otherwise, ' + 'set either `onChange` or `readOnly`.'); 78081 }, 78082 onChange: ReactPropTypes.func 78083}; 78084 78085var loggedTypeFailures = {}; 78086function getDeclarationErrorAddendum(owner) { 78087 if (owner) { 78088 var name = owner.getName(); 78089 if (name) { 78090 return ' Check the render method of `' + name + '`.'; 78091 } 78092 } 78093 return ''; 78094} 78095 78096/** 78097 * Provide a linked `value` attribute for controlled forms. You should not use 78098 * this outside of the ReactDOM controlled form components. 78099 */ 78100var LinkedValueUtils = { 78101 checkPropTypes: function (tagName, props, owner) { 78102 for (var propName in propTypes) { 78103 if (propTypes.hasOwnProperty(propName)) { 78104 var error = propTypes[propName](props, propName, tagName, ReactPropTypeLocations.prop); 78105 } 78106 if (error instanceof Error && !(error.message in loggedTypeFailures)) { 78107 // Only monitor this failure once because there tends to be a lot of the 78108 // same error. 78109 loggedTypeFailures[error.message] = true; 78110 78111 var addendum = getDeclarationErrorAddendum(owner); 78112 "development" !== 'production' ? warning(false, 'Failed form propType: %s%s', error.message, addendum) : void 0; 78113 } 78114 } 78115 }, 78116 78117 /** 78118 * @param {object} inputProps Props for form component 78119 * @return {*} current value of the input either from value prop or link. 78120 */ 78121 getValue: function (inputProps) { 78122 if (inputProps.valueLink) { 78123 _assertValueLink(inputProps); 78124 return inputProps.valueLink.value; 78125 } 78126 return inputProps.value; 78127 }, 78128 78129 /** 78130 * @param {object} inputProps Props for form component 78131 * @return {*} current checked status of the input either from checked prop 78132 * or link. 78133 */ 78134 getChecked: function (inputProps) { 78135 if (inputProps.checkedLink) { 78136 _assertCheckedLink(inputProps); 78137 return inputProps.checkedLink.value; 78138 } 78139 return inputProps.checked; 78140 }, 78141 78142 /** 78143 * @param {object} inputProps Props for form component 78144 * @param {SyntheticEvent} event change event to handle 78145 */ 78146 executeOnChange: function (inputProps, event) { 78147 if (inputProps.valueLink) { 78148 _assertValueLink(inputProps); 78149 return inputProps.valueLink.requestChange(event.target.value); 78150 } else if (inputProps.checkedLink) { 78151 _assertCheckedLink(inputProps); 78152 return inputProps.checkedLink.requestChange(event.target.checked); 78153 } else if (inputProps.onChange) { 78154 return inputProps.onChange.call(undefined, event); 78155 } 78156 } 78157}; 78158 78159module.exports = LinkedValueUtils; 78160},{"158":158,"168":168,"84":84,"85":85}],25:[function(_dereq_,module,exports){ 78161/** 78162 * Copyright 2013-present, Facebook, Inc. 78163 * All rights reserved. 78164 * 78165 * This source code is licensed under the BSD-style license found in the 78166 * LICENSE file in the root directory of this source tree. An additional grant 78167 * of patent rights can be found in the PATENTS file in the same directory. 78168 * 78169 * @providesModule PooledClass 78170 */ 78171 78172 78173 78174var invariant = _dereq_(158); 78175 78176/** 78177 * Static poolers. Several custom versions for each potential number of 78178 * arguments. A completely generic pooler is easy to implement, but would 78179 * require accessing the `arguments` object. In each of these, `this` refers to 78180 * the Class itself, not an instance. If any others are needed, simply add them
78181 * here, or in their own files. 78182 */ 78183var oneArgumentPooler = function (copyFieldsFrom) { 78184 var Klass = this; 78185 if (Klass.instancePool.length) { 78186 var instance = Klass.instancePool.pop(); 78187 Klass.call(instance, copyFieldsFrom); 78188 return instance; 78189 } else { 78190 return new Klass(copyFieldsFrom); 78191 } 78192}; 78193 78194var twoArgumentPooler = function (a1, a2) { 78195 var Klass = this; 78196 if (Klass.instancePool.length) { 78197 var instance = Klass.instancePool.pop(); 78198 Klass.call(instance, a1, a2); 78199 return instance; 78200 } else { 78201 return new Klass(a1, a2); 78202 } 78203}; 78204 78205var threeArgumentPooler = function (a1, a2, a3) { 78206 var Klass = this; 78207 if (Klass.instancePool.length) { 78208 var instance = Klass.instancePool.pop(); 78209 Klass.call(instance, a1, a2, a3); 78210 return instance; 78211 } else { 78212 return new Klass(a1, a2, a3); 78213 } 78214}; 78215 78216var fourArgumentPooler = function (a1, a2, a3, a4) { 78217 var Klass = this; 78218 if (Klass.instancePool.length) { 78219 var instance = Klass.instancePool.pop(); 78220 Klass.call(instance, a1, a2, a3, a4); 78221 return instance; 78222 } else { 78223 return new Klass(a1, a2, a3, a4); 78224 } 78225}; 78226 78227var fiveArgumentPooler = function (a1, a2, a3, a4, a5) { 78228 var Klass = this; 78229 if (Klass.instancePool.length) { 78230 var instance = Klass.instancePool.pop(); 78231 Klass.call(instance, a1, a2, a3, a4, a5); 78232 return instance; 78233 } else { 78234 return new Klass(a1, a2, a3, a4, a5); 78235 } 78236}; 78237 78238var standardReleaser = function (instance) { 78239 var Klass = this; 78240 !(instance instanceof Klass) ? "development" !== 'production' ? invariant(false, 'Trying to release an instance into a pool of a different type.') : invariant(false) : void 0; 78241 instance.destructor(); 78242 if (Klass.instancePool.length < Klass.poolSize) { 78243 Klass.instancePool.push(instance); 78244 } 78245}; 78246 78247var DEFAULT_POOL_SIZE = 10; 78248var DEFAULT_POOLER = oneArgumentPooler; 78249 78250/** 78251 * Augments `CopyConstructor` to be a poolable class, augmenting only the class 78252 * itself (statically) not adding any prototypical fields. Any CopyConstructor 78253 * you give this may have a `poolSize` property, and will look for a 78254 * prototypical `destructor` on instances (optional). 78255 * 78256 * @param {Function} CopyConstructor Constructor that can be used to reset. 78257 * @param {Function} pooler Customizable pooler. 78258 */ 78259var addPoolingTo = function (CopyConstructor, pooler) { 78260 var NewKlass = CopyConstructor; 78261 NewKlass.instancePool = []; 78262 NewKlass.getPooled = pooler || DEFAULT_POOLER; 78263 if (!NewKlass.poolSize) { 78264 NewKlass.poolSize = DEFAULT_POOL_SIZE; 78265 } 78266 NewKlass.release = standardReleaser; 78267 return NewKlass; 78268}; 78269 78270var PooledClass = { 78271 addPoolingTo: addPoolingTo, 78272 oneArgumentPooler: oneArgumentPooler, 78273 twoArgumentPooler: twoArgumentPooler, 78274 threeArgumentPooler: threeArgumentPooler, 78275 fourArgumentPooler: fourArgumentPooler, 78276 fiveArgumentPooler: fiveArgumentPooler 78277}; 78278 78279module.exports = PooledClass; 78280},{"158":158}],26:[function(_dereq_,module,exports){ 78281/** 78282 * Copyright 2013-present, Facebook, Inc. 78283 * All rights reserved. 78284 * 78285 * This source code is licensed under the BSD-style license found in the 78286 * LICENSE file in the root directory of this source tree. An additional grant 78287 * of patent rights can be found in the PATENTS file in the same directory. 78288 * 78289 * @providesModule React 78290 */ 78291 78292 78293 78294var _assign = _dereq_(169); 78295 78296var ReactChildren = _dereq_(29); 78297var ReactComponent = _dereq_(31); 78298var ReactClass = _dereq_(30); 78299var ReactDOMFactories = _dereq_(44); 78300var ReactElement = _dereq_(62); 78301var ReactElementValidator = _dereq_(63); 78302var ReactPropTypes = _dereq_(85); 78303var ReactVersion = _dereq_(95); 78304 78305var onlyChild = _dereq_(135); 78306var warning = _dereq_(168); 78307 78308var createElement = ReactElement.createElement; 78309var createFactory = ReactElement.createFactory; 78310var cloneElement = ReactElement.cloneElement; 78311 78312if ("development" !== 'production') { 78313 createElement = ReactElementValidator.createElement; 78314 createFactory = ReactElementValidator.createFactory; 78315 cloneElement = ReactElementValidator.cloneElement; 78316} 78317 78318var __spread = _assign; 78319 78320if ("development" !== 'production') { 78321 var warned = false; 78322 __spread = function () { 78323 "development" !== 'production' ? warning(warned, 'React.__spread is deprecated and should not be used. Use ' + 'Object.assign directly or another helper function with similar ' + 'semantics. You may be seeing this warning due to your compiler. ' + 'See https://fb.me/react-spread-deprecation for more details.') : void 0; 78324 warned = true; 78325 return _assign.apply(null, arguments); 78326 }; 78327} 78328 78329var React = { 78330 78331 // Modern 78332 78333 Children: { 78334 map: ReactChildren.map,
78335 forEach: ReactChildren.forEach, 78336 count: ReactChildren.count, 78337 toArray: ReactChildren.toArray, 78338 only: onlyChild 78339 }, 78340 78341 Component: ReactComponent, 78342 78343 createElement: createElement, 78344 cloneElement: cloneElement, 78345 isValidElement: ReactElement.isValidElement, 78346 78347 // Classic 78348 78349 PropTypes: ReactPropTypes, 78350 createClass: ReactClass.createClass, 78351 createFactory: createFactory, 78352 createMixin: function (mixin) { 78353 // Currently a noop. Will be used to validate and trace mixins. 78354 return mixin; 78355 }, 78356 78357 // This looks DOM specific but these are actually isomorphic helpers 78358 // since they are just generating DOM strings. 78359 DOM: ReactDOMFactories, 78360 78361 version: ReactVersion, 78362 78363 // Deprecated hook for JSX spread, don't use this for anything. 78364 __spread: __spread 78365}; 78366 78367module.exports = React; 78368},{"135":135,"168":168,"169":169,"29":29,"30":30,"31":31,"44":44,"62":62,"63":63,"85":85,"95":95}],27:[function(_dereq_,module,exports){ 78369/** 78370 * Copyright 2013-present, Facebook, Inc. 78371 * All rights reserved. 78372 * 78373 * This source code is licensed under the BSD-style license found in the 78374 * LICENSE file in the root directory of this source tree. An additional grant 78375 * of patent rights can be found in the PATENTS file in the same directory. 78376 * 78377 * @providesModule ReactBrowserEventEmitter 78378 */ 78379 78380 78381 78382var _assign = _dereq_(169); 78383 78384var EventConstants = _dereq_(16); 78385var EventPluginRegistry = _dereq_(18); 78386var ReactEventEmitterMixin = _dereq_(66); 78387var ViewportMetrics = _dereq_(113); 78388 78389var getVendorPrefixedEventName = _dereq_(131); 78390var isEventSupported = _dereq_(133); 78391 78392/** 78393 * Summary of `ReactBrowserEventEmitter` event handling: 78394 * 78395 * - Top-level delegation is used to trap most native browser events. This 78396 * may only occur in the main thread and is the responsibility of 78397 * ReactEventListener, which is injected and can therefore support pluggable 78398 * event sources. This is the only work that occurs in the main thread. 78399 * 78400 * - We normalize and de-duplicate events to account for browser quirks. This 78401 * may be done in the worker thread. 78402 * 78403 * - Forward these native events (with the associated top-level type used to 78404 * trap it) to `EventPluginHub`, which in turn will ask plugins if they want 78405 * to extract any synthetic events. 78406 * 78407 * - The `EventPluginHub` will then process each event by annotating them with 78408 * "dispatches", a sequence of listeners and IDs that care about that event. 78409 * 78410 * - The `EventPluginHub` then dispatches the events. 78411 * 78412 * Overview of React and the event system: 78413 * 78414 * +------------+ . 78415 * | DOM | . 78416 * +------------+ . 78417 * | . 78418 * v . 78419 * +------------+ . 78420 * | ReactEvent | . 78421 * | Listener | . 78422 * +------------+ . +-----------+ 78423 * | . +--------+|SimpleEvent| 78424 * | . | |Plugin | 78425 * +-----|------+ . v +-----------+ 78426 * | | | . +--------------+ +------------+ 78427 * | +-----------.--->|EventPluginHub| | Event | 78428 * | | . | | +-----------+ | Propagators| 78429 * | ReactEvent | . | | |TapEvent | |------------| 78430 * | Emitter | . | |<---+|Plugin | |other plugin| 78431 * | | . | | +-----------+ | utilities | 78432 * | +-----------.--->| | +------------+ 78433 * | | | . +--------------+ 78434 * +-----|------+ . ^ +-----------+ 78435 * | . | |Enter/Leave| 78436 * + . +-------+|Plugin | 78437 * +-------------+ . +-----------+ 78438 * | application | . 78439 * |-------------| . 78440 * | | . 78441 * | | . 78442 * +-------------+ . 78443 * . 78444 * React Core . General Purpose Event Plugin System 78445 */ 78446 78447var hasEventPageXY; 78448var alreadyListeningTo = {}; 78449var isMonitoringScrollValue = false; 78450var reactTopListenersCounter = 0; 78451 78452// For events like 'submit' which don't consistently bubble (which we trap at a 78453// lower node than `document`), binding at `document` would cause duplicate 78454// events so we don't include them here 78455var topEventMapping = { 78456 topAbort: 'abort', 78457 topAnimationEnd: getVendorPrefixedEventName('animationend') || 'animationend', 78458 topAnimationIteration: getVendorPrefixedEventName('animationiteration') || 'animationiteration', 78459 topAnimationStart: getVendorPrefixedEventName('animationstart') || 'animationstart', 78460 topBlur: 'blur', 78461 topCanPlay: 'canplay', 78462 topCanPlayThrough: 'canplaythrough', 78463 topChange: 'change', 78464 topClick: 'click', 78465 topCompositionEnd: 'compositionend', 78466 topCompositionStart: 'compositionstart', 78467 topCompositionUpdate: 'compositionupdate', 78468 topContextMenu: 'contextmenu', 78469 topCopy: 'copy', 78470 topCut: 'cut', 78471 topDoubleClick: 'dblclick', 78472 topDrag: 'drag', 78473 topDragEnd: 'dragend', 78474 topDragEnter: 'dragenter', 78475 topDragExit: 'dragexit', 78476 topDragLeave: 'dragleave', 78477 topDragOver: 'dragover', 78478 topDragStart: 'dragstart', 78479 topDrop: 'drop', 78480 topDurationChange: 'durationchange', 78481 topEmptied: 'emptied', 78482 topEncrypted: 'encrypted', 78483 topEnded: 'ended', 78484 topError: 'error', 78485 topFocus: 'focus', 78486 topInput: 'input', 78487 topKeyDown: 'keydown', 78488 topKeyPress: 'keypress', 78489 topKeyUp: 'keyup', 78490 topLoadedData: 'loadeddata', 78491 topLoadedMetadata: 'loadedmetadata', 78492 topLoadStart: 'loadstart', 78493 topMouseDown: 'mousedown', 78494 topMouseMove: 'mousemove', 78495 topMouseOut: 'mouseout', 78496 topMouseOver: 'mouseover', 78497 topMouseUp: 'mouseup', 78498 topPaste: 'paste', 78499 topPause: 'pause', 78500 topPlay: 'play', 78501 topPlaying: 'playing', 78502 topProgress: 'progress', 78503 topRateChange: 'ratechange', 78504 topScroll: 'scroll', 78505 topSeeked: 'seeked', 78506 topSeeking: 'seeking', 78507 topSelectionChange: 'selectionchange', 78508 topStalled: 'stalled', 78509 topSuspend: 'suspend', 78510 topTextInput: 'textInput', 78511 topTimeUpdate: 'timeupdate', 78512 topTouchCancel: 'touchcancel', 78513 topTouchEnd: 'touchend', 78514 topTouchMove: 'touchmove', 78515 topTouchStart: 'touchstart', 78516 topTransitionEnd: getVendorPrefixedEventName('transitionend') || 'transitionend', 78517 topVolumeChange: 'volumechange', 78518 topWaiting: 'waiting', 78519 topWheel: 'wheel' 78520}; 78521 78522/** 78523 * To ensure no conflicts with other potential React instances on the page 78524 */ 78525var topListenersIDKey = '_reactListenersID' + String(Math.random()).slice(2); 78526 78527function getListeningForDocument(mountAt) { 78528 // In IE8, `mountAt` is a host object and doesn't have `hasOwnProperty` 78529 // directly. 78530 if (!Object.prototype.hasOwnProperty.call(mountAt, topListenersIDKey)) { 78531 mountAt[topListenersIDKey] = reactTopListenersCounter++; 78532 alreadyListeningTo[mountAt[topListenersIDKey]] = {}; 78533 } 78534 return alreadyListeningTo[mountAt[topListenersIDKey]]; 78535} 78536 78537/** 78538 * `ReactBrowserEventEmitter` is used to attach top-level event listeners. For 78539 * example: 78540 * 78541 * EventPluginHub.putListener('myID', 'onClick', myFunction); 78542 * 78543 * This would allocate a "registration" of `('onClick', myFunction)` on 'myID'. 78544 * 78545 * @internal 78546 */ 78547var ReactBrowserEventEmitter = _assign({}, ReactEventEmitterMixin, { 78548 78549 /** 78550 * Injectable event backend 78551 */ 78552 ReactEventListener: null, 78553 78554 injection: { 78555 /** 78556 * @param {object} ReactEventListener 78557 */ 78558 injectReactEventListener: function (ReactEventListener) { 78559 ReactEventListener.setHandleTopLevel(ReactBrowserEventEmitter.handleTopLevel); 78560 ReactBrowserEventEmitter.ReactEventListener = ReactEventListener; 78561 } 78562 }, 78563 78564 /** 78565 * Sets whether or not any created callbacks should be enabled. 78566 * 78567 * @param {boolean} enabled True if callbacks should be enabled. 78568 */ 78569 setEnabled: function (enabled) { 78570 if (ReactBrowserEventEmitter.ReactEventListener) { 78571 ReactBrowserEventEmitter.ReactEventListener.setEnabled(enabled); 78572 } 78573 }, 78574 78575 /** 78576 * @return {boolean} True if callbacks are enabled. 78577 */ 78578 isEnabled: function () { 78579 return !!(ReactBrowserEventEmitter.ReactEventListener && ReactBrowserEventEmitter.ReactEventListener.isEnabled()); 78580 }, 78581 78582 /** 78583 * We listen for bubbled touch events on the document object. 78584 * 78585 * Firefox v8.01 (and possibly others) exhibited strange behavior when 78586 * mounting `onmousemove` events at some node that was not the document 78587 * element. The symptoms were that if your mouse is not moving over something 78588 * contained within that mount point (for example on the background) the 78589 * top-level listeners for `onmousemove` won't be called. However, if you 78590 * register the `mousemove` on the document object, then it will of course 78591 * catch all `mousemove`s. This along with iOS quirks, justifies restricting 78592 * top-level listeners to the document object only, at least for these 78593 * movement types of events and possibly all events. 78594 * 78595 * @see http://www.quirksmode.org/blog/archives/2010/09/click_event_del.html 78596 * 78597 * Also, `keyup`/`keypress`/`keydown` do not bubble to the window on IE, but 78598 * they bubble to document. 78599 * 78600 * @param {string} registrationName Name of listener (e.g. `onClick`). 78601 * @param {object} contentDocumentHandle Document which owns the container 78602 */ 78603 listenTo: function (registrationName, contentDocumentHandle) { 78604 var mountAt = contentDocumentHandle; 78605 var isListening = getListeningForDocument(mountAt); 78606 var dependencies = EventPluginRegistry.registrationNameDependencies[registrationName]; 78607
78608 var topLevelTypes = EventConstants.topLevelTypes; 78609 for (var i = 0; i < dependencies.length; i++) { 78610 var dependency = dependencies[i]; 78611 if (!(isListening.hasOwnProperty(dependency) && isListening[dependency])) { 78612 if (dependency === topLevelTypes.topWheel) { 78613 if (isEventSupported('wheel')) { 78614 ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(topLevelTypes.topWheel, 'wheel', mountAt); 78615 } else if (isEventSupported('mousewheel')) { 78616 ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(topLevelTypes.topWheel, 'mousewheel', mountAt); 78617 } else { 78618 // Firefox needs to capture a different mouse scroll event. 78619 // @see http://www.quirksmode.org/dom/events/tests/scroll.html 78620 ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(topLevelTypes.topWheel, 'DOMMouseScroll', mountAt); 78621 } 78622 } else if (dependency === topLevelTypes.topScroll) { 78623 78624 if (isEventSupported('scroll', true)) { 78625 ReactBrowserEventEmitter.ReactEventListener.trapCapturedEvent(topLevelTypes.topScroll, 'scroll', mountAt); 78626 } else { 78627 ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(topLevelTypes.topScroll, 'scroll', ReactBrowserEventEmitter.ReactEventListener.WINDOW_HANDLE); 78628 } 78629 } else if (dependency === topLevelTypes.topFocus || dependency === topLevelTypes.topBlur) { 78630 78631 if (isEventSupported('focus', true)) { 78632 ReactBrowserEventEmitter.ReactEventListener.trapCapturedEvent(topLevelTypes.topFocus, 'focus', mountAt); 78633 ReactBrowserEventEmitter.ReactEventListener.trapCapturedEvent(topLevelTypes.topBlur, 'blur', mountAt); 78634 } else if (isEventSupported('focusin')) { 78635 // IE has `focusin` and `focusout` events which bubble. 78636 // @see http://www.quirksmode.org/blog/archives/2008/04/delegating_the.html 78637 ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(topLevelTypes.topFocus, 'focusin', mountAt); 78638 ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(topLevelTypes.topBlur, 'focusout', mountAt); 78639 } 78640 78641 // to make sure blur and focus event listeners are only attached once 78642 isListening[topLevelTypes.topBlur] = true; 78643 isListening[topLevelTypes.topFocus] = true; 78644 } else if (topEventMapping.hasOwnProperty(dependency)) { 78645 ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(dependency, topEventMapping[dependency], mountAt); 78646 } 78647 78648 isListening[dependency] = true; 78649 } 78650 } 78651 }, 78652 78653 trapBubbledEvent: function (topLevelType, handlerBaseName, handle) { 78654 return ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(topLevelType, handlerBaseName, handle); 78655 }, 78656 78657 trapCapturedEvent: function (topLevelType, handlerBaseName, handle) { 78658 return ReactBrowserEventEmitter.ReactEventListener.trapCapturedEvent(topLevelType, handlerBaseName, handle); 78659 }, 78660 78661 /** 78662 * Listens to window scroll and resize events. We cache scroll values so that 78663 * application code can access them without triggering reflows. 78664 * 78665 * ViewportMetrics is only used by SyntheticMouse/TouchEvent and only when 78666 * pageX/pageY isn't supported (legacy browsers). 78667 * 78668 * NOTE: Scroll events do not bubble. 78669 * 78670 * @see http://www.quirksmode.org/dom/events/scroll.html 78671 */ 78672 ensureScrollValueMonitoring: function () { 78673 if (hasEventPageXY === undefined) { 78674 hasEventPageXY = document.createEvent && 'pageX' in document.createEvent('MouseEvent'); 78675 } 78676 if (!hasEventPageXY && !isMonitoringScrollValue) { 78677 var refresh = ViewportMetrics.refreshScrollValues; 78678 ReactBrowserEventEmitter.ReactEventListener.monitorScrollValue(refresh); 78679 isMonitoringScrollValue = true; 78680 } 78681 } 78682 78683}); 78684 78685module.exports = ReactBrowserEventEmitter; 78686},{"113":113,"131":131,"133":133,"16":16,"169":169,"18":18,"66":66}],28:[function(_dereq_,module,exports){ 78687/** 78688 * Copyright 2014-present, Facebook, Inc. 78689 * All rights reserved. 78690 * 78691 * This source code is licensed under the BSD-style license found in the 78692 * LICENSE file in the root directory of this source tree. An additional grant 78693 * of patent rights can be found in the PATENTS file in the same directory. 78694 * 78695 * @providesModule ReactChildReconciler 78696 */ 78697 78698 78699 78700var ReactReconciler = _dereq_(87); 78701 78702var instantiateReactComponent = _dereq_(132); 78703var KeyEscapeUtils = _dereq_(23); 78704var shouldUpdateReactComponent = _dereq_(140); 78705var traverseAllChildren = _dereq_(141); 78706var warning = _dereq_(168); 78707 78708function instantiateChild(childInstances, child, name) { 78709 // We found a component instance. 78710 var keyUnique = childInstances[name] === undefined; 78711 if ("development" !== 'production') { 78712 "development" !== 'production' ? warning(keyUnique, 'flattenChildren(...): Encountered two children with the same key, ' + '`%s`. Child keys must be unique; when two children share a key, only ' + 'the first child will be used.', KeyEscapeUtils.unescape(name)) : void 0; 78713 } 78714 if (child != null && keyUnique) { 78715 childInstances[name] = instantiateReactComponent(child); 78716 } 78717} 78718 78719/** 78720 * ReactChildReconciler provides helpers for initializing or updating a set of 78721 * children. Its output is suitable for passing it onto ReactMultiChild which 78722 * does diffed reordering and insertion. 78723 */ 78724var ReactChildReconciler = { 78725 /** 78726 * Generates a "mount image" for each of the supplied children. In the case 78727 * of `ReactDOMComponent`, a mount image is a string of markup. 78728 * 78729 * @param {?object} nestedChildNodes Nested child maps. 78730 * @return {?object} A set of child instances. 78731 * @internal 78732 */ 78733 instantiateChildren: function (nestedChildNodes, transaction, context) { 78734 if (nestedChildNodes == null) { 78735 return null; 78736 } 78737 var childInstances = {}; 78738 traverseAllChildren(nestedChildNodes, instantiateChild, childInstances); 78739 return childInstances; 78740 }, 78741 78742 /** 78743 * Updates the rendered children and returns a new set of children. 78744 * 78745 * @param {?object} prevChildren Previously initialized set of children. 78746 * @param {?object} nextChildren Flat child element maps. 78747 * @param {ReactReconcileTransaction} transaction 78748 * @param {object} context 78749 * @return {?object} A new set of child instances. 78750 * @internal 78751 */ 78752 updateChildren: function (prevChildren, nextChildren, removedNodes, transaction, context) { 78753 // We currently don't have a way to track moves here but if we use iterators 78754 // instead of for..in we can zip the iterators and check if an item has 78755 // moved. 78756 // TODO: If nothing has changed, return the prevChildren object so that we 78757 // can quickly bailout if nothing has changed. 78758 if (!nextChildren && !prevChildren) { 78759 return; 78760 } 78761 var name; 78762 var prevChild; 78763 for (name in nextChildren) { 78764 if (!nextChildren.hasOwnProperty(name)) { 78765 continue; 78766 } 78767 prevChild = prevChildren && prevChildren[name]; 78768 var prevElement = prevChild && prevChild._currentElement; 78769 var nextElement = nextChildren[name]; 78770 if (prevChild != null && shouldUpdateReactComponent(prevElement, nextElement)) { 78771 ReactReconciler.receiveComponent(prevChild, nextElement, transaction, context); 78772 nextChildren[name] = prevChild; 78773 } else { 78774 if (prevChild) { 78775 removedNodes[name] = ReactReconciler.getNativeNode(prevChild); 78776 ReactReconciler.unmountComponent(prevChild, false); 78777 } 78778 // The child must be instantiated before it's mounted. 78779 var nextChildInstance = instantiateReactComponent(nextElement); 78780 nextChildren[name] = nextChildInstance; 78781 } 78782 } 78783 // Unmount children that are no longer present. 78784 for (name in prevChildren) { 78785 if (prevChildren.hasOwnProperty(name) && !(nextChildren && nextChildren.hasOwnProperty(name))) { 78786 prevChild = prevChildren[name]; 78787 removedNodes[name] = ReactReconciler.getNativeNode(prevChild); 78788 ReactReconciler.unmountComponent(prevChild, false); 78789 } 78790 } 78791 }, 78792 78793 /** 78794 * Unmounts all rendered children. This should be used to clean up children 78795 * when this component is unmounted. 78796 * 78797 * @param {?object} renderedChildren Previously initialized set of children. 78798 * @internal 78799 */ 78800 unmountChildren: function (renderedChildren, safely) { 78801 for (var name in renderedChildren) { 78802 if (renderedChildren.hasOwnProperty(name)) { 78803 var renderedChild = renderedChildren[name]; 78804 ReactReconciler.unmountComponent(renderedChild, safely); 78805 } 78806 } 78807 } 78808 78809}; 78810 78811module.exports = ReactChildReconciler; 78812},{"132":132,"140":140,"141":141,"168":168,"23":23,"87":87}],29:[function(_dereq_,module,exports){ 78813/** 78814 * Copyright 2013-present, Facebook, Inc. 78815 * All rights reserved. 78816 * 78817 * This source code is licensed under the BSD-style license found in the 78818 * LICENSE file in the root directory of this source tree. An additional grant 78819 * of patent rights can be found in the PATENTS file in the same directory. 78820 * 78821 * @providesModule ReactChildren 78822 */ 78823 78824 78825 78826var PooledClass = _dereq_(25); 78827var ReactElement = _dereq_(62); 78828 78829var emptyFunction = _dereq_(150); 78830var traverseAllChildren = _dereq_(141); 78831 78832var twoArgumentPooler = PooledClass.twoArgumentPooler; 78833var fourArgumentPooler = PooledClass.fourArgumentPooler; 78834 78835var userProvidedKeyEscapeRegex = /\/+/g; 78836function escapeUserProvidedKey(text) { 78837 return ('' + text).replace(userProvidedKeyEscapeRegex, '$&/'); 78838} 78839 78840/** 78841 * PooledClass representing the bookkeeping associated with performing a child 78842 * traversal. Allows avoiding binding callbacks. 78843 * 78844 * @constructor ForEachBookKeeping 78845 * @param {!function} forEachFunction Function to perform traversal with. 78846 * @param {?*} forEachContext Context to perform context with. 78847 */
78848function ForEachBookKeeping(forEachFunction, forEachContext) { 78849 this.func = forEachFunction; 78850 this.context = forEachContext; 78851 this.count = 0; 78852} 78853ForEachBookKeeping.prototype.destructor = function () { 78854 this.func = null; 78855 this.context = null; 78856 this.count = 0; 78857}; 78858PooledClass.addPoolingTo(ForEachBookKeeping, twoArgumentPooler); 78859 78860function forEachSingleChild(bookKeeping, child, name) { 78861 var func = bookKeeping.func; 78862 var context = bookKeeping.context; 78863 78864 func.call(context, child, bookKeeping.count++); 78865} 78866 78867/** 78868 * Iterates through children that are typically specified as `props.children`. 78869 * 78870 * The provided forEachFunc(child, index) will be called for each 78871 * leaf child. 78872 * 78873 * @param {?*} children Children tree container. 78874 * @param {function(*, int)} forEachFunc 78875 * @param {*} forEachContext Context for forEachContext. 78876 */ 78877function forEachChildren(children, forEachFunc, forEachContext) { 78878 if (children == null) { 78879 return children; 78880 } 78881 var traverseContext = ForEachBookKeeping.getPooled(forEachFunc, forEachContext); 78882 traverseAllChildren(children, forEachSingleChild, traverseContext); 78883 ForEachBookKeeping.release(traverseContext); 78884} 78885 78886/** 78887 * PooledClass representing the bookkeeping associated with performing a child 78888 * mapping. Allows avoiding binding callbacks. 78889 * 78890 * @constructor MapBookKeeping 78891 * @param {!*} mapResult Object containing the ordered map of results. 78892 * @param {!function} mapFunction Function to perform mapping with. 78893 * @param {?*} mapContext Context to perform mapping with. 78894 */ 78895function MapBookKeeping(mapResult, keyPrefix, mapFunction, mapContext) { 78896 this.result = mapResult; 78897 this.keyPrefix = keyPrefix; 78898 this.func = mapFunction; 78899 this.context = mapContext; 78900 this.count = 0; 78901} 78902MapBookKeeping.prototype.destructor = function () { 78903 this.result = null; 78904 this.keyPrefix = null; 78905 this.func = null; 78906 this.context = null; 78907 this.count = 0; 78908}; 78909PooledClass.addPoolingTo(MapBookKeeping, fourArgumentPooler); 78910 78911function mapSingleChildIntoContext(bookKeeping, child, childKey) { 78912 var result = bookKeeping.result; 78913 var keyPrefix = bookKeeping.keyPrefix; 78914 var func = bookKeeping.func; 78915 var context = bookKeeping.context; 78916 78917 78918 var mappedChild = func.call(context, child, bookKeeping.count++); 78919 if (Array.isArray(mappedChild)) { 78920 mapIntoWithKeyPrefixInternal(mappedChild, result, childKey, emptyFunction.thatReturnsArgument); 78921 } else if (mappedChild != null) { 78922 if (ReactElement.isValidElement(mappedChild)) { 78923 mappedChild = ReactElement.cloneAndReplaceKey(mappedChild, 78924 // Keep both the (mapped) and old keys if they differ, just as 78925 // traverseAllChildren used to do for objects as children 78926 keyPrefix + (mappedChild.key && (!child || child.key !== mappedChild.key) ? escapeUserProvidedKey(mappedChild.key) + '/' : '') + childKey); 78927 } 78928 result.push(mappedChild); 78929 } 78930} 78931 78932function mapIntoWithKeyPrefixInternal(children, array, prefix, func, context) { 78933 var escapedPrefix = ''; 78934 if (prefix != null) { 78935 escapedPrefix = escapeUserProvidedKey(prefix) + '/'; 78936 } 78937 var traverseContext = MapBookKeeping.getPooled(array, escapedPrefix, func, context); 78938 traverseAllChildren(children, mapSingleChildIntoContext, traverseContext); 78939 MapBookKeeping.release(traverseContext); 78940} 78941 78942/** 78943 * Maps children that are typically specified as `props.children`. 78944 * 78945 * The provided mapFunction(child, index) will be called for each 78946 * leaf child. 78947 * 78948 * @param {?*} children Children tree container. 78949 * @param {function(*, int)} func The map function. 78950 * @param {*} context Context for mapFunction. 78951 * @return {object} Object containing the ordered map of results. 78952 */ 78953function mapChildren(children, func, context) { 78954 if (children == null) { 78955 return children; 78956 } 78957 var result = []; 78958 mapIntoWithKeyPrefixInternal(children, result, null, func, context); 78959 return result; 78960} 78961 78962function forEachSingleChildDummy(traverseContext, child, name) { 78963 return null; 78964} 78965 78966/** 78967 * Count the number of children that are typically specified as 78968 * `props.children`. 78969 * 78970 * @param {?*} children Children tree container. 78971 * @return {number} The number of children. 78972 */ 78973function countChildren(children, context) {
78974 return traverseAllChildren(children, forEachSingleChildDummy, null); 78975} 78976 78977/** 78978 * Flatten a children object (typically specified as `props.children`) and 78979 * return an array with appropriately re-keyed children. 78980 */ 78981function toArray(children) { 78982 var result = []; 78983 mapIntoWithKeyPrefixInternal(children, result, null, emptyFunction.thatReturnsArgument); 78984 return result; 78985} 78986 78987var ReactChildren = { 78988 forEach: forEachChildren, 78989 map: mapChildren, 78990 mapIntoWithKeyPrefixInternal: mapIntoWithKeyPrefixInternal, 78991 count: countChildren, 78992 toArray: toArray 78993}; 78994 78995module.exports = ReactChildren; 78996},{"141":141,"150":150,"25":25,"62":62}],30:[function(_dereq_,module,exports){ 78997/** 78998 * Copyright 2013-present, Facebook, Inc. 78999 * All rights reserved. 79000 * 79001 * This source code is licensed under the BSD-style license found in the 79002 * LICENSE file in the root directory of this source tree. An additional grant 79003 * of patent rights can be found in the PATENTS file in the same directory. 79004 * 79005 * @providesModule ReactClass 79006 */ 79007 79008 79009 79010var _assign = _dereq_(169); 79011 79012var ReactComponent = _dereq_(31); 79013var ReactElement = _dereq_(62); 79014var ReactPropTypeLocations = _dereq_(84); 79015var ReactPropTypeLocationNames = _dereq_(83); 79016var ReactNoopUpdateQueue = _dereq_(80); 79017 79018var emptyObject = _dereq_(151); 79019var invariant = _dereq_(158); 79020var keyMirror = _dereq_(161); 79021var keyOf = _dereq_(162); 79022var warning = _dereq_(168); 79023 79024var MIXINS_KEY = keyOf({ mixins: null }); 79025 79026/** 79027 * Policies that describe methods in `ReactClassInterface`. 79028 */ 79029var SpecPolicy = keyMirror({ 79030 /** 79031 * These methods may be defined only once by the class specification or mixin. 79032 */ 79033 DEFINE_ONCE: null, 79034 /** 79035 * These methods may be defined by both the class specification and mixins. 79036 * Subsequent definitions will be chained. These methods must return void. 79037 */ 79038 DEFINE_MANY: null, 79039 /** 79040 * These methods are overriding the base class. 79041 */ 79042 OVERRIDE_BASE: null, 79043 /** 79044 * These methods are similar to DEFINE_MANY, except we assume they return 79045 * objects. We try to merge the keys of the return values of all the mixed in 79046 * functions. If there is a key conflict we throw. 79047 */ 79048 DEFINE_MANY_MERGED: null 79049}); 79050 79051var injectedMixins = []; 79052 79053/** 79054 * Composite components are higher-level components that compose other composite 79055 * or native components. 79056 * 79057 * To create a new type of `ReactClass`, pass a specification of 79058 * your new class to `React.createClass`. The only requirement of your class 79059 * specification is that you implement a `render` method. 79060 * 79061 * var MyComponent = React.createClass({ 79062 * render: function() { 79063 * return <div>Hello World</div>; 79064 * } 79065 * }); 79066 * 79067 * The class specification supports a specific protocol of methods that have 79068 * special meaning (e.g. `render`). See `ReactClassInterface` for 79069 * more the comprehensive protocol. Any other properties and methods in the 79070 * class specification will be available on the prototype. 79071 * 79072 * @interface ReactClassInterface 79073 * @internal 79074 */ 79075var ReactClassInterface = { 79076 79077 /** 79078 * An array of Mixin objects to include when defining your component. 79079 * 79080 * @type {array} 79081 * @optional 79082 */ 79083 mixins: SpecPolicy.DEFINE_MANY, 79084 79085 /** 79086 * An object containing properties and methods that should be defined on 79087 * the component's constructor instead of its prototype (static methods). 79088 * 79089 * @type {object} 79090 * @optional 79091 */ 79092 statics: SpecPolicy.DEFINE_MANY, 79093 79094 /** 79095 * Definition of prop types for this component. 79096 * 79097 * @type {object} 79098 * @optional 79099 */ 79100 propTypes: SpecPolicy.DEFINE_MANY, 79101 79102 /** 79103 * Definition of context types for this component. 79104 * 79105 * @type {object} 79106 * @optional 79107 */ 79108 contextTypes: SpecPolicy.DEFINE_MANY, 79109 79110 /** 79111 * Definition of context types this component sets for its children. 79112 * 79113 * @type {object} 79114 * @optional 79115 */ 79116 childContextTypes: SpecPolicy.DEFINE_MANY, 79117 79118 // ==== Definition methods ==== 79119 79120 /** 79121 * Invoked when the component is mounted. Values in the mapping will be set on 79122 * `this.props` if that prop is not specified (i.e. using an `in` check). 79123 * 79124 * This method is invoked before `getInitialState` and therefore cannot rely 79125 * on `this.state` or use `this.setState`. 79126 * 79127 * @return {object} 79128 * @optional 79129 */ 79130 getDefaultProps: SpecPolicy.DEFINE_MANY_MERGED, 79131 79132 /** 79133 * Invoked once before the component is mounted. The return value will be used 79134 * as the initial value of `this.state`. 79135 * 79136 * getInitialState: function() { 79137 * return { 79138 * isOn: false, 79139 * fooBaz: new BazFoo() 79140 * } 79141 * } 79142 * 79143 * @return {object} 79144 * @optional 79145 */ 79146 getInitialState: SpecPolicy.DEFINE_MANY_MERGED, 79147 79148 /** 79149 * @return {object} 79150 * @optional 79151 */ 79152 getChildContext: SpecPolicy.DEFINE_MANY_MERGED, 79153 79154 /** 79155 * Uses props from `this.props` and state from `this.state` to render the 79156 * structure of the component. 79157 * 79158 * No guarantees are made about when or how often this method is invoked, so 79159 * it must not have side effects. 79160 * 79161 * render: function() { 79162 * var name = this.props.name; 79163 * return <div>Hello, {name}!</div>; 79164 * } 79165 * 79166 * @return {ReactComponent} 79167 * @nosideeffects 79168 * @required 79169 */ 79170 render: SpecPolicy.DEFINE_ONCE, 79171 79172 // ==== Delegate methods ==== 79173 79174 /** 79175 * Invoked when the component is initially created and about to be mou
79175nted. 79176 * This may have side effects, but any external subscriptions or data created 79177 * by this method must be cleaned up in `componentWillUnmount`. 79178 * 79179 * @optional 79180 */ 79181 componentWillMount: SpecPolicy.DEFINE_MANY, 79182 79183 /** 79184 * Invoked when the component has been mounted and has a DOM representation. 79185 * However, there is no guarantee that the DOM node is in the document. 79186 * 79187 * Use this as an opportunity to operate on the DOM when the component has 79188 * been mounted (initialized and rendered) for the first time. 79189 * 79190 * @param {DOMElement} rootNode DOM element representing the component. 79191 * @optional 79192 */ 79193 componentDidMount: SpecPolicy.DEFINE_MANY, 79194 79195 /** 79196 * Invoked before the component receives new props. 79197 * 79198 * Use this as an opportunity to react to a prop transition by updating the 79199 * state using `this.setState`. Current props are accessed via `this.props`. 79200 * 79201 * componentWillReceiveProps: function(nextProps, nextContext) { 79202 * this.setState({ 79203 * likesIncreasing: nextProps.likeCount > this.props.likeCount 79204 * }); 79205 * } 79206 * 79207 * NOTE: There is no equivalent `componentWillReceiveState`. An incoming prop 79208 * transition may cause a state change, but the opposite is not true. If you 79209 * need it, you are probably looking for `componentWillUpdate`. 79210 * 79211 * @param {object} nextProps 79212 * @optional 79213 */ 79214 componentWillReceiveProps: SpecPolicy.DEFINE_MANY, 79215 79216 /** 79217 * Invoked while deciding if the component should be updated as a result of 79218 * receiving new props, state and/or context. 79219 * 79220 * Use this as an opportunity to `return false` when you're certain that the 79221 * transition to the new props/state/context will not require a component 79222 * update. 79223 * 79224 * shouldComponentUpdate: function(nextProps, nextState, nextContext) { 79225 * return !equal(nextProps, this.props) || 79226 * !equal(nextState, this.state) || 79227 * !equal(nextContext, this.context); 79228 * } 79229 * 79230 * @param {object} nextProps 79231 * @param {?object} nextState 79232 * @param {?object} nextContext 79233 * @return {boolean} True if the component should update. 79234 * @optional 79235 */ 79236 shouldComponentUpdate: SpecPolicy.DEFINE_ONCE, 79237 79238 /** 79239 * Invoked when the component is about to update due to a transition from 79240 * `this.props`, `this.state` and `this.context` to `nextProps`, `nextState` 79241 * and `nextContext`. 79242 * 79243 * Use this as an opportunity to perform preparation before an update occurs. 79244 * 79245 * NOTE: You **cannot** use `this.setState()` in this method. 79246 * 79247 * @param {object} nextProps 79248 * @param {?object} nextState 79249 * @param {?object} nextContext 79250 * @param {ReactReconcileTransaction} transaction 79251 * @optional 79252 */ 79253 componentWillUpdate: SpecPolicy.DEFINE_MANY, 79254 79255 /** 79256 * Invoked when the component's DOM representation has been updated. 79257 * 79258 * Use this as an opportunity to operate on the DOM when the component has 79259 * been updated. 79260 * 79261 * @param {object} prevProps 79262 * @param {?object} prevState 79263 * @param {?object} prevContext 79264 * @param {DOMElement} rootNode DOM element representing the component. 79265 * @optional 79266 */ 79267 componentDidUpdate: SpecPolicy.DEFINE_MANY, 79268 79269 /** 79270 * Invoked when the component is about to be removed from its parent and have 79271 * its DOM representation destroyed. 79272 * 79273 * Use this as an opportunity to deallocate any external resources. 79274 * 79275 * NOTE: There is no `componentDidUnmount` since your component will have been 79276 * destroyed by that point. 79277 * 79278 * @optional 79279 */ 79280 componentWillUnmount: SpecPolicy.DEFINE_MANY, 79281 79282 // ==== Advanced methods ==== 79283 79284 /** 79285 * Updates the component's currently mounted DOM representation. 79286 * 79287 * By default, this implements React's rendering and reconciliation algorithm. 79288 * Sophisticated clients may wish to override this. 79289 * 79290 * @param {ReactReconcileTransaction} transaction 79291 * @internal 79292 * @overridable 79293 */ 79294 updateComponent: SpecPolicy.OVERRIDE_BASE 79295 79296}; 79297 79298/** 79299 * Mapping from class specification keys to special processing functions. 79300 * 79301 * Although these are declared like instance properties in the specification 79302 * when defining classes using `React.createClass`, they are actually static 79303 * and are accessible on the constructor instead of the prototype. Despite 79304 * being static, they must be defined outside of the "statics" key under 79305 * which all other static methods are defined. 79306 */ 79307var RESERVED_SPEC_KEYS = { 79308 displayName: function (Constructor, displayName) { 79309 Constructor.displayName = displayName; 79310 }, 79311 mixins: function (Constructor, mixins) { 79312 if (mixins) { 79313 for (var i = 0; i < mixins.length; i++) { 79314 mixSpecIntoComponent(Constructor, mixins[i]); 79315 } 79316 } 79317 }, 79318 childContextTypes: function (Constructor, childContextTypes) { 79319 if ("development" !== 'production') { 79320 validateTypeDef(Constructor, childContextTypes, ReactPropTypeLocations.childContext); 79321 } 79322 Constructor.childContextTypes = _assign({}, Constructor.childContextTypes, childContextTypes); 79323 }, 79324 contextTypes: function (Constructor, contextTypes) { 79325 if ("development" !== 'production') { 79326 validateTypeDef(Constructor, contextTypes, ReactPropTypeLocations.context); 79327 } 79328 Constructor.contextTypes = _assign({}, Constructor.contextTypes, contextTypes); 79329 }, 79330 /** 79331 * Special case getDefaultProps which should move into statics but requires 79332 * automatic merging. 79333 */ 79334 getDefaultProps: function (Constructor, getDefaultProps) { 79335 if (Constructor.getDefaultProps) { 79336 Constructor.getDefaultProps = createMergedResultFunction(Constructor.getDefaultProps, getDefaultProps); 79337 } else { 79338 Constructor.getDefaultProps = getDefaultProps; 79339 } 79340 }, 79341 propTypes: function (Constructor, propTypes) { 79342 if ("development" !== 'production') { 79343 validateTypeDef(Constructor, propTypes, ReactPropTypeLocations.prop); 79344 } 79345 Constructor.propTypes = _assign({}, Constructor.propTypes, propTypes); 79346 }, 79347 statics: function (Constructor, statics) { 79348 mixStaticSpecIntoComponent(Constructor, statics); 79349 }, 79350 autobind: function () {} }; 79351 79352// noop 79353function validateTypeDef(Constructor, typeDef, location) { 79354 for (var propName in typeDef) { 79355 if (typeDef.hasOwnProperty(propName)) { 79356 // use a warning instead of an invariant so components 79357 // don't show up in prod but only in __DEV__ 79358 "development" !== 'production' ? warning(typeof typeDef[propName] === 'function', '%s: %s type `%s` is invali
79358d; it must be a function, usually from ' + 'React.PropTypes.', Constructor.displayName || 'ReactClass', ReactPropTypeLocationNames[location], propName) : void 0; 79359 } 79360 } 79361} 79362 79363function validateMethodOverride(isAlreadyDefined, name) { 79364 var specPolicy = ReactClassInterface.hasOwnProperty(name) ? ReactClassInterface[name] : null; 79365 79366 // Disallow overriding of base class methods unless explicitly allowed. 79367 if (ReactClassMixin.hasOwnProperty(name)) { 79368 !(specPolicy === SpecPolicy.OVERRIDE_BASE) ? "development" !== 'production' ? invariant(false, 'ReactClassInterface: You are attempting to override ' + '`%s` from your class specification. Ensure that your method names ' + 'do not overlap with React methods.', name) : invariant(false) : void 0; 79369 } 79370 79371 // Disallow defining methods more than once unless explicitly allowed. 79372 if (isAlreadyDefined) { 79373 !(specPolicy === SpecPolicy.DEFINE_MANY || specPolicy === SpecPolicy.DEFINE_MANY_MERGED) ? "development" !== 'production' ? invariant(false, 'ReactClassInterface: You are attempting to define ' + '`%s` on your component more than once. This conflict may be due ' + 'to a mixin.', name) : invariant(false) : void 0; 79374 } 79375} 79376 79377/** 79378 * Mixin helper which handles policy validation and reserved 79379 * specification keys when building React classes. 79380 */ 79381function mixSpecIntoComponent(Constructor, spec) { 79382 if (!spec) { 79383 return; 79384 } 79385 79386 !(typeof spec !== 'function') ? "development" !== 'production' ? invariant(false, 'ReactClass: You\'re attempting to ' + 'use a component class or function as a mixin. Instead, just use a ' + 'regular object.') : invariant(false) : void 0; 79387 !!ReactElement.isValidElement(spec) ? "development" !== 'production' ? invariant(false, 'ReactClass: You\'re attempting to ' + 'use a component as a mixin. Instead, just use a regular object.') : invariant(false) : void 0; 79388 79389 var proto = Constructor.prototype; 79390 var autoBindPairs = proto.__reactAutoBindPairs; 79391 79392 // By handling mixins before any other properties, we ensure the same 79393 // chaining order is applied to methods with DEFINE_MANY policy, whether 79394 // mixins are listed before or after these methods in the spec. 79395 if (spec.hasOwnProperty(MIXINS_KEY)) { 79396 RESERVED_SPEC_KEYS.mixins(Constructor, spec.mixins); 79397 } 79398 79399 for (var name in spec) { 79400 if (!spec.hasOwnProperty(name)) { 79401 continue; 79402 } 79403 79404 if (name === MIXINS_KEY) { 79405 // We have already handled mixins in a special case above. 79406 continue; 79407 } 79408 79409 var property = spec[name]; 79410 var isAlreadyDefined = proto.hasOwnProperty(name); 79411 validateMethodOverride(isAlreadyDefined, name); 79412 79413 if (RESERVED_SPEC_KEYS.hasOwnProperty(name)) { 79414 RESERVED_SPEC_KEYS[name](Constructor, property); 79415 } else { 79416 // Setup methods on prototype: 79417 // The following member methods should not be automatically bound: 79418 // 1. Expected ReactClass methods (in the "interface"). 79419 // 2. Overridden methods (that were mixed in). 79420 var isReactClassMethod = ReactClassInterface.hasOwnProperty(name); 79421 var isFunction = typeof property === 'function'; 79422 var shouldAutoBind = isFunction && !isReactClassMethod && !isAlreadyDefined && spec.autobind !== false; 79423 79424 if (shouldAutoBind) { 79425 autoBindPairs.push(name, property); 79426 proto[name] = property; 79427 } else { 79428 if (isAlreadyDefined) { 79429 var specPolicy = ReactClassInterface[name]; 79430 79431 // These cases should already be caught by validateMethodOverride. 79432 !(isReactClassMethod && (specPolicy === SpecPolicy.DEFINE_MANY_MERGED || specPolicy === SpecPolicy.DEFINE_MANY)) ? "development" !== 'production' ? invariant(false, 'ReactClass: Unexpected spec policy %s for key %s ' + 'when mixing in component specs.', specPolicy, name) : invariant(false) : void 0; 79433 79434 // For methods which are defined more than once, call the existing 79435 // methods before calling the new property, merging if appropriate. 79436 if (specPolicy === SpecPolicy.DEFINE_MANY_MERGED) { 79437 proto[name] = createMergedResultFunction(proto[name], property); 79438 } else if (specPolicy === SpecPolicy.DEFINE_MANY) { 79439 proto[name] = createChainedFunction(proto[name], property); 79440 } 79441 } else { 79442 proto[name] = property; 79443 if ("development" !== 'production') { 79444 // Add verbose displayName to the function, which helps when looking 79445 // at profiling tools. 79446 if (typeof property === 'function' && spec.displayName) { 79447 proto[name].displayName = spec.displayName + '_' + name; 79448 } 79449 } 79450 } 79451 } 79452 } 79453 } 79454} 79455 79456function mixStaticSpecIntoComponent(Constructor, statics) { 79457 if (!statics) { 79458 return; 79459 } 79460 for (var name in statics) { 79461 var property = statics[name]; 79462 if (!statics.hasOwnProperty(name)) { 79463 continue; 79464 } 79465 79466 var isReserved = name in RESERVED_SPEC_KEYS; 79467 !!isReserved ? "development" !== 'production' ? invariant(false, 'ReactClass: You are attempting to define a reserved ' + 'property, `%s`, that shouldn\'t be on the "statics" key. Define it ' + 'as an instance property instead; it will still be accessible on the ' + 'constructor.', name) : invariant(false) : void 0; 79468 79469 var isInherited = name in Constructor; 79470 !!isInherited ? "development" !== 'production' ? invariant(false, 'ReactClass: You are attempting to define ' + '`%s` on your component more than once. This conflict may be ' + 'due to a mixin.', name) : invariant(false) : void 0; 79471 Constructor[name] = property; 79472 } 79473} 79474 79475/** 79476 * Merge two objects, but throw if both contain the same key. 79477 * 79478 * @param {object} one The first object, which is mutated. 79479 * @param {object} two The second object 79480 * @return {object} one after it has been mutated to contain everything in two. 79481 */ 79482function mergeIntoWithNoDuplicateKeys(one, two) { 79483 !(one && two && typeof one === 'object' && typeof two === 'object') ? "development" !== 'production' ? invariant(false, 'mergeIntoWithNoDuplicateKeys(): Cannot merge non-objects.') : invariant(false) : void 0; 79484 79485 for (var key in two) { 79486 if (two.hasOwnProperty(key)) { 79487 !(one[key] === undefined) ? "development" !== 'production' ? invariant(false, 'mergeIntoWithNoDuplicateKeys(): ' + 'Tried to merge two objects with the same key: `%s`. This conflict ' + 'may be due to a mixin; in particular, this may be caused by two ' + 'getInitialState() or getDefaultProps() methods returning objects ' + 'with clashing keys.', key) : invariant(false) : void 0; 79488 one[key] = two[key]; 79489 } 79490 } 79491 return one; 79492} 79493 79494/** 79495 * Creates a function that invokes two functions and merges their return values. 79496 * 79497 * @param {function} one Function to invoke first. 79498 * @param {function} two Function to invoke second. 79499 * @return {function} Function that invokes the two argument functions. 79500 * @private 79501 */ 79502function createMergedResultFunction(one, two) { 79503 return function mergedResult() { 79504 var a = one.apply(this, arguments); 79505 var b = two.apply(this, arguments); 79506 if (a == null) { 79507 return b; 79508 } else if (b == null) { 79509 return a; 79510 } 79511 var c = {}; 79512 mergeIntoWithNoDuplicateKeys(c, a); 79513 mergeIntoWithNoDuplicateKeys(c, b); 79514 return c; 79515 }; 79516} 79517 79518/** 79519 * Creates a function that invokes two functions and ignores their return vales. 79520 * 79521 * @param {function} one Function to invoke first. 79522 * @param {function} two Function to invoke second. 79523 * @return {function} Function that invokes the two argument functions. 79524 * @private 79525 */ 79526function createChainedFunction(one, two) { 79527 return function chainedFunction() { 79528 one.apply(this, arguments); 79529 two.apply(this, arguments); 79530 }; 79531} 79532 79533/** 79534 * Binds a method to the component. 79535 * 79536 * @param {object} component Component whose method is going to be bound. 79537 * @param {function} method Method to be bound. 79538 * @return {function} The bound method. 79539 */ 79540function bindAutoBindMethod(component, method) { 79541 var boundMethod = method.bind(component); 79542 if ("development" !== 'production') { 79543 boundMethod.__reactBoundContext = component; 79544 boundMethod.__reactBoundMethod = method; 79545 boundMethod.__reactBoundArguments = null; 79546 var componentName = component.constructor.displayName; 79547 var _bind = boundMethod.bind; 79548 boundMethod.bind = function (newThis) { 79549 for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { 79550 args[_key - 1] = arguments[_key]; 79551 } 79552 79553 // User is trying to bind() an autobound method; we effectively will 79554 // ignore the value of "this" that the user is trying to use, so 79555 // let's warn. 79556 if (newThis !== component && newThis !== null) { 79557 "development" !== 'production' ? warning(false, 'bind(): React component methods may only be bound to the ' + 'component instance. See %s', componentName) : void 0; 79558 } else if (!args.length) { 79559 "development" !== 'production' ? warning(false, 'bind(): You are binding a component method to the component. ' + 'React does this for you automatically in a high-performance ' + 'way, so you can safely remove this call. See %s', componentName) : void 0; 79560 return boundMethod; 79561 } 79562 var reboundMethod = _bind.apply(boundMethod, arguments); 79563 reboundMethod.__reactBoundContext = component; 79564 reboundMethod.__reactBoundMethod = method; 79565 reboundMethod.__reactBoundArguments = args; 79566 return reboundMethod; 79567 }; 79568 } 79569 return boundMethod; 79570} 79571 79572/** 79573 * Binds all auto-bound methods in a component. 79574 * 79575 * @param {object} component Component whose method is going to be bound. 79576 */ 79577function bindAutoBindMethods(component) { 79578 var pairs = component.__reactAutoBindPairs; 79579 for (var i = 0; i < pairs.length; i += 2) { 79580 var autoBindKey = pairs[i]; 79581 var method = pairs[i + 1]; 79582 component[autoBindKey] = bindAutoBindMethod(component, method); 79583 } 79584} 79585 79586/** 79587 * Add more to the ReactClass base class. These are all legacy features and 79588 * therefore not already part of the modern ReactComponent. 79589 */ 79590var ReactClassMixin = { 79591 79592 /** 79593 * TODO: This will be deprecated because state should always keep a consistent 79594 * type signature and the only use case for this, is to avoid that. 79595 */ 79596 replaceState: function (newState, callback) { 79597 this.updater.enqueueReplaceState(this, newState); 79598 if (callback) { 79599 this.updater.enqueueCallback(this, callback, 'replaceState'); 79600 } 79601 }, 79602 79603 /** 79604 * Checks whether or not this composite component is mounted. 79605 * @return {boolean} True if mounted, false otherwise. 79606 * @protected 79607 * @final 79608 */ 79609 isMounted: function () { 79610 return this.updater.isMounted(this); 79611 } 79612}; 79613 79614var ReactClassComponent = function () {}; 79615_assign(ReactClassComponent.prototype, ReactComponent.prototype, ReactClassMixin); 79616 79617/** 79618 * Module for creating composite components. 79619 * 79620 * @class ReactClass 79621 */ 79622var ReactClass = { 79623 79624 /** 79625 * Creates a composite component class given a class specification. 79626 * 79627 * @param {object} spec Class specification (which must define `render`). 79628 * @return {function} Component constructor function. 79629 * @public 79630 */ 79631 createClass: function (spec) { 79632 var Constructor = function (props, context, updater) { 79633 // This constructor gets overridden by mocks. The argument is used 79634 // by mocks to assert on what gets mounted. 79635 79636 if ("development" !== 'production') { 79637 "development" !== 'production' ? warning(this instanceof Constructor, 'Something is calling a React component directly. Use a factory or ' + 'JSX instead. See: https://fb.me/react-legacyfactory') : void 0; 79638 } 79639
79640 // Wire up auto-binding 79641 if (this.__reactAutoBindPairs.length) { 79642 bindAutoBindMethods(this); 79643 } 79644 79645 this.props = props; 79646 this.context = context; 79647 this.refs = emptyObject; 79648 this.updater = updater || ReactNoopUpdateQueue; 79649 79650 this.state = null; 79651 79652 // ReactClasses doesn't have constructors. Instead, they use the 79653 // getInitialState and componentWillMount methods for initialization. 79654 79655 var initialState = this.getInitialState ? this.getInitialState() : null; 79656 if ("development" !== 'production') { 79657 // We allow auto-mocks to proceed as if they're returning null. 79658 if (initialState === undefined && this.getInitialState._isMockFunction) { 79659 // This is probably bad practice. Consider warning here and 79660 // deprecating this convenience. 79661 initialState = null; 79662 } 79663 } 79664 !(typeof initialState === 'object' && !Array.isArray(initialState)) ? "development" !== 'production' ? invariant(false, '%s.getInitialState(): must return an object or null', Constructor.displayName || 'ReactCompositeComponent') : invariant(false) : void 0; 79665 79666 this.state = initialState; 79667 }; 79668 Constructor.prototype = new ReactClassComponent(); 79669 Constructor.prototype.constructor = Constructor; 79670 Constructor.prototype.__reactAutoBindPairs = []; 79671 79672 injectedMixins.forEach(mixSpecIntoComponent.bind(null, Constructor)); 79673 79674 mixSpecIntoComponent(Constructor, spec); 79675 79676 // Initialize the defaultProps property after all mixins have been merged. 79677 if (Constructor.getDefaultProps) { 79678 Constructor.defaultProps = Constructor.getDefaultProps(); 79679 } 79680 79681 if ("development" !== 'production') { 79682 // This is a tag to indicate that the use of these method names is ok, 79683 // since it's used with createClass. If it's not, then it's likely a 79684 // mistake so we'll warn you to use the static property, property 79685 // initializer or constructor respectively. 79686 if (Constructor.getDefaultProps) { 79687 Constructor.getDefaultProps.isReactClassApproved = {}; 79688 } 79689 if (Constructor.prototype.getInitialState) { 79690 Constructor.prototype.getInitialState.isReactClassApproved = {}; 79691 } 79692 } 79693 79694 !Constructor.prototype.render ? "development" !== 'production' ? invariant(false, 'createClass(...): Class specification must implement a `render` method.') : invariant(false) : void 0; 79695 79696 if ("development" !== 'production') { 79697 "development" !== 'production' ? warning(!Constructor.prototype.componentShouldUpdate, '%s has a method called ' + 'componentShouldUpdate(). Did you mean shouldComponentUpdate()? ' + 'The name is phrased as a question because the function is ' + 'expected to return a value.', spec.displayName || 'A component') : void 0; 79698 "development" !== 'production' ? warning(!Constructor.prototype.componentWillRecieveProps, '%s has a method called ' + 'componentWillRecieveProps(). Did you mean componentWillReceiveProps()?', spec.displayName || 'A component') : void 0; 79699 } 79700 79701 // Reduce time spent doing lookups by setting these on the prototype. 79702 for (var methodName in ReactClassInterface) { 79703 if (!Constructor.prototype[methodName]) { 79704 Constructor.prototype[methodName] = null; 79705 } 79706 } 79707 79708 return Constructor; 79709 }, 79710 79711 injection: { 79712 injectMixin: function (mixin) { 79713 injectedMixins.push(mixin); 79714 } 79715 } 79716 79717}; 79718 79719module.exports = ReactClass; 79720},{"151":151,"158":158,"161":161,"162":162,"168":168,"169":169,"31":31,"62":62,"80":80,"83":83,"84":84}],31:[function(_dereq_,module,exports){ 79721/** 79722 * Copyright 2013-present, Facebook, Inc. 79723 * All rights reserved. 79724 * 79725 * This source code is licensed under the BSD-style license found in the 79726 * LICENSE file in the root directory of this source tree. An additional grant 79727 * of patent rights can be found in the PATENTS file in the same directory. 79728 * 79729 * @providesModule ReactComponent 79730 */ 79731 79732 79733 79734var ReactNoopUpdateQueue = _dereq_(80); 79735var ReactInstrumentation = _dereq_(72); 79736 79737var canDefineProperty = _dereq_(116); 79738var emptyObject = _dereq_(151); 79739var invariant = _dereq_(158); 79740var warning = _dereq_(168); 79741 79742/** 79743 * Base class helpers for the updating state of a component. 79744 */ 79745function ReactComponent(props, context, updater) { 79746 this.props = props; 79747 this.context = context; 79748 this.refs = emptyObject; 79749 // We initialize the default updater but the real one gets injected by the 79750 // renderer. 79751 this.updater = updater || ReactNoopUpdateQueue; 79752} 79753 79754ReactComponent.prototype.isReactComponent = {}; 79755 79756/** 79757 * Sets a subset of the state. Always use this to mutate 79758 * state. You should treat `this.state` as immutable. 79759 * 79760 * There is no guarantee that `this.state` will be immediately updated, so 79761 * accessing `this.state` after calling this method may return the old value. 79762 * 79763 * There is no guarantee that calls to `setState` will run synchronously, 79764 * as they may eventually be batched together. You can provide an optional 79765 * callback that will be executed when the call to setState is actually 79766 * completed. 79767 * 79768 * When a function is provided to setState, it will be called at some point in 79769 * the future (not synchronously). It will be called with the up to date 79770 * component arguments (state, props, context). These values can be different 79771 * from this.* because your function may be called after receiveProps but before 79772 * shouldComponentUpdate, and this new state, props, and context will not yet be 79773 * assigned to this. 79774 * 79775 * @param {object|function} partialState Next partial state or function to 79776 * produce next partial state to be merged with current state. 79777 * @param {?function} callback Called after state is updated. 79778 * @final 79779 * @protected 79780 */ 79781ReactComponent.prototype.setState = function (partialState, callback) { 79782 !(typeof partialState === 'object' || typeof partialState === 'function' || partialState == null) ? "development" !== 'production' ? invariant(false, 'setState(...): takes an object of state variables to update or a ' + 'function which returns an object of state variables.') : invariant(false) : void 0; 79783 if ("development" !== 'production') { 79784 ReactInstrumentation.debugTool.onSetState(); 79785 "development" !== 'production' ? warning(partialState != null, 'setState(...): You passed an undefined or null state object; ' + 'instead, use forceUpdate().') : void 0; 79786 } 79787 this.updater.enqueueSetState(this, partialState); 79788 if (callback) { 79789 this.updater.enqueueCallback(this, callback, 'setState'); 79790 } 79791}; 79792 79793/** 79794 * Forces an update. This should only be invoked when it is known with 79795 * certainty that we are **not** in a DOM transaction. 79796 * 79797 * You may want to call this when you know that some deeper aspect of the 79798 * component's state has changed but `setState` was not called. 79799 * 79800 * This will not invoke `shouldComponentUpdate`, but it will invoke 79801 * `componentWillUpdate` and `componentDidUpdate`. 79802 * 79803 * @param {?function} callback Called after update is complete. 79804 * @final 79805 * @protected 79806 */ 79807ReactComponent.prototype.forceUpdate = function (callback) { 79808 this.updater.enqueueForceUpdate(this); 79809 if (callback) { 79810 this.updater.enqueueCallback(this, callback, 'forceUpdate'); 79811 } 79812}; 79813 79814/** 79815 * Deprecated APIs. These APIs used to exist on classic React classes but since 79816 * we would like to deprecate them, we're not going to move them over to this 79817 * modern base class. Instead, we define a getter that warns if it's accessed. 79818 */ 79819if ("development" !== 'production') { 79820 var deprecatedAPIs = { 79821 isMounted: ['isMounted', 'Instead, make sure to clean up subscriptions and pending requests in ' + 'componentWillUnmount to prevent memory leaks.'],
79822 replaceState: ['replaceState', 'Refactor your code to use setState instead (see ' + 'https://github.com/facebook/react/issues/3236).'] 79823 }; 79824 var defineDeprecationWarning = function (methodName, info) { 79825 if (canDefineProperty) { 79826 Object.defineProperty(ReactComponent.prototype, methodName, { 79827 get: function () { 79828 "development" !== 'production' ? warning(false, '%s(...) is deprecated in plain JavaScript React classes. %s', info[0], info[1]) : void 0; 79829 return undefined; 79830 } 79831 }); 79832 } 79833 }; 79834 for (var fnName in deprecatedAPIs) { 79835 if (deprecatedAPIs.hasOwnProperty(fnName)) { 79836 defineDeprecationWarning(fnName, deprecatedAPIs[fnName]); 79837 } 79838 } 79839} 79840 79841module.exports = ReactComponent; 79842},{"116":116,"151":151,"158":158,"168":168,"72":72,"80":80}],32:[function(_dereq_,module,exports){ 79843/** 79844 * Copyright 2013-present, Facebook, Inc. 79845 * All rights reserved. 79846 * 79847 * This source code is licensed under the BSD-style license found in the 79848 * LICENSE file in the root directory of this source tree. An additional grant 79849 * of patent rights can be found in the PATENTS file in the same directory. 79850 * 79851 * @providesModule ReactComponentBrowserEnvironment 79852 */ 79853 79854 79855 79856var DOMChildrenOperations = _dereq_(7); 79857var ReactDOMIDOperations = _dereq_(46); 79858var ReactPerf = _dereq_(82); 79859 79860/** 79861 * Abstracts away all functionality of the reconciler that requires knowledge of 79862 * the browser context. TODO: These callers should be refactored to avoid the 79863 * need for this injection. 79864 */ 79865var ReactComponentBrowserEnvironment = { 79866 79867 processChildrenUpdates: ReactDOMIDOperations.dangerouslyProcessChildrenUpdates, 79868 79869 replaceNodeWithMarkup: DOMChildrenOperations.dangerouslyReplaceNodeWithMarkup, 79870 79871 /** 79872 * If a particular environment requires that some resources be cleaned up, 79873 * specify this in the injected Mixin. In the DOM, we would likely want to 79874 * purge any cached node ID lookups. 79875 * 79876 * @private 79877 */ 79878 unmountIDFromEnvironment: function (rootNodeID) {} 79879 79880}; 79881 79882ReactPerf.measureMethods(ReactComponentBrowserEnvironment, 'ReactComponentBrowserEnvironment', { 79883 replaceNodeWithMarkup: 'replaceNodeWithMarkup' 79884}); 79885 79886module.exports = ReactComponentBrowserEnvironment; 79887},{"46":46,"7":7,"82":82}],33:[function(_dereq_,module,exports){ 79888/** 79889 * Copyright 2014-present, Facebook, Inc. 79890 * All rights reserved. 79891 * 79892 * This source code is licensed under the BSD-style license found in the 79893 * LICENSE file in the root directory of this source tree. An additional grant 79894 * of patent rights can be found in the PATENTS file in the same directory. 79895 * 79896 * @providesModule ReactComponentEnvironment 79897 */ 79898 79899 79900 79901var invariant = _dereq_(158); 79902 79903var injected = false; 79904 79905var ReactComponentEnvironment = { 79906 79907 /** 79908 * Optionally injectable environment dependent cleanup hook. (server vs. 79909 * browser etc). Example: A browser system caches DOM nodes based on component 79910 * ID and must remove that cache entry when this instance is unmounted. 79911 */ 79912 unmountIDFromEnvironment: null, 79913 79914 /** 79915 * Optionally injectable hook for swapping out mount images in the middle of 79916 * the tree. 79917 */ 79918 replaceNodeWithMarkup: null, 79919 79920 /** 79921 * Optionally injectable hook for processing a queue of child updates. Will 79922 * later move into MultiChildComponents. 79923 */ 79924 processChildrenUpdates: null, 79925 79926 injection: { 79927 injectEnvironment: function (environment) { 79928 !!injected ? "development" !== 'production' ? invariant(false, 'ReactCompositeComponent: injectEnvironment() can only be called once.') : invariant(false) : void 0; 79929 ReactComponentEnvironment.unmountIDFromEnvironment = environment.unmountIDFromEnvironment; 79930 ReactComponentEnvironment.replaceNodeWithMarkup = environment.replaceNodeWithMarkup; 79931 ReactComponentEnvironment.processChildrenUpdates = environment.processChildrenUpdates; 79932 injected = true; 79933 } 79934 } 79935 79936}; 79937 79938module.exports = ReactComponentEnvironment; 79939},{"158":158}],34:[function(_dereq_,module,exports){ 79940/** 79941 * Copyright 2013-present, Facebook, Inc. 79942 * All rights reserved. 79943 * 79944 * This source code is licensed under the BSD-style license found in the 79945 * LICENSE file in the root directory of this source tree. An additional grant 79946 * of patent rights can be found in the PATENTS file in the same directory. 79947 * 79948 * @providesModule ReactCompositeComponent 79949 */ 79950 79951 79952 79953var _assign = _dereq_(169); 79954 79955var ReactComponentEnvironment = _dereq_(33); 79956var ReactCurrentOwner = _dereq_(35); 79957var ReactElement = _dereq_(62);
79958var ReactErrorUtils = _dereq_(65); 79959var ReactInstanceMap = _dereq_(71); 79960var ReactInstrumentation = _dereq_(72); 79961var ReactNodeTypes = _dereq_(79); 79962var ReactPerf = _dereq_(82); 79963var ReactPropTypeLocations = _dereq_(84); 79964var ReactPropTypeLocationNames = _dereq_(83); 79965var ReactReconciler = _dereq_(87); 79966var ReactUpdateQueue = _dereq_(93); 79967 79968var emptyObject = _dereq_(151); 79969var invariant = _dereq_(158); 79970var shouldUpdateReactComponent = _dereq_(140); 79971var warning = _dereq_(168); 79972 79973function getDeclarationErrorAddendum(component) { 79974 var owner = component._currentElement._owner || null; 79975 if (owner) { 79976 var name = owner.getName(); 79977 if (name) { 79978 return ' Check the render method of `' + name + '`.'; 79979 } 79980 } 79981 return ''; 79982} 79983 79984function StatelessComponent(Component) {} 79985StatelessComponent.prototype.render = function () { 79986 var Component = ReactInstanceMap.get(this)._currentElement.type; 79987 var element = Component(this.props, this.context, this.updater); 79988 warnIfInvalidElement(Component, element); 79989 return element; 79990}; 79991 79992function warnIfInvalidElement(Component, element) { 79993 if ("development" !== 'production') { 79994 "development" !== 'production' ? warning(element === null || element === false || ReactElement.isValidElement(element), '%s(...): A val
79994id React element (or null) must be returned. You may have ' + 'returned undefined, an array or some other invalid object.', Component.displayName || Component.name || 'Component') : void 0; 79995 } 79996} 79997 79998function shouldConstruct(Component) { 79999 return Component.prototype && Component.prototype.isReactComponent; 80000} 80001 80002/** 80003 * ------------------ The Life-Cycle of a Composite Component ------------------ 80004 * 80005 * - constructor: Initialization of state. The instance is now retained. 80006 * - componentWillMount 80007 * - render 80008 * - [children's constructors] 80009 * - [children's componentWillMount and render] 80010 * - [children's componentDidMount] 80011 * - componentDidMount 80012 * 80013 * Update Phases: 80014 * - componentWillReceiveProps (only called if parent updated) 80015 * - shouldComponentUpdate 80016 * - componentWillUpdate 80017 * - render 80018 * - [children's constructors or receive props phases] 80019 * - componentDidUpdate 80020 * 80021 * - componentWillUnmount 80022 * - [children's componentWillUnmount] 80023 * - [children destroyed] 80024 * - (destroyed): The instance is now blank, released by React and ready for GC. 80025 * 80026 * ----------------------------------------------------------------------------- 80027 */ 80028 80029/** 80030 * An incrementing ID assigned to each component when it is mounted. This is 80031 * used to enforce the order in which `ReactUpdates` updates dirty components. 80032 * 80033 * @private 80034 */ 80035var nextMountID = 1; 80036 80037/** 80038 * @lends {ReactCompositeComponent.prototype} 80039 */ 80040var ReactCompositeComponentMixin = { 80041 80042 /** 80043 * Base constructor for all composite component. 80044 * 80045 * @param {ReactElement} element 80046 * @final 80047 * @internal 80048 */ 80049 construct: function (element) { 80050 this._currentElement = element; 80051 this._rootNodeID = null; 80052 this._instance = null; 80053 this._nativeParent = null; 80054 this._nativeContainerInfo = null; 80055 80056 // See ReactUpdateQueue 80057 this._pendingElement = null; 80058 this._pendingStateQueue = null; 80059 this._pendingReplaceState = false; 80060 this._pendingForceUpdate = false; 80061 80062 this._renderedNodeType = null; 80063 this._renderedComponent = null; 80064 this._context = null; 80065 this._mountOrder = 0; 80066 this._topLevelWrapper = null; 80067 80068 // See ReactUpdates and ReactUpdateQueue. 80069 this._pendingCallbacks = null; 80070 80071 // ComponentWillUnmount shall only be called once 80072 this._calledComponentWillUnmount = false; 80073 }, 80074 80075 /** 80076 * Initializes the component, renders markup, and registers event listeners. 80077 * 80078 * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction 80079 * @param {?object} nativeParent 80080 * @param {?object} nativeContainerInfo 80081 * @param {?object} context 80082 * @return {?string} Rendered markup to be inserted into the DOM. 80083 * @final 80084 * @internal 80085 */ 80086 mountComponent: function (transaction, nativeParent, nativeContainerInfo, context) { 80087 this._context = context; 80088 this._mountOrder = nextMountID++; 80089 this._nativeParent = nativeParent; 80090 this._nativeContainerInfo = nativeContainerInfo; 80091 80092 var publicProps = this._processProps(this._currentElement.props); 80093 var publicContext = this._processContext(context); 80094 80095 var Component = this._currentElement.type; 80096 80097 // Initialize the public class 80098 var inst = this._constructComponent(publicProps, publicContext); 80099 var renderedElement; 80100 80101 // Support functional components 80102 if (!shouldConstruct(Component) && (inst == null || inst.render == null)) { 80103 renderedElement = inst; 80104 warnIfInvalidElement(Component, renderedElement); 80105 !(inst === null || inst === false || ReactElement.isValidElement(inst)) ? "development" !== 'production' ? invariant(false, '%s(...): A val
80105id React element (or null) must be returned. You may have ' + 'returned undefined, an array or some other invalid object.', Component.displayName || Component.name || 'Component') : invariant(false) : void 0; 80106 inst = new StatelessComponent(Component); 80107 } 80108 80109 if ("development" !== 'production') { 80110 // This will throw later in _renderValidatedComponent, but add an early 80111 // warning now to help debugging 80112 if (inst.render == null) { 80113 "development" !== 'production' ? warning(false, '%s(...): No `render` method found on the returned component ' + 'instance: you may have forgotten to define `render`.', Component.displayName || Component.name || 'Component') : void 0; 80114 } 80115 80116 var propsMutated = inst.props !== publicProps; 80117 var componentName = Component.displayName || Component.name || 'Component'; 80118 80119 "development" !== 'production' ? warning(inst.props === undefined || !propsMutated, '%s(...): When calling super() in `%s`, make sure to pass ' + 'up the same props that your component\'s constructor was passed.', componentName, componentName) : void 0; 80120 } 80121 80122 // These should be set up in the constructor, but as a convenience for 80123 // simpler class abstractions, we set them up after the fact. 80124 inst.props = publicProps; 80125 inst.context = publicContext; 80126 inst.refs = emptyObject; 80127 inst.updater = ReactUpdateQueue; 80128 80129 this._instance = inst; 80130 80131 // Store a reference from the instance back to the internal representation 80132 ReactInstanceMap.set(inst, this); 80133 80134 if ("development" !== 'production') { 80135 // Since plain JS classes are defined without any special initialization 80136 // logic, we can not catch common errors early. Therefore, we have to 80137 // catch them here, at initialization time, instead. 80138 "development" !== 'production' ? warning(!inst.getInitialState || inst.getInitialState.isReactClassApproved, 'getInitialState was defined on %s, a plain JavaScript class. ' + 'This is only supported for classes created using React.createClass. ' + 'Did you mean to define a state property instead?', this.getName() || 'a component') : void 0; 80139 "development" !== 'production' ? warning(!inst.getDefaultProps || inst.getDefaultProps.isReactClassApproved, 'getDefaultProps was defined on %s, a plain JavaScript class. ' + 'This is only supported for classes created using React.createClass. ' + 'Use a static property to define defaultProps instead.', this.getName() || 'a component') : void 0; 80140 "development" !== 'production' ? warning(!inst.propTypes, 'propTypes was defined as an instance property on %s. Use a static ' + 'property to define propTypes instead.', this.getName() || 'a component') : void 0; 80141 "development" !== 'production' ? warning(!inst.contextTypes, 'contextTypes was defined as an instance property on %s. Use a ' + 'static property to define contextTypes instead.', this.getName() || 'a component') : void 0; 80142 "development" !== 'production' ? warning(typeof inst.componentShouldUpdate !== 'function', '%s has a method called ' + 'componentShouldUpdate(). Did you mean shouldComponentUpdate()? ' + 'The name is phrased as a question because the function is ' + 'expected to return a value.', this.getName() || 'A c
80142omponent') : void 0; 80143 "development" !== 'production' ? warning(typeof inst.componentDidUnmount !== 'function', '%s has a method called ' + 'componentDidUnmount(). But there is no such lifecycle method. ' + 'Did you mean componentWillUnmount()?', this.getName() || 'A component') : void 0; 80144 "development" !== 'production' ? warning(typeof inst.componentWillRecieveProps !== 'function', '%s has a method called ' + 'componentWillRecieveProps(). Did you mean componentWillReceiveProps()?', this.getName() || 'A component') : void 0; 80145 } 80146 80147 var initialState = inst.state; 80148 if (initialState === undefined) { 80149 inst.state = initialState = null; 80150 } 80151 !(typeof initialState === 'object' && !Array.isArray(initialState)) ? "development" !== 'production' ? invariant(false, '%s.state: must be set to an object or null', this.getName() || 'ReactCompositeComponent') : invariant(false) : void 0; 80152 80153 this._pendingStateQueue = null; 80154 this._pendingReplaceState = false; 80155 this._pendingForceUpdate = false; 80156 80157 var markup; 80158 if (inst.unstable_handleError) { 80159 markup = this.performInitialMountWithErrorHandling(renderedElement, nativeParent, nativeContainerInfo, transaction, context); 80160 } else { 80161 markup = this.performInitialMount(renderedElement, nativeParent, nativeContainerInfo, transaction, context); 80162 } 80163 80164 if (inst.componentDidMount) { 80165 transaction.getReactMountReady().enqueue(inst.componentDidMount, inst); 80166 } 80167 80168 return markup; 80169 }, 80170 80171 _constructComponent: function (publicProps, publicContext) { 80172 if ("development" !== 'production') { 80173 ReactCurrentOwner.current = this; 80174 try { 80175 return this._constructComponentWithoutOwner(publicProps, publicContext); 80176 } finally { 80177 ReactCurrentOwner.current = null; 80178 } 80179 } else { 80180 return this._constructComponentWithoutOwner(publicProps, publicContext); 80181 } 80182 }, 80183 80184 _constructComponentWithoutOwner: function (publicProps, publicContext) { 80185 var Component = this._currentElement.type; 80186 if (shouldConstruct(Component)) { 80187 return new Component(publicProps, publicContext, ReactUpdateQueue); 80188 } else { 80189 return Component(publicProps, publicContext, ReactUpdateQueue); 80190 } 80191 }, 80192 80193 performInitialMountWithErrorHandling: function (renderedElement, nativeParent, nativeContainerInfo, transaction, context) { 80194 var markup; 80195 var checkpoint = transaction.checkpoint(); 80196 try { 80197 markup = this.performInitialMount(renderedElement, nativeParent, nativeContainerInfo, transaction, context); 80198 } catch (e) { 80199 // Roll back to checkpoint, handle error (which may add items to the transaction), and take a new checkpoint 80200 transaction.rollback(checkpoint); 80201 this._instance.unstable_handleError(e); 80202 if (this._pendingStateQueue) { 80203 this._instance.state = this._processPendingState(this._instance.props, this._instance.context); 80204 } 80205 checkpoint = transaction.checkpoint(); 80206 80207 this._renderedComponent.unmountComponent(true); 80208 transaction.rollback(checkpoint); 80209 80210 // Try again - we've informed the component about the error, so they can render an error message this time. 80211 // If this throws again, the error will bubble up (and can be caught by a higher error boundary). 80212 markup = this.performInitialMount(renderedElement, nativeParent, nativeContainerInfo, transaction, context); 80213 } 80214 return markup; 80215 }, 80216 80217 performInitialMount: function (renderedElement, nativeParent, nativeContainerInfo, transaction, context) { 80218 var inst = this._instance; 80219 if (inst.componentWillMount) { 80220 inst.componentWillMount(); 80221 // When mounting, calls to `setState` by `componentWillMount` will set 80222 // `this._pendingStateQueue` without triggering a re-render. 80223 if (this._pendingStateQueue) { 80224 inst.state = this._processPendingState(inst.props, inst.context); 80225 } 80226 } 80227 80228 // If not a stateless component, we now render 80229 if (renderedElement === undefined) { 80230 renderedElement = this._renderValidatedComponent(); 80231 } 80232 80233 this._renderedNodeType = ReactNodeTypes.getType(renderedElement); 80234 this._renderedComponent = this._instantiateReactComponent(renderedElement); 80235 80236 var markup = ReactReconciler.mountComponent(this._renderedComponent, transaction, nativeParent, nativeContainerInfo, this._processChildContext(context)); 80237 80238 return markup; 80239 }, 80240 80241 getNativeNode: function () { 80242 return ReactReconciler.getNativeNode(this._renderedComponent); 80243 }, 80244 80245 /** 80246 * Releases any resources allocated by `mountComponent`. 80247 * 80248 * @final 80249 * @internal 80250 */ 80251 unmountComponent: function (safely) { 80252 if (!this._renderedComponent) { 80253 return; 80254 } 80255 var inst = this._instance; 80256 80257 if (inst.componentWillUnmount && !inst._calledComponentWillUnmount) { 80258 inst._calledComponentWillUnmount = true; 80259 if (safely) { 80260 var name = this.getName() + '.componentWillUnmount()'; 80261 ReactErrorUtils.invokeGuardedCallback(name, inst.componentWillUnmount.bind(inst)); 80262 } else { 80263 inst.componentWillUnmount(); 80264 } 80265 } 80266 80267 if (this._renderedComponent) { 80268 ReactReconciler.unmountComponent(this._renderedComponent, safely); 80269 this._renderedNodeType = null; 80270 this._renderedComponent = null; 80271 this._instance = null; 80272 } 80273 80274 // Reset pending fields 80275 // Even if this component is scheduled for another update in ReactUpdates, 80276 // it would still be ignored because these fields are reset. 80277 this._pendingStateQueue = null; 80278 this._pendingReplaceState = false;
80279 this._pendingForceUpdate = false; 80280 this._pendingCallbacks = null; 80281 this._pendingElement = null; 80282 80283 // These fields do not really need to be reset since this object is no 80284 // longer accessible. 80285 this._context = null; 80286 this._rootNodeID = null; 80287 this._topLevelWrapper = null; 80288 80289 // Delete the reference from the instance to this internal representation 80290 // which allow the internals to be properly cleaned up even if the user 80291 // leaks a reference to the public instance. 80292 ReactInstanceMap.remove(inst); 80293 80294 // Some existing components rely on inst.props even after they've been 80295 // destroyed (in event handlers). 80296 // TODO: inst.props = null; 80297 // TODO: inst.state = null; 80298 // TODO: inst.context = null; 80299 }, 80300 80301 /** 80302 * Filters the context object to only contain keys specified in 80303 * `contextTypes` 80304 * 80305 * @param {object} context 80306 * @return {?object} 80307 * @private 80308 */ 80309 _maskContext: function (context) { 80310 var Component = this._currentElement.type; 80311 var contextTypes = Component.contextTypes; 80312 if (!contextTypes) { 80313 return emptyObject; 80314 } 80315 var maskedContext = {}; 80316 for (var contextName in contextTypes) { 80317 maskedContext[contextName] = context[contextName]; 80318 } 80319 return maskedContext; 80320 }, 80321 80322 /** 80323 * Filters the context object to only contain keys specified in 80324 * `contextTypes`, and asserts that they are valid. 80325 * 80326 * @param {object} context 80327 * @return {?object} 80328 * @private 80329 */ 80330 _processContext: function (context) { 80331 var maskedContext = this._maskContext(context); 80332 if ("development" !== 'production') { 80333 var Component = this._currentElement.type; 80334 if (Component.contextTypes) { 80335 this._checkPropTypes(Component.contextTypes, maskedContext, ReactPropTypeLocations.context); 80336 } 80337 } 80338 return maskedContext; 80339 }, 80340 80341 /** 80342 * @param {object} currentContext 80343 * @return {object} 80344 * @private 80345 */ 80346 _processChildContext: function (currentContext) { 80347 var Component = this._currentElement.type; 80348 var inst = this._instance; 80349 if ("development" !== 'production') { 80350 ReactInstrumentation.debugTool.onBeginProcessingChildContext(); 80351 } 80352 var childContext = inst.getChildContext && inst.getChildContext(); 80353 if ("development" !== 'production') { 80354 ReactInstrumentation.debugTool.onEndProcessingChildContext(); 80355 } 80356 if (childContext) { 80357 !(typeof Component.childContextTypes === 'object') ? "development" !== 'production' ? invariant(false, '%s.getChildContext(): childContextTypes must be defined in order to ' + 'use getChildContext().', this.getName() || 'ReactCompositeComponent') : invariant(false) : void 0; 80358 if ("development" !== 'production') { 80359 this._checkPropTypes(Component.childContextTypes, childContext, ReactPropTypeLocations.childContext); 80360 } 80361 for (var name in childContext) { 80362 !(name in Component.childContextTypes) ? "development" !== 'production' ? invariant(false, '%s.getChildContext(): key "%s" is not defined in childContextTypes.', this.getName() || 'ReactCompositeComponent', name) : invariant(false) : void 0; 80363 } 80364 return _assign({}, currentContext, childContext); 80365 } 80366 return currentContext; 80367 }, 80368 80369 /** 80370 * Processes props by setting default values for unspecified props and 80371 * asserting that the props are valid. Does not mutate its argument; returns 80372 * a new props object with defaults merged in. 80373 * 80374 * @param {object} newProps 80375 * @return {object} 80376 * @private 80377 */ 80378 _processProps: function (newProps) { 80379 if ("development" !== 'production') { 80380 var Component = this._currentElement.type; 80381 if (Component.propTypes) { 80382 this._checkPropTypes(Component.propTypes, newProps, ReactPropTypeLocations.prop); 80383 } 80384 } 80385 return newProps; 80386 }, 80387 80388 /** 80389 * Assert that the props are valid 80390 * 80391 * @param {object} propTypes Map of prop name to a ReactPropType 80392 * @param {object} props 80393 * @param {string} location e.g. "prop", "context", "child context" 80394 * @private 80395 */ 80396 _checkPropTypes: function (propTypes, props, location) { 80397 // TODO: Stop validating prop types here and only use the element 80398 // validation. 80399 var componentName = this.getName(); 80400 for (var propName in propTypes) { 80401 if (propTypes.hasOwnProperty(propName)) { 80402 var error; 80403 try { 80404 // This is intentionally an invariant that gets caught. It's the same 80405 // behavior as without this statement except with a better message. 80406 !(typeof propTypes[propName] === 'function') ? "development" !== 'production' ? invariant(false, '%s: %s type `%s` is invali
80406d; it must be a function, usually ' + 'from React.PropTypes.', componentName || 'React class', ReactPropTypeLocationNames[location], propName) : invariant(false) : void 0; 80407 error = propTypes[propName](props, propName, componentName, location); 80408 } catch (ex) { 80409 error = ex; 80410 } 80411 if (error instanceof Error) { 80412 // We may want to extend this logic for similar errors in 80413 // top-level render calls, so I'm abstracting it away into 80414 // a function to minimize refactoring in the future 80415 var addendum = getDeclarationErrorAddendum(this); 80416 80417 if (location === ReactPropTypeLocations.prop) { 80418 // Preface gives us something to blacklist in warning module 80419 "development" !== 'production' ? warning(false, 'Failed Composite propType: %s%s', error.message, addendum) : void 0; 80420 } else { 80421 "development" !== 'production' ? warning(false, 'Failed Context Types: %s%s', error.message, addendum) : void 0; 80422 } 80423 } 80424 } 80425 } 80426 }, 80427 80428 receiveComponent: function (nextElement, transaction, nextContext) { 80429 var prevElement = this._currentElement; 80430 var prevContext = this._context; 80431 80432 this._pendingElement = null; 80433 80434 this.updateComponent(transaction, prevElement, nextElement, prevContext, nextContext); 80435 }, 80436 80437 /** 80438 * If any of `_pendingElement`, `_pendingStateQueue`, or `_pendingForceUpdate` 80439 * is set, update the component. 80440 * 80441 * @param {ReactReconcileTransaction} transaction 80442 * @internal 80443 */ 80444 performUpdateIfNecessary: function (transaction) { 80445 if (this._pendingElement != null) { 80446 ReactReconciler.receiveComponent(this, this._pendingElement, transaction, this._context); 80447 } 80448 80449 if (this._pendingStateQueue !== null || this._pendingForceUpdate) { 80450 this.updateComponent(transaction, this._currentElement, this._currentElement, this._context, this._context); 80451 } 80452 }, 80453 80454 /** 80455 * Perform an update to a mounted component. The componentWillReceiveProps and 80456 * shouldComponentUpdate methods are called, then (assuming the update isn't 80457 * skipped) the remaining update lifecycle methods are called and the DOM 80458 * representation is updated. 80459 * 80460 * By default, this implements React's rendering and reconciliation algorithm. 80461 * Sophisticated clients may wish to override this. 80462 * 80463 * @param {ReactReconcileTransaction} transaction 80464 * @param {ReactElement} prevParentElement 80465 * @param {ReactElement} nextParentElement 80466 * @internal 80467 * @overridable 80468 */ 80469 updateComponent: function (transaction, prevParentElement, nextParentElement, prevUnmaskedContext, nextUnmaskedContext) { 80470 var inst = this._instance; 80471 var willReceive = false; 80472 var nextContext; 80473 var nextProps; 80474 80475 // Determine if the context has changed or not 80476 if (this._context === nextUnmaskedContext) { 80477 nextContext = inst.context; 80478 } else { 80479 nextContext = this._processContext(nextUnmaskedContext); 80480 willReceive = true; 80481 } 80482 80483 // Distinguish between a props update versus a simple state update 80484 if (prevParentElement === nextParentElement) { 80485 // Skip checking prop types again -- we don't read inst.props to avoid 80486 // warning for DOM component props in this upgrade 80487 nextProps = nextParentElement.props; 80488 } else { 80489 nextProps = this._processProps(nextParentElement.props); 80490 willReceive = true; 80491 } 80492 80493 // An update here will schedule an update but immediately set 80494 // _pendingStateQueue which will ensure that any state updates gets 80495 // immediately reconciled instead of waiting for the next batch. 80496 if (willReceive && inst.componentWillReceiveProps) { 80497 inst.componentWillReceiveProps(nextProps, nextContext); 80498 } 80499 80500 var nextState = this._processPendingState(nextProps, nextContext); 80501 80502 var shouldUpdate = this._pendingForceUpdate || !inst.shouldComponentUpdate || inst.shouldComponentUpdate(nextProps, nextState, nextContext); 80503 80504 if ("development" !== 'production') { 80505 "development" !== 'production' ? warning(shouldUpdate !== undefined, '%s.shouldComponentUpdate(): Returned undefined instead of a ' + 'boolean value. Make sure to return true or false.', this.getName() || 'ReactCompositeComponent') : void 0; 80506 } 80507 80508 if (shouldUpdate) { 80509 this._pendingForceUpdate = false;
80510 // Will set `this.props`, `this.state` and `this.context`. 80511 this._performComponentUpdate(nextParentElement, nextProps, nextState, nextContext, transaction, nextUnmaskedContext); 80512 } else { 80513 // If it's determined that a component should not update, we still want 80514 // to set props and state but we shortcut the rest of the update. 80515 this._currentElement = nextParentElement; 80516 this._context = nextUnmaskedContext; 80517 inst.props = nextProps; 80518 inst.state = nextState; 80519 inst.context = nextContext; 80520 } 80521 }, 80522 80523 _processPendingState: function (props, context) { 80524 var inst = this._instance; 80525 var queue = this._pendingStateQueue; 80526 var replace = this._pendingReplaceState; 80527 this._pendingReplaceState = false; 80528 this._pendingStateQueue = null; 80529 80530 if (!queue) { 80531 return inst.state; 80532 } 80533 80534 if (replace && queue.length === 1) { 80535 return queue[0]; 80536 } 80537 80538 var nextState = _assign({}, replace ? queue[0] : inst.state); 80539 for (var i = replace ? 1 : 0; i < queue.length; i++) { 80540 var partial = queue[i]; 80541 _assign(nextState, typeof partial === 'function' ? partial.call(inst, nextState, props, context) : partial); 80542 } 80543 80544 return nextState; 80545 }, 80546 80547 /** 80548 * Merges new props and state, notifies delegate methods of update and 80549 * performs update. 80550 * 80551 * @param {ReactElement} nextElement Next element 80552 * @param {object} nextProps Next public object to set as properties. 80553 * @param {?object} nextState Next object to set as state. 80554 * @param {?object} nextContext Next public object to set as context. 80555 * @param {ReactReconcileTransaction} transaction 80556 * @param {?object} unmaskedContext 80557 * @private 80558 */ 80559 _performComponentUpdate: function (nextElement, nextProps, nextState, nextContext, transaction, unmaskedContext) { 80560 var inst = this._instance; 80561 80562 var hasComponentDidUpdate = Boolean(inst.componentDidUpdate); 80563 var prevProps; 80564 var prevState; 80565 var prevContext; 80566 if (hasComponentDidUpdate) { 80567 prevProps = inst.props; 80568 prevState = inst.state; 80569 prevContext = inst.context; 80570 } 80571 80572 if (inst.componentWillUpdate) { 80573 inst.componentWillUpdate(nextProps, nextState, nextContext); 80574 } 80575 80576 this._currentElement = nextElement; 80577 this._context = unmaskedContext; 80578 inst.props = nextProps; 80579 inst.state = nextState; 80580 inst.context = nextContext; 80581 80582 this._updateRenderedComponent(transaction, unmaskedContext); 80583 80584 if (hasComponentDidUpdate) { 80585 transaction.getReactMountReady().enqueue(inst.componentDidUpdate.bind(inst, prevProps, prevState, prevContext), inst); 80586 } 80587 }, 80588 80589 /** 80590 * Call the component's `render` method and update the DOM accordingly. 80591 * 80592 * @param {ReactReconcileTransaction} transaction 80593 * @internal 80594 */ 80595 _updateRenderedComponent: function (transaction, context) { 80596 var prevComponentInstance = this._renderedComponent; 80597 var prevRenderedElement = prevComponentInstance._currentElement; 80598 var nextRenderedElement = this._renderValidatedComponent(); 80599 if (shouldUpdateReactComponent(prevRenderedElement, nextRenderedElement)) { 80600 ReactReconciler.receiveComponent(prevComponentInstance, nextRenderedElement, transaction, this._processChildContext(context)); 80601 } else { 80602 var oldNativeNode = ReactReconciler.getNativeNode(prevComponentInstance); 80603 ReactReconciler.unmountComponent(prevComponentInstance, false); 80604 80605 this._renderedNodeType = ReactNodeTypes.getType(nextRenderedElement); 80606 this._renderedComponent = this._instantiateReactComponent(nextRenderedElement); 80607 var nextMarkup = ReactReconciler.mountComponent(this._renderedComponent, transaction, this._nativeParent, this._nativeContainerInfo, this._processChildContext(context)); 80608 this._replaceNodeWithMarkup(oldNativeNode, nextMarkup); 80609 } 80610 }, 80611 80612 /** 80613 * Overridden in shallow rendering. 80614 * 80615 * @protected 80616 */ 80617 _replaceNodeWithMarkup: function (oldNativeNode, nextMarkup) { 80618 ReactComponentEnvironment.replaceNodeWithMarkup(oldNativeNode, nextMarkup); 80619 }, 80620 80621 /** 80622 * @protected 80623 */ 80624 _renderValidatedComponentWithoutOwnerOrContext: function () { 80625 var inst = this._instance; 80626 var renderedComponent = inst.render(); 80627 if ("development" !== 'production') { 80628 // We allow auto-mocks to proceed as if they're returning null. 80629 if (renderedComponent === undefined && inst.render._isMockFunction) { 80630 // This is probably bad practice. Consider warning here and 80631 // deprecating this convenience. 80632 renderedComponent = null; 80633 } 80634 } 80635 80636 return renderedComponent; 80637 }, 80638 80639 /** 80640 * @private 80641 */ 80642 _renderValidatedComponent: function () { 80643 var renderedComponent; 80644 ReactCurrentOwner.current = this; 80645 try { 80646 renderedComponent = this._renderValidatedComponentWithoutOwnerOrContext(); 80647 } finally { 80648 ReactCurrentOwner.current = null; 80649 } 80650 !( 80651 // TODO: An `isValidNode` function would probably be more appropriate 80652 renderedComponent === null || renderedComponent === false || ReactElement.isValidElement(renderedComponent)) ? "development" !== 'production' ? invariant(false, '%s.render(): A valid React element (or null) must be returned. You may have ' + 'returned undefined, an array or some other invalid object.', this.getName() || 'ReactCompositeComponent') : invariant(false) : void 0; 80653 return renderedComponent; 80654 }, 80655 80656 /** 80657 * Lazily allocates the refs object and stores `component` as `ref`. 80658 * 80659 * @param {string} ref Reference name. 80660 * @param {component} component Component to store as `ref`. 80661 * @final 80662 * @private 80663 */ 80664 attachRef: function (ref, component) { 80665 var inst = this.getPublicInstance(); 80666 !(inst != null) ? "development" !== 'production' ? invariant(false, 'Stateless function components cannot have refs.') : invariant(false) : void 0; 80667 var publicComponentInstance = component.getPublicInstance(); 80668 if ("development" !== 'production') { 80669 var componentName = component && component.getName ? component.getName() : 'a component'; 80670 "development" !== 'production' ? warning(publicComponentInstance != null, 'Stateless function components cannot be given refs ' + '(See ref "%s" in %s created by %s). ' + 'Attempts to access this ref will fail.', ref, componentName, this.getName()) : void 0; 80671 } 80672 var refs = inst.refs === emptyObject ? inst.refs = {} : inst.refs; 80673 refs[ref] = publicComponentInstance; 80674 }, 80675 80676 /** 80677 * Detaches a reference name. 80678 * 80679 * @param {string} ref Name to dereference. 80680 * @final 80681 * @private 80682 */ 80683 detachRef: function (ref) { 80684 var refs = this.getPublicInstance().refs; 80685 delete refs[ref]; 80686 }, 80687 80688 /** 80689 * Get a text description of the component that can be used to identify it 80690 * in error messages. 80691 * @return {string} The name or null. 80692 * @internal 80693 */ 80694 getName: function () { 80695 var type = this._currentElement.type; 80696 var constructor = this._instance && this._instance.constructor; 80697 return type.displayName || constructor && constructor.displayName || type.name || constructor && constructor.name || null; 80698 }, 80699 80700 /** 80701 * Get the publicly accessible representation of this component - i.e. what 80702 * is exposed by refs and returned by render. Can be null for stateless 80703 * components. 80704 * 80705 * @return {ReactComponent} the public component instance. 80706 * @internal 80707 */ 80708 getPublicInstance: function () { 80709 var inst = this._instance; 80710 if (inst instanceof StatelessComponent) { 80711 return null; 80712 } 80713 return inst; 80714 }, 80715 80716 // Stub 80717 _instantiateReactComponent: null 80718 80719}; 80720 80721ReactPerf.measureMethods(ReactCompositeComponentMixin, 'ReactCompositeComponent', { 80722 mountComponent: 'mountComponent', 80723 updateComponent: 'updateComponent', 80724 _renderValidatedComponent: '_renderValidatedComponent' 80725}); 80726 80727var ReactCompositeComponent = { 80728 80729 Mixin: ReactCompositeComponentMixin 80730 80731}; 80732 80733module.exports = ReactCompositeComponent; 80734},{"140":140,"151":151,"158":158,"168":168,"169":169,"33":33,"35":35,"62":62,"65":65,"71":71,"72":72,"79":79,"82":82,"83":83,"84":84,"87":87,"93":93}],35:[function(_dereq_,module,exports){ 80735/** 80736 * Copyright 2013-present, Facebook, Inc. 80737 * All rights reserved. 80738 * 80739 * This source code is licensed under the BSD-style license found in the 80740 * LICENSE file in the root directory of this source tree. An additional grant 80741 * of patent rights can be found in the PATENTS file in the same directory. 80742 * 80743 * @providesModule ReactCurrentOwner 80744 */ 80745 80746 80747 80748/** 80749 * Keeps track of the current owner. 80750 * 80751 * The current owner is the component who should own any components that are 80752 * currently being constructed. 80753 */ 80754 80755var ReactCurrentOwner = { 80756 80757 /** 80758 * @internal 80759 * @type {ReactComponent} 80760 */ 80761 current: null 80762 80763}; 80764 80765module.exports = ReactCurrentOwner; 80766},{}],36:[function(_dereq_,module,exports){ 80767/** 80768 * Copyright 2013-present, Facebook, Inc. 80769 * All rights reserved. 80770 * 80771 * This source code is licensed under the BSD-style license found in the 80772 * LICENSE file in the root directory of this source tree. An additional grant 80773 * of patent rights can be found in the PATENTS file in the same directory. 80774 * 80775 * @providesModule ReactDOM 80776 */ 80777 80778/* globals __REACT_DEVTOOLS_GLOBAL_HOOK__*/ 80779 80780 80781 80782var ReactDOMComponentTree = _dereq_(40); 80783var ReactDefaultInjection = _dereq_(59); 80784var ReactMount = _dereq_(75); 80785var ReactPerf = _dereq_(82); 80786var ReactReconciler = _dereq_(87); 80787var ReactUpdates = _dereq_(94); 80788var ReactVersion = _dereq_(95); 80789 80790var findDOMNode = _dereq_(120); 80791var getNativeComponentFromComposite = _dereq_(128); 80792var renderSubtreeIntoContainer = _dereq_(137); 80793var warning = _dereq_(168); 80794 80795ReactDefaultInjection.inject(); 80796 80797var render = ReactPerf.measure('React', 'render', ReactMount.render); 80798 80799var React = { 80800 findDOMNode: findDOMNode, 80801 render: render, 80802 unmountComponentAtNode: ReactMount.unmountComponentAtNode, 80803 version: ReactVersion, 80804 80805 /* eslint-disable camelcase */ 80806 unstable_batchedUpdates: ReactUpdates.batchedUpdates, 80807 unstable_renderSubtreeIntoContainer: renderSubtreeIntoContainer 80808}; 80809 80810// Inject the runtime into a devtools global hook regardless of browser. 80811// Allows for debugging when the hook is injected on the page. 80812/* eslint-enable camelcase */ 80813if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== 'undefined' && typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.inject === 'function') { 80814 __REACT_DEVTOOLS_GLOBAL_HOOK__.inject({ 80815 ComponentTree: { 80816 getClosestInstanceFromNode: ReactDOMComponentTree.getClosestInstanceFromNode, 80817 getNodeFromInstance: function (inst) { 80818 // inst is an internal instance (but could be a composite) 80819 if (inst._renderedComponent) { 80820 inst = getNativeComponentFromComposite(inst); 80821 } 80822 if (inst) { 80823 return ReactDOMComponentTree.getNodeFromInstance(inst); 80824 } else { 80825 return null; 80826 } 80827 } 80828 }, 80829 Mount: ReactMount, 80830 Reconciler: ReactReconciler 80831 }); 80832} 80833 80834if ("development" !== 'production') { 80835 var ExecutionEnvironment = _dereq_(144); 80836 if (ExecutionEnvironment.canUseDOM && window.top === window.self) { 80837 80838 // First check if devtools is not installed 80839 if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === 'undefined') { 80840 // If we're in Chrome or Firefox, provide a download link if not installed. 80841 if (navigator.userAgent.indexOf('Chrome') > -1 && navigator.userAgent.indexOf('Edge') === -1 || navigator.userAgent.indexOf('Firefox') > -1) { 80842 // Firefox does not have the issue with devtools loaded over file:// 80843 var showFileUrlMessage = window.location.protocol.indexOf('http') === -1 && navigator.userAgent.indexOf('Firefox') === -1; 80844 console.debug('Download the React DevTools ' + (showFileUrlMessage ? 'and use an HTTP server (instead of a file: URL) ' : '') + 'for a better development experience: ' + 'https://fb.me/react-devtools'); 80845 } 80846 } 80847 80848 var testFunc = function testFn() {}; 80849 "development" !== 'production' ? warning((testFunc.name || testFunc.toString()).indexOf('testFn') !== -1, 'It looks like you\'re using a minified copy of the development build ' + 'of React. When deploying React apps to production, make sure to use ' + 'the production build which skips development warnings and is faster. ' + 'See https://fb.me/react-minification for more details.') : void 0; 80850 80851 // If we're in IE8, check to see if we are in compatibility mode and provide 80852 // information on preventing compatibility mode 80853 var ieCompatibilityMode = document.documentMode && document.documentMode < 8; 80854 80855 "development" !== 'production' ? warning(!ieCompatibilityMode, 'Internet Explorer is running in compatibility mode; please add the ' + 'following tag to your HTML to prevent this from happening: ' + '<meta http-equiv="X-UA-Compatible" content="IE=edge" />') : void 0; 80856 80857 var expectedFeatures = [ 80858 // shims 80859 Array.isArray, Array.prototype.every, Array.prototype.forEach, Array.prototype.indexOf, Array.prototype.map, Date.now, Function.prototype.bind, Object.keys, String.prototype.split, String.prototype.trim]; 80860 80861 for (var i = 0; i < expectedFeatures.length; i++) { 80862 if (!expectedFeatures[i]) { 80863 "development" !== 'production' ? warning(false, 'One or more ES5 shims expected by React are not available: ' + 'https://fb.me/react-warning-polyfills') : void 0; 80864 break; 80865 } 80866 } 80867 } 80868} 80869 80870module.exports = React; 80871},{"120":120,"128":128,"137":137,"144":144,"168":168,"40":40,"59":59,"75":75,"82":82,"87":87,"94":94,"95":95}],37:[function(_dereq_,module,exports){ 80872/** 80873 * Copyright 2013-present, Facebook, Inc. 80874 * All rights reserved. 80875 * 80876 * This source code is licensed under the BSD-style license found in the 80877 * LICENSE file in the root directory of this source tree. An additional grant 80878 * of patent rights can be found in the PATENTS file in the same directory. 80879 * 80880 * @providesModule ReactDOMButton 80881 */ 80882 80883 80884 80885var DisabledInputUtils = _dereq_(14); 80886 80887/** 80888 * Implements a <button> native component that does not receive mouse events 80889 * when `disabled` is set. 80890 */ 80891var ReactDOMButton = { 80892 getNativeProps: DisabledInputUtils.getNativeProps 80893}; 80894 80895module.exports = ReactDOMButton; 80896},{"14":14}],38:[function(_dereq_,module,exports){ 80897/** 80898 * Copyright 2013-present, Facebook, Inc. 80899 * All rights reserved. 80900 * 80901 * This source code is licensed under the BSD-style license found in the 80902 * LICENSE file in the root directory of this source tree. An additional grant 80903 * of patent rights can be found in the PATENTS file in the same directory. 80904 * 80905 * @providesModule ReactDOMComponent 80906 */ 80907 80908/* global hasOwnProperty:true */ 80909 80910 80911 80912var _assign = _dereq_(169); 80913 80914var AutoFocusUtils = _dereq_(1); 80915var CSSPropertyOperations = _dereq_(4); 80916var DOMLazyTree = _dereq_(8); 80917var DOMNamespaces = _dereq_(9); 80918var DOMProperty = _dereq_(10); 80919var DOMPropertyOperations = _dereq_(11); 80920var EventConstants = _dereq_(16); 80921var EventPluginHub = _dereq_(17); 80922var EventPluginRegistry = _dereq_(18); 80923var ReactBrowserEventEmitter = _dereq_(27); 80924var ReactComponentBrowserEnvironment = _dereq_(32); 80925var ReactDOMButton = _dereq_(37); 80926var ReactDOMComponentFlags = _dereq_(39); 80927var ReactDOMComponentTree = _dereq_(40); 80928var ReactDOMInput = _dereq_(47); 80929var ReactDOMOption = _dereq_(49); 80930var ReactDOMSelect = _dereq_(50); 80931var ReactDOMTextarea = _dereq_(54); 80932var ReactMultiChild = _dereq_(76); 80933var ReactPerf = _dereq_(82); 80934 80935var escapeTextContentForBrowser = _dereq_(119); 80936var invariant = _dereq_(158); 80937var isEventSupported = _dereq_(133); 80938var keyOf = _dereq_(162); 80939var shallowEqual = _dereq_(167); 80940var validateDOMNesting = _dereq_(142); 80941var warning = _dereq_(168); 80942 80943var Flags = ReactDOMComponentFlags; 80944var deleteListener = EventPluginHub.deleteListener; 80945var getNode = ReactDOMComponentTree.getNodeFromInstance; 80946var listenTo = ReactBrowserEventEmitter.listenTo; 80947var registrationNameModules = EventPluginRegistry.registrationNameModules; 80948 80949// For quickly matching children type, to test if can be treated as content. 80950var CONTENT_TYPES = { 'string': true, 'number': true }; 80951 80952var STYLE = keyOf({ style: null }); 80953var HTML = keyOf({ __html: null }); 80954var RESERVED_PROPS = { 80955 children: null,
80956 dangerouslySetInnerHTML: null, 80957 suppressContentEditableWarning: null 80958}; 80959 80960// Node type for document fragments (Node.DOCUMENT_FRAGMENT_NODE). 80961var DOC_FRAGMENT_TYPE = 11; 80962 80963function getDeclarationErrorAddendum(internalInstance) { 80964 if (internalInstance) { 80965 var owner = internalInstance._currentElement._owner || null; 80966 if (owner) { 80967 var name = owner.getName(); 80968 if (name) { 80969 return ' This DOM node was rendered by `' + name + '`.'; 80970 } 80971 } 80972 } 80973 return ''; 80974} 80975 80976function friendlyStringify(obj) { 80977 if (typeof obj === 'object') { 80978 if (Array.isArray(obj)) { 80979 return '[' + obj.map(friendlyStringify).join(', ') + ']'; 80980 } else { 80981 var pairs = []; 80982 for (var key in obj) { 80983 if (Object.prototype.hasOwnProperty.call(obj, key)) { 80984 var keyEscaped = /^[a-z$_][\w$_]*$/i.test(key) ? key : JSON.stringify(key); 80985 pairs.push(keyEscaped + ': ' + friendlyStringify(obj[key])); 80986 } 80987 } 80988 return '{' + pairs.join(', ') + '}'; 80989 } 80990 } else if (typeof obj === 'string') { 80991 return JSON.stringify(obj); 80992 } else if (typeof obj === 'function') { 80993 return '[function object]'; 80994 } 80995 // Differs from JSON.stringify in that undefined because undefined and that 80996 // inf and nan don't become null 80997 return String(obj); 80998} 80999 81000var styleMutationWarning = {}; 81001 81002function checkAndWarnForMutatedStyle(style1, style2, component) { 81003 if (style1 == null || style2 == null) { 81004 return; 81005 } 81006 if (shallowEqual(style1, style2)) { 81007 return; 81008 } 81009 81010 var componentName = component._tag; 81011 var owner = component._currentElement._owner; 81012 var ownerName; 81013 if (owner) { 81014 ownerName = owner.getName(); 81015 } 81016 81017 var hash = ownerName + '|' + componentName; 81018 81019 if (styleMutationWarning.hasOwnProperty(hash)) { 81020 return; 81021 } 81022 81023 styleMutationWarning[hash] = true; 81024 81025 "development" !== 'production' ? warning(false, '`%s` was passed a style object that has previously been mutated. ' + 'Mutating `style` is deprecated. Consider cloning it beforehand. Check ' + 'the `render` %s. Previous style: %s. Mutated style: %s.', componentName, owner ? 'of `' + ownerName + '`' : 'using <' + componentName + '>', friendlyStringify(style1), friendlyStringify(style2)) : void 0; 81026} 81027 81028/** 81029 * @param {object} component 81030 * @param {?object} props 81031 */ 81032function assertValidProps(component, props) { 81033 if (!props) { 81034 return; 81035 } 81036 // Note the use of `==` which checks for null or undefined. 81037 if (voidElementTags[component._tag]) { 81038 !(props.children == null && props.dangerouslySetInnerHTML == null) ? "development" !== 'production' ? invariant(false, '%s is a void element tag and must not have `children` or ' + 'use `props.dangerouslySetInnerHTML`.%s', component._tag, component._currentElement._owner ? ' Check the render method of ' + component._currentElement._owner.getName() + '.' : '') : invariant(false) : void 0; 81039 } 81040 if (props.dangerouslySetInnerHTML != null) { 81041 !(props.children == null) ? "development" !== 'production' ? invariant(false, 'Can only set one of `children` or `props.dangerouslySetInnerHTML`.') : invariant(false) : void 0; 81042 !(typeof props.dangerouslySetInnerHTML === 'object' && HTML in props.dangerouslySetInnerHTML) ? "development" !== 'production' ? invariant(false, '`props.dangerouslySetInnerHTML` must be in the form `{__html: ...}`. ' + 'Please visit https://fb.me/react-invariant-dangerously-set-inner-html ' + 'for more information.') : invariant(false) : void 0; 81043 } 81044 if ("development" !== 'production') { 81045 "development" !== 'production' ? warning(props.innerHTML == null, 'Directly setting property `innerHTML` is not permitted. ' + 'For more information, lookup documentation on `dangerouslySetInnerHTML`.') : void 0; 81046 "development" !== 'production' ? warning(props.suppressContentEditableWarning || !props.contentEditable || props.children == null, 'A component is `contentEditable` and contains `children` managed by ' + 'React. It is now your responsibility to guarantee that none of ' + 'those nodes are unexpectedly modified or duplicated. This is ' + 'probably not intentional.') : void 0; 81047 "development" !== 'production' ? warning(props.onFocusIn == null && props.onFocusOut == null, 'React uses onFocus and onBlur instead of onFocusIn and onFocusOut. ' + 'All React events are normalized to bubble, so onFocusIn and onFocusOut ' + 'are not needed/supported by React.') : void 0; 81048 } 81049 !(props.style == null || typeof props.style === 'object') ? "development" !== 'production' ? invariant(false, 'The `style` prop expects a mapping from style properties to values, ' + 'not a string. For example, style={{marginRight: spacing + \'em\'}} when ' + 'using JSX.%s', getDeclarationErrorAddendum(component)) : invariant(false) : void 0; 81050} 81051 81052function enqueuePutListener(inst, registrationName, listener, transaction) { 81053 if ("development" !== 'production') { 81054 // IE8 has no API for event capturing and the `onScroll` event doesn't 81055 // bubble. 81056 "development" !== 'production' ? warning(registrationName !== 'onScroll' || isEventSupported('scroll', true), 'This browser doesn\'t support the `onScroll` event') : void 0; 81057 } 81058 var containerInfo = inst._nativeContainerInfo; 81059 var isDocumentFragment = containerInfo._node && containerInfo._node.nodeType === DOC_FRAGMENT_TYPE; 81060 var doc = isDocumentFragment ? containerInfo._node : containerInfo._ownerDocument; 81061 if (!doc) { 81062 // Server rendering. 81063 return; 81064 } 81065 listenTo(registrationName, doc); 81066 transaction.getReactMountReady().enqueue(putListener, { 81067 inst: inst, 81068 registrationName: registrationName, 81069 listener: listener 81070 }); 81071} 81072 81073function putListener() { 81074 var listenerToPut = this; 81075 EventPluginHub.putListener(listenerToPut.inst, listenerToPut.registrationName, listenerToPut.listener); 81076} 81077 81078function optionPostMount() { 81079 var inst = this; 81080 ReactDOMOption.postMountWrapper(inst); 81081} 81082 81083// There are so many media events, it makes sense to just
81084// maintain a list rather than create a `trapBubbledEvent` for each 81085var mediaEvents = { 81086 topAbort: 'abort', 81087 topCanPlay: 'canplay', 81088 topCanPlayThrough: 'canplaythrough', 81089 topDurationChange: 'durationchange', 81090 topEmptied: 'emptied', 81091 topEncrypted: 'encrypted', 81092 topEnded: 'ended', 81093 topError: 'error', 81094 topLoadedData: 'loadeddata', 81095 topLoadedMetadata: 'loadedmetadata', 81096 topLoadStart: 'loadstart', 81097 topPause: 'pause', 81098 topPlay: 'play', 81099 topPlaying: 'playing', 81100 topProgress: 'progress', 81101 topRateChange: 'ratechange', 81102 topSeeked: 'seeked', 81103 topSeeking: 'seeking', 81104 topStalled: 'stalled', 81105 topSuspend: 'suspend', 81106 topTimeUpdate: 'timeupdate', 81107 topVolumeChange: 'volumechange', 81108 topWaiting: 'waiting' 81109}; 81110 81111function trapBubbledEventsLocal() { 81112 var inst = this; 81113 // If a component renders to null or if another component fatals and causes 81114 // the state of the tree to be corrupted, `node` here can be null. 81115 !inst._rootNodeID ? "development" !== 'production' ? invariant(false, 'Must be mounted to trap events') : invariant(false) : void 0; 81116 var node = getNode(inst); 81117 !node ? "development" !== 'production' ? invariant(false, 'trapBubbledEvent(...): Requires node to be rendered.') : invariant(false) : void 0; 81118 81119 switch (inst._tag) { 81120 case 'iframe': 81121 case 'object': 81122 inst._wrapperState.listeners = [ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes.topLoad, 'load', node)]; 81123 break; 81124 case 'video': 81125 case 'audio': 81126 81127 inst._wrapperState.listeners = []; 81128 // Create listener for each media event 81129 for (var event in mediaEvents) { 81130 if (mediaEvents.hasOwnProperty(event)) { 81131 inst._wrapperState.listeners.push(ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes[event], mediaEvents[event], node)); 81132 } 81133 } 81134 81135 break; 81136 case 'img': 81137 inst._wrapperState.listeners = [ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes.topError, 'error', node), ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes.topLoad, 'load', node)]; 81138 break; 81139 case 'form': 81140 inst._wrapperState.listeners = [ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes.topReset, 'reset', node), ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes.topSubmit, 'submit', node)]; 81141 break; 81142 case 'input': 81143 case 'select': 81144 case 'textarea': 81145 inst._wrapperState.listeners = [ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes.topInvalid, 'invalid', node)]; 81146 break; 81147 } 81148} 81149 81150function postUpdateSelectWrapper() { 81151 ReactDOMSelect.postUpdateWrapper(this); 81152} 81153 81154// For HTML, certain tags should omit their close tag. We keep a whitelist for 81155// those special-case tags. 81156 81157var omittedCloseTags = { 81158 'area': true, 81159 'base': true, 81160 'br': true, 81161 'col': true, 81162 'embed': true, 81163 'hr': true, 81164 'img': true, 81165 'input': true, 81166 'keygen': true, 81167 'link': true, 81168 'meta': true, 81169 'param': true, 81170 'source': true, 81171 'track': true, 81172 'wbr': true 81173}; 81174 81175// NOTE: menuitem's close tag should be omitted, but that causes problems. 81176var newlineEatingTags = { 81177 'listing': true, 81178 'pre': true, 81179 'textarea': true 81180}; 81181 81182// For HTML, certain tags cannot have children. This has the same purpose as 81183// `omittedCloseTags` except that `menuitem` should still have its closing tag. 81184 81185var voidElementTags = _assign({ 81186 'menuitem': true 81187}, omittedCloseTags); 81188 81189// We accept any tag to be rendered but since this gets injected into arbitrary 81190// HTML, we want to make sure that it's a safe tag. 81191// http://www.w3.org/TR/REC-xml/#NT-Name 81192 81193var VALID_TAG_REGEX = /^[a-zA-Z][a-zA-Z:_\.\-\d]*$/; // Simplified subset 81194var validatedTagCache = {}; 81195var hasOwnProperty = {}.hasOwnProperty; 81196 81197function validateDangerousTag(tag) { 81198 if (!hasOwnProperty.call(validatedTagCache, tag)) { 81199 !VALID_TAG_REGEX.test(tag) ? "development" !== 'production' ? invariant(false, 'Invalid tag: %s', tag) : invariant(false) : void 0; 81200 validatedTagCache[tag] = true; 81201 } 81202} 81203 81204function isCustomComponent(tagName, props) { 81205 return tagName.indexOf('-') >= 0 || props.is != null; 81206} 81207 81208var globalIdCounter = 1; 81209 81210/** 81211 * Creates a new React class that is idempotent and capable of containing other 81212 * React components. It accepts event listeners and DOM properties that are 81213 * valid according to `DOMProperty`. 81214 * 81215 * - Event listeners: `onClick`, `onMouseDown`, etc. 81216 * - DOM properties: `className`, `name`, `title`, etc. 81217 * 81218 * The `style` property functions differently from the DOM API. It accepts an 81219 * object mapping of style properties to values. 81220 * 81221 * @constructor ReactDOMComponent 81222 * @extends ReactMultiChild 81223 */ 81224function ReactDOMComponent(element) { 81225 var tag = element.type; 81226 validateDangerousTag(tag); 81227 this._currentElement = element; 81228 this._tag = tag.toLowerCase(); 81229 this._namespaceURI = null; 81230 this._renderedChildren = null; 81231 this._previousStyle = null; 81232 this._previousStyleCopy = null; 81233 this._nativeNode = null; 81234 this._nativeParent = null; 81235 this._rootNodeID = null; 81236 this._domID = null; 81237 this._nativeContainerInfo = null; 81238 this._wrapperState = null; 81239 this._topLevelWrapper = null; 81240 this._flags = 0; 81241 if ("development" !== 'production') { 81242 this._ancestorInfo = null; 81243 } 81244} 81245 81246ReactDOMComponent.displayName = 'ReactDOMComponent'; 81247 81248ReactDOMComponent.Mixin = { 81249 81250 /** 81251 * Generates root tag markup then recurses. This method has side effects and 81252 * is not idempotent. 81253 * 81254 * @internal 81255 * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction 81256 * @param {?ReactDOMComponent} the containing DOM component instance 81257 * @param {?object} info about the native container 81258 * @param {object} context 81259 * @return {string} The computed markup. 81260 */ 81261 mountComponent: function (transaction, nativeParent, nativeContainerInfo, context) { 81262 this._rootNodeID = globalIdCounter++; 81263 this._domID = nativeContainerInfo._idCounter++; 81264 this._nativeParent = nativeParent; 81265 this._nativeContainerInfo = nativeContainerInfo; 81266 81267 var props = this._currentElement.props; 81268 81269 switch (this._tag) { 81270 case 'iframe': 81271 case 'object': 81272 case 'img': 81273 case 'form': 81274 case 'video': 81275 case 'audio': 81276 this._wrapperState = { 81277 listeners: null 81278 }; 81279 transaction.getReactMountReady().enqueue(trapBubbledEventsLocal, this); 81280 break; 81281 case 'button': 81282 props = ReactDOMButton.getNativeProps(this, props, nativeParent); 81283 break; 81284 case 'input': 81285 ReactDOMInput.mountWrapper(this, props, nativeParent); 81286 props = ReactDOMInput.getNativeProps(this, props); 81287 transaction.getReactMountReady().enqueue(trapBubbledEventsLocal, this); 81288 break; 81289 case 'option': 81290 ReactDOMOption.mountWrapper(this, props, nativeParent); 81291 props = ReactDOMOption.getNativeProps(this, props); 81292 break; 81293 case 'select': 81294 ReactDOMSelect.mountWrapper(this, props, nativeParent); 81295 props = ReactDOMSelect.getNativeProps(this, props); 81296 transaction.getReactMountReady().enqueue(trapBubbledEventsLocal, this); 81297 break; 81298 case 'textarea': 81299 ReactDOMTextarea.mountWrapper(this, props, nativeParent); 81300 props = ReactDOMTextarea.getNativeProps(this, props); 81301 transaction.getReactMountReady().enqueue(trapBubbledEventsLocal, this); 81302 break; 81303 } 81304 81305 assertValidProps(this, props); 81306 81307 // We create tags in the namespace of their parent container, except HTML 81308 // tags get no namespace. 81309 var namespaceURI; 81310 var parentTag; 81311 if (nativeParent != null) { 81312 namespaceURI = nativeParent._namespaceURI; 81313 parentTag = nativeParent._tag; 81314 } else if (nativeContainerInfo._tag) { 81315 namespaceURI = nativeContainerInfo._namespaceURI; 81316 parentTag = nativeContainerInfo._tag; 81317 } 81318 if (namespaceURI == null || namespaceURI === DOMNamespaces.svg && parentTag === 'foreignobject') { 81319 namespaceURI = DOMNamespaces.html; 81320 } 81321 if (namespaceURI === DOMNamespaces.html) { 81322 if (this._tag === 'svg') { 81323 namespaceURI = DOMNamespaces.svg; 81324 } else if (this._tag === 'math') { 81325 namespaceURI = DOMNamespaces.mathml; 81326 } 81327 } 81328 this._namespaceURI = namespaceURI; 81329 81330 if ("development" !== 'production') { 81331 var parentInfo; 81332 if (nativeParent != null) { 81333 parentInfo = nativeParent._ancestorInfo; 81334 } else if (nativeContainerInfo._tag) { 81335 parentInfo = nativeContainerInfo._ancestorInfo; 81336 } 81337 if (parentInfo) { 81338 // parentInfo should always be present except for the top-level 81339 // component when server rendering 81340 validateDOMNesting(this._tag, this, parentInfo); 81341 } 81342 this._ancestorInfo = validateDOMNesting.updatedAncestorInfo(p
81342arentInfo, this._tag, this); 81343 } 81344 81345 var mountImage; 81346 if (transaction.useCreateElement) { 81347 var ownerDocument = nativeContainerInfo._ownerDocument; 81348 var el; 81349 if (namespaceURI === DOMNamespaces.html) { 81350 if (this._tag === 'script') { 81351 // Create the script via .innerHTML so its "parser-inserted" flag is 81352 // set to true and it does not execute 81353 var div = ownerDocument.createElement('div'); 81354 var type = this._currentElement.type; 81355 div.innerHTML = '<' + type + '></' + type + '>'; 81356 el = div.removeChild(div.firstChild); 81357 } else { 81358 el = ownerDocument.createElement(this._currentElement.type); 81359 } 81360 } else { 81361 el = ownerDocument.createElementNS(namespaceURI, this._currentElement.type); 81362 } 81363 ReactDOMComponentTree.precacheNode(this, el); 81364 this._flags |= Flags.hasCachedChildNodes; 81365 if (!this._nativeParent) { 81366 DOMPropertyOperations.setAttributeForRoot(el); 81367 } 81368 this._updateDOMProperties(null, props, transaction); 81369 var lazyTree = DOMLazyTree(el); 81370 this._createInitialChildren(transaction, props, context, lazyTree); 81371 mountImage = lazyTree; 81372 } else { 81373 var tagOpen = this._createOpenTagMarkupAndPutListeners(transaction, props); 81374 var tagContent = this._createContentMarkup(transaction, props, context); 81375 if (!tagContent && omittedCloseTags[this._tag]) { 81376 mountImage = tagOpen + '/>'; 81377 } else { 81378 mountImage = tagOpen + '>' + tagContent + '</' + this._currentElement.type + '>'; 81379 } 81380 } 81381 81382 switch (this._tag) { 81383 case 'button': 81384 case 'input': 81385 case 'select': 81386 case 'textarea': 81387 if (props.autoFocus) { 81388 transaction.getReactMountReady().enqueue(AutoFocusUtils.focusDOMComponent, this); 81389 } 81390 break; 81391 case 'option': 81392 transaction.getReactMountReady().enqueue(optionPostMount, this); 81393 } 81394 81395 return mountImage; 81396 }, 81397 81398 /** 81399 * Creates markup for the open tag and all attributes. 81400 * 81401 * This method has side effects because events get registered. 81402 * 81403 * Iterating over object properties is faster than iterating over arrays. 81404 * @see http://jsperf.com/obj-vs-arr-iteration 81405 * 81406 * @private 81407 * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction 81408 * @param {object} props 81409 * @return {string} Markup of opening tag. 81410 */ 81411 _createOpenTagMarkupAndPutListeners: function (transaction, props) { 81412 var ret = '<' + this._currentElement.type; 81413 81414 for (var propKey in props) { 81415 if (!props.hasOwnProperty(propKey)) { 81416 continue; 81417 } 81418 var propValue = props[propKey]; 81419 if (propValue == null) { 81420 continue; 81421 } 81422 if (registrationNameModules.hasOwnProperty(propKey)) { 81423 if (propValue) { 81424 enqueuePutListener(this, propKey, propValue, transaction); 81425 } 81426 } else { 81427 if (propKey === STYLE) { 81428 if (propValue) { 81429 if ("development" !== 'production') { 81430 // See `_updateDOMProperties`. style block 81431 this._previousStyle = propValue; 81432 } 81433 propValue = this._previousStyleCopy = _assign({}, props.style); 81434 } 81435 propValue = CSSPropertyOperations.createMarkupForStyles(propValue, this); 81436 } 81437 var markup = null; 81438 if (this._tag != null && isCustomComponent(this._tag, props)) { 81439 if (!RESERVED_PROPS.hasOwnProperty(propKey)) { 81440 markup = DOMPropertyOperations.createMarkupForCustomAttribute(propKey, propValue); 81441 } 81442 } else { 81443 markup = DOMPropertyOperations.createMarkupForProperty(propKey, propValue); 81444 } 81445 if (markup) { 81446 ret += ' ' + markup; 81447 } 81448 } 81449 } 81450 81451 // For static pages, no need to put React ID and checksum. Saves lots of 81452 // bytes. 81453 if (transaction.renderToStaticMarkup) { 81454 return ret; 81455 } 81456 81457 if (!this._nativeParent) { 81458 ret += ' ' + DOMPropertyOperations.createMarkupForRoot(); 81459 } 81460 ret += ' ' + DOMPropertyOperations.createMarkupForID(this._domID); 81461 return ret; 81462 }, 81463 81464 /** 81465 * Creates markup for the content between the tags. 81466 * 81467 * @private 81468 * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction 81469 * @param {object} props 81470 * @param {object} context 81471 * @return {string} Content markup. 81472 */ 81473 _createContentMarkup: function (transaction, props, context) { 81474 var ret = ''; 81475 81476 // Intentional use of != to avoid catching zero/false. 81477 var innerHTML = props.dangerouslySetInnerHTML; 81478 if (innerHTML != null) { 81479 if (innerHTML.__html != null) { 81480 ret = innerHTML.__html; 81481 } 81482 } else { 81483 var contentToUse = CONTENT_TYPES[typeof props.children] ? props.children : null; 81484 var childrenToUse = contentToUse != null ? null : props.children; 81485 if (contentToUse != null) { 81486 // TODO: Validate that text is allowed as a child of this node 81487 ret = escapeTextContentForBrowser(contentToUse); 81488 } else if (childrenToUse != null) { 81489 var mountImages = this.mountChildren(childrenToUse, transaction, context); 81490 ret = mountImages.join(''); 81491 } 81492 } 81493 if (newlineEatingTags[this._tag] && ret.charAt(0) === '\n') { 81494 // text/html ignores the first character in these tags if it's a newline 81495 // Prefer to break application/xml over text/html (for now) by adding 81496 // a newline specifically to get eaten by the parser. (Alternately for 81497 // textareas, replacing "^\n" with "\r\n" doesn't get eaten, and the first 81498 // \r is normalized out by HTMLTextAreaElement#value.) 81499 // See: <http://www.w3.org/TR/html-polyglot/#newlines-in-textarea-and-pre> 81500 // See: <http://www.w3.org/TR/html5/syntax.html#element-restr
81500ictions> 81501 // See: <http://www.w3.org/TR/html5/syntax.html#newlines> 81502 // See: Parsing of "textarea" "listing" and "pre" elements 81503 // from <http://www.w3.org/TR/html5/syntax.html#parsing-main-inbody> 81504 return '\n' + ret; 81505 } else { 81506 return ret; 81507 } 81508 }, 81509 81510 _createInitialChildren: function (transaction, props, context, lazyTree) { 81511 // Intentional use of != to avoid catching zero/false. 81512 var innerHTML = props.dangerouslySetInnerHTML; 81513 if (innerHTML != null) { 81514 if (innerHTML.__html != null) { 81515 DOMLazyTree.queueHTML(lazyTree, innerHTML.__html); 81516 } 81517 } else { 81518 var contentToUse = CONTENT_TYPES[typeof props.children] ? props.children : null; 81519 var childrenToUse = contentToUse != null ? null : props.children; 81520 if (contentToUse != null) { 81521 // TODO: Validate that text is allowed as a child of this node 81522 DOMLazyTree.queueText(lazyTree, contentToUse); 81523 } else if (childrenToUse != null) { 81524 var mountImages = this.mountChildren(childrenToUse, transaction, context); 81525 for (var i = 0; i < mountImages.length; i++) { 81526 DOMLazyTree.queueChild(lazyTree, mountImages[i]); 81527 } 81528 } 81529 } 81530 }, 81531 81532 /** 81533 * Receives a next element and updates the component. 81534 * 81535 * @internal 81536 * @param {ReactElement} nextElement 81537 * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction 81538 * @param {object} context 81539 */ 81540 receiveComponent: function (nextElement, transaction, context) { 81541 var prevElement = this._currentElement; 81542 this._currentElement = nextElement; 81543 this.updateComponent(transaction, prevElement, nextElement, context); 81544 }, 81545 81546 /** 81547 * Updates a native DOM component after it has already been allocated and 81548 * attached to the DOM. Reconciles the root DOM node, then recurses. 81549 * 81550 * @param {ReactReconcileTransaction} transaction 81551 * @param {ReactElement} prevElement 81552 * @param {ReactElement} nextElement 81553 * @internal 81554 * @overridable 81555 */ 81556 updateComponent: function (transaction, prevElement, nextElement, context) { 81557 var lastProps = prevElement.props; 81558 var nextProps = this._currentElement.props; 81559 81560 switch (this._tag) { 81561 case 'button': 81562 lastProps = ReactDOMButton.getNativeProps(this, lastProps); 81563 nextProps = ReactDOMButton.getNativeProps(this, nextProps); 81564 break; 81565 case 'input': 81566 ReactDOMInput.updateWrapper(this); 81567 lastProps = ReactDOMInput.getNativeProps(this, lastProps); 81568 nextProps = ReactDOMInput.getNativeProps(this, nextProps); 81569 break; 81570 case 'option': 81571 lastProps = ReactDOMOption.getNativeProps(this, lastProps); 81572 nextProps = ReactDOMOption.getNativeProps(this, nextProps); 81573 break; 81574 case 'select': 81575 lastProps = ReactDOMSelect.getNativeProps(this, lastProps); 81576 nextProps = ReactDOMSelect.getNativeProps(this, nextProps); 81577 break; 81578 case 'textarea': 81579 ReactDOMTextarea.updateWrapper(this); 81580 lastProps = ReactDOMTextarea.getNativeProps(this, lastProps); 81581 nextProps = ReactDOMTextarea.getNativeProps(this, nextProps); 81582 break; 81583 } 81584 81585 assertValidProps(this, nextProps); 81586 this._updateDOMProperties(lastProps, nextProps, transaction); 81587 this._updateDOMChildren(lastProps, nextProps, transaction, context); 81588 81589 if (this._tag === 'select') { 81590 // <select> value update needs to occur after <option> children 81591 // reconciliation 81592 transaction.getReactMountReady().enqueue(postUpdateSelectWrapper, this); 81593 } 81594 }, 81595 81596 /** 81597 * Reconciles the properties by detecting differences in property values and 81598 * updating the DOM as necessary. This function is probably the single most 81599 * critical path for performance optimization. 81600 * 81601 * TODO: Benchmark whether checking for changed values in memory actually 81602 * improves performance (especially statically positioned elements). 81603 * TODO: Benchmark the effects of putting this at the top since 99% of props 81604 * do not change for a given reconciliation. 81605 * TODO: Benchmark areas that can be improved with caching. 81606 * 81607 * @private 81608 * @param {object} lastProps 81609 * @param {object} nextProps 81610 * @param {?DOMElement} node 81611 */ 81612 _updateDOMProperties: function (lastProps, nextProps, transaction) { 81613 var propKey; 81614 var styleName; 81615 var styleUpdates; 81616 for (propKey in lastProps) { 81617 if (nextProps.hasOwnProperty(propKey) || !lastProps.hasOwnProperty(propKey) || lastProps[propKey] == null) { 81618 continue; 81619 } 81620 if (propKey === STYLE) { 81621 var lastStyle = this._previousStyleCopy; 81622 for (styleName in lastStyle) { 81623 if (lastStyle.hasOwnProperty(styleName)) { 81624 styleUpdates = styleUpdates || {}; 81625 styleUpdates[styleName] = ''; 81626 } 81627 } 81628 this._previousStyleCopy = null; 81629 } else if (registrationNameModules.hasOwnProperty(propKey)) { 81630 if (lastProps[propKey]) { 81631 // Only call deleteListener if there was a listener previously or 81632 // else willDeleteListener gets called when there wasn't actually a 81633 // listener (e.g., onClick={null}) 81634 deleteListener(this, propKey); 81635 } 81636 } else if (DOMProperty.properties[propKey] || DOMProperty.isCustomAttribute(propKey)) { 81637 DOMPropertyOperations.deleteValueForProperty(getNode(this), propKey); 81638 } 81639 } 81640 for (propKey in nextProps) { 81641 var nextProp = nextProps[propKey]; 81642 var lastProp = propKey === STYLE ? this._previousStyleCopy : lastProps != null ? lastProps[propKey] : undefined; 81643 if (!nextProps.hasOwnProperty(propKey) || nextProp === lastProp || nextProp == null && lastProp == null) { 81644 continue; 81645 } 81646 if (propKey === STYLE) { 81647 if (nextProp) { 81648 if ("development" !== 'production') { 81649 checkAndWarnForMutatedStyle(this._previousStyleCopy, this._previousStyle, this); 81650 this._previousStyle = nextProp; 81651 } 81652 nextProp = this._previousStyleCopy = _assign({}, nextProp); 81653 } else { 81654 this._previousStyleCopy = null; 81655 } 81656 if (lastProp) { 81657 // Unset styles on `lastProp` but not on `nextProp`. 81658 for (styleName in lastProp) { 81659 if (lastProp.hasOwnProperty(styleName) && (!nextProp || !nextProp.hasOwnProperty(styleName))) { 81660 styleUpdates = styleUpdates || {}; 81661 styleUpdates[styleName] = ''; 81662 } 81663 } 81664 // Update styles that changed since `lastProp`. 81665 for (styleName in nextProp) { 81666 if (nextProp.hasOwnProperty(styleName) && lastProp[styleName] !== nextProp[styleName]) { 81667 styleUpdates = styleUpdates || {}; 81668 styleUpdates[styleName] = nextProp[styleName]; 81669 } 81670 } 81671 } else { 81672 // Relies on `updateStylesByID` not mutating `styleUpdates`. 81673 styleUpdates = nextProp; 81674 } 81675 } else if (registrationNameModules.hasOwnProperty(propKey)) { 81676 if (nextProp) { 81677 enqueuePutListener(this, propKey, nextProp, transaction); 81678 } else if (lastProp) { 81679 deleteListener(this, propKey); 81680 } 81681 } else if (isCustomComponent(this._tag, nextProps)) { 81682 if (!RESERVED_PROPS.hasOwnProperty(propKey)) { 81683 DOMPropertyOperations.setValueForAttribute(getNode(this), propKey, nextProp); 81684 } 81685 } else if (DOMProperty.properties[propKey] || DOMProperty.isCustomAttribute(propKey)) { 81686 var node = getNode(this); 81687 // If we're updating to null or undefined, we should remove the property 81688 // from the DOM node instead of inadvertently setting to a string. This 81689 // brings us in line with the same behavior we have on initial render. 81690 if (nextProp != null) { 81691 DOMPropertyOperations.setValueForProperty(node, propKey, nextProp); 81692 } else { 81693 DOMPropertyOperations.deleteValueForProperty(node, propKey); 81694 } 81695 } 81696 } 81697 if (styleUpdates) { 81698 CSSPropertyOperations.setValueForStyles(getNode(this), styleUpdates, this); 81699 } 81700 }, 81701 81702 /** 81703 * Reconciles the children with the various properties that affect the 81704 * children content. 81705 * 81706 * @param {object} lastProps 81707 * @param {object} nextProps 81708 * @param {ReactReconcileTransaction} transaction 81709 * @param {object} context 81710 */ 81711 _updateDOMChildren: function (lastProps, nextProps, transaction, context) { 81712 var lastContent = CONTENT_TYPES[typeof lastProps.children] ? lastProps.children : null; 81713 var nextContent = CONTENT_TYPES[typeof nextProps.children] ? nextProps.children : null; 81714 81715 var lastHtml = lastProps.dangerouslySetInnerHTML && lastProps.dangerouslySetInnerHTML.__html; 81716 var nextHtml = nextProps.dangerouslySetInnerHTML && nextProps.dangerouslySetInnerHTML.__html; 81717 81718 // Note the use of `!=` which checks for null or undefined. 81719 var lastChildren = lastContent != null ? null : lastProps.children; 81720 var nextChildren = nextContent != null ? null : nextProps.children; 81721 81722 // If we're switching from children to content/html or vice versa, remove 81723 // the old content
81724 var lastHasContentOrHtml = lastContent != null || lastHtml != null; 81725 var nextHasContentOrHtml = nextContent != null || nextHtml != null; 81726 if (lastChildren != null && nextChildren == null) { 81727 this.updateChildren(null, transaction, context); 81728 } else if (lastHasContentOrHtml && !nextHasContentOrHtml) { 81729 this.updateTextContent(''); 81730 } 81731 81732 if (nextContent != null) { 81733 if (lastContent !== nextContent) { 81734 this.updateTextContent('' + nextContent); 81735 } 81736 } else if (nextHtml != null) { 81737 if (lastHtml !== nextHtml) { 81738 this.updateMarkup('' + nextHtml); 81739 } 81740 } else if (nextChildren != null) { 81741 this.updateChildren(nextChildren, transaction, context); 81742 } 81743 }, 81744 81745 getNativeNode: function () { 81746 return getNode(this); 81747 }, 81748 81749 /** 81750 * Destroys all event registrations for this instance. Does not remove from 81751 * the DOM. That must be done by the parent. 81752 * 81753 * @internal 81754 */ 81755 unmountComponent: function (safely) { 81756 switch (this._tag) { 81757 case 'iframe': 81758 case 'object': 81759 case 'img': 81760 case 'form': 81761 case 'video': 81762 case 'audio': 81763 var listeners = this._wrapperState.listeners; 81764 if (listeners) { 81765 for (var i = 0; i < listeners.length; i++) { 81766 listeners[i].remove(); 81767 } 81768 } 81769 break; 81770 case 'html': 81771 case 'head': 81772 case 'body': 81773 /** 81774 * Components like <html> <head> and <body> can't be removed or added 81775 * easily in a cross-browser way, however it's valuable to be able to 81776 * take advantage of React's reconciliation for styling and <title> 81777 * management. So we just document it and throw in dangerous cases. 81778 */ 81779 !false ? "development" !== 'production' ? invariant(false, '<%s> tried to unmount. Because of cross-browser quirks it is ' + 'impossible to unmount some top-level components (eg <html>, ' + '<head>, and <body>) reliably and efficiently. To fix this, have a ' + 'single top-level component that never unmounts render these ' + 'elements.', this._tag) : invariant(false) : void 0; 81780 break; 81781 } 81782 81783 this.unmountChildren(safely); 81784 ReactDOMComponentTree.uncacheNode(this); 81785 EventPluginHub.deleteAllListeners(this); 81786 ReactComponentBrowserEnvironment.unmountIDFromEnvironment(this._rootNodeID); 81787 this._rootNodeID = null; 81788 this._domID = null; 81789 this._wrapperState = null; 81790 }, 81791 81792 getPublicInstance: function () { 81793 return getNode(this); 81794 } 81795 81796}; 81797 81798ReactPerf.measureMethods(ReactDOMComponent.Mixin, 'ReactDOMComponent', { 81799 mountComponent: 'mountComponent', 81800 receiveComponent: 'receiveComponent' 81801}); 81802 81803_assign(ReactDOMComponent.prototype, ReactDOMComponent.Mixin, ReactMultiChild.Mixin); 81804 81805module.exports = ReactDOMComponent; 81806},{"1":1,"10":10,"11":11,"119":119,"133":133,"142":142,"158":158,"16":16,"162":162,"167":167,"168":168,"169":169,"17":17,"18":18,"27":27,"32":32,"37":37,"39":39,"4":4,"40":40,"47":47,"49":49,"50":50,"54":54,"76":76,"8":8,"82":82,"9":9}],39:[function(_dereq_,module,exports){ 81807/** 81808 * Copyright 2015-present, Facebook, Inc. 81809 * All rights reserved. 81810 * 81811 * This source code is licensed under the BSD-style license found in the 81812 * LICENSE file in the root directory of this source tree. An additional grant 81813 * of patent rights can be found in the PATENTS file in the same directory. 81814 * 81815 * @providesModule ReactDOMComponentFlags 81816 */ 81817 81818 81819 81820var ReactDOMComponentFlags = { 81821 hasCachedChildNodes: 1 << 0 81822}; 81823 81824module.exports = ReactDOMComponentFlags; 81825},{}],40:[function(_dereq_,module,exports){ 81826/** 81827 * Copyright 2013-present, Facebook, Inc. 81828 * All rights reserved. 81829 * 81830 * This source code is licensed under the BSD-style license found in the 81831 * LICENSE file in the root directory of this source tree. An additional grant 81832 * of patent rights can be found in the PATENTS file in the same directory. 81833 * 81834 * @providesModule ReactDOMComponentTree 81835 */ 81836 81837 81838 81839var DOMProperty = _dereq_(10); 81840var ReactDOMComponentFlags = _dereq_(39); 81841 81842var invariant = _dereq_(158); 81843 81844var ATTR_NAME = DOMProperty.ID_ATTRIBUTE_NAME; 81845var Flags = ReactDOMComponentFlags; 81846 81847var internalInstanceKey = '__reactInternalInstance$' + Math.random().toString(36).slice(2); 81848 81849/** 81850 * Drill down (through composites and empty components) until we get a native or
81851 * native text component. 81852 * 81853 * This is pretty polymorphic but unavoidable with the current structure we have 81854 * for `_renderedChildren`. 81855 */ 81856function getRenderedNativeOrTextFromComponent(component) { 81857 var rendered; 81858 while (rendered = component._renderedComponent) { 81859 component = rendered; 81860 } 81861 return component; 81862} 81863 81864/** 81865 * Populate `_nativeNode` on the rendered native/text component with the given 81866 * DOM node. The passed `inst` can be a composite. 81867 */ 81868function precacheNode(inst, node) { 81869 var nativeInst = getRenderedNativeOrTextFromComponent(inst); 81870 nativeInst._nativeNode = node; 81871 node[internalInstanceKey] = nativeInst; 81872} 81873 81874function uncacheNode(inst) { 81875 var node = inst._nativeNode; 81876 if (node) { 81877 delete node[internalInstanceKey]; 81878 inst._nativeNode = null; 81879 } 81880} 81881 81882/** 81883 * Populate `_nativeNode` on each child of `inst`, assuming that the children 81884 * match up with the DOM (element) children of `node`. 81885 * 81886 * We cache entire levels at once to avoid an n^2 problem where we access the 81887 * children of a node sequentially and have to walk from the start to our target 81888 * node every time. 81889 * 81890 * Since we update `_renderedChildren` and the actual DOM at (slightly) 81891 * different times, we could race here and see a newer `_renderedChildren` than 81892 * the DOM nodes we see. To avoid this, ReactMultiChild calls 81893 * `prepareToManageChildren` before we change `_renderedChildren`, at which 81894 * time the container's child nodes are always cached (until it unmounts). 81895 */ 81896function precacheChildNodes(inst, node) { 81897 if (inst._flags & Flags.hasCachedChildNodes) { 81898 return; 81899 } 81900 var children = inst._renderedChildren; 81901 var childNode = node.firstChild; 81902 outer: for (var name in children) { 81903 if (!children.hasOwnProperty(name)) { 81904 continue; 81905 } 81906 var childInst = children[name]; 81907 var childID = getRenderedNativeOrTextFromComponent(childInst)._domID; 81908 if (childID == null) { 81909 // We're currently unmounting this child in ReactMultiChild; skip it. 81910 continue; 81911 } 81912 // We assume the child nodes are in the same order as the child instances. 81913 for (; childNode !== null; childNode = childNode.nextSibling) { 81914 if (childNode.nodeType === 1 && childNode.getAttribute(ATTR_NAME) === String(childID) || childNode.nodeType === 8 && childNode.nodeValue === ' react-text: ' + childID + ' ' || childNode.nodeType === 8 && childNode.nodeValue === ' react-empty: ' + childID + ' ') { 81915 precacheNode(childInst, childNode); 81916 continue outer; 81917 } 81918 } 81919 // We reached the end of the DOM children without finding an ID match. 81920 !false ? "development" !== 'production' ? invariant(false, 'Unable to find element with ID %s.', childID) : invariant(false) : void 0; 81921 } 81922 inst._flags |= Flags.hasCachedChildNodes; 81923} 81924 81925/** 81926 * Given a DOM node, return the closest ReactDOMComponent or 81927 * ReactDOMTextComponent instance ancestor. 81928 */ 81929function getClosestInstanceFromNode(node) { 81930 if (node[internalInstanceKey]) { 81931 return node[internalInstanceKey]; 81932 } 81933 81934 // Walk up the tree until we find an ancestor whose instance we have cached. 81935 var parents = []; 81936 while (!node[internalInstanceKey]) { 81937 parents.push(node); 81938 if (node.parentNode) { 81939 node = node.parentNode; 81940 } else { 81941 // Top of the tree. This node must not be part of a React tree (or is 81942 // unmounted, potentially). 81943 return null; 81944 } 81945 } 81946 81947 var closest; 81948 var inst; 81949 for (; node && (inst = node[internalInstanceKey]); node = parents.pop()) { 81950 closest = inst; 81951 if (parents.length) { 81952 precacheChildNodes(inst, node); 81953 } 81954 } 81955 81956 return closest; 81957} 81958 81959/** 81960 * Given a DOM node, return the ReactDOMComponent or ReactDOMTextComponent 81961 * instance, or null if the node was not rendered by this React. 81962 */ 81963function getInstanceFromNode(node) { 81964 var inst = getClosestInstanceFromNode(node); 81965 if (inst != null && inst._nativeNode === node) { 81966 return inst; 81967 } else { 81968 return null; 81969 } 81970} 81971 81972/** 81973 * Given a ReactDOMComponent or ReactDOMTextComponent, return the corresponding 81974 * DOM node. 81975 */ 81976function getNodeFromInstance(inst) { 81977 // Without this first invariant, passing a non-DOM-component triggers the next 81978 // invariant for a missing parent, which is super confusing. 81979 !(inst._nativeNode !== undefined) ? "development" !== 'production' ? invariant(false, 'getNodeFromInstance: Invalid argument.') : invariant(false) : void 0; 81980 81981 if (inst._nativeNode) { 81982 return inst._nativeNode; 81983 } 81984 81985 // Walk up the tree until we find an ancestor whose DOM node we have cached. 81986 var parents = []; 81987 while (!inst._nativeNode) { 81988 parents.push(inst); 81989 !inst._nativeParent ? "development" !== 'production' ? invariant(false, 'React DOM tree root should always have a node reference.')
81989: invariant(false) : void 0; 81990 inst = inst._nativeParent; 81991 } 81992 81993 // Now parents contains each ancestor that does *not* have a cached native 81994 // node, and `inst` is the deepest ancestor that does. 81995 for (; parents.length; inst = parents.pop()) { 81996 precacheChildNodes(inst, inst._nativeNode); 81997 } 81998 81999 return inst._nativeNode; 82000} 82001 82002var ReactDOMComponentTree = { 82003 getClosestInstanceFromNode: getClosestInstanceFromNode, 82004 getInstanceFromNode: getInstanceFromNode, 82005 getNodeFromInstance: getNodeFromInstance, 82006 precacheChildNodes: precacheChildNodes, 82007 precacheNode: precacheNode, 82008 uncacheNode: uncacheNode 82009}; 82010 82011module.exports = ReactDOMComponentTree; 82012},{"10":10,"158":158,"39":39}],41:[function(_dereq_,module,exports){ 82013/** 82014 * Copyright 2013-present, Facebook, Inc. 82015 * All rights reserved. 82016 * 82017 * This source code is licensed under the BSD-style license found in the 82018 * LICENSE file in the root directory of this source tree. An additional grant 82019 * of patent rights can be found in the PATENTS file in the same directory. 82020 * 82021 * @providesModule ReactDOMContainerInfo 82022 */ 82023 82024 82025 82026var validateDOMNesting = _dereq_(142); 82027 82028var DOC_NODE_TYPE = 9; 82029 82030function ReactDOMContainerInfo(topLevelWrapper, node) { 82031 var info = { 82032 _topLevelWrapper: topLevelWrapper, 82033 _idCounter: 1, 82034 _ownerDocument: node ? node.nodeType === DOC_NODE_TYPE ? node : node.ownerDocument : null, 82035 _node: node, 82036 _tag: node ? node.nodeName.toLowerCase() : null, 82037 _namespaceURI: node ? node.namespaceURI : null 82038 }; 82039 if ("development" !== 'production') { 82040 info._ancestorInfo = node ? validateDOMNesting.updatedAncestorInfo(null, info._tag, null) : null; 82041 } 82042 return info; 82043} 82044 82045module.exports = ReactDOMContainerInfo; 82046},{"142":142}],42:[function(_dereq_,module,exports){ 82047/** 82048 * Copyright 2013-present, Facebook, Inc. 82049 * All rights reserved. 82050 * 82051 * This source code is licensed under the BSD-style license found in the 82052 * LICENSE file in the root directory of this source tree. An additional grant 82053 * of patent rights can be found in the PATENTS file in the same directory. 82054 * 82055 * @providesModule ReactDOMDebugTool 82056 */ 82057 82058 82059 82060var ReactDOMUnknownPropertyDevtool = _dereq_(56); 82061 82062var warning = _dereq_(168); 82063 82064var eventHandlers = []; 82065var handlerDoesThrowForEvent = {}; 82066 82067function emitEvent(handlerFunctionName, arg1, arg2, arg3, arg4, arg5) { 82068 if ("development" !== 'production') { 82069 eventHandlers.forEach(function (handler) { 82070 try { 82071 if (handler[handlerFunctionName]) { 82072 handler[handlerFunctionName](arg1, arg2, arg3, arg4, arg5); 82073 } 82074 } catch (e) { 82075 "development" !== 'production' ? warning(!handlerDoesThrowForEvent[handlerFunctionName], 'exception thrown by devtool while handling %s: %s', handlerFunctionName, e.message) : void 0; 82076 handlerDoesThrowForEvent[handlerFunctionName] = true; 82077 } 82078 }); 82079 } 82080} 82081 82082var ReactDOMDebugTool = { 82083 addDevtool: function (devtool) { 82084 eventHandlers.push(devtool); 82085 }, 82086 removeDevtool: function (devtool) { 82087 for (var i = 0; i < eventHandlers.length; i++) { 82088 if (eventHandlers[i] === devtool) { 82089 eventHandlers.splice(i, 1); 82090 i--; 82091 } 82092 } 82093 }, 82094 onCreateMarkupForProperty: function (name, value) { 82095 emitEvent('onCreateMarkupForProperty', name, value); 82096 }, 82097 onSetValueForProperty: function (node, name, value) { 82098 emitEvent('onSetValueForProperty', node, name, value); 82099 }, 82100 onDeleteValueForProperty: function (node, name) { 82101 emitEvent('onDeleteValueForProperty', node, name); 82102 } 82103}; 82104 82105ReactDOMDebugTool.addDevtool(ReactDOMUnknownPropertyDevtool); 82106 82107module.exports = ReactDOMDebugTool; 82108},{"168":168,"56":56}],43:[function(_dereq_,module,exports){ 82109/** 82110 * Copyright 2014-present, Facebook, Inc. 82111 * All rights reserved. 82112 * 82113 * This source code is licensed under the BSD-style license found in the 82114 * LICENSE file in the root directory of this source tree. An additional grant 82115 * of patent rights can be found in the PATENTS file in the same directory. 82116 * 82117 * @providesModule ReactDOMEmptyComponent 82118 */ 82119 82120 82121 82122var _assign = _dereq_(169); 82123 82124var DOMLazyTree = _dereq_(8); 82125var ReactDOMComponentTree = _dereq_(40); 82126 82127var ReactDOMEmptyComponent = function (instantiate) { 82128 // ReactCompositeComponent uses this: 82129 this._currentElement = null; 82130 // ReactDOMComponentTree uses these: 82131 this._nativeNode = null; 82132 this._nativeParent = null; 82133 this._nativeContainerInfo = null; 82134 this._domID = null; 82135}; 82136_assign(ReactDOMEmptyComponent.prototype, { 82137 mountComponent: function (transaction, nativeParent, nativeContainerInfo, context) { 82138 var domID = nativeContainerInfo._idCounter++; 82139 this._domID = domID; 82140 this._nativeParent = nativeParent; 82141 this._nativeContainerInfo = nativeContainerInfo; 82142 82143 var nodeValue = ' react-empty: ' + this._domID + ' '; 82144 if (transaction.useCreateElement) { 82145 var ownerDocument = nativeContainerInfo._ownerDocument; 82146 var node = ownerDocument.createComment(nodeValue); 82147 ReactDOMComponentTree.precacheNode(this, node); 82148 return DOMLazyTree(node); 82149 } else { 82150 if (transaction.renderToStaticMarkup) { 82151 // Normally we'd insert a comment node, but since this is a situation 82152 // where React won't take over (static pages), we can simply return 82153 // nothing. 82154 return ''; 82155 } 82156 return '<!--' + nodeValue + '-->'; 82157 } 82158 }, 82159 receiveComponent: function () {}, 82160 getNativeNode: function () { 82161 return ReactDOMComponentTree.getNodeFromInstance(this); 82162 }, 82163 unmountComponent: function () { 82164 ReactDOMComponentTree.uncacheNode(this); 82165 } 82166}); 82167 82168module.exports = ReactDOMEmptyComponent; 82169},{"169":169,"40":40,"8":8}],44:[function(_dereq_,module,exports){ 82170/** 82171 * Copyright 2013-present, Facebook, Inc. 82172 * All rights reserved. 82173 * 82174 * This source code is licensed under the BSD-style license found in the 82175 * LICENSE file in the root directory of this source tree. An additional grant 82176 * of patent rights can be found in the PATENTS file in the same directory. 82177 * 82178 * @providesModule ReactDOMFactories 82179 */ 82180 82181 82182 82183var ReactElement = _dereq_(62); 82184var ReactElementValidator = _dereq_(63); 82185 82186var mapObject = _dereq_(163); 82187 82188/** 82189 * Create a factory that creates HTML tag elements. 82190 * 82191 * @param {string} tag Tag name (e.g. `div`). 82192 * @private 82193 */ 82194function createDOMFactory(tag) { 82195 if ("development" !== 'production') { 82196 return ReactElementValidator.createFactory(tag); 82197 } 82198 return ReactElement.createFactory(tag); 82199} 82200 82201/** 82202 * Creates a mapping from supported HTML tags to `ReactDOMComponent` classes. 82203 * This is also accessible via `React.DOM`. 82204 * 82205 * @public 82206 */ 82207var ReactDOMFactories = mapObject({ 82208 a: 'a', 82209 abbr: 'abbr', 82210 address: 'address', 82211 area: 'area', 82212 article: 'article', 82213 aside: 'aside', 82214 audio: 'audio', 82215 b: 'b', 82216 base: 'base', 82217 bdi: 'bdi', 82218 bdo: 'bdo', 82219 big: 'big', 82220 blockquote: 'blockquote', 82221 body: 'body', 82222 br: 'br', 82223 button: 'button', 82224 canvas: 'canvas', 82225 caption: 'caption', 82226 cite: 'cite',
82227 code: 'code', 82228 col: 'col', 82229 colgroup: 'colgroup', 82230 data: 'data', 82231 datalist: 'datalist', 82232 dd: 'dd', 82233 del: 'del', 82234 details: 'details', 82235 dfn: 'dfn', 82236 dialog: 'dialog', 82237 div: 'div', 82238 dl: 'dl', 82239 dt: 'dt', 82240 em: 'em', 82241 embed: 'embed', 82242 fieldset: 'fieldset', 82243 figcaption: 'figcaption', 82244 figure: 'figure', 82245 footer: 'footer', 82246 form: 'form', 82247 h1: 'h1', 82248 h2: 'h2', 82249 h3: 'h3', 82250 h4: 'h4', 82251 h5: 'h5', 82252 h6: 'h6', 82253 head: 'head', 82254 header: 'header', 82255 hgroup: 'hgroup', 82256 hr: 'hr', 82257 html: 'html', 82258 i: 'i', 82259 iframe: 'iframe', 82260 img: 'img', 82261 input: 'input', 82262 ins: 'ins', 82263 kbd: 'kbd', 82264 keygen: 'keygen', 82265 label: 'label', 82266 legend: 'legend', 82267 li: 'li', 82268 link: 'link', 82269 main: 'main', 82270 map: 'map', 82271 mark: 'mark', 82272 menu: 'menu', 82273 menuitem: 'menuitem', 82274 meta: 'meta', 82275 meter: 'meter', 82276 nav: 'nav', 82277 noscript: 'noscript', 82278 object: 'object', 82279 ol: 'ol', 82280 optgroup: 'optgroup', 82281 option: 'option', 82282 output: 'output', 82283 p: 'p', 82284 param: 'param', 82285 picture: 'picture', 82286 pre: 'pre', 82287 progress: 'progress', 82288 q: 'q', 82289 rp: 'rp', 82290 rt: 'rt', 82291 ruby: 'ruby', 82292 s: 's', 82293 samp: 'samp', 82294 script: 'script', 82295 section: 'section', 82296 select: 'select', 82297 small: 'small', 82298 source: 'source', 82299 span: 'span', 82300 strong: 'strong', 82301 style: 'style', 82302 sub: 'sub', 82303 summary: 'summary', 82304 sup: 'sup', 82305 table: 'table', 82306 tbody: 'tbody', 82307 td: 'td', 82308 textarea: 'textarea', 82309 tfoot: 'tfoot', 82310 th: 'th', 82311 thead: 'thead', 82312 time: 'time', 82313 title: 'title', 82314 tr: 'tr', 82315 track: 'track', 82316 u: 'u', 82317 ul: 'ul', 82318 'var': 'var', 82319 video: 'video', 82320 wbr: 'wbr', 82321 82322 // SVG 82323 circle: 'circle', 82324 clipPath: 'clipPath', 82325 defs: 'defs', 82326 ellipse: 'ellipse', 82327 g: 'g', 82328 image: 'image', 82329 line: 'line', 82330 linearGradient: 'linearGradient', 82331 mask: 'mask', 82332 path: 'path', 82333 pattern: 'pattern', 82334 polygon: 'polygon', 82335 polyline: 'polyline', 82336 radialGradient: 'radialGradient', 82337 rect: 'rect', 82338 stop: 'stop', 82339 svg: 'svg', 82340 text: 'text', 82341 tspan: 'tspan' 82342 82343}, createDOMFactory); 82344 82345module.exports = ReactDOMFactories; 82346},{"163":163,"62":62,"63":63}],45:[function(_dereq_,module,exports){ 82347/** 82348 * Copyright 2013-present, Facebook, Inc. 82349 * All rights reserved. 82350 * 82351 * This source code is licensed under the BSD-style license found in the 82352 * LICENSE file in the root directory of this source tree. An additional grant 82353 * of patent rights can be found in the PATENTS file in the same directory. 82354 * 82355 * @providesModule ReactDOMFeatureFlags 82356 */ 82357 82358 82359 82360var ReactDOMFeatureFlags = { 82361 useCreateElement: true 82362}; 82363 82364module.exports = ReactDOMFeatureFlags; 82365},{}],46:[function(_dereq_,module,exports){ 82366/** 82367 * Copyright 2013-present, Facebook, Inc. 82368 * All rights reserved. 82369 * 82370 * This source code is licensed under the BSD-style license found in the 82371 * LICENSE file in the root directory of this source tree. An additional grant 82372 * of patent rights can be found in the PATENTS file in the same directory. 82373 * 82374 * @providesModule ReactDOMIDOperations 82375 */ 82376 82377 82378 82379var DOMChildrenOperations = _dereq_(7); 82380var ReactDOMComponentTree = _dereq_(40); 82381var ReactPerf = _dereq_(82); 82382 82383/** 82384 * Operations used to process updates to DOM nodes. 82385 */ 82386var ReactDOMIDOperations = { 82387 82388 /** 82389 * Updates a component's children by processing a series of updates. 82390 * 82391 * @param {array<object>} updates List of update configurations. 82392 * @internal 82393 */ 82394 dangerouslyProcessChildrenUpdates: function (parentInst, updates) { 82395 var node = ReactDOMComponentTree.getNodeFromInstance(parentInst); 82396 DOMChildrenOperations.processUpdates(node, updates); 82397 } 82398}; 82399 82400ReactPerf.measureMethods(ReactDOMIDOperations, 'ReactDOMIDOperations', { 82401 dangerouslyProcessChildrenUpdates: 'dangerouslyProcessChildrenUpdates' 82402}); 82403 82404module.exports = ReactDOMIDOperations; 82405},{"40":40,"7":7,"82":82}],47:[function(_dereq_,module,exports){ 82406/** 82407 * Copyright 2013-present, Facebook, Inc. 82408 * All rights reserved. 82409 * 82410 * This source code is licensed under the BSD-style license found in the 82411 * LICENSE file in the root directory of this source tree. An additional grant 82412 * of patent rights can be found in the PATENTS file in the same directory. 82413 * 82414 * @providesModule ReactDOMInput 82415 */ 82416 82417 82418 82419var _assign = _dereq_(169); 82420 82421var DisabledInputUtils = _dereq_(14); 82422var DOMPropertyOperations = _dereq_(11); 82423var LinkedValueUtils = _dereq_(24); 82424var ReactDOMComponentTree = _dereq_(40); 82425var ReactUpdates = _dereq_(94); 82426 82427var invariant = _dereq_(158); 82428var warning = _dereq_(168); 82429 82430var didWarnValueLink = false;
82431var didWarnCheckedLink = false; 82432var didWarnValueNull = false; 82433var didWarnValueDefaultValue = false; 82434var didWarnCheckedDefaultChecked = false; 82435var didWarnControlledToUncontrolled = false; 82436var didWarnUncontrolledToControlled = false; 82437 82438function forceUpdateIfMounted() { 82439 if (this._rootNodeID) { 82440 // DOM component is still mounted; update 82441 ReactDOMInput.updateWrapper(this); 82442 } 82443} 82444 82445function warnIfValueIsNull(props) { 82446 if (props != null && props.value === null && !didWarnValueNull) { 82447 "development" !== 'production' ? warning(false, '`value` prop on `input` should not be null. ' + 'Consider using the empty string to clear the component or `undefined` ' + 'for uncontrolled components.') : void 0; 82448 82449 didWarnValueNull = true; 82450 } 82451} 82452 82453/** 82454 * Implements an <input> native component that allows setting these optional 82455 * props: `checked`, `value`, `defaultChecked`, and `defaultValue`. 82456 * 82457 * If `checked` or `value` are not supplied (or null/undefined), user actions 82458 * that affect the checked state or value will trigger updates to the element. 82459 * 82460 * If they are supplied (and not null/undefined), the rendered element will not 82461 * trigger updates to the element. Instead, the props must change in order for 82462 * the rendered element to be updated. 82463 * 82464 * The rendered element will be initialized as unchecked (or `defaultChecked`) 82465 * with an empty value (or `defaultValue`). 82466 * 82467 * @see http://www.w3.org/TR/2012/WD-html5-20121025/the-input-element.html 82468 */ 82469var ReactDOMInput = { 82470 getNativeProps: function (inst, props) { 82471 var value = LinkedValueUtils.getValue(props); 82472 var checked = LinkedValueUtils.getChecked(props); 82473 82474 var nativeProps = _assign({ 82475 // Make sure we set .type before any other properties (setting .value 82476 // before .type means .value is lost in IE11 and below) 82477 type: undefined 82478 }, DisabledInputUtils.getNativeProps(inst, props), { 82479 defaultChecked: undefined, 82480 defaultValue: undefined, 82481 value: value != null ? value : inst._wrapperState.initialValue, 82482 checked: checked != null ? checked : inst._wrapperState.initialChecked, 82483 onChange: inst._wrapperState.onChange 82484 }); 82485 82486 return nativeProps; 82487 }, 82488 82489 mountWrapper: function (inst, props) { 82490 if ("development" !== 'production') { 82491 LinkedValueUtils.checkPropTypes('input', props, inst._currentElement._owner); 82492 82493 if (props.valueLink !== undefined && !didWarnValueLink) { 82494 "development" !== 'production' ? warning(false, '`valueLink` prop on `input` is deprecated; set `value` and `onChange` instead.') : void 0; 82495 didWarnValueLink = true; 82496 } 82497 if (props.checkedLink !== undefined && !didWarnCheckedLink) { 82498 "development" !== 'production' ? warning(false, '`checkedLink` prop on `input` is deprecated; set `value` and `onChange` instead.') : void 0; 82499 didWarnCheckedLink = true; 82500 } 82501 if (props.checked !== undefined && props.defaultChecked !== undefined && !didWarnCheckedDefaultChecked) { 82502 "development" !== 'production' ? warning(false, 'Input elements must be either controlled or uncontrolled ' + '(specify either the checked prop, or the defaultChecked prop, but not ' + 'both). Decide between using a controlled or uncontrolled input ' + 'element and remove one of these props. More info: ' + 'https://fb.me/react-controlled-components') : void 0; 82503 didWarnCheckedDefaultChecked = true; 82504 } 82505 if (props.value !== undefined && props.defaultValue !== undefined && !didWarnValueDefaultValue) { 82506 "development" !== 'production' ? warning(false, 'Input elements must be either controlled or uncontrolled ' + '(specify either the value prop, or the defaultValue prop, but not ' + 'both). Decide between using a controlled or uncontrolled input ' + 'element and remove one of these props. More info: ' + 'https://fb.me/react-controlled-components') : void 0; 82507 didWarnValueDefaultValue = true; 82508 } 82509 warnIfValueIsNull(props); 82510 } 82511 82512 var defaultValue = props.defaultValue; 82513 inst._wrapperState = { 82514 initialChecked: props.defaultChecked || false, 82515 initialValue: defaultValue != null ? defaultValue : null, 82516 listeners: null, 82517 onChange: _handleChange.bind(inst) 82518 }; 82519 82520 if ("development" !== 'production') { 82521 inst._wrapperState.controlled = props.checked !== undefined || props.value !== undefined; 82522 } 82523 }, 82524 82525 updateWrapper: function (inst) { 82526 var props = inst._currentElement.props; 82527 82528 if ("development" !== 'production') { 82529 warnIfValueIsNull(props); 82530 82531 var initialValue = inst._wrapperState.initialChecked || inst._wrapperState.initialValue; 82532 var defaultValue = props.defaultChecked || props.defaultValue; 82533 var controlled = props.checked !== undefined || props.value !== undefined; 82534 var owner = inst._currentElement._owner; 82535 82536 if ((initialValue || !inst._wrapperState.controlled) && controlled && !didWarnUncontrolledToControlled) { 82537 "development" !== 'production' ? warning(false, '%s is changing a uncontrolled input of type %s to be controlled. ' + 'Input elements should not switch from uncontrolled to controlled (or vice versa). ' + 'Decide between using a controlled or uncontrolled input ' + 'element for the lifetime of the component. More info: https://fb.me/react-controlled-components', owner && owner.getName() || 'A c
82537omponent', props.type) : void 0; 82538 didWarnUncontrolledToControlled = true; 82539 } 82540 if (inst._wrapperState.controlled && (defaultValue || !controlled) && !didWarnControlledToUncontrolled) { 82541 "development" !== 'production' ? warning(false, '%s is changing a controlled input of type %s to be uncontrolled. ' + 'Input elements should not switch from controlled to uncontrolled (or vice versa). ' + 'Decide between using a controlled or uncontrolled input ' + 'element for the lifetime of the component. More info: https://fb.me/react-controlled-components', owner && owner.getName() || 'A component', props.type) : void 0; 82542 didWarnControlledToUncontrolled = true; 82543 } 82544 } 82545 82546 // TODO: Shouldn't this be getChecked(props)? 82547 var checked = props.checked; 82548 if (checked != null) { 82549 DOMPropertyOperations.setValueForProperty(ReactDOMComponentTree.getNodeFromInstance(inst), 'checked', checked || false); 82550 } 82551 82552 var value = LinkedValueUtils.getValue(props); 82553 if (value != null) { 82554 // Cast `value` to a string to ensure the value is set correctly. While 82555 // browsers typically do this as necessary, jsdom doesn't. 82556 DOMPropertyOperations.setValueForProperty(ReactDOMComponentTree.getNodeFromInstance(inst), 'value', '' + value); 82557 } 82558 } 82559}; 82560 82561function _handleChange(event) { 82562 var props = this._currentElement.props; 82563 82564 var returnValue = LinkedValueUtils.executeOnChange(props, event); 82565 82566 // Here we use asap to wait until all updates have propagated, which 82567 // is important when using controlled components within layers: 82568 // https://github.com/facebook/react/issues/1698 82569 ReactUpdates.asap(forceUpdateIfMounted, this); 82570 82571 var name = props.name; 82572 if (props.type === 'radio' && name != null) { 82573 var rootNode = ReactDOMComponentTree.getNodeFromInstance(this); 82574 var queryRoot = rootNode; 82575 82576 while (queryRoot.parentNode) { 82577 queryRoot = queryRoot.parentNode; 82578 } 82579 82580 // If `rootNode.form` was non-null, then we could try `form.elements`, 82581 // but that sometimes behaves strangely in IE8. We could also try using 82582 // `form.getElementsByName`, but that will only return direct children 82583 // and won't include inputs that use the HTML5 `form=` attribute. Since 82584 // the input might not even be in a form, let's just use the global 82585 // `querySelectorAll` to ensure we don't miss anything. 82586 var group = queryRoot.querySelectorAll('input[name=' + JSON.stringify('' + name) + '][type="radio"]'); 82587 82588 for (var i = 0; i < group.length; i++) { 82589 var otherNode = group[i]; 82590 if (otherNode === rootNode || otherNode.form !== rootNode.form) { 82591 continue; 82592 } 82593 // This will throw if radio buttons rendered by different copies of React 82594 // and the same name are rendered into the same form (same as #1939). 82595 // That's probably okay; we don't support it just as we don't support 82596 // mixing React radio buttons with non-React ones. 82597 var otherInstance = ReactDOMComponentTree.getInstanceFromNode(otherNode); 82598 !otherInstance ? "development" !== 'production' ? invariant(false, 'ReactDOMInput: Mixing React and non-React radio inputs with the ' + 'same `name` is not supported.') : invariant(false) : void 0; 82599 // If this is a controlled radio button group, forcing the input that 82600 // was previously checked to update will cause it to be come re-checked 82601 // as appropriate. 82602 ReactUpdates.asap(forceUpdateIfMounted, otherInstance); 82603 } 82604 } 82605 82606 return returnValue; 82607} 82608 82609module.exports = ReactDOMInput; 82610},{"11":11,"14":14,"158":158,"168":168,"169":169,"24":24,"40":40,"94":94}],48:[function(_dereq_,module,exports){ 82611/** 82612 * Copyright 2013-present, Facebook, Inc. 82613 * All rights reserved. 82614 * 82615 * This source code is licensed under the BSD-style license found in the 82616 * LICENSE file in the root directory of this source tree. An additional grant 82617 * of patent rights can be found in the PATENTS file in the same directory. 82618 * 82619 * @providesModule ReactDOMInstrumentation 82620 */ 82621 82622 82623 82624var ReactDOMDebugTool = _dereq_(42); 82625 82626module.exports = { debugTool: ReactDOMDebugTool }; 82627},{"42":42}],49:[function(_dereq_,module,exports){ 82628/** 82629 * Copyright 2013-present, Facebook, Inc. 82630 * All rights reserved. 82631 * 82632 * This source code is licensed under the BSD-style license found in the 82633 * LICENSE file in the root directory of this source tree. An additional grant 82634 * of patent rights can be found in the PATENTS file in the same directory. 82635 * 82636 * @providesModule ReactDOMOption 82637 */ 82638 82639 82640 82641var _assign = _dereq_(169); 82642 82643var ReactChildren = _dereq_(29); 82644var ReactDOMComponentTree = _dereq_(40); 82645var ReactDOMSelect = _dereq_(50); 82646 82647var warning = _dereq_(168); 82648 82649/** 82650 * Implements an <option>
82650 native component that warns when `selected` is set. 82651 */ 82652var ReactDOMOption = { 82653 mountWrapper: function (inst, props, nativeParent) { 82654 // TODO (yungsters): Remove support for `selected` in <option>. 82655 if ("development" !== 'production') { 82656 "development" !== 'production' ? warning(props.selected == null, 'Use the `defaultValue` or `value` props on <select> instead of ' + 'setting `selected` on <option>.') : void 0; 82657 } 82658 82659 // Look up whether this option is 'selected' 82660 var selectValue = null; 82661 if (nativeParent != null) { 82662 var selectParent = nativeParent; 82663 82664 if (selectParent._tag === 'optgroup') { 82665 selectParent = selectParent._nativeParent; 82666 } 82667 82668 if (selectParent != null && selectParent._tag === 'select') { 82669 selectValue = ReactDOMSelect.getSelectValueContext(selectParent); 82670 } 82671 } 82672 82673 // If the value is null (e.g., no specified value or after initial mount) 82674 // or missing (e.g., for <datalist>), we don't change props.selected 82675 var selected = null; 82676 if (selectValue != null) { 82677 selected = false; 82678 if (Array.isArray(selectValue)) { 82679 // multiple 82680 for (var i = 0; i < selectValue.length; i++) { 82681 if ('' + selectValue[i] === '' + props.value) { 82682 selected = true; 82683 break; 82684 } 82685 } 82686 } else { 82687 selected = '' + selectValue === '' + props.value; 82688 } 82689 } 82690 82691 inst._wrapperState = { selected: selected }; 82692 }, 82693 82694 postMountWrapper: function (inst) { 82695 // value="" should make a value attribute (#6219) 82696 var props = inst._currentElement.props; 82697 if (props.value != null) { 82698 var node = ReactDOMComponentTree.getNodeFromInstance(inst); 82699 node.setAttribute('value', props.value); 82700 } 82701 }, 82702 82703 getNativeProps: function (inst, props) { 82704 var nativeProps = _assign({ selected: undefined, children: undefined }, props); 82705 82706 // Read state only from initial mount because <select> updates value 82707 // manually; we need the initial state only for server rendering 82708 if (inst._wrapperState.selected != null) { 82709 nativeProps.selected = inst._wrapperState.selected; 82710 } 82711 82712 var content = ''; 82713 82714 // Flatten children and warn if they aren't strings or numbers; 82715 // invalid types are ignored. 82716 ReactChildren.forEach(props.children, function (child) { 82717 if (child == null) { 82718 return; 82719 } 82720 if (typeof child === 'string' || typeof child === 'number') { 82721 content += child; 82722 } else { 82723 "development" !== 'production' ? warning(false, 'Only strings and numbers are supported as <option> children.') : void 0; 82724 } 82725 }); 82726 82727 if (content) { 82728 nativeProps.children = content; 82729 } 82730 82731 return nativeProps; 82732 } 82733 82734}; 82735 82736module.exports = ReactDOMOption; 82737},{"168":168,"169":169,"29":29,"40":40,"50":50}],50:[function(_dereq_,module,exports){ 82738/** 82739 * Copyright 2013-present, Facebook, Inc. 82740 * All rights reserved. 82741 * 82742 * This source code is licensed under the BSD-style license found in the 82743 * LICENSE file in the root directory of this source tree. An additional grant 82744 * of patent rights can be found in the PATENTS file in the same directory. 82745 * 82746 * @providesModule ReactDOMSelect 82747 */ 82748 82749 82750 82751var _assign = _dereq_(169); 82752 82753var DisabledInputUtils = _dereq_(14); 82754var LinkedValueUtils = _dereq_(24); 82755var ReactDOMComponentTree = _dereq_(40); 82756var ReactUpdates = _dereq_(94); 82757 82758var warning = _dereq_(168); 82759 82760var didWarnValueLink = false; 82761var didWarnValueNull = false; 82762var didWarnValueDefaultValue = false; 82763 82764function updateOptionsIfPendingUpdateAndMounted() { 82765 if (this._rootNodeID && this._wrapperState.pendingUpdate) { 82766 this._wrapperState.pendingUpdate = false; 82767 82768 var props = this._currentElement.props; 82769 var value = LinkedValueUtils.getValue(props); 82770 82771 if (value != null) { 82772 updateOptions(this, Boolean(props.multiple), value); 82773 } 82774 } 82775} 82776 82777function getDeclarationErrorAddendum(owner) { 82778 if (owner) { 82779 var name = owner.getName(); 82780 if (name) { 82781 return ' Check the render method of `' + name + '`.'; 82782 } 82783 } 82784 return ''; 82785} 82786 82787function warnIfValueIsNull(props) { 82788 if (props != null && props.value === null && !didWarnValueNull) { 82789 "development" !== 'production' ? warning(false, '`value` prop on `select` should not be null. ' + 'Consider using the empty string to clear the component or `undefined` ' + 'for uncontrolled components.') : void 0; 82790 82791 didWarnValueNull = true; 82792 } 82793} 82794 82795var valuePropNames = ['value', 'defaultValue']; 82796 82797/** 82798 * Validation function for `value` and `defaultValue`. 82799 * @private 82800 */ 82801function checkSelectPropTypes(inst, props) { 82802 var owner = inst._currentElement._owner; 82803 LinkedValueUtils.checkPropTypes('select', props, owner); 82804 82805 if (props.valueLink !== undefined && !didWarnValueLink) { 82806 "development" !== 'production' ? warning(false, '`valueLink` prop on `select` is deprecated; set `value` and `onChange` instead.') : void 0; 82807 didWarnValueLink = true; 82808 } 82809 82810 for (var i = 0; i < valuePropNames.length; i++) { 82811 var propName = valuePropNames[i]; 82812 if (props[propName] == null) { 82813 continue; 82814 } 82815 if (props.multiple) { 82816 "development" !== 'production' ? warning(Array.isArray(props[propName]), 'The `%s` prop supplied to <select> must be an array if ' + '`multiple` is true.%s', propName, getDeclarationErrorAddendum(owner)) : void 0; 82817 } else { 82818 "development" !== 'production' ? warning(!Array.isArray(props[propName]), 'The `%s` prop supplied to <select> must be a scalar ' + 'value if `multiple` is false.%s', propName, getDeclarationErrorAddendum(owner)) : void 0; 82819 } 82820 } 82821} 82822 82823/** 82824 * @param {ReactDOMComponent} inst 82825 * @param {boolean} multiple 82826 * @param {*} propValue A stringable (with `multiple`, a list of stringables). 82827 * @private 82828 */ 82829function updateOptions(inst, multiple, propValue) { 82830 var selectedValue, i; 82831 var options = ReactDOMComponentTree.getNodeFromInstance(inst).options; 82832 82833 if (multiple) { 82834 selectedValue = {}; 82835 for (i = 0; i < propValue.length; i++) { 82836 selectedValue['' + propValue[i]] = true; 82837 } 82838 for (i = 0; i < options.length; i++) { 82839 var selected = selectedValue.hasOwnProperty(options[i].value); 82840 if (options[i].selected !== selected) { 82841 options[i].selected = selected; 82842 } 82843 } 82844 } else {
82845 // Do not set `select.value` as exact behavior isn't consistent across all 82846 // browsers for all cases. 82847 selectedValue = '' + propValue; 82848 for (i = 0; i < options.length; i++) { 82849 if (options[i].value === selectedValue) { 82850 options[i].selected = true; 82851 return; 82852 } 82853 } 82854 if (options.length) { 82855 options[0].selected = true; 82856 } 82857 } 82858} 82859 82860/** 82861 * Implements a <select> native component that allows optionally setting the 82862 * props `value` and `defaultValue`. If `multiple` is false, the prop must be a 82863 * stringable. If `multiple` is true, the prop must be an array of stringables. 82864 * 82865 * If `value` is not supplied (or null/undefined), user actions that change the 82866 * selected option will trigger updates to the rendered options. 82867 * 82868 * If it is supplied (and not null/undefined), the rendered options will not 82869 * update in response to user actions. Instead, the `value` prop must change in 82870 * order for the rendered options to update. 82871 * 82872 * If `defaultValue` is provided, any options with the supplied values will be 82873 * selected. 82874 */ 82875var ReactDOMSelect = { 82876 getNativeProps: function (inst, props) { 82877 return _assign({}, DisabledInputUtils.getNativeProps(inst, props), { 82878 onChange: inst._wrapperState.onChange, 82879 value: undefined 82880 }); 82881 }, 82882 82883 mountWrapper: function (inst, props) { 82884 if ("development" !== 'production') { 82885 checkSelectPropTypes(inst, props); 82886 warnIfValueIsNull(props); 82887 } 82888 82889 var value = LinkedValueUtils.getValue(props); 82890 inst._wrapperState = { 82891 pendingUpdate: false, 82892 initialValue: value != null ? value : props.defaultValue, 82893 listeners: null, 82894 onChange: _handleChange.bind(inst), 82895 wasMultiple: Boolean(props.multiple) 82896 }; 82897 82898 if (props.value !== undefined && props.defaultValue !== undefined && !didWarnValueDefaultValue) { 82899 "development" !== 'production' ? warning(false, 'Select elements must be either controlled or uncontrolled ' + '(specify either the value prop, or the defaultValue prop, but not ' + 'both). Decide between using a controlled or uncontrolled select ' + 'element and remove one of these props. More info: ' + 'https://fb.me/react-controlled-components') : void 0; 82900 didWarnValueDefaultValue = true; 82901 } 82902 }, 82903 82904 getSelectValueContext: function (inst) { 82905 // ReactDOMOption looks at this initial value so the initial generated 82906 // markup has correct `selected` attributes 82907 return inst._wrapperState.initialValue; 82908 }, 82909 82910 postUpdateWrapper: function (inst) { 82911 var props = inst._currentElement.props; 82912 if ("development" !== 'production') { 82913 warnIfValueIsNull(props); 82914 } 82915 82916 // After the initial mount, we control selected-ness manually so don't pass 82917 // this value down 82918 inst._wrapperState.initialValue = undefined; 82919 82920 var wasMultiple = inst._wrapperState.wasMultiple; 82921 inst._wrapperState.wasMultiple = Boolean(props.multiple); 82922 82923 var value = LinkedValueUtils.getValue(props); 82924 if (value != null) { 82925 inst._wrapperState.pendingUpdate = false; 82926 updateOptions(inst, Boolean(props.multiple), value); 82927 } else if (wasMultiple !== Boolean(props.multiple)) { 82928 // For simplicity, reapply `defaultValue` if `multiple` is toggled. 82929 if (props.defaultValue != null) { 82930 updateOptions(inst, Boolean(props.multiple), props.defaultValue); 82931 } else { 82932 // Revert the select back to its default unselected state. 82933 updateOptions(inst, Boolean(props.multiple), props.multiple ? [] : ''); 82934 } 82935 } 82936 } 82937}; 82938 82939function _handleChange(event) { 82940 var props = this._currentElement.props; 82941 var returnValue = LinkedValueUtils.executeOnChange(props, event); 82942 82943 if (this._rootNodeID) { 82944 this._wrapperState.pendingUpdate = true; 82945 } 82946 ReactUpdates.asap(updateOptionsIfPendingUpdateAndMounted, this); 82947 return returnValue; 82948} 82949 82950module.exports = ReactDOMSelect; 82951},{"14":14,"168":168,"169":169,"24":24,"40":40,"94":94}],51:[function(_dereq_,module,exports){ 82952/** 82953 * Copyright 2013-present, Facebook, Inc. 82954 * All rights reserved. 82955 * 82956 * This source code is licensed under the BSD-style license found in the 82957 * LICENSE file in the root directory of this source tree. An additional grant 82958 * of patent rights can be found in the PATENTS file in the same directory. 82959 * 82960 * @providesModule ReactDOMSelection 82961 */ 82962 82963 82964 82965var ExecutionEnvironment = _dereq_(144); 82966 82967var getNodeForCharacterOffset = _dereq_(129); 82968var getTextContentAccessor = _dereq_(130); 82969 82970/** 82971 * While `isCollapsed` is available on the Selection object and `collapsed` 82972 * is available on the Range object, IE11 sometimes gets them wrong.
82973 * If the anchor/focus nodes and offsets are the same, the range is collapsed. 82974 */ 82975function isCollapsed(anchorNode, anchorOffset, focusNode, focusOffset) { 82976 return anchorNode === focusNode && anchorOffset === focusOffset; 82977} 82978 82979/** 82980 * Get the appropriate anchor and focus node/offset pairs for IE. 82981 * 82982 * The catch here is that IE's selection API doesn't provide information 82983 * about whether the selection is forward or backward, so we have to 82984 * behave as though it's always forward. 82985 * 82986 * IE text differs from modern selection in that it behaves as though 82987 * block elements end with a new line. This means character offsets will 82988 * differ between the two APIs. 82989 * 82990 * @param {DOMElement} node 82991 * @return {object} 82992 */ 82993function getIEOffsets(node) { 82994 var selection = document.selection; 82995 var selectedRange = selection.createRange(); 82996 var selectedLength = selectedRange.text.length; 82997 82998 // Duplicate selection so we can move range without breaking user selection. 82999 var fromStart = selectedRange.duplicate(); 83000 fromStart.moveToElementText(node); 83001 fromStart.setEndPoint('EndToStart', selectedRange); 83002 83003 var startOffset = fromStart.text.length; 83004 var endOffset = startOffset + selectedLength; 83005 83006 return { 83007 start: startOffset, 83008 end: endOffset 83009 }; 83010} 83011 83012/** 83013 * @param {DOMElement} node 83014 * @return {?object} 83015 */ 83016function getModernOffsets(node) { 83017 var selection = window.getSelection && window.getSelection(); 83018 83019 if (!selection || selection.rangeCount === 0) { 83020 return null; 83021 } 83022 83023 var anchorNode = selection.anchorNode; 83024 var anchorOffset = selection.anchorOffset; 83025 var focusNode = selection.focusNode; 83026 var focusOffset = selection.focusOffset; 83027 83028 var currentRange = selection.getRangeAt(0); 83029 83030 // In Firefox, range.startContainer and range.endContainer can be "anonymous 83031 // divs", e.g. the up/down buttons on an <input type="number">. Anonymous 83032 // divs do not seem to expose properties, triggering a "Permission denied 83033 // error" if any of its properties are accessed. The only seemingly possible 83034 // way to avoid erroring is to access a property that typically works for 83035 // non-anonymous divs and catch any error that may otherwise arise. See 83036 // https://bugzilla.mozilla.org/show_bug.cgi?id=208427 83037 try { 83038 /* eslint-disable no-unused-expressions */ 83039 currentRange.startContainer.nodeType; 83040 currentRange.endContainer.nodeType; 83041 /* eslint-enable no-unused-expressions */ 83042 } catch (e) { 83043 return null; 83044 } 83045 83046 // If the node and offset values are the same, the selection is collapsed. 83047 // `Selection.isCollapsed` is available natively, but IE sometimes gets 83048 // this value wrong. 83049 var isSelectionCollapsed = isCollapsed(selection.anchorNode, selection.anchorOffset, selection.focusNode, selection.focusOffset); 83050 83051 var rangeLength = isSelectionCollapsed ? 0 : currentRange.toString().length; 83052 83053 var tempRange = currentRange.cloneRange(); 83054 tempRange.selectNodeContents(node); 83055 tempRange.setEnd(currentRange.startContainer, currentRange.startOffset); 83056 83057 var isTempRangeCollapsed = isCollapsed(tempRange.startContainer, tempRange.startOffset, tempRange.endContainer, tempRange.endOffset); 83058 83059 var start = isTempRangeCollapsed ? 0 : tempRange.toString().length; 83060 var end = start + rangeLength; 83061 83062 // Detect whether the selection is backward. 83063 var detectionRange = document.createRange(); 83064 detectionRange.setStart(anchorNode, anchorOffset); 83065 detectionRange.setEnd(focusNode, focusOffset); 83066 var isBackward = detectionRange.collapsed; 83067 83068 return { 83069 start: isBackward ? end : start, 83070 end: isBackward ? start : end 83071 }; 83072} 83073 83074/** 83075 * @param {DOMElement|DOMTextNode} node 83076 * @param {object} offsets 83077 */ 83078function setIEOffsets(node, offsets) { 83079 var range = document.selection.createRange().duplicate(); 83080 var start, end; 83081 83082 if (offsets.end === undefined) { 83083 start = offsets.start; 83084 end = start; 83085 } else if (offsets.start > offsets.end) { 83086 start = offsets.end; 83087 end = offsets.start; 83088 } else { 83089 start = offsets.start; 83090 end = offsets.end; 83091 } 83092 83093 range.moveToElementText(node); 83094 range.moveStart('character', start); 83095 range.setEndPoint('EndToStart', range); 83096 range.moveEnd('character', end - start); 83097 range.select(); 83098} 83099 83100/** 83101 * In modern non-IE browsers, we can support both forward and backward 83102 * selections. 83103 *
83104 * Note: IE10+ supports the Selection object, but it does not support 83105 * the `extend` method, which means that even in modern IE, it's not possible 83106 * to programmatically create a backward selection. Thus, for all IE 83107 * versions, we use the old IE API to create our selections. 83108 * 83109 * @param {DOMElement|DOMTextNode} node 83110 * @param {object} offsets 83111 */ 83112function setModernOffsets(node, offsets) { 83113 if (!window.getSelection) { 83114 return; 83115 } 83116 83117 var selection = window.getSelection(); 83118 var length = node[getTextContentAccessor()].length; 83119 var start = Math.min(offsets.start, length); 83120 var end = offsets.end === undefined ? start : Math.min(offsets.end, length); 83121 83122 // IE 11 uses modern selection, but doesn't support the extend method. 83123 // Flip backward selections, so we can set with a single range. 83124 if (!selection.extend && start > end) { 83125 var temp = end; 83126 end = start; 83127 start = temp; 83128 } 83129 83130 var startMarker = getNodeForCharacterOffset(node, start); 83131 var endMarker = getNodeForCharacterOffset(node, end); 83132 83133 if (startMarker && endMarker) { 83134 var range = document.createRange(); 83135 range.setStart(startMarker.node, startMarker.offset); 83136 selection.removeAllRanges(); 83137 83138 if (start > end) { 83139 selection.addRange(range); 83140 selection.extend(endMarker.node, endMarker.offset); 83141 } else { 83142 range.setEnd(endMarker.node, endMarker.offset); 83143 selection.addRange(range); 83144 } 83145 } 83146} 83147 83148var useIEOffsets = ExecutionEnvironment.canUseDOM && 'selection' in document && !('getSelection' in window); 83149 83150var ReactDOMSelection = { 83151 /** 83152 * @param {DOMElement} node 83153 */ 83154 getOffsets: useIEOffsets ? getIEOffsets : getModernOffsets, 83155 83156 /** 83157 * @param {DOMElement|DOMTextNode} node 83158 * @param {object} offsets 83159 */ 83160 setOffsets: useIEOffsets ? setIEOffsets : setModernOffsets 83161}; 83162 83163module.exports = ReactDOMSelection; 83164},{"129":129,"130":130,"144":144}],52:[function(_dereq_,module,exports){ 83165/** 83166 * Copyright 2013-present, Facebook, Inc. 83167 * All rights reserved. 83168 * 83169 * This source code is licensed under the BSD-style license found in the 83170 * LICENSE file in the root directory of this source tree. An additional grant 83171 * of patent rights can be found in the PATENTS file in the same directory. 83172 * 83173 * @providesModule ReactDOMServer 83174 */ 83175 83176 83177 83178var ReactDefaultInjection = _dereq_(59); 83179var ReactServerRendering = _dereq_(90); 83180var ReactVersion = _dereq_(95); 83181 83182ReactDefaultInjection.inject(); 83183 83184var ReactDOMServer = { 83185 renderToString: ReactServerRendering.renderToString, 83186 renderToStaticMarkup: ReactServerRendering.renderToStaticMarkup, 83187 version: ReactVersion 83188}; 83189 83190module.exports = ReactDOMServer; 83191},{"59":59,"90":90,"95":95}],53:[function(_dereq_,module,exports){ 83192/** 83193 * Copyright 2013-present, Facebook, Inc. 83194 * All rights reserved. 83195 * 83196 * This source code is licensed under the BSD-style license found in the 83197 * LICENSE file in the root directory of this source tree. An additional grant 83198 * of patent rights can be found in the PATENTS file in the same directory. 83199 * 83200 * @providesModule ReactDOMTextComponent 83201 */ 83202 83203 83204 83205var _assign = _dereq_(169); 83206 83207var DOMChildrenOperations = _dereq_(7); 83208var DOMLazyTree = _dereq_(8); 83209var ReactDOMComponentTree = _dereq_(40); 83210var ReactPerf = _dereq_(82); 83211 83212var escapeTextContentForBrowser = _dereq_(119); 83213var invariant = _dereq_(158); 83214var validateDOMNesting = _dereq_(142); 83215 83216/** 83217 * Text nodes violate a couple assumptions that React makes about components: 83218 * 83219 * - When mounting text into the DOM, adjacent text nodes are merged. 83220 * - Text nodes cannot be assigned a React root ID. 83221 * 83222 * This component is used to wrap strings between comment nodes so that they 83223 * can undergo the same reconciliation that is applied to elements. 83224 * 83225 * TODO: Investigate representing React components in the DOM with text nodes. 83226 * 83227 * @class ReactDOMTextComponent 83228 * @extends ReactComponent 83229 * @internal 83230 */ 83231var ReactDOMTextComponent = function (text) { 83232 // TODO: This is really a ReactText (ReactNode), not a ReactElement 83233 this._currentElement = text; 83234 this._stringText = '' + text; 83235 // ReactDOMComponentTree uses these: 83236 this._nativeNode = null; 83237 this._nativeParent = null; 83238 83239 // Properties 83240 this._domID = null; 83241 this._mountIndex = 0; 83242 this._closingComment = null; 83243 this._commentNodes = null; 83244}; 83245 83246_assign(ReactDOMTextComponent.prototype, { 83247 83248 /**
83249 * Creates the markup for this text node. This node is not intended to have 83250 * any features besides containing text content. 83251 * 83252 * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction 83253 * @return {string} Markup for this text node. 83254 * @internal 83255 */ 83256 mountComponent: function (transaction, nativeParent, nativeContainerInfo, context) { 83257 if ("development" !== 'production') { 83258 var parentInfo; 83259 if (nativeParent != null) { 83260 parentInfo = nativeParent._ancestorInfo; 83261 } else if (nativeContainerInfo != null) { 83262 parentInfo = nativeContainerInfo._ancestorInfo; 83263 } 83264 if (parentInfo) { 83265 // parentInfo should always be present except for the top-level 83266 // component when server rendering 83267 validateDOMNesting('#text', this, parentInfo); 83268 } 83269 } 83270 83271 var domID = nativeContainerInfo._idCounter++; 83272 var openingValue = ' react-text: ' + domID + ' '; 83273 var closingValue = ' /react-text '; 83274 this._domID = domID; 83275 this._nativeParent = nativeParent; 83276 if (transaction.useCreateElement) { 83277 var ownerDocument = nativeContainerInfo._ownerDocument; 83278 var openingComment = ownerDocument.createComment(openingValue); 83279 var closingComment = ownerDocument.createComment(closingValue); 83280 var lazyTree = DOMLazyTree(ownerDocument.createDocumentFragment()); 83281 DOMLazyTree.queueChild(lazyTree, DOMLazyTree(openingComment)); 83282 if (this._stringText) { 83283 DOMLazyTree.queueChild(lazyTree, DOMLazyTree(ownerDocument.createTextNode(this._stringText))); 83284 } 83285 DOMLazyTree.queueChild(lazyTree, DOMLazyTree(closingComment)); 83286 ReactDOMComponentTree.precacheNode(this, openingComment); 83287 this._closingComment = closingComment; 83288 return lazyTree; 83289 } else { 83290 var escapedText = escapeTextContentForBrowser(this._stringText); 83291 83292 if (transaction.renderToStaticMarkup) { 83293 // Normally we'd wrap this between comment nodes for the reasons stated 83294 // above, but since this is a situation where React won't take over 83295 // (static pages), we can simply return the text as it is. 83296 return escapedText; 83297 } 83298 83299 return '<!--' + openingValue + '-->' + escapedText + '<!--' + closingValue + '-->'; 83300 } 83301 }, 83302 83303 /** 83304 * Updates this component by updating the text content. 83305 * 83306 * @param {ReactText} nextText The next text content 83307 * @param {ReactReconcileTransaction} transaction 83308 * @internal 83309 */ 83310 receiveComponent: function (nextText, transaction) { 83311 if (nextText !== this._currentElement) { 83312 this._currentElement = nextText; 83313 var nextStringText = '' + nextText; 83314 if (nextStringText !== this._stringText) { 83315 // TODO: Save this as pending props and use performUpdateIfNecessary 83316 // and/or updateComponent to do the actual update for consistency with 83317 // other component types? 83318 this._stringText = nextStringText; 83319 var commentNodes = this.getNativeNode(); 83320 DOMChildrenOperations.replaceDelimitedText(commentNodes[0], commentNodes[1], nextStringText); 83321 } 83322 } 83323 }, 83324 83325 getNativeNode: function () { 83326 var nativeNode = this._commentNodes; 83327 if (nativeNode) { 83328 return nativeNode; 83329 } 83330 if (!this._closingComment) { 83331 var openingComment = ReactDOMComponentTree.getNodeFromInstance(this);
83332 var node = openingComment.nextSibling; 83333 while (true) { 83334 !(node != null) ? "development" !== 'production' ? invariant(false, 'Missing closing comment for text component %s', this._domID) : invariant(false) : void 0; 83335 if (node.nodeType === 8 && node.nodeValue === ' /react-text ') { 83336 this._closingComment = node; 83337 break; 83338 } 83339 node = node.nextSibling; 83340 } 83341 } 83342 nativeNode = [this._nativeNode, this._closingComment]; 83343 this._commentNodes = nativeNode; 83344 return nativeNode; 83345 }, 83346 83347 unmountComponent: function () { 83348 this._closingComment = null; 83349 this._commentNodes = null; 83350 ReactDOMComponentTree.uncacheNode(this); 83351 } 83352 83353}); 83354 83355ReactPerf.measureMethods(ReactDOMTextComponent.prototype, 'ReactDOMTextComponent', { 83356 mountComponent: 'mountComponent', 83357 receiveComponent: 'receiveComponent' 83358}); 83359 83360module.exports = ReactDOMTextComponent; 83361},{"119":119,"142":142,"158":158,"169":169,"40":40,"7":7,"8":8,"82":82}],54:[function(_dereq_,module,exports){ 83362/** 83363 * Copyright 2013-present, Facebook, Inc. 83364 * All rights reserved. 83365 * 83366 * This source code is licensed under the BSD-style license found in the 83367 * LICENSE file in the root directory of this source tree. An additional grant 83368 * of patent rights can be found in the PATENTS file in the same directory. 83369 * 83370 * @providesModule ReactDOMTextarea 83371 */ 83372 83373 83374 83375var _assign = _dereq_(169); 83376 83377var DisabledInputUtils = _dereq_(14); 83378var DOMPropertyOperations = _dereq_(11); 83379var LinkedValueUtils = _dereq_(24); 83380var ReactDOMComponentTree = _dereq_(40); 83381var ReactUpdates = _dereq_(94); 83382 83383var invariant = _dereq_(158); 83384var warning = _dereq_(168); 83385 83386var didWarnValueLink = false; 83387var didWarnValueNull = false; 83388var didWarnValDefaultVal = false; 83389 83390function forceUpdateIfMounted() { 83391 if (this._rootNodeID) { 83392 // DOM component is still mounted; update 83393 ReactDOMTextarea.updateWrapper(this); 83394 } 83395} 83396 83397function warnIfValueIsNull(props) { 83398 if (props != null && props.value === null && !didWarnValueNull) { 83399 "development" !== 'production' ? warning(false, '`value` prop on `textarea` should not be null. ' + 'Consider using the empty string to clear the component or `undefined` ' + 'for uncontrolled components.') : void 0; 83400 83401 didWarnValueNull = true; 83402 } 83403} 83404 83405/** 83406 * Implements a <textarea> native component that allows setting `value`, and 83407 * `defaultValue`. This differs from the traditional DOM API because value is 83408 * usually set as PCDATA children. 83409 * 83410 * If `value` is not supplied (or null/undefined), user actions that affect the 83411 * value will trigger updates to the element. 83412 * 83413 * If `value` is supplied (and not null/undefined), the rendered element will 83414 * not trigger updates to the element. Instead, the `value` prop must change in 83415 * order for the rendered element to be updated. 83416 * 83417 * The rendered element will be initialized with an empty value, the prop 83418 * `defaultValue` if specified, or the children content (deprecated). 83419 */ 83420var ReactDOMTextarea = { 83421 getNativeProps: function (inst, props) { 83422 !(props.dangerouslySetInnerHTML == null) ? "development" !== 'production' ? invariant(false, '`dangerouslySetInnerHTML` does not make sense on <textarea>.') : invariant(false) : void 0; 83423 83424 // Always set children to the same thing. In IE9, the selection range will 83425 // get reset if `textContent` is mutated. 83426 var nativeProps = _assign({}, DisabledInputUtils.getNativeProps(inst, props), { 83427 defaultValue: undefined, 83428 value: undefined, 83429 children: inst._wrapperState.initialValue, 83430 onChange: inst._wrapperState.onChange 83431 }); 83432 83433 return nativeProps; 83434 }, 83435 83436 mountWrapper: function (inst, props) { 83437 if ("development" !== 'production') { 83438 LinkedValueUtils.checkPropTypes('textarea', props, inst._currentElement._owner); 83439 if (props.valueLink !== undefined && !didWarnValueLink) { 83440 "development" !== 'production' ? warning(false, '`valueLink` prop on `textarea` is deprecated; set `value` and `onChange` instead.') : void 0; 83441 didWarnValueLink = true; 83442 } 83443 if (props.value !== undefined && props.defaultValue !== undefined && !didWarnValDefaultVal) { 83444 "development" !== 'production' ? warning(false, 'Textarea elements must be either controlled or uncontrolled ' + '(specify either the value prop, or the defaultValue prop, but not ' + 'both). Decide between using a controlled or uncontrolled textarea ' + 'and remove one of these props. More info: ' + 'https://fb.me/react-controlled-components') : void 0; 83445 didWarnValDefaultVal = true; 83446 } 83447 warnIfValueIsNull(props); 83448 } 83449 83450 var defaultValue = props.defaultValue; 83451 // TODO (yungsters): Remove support for children content in <textarea>. 83452 var children = props.children; 83453 if (children != null) { 83454 if ("development" !== 'production') { 83455 "development" !== 'production' ? warning(false, 'Use the `defaultValue` or `value` props instead of setting ' + 'children on <textarea>.') : void 0; 83456 } 83457 !(defaultValue == null) ? "development" !== 'production' ? invariant(false, 'If you supply `defaultValue` on a <textarea>, do not pass children.') : invariant(false) : void 0; 83458 if (Array.isArray(children)) { 83459 !(children.length <= 1) ? "development" !== 'production' ? invariant(false, '<textarea> can only have at most one child.') : invariant(false) : void 0; 83460 children = children[0]; 83461 } 83462 83463 defaultValue = '' + children; 83464 } 83465 if (defaultValue == null) { 83466 defaultValue = ''; 83467 } 83468 var value = LinkedValueUtils.getValue(props); 83469 inst._wrapperState = { 83470 // We save the initial value so that `ReactDOMComponent` doesn't update 83471 // `textContent` (unnecessary since we update value). 83472 // The initial value can be a boolean or object so that's why it's 83473 // forced to be a string. 83474 initialValue: '' + (value != null ? value : defaultValue), 83475 listeners: null, 83476 onChange: _handleChange.bind(inst) 83477 }; 83478 }, 83479 83480 updateWrapper: function (inst) { 83481 var props = inst._currentElement.props; 83482 83483 if ("development" !== 'production') { 83484 warnIfValueIsNull(props); 83485 } 83486 83487 var value = LinkedValueUtils.getValue(props); 83488 if (value != null) { 83489 // Cast `value` to a string to ensure the value is set correctly. While 83490 // browsers typically do this as necessary, jsdom doesn't. 83491 DOMPropertyOperations.setValueForProperty(ReactDOMComponentTree.getNodeFromInstance(inst), 'value', '' + value); 83492 } 83493 } 83494}; 83495 83496function _handleChange(event) { 83497 var props = this._currentElement.props; 83498 var returnValue = LinkedValueUtils.executeOnChange(props, event); 83499 ReactUpdates.asap(forceUpdateIfMounted, this); 83500 return returnValue; 83501} 83502 83503module.exports = ReactDOMTextarea; 83504},{"11":11,"14":14,"158":158,"168":168,"169":169,"24":24,"40":40,"94":94}],55:[function(_dereq_,module,exports){ 83505/** 83506 * Copyright 2015-present, Facebook, Inc. 83507 * All rights reserved. 83508 * 83509 * This source code is licensed under the BSD-style license found in the 83510 * LICENSE file in the root directory of this source tree. An additional grant 83511 * of patent rights can be found in the PATENTS file in the same directory. 83512 * 83513 * @providesModule ReactDOMTreeTraversal 83514 */ 83515 83516 83517 83518var invariant = _dereq_(158); 83519 83520/** 83521 * Return the lowest common ancestor of A and B, or null if they are in 83522 * different trees. 83523 */ 83524function getLowestCommonAncestor(instA, instB) { 83525 !('_nativeNode' in instA) ? "development" !== 'production' ? invariant(false, 'getNodeFromInstance: Invalid argument.') : invariant(false) : void 0; 83526 !('_nativeNode' in instB) ? "development" !== 'production' ? invariant(false, 'getNodeFromInstance: Invalid argument.') : invariant(false) : void 0; 83527 83528 var depthA = 0; 83529 for (var tempA = instA; tempA; tempA = tempA._nativeParent) { 83530 depthA++; 83531 } 83532 var depthB = 0; 83533 for (var tempB = instB; tempB; tempB = tempB._nativeParent) { 83534 depthB++; 83535 } 83536 83537 // If A is deeper, crawl up. 83538 while (depthA - depthB > 0) { 83539 instA = instA._nativeParent; 83540 depthA--; 83541 } 83542 83543 // If B is deeper, crawl up. 83544 while (depthB - depthA > 0) { 83545 instB = instB._nativeParent; 83546 depthB--; 83547 } 83548 83549 // Walk in lockstep until we find a match. 83550 var depth = depthA; 83551 while (depth--) { 83552 if (instA === instB) { 83553 return instA; 83554 } 83555 instA = instA._nativeParent; 83556 instB = instB._nativeParent; 83557 } 83558 return null; 83559} 83560 83561/** 83562 * Return if A is an ancestor of B. 83563 */ 83564function isAncestor(instA, instB) { 83565 !('_nativeNode' in instA) ? "development" !== 'production' ? invariant(false, 'isAncestor: Invalid argument.') : invariant(false) : void 0; 83566 !('_nativeNode' in instB) ? "development" !== 'production' ? invariant(false, 'isAncestor: Invalid argument.') : invariant(false) : void 0; 83567 83568 while (instB) { 83569 if (instB === instA) { 83570 return true; 83571 } 83572 instB = instB._nativeParent; 83573 } 83574 return false;
83575} 83576 83577/** 83578 * Return the parent instance of the passed-in instance. 83579 */ 83580function getParentInstance(inst) { 83581 !('_nativeNode' in inst) ? "development" !== 'production' ? invariant(false, 'getParentInstance: Invalid argument.') : invariant(false) : void 0; 83582 83583 return inst._nativeParent; 83584} 83585 83586/** 83587 * Simulates the traversal of a two-phase, capture/bubble event dispatch. 83588 */ 83589function traverseTwoPhase(inst, fn, arg) { 83590 var path = []; 83591 while (inst) { 83592 path.push(inst); 83593 inst = inst._nativeParent; 83594 } 83595 var i; 83596 for (i = path.length; i-- > 0;) { 83597 fn(path[i], false, arg); 83598 } 83599 for (i = 0; i < path.length; i++) { 83600 fn(path[i], true, arg); 83601 } 83602} 83603 83604/** 83605 * Traverses the ID hierarchy and invokes the supplied `cb` on any IDs that 83606 * should would receive a `mouseEnter` or `mouseLeave` event. 83607 * 83608 * Does not invoke the callback on the nearest common ancestor because nothing 83609 * "entered" or "left" that element. 83610 */ 83611function traverseEnterLeave(from, to, fn, argFrom, argTo) { 83612 var common = from && to ? getLowestCommonAncestor(from, to) : null; 83613 var pathFrom = []; 83614 while (from && from !== common) { 83615 pathFrom.push(from); 83616 from = from._nativeParent; 83617 } 83618 var pathTo = []; 83619 while (to && to !== common) { 83620 pathTo.push(to); 83621 to = to._nativeParent; 83622 } 83623 var i; 83624 for (i = 0; i < pathFrom.length; i++) { 83625 fn(pathFrom[i], true, argFrom); 83626 } 83627 for (i = pathTo.length; i-- > 0;) { 83628 fn(pathTo[i], false, argTo); 83629 } 83630} 83631 83632module.exports = { 83633 isAncestor: isAncestor, 83634 getLowestCommonAncestor: getLowestCommonAncestor, 83635 getParentInstance: getParentInstance, 83636 traverseTwoPhase: traverseTwoPhase, 83637 traverseEnterLeave: traverseEnterLeave 83638}; 83639},{"158":158}],56:[function(_dereq_,module,exports){ 83640/** 83641 * Copyright 2013-present, Facebook, Inc. 83642 * All rights reserved. 83643 * 83644 * This source code is licensed under the BSD-style license found in the 83645 * LICENSE file in the root directory of this source tree. An additional grant 83646 * of patent rights can be found in the PATENTS file in the same directory. 83647 * 83648 * @providesModule ReactDOMUnknownPropertyDevtool 83649 */ 83650 83651 83652 83653var DOMProperty = _dereq_(10); 83654var EventPluginRegistry = _dereq_(18); 83655 83656var warning = _dereq_(168); 83657 83658if ("development" !== 'production') { 83659 var reactProps = { 83660 children: true, 83661 dangerouslySetInnerHTML: true, 83662 key: true, 83663 ref: true 83664 }; 83665 var warnedProperties = {}; 83666 83667 var warnUnknownProperty = function (name) { 83668 if (DOMProperty.properties.hasOwnProperty(name) || DOMProperty.isCustomAttribute(name)) { 83669 return; 83670 } 83671 if (reactProps.hasOwnProperty(name) && reactProps[name] || warnedProperties.hasOwnProperty(name) && warnedProperties[name]) { 83672 return; 83673 } 83674 83675 warnedProperties[name] = true; 83676 var lowerCasedName = name.toLowerCase(); 83677 83678 // data-* attributes should be lowercase; suggest the lowercase version 83679 var standardName = DOMProperty.isCustomAttribute(lowerCasedName) ? lowerCasedName : DOMProperty.getPossibleStandardName.hasOwnProperty(lowerCasedName) ? DOMProperty.getPossibleStandardName[lowerCasedName] : null; 83680 83681 // For now, only warn when we have a suggested correction. This prevents 83682 // logging too much when using transferPropsTo. 83683 "development" !== 'production' ? warning(standardName == null, 'Unknown DOM property %s. Did you mean %s?', name, standardName) : void 0; 83684 83685 var registrationName = EventPluginRegistry.possibleRegistrationNames.hasOwnProperty(lowerCasedName) ? EventPluginRegistry.possibleRegistrationNames[lowerCasedName] : null; 83686 83687 "development" !== 'production' ? warning(registrationName == null, 'Unknown event handler property %s. Did you mean `%s`?', name, registrationName) : void 0; 83688 }; 83689} 83690 83691var ReactDOMUnknownPropertyDevtool = { 83692 onCreateMarkupForProperty: function (name, value) { 83693 warnUnknownProperty(name); 83694 }, 83695 onSetValueForProperty: function (node, name, value) { 83696 warnUnknownProperty(name); 83697 }, 83698 onDeleteValueForProperty: function (node, name) { 83699 warnUnknownProperty(name); 83700 } 83701}; 83702 83703module.exports = ReactDOMUnknownPropertyDevtool; 83704},{"10":10,"168":168,"18":18}],57:[function(_dereq_,module,exports){ 83705/** 83706 * Copyright 2016-present, Facebook, Inc. 83707 * All rights reserved. 83708 * 83709 * This source code is licensed under the BSD-style license found in the 83710 * LICENSE file in the root directory of this source tree. An additional grant 83711 * of patent rights can be found in the PATENTS file in the same directory. 83712 * 83713 * @providesModule ReactDebugTool 83714 */ 83715 83716 83717 83718var ReactInvalidSetStateWarningDevTool = _dereq_(73); 83719var warning = _dereq_(168); 83720 83721var eventHandlers = []; 83722var handlerDoesThrowForEvent = {}; 83723 83724function emitEvent(handlerFunctionName, arg1, arg2, arg3, arg4, arg5) { 83725 if ("development" !== 'production') {
83726 eventHandlers.forEach(function (handler) { 83727 try { 83728 if (handler[handlerFunctionName]) { 83729 handler[handlerFunctionName](arg1, arg2, arg3, arg4, arg5); 83730 } 83731 } catch (e) { 83732 "development" !== 'production' ? warning(!handlerDoesThrowForEvent[handlerFunctionName], 'exception thrown by devtool while handling %s: %s', handlerFunctionName, e.message) : void 0; 83733 handlerDoesThrowForEvent[handlerFunctionName] = true; 83734 } 83735 }); 83736 } 83737} 83738 83739var ReactDebugTool = { 83740 addDevtool: function (devtool) { 83741 eventHandlers.push(devtool); 83742 }, 83743 removeDevtool: function (devtool) { 83744 for (var i = 0; i < eventHandlers.length; i++) { 83745 if (eventHandlers[i] === devtool) { 83746 eventHandlers.splice(i, 1); 83747 i--; 83748 } 83749 } 83750 }, 83751 onBeginProcessingChildContext: function () { 83752 emitEvent('onBeginProcessingChildContext'); 83753 }, 83754 onEndProcessingChildContext: function () { 83755 emitEvent('onEndProcessingChildContext'); 83756 }, 83757 onSetState: function () { 83758 emitEvent('onSetState'); 83759 }, 83760 onMountRootComponent: function (internalInstance) { 83761 emitEvent('onMountRootComponent', internalInstance); 83762 }, 83763 onMountComponent: function (internalInstance) { 83764 emitEvent('onMountComponent', internalInstance); 83765 }, 83766 onUpdateComponent: function (internalInstance) { 83767 emitEvent('onUpdateComponent', internalInstance); 83768 }, 83769 onUnmountComponent: function (internalInstance) { 83770 emitEvent('onUnmountComponent', internalInstance); 83771 } 83772}; 83773 83774ReactDebugTool.addDevtool(ReactInvalidSetStateWarningDevTool); 83775 83776module.exports = ReactDebugTool; 83777},{"168":168,"73":73}],58:[function(_dereq_,module,exports){ 83778/** 83779 * Copyright 2013-present, Facebook, Inc. 83780 * All rights reserved. 83781 * 83782 * This source code is licensed under the BSD-style license found in the 83783 * LICENSE file in the root directory of this source tree. An additional grant 83784 * of patent rights can be found in the PATENTS file in the same directory. 83785 * 83786 * @providesModule ReactDefaultBatchingStrategy 83787 */ 83788 83789 83790 83791var _assign = _dereq_(169); 83792 83793var ReactUpdates = _dereq_(94); 83794var Transaction = _dereq_(112); 83795 83796var emptyFunction = _dereq_(150); 83797 83798var RESET_BATCHED_UPDATES = { 83799 initialize: emptyFunction, 83800 close: function () { 83801 ReactDefaultBatchingStrategy.isBatchingUpdates = false; 83802 } 83803}; 83804 83805var FLUSH_BATCHED_UPDATES = { 83806 initialize: emptyFunction, 83807 close: ReactUpdates.flushBatchedUpdates.bind(ReactUpdates) 83808}; 83809 83810var TRANSACTION_WRAPPERS = [FLUSH_BATCHED_UPDATES, RESET_BATCHED_UPDATES]; 83811 83812function ReactDefaultBatchingStrategyTransaction() { 83813 this.reinitializeTransaction(); 83814} 83815 83816_assign(ReactDefaultBatchingStrategyTransaction.prototype, Transaction.Mixin, { 83817 getTransactionWrappers: function () { 83818 return TRANSACTION_WRAPPERS; 83819 } 83820}); 83821 83822var transaction = new ReactDefaultBatchingStrategyTransaction(); 83823 83824var ReactDefaultBatchingStrategy = { 83825 isBatchingUpdates: false, 83826 83827 /** 83828 * Call the provided function in a context within which calls to `setState` 83829 * and friends are batched such that components aren't updated unnecessarily. 83830 */ 83831 batchedUpdates: function (callback, a, b, c, d, e) { 83832 var alreadyBatchingUpdates = ReactDefaultBatchingStrategy.isBatchingUpdates; 83833 83834 ReactDefaultBatchingStrategy.isBatchingUpdates = true; 83835 83836 // The code is written this way to avoid extra allocations 83837 if (alreadyBatchingUpdates) { 83838 callback(a, b, c, d, e); 83839 } else { 83840 transaction.perform(callback, null, a, b, c, d, e); 83841 } 83842 } 83843}; 83844 83845module.exports = ReactDefaultBatchingStrategy; 83846},{"112":112,"150":150,"169":169,"94":94}],59:[function(_dereq_,module,exports){ 83847/** 83848 * Copyright 2013-present, Facebook, Inc. 83849 * All rights reserved. 83850 * 83851 * This source code is licensed under the BSD-style license found in the 83852 * LICENSE file in the root directory of this source tree. An additional grant 83853 * of patent rights can be found in the PATENTS file in the same directory. 83854 * 83855 * @providesModule ReactDefaultInjection 83856 */ 83857 83858 83859 83860var BeforeInputEventPlugin = _dereq_(2); 83861var ChangeEventPlugin = _dereq_(6); 83862var DefaultEventPluginOrder = _dereq_(13); 83863var EnterLeaveEventPlugin = _dereq_(15); 83864var ExecutionEnvironment = _dereq_(144); 83865var HTMLDOMPropertyConfig = _dereq_(22); 83866var ReactComponentBrowserEnvironment = _dereq_(32); 83867var ReactDOMComponent = _dereq_(38); 83868var ReactDOMComponentTree = _dereq_(40); 83869var ReactDOMEmptyComponent = _dereq_(43); 83870var ReactDOMTreeTraversal = _dereq_(55); 83871var ReactDOMTextComponent = _dereq_(53); 83872var ReactDefaultBatchingStrategy = _dereq_(58); 83873var ReactEventListener = _dereq_(67); 83874var ReactInjection = _dereq_(69); 83875var ReactReconcileTransaction = _dereq_(86); 83876var SVGDOMPropertyConfig = _dereq_(96); 83877var SelectEventPlugin = _dereq_(97); 83878var SimpleEventPlugin = _dereq_(98); 83879 83880var alreadyInjected = false;
83881 83882function inject() { 83883 if (alreadyInjected) { 83884 // TODO: This is currently true because these injections are shared between 83885 // the client and the server package. They should be built independently 83886 // and not share any injection state. Then this problem will be solved. 83887 return; 83888 } 83889 alreadyInjected = true; 83890 83891 ReactInjection.EventEmitter.injectReactEventListener(ReactEventListener); 83892 83893 /** 83894 * Inject modules for resolving DOM hierarchy and plugin ordering. 83895 */ 83896 ReactInjection.EventPluginHub.injectEventPluginOrder(DefaultEventPluginOrder); 83897 ReactInjection.EventPluginUtils.injectComponentTree(ReactDOMComponentTree); 83898 ReactInjection.EventPluginUtils.injectTreeTraversal(ReactDOMTreeTraversal); 83899 83900 /** 83901 * Some important event plugins included by default (without having to require 83902 * them). 83903 */ 83904 ReactInjection.EventPluginHub.injectEventPluginsByName({ 83905 SimpleEventPlugin: SimpleEventPlugin, 83906 EnterLeaveEventPlugin: EnterLeaveEventPlugin, 83907 ChangeEventPlugin: ChangeEventPlugin, 83908 SelectEventPlugin: SelectEventPlugin, 83909 BeforeInputEventPlugin: BeforeInputEventPlugin 83910 }); 83911 83912 ReactInjection.NativeComponent.injectGenericComponentClass(ReactDOMComponent); 83913 83914 ReactInjection.NativeComponent.injectTextComponentClass(ReactDOMTextComponent); 83915 83916 ReactInjection.DOMProperty.injectDOMPropertyConfig(HTMLDOMPropertyConfig); 83917 ReactInjection.DOMProperty.injectDOMPropertyConfig(SVGDOMPropertyConfig); 83918 83919 ReactInjection.EmptyComponent.injectEmptyComponentFactory(function (instantiate) { 83920 return new ReactDOMEmptyComponent(instantiate); 83921 }); 83922 83923 ReactInjection.Updates.injectReconcileTransaction(ReactReconcileTransaction); 83924 ReactInjection.Updates.injectBatchingStrategy(ReactDefaultBatchingStrategy); 83925 83926 ReactInjection.Component.injectEnvironment(ReactComponentBrowserEnvironment); 83927 83928 if ("development" !== 'production') { 83929 var url = ExecutionEnvironment.canUseDOM && window.location.href || ''; 83930 if (/[?&]react_perf\b/.test(url)) { 83931 var ReactDefaultPerf = _dereq_(60); 83932 ReactDefaultPerf.start(); 83933 } 83934 } 83935} 83936 83937module.exports = { 83938 inject: inject 83939}; 83940},{"13":13,"144":144,"15":15,"2":2,"22":22,"32":32,"38":38,"40":40,"43":43,"53":53,"55":55,"58":58,"6":6,"60":60,"67":67,"69":69,"86":86,"96":96,"97":97,"98":98}],60:[function(_dereq_,module,exports){ 83941/** 83942 * Copyright 2013-present, Facebook, Inc. 83943 * All rights reserved. 83944 * 83945 * This source code is licensed under the BSD-style license found in the 83946 * LICENSE file in the root directory of this source tree. An additional grant 83947 * of patent rights can be found in the PATENTS file in the same directory. 83948 * 83949 * @providesModule ReactDefaultPerf 83950 */ 83951 83952 83953 83954var DOMProperty = _dereq_(10); 83955var ReactDOMComponentTree = _dereq_(40); 83956var ReactDefaultPerfAnalysis = _dereq_(61); 83957var ReactMount = _dereq_(75); 83958var ReactPerf = _dereq_(82); 83959 83960var performanceNow = _dereq_(166); 83961var warning = _dereq_(168); 83962 83963function roundFloat(val) { 83964 return Math.floor(val * 100) / 100; 83965} 83966 83967function addValue(obj, key, val) { 83968 obj[key] = (obj[key] || 0) + val; 83969} 83970 83971// Composite/text components don't have any built-in ID: we have to make our own 83972var compositeIDMap; 83973var compositeIDCounter = 17000; 83974function getIDOfComposite(inst) { 83975 if (!compositeIDMap) { 83976 compositeIDMap = new WeakMap(); 83977 } 83978 if (compositeIDMap.has(inst)) { 83979 return compositeIDMap.get(inst); 83980 } else { 83981 var id = compositeIDCounter++; 83982 compositeIDMap.set(inst, id); 83983 return id; 83984 } 83985} 83986 83987function getID(inst) { 83988 if (inst.hasOwnProperty('_rootNodeID')) { 83989 return inst._rootNodeID; 83990 } else { 83991 return getIDOfComposite(inst); 83992 } 83993} 83994 83995function stripComplexValues(key, value) { 83996 if (typeof value !== 'object' || Array.isArray(value) || value == null) { 83997 return value; 83998 } 83999 var prototype = Object.getPrototypeOf(value); 84000 if (!prototype || prototype === Object.prototype) { 84001 return value; 84002 } 84003 return '<not serializable>'; 84004} 84005 84006// This implementation of ReactPerf is going away some time mid 15.x. 84007// While we plan to keep most of the API, the actual format of measurements 84008// will change dramatically. To signal this, we wrap them into an opaque-ish 84009// object to discourage reaching into it until the API stabilizes. 84010function wrapLegacyMeasurements(measurements) { 84011 return { __unstable_this_format_will_change: measurements }; 84012} 84013function unwrapLegacyMeasurements(measurements) { 84014 return measurements && measurements.__unstable_this_format_will_change || measurements; 84015} 84016 84017var warnedAboutPrintDOM = false;
84018var warnedAboutGetMeasurementsSummaryMap = false; 84019 84020var ReactDefaultPerf = { 84021 _allMeasurements: [], // last item in the list is the current one 84022 _mountStack: [0], 84023 _compositeStack: [], 84024 _injected: false, 84025 84026 start: function () { 84027 if (!ReactDefaultPerf._injected) { 84028 ReactPerf.injection.injectMeasure(ReactDefaultPerf.measure); 84029 } 84030 84031 ReactDefaultPerf._allMeasurements.length = 0; 84032 ReactPerf.enableMeasure = true; 84033 }, 84034 84035 stop: function () { 84036 ReactPerf.enableMeasure = false; 84037 }, 84038 84039 getLastMeasurements: function () { 84040 return wrapLegacyMeasurements(ReactDefaultPerf._allMeasurements); 84041 }, 84042 84043 printExclusive: function (measurements) { 84044 measurements = unwrapLegacyMeasurements(measurements || ReactDefaultPerf._allMeasurements); 84045 var summary = ReactDefaultPerfAnalysis.getExclusiveSummary(measurements); 84046 console.table(summary.map(function (item) { 84047 return { 84048 'Component class name': item.componentName, 84049 'Total inclusive time (ms)': roundFloat(item.inclusive), 84050 'Exclusive mount time (ms)': roundFloat(item.exclusive), 84051 'Exclusive render time (ms)': roundFloat(item.render), 84052 'Mount time per instance (ms)': roundFloat(item.exclusive / item.count), 84053 'Render time per instance (ms)': roundFloat(item.render / item.count), 84054 'Instances': item.count 84055 }; 84056 })); 84057 // TODO: ReactDefaultPerfAnalysis.getTotalTime() does not return the correct 84058 // number. 84059 }, 84060 84061 printInclusive: function (measurements) { 84062 measurements = unwrapLegacyMeasurements(measurements || ReactDefaultPerf._allMeasurements); 84063 var summary = ReactDefaultPerfAnalysis.getInclusiveSummary(measurements); 84064 console.table(summary.map(function (item) { 84065 return { 84066 'Owner > component': item.componentName, 84067 'Inclusive time (ms)': roundFloat(item.time), 84068 'Instances': item.count 84069 }; 84070 })); 84071 console.log('Total time:', ReactDefaultPerfAnalysis.getTotalTime(measurements).toFixed(2) + ' ms'); 84072 }, 84073 84074 getMeasurementsSummaryMap: function (measurements) { 84075 "development" !== 'production' ? warning(warnedAboutGetMeasurementsSummaryMap, '`ReactPerf.getMeasurementsSummaryMap(...)` is deprecated. Use ' + '`ReactPerf.getWasted(...)` instead.') : void 0; 84076 warnedAboutGetMeasurementsSummaryMap = true; 84077 return ReactDefaultPerf.getWasted(measurements); 84078 }, 84079 84080 getWasted: function (measurements) { 84081 measurements = unwrapLegacyMeasurements(measurements); 84082 var summary = ReactDefaultPerfAnalysis.getInclusiveSummary(measurements, true); 84083 return summary.map(function (item) { 84084 return { 84085 'Owner > component': item.componentName, 84086 'Wasted time (ms)': item.time, 84087 'Instances': item.count 84088 }; 84089 }); 84090 }, 84091 84092 printWasted: function (measurements) { 84093 measurements = unwrapLegacyMeasurements(measurements || ReactDefaultPerf._allMeasurements); 84094 console.table(ReactDefaultPerf.getWasted(measurements)); 84095 console.log('Total time:', ReactDefaultPerfAnalysis.getTotalTime(measurements).toFixed(2) + ' ms'); 84096 }, 84097 84098 printDOM: function (measurements) { 84099 "development" !== 'production' ? warning(warnedAboutPrintDOM, '`ReactPerf.printDOM(...)` is deprecated. Use ' + '`ReactPerf.printOperations(...)` instead.') : void 0; 84100 warnedAboutPrintDOM = true; 84101 return ReactDefaultPerf.printOperations(measurements); 84102 }, 84103 84104 printOperations: function (measurements) { 84105 measurements = unwrapLegacyMeasurements(measurements || ReactDefaultPerf._allMeasurements); 84106 var summary = ReactDefaultPerfAnalysis.getDOMSummary(measurements); 84107 console.table(summary.map(function (item) { 84108 var result = {}; 84109 result[DOMProperty.ID_ATTRIBUTE_NAME] = item.id; 84110 result.type = item.type; 84111 result.args = JSON.stringify(item.args, stripComplexValues); 84112 return result; 84113 })); 84114 console.log('Total time:', ReactDefaultPerfAnalysis.getTotalTime(measurements).toFixed(2) + ' ms'); 84115 }, 84116 84117 _recordWrite: function (id, fnName, totalTime, args) { 84118 // TODO: totalTime isn't that useful since it doesn't count paints/reflows 84119 var entry = ReactDefaultPerf._allMeasurements[ReactDefaultPerf._allMeasurements.length - 1]; 84120 var writes = entry.writes; 84121 writes[id] = writes[id] || []; 84122 writes[id].push({ 84123 type: fnName, 84124 time: totalTime, 84125 args: args 84126 }); 84127 }, 84128 84129 measure: function (moduleName, fnName, func) { 84130 return function () { 84131 for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { 84132 args[_key] = arguments[_key]; 84133 } 84134 84135 var totalTime; 84136 var rv; 84137 var start; 84138 84139 var entry = ReactDefaultPerf._allMeasurements[ReactDefaultPerf._allMeasurements.length - 1]; 84140 84141 if (fnName === '_renderNewRootComponent' || fnName === 'flushBatchedUp
84141dates') { 84142 // A "measurement" is a set of metrics recorded for each flush. We want 84143 // to group the metrics for a given flush together so we can look at the 84144 // components that rendered and the DOM operations that actually 84145 // happened to determine the amount of "wasted work" performed. 84146 ReactDefaultPerf._allMeasurements.push(entry = { 84147 exclusive: {}, 84148 inclusive: {}, 84149 render: {}, 84150 counts: {}, 84151 writes: {}, 84152 displayNames: {}, 84153 hierarchy: {}, 84154 totalTime: 0, 84155 created: {} 84156 }); 84157 start = performanceNow(); 84158 rv = func.apply(this, args); 84159 entry.totalTime = performanceNow() - start; 84160 return rv; 84161 } else if (fnName === '_mountImageIntoNode' || moduleName === 'ReactDOMIDOperations' || moduleName === 'CSSPropertyOperations' || moduleName === 'DOMChildrenOperations' || moduleName === 'DOMPropertyOperations' || moduleName === 'ReactComponentBrowserEnvironment') { 84162 start = performanceNow(); 84163 rv = func.apply(this, args); 84164 totalTime = performanceNow() - start; 84165 84166 if (fnName === '_mountImageIntoNode') { 84167 ReactDefaultPerf._recordWrite('', fnName, totalTime, args[0]); 84168 } else if (fnName === 'dangerouslyProcessChildrenUpdates') { 84169 // special format 84170 args[1].forEach(function (update) { 84171 var writeArgs = {}; 84172 if (update.fromIndex !== null) { 84173 writeArgs.fromIndex = update.fromIndex; 84174 } 84175 if (update.toIndex !== null) { 84176 writeArgs.toIndex = update.toIndex; 84177 } 84178 if (update.content !== null) { 84179 writeArgs.content = update.content; 84180 } 84181 ReactDefaultPerf._recordWrite(args[0]._rootNodeID, update.type, totalTime, writeArgs); 84182 }); 84183 } else { 84184 // basic format 84185 var id = args[0]; 84186 if (moduleName === 'EventPluginHub') { 84187 id = id._rootNodeID; 84188 } else if (fnName === 'replaceNodeWithMarkup') { 84189 // Old node is already unmounted; can't get its instance 84190 id = ReactDOMComponentTree.getInstanceFromNode(args[1].node)._rootNodeID; 84191 } else if (fnName === 'replaceDelimitedText') { 84192 id = getID(ReactDOMComponentTree.getInstanceFromNode(args[0])); 84193 } else if (typeof id === 'object') { 84194 id = getID(ReactDOMComponentTree.getInstanceFromNode(args[0])); 84195 } 84196 ReactDefaultPerf._recordWrite(id, fnName, totalTime, Array.prototype.slice.call(args, 1)); 84197 } 84198 return rv; 84199 } else if (moduleName === 'ReactCompositeComponent' && (fnName === 'mountComponent' || fnName === 'updateComponent' || // TODO: receiveComponent()? 84200 fnName === '_renderValidatedComponent')) { 84201 84202 if (this._currentElement.type === ReactMount.TopLevelWrapper) { 84203 return func.apply(this, args); 84204 } 84205 84206 var rootNodeID = getIDOfComposite(this); 84207 var isRender = fnName === '_renderValidatedComponent'; 84208 var isMount = fnName === 'mountComponent'; 84209 84210 var mountStack = ReactDefaultPerf._mountStack; 84211 84212 if (isRender) { 84213 addValue(entry.counts, rootNodeID, 1); 84214 } else if (isMount) { 84215 entry.created[rootNodeID] = true; 84216 mountStack.push(0); 84217 } 84218 84219 ReactDefaultPerf._compositeStack.push(rootNodeID); 84220 84221 start = performanceNow(); 84222 rv = func.apply(this, args); 84223 totalTime = performanceNow() - start; 84224 84225 ReactDefaultPerf._compositeStack.pop(); 84226 84227 if (isRender) { 84228 addValue(entry.render, rootNodeID, totalTime); 84229 } else if (isMount) { 84230 var subMountTime = mountStack.pop(); 84231 mountStack[mountStack.length - 1] += totalTime; 84232 addValue(entry.exclusive, rootNodeID, totalTime - subMountTime); 84233 addValue(entry.inclusive, rootNodeID, totalTime); 84234 } else { 84235 addValue(entry.inclusive, rootNodeID, totalTime); 84236 } 84237 84238 entry.displayNames[rootNodeID] = { 84239 current: this.getName(), 84240 owner: this._currentElement._owner ? this._currentElement._owner.getName() : '<root>' 84241 }; 84242 84243 return rv; 84244 } else if ((moduleName === 'ReactDOMComponent' || moduleName === 'ReactDOMTextComponent') && (fnName === 'mountComponent' || fnName === 'receiveComponent')) { 84245 84246 rv = func.apply(this, args); 84247 entry.hierarchy[getID(this)] = ReactDefaultPerf._compositeStack.slice(); 84248 return rv; 84249 } else { 84250 return func.apply(this, args); 84251 } 84252 }; 84253 } 84254}; 84255 84256module.exports = ReactDefaultPerf; 84257},{"10":10,"166":166,"168":168,"40":40,"61":61,"75":75,"82":82}],61:[function(_dereq_,module,exports){ 84258/** 84259 * Copyright 2013-present, Facebook, Inc. 84260 * All rights reserved. 84261 * 84262 * This source code is licensed under the BSD-style license found in the 84263 * LICENSE file in the root directory of this source tree. An additional grant 84264 * of patent rights can be found in the PATENTS file in the same directory. 84265 * 84266 * @providesModule ReactDefaultPerfAnalysis 84267 */ 84268 84269 84270 84271// Don't try to save users less than 1.2ms (a number I made up) 84272 84273var _assign = _dereq_(169); 84274 84275var DONT_CARE_THRESHOLD = 1.2; 84276var DOM_OPERATION_TYPES = {
84277 '_mountImageIntoNode': 'set innerHTML', 84278 INSERT_MARKUP: 'set innerHTML', 84279 MOVE_EXISTING: 'move', 84280 REMOVE_NODE: 'remove', 84281 SET_MARKUP: 'set innerHTML', 84282 TEXT_CONTENT: 'set textContent', 84283 'setValueForProperty': 'update attribute', 84284 'setValueForAttribute': 'update attribute', 84285 'deleteValueForProperty': 'remove attribute', 84286 'setValueForStyles': 'update styles', 84287 'replaceNodeWithMarkup': 'replace', 84288 'replaceDelimitedText': 'replace' 84289}; 84290 84291function getTotalTime(measurements) { 84292 // TODO: return number of DOM ops? could be misleading. 84293 // TODO: measure dropped frames after reconcile? 84294 // TODO: log total time of each reconcile and the top-level component 84295 // class that triggered it. 84296 var totalTime = 0; 84297 for (var i = 0; i < measurements.length; i++) { 84298 var measurement = measurements[i]; 84299 totalTime += measurement.totalTime; 84300 } 84301 return totalTime; 84302} 84303 84304function getDOMSummary(measurements) { 84305 var items = []; 84306 measurements.forEach(function (measurement) { 84307 Object.keys(measurement.writes).forEach(function (id) { 84308 measurement.writes[id].forEach(function (write) { 84309 items.push({ 84310 id: id, 84311 type: DOM_OPERATION_TYPES[write.type] || write.type, 84312 args: write.args 84313 }); 84314 }); 84315 }); 84316 }); 84317 return items; 84318} 84319 84320function getExclusiveSummary(measurements) { 84321 var candidates = {}; 84322 var displayName; 84323 84324 for (var i = 0; i < measurements.length; i++) { 84325 var measurement = measurements[i]; 84326 var allIDs = _assign({}, measurement.exclusive, measurement.inclusive); 84327 84328 for (var id in allIDs) { 84329 displayName = measurement.displayNames[id].current; 84330 84331 candidates[displayName] = candidates[displayName] || { 84332 componentName: displayName, 84333 inclusive: 0, 84334 exclusive: 0, 84335 render: 0, 84336 count: 0 84337 }; 84338 if (measurement.render[id]) { 84339 candidates[displayName].render += measurement.render[id]; 84340 } 84341 if (measurement.exclusive[id]) { 84342 candidates[displayName].exclusive += measurement.exclusive[id]; 84343 } 84344 if (measurement.inclusive[id]) { 84345 candidates[displayName].inclusive += measurement.inclusive[id]; 84346 } 84347 if (measurement.counts[id]) { 84348 candidates[displayName].count += measurement.counts[id]; 84349 } 84350 } 84351 } 84352 84353 // Now make a sorted array with the results. 84354 var arr = []; 84355 for (displayName in candidates) { 84356 if (candidates[displayName].exclusive >= DONT_CARE_THRESHOLD) { 84357 arr.push(candidates[displayName]); 84358 } 84359 } 84360 84361 arr.sort(function (a, b) { 84362 return b.exclusive - a.exclusive; 84363 }); 84364 84365 return arr; 84366} 84367 84368function getInclusiveSummary(measurements, onlyClean) { 84369 var candidates = {}; 84370 var inclusiveKey; 84371 84372 for (var i = 0; i < measurements.length; i++) { 84373 var measurement = measurements[i]; 84374 var allIDs = _assign({}, measurement.exclusive, measurement.inclusive); 84375 var cleanComponents; 84376 84377 if (onlyClean) { 84378 cleanComponents = getUnchangedComponents(measurement); 84379 } 84380 84381 for (var id in allIDs) { 84382 if (onlyClean && !cleanComponents[id]) { 84383 continue; 84384 } 84385 84386 var displayName = measurement.displayNames[id]; 84387 84388 // Inclusive time is not useful for many components without knowing where 84389 // they are instantiated. So we aggregate inclusive time with both the 84390 // owner and current displayName as the key. 84391 inclusiveKey = displayName.owner + ' > ' + displayName.current; 84392 84393 candidates[inclusiveKey] = candidates[inclusiveKey] || { 84394 componentName: inclusiveKey, 84395 time: 0, 84396 count: 0 84397 }; 84398 84399 if (measurement.inclusive[id]) { 84400 candidates[inclusiveKey].time += measurement.inclusive[id]; 84401 } 84402 if (measurement.counts[id]) { 84403 candidates[inclusiveKey].count += measurement.counts[id]; 84404 } 84405 } 84406 } 84407 84408 // Now make a sorted array with the results. 84409 var arr = []; 84410 for (inclusiveKey in candidates) { 84411 if (candidates[inclusiveKey].time >= DONT_CARE_THRESHOLD) { 84412 arr.push(candidates[inclusiveKey]); 84413 } 84414 } 84415 84416 arr.sort(function (a, b) { 84417 return b.time - a.time; 84418 }); 84419 84420 return arr; 84421} 84422 84423function getUnchangedComponents(measurement) { 84424 // For a given reconcile, look at which components did not actually 84425 // render anything to the DOM and return a mapping of their ID to 84426 // the amount of time it took to render the entire subtree. 84427 var cleanComponents = {}; 84428 var writes = measurement.writes; 84429 var hierarchy = measurement.hierarchy; 84430 var dirtyComposites = {};
84431 Object.keys(writes).forEach(function (id) { 84432 writes[id].forEach(function (write) { 84433 // Root mounting (innerHTML set) is recorded with an ID of '' 84434 if (id !== '' && hierarchy.hasOwnProperty(id)) { 84435 hierarchy[id].forEach(function (c) { 84436 return dirtyComposites[c] = true; 84437 }); 84438 } 84439 }); 84440 }); 84441 var allIDs = _assign({}, measurement.exclusive, measurement.inclusive); 84442 84443 for (var id in allIDs) { 84444 var isDirty = false; 84445 // See if any of the DOM operations applied to this component's subtree. 84446 if (dirtyComposites[id]) { 84447 isDirty = true; 84448 } 84449 // check if component newly created 84450 if (measurement.created[id]) { 84451 isDirty = true; 84452 } 84453 if (!isDirty && measurement.counts[id] > 0) { 84454 cleanComponents[id] = true; 84455 } 84456 } 84457 return cleanComponents; 84458} 84459 84460var ReactDefaultPerfAnalysis = { 84461 getExclusiveSummary: getExclusiveSummary, 84462 getInclusiveSummary: getInclusiveSummary, 84463 getDOMSummary: getDOMSummary, 84464 getTotalTime: getTotalTime 84465}; 84466 84467module.exports = ReactDefaultPerfAnalysis; 84468},{"169":169}],62:[function(_dereq_,module,exports){ 84469/** 84470 * Copyright 2014-present, Facebook, Inc. 84471 * All rights reserved. 84472 * 84473 * This source code is licensed under the BSD-style license found in the 84474 * LICENSE file in the root directory of this source tree. An additional grant 84475 * of patent rights can be found in the PATENTS file in the same directory. 84476 * 84477 * @providesModule ReactElement 84478 */ 84479 84480 84481 84482var _assign = _dereq_(169); 84483 84484var ReactCurrentOwner = _dereq_(35); 84485 84486var warning = _dereq_(168); 84487var canDefineProperty = _dereq_(116); 84488 84489// The Symbol used to tag the ReactElement type. If there is no native Symbol 84490// nor polyfill, then a plain number is used for performance. 84491var REACT_ELEMENT_TYPE = typeof Symbol === 'function' && Symbol['for'] && Symbol['for']('react.element') || 0xeac7; 84492 84493var RESERVED_PROPS = { 84494 key: true, 84495 ref: true, 84496 __self: true, 84497 __source: true 84498}; 84499 84500var specialPropKeyWarningShown, specialPropRefWarningShown; 84501 84502/** 84503 * Factory method to create a new React element. This no longer adheres to 84504 * the class pattern, so do not use new to call it. Also, no instanceof check 84505 * will work. Instead test $$typeof field against Symbol.for('react.element') to check 84506 * if something is a React Element. 84507 * 84508 * @param {*} type 84509 * @param {*} key 84510 * @param {string|object} ref 84511 * @param {*} self A *temporary* helper to detect places where `this` is 84512 * different from the `owner` when React.createElement is called, so that we 84513 * can warn. We want to get rid of owner and replace string `ref`s with arrow 84514 * functions, and as long as `this` and owner are the same, there will be no 84515 * change in behavior. 84516 * @param {*} source An annotation object (added by a transpiler or otherwise) 84517 * indicating filename, line number, and/or other information. 84518 * @param {*} owner 84519 * @param {*} props 84520 * @internal 84521 */ 84522var ReactElement = function (type, key, ref, self, source, owner, props) { 84523 var element = { 84524 // This tag allow us to uniquely identify this as a React Element 84525 $$typeof: REACT_ELEMENT_TYPE, 84526 84527 // Built-in properties that belong on the element 84528 type: type, 84529 key: key, 84530 ref: ref, 84531 props: props, 84532 84533 // Record the component responsible for creating this element. 84534 _owner: owner 84535 }; 84536 84537 if ("development" !== 'production') { 84538 // The validation flag is currently mutative. We put it on 84539 // an external backing store so that we can freeze the whole object. 84540 // This can be replaced with a WeakMap once they are implemented in 84541 // commonly used development environments. 84542 element._store = {}; 84543 84544 // To make comparing ReactElements easier for testing purposes, we make 84545 // the validation flag non-enumerable (where possible, which should 84546 // include every environment we run tests in), so the test framework 84547 // ignores it. 84548 if (canDefineProperty) { 84549 Object.defineProperty(element._store, 'validated', { 84550 configurable: false, 84551 enumerable: false, 84552 writable: true, 84553 value: false 84554 }); 84555 // self and source are DEV only properties. 84556 Object.defineProperty(element, '_self', { 84557 configurable: false, 84558 enumerable: false, 84559 writable: false, 84560 value: self 84561 }); 84562 // Two elements created in two different places should be considered 84563 // equal for testing purposes and therefore we hide it from enumeration. 84564 Object.defineProperty(element, '_source', { 84565 configurable: false, 84566 enumerable: false, 84567 writable: false, 84568 value: source 84569 }); 84570 } else { 84571 element._store.validated = false;
84572 element._self = self; 84573 element._source = source; 84574 } 84575 if (Object.freeze) { 84576 Object.freeze(element.props); 84577 Object.freeze(element); 84578 } 84579 } 84580 84581 return element; 84582}; 84583 84584ReactElement.createElement = function (type, config, children) { 84585 var propName; 84586 84587 // Reserved names are extracted 84588 var props = {}; 84589 84590 var key = null; 84591 var ref = null; 84592 var self = null; 84593 var source = null; 84594 84595 if (config != null) { 84596 if ("development" !== 'production') { 84597 ref = !config.hasOwnProperty('ref') || Object.getOwnPropertyDescriptor(config, 'ref').get ? null : config.ref; 84598 key = !config.hasOwnProperty('key') || Object.getOwnPropertyDescriptor(config, 'key').get ? null : '' + config.key; 84599 } else { 84600 ref = config.ref === undefined ? null : config.ref; 84601 key = config.key === undefined ? null : '' + config.key; 84602 } 84603 self = config.__self === undefined ? null : config.__self; 84604 source = config.__source === undefined ? null : config.__source; 84605 // Remaining properties are added to a new props object 84606 for (propName in config) { 84607 if (config.hasOwnProperty(propName) && !RESERVED_PROPS.hasOwnProperty(propName)) { 84608 props[propName] = config[propName]; 84609 } 84610 } 84611 } 84612 84613 // Children can be more than one argument, and those are transferred onto 84614 // the newly allocated props object. 84615 var childrenLength = arguments.length - 2; 84616 if (childrenLength === 1) { 84617 props.children = children; 84618 } else if (childrenLength > 1) { 84619 var childArray = Array(childrenLength); 84620 for (var i = 0; i < childrenLength; i++) { 84621 childArray[i] = arguments[i + 2]; 84622 } 84623 props.children = childArray; 84624 } 84625 84626 // Resolve default props 84627 if (type && type.defaultProps) { 84628 var defaultProps = type.defaultProps; 84629 for (propName in defaultProps) { 84630 if (props[propName] === undefined) { 84631 props[propName] = defaultProps[propName]; 84632 } 84633 } 84634 } 84635 if ("development" !== 'production') { 84636 // Create dummy `key` and `ref` property to `props` to warn users 84637 // against its use 84638 if (typeof props.$$typeof === 'undefined' || props.$$typeof !== REACT_ELEMENT_TYPE) { 84639 if (!props.hasOwnProperty('key')) { 84640 Object.defineProperty(props, 'key', { 84641 get: function () { 84642 if (!specialPropKeyWarningShown) { 84643 specialPropKeyWarningShown = true; 84644 "development" !== 'production' ? warning(false, '%s: `key` is not a prop. Trying to access it will result ' + 'in `undefined` being returned. If you need to access the same ' + 'value within the child component, you should pass it as a different ' + 'prop. (https://fb.me/react-special-props)', typeof type === 'function' && 'displayName' in type ? type.displayName : 'Element') : void 0; 84645 } 84646 return undefined; 84647 }, 84648 configurable: true 84649 }); 84650 } 84651 if (!props.hasOwnProperty('ref')) { 84652 Object.defineProperty(props, 'ref', { 84653 get: function () { 84654 if (!specialPropRefWarningShown) { 84655 specialPropRefWarningShown = true; 84656 "development" !== 'production' ? warning(false, '%s: `ref` is not a prop. Trying to access it will result ' + 'in `undefined` being returned. If you need to access the same ' + 'value within the child component, you should pass it as a different ' + 'prop. (https://fb.me/react-special-props)', typeof type === 'function' && 'displayName' in type ? type.displayName : 'Element') : void 0; 84657 } 84658 return undefined; 84659 }, 84660 configurable: true 84661 }); 84662 } 84663 } 84664 } 84665 return ReactElement(type, key, ref, self, source, ReactCurrentOwner.current, props); 84666}; 84667 84668ReactElement.createFactory = function (type) { 84669 var factory = ReactElement.createElement.bind(null, type); 84670 // Expose the type on the factory and the prototype so that it can be 84671 // easily accessed on elements. E.g. `<Foo />.type === Foo`. 84672 // This should not be named `constructor` since this may not be the function 84673 // that created the element, and it may not even be a constructor. 84674 // Legacy hook TODO: Warn if this is accessed 84675 factory.type = type; 84676 return factory; 84677}; 84678 84679ReactElement.cloneAndReplaceKey = function (oldElement, newKey) { 84680 var newElement = ReactElement(oldElement.type, newKey, oldElement.ref, oldElement._self, oldElement._source, oldElement._owner, oldElement.props); 84681 84682 return newElement; 84683}; 84684 84685ReactElement.cloneElement = function (element, config, children) { 84686 var propName; 84687 84688 // Original props are copied 84689 var props = _assign({}, element.props); 84690 84691 // Reserved names are extracted 84692 var key = element.key; 84693 var ref = element.ref; 84694 // Self is preserved since the owner is preserved. 84695 var self = element._self; 84696 // Source is preserved since cloneElement is unlikely to be targeted by a 84697 // transpiler, and the original source is probably a better indicator of the 84698 // true owner. 84699 var source = element._source; 84700 84701 // Owner will be preserved, unless ref is overridden 84702 var owner = element._owner; 84703 84704 if (config != null) { 84705 if (config.ref !== undefined) { 84706 // Silently steal the ref from the parent. 84707 ref = config.ref; 84708 owner = ReactCurrentOwner.current; 84709 } 84710 if (config.key !== undefined) { 84711 key = '' + config.key; 84712 } 84713 // Remaining properties override existing props 84714 var defaultProps; 84715 if (element.type && element.type.defaultProps) { 84716 defaultProps = element.type.defaultProps; 84717 } 84718 for (propName in config) { 84719 if (config.hasOwnProperty(propName) && !RESERVED_PROPS.hasOwnProperty(propName)) { 84720 if (config[propName] === undefined && defaultProps !== undefined) { 84721 // Resolve default props 84722 props[propName] = defaultProps[propName]; 84723 } else { 84724 props[propName] = config[propName]; 84725 } 84726 } 84727 } 84728 } 84729 84730 // Children can be more than one argument, and those are transferred onto 84731 // the newly allocated props object. 84732 var childrenLength = arguments.length - 2; 84733 if (childrenLength === 1) { 84734 props.children = children; 84735 } else if (childrenLength > 1) { 84736 var childArray = Array(childrenLength); 84737 for (var i = 0; i < childrenLength; i++) { 84738 childArray[i] = arguments[i + 2]; 84739 } 84740 props.children = childArray; 84741 } 84742 84743 return ReactElement(element.type, key, ref, self, source, owner, props); 84744}; 84745 84746/** 84747 * @param {?object} object 84748 * @return {boolean} True if `object` is a valid component. 84749 * @final 84750 */ 84751ReactElement.isValidElement = function (object) { 84752 return typeof object === 'object' && object !== null && object.$$typeof === REACT_ELEMENT_TYPE; 84753}; 84754 84755module.exports = ReactElement; 84756},{"116":116,"168":168,"169":169,"35":35}],63:[function(_dereq_,module,exports){ 84757/** 84758 * Copyright 2014-present, Facebook, Inc. 84759 * All rights reserved. 84760 * 84761 * This source code is licensed under the BSD-style license found in the 84762 * LICENSE file in the root directory of this source tree. An additional grant 84763 * of patent rights can be found in the PATENTS file in the same directory. 84764 * 84765 * @providesModule ReactElementValidator 84766 */ 84767 84768/** 84769 * ReactElementValidator provides a wrapper around a element factory 84770 * which validates the props passed to the element. This is intended to be 84771 * used only in DEV and could be replaced by a static type checker for languages 84772 * that support it. 84773 */ 84774 84775 84776 84777var ReactElement = _dereq_(62); 84778var ReactPropTypeLocations = _dereq_(84); 84779var ReactPropTypeLocationNames = _dereq_(83); 84780var ReactCurrentOwner = _dereq_(35); 84781 84782var canDefineProperty = _dereq_(116); 84783var getIteratorFn = _dereq_(127); 84784var invariant = _dereq_(158); 84785var warning = _dereq_(168); 84786 84787function getDeclarationErrorAddendum() { 84788 if (ReactCurrentOwner.current) { 84789 var name = ReactCurrentOwner.current.getName(); 84790 if (name) { 84791 return ' Check the render method of `' + name + '`.'; 84792 } 84793 } 84794 return ''; 84795} 84796 84797/** 84798 * Warn if there's no key explicitly set on dynamic arrays of children or 84799 * object keys are not valid. This allows us to keep track of children between 84800 * updates. 84801 */ 84802var ownerHasKeyUseWarning = {}; 84803 84804var loggedTypeFailures = {}; 84805 84806/** 84807 * Warn if the element doesn't have an explicit key assigned to it. 84808 * This element is in an array. The array could grow and shrink or be 84809 * reordered. All children that haven't already been validated are required to 84810 * have a "key" property assigned to it. 84811 * 84812 * @internal 84813 * @param {ReactElement} element Element that requires a key. 84814 * @param {*} parentType element's parent's type. 84815 */ 84816function validateExplicitKey(element, parentType) { 84817 if (!element._store || element._store.validated || element.key != null) { 84818 return; 84819 } 84820 element._store.validated = true; 84821 84822 var addenda = getAddendaForKeyUse('uniqueKey', element, parentType); 84823 if (addenda === null) { 84824 // we already showed the warning 84825 return; 84826 } 84827 "development" !== 'production' ? warning(false, 'Each child in an array or iterator should have a unique "key" prop.' + '%s%s%s', addenda.parentOrOwner || '', addenda.childOwner || '', addenda.url || '') : void 0; 84828} 84829 84830/** 84831 * Shared warning and monitoring code for the key warnings. 84832 * 84833 * @internal 84834 * @param {string} messageType A key used for de-duping warnings. 84835 * @param {ReactElement} element Component that requires a key. 84836 * @param {*} parentType element's parent's type. 84837 * @returns {?object} A set of addenda to use in the warning message, or null 84838 * if the warning has already been shown before (and shouldn't be shown again). 84839 */ 84840function getAddendaForKeyUse(messageType, element, parentType) { 84841 var addendum = getDeclarationErrorAddendum(); 84842 if (!addendum) { 84843 var parentName = typeof parentType === 'string' ? parentType : parentType.displayName || parentType.name; 84844 if (parentName) { 84845 addendum = ' Check the top-level render call using <' + parentName + '>.'; 84846 } 84847 } 84848 84849 var memoizer = ownerHasKeyUseWarning[messageType] || (ownerHasKeyUseWarning[messageType] = {}); 84850 if (memoizer[addendum]) { 84851 return null; 84852 } 84853 memoizer[addendum] = true; 84854 84855 var addenda = { 84856 parentOrOwner: addendum, 84857 url: ' See https://fb.me/react-warning-keys for more information.', 84858 childOwner: null 84859 }; 84860 84861 // Usually the current owner is the offender, but if it accepts children as a 84862 // property, it may be the creator of the child that's responsible for 84863 // assigning it a key. 84864 if (element && element._owner && element._owner !== ReactCurrentOwner.current) { 84865 // Give the component that originally created this child. 84866 addenda.childOwner = ' It was passed a child from ' + element._owner.getName() + '.'; 84867 } 84868 84869 return addenda; 84870} 84871 84872/** 84873 * Ensure that every element either is passed in a static location, in an 84874 * array with an explicit keys property defined, or in an object literal 84875 * with valid key property. 84876 * 84877 * @internal 84878 * @param {ReactNode} node Statically passed child of any type. 84879 * @param {*} parentType node's parent's type. 84880 */ 84881function validateChildKeys(node, parentType) { 84882 if (typeof node !== 'object') { 84883 return; 84884 } 84885 if (Array.isArray(node)) { 84886 for (var i = 0; i < node.length; i++) { 84887 var child = node[i]; 84888 if (ReactElement.isValidElement(child)) { 84889 validateExplicitKey(child, parentType); 84890 } 84891 } 84892 } else if (ReactElement.isValidElement(node)) { 84893 // This element was passed in a valid location. 84894 if (node._store) { 84895 node._store.validated = true; 84896 } 84897 } else if (node) { 84898 var iteratorFn = getIteratorFn(node); 84899 // Entry iterators provide implicit keys. 84900 if (iteratorFn) { 84901 if (iteratorFn !== node.entries) { 84902 var iterator = iteratorFn.call(node); 84903 var step; 84904 while (!(step = iterator.next()).done) { 84905 if (ReactElement.isValidElement(step.value)) { 84906 validateExplicitKey(step.value, parentType); 84907 } 84908 } 84909 } 84910 } 84911 } 84912} 84913 84914/** 84915 * Assert that the props are valid 84916 * 84917 * @param {string} componentName Name of the component for error messages. 84918 * @param {object} propTypes Map of prop name to a ReactPropType 84919 * @param {object} props 84920 * @param {string} location e.g. "prop", "context", "child context" 84921 * @private 84922 */ 84923function checkPropTypes(componentName, propTypes, props, location) { 84924 for (var propName in propTypes) { 84925 if (propTypes.hasOwnProperty(propName)) { 84926 var error; 84927 // Prop type validation may throw. In case they do, we don't want to 84928 // fail the render phase where it didn't fail before. So we log it. 84929 // After these have been cleaned up, we'll let them throw.
84930 try { 84931 // This is intentionally an invariant that gets caught. It's the same 84932 // behavior as without this statement except with a better message. 84933 !(typeof propTypes[propName] === 'function') ? "development" !== 'production' ? invariant(false, '%s: %s type `%s` is invalid; it must be a function, usually from ' + 'React.PropTypes.', componentName || 'React class', ReactPropTypeLocationNames[location], propName) : invariant(false) : void 0; 84934 error = propTypes[propName](props, propName, componentName, location); 84935 } catch (ex) { 84936 error = ex; 84937 } 84938 "development" !== 'production' ? warning(!error || error instanceof Error, '%s: type specification of %s `%s` is invalid; the type checker ' + 'function must return `null` or an `Error` but returned a %s. ' + 'You may have forgotten to pass an argument to the type checker ' + 'creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and ' + 'shape all require an argument).', componentName || 'React class', ReactPropTypeLocationNames[location], propName, typeof error) : void 0; 84939 if (error instanceof Error && !(error.message in loggedTypeFailures)) { 84940 // Only monitor this failure once because there tends to be a lot of the 84941 // same error. 84942 loggedTypeFailures[error.message] = true; 84943 84944 var addendum = getDeclarationErrorAddendum(); 84945 "development" !== 'production' ? warning(false, 'Failed propType: %s%s', error.message, addendum) : void 0; 84946 } 84947 } 84948 } 84949} 84950 84951/** 84952 * Given an element, validate that its props follow the propTypes definition, 84953 * provided by the type. 84954 * 84955 * @param {ReactElement} element 84956 */ 84957function validatePropTypes(element) { 84958 var componentClass = element.type; 84959 if (typeof componentClass !== 'function') { 84960 return; 84961 } 84962 var name = componentClass.displayName || componentClass.name; 84963 if (componentClass.propTypes) { 84964 checkPropTypes(name, componentClass.propTypes, element.props, ReactPropTypeLocations.prop); 84965 } 84966 if (typeof componentClass.getDefaultProps === 'function') { 84967 "development" !== 'production' ? warning(componentClass.getDefaultProps.isReactClassApproved, 'getDefaultProps is only used on classic React.createClass ' + 'definitions. Use a static property named `defaultProps` instead.') : void 0; 84968 } 84969} 84970 84971var ReactElementValidator = { 84972 84973 createElement: function (type, props, children) { 84974 var validType = typeof type === 'string' || typeof type === 'function'; 84975 // We warn in this case but don't throw. We expect the element creation to 84976 // succeed and there will likely be errors in render. 84977 "development" !== 'production' ? warning(validType, 'React.createElement: type should not be null, undefined, boolean, or ' + 'number. It should be a string (for DOM elements) or a ReactClass ' + '(for composite components).%s', getDeclarationErrorAddendum()) : void 0; 84978 84979 var element = ReactElement.createElement.apply(this, arguments); 84980 84981 // The result can be nullish if a mock or a custom function is used. 84982 // TODO: Drop this when these are no longer allowed as the type argument. 84983 if (element == null) { 84984 return element; 84985 } 84986 84987 // Skip key warning if the type isn't valid since our key validation logic 84988 // doesn't expect a non-string/function type and can throw confusing errors. 84989 // We don't want exception behavior to differ between dev and prod. 84990 // (Rendering will throw with a helpful message and as soon as the type is 84991 // fixed, the key warnings will appear.) 84992 if (validType) { 84993 for (var i = 2; i < arguments.length; i++) { 84994 validateChildKeys(arguments[i], type); 84995 } 84996 } 84997 84998 validatePropTypes(element); 84999 85000 return element; 85001 }, 85002 85003 createFactory: function (type) { 85004 var validatedFactory = ReactElementValidator.createElement.bind(null, type); 85005 // Legacy hook TODO: Warn if this is accessed 85006 validatedFactory.type = type; 85007 85008 if ("development" !== 'production') { 85009 if (canDefineProperty) { 85010 Object.defineProperty(validatedFactory, 'type', { 85011 enumerable: false, 85012 get: function () { 85013 "development" !== 'production' ? warning(false, 'Factory.type is deprecated. Access the class directly ' + 'before passing it to createFactory.') : void 0; 85014 Object.defineProperty(this, 'type', { 85015 value: type 85016 }); 85017 return type; 85018 } 85019 }); 85020 } 85021 } 85022 85023 return validatedFactory; 85024 }, 85025 85026 cloneElement: function (element, props, children) { 85027 var newElement = ReactElement.cloneElement.apply(this, arguments); 85028 for (var i = 2; i < arguments.length; i++) { 85029 validateChildKeys(arguments[i], newElement.type); 85030 } 85031 validatePropTypes(newElement); 85032 return newElement; 85033 } 85034 85035}; 85036 85037module.exports = ReactElementValidator; 85038},{"116":116,"127":127,"158":158,"168":168,"35":35,"62":62,"83":83,"84":84}],64:[function(_dereq_,module,exports){ 85039/** 85040 * Copyright 2014-present, Facebook, Inc. 85041 * All rights reserved. 85042 * 85043 * This source code is licensed under the BSD-style license found in the 85044 * LICENSE file in the root directory of this source tree. An additional grant 85045 * of patent rights can be found in the PATENTS file in the same directory. 85046 * 85047 * @providesModule ReactEmptyComponent 85048 */ 85049 85050 85051 85052var emptyComponentFactory; 85053 85054var ReactEmptyComponentInjection = { 85055 injectEmptyComponentFactory: function (factory) { 85056 emptyComponentFactory = factory; 85057 } 85058}; 85059 85060var ReactEmptyComponent = { 85061 create: function (instantiate) { 85062 return emptyComponentFactory(instantiate); 85063 } 85064}; 85065 85066ReactEmptyComponent.injection = ReactEmptyComponentInjection; 85067 85068module.exports = ReactEmptyComponent; 85069},{}],65:[function(_dereq_,module,exports){ 85070/** 85071 * Copyright 2013-present, Facebook, Inc. 85072 * All rights reserved. 85073 * 85074 * This source code is licensed under the BSD-style license found in the 85075 * LICENSE file in the root directory of this source tree. An additional grant 85076 * of patent rights can be found in the PATENTS file in the same directory. 85077 * 85078 * @providesModule ReactErrorUtils 85079 */ 85080 85081 85082 85083var caughtError = null; 85084 85085/** 85086 * Call a function while guarding against errors that happens within it. 85087 * 85088 * @param {?String} name of the guard to use for logging or debugging 85089 * @param {Function} func The function to invoke 85090 * @param {*} a First argument 85091 * @param {*} b Second argument 85092 */ 85093function invokeGuardedCallback(name, func, a, b) { 85094 try { 85095 return func(a, b); 85096 } catch (x) { 85097 if (caughtError === null) { 85098 caughtError = x; 85099 } 85100 return undefined; 85101 } 85102} 85103 85104var ReactErrorUtils = { 85105 invokeGuardedCallback: invokeGuardedCallback, 85106 85107 /** 85108 * Invoked by ReactTestUtils.Simulate so that any errors thrown by the event 85109 * handler are sure to be rethrown by rethrowCaughtError. 85110 */ 85111 invokeGuardedCallbackWithCatch: invokeGuardedCallback, 85112 85113 /** 85114 * During execution of guarded functions we will capture the first error which 85115 * we will rethrow to be handled by the top level error handler. 85116 */ 85117 rethrowCaughtError: function () { 85118 if (caughtError) { 85119 var error = caughtError; 85120 caughtError = null; 85121 throw error; 85122 } 85123 } 85124}; 85125 85126if ("development" !== 'production') { 85127 /** 85128 * To help development we can get better devtools integration by simulating a 85129 * real browser event. 85130 */ 85131 if (typeof window !== 'undefined' && typeof window.dispatchEvent === 'function' && typeof document !== 'undefined' && typeof document.createEvent === 'function') { 85132 var fakeNode = document.createElement('react'); 85133 ReactErrorUtils.invokeGuardedCallback = function (name, func, a, b) { 85134 var boundFunc = func.bind(null, a, b); 85135 var evtType = 'react-' + name; 85136 fakeNode.addEventListener(evtType, boundFunc, false); 85137 var evt = document.createEvent('Event'); 85138 evt.initEvent(evtType, false, false); 85139 fakeNode.dispatchEvent(evt); 85140 fakeNode.removeEventListener(evtType, boundFunc, false); 85141 }; 85142 } 85143} 85144 85145module.exports = ReactErrorUtils; 85146},{}],66:[function(_dereq_,module,exports){ 85147/** 85148 * Copyright 2013-present, Facebook, Inc. 85149 * All rights reserved. 85150 * 85151 * This source code is licensed under the BSD-style license found in the 85152 * LICENSE file in the root directory of this source tree. An additional grant 85153 * of patent rights can be found in the PATENTS file in the same directory. 85154 * 85155 * @providesModule ReactEventEmitterMixin 85156 */ 85157 85158 85159 85160var EventPluginHub = _dereq_(17); 85161 85162function runEventQueueInBatch(events) { 85163 EventPluginHub.enqueueEvents(events); 85164 EventPluginHub.processEventQueue(false); 85165} 85166 85167var ReactEventEmitterMixin = { 85168 85169 /** 85170 * Streams a fired top-level event to `EventPluginHub` where plugins have the 85171 * opportunity to create `ReactEvent`s to be dispatched. 85172 */ 85173 handleTopLevel: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) { 85174 var events = EventPluginHub.extractEvents(topLevelType, targetInst, nativeEvent, nativeEventTarget); 85175 runEventQueueInBatch(events); 85176 } 85177}; 85178 85179module.exports = ReactEventEmitterMixin; 85180},{"17":17}],67:[function(_dereq_,module,exports){ 85181/** 85182 * Copyright 2013-present, Facebook, Inc. 85183 * All rights reserved. 85184 * 85185 * This source code is licensed under the BSD-style license found in the 85186 * LICENSE file in the root directory of this source tree. An additional grant 85187 * of patent rights can be found in the PATENTS file in the same directory. 85188 * 85189 * @providesModule ReactEventListener 85190 */ 85191 85192 85193 85194var _assign = _dereq_(169); 85195 85196var EventListener = _dereq_(143); 85197var ExecutionEnvironment = _dereq_(144); 85198var PooledClass = _dereq_(25); 85199var ReactDOMComponentTree = _dereq_(40); 85200var ReactUpdates = _dereq_(94); 85201 85202var getEventTarget = _dereq_(126);
85203var getUnboundedScrollPosition = _dereq_(155); 85204 85205/** 85206 * Find the deepest React component completely containing the root of the 85207 * passed-in instance (for use when entire React trees are nested within each 85208 * other). If React trees are not nested, returns null. 85209 */ 85210function findParent(inst) { 85211 // TODO: It may be a good idea to cache this to prevent unnecessary DOM 85212 // traversal, but caching is difficult to do correctly without using a 85213 // mutation observer to listen for all DOM changes. 85214 while (inst._nativeParent) { 85215 inst = inst._nativeParent; 85216 } 85217 var rootNode = ReactDOMComponentTree.getNodeFromInstance(inst); 85218 var container = rootNode.parentNode; 85219 return ReactDOMComponentTree.getClosestInstanceFromNode(container); 85220} 85221 85222// Used to store ancestor hierarchy in top level callback 85223function TopLevelCallbackBookKeeping(topLevelType, nativeEvent) { 85224 this.topLevelType = topLevelType; 85225 this.nativeEvent = nativeEvent; 85226 this.ancestors = []; 85227} 85228_assign(TopLevelCallbackBookKeeping.prototype, { 85229 destructor: function () { 85230 this.topLevelType = null; 85231 this.nativeEvent = null; 85232 this.ancestors.length = 0; 85233 } 85234}); 85235PooledClass.addPoolingTo(TopLevelCallbackBookKeeping, PooledClass.twoArgumentPooler); 85236 85237function handleTopLevelImpl(bookKeeping) { 85238 var nativeEventTarget = getEventTarget(bookKeeping.nativeEvent); 85239 var targetInst = ReactDOMComponentTree.getClosestInstanceFromNode(nativeEventTarget); 85240 85241 // Loop through the hierarchy, in case there's any nested components. 85242 // It's important that we build the array of ancestors before calling any 85243 // event handlers, because event handlers can modify the DOM, leading to 85244 // inconsistencies with ReactMount's node cache. See #1105. 85245 var ancestor = targetInst; 85246 do { 85247 bookKeeping.ancestors.push(ancestor); 85248 ancestor = ancestor && findParent(ancestor); 85249 } while (ancestor); 85250 85251 for (var i = 0; i < bookKeeping.ancestors.length; i++) { 85252 targetInst = bookKeeping.ancestors[i]; 85253 ReactEventListener._handleTopLevel(bookKeeping.topLevelType, targetInst, bookKeeping.nativeEvent, getEventTarget(bookKeeping.nativeEvent)); 85254 } 85255} 85256 85257function scrollValueMonitor(cb) { 85258 var scrollPosition = getUnboundedScrollPosition(window); 85259 cb(scrollPosition); 85260} 85261 85262var ReactEventListener = { 85263 _enabled: true, 85264 _handleTopLevel: null, 85265 85266 WINDOW_HANDLE: ExecutionEnvironment.canUseDOM ? window : null, 85267 85268 setHandleTopLevel: function (handleTopLevel) { 85269 ReactEventListener._handleTopLevel = handleTopLevel; 85270 }, 85271 85272 setEnabled: function (enabled) { 85273 ReactEventListener._enabled = !!enabled; 85274 }, 85275 85276 isEnabled: function () { 85277 return ReactEventListener._enabled; 85278 }, 85279 85280 /** 85281 * Traps top-level events by using event bubbling. 85282 * 85283 * @param {string} topLevelType Record from `EventConstants`. 85284 * @param {string} handlerBaseName Event name (e.g. "click"). 85285 * @param {object} handle Element on which to attach listener. 85286 * @return {?object} An object with a remove function which will forcefully 85287 * remove the listener. 85288 * @internal 85289 */ 85290 trapBubbledEvent: function (topLevelType, handlerBaseName, handle) { 85291 var element = handle; 85292 if (!element) { 85293 return null; 85294 } 85295 return EventListener.listen(element, handlerBaseName, ReactEventListener.dispatchEvent.bind(null, topLevelType)); 85296 }, 85297 85298 /** 85299 * Traps a top-level event by using event capturing. 85300 * 85301 * @param {string} topLevelType Record from `EventConstants`. 85302 * @param {string} handlerBaseName Event name (e.g. "click"). 85303 * @param {object} handle Element on which to attach listener. 85304 * @return {?object} An object with a remove function which will forcefully 85305 * remove the listener. 85306 * @internal 85307 */ 85308 trapCapturedEvent: function (topLevelType, handlerBaseName, handle) { 85309 var element = handle; 85310 if (!element) { 85311 return null; 85312 } 85313 return EventListener.capture(element, handlerBaseName, ReactEventListener.dispatchEvent.bind(null, topLevelType)); 85314 }, 85315 85316 monitorScrollValue: function (refresh) { 85317 var callback = scrollValueMonitor.bind(null, refresh); 85318 EventListener.listen(window, 'scroll', callback); 85319 }, 85320 85321 dispatchEvent: function (topLevelType, nativeEvent) { 85322 if (!ReactEventListener._enabled) { 85323 return; 85324 } 85325 85326 var bookKeeping = TopLevelCallbackBookKeeping.getPooled(topLevelType, nativeEvent); 85327 try { 85328 // Event queue being processed in the same cycle allows 85329 // `preventDefault`. 85330 ReactUpdates.batchedUpdates(handleTopLevelImpl, bookKeeping); 85331 } finally { 85332 TopLevelCallbackBookKeeping.release(bookKeeping); 85333 } 85334 } 85335}; 85336 85337module.exports = ReactEventListener; 85338},{"126":126,"143":143,"144":144,"155":155,"169":169,"25":25,"40":40,"94":94}],68:[function(_dereq_,module,exports){ 85339/** 85340 * Copyright 2013-present, Facebook, Inc. 85341 * All rights reserved. 85342 * 85343 * This source code is licensed under the BSD-style license found in the 85344 * LICENSE file in the root directory of this source tree. An additional grant 85345 * of patent rights can be found in the PATENTS file in the same directory. 85346 * 85347 * @providesModule ReactFeatureFlags 85348 */ 85349 85350 85351 85352var ReactFeatureFlags = { 85353 // When true, call console.time() before and .timeEnd() after each top-level 85354 // render (both initial renders and updates). Useful when looking at prod-mode 85355 // timeline profiles in Chrome, for example. 85356 logTopLevelRenders: false 85357}; 85358 85359module.exports = ReactFeatureFlags; 85360},{}],69:[function(_dereq_,module,exports){ 85361/** 85362 * Copyright 2013-present, Facebook, Inc. 85363 * All rights reserved. 85364 * 85365 * This source code is licensed under the BSD-style license found in the 85366 * LICENSE file in the root directory of this source tree. An additional grant 85367 * of patent rights can be found in the PATENTS file in the same directory. 85368 * 85369 * @providesModule ReactInjection 85370 */ 85371 85372 85373 85374var DOMProperty = _dereq_(10); 85375var EventPluginHub = _dereq_(17); 85376var EventPluginUtils = _dereq_(19); 85377var ReactComponentEnvironment = _dereq_(33); 85378var ReactClass = _dereq_(30); 85379var ReactEmptyComponent = _dereq_(64); 85380var ReactBrowserEventEmitter = _dereq_(27); 85381var ReactNativeComponent = _dereq_(78); 85382var ReactPerf = _dereq_(82); 85383var ReactUpdates = _dereq_(94); 85384 85385var ReactInjection = { 85386 Component: ReactComponentEnvironment.injection, 85387 Class: ReactClass.injection, 85388 DOMProperty: DOMProperty.injection, 85389 EmptyComponent: ReactEmptyComponent.injection, 85390 EventPluginHub: EventPluginHub.injection, 85391 EventPluginUtils: EventPluginUtils.injection, 85392 EventEmitter: ReactBrowserEventEmitter.injection, 85393 NativeComponent: ReactNativeComponent.injection, 85394 Perf: ReactPerf.injection, 85395 Updates: ReactUpdates.injection 85396}; 85397 85398module.exports = ReactInjection; 85399},{"10":10,"17":17,"19":19,"27":27,"30":30,"33":33,"64":64,"78":78,"82":82,"94":94}],70:[function(_dereq_,module,exports){ 85400/** 85401 * Copyright 2013-present, Facebook, Inc. 85402 * All rights reserved. 85403 * 85404 * This source code is licensed under the BSD-style license found in the 85405 * LICENSE file in the root directory of this source tree. An additional grant 85406 * of patent rights can be found in the PATENTS file in the same directory. 85407 * 85408 * @providesModule ReactInputSelection 85409 */ 85410 85411 85412 85413var ReactDOMSelection = _dereq_(51); 85414
85415var containsNode = _dereq_(147); 85416var focusNode = _dereq_(152); 85417var getActiveElement = _dereq_(153); 85418 85419function isInDocument(node) { 85420 return containsNode(document.documentElement, node); 85421} 85422 85423/** 85424 * @ReactInputSelection: React input selection module. Based on Selection.js, 85425 * but modified to be suitable for react and has a couple of bug fixes (doesn't 85426 * assume buttons have range selections allowed). 85427 * Input selection module for React. 85428 */ 85429var ReactInputSelection = { 85430 85431 hasSelectionCapabilities: function (elem) { 85432 var nodeName = elem && elem.nodeName && elem.nodeName.toLowerCase(); 85433 return nodeName && (nodeName === 'input' && elem.type === 'text' || nodeName === 'textarea' || elem.contentEditable === 'true'); 85434 }, 85435 85436 getSelectionInformation: function () { 85437 var focusedElem = getActiveElement(); 85438 return { 85439 focusedElem: focusedElem, 85440 selectionRange: ReactInputSelection.hasSelectionCapabilities(focusedElem) ? ReactInputSelection.getSelection(focusedElem) : null 85441 }; 85442 }, 85443 85444 /** 85445 * @restoreSelection: If any selection information was potentially lost, 85446 * restore it. This is useful when performing operations that could remove dom 85447 * nodes and place them back in, resulting in focus being lost. 85448 */ 85449 restoreSelection: function (priorSelectionInformation) { 85450 var curFocusedElem = getActiveElement(); 85451 var priorFocusedElem = priorSelectionInformation.focusedElem; 85452 var priorSelectionRange = priorSelectionInformation.selectionRange; 85453 if (curFocusedElem !== priorFocusedElem && isInDocument(priorFocusedElem)) { 85454 if (ReactInputSelection.hasSelectionCapabilities(priorFocusedElem)) { 85455 ReactInputSelection.setSelection(priorFocusedElem, priorSelectionRange); 85456 } 85457 focusNode(priorFocusedElem); 85458 } 85459 }, 85460 85461 /** 85462 * @getSelection: Gets the selection bounds of a focused textarea, input or 85463 * contentEditable node. 85464 * -@input: Look up selection bounds of this input 85465 * -@return {start: selectionStart, end: selectionEnd} 85466 */ 85467 getSelection: function (input) { 85468 var selection; 85469 85470 if ('selectionStart' in input) { 85471 // Modern browser with input or textarea. 85472 selection = { 85473 start: input.selectionStart, 85474 end: input.selectionEnd 85475 }; 85476 } else if (document.selection && input.nodeName && input.nodeName.toLowerCase() === 'input') { 85477 // IE8 input. 85478 var range = document.selection.createRange(); 85479 // There can only be one selection per document in IE, so it must 85480 // be in our element. 85481 if (range.parentElement() === input) { 85482 selection = { 85483 start: -range.moveStart('character', -input.value.length), 85484 end: -range.moveEnd('character', -input.value.length) 85485 }; 85486 } 85487 } else { 85488 // Content editable or old IE textarea. 85489 selection = ReactDOMSelection.getOffsets(input); 85490 } 85491 85492 return selection || { start: 0, end: 0 }; 85493 }, 85494 85495 /** 85496 * @setSelection: Sets the selection bounds of a textarea or input and focuses 85497 * the input. 85498 * -@input Set selection bounds of this input or textarea 85499 * -@offsets Object of same form that is returned from get* 85500 */ 85501 setSelection: function (input, offsets) { 85502 var start = offsets.start; 85503 var end = offsets.end; 85504 if (end === undefined) { 85505 end = start; 85506 } 85507 85508 if ('selectionStart' in input) { 85509 input.selectionStart = start; 85510 input.selectionEnd = Math.min(end, input.value.length); 85511 } else if (document.selection && input.nodeName && input.nodeName.toLowerCase() === 'input') { 85512 var range = input.createTextRange(); 85513 range.collapse(true); 85514 range.moveStart('character', start); 85515 range.moveEnd('character', end - start); 85516 range.select(); 85517 } else { 85518 ReactDOMSelection.setOffsets(input, offsets); 85519 } 85520 } 85521}; 85522 85523module.exports = ReactInputSelection; 85524},{"147":147,"152":152,"153":153,"51":51}],71:[function(_dereq_,module,exports){ 85525/** 85526 * Copyright 2013-present, Facebook, Inc. 85527 * All rights reserved. 85528 * 85529 * This source code is licensed under the BSD-style license found in the 85530 * LICENSE file in the root directory of this source tree. An additional grant 85531 * of patent rights can be found in the PATENTS file in the same directory. 85532 * 85533 * @providesModule ReactInstanceMap 85534 */ 85535 85536 85537 85538/** 85539 * `ReactInstanceMap` maintains a mapping from a public facing stateful 85540 * instance (key) and the internal representation (value). This allows public 85541 * methods to accept the user facing instance as an argument and map them back 85542 * to internal methods. 85543 */ 85544 85545// TODO: Replace this with ES6: var ReactInstanceMap = new Map(); 85546 85547var ReactInstanceMap = { 85548 85549 /** 85550 * This API should be called `delete` but we'd have to make sure to always
85551 * transform these to strings for IE support. When this transform is fully 85552 * supported we can rename it. 85553 */ 85554 remove: function (key) { 85555 key._reactInternalInstance = undefined; 85556 }, 85557 85558 get: function (key) { 85559 return key._reactInternalInstance; 85560 }, 85561 85562 has: function (key) { 85563 return key._reactInternalInstance !== undefined; 85564 }, 85565 85566 set: function (key, value) { 85567 key._reactInternalInstance = value; 85568 } 85569 85570}; 85571 85572module.exports = ReactInstanceMap; 85573},{}],72:[function(_dereq_,module,exports){ 85574/** 85575 * Copyright 2016-present, Facebook, Inc. 85576 * All rights reserved. 85577 * 85578 * This source code is licensed under the BSD-style license found in the 85579 * LICENSE file in the root directory of this source tree. An additional grant 85580 * of patent rights can be found in the PATENTS file in the same directory. 85581 * 85582 * @providesModule ReactInstrumentation 85583 */ 85584 85585 85586 85587var ReactDebugTool = _dereq_(57); 85588 85589module.exports = { debugTool: ReactDebugTool }; 85590},{"57":57}],73:[function(_dereq_,module,exports){ 85591/** 85592 * Copyright 2016-present, Facebook, Inc. 85593 * All rights reserved. 85594 * 85595 * This source code is licensed under the BSD-style license found in the 85596 * LICENSE file in the root directory of this source tree. An additional grant 85597 * of patent rights can be found in the PATENTS file in the same directory. 85598 * 85599 * @providesModule ReactInvalidSetStateWarningDevTool 85600 */ 85601 85602 85603 85604var warning = _dereq_(168); 85605 85606if ("development" !== 'production') { 85607 var processingChildContext = false; 85608 85609 var warnInvalidSetState = function () { 85610 "development" !== 'production' ? warning(!processingChildContext, 'setState(...): Cannot call setState() inside getChildContext()') : void 0; 85611 }; 85612} 85613 85614var ReactInvalidSetStateWarningDevTool = { 85615 onBeginProcessingChildContext: function () { 85616 processingChildContext = true; 85617 }, 85618 onEndProcessingChildContext: function () { 85619 processingChildContext = false; 85620 }, 85621 onSetState: function () { 85622 warnInvalidSetState(); 85623 } 85624}; 85625 85626module.exports = ReactInvalidSetStateWarningDevTool; 85627},{"168":168}],74:[function(_dereq_,module,exports){ 85628/** 85629 * Copyright 2013-present, Facebook, Inc. 85630 * All rights reserved. 85631 * 85632 * This source code is licensed under the BSD-style license found in the 85633 * LICENSE file in the root directory of this source tree. An additional grant 85634 * of patent rights can be found in the PATENTS file in the same directory. 85635 * 85636 * @providesModule ReactMarkupChecksum 85637 */ 85638 85639 85640 85641var adler32 = _dereq_(115); 85642 85643var TAG_END = /\/?>/; 85644var COMMENT_START = /^<\!\-\-/; 85645 85646var ReactMarkupChecksum = { 85647 CHECKSUM_ATTR_NAME: 'data-react-checksum', 85648 85649 /** 85650 * @param {string} markup Markup string 85651 * @return {string} Markup string with checksum attribute attached 85652 */ 85653 addChecksumToMarkup: function (markup) { 85654 var checksum = adler32(markup); 85655 85656 // Add checksum (handle both parent tags, comments and self-closing tags) 85657 if (COMMENT_START.test(markup)) { 85658 return markup; 85659 } else { 85660 return markup.replace(TAG_END, ' ' + ReactMarkupChecksum.CHECKSUM_ATTR_NAME + '="' + checksum + '"$&'); 85661 } 85662 }, 85663 85664 /** 85665 * @param {string} markup to use 85666 * @param {DOMElement} element root React element 85667 * @returns {boolean} whether or not the markup is the same 85668 */ 85669 canReuseMarkup: function (markup, element) { 85670 var existingChecksum = element.getAttribute(ReactMarkupChecksum.CHECKSUM_ATTR_NAME); 85671 existingChecksum = existingChecksum && parseInt(existingChecksum, 10); 85672 var markupChecksum = adler32(markup); 85673 return markupChecksum === existingChecksum; 85674 } 85675}; 85676 85677module.exports = ReactMarkupChecksum; 85678},{"115":115}],75:[function(_dereq_,module,exports){ 85679/** 85680 * Copyright 2013-present, Facebook, Inc. 85681 * All rights reserved. 85682 * 85683 * This source code is licensed under the BSD-style license found in the 85684 * LICENSE file in the root directory of this source tree. An additional grant 85685 * of patent rights can be found in the PATENTS file in the same directory. 85686 * 85687 * @providesModule ReactMount 85688 */ 85689 85690 85691 85692var DOMLazyTree = _dereq_(8); 85693var DOMProperty = _dereq_(10); 85694var ReactBrowserEventEmitter = _dereq_(27); 85695var ReactCurrentOwner = _dereq_(35); 85696var ReactDOMComponentTree = _dereq_(40); 85697var ReactDOMContainerInfo = _dereq_(41); 85698var ReactDOMFeatureFlags = _dereq_(45); 85699var ReactElement = _dereq_(62); 85700var ReactFeatureFlags = _dereq_(68); 85701var ReactInstrumentation = _dereq_(72); 85702var ReactMarkupChecksum = _dereq_(74); 85703var ReactPerf = _dereq_(82); 85704var ReactReconciler = _dereq_(87); 85705var ReactUpdateQueue = _dereq_(93); 85706var ReactUpdates = _dereq_(94); 85707 85708var emptyObject = _dereq_(151); 85709var instantiateReactComponent = _dereq_(132); 85710var invariant = _dereq_(158); 85711var setInnerHTML = _dereq_(138); 85712var shouldUpdateReactComponent = _dereq_(140); 85713var warning = _dereq_(168); 85714 85715var ATTR_NAME = DOMProperty.ID_ATTRIBUTE_NAME; 85716var ROOT_ATTR_NAME = DOMProperty.ROOT_ATTRIBUTE_NAME; 85717 85718var ELEMENT_NODE_TYPE = 1; 85719var DOC_NODE_TYPE = 9; 85720var DOCUMENT_FRAGMENT_NODE_TYPE = 11; 85721 85722var instancesByReactRootID = {}; 85723 85724/** 85725 * Finds the index of the first character 85726 * that's not common between the two given strings. 85727 * 85728 * @return {number} the index of the character where the strings diverge 85729 */ 85730function firstDifferenceIndex(string1, string2) { 85731 var minLen = Math.min(string1.length, string2.length); 85732 for (var i = 0; i < minLen; i++) { 85733 if (string1.charAt(i) !== string2.charAt(i)) { 85734 return i; 85735 } 85736 } 85737 return string1.length === string2.length ? -1 : minLen; 85738} 85739 85740/** 85741 * @param {DOMElement|DOMDocument} container DOM element that may contain 85742 * a React component 85743 * @return {?*} DOM element that may have the reactRoot ID, or null. 85744 */ 85745function getReactRootElementInContainer(container) { 85746 if (!container) { 85747 return null; 85748 } 85749 85750 if (container.nodeType === DOC_NODE_TYPE) { 85751 return container.documentElement; 85752 } else { 85753 return container.firstChild; 85754 } 85755} 85756 85757function internalGetID(node) { 85758 // If node is something like a window, document, or text node, none of 85759 // which support attributes or a .getAttribute method, gracefully return 85760 // the empty string, as if the attribute were missing. 85761 return node.getAttribute && node.getAttribute(ATTR_NAME) || ''; 85762} 85763 85764/** 85765 * Mounts this component and inserts it into the DOM. 85766 * 85767 * @param {ReactComponent} componentInstance The instance to mount. 85768 * @param {DOMElement} container DOM element to mount into. 85769 * @param {ReactReconcileTransaction} transaction 85770 * @param {boolean} shouldReuseMarkup If true, do not insert markup 85771 */ 85772function mountComponentIntoNode(wrapperInstance, container, transaction, shouldReuseMarkup, context) { 85773 var markerName; 85774 if (ReactFeatureFlags.logTopLevelRenders) { 85775 var wrappedElement = wrapperInstance._currentElement.props; 85776 var type = wrappedElement.type; 85777 markerName = 'React mount: ' + (typeof type === 'string' ? type : type.displayName || type.name); 85778 console.time(markerName); 85779 } 85780 85781 var markup = ReactReconciler.mountComponent(wrapperInstance, transaction, null, ReactDOMContainerInfo(wrapperInstance, container), context); 85782 85783 if (markerName) { 85784 console.timeEnd(markerName); 85785 } 85786 85787 wrapperInstance._renderedComponent._topLevelWrapper = wrapperInstance; 85788 ReactMount._mountImageIntoNode(markup, container, wrapperInstance, shouldReuseMarkup, transaction); 85789} 85790 85791/** 85792 * Batched mount. 85793 * 85794 * @param {ReactComponent} componentInstance The instance to mount. 85795 * @param {DOMElement} container DOM element to mount into. 85796 * @param {boolean} shouldReuseMarkup If true, do not insert markup 85797 */ 85798function batchedMountComponentIntoNode(componentInstance, container, shouldReuseMarkup, context) { 85799 var transaction = ReactUpdates.ReactReconcileTransaction.getPooled( 85800 /* useCreateElement */ 85801 !shouldReuseMarkup && ReactDOMFeatureFlags.useCreateElement); 85802 transaction.perform(mountComponentIntoNode, null, componentInstance, container, transaction, shouldReuseMarkup, context); 85803 ReactUpdates.ReactReconcileTransaction.release(transaction); 85804} 85805 85806/** 85807 * Unmounts a component and removes it from the DOM. 85808 * 85809 * @param {ReactComponent} instance React component instance. 85810 * @param {DOMElement} container DOM element to unmount from. 85811 * @final 85812 * @internal 85813 * @see {ReactMount.unmountComponentAtNode} 85814 */ 85815function unmountComponentFromNode(instance, container, safely) { 85816 ReactReconciler.unmountComponent(instance, safely); 85817 85818 if (container.nodeType === DOC_NODE_TYPE) { 85819 container = container.documentElement; 85820 } 85821 85822 // http://jsperf.com/emptying-a-node 85823 while (container.lastChild) { 85824 container.removeChild(container.lastChild); 85825 } 85826} 85827 85828/** 85829 * True if the supplied DOM node has a direct React-rendered child that is 85830 * not a React root element. Useful for warning in `render`, 85831 * `unmountComponentAtNode`, etc. 85832 * 85833 * @param {?DOMElement} node The candidate DOM node. 85834 * @return {boolean} True if the DOM element contains a direct child that was 85835 * rendered by React but is not a root element. 85836 * @internal 85837 */ 85838function hasNonRootReactChild(container) { 85839 var rootEl = getReactRootElementInContainer(container); 85840 if (rootEl) { 85841 var inst = ReactDOMComponentTree.getInstanceFromNode(rootEl); 85842 return !!(inst && inst._nativeParent); 85843 } 85844} 85845 85846function getNativeRootInstanceInContainer(container) { 85847 var rootEl = getReactRootElementInContainer(container); 85848 var prevNativeInstance = rootEl && ReactDOMComponentTree.getInstanceFromNode(rootEl); 85849 return prevNativeInstance && !prevNativeInstance._nativeParent ? prevNativeInstance : null; 85850} 85851 85852function getTopLevelWrapperInContainer(container) { 85853 var root = getNativeRootInstanceInContainer(container); 85854 return root ? root._nativeContainerInfo._topLevelWrapper : null; 85855} 85856 85857/** 85858 * Temporary (?) hack so that we can store all top-level pending updates on 85859 * composites instead of having to worry about different types of components 85860 * here. 85861 */ 85862var topLevelRootCounter = 1; 85863var TopLevelWrapper = function () { 85864 this.rootID = topLevelRootCounter++; 85865}; 85866TopLevelWrapper.prototype.isReactComponent = {}; 85867if ("development" !== 'production') { 85868 TopLevelWrapper.displayName = 'TopLevelWrapper'; 85869} 85870TopLevelWrapper.prototype.render = function () { 85871 // this.props is actually a ReactElement 85872 return this.props; 85873}; 85874 85875/** 85876 * Mounting is the process of initializing a React component by creating its 85877 * representative DOM elements and inserting them into a supplied `container`. 85878 * Any prior content inside `container` is destroyed in the process. 85879 * 85880 * ReactMount.render( 85881 * component, 85882 * document.getElementById('container') 85883 * ); 85884 * 85885 * <div id="container"> <-- Supplied `container`. 85886 * <div data-reactid=".3"> <-- Rendered reactRoot of React 85887 * // ... component.
85888 * </div> 85889 * </div> 85890 * 85891 * Inside of `container`, the first element rendered is the "reactRoot". 85892 */ 85893var ReactMount = { 85894 85895 TopLevelWrapper: TopLevelWrapper, 85896 85897 /** 85898 * Used by devtools. The keys are not important. 85899 */ 85900 _instancesByReactRootID: instancesByReactRootID, 85901 85902 /** 85903 * This is a hook provided to support rendering React components while 85904 * ensuring that the apparent scroll position of its `container` does not 85905 * change. 85906 * 85907 * @param {DOMElement} container The `container` being rendered into. 85908 * @param {function} renderCallback This must be called once to do the render. 85909 */ 85910 scrollMonitor: function (container, renderCallback) { 85911 renderCallback(); 85912 }, 85913 85914 /** 85915 * Take a component that's already mounted into the DOM and replace its props 85916 * @param {ReactComponent} prevComponent component instance already in the DOM 85917 * @param {ReactElement} nextElement component instance to render 85918 * @param {DOMElement} container container to render into 85919 * @param {?function} callback function triggered on completion 85920 */ 85921 _updateRootComponent: function (prevComponent, nextElement, container, callback) { 85922 ReactMount.scrollMonitor(container, function () { 85923 ReactUpdateQueue.enqueueElementInternal(prevComponent, nextElement); 85924 if (callback) { 85925 ReactUpdateQueue.enqueueCallbackInternal(prevComponent, callback); 85926 } 85927 }); 85928 85929 return prevComponent; 85930 }, 85931 85932 /** 85933 * Render a new component into the DOM. Hooked by devtools! 85934 * 85935 * @param {ReactElement} nextElement element to render 85936 * @param {DOMElement} container container to render into 85937 * @param {boolean} shouldReuseMarkup if we should skip the markup insertion 85938 * @return {ReactComponent} nextComponent 85939 */ 85940 _renderNewRootComponent: function (nextElement, container, shouldReuseMarkup, context) { 85941 // Various parts of our code (such as ReactCompositeComponent's 85942 // _renderValidatedComponent) assume that calls to render aren't nested; 85943 // verify that that's the case. 85944 "development" !== 'production' ? warning(ReactCurrentOwner.current == null, '_renderNewRootComponent(): Render methods should be a pure function ' + 'of props and state; triggering nested component updates from ' + 'render is not allowed. If necessary, trigger nested updates in ' + 'componentDidUpdate. Check the render method of %s.', ReactCurrentOwner.current && ReactCurrentOwner.current.getName() || 'ReactCompositeComponent') : void 0; 85945 85946 !(container && (container.nodeType === ELEMENT_NODE_TYPE || container.nodeType === DOC_NODE_TYPE || container.nodeType === DOCUMENT_FRAGMENT_NODE_TYPE)) ? "development" !== 'production' ? invariant(false, '_registerComponent(...): Target container is not a DOM element.') : invariant(false) : void 0; 85947 85948 ReactBrowserEventEmitter.ensureScrollValueMonitoring(); 85949 var componentInstance = instantiateReactComponent(nextElement); 85950 85951 // The initial render is synchronous but any updates that happen during 85952 // rendering, in componentWillMount or componentDidMount, will be batched 85953 // according to the current batching strategy. 85954 85955 ReactUpdates.batchedUpdates(batchedMountComponentIntoNode, componentInstance, container, shouldReuseMarkup, context); 85956 85957 var wrapperID = componentInstance._instance.rootID; 85958 instancesByReactRootID[wrapperID] = componentInstance; 85959 85960 if ("development" !== 'production') { 85961 ReactInstrumentation.debugTool.onMountRootComponent(componentInstance); 85962 } 85963 85964 return componentInstance; 85965 }, 85966 85967 /** 85968 * Renders a React component into the DOM in the supplied `container`. 85969 * 85970 * If the React component was previously rendered into `container`, this will 85971 * perform an update on it and only mutate the DOM as necessary to reflect the 85972 * latest React component. 85973 * 85974 * @param {ReactComponent} parentComponent The conceptual parent of this render tree. 85975 * @param {ReactElement} nextElement Component element to render. 85976 * @param {DOMElement} container DOM element to render into. 85977 * @param {?function} callback function triggered on completion 85978 * @return {ReactComponent} Component instance rendered in `container`. 85979 */ 85980 renderSubtreeIntoContainer: function (parentComponent, nextElement, container, callback) { 85981 !(parentComponent != null && parentComponent._reactInternalInstance != null) ? "development" !== 'production' ? invariant(false, 'parentComponent must be a valid React Component') : invariant(false) : void 0; 85982 return ReactMount._renderSubtreeIntoContainer(parentComponent, nextElement, container, callback); 85983 }, 85984 85985 _renderSubtreeIntoContainer: function (parentComponent, nextElement, container, callback) { 85986 ReactUpdateQueue.validateCallback(callback, 'ReactDOM.render'); 85987 !ReactElement.isValidElement(nextElement) ? "development" !== 'production' ? invariant(false, 'ReactDOM.render(): Invalid component element.%s', typeof nextElement === 'string' ? ' Instead of passing a string like \'div\', pass ' + 'React.createElement(\'div\') or <div />.' : typeof nextElement === 'function' ? ' Instead of passing a class like Foo, pass ' + 'React.createElement(Foo) or <Foo />.' : 85988 // Check if it quacks like an element 85989 nextElement != null && nextElement.props !== undefined ? ' This may be caused by unintentionally loading two independent ' + 'copies of React.' : '') : invariant(false) : void 0; 85990 85991 "development" !== 'production' ? warning(!container || !container.tagName || container.tagName.toUpperCase() !== 'BODY', 'render(): Rendering components directly into document.body is ' + 'discouraged, since its children are often manipulated by third-party ' + 'scripts and browser extensions. This may lead to subtle ' + 'reconciliation issues. Try rendering into a container element created ' + 'for your app.') : void 0; 85992 85993 var nextWrappedElement = ReactElement(TopLevelWrapper, null, null, null, null, null, nextElement); 85994 85995 var prevComponent = getTopLevelWrapperInContainer(container); 85996 85997 if (prevComponent) { 85998 var prevWrappedElement = prevComponent._currentElement; 85999 var prevElement = prevWrappedElement.props; 86000 if (shouldUpdateReactComponent(prevElement, nextElement)) { 86001 var publicInst = prevComponent._renderedComponent.getPublicInstance(); 86002 var updatedCallback = callback && function () { 86003 callback.call(publicInst); 86004 }; 86005 ReactMount._updateRootComponent(prevComponent, nextWrappedElement, container, updatedCallback); 86006 return publicInst; 86007 } else { 86008 ReactMount.unmountComponentAtNode(container); 86009 } 86010 } 86011 86012 var reactRootElement = getReactRootElementInContainer(container); 86013 var containerHasReactMarkup = reactRootElement && !!internalGetID(reactRootElement); 86014 var containerHasNonRootReactChild = hasNonRootReactChild(container); 86015 86016 if ("development" !== 'production') { 86017 "development" !== 'production' ? warning(!containerHasNonRootReactChild, 'render(...): Replacing React-rendered children with a new root ' + 'component. If you intended to update the children of this node, ' + 'you should instead have the existing children update their state ' + 'and render the new components instead of calling ReactDOM.render.') : void 0; 86018 86019 if (!containerHasReactMarkup || reactRootElement.nextSibling) { 86020 var rootElementSibling = reactRootElement; 86021 while (rootElementSibling) { 86022 if (internalGetID(rootElementSibling)) { 86023 "development" !== 'production' ? warning(false, 'render(): Target node has markup rendered by React, but there ' + 'are unrelated nodes as well. This is most commonly caused by ' + 'white-space inserted around server-rendered markup.') : void 0; 86024 break; 86025 } 86026 rootElementSibling = rootElementSibling.nextSibling; 86027 } 86028 } 86029 } 86030 86031 var shouldReuseMarkup = containerHasReactMarkup && !prevComponent && !containerHasNonRootReactChild; 86032 var component = ReactMount._renderNewRootComponent(nextWrappedElement, container, shouldReuseMarkup, parentComponent != null ? parentComponent._reactInternalInstance._processChildContext(parentComponent._reactInternalInstance._context) : emptyObject)._renderedComponent.getPublicInstance(); 86033 if (callback) { 86034 callback.call(component); 86035 } 86036 return component; 86037 }, 86038 86039 /** 86040 * Renders a React component into the DOM in the supplied `container`. 86041 * 86042 * If the React component was previously rendered into `container`, this will 86043 * perform an update on it and only mutate the DOM as necessary to reflect the 86044 * latest React component. 86045 * 86046 * @param {ReactElement} nextElement Component element to render. 86047 * @param {DOMElement} container DOM element to render into. 86048 * @param {?function} callback function triggered on completion 86049 * @return {ReactComponent} Component instance rendered in `container`. 86050 */ 86051 render: function (nextElement, container, callback) { 86052 return ReactMount._renderSubtreeIntoContainer(null, nextElement, container, callback); 86053 }, 86054 86055 /** 86056 * Unmounts and destroys the React component rendered in the `container`. 86057 * 86058 * @param {DOMElement} container DOM element containing a React component. 86059 * @return {boolean} True if a component was found in and unmounted from 86060 * `container` 86061 */ 86062 unmountComponentAtNode: function (container) { 86063 // Various parts of our code (such as ReactCompositeComponent's 86064 // _renderValidatedComponent) assume that calls to render aren't nested; 86065 // verify that that's the case. (Strictly speaking, unmounting won't
86065cause a 86066 // render but we still don't expect to be in a render call here.) 86067 "development" !== 'production' ? warning(ReactCurrentOwner.current == null, 'unmountComponentAtNode(): Render methods should be a pure function ' + 'of props and state; triggering nested component updates from render ' + 'is not allowed. If necessary, trigger nested updates in ' + 'componentDidUpdate. Check the render method of %s.', ReactCurrentOwner.current && ReactCurrentOwner.current.getName() || 'ReactCompositeComponent') : void 0; 86068 86069 !(container && (container.nodeType === ELEMENT_NODE_TYPE || container.nodeType === DOC_NODE_TYPE || container.nodeType === DOCUMENT_FRAGMENT_NODE_TYPE)) ? "development" !== 'production' ? invariant(false, 'unmountComponentAtNode(...): Target container is not a DOM element.') : invariant(false) : void 0; 86070 86071 var prevComponent = getTopLevelWrapperInContainer(container); 86072 if (!prevComponent) { 86073 // Check if the node being unmounted was rendered by React, but isn't a 86074 // root node. 86075 var containerHasNonRootReactChild = hasNonRootReactChild(container); 86076 86077 // Check if the container itself is a React root node. 86078 var isContainerReactRoot = container.nodeType === 1 && container.hasAttribute(ROOT_ATTR_NAME); 86079 86080 if ("development" !== 'production') { 86081 "development" !== 'production' ? warning(!containerHasNonRootReactChild, 'unmountComponentAtNode(): The node you\'re attempting to unmount ' + 'was rendered by React and is not a top-level container. %s', isContainerReactRoot ? 'You may have accidentally passed in a React root node instead ' + 'of its container.' : 'Instead, have the parent component update its state and ' + 'rerender in order to remove this component.') : void 0; 86082 } 86083 86084 return false; 86085 } 86086 delete instancesByReactRootID[prevComponent._instance.rootID]; 86087 ReactUpdates.batchedUpdates(unmountComponentFromNode, prevComponent, container, false); 86088 return true; 86089 }, 86090 86091 _mountImageIntoNode: function (markup, container, instance, shouldReuseMarkup, transaction) { 86092 !(container && (container.nodeType === ELEMENT_NODE_TYPE || container.nodeType === DOC_NODE_TYPE || container.nodeType === DOCUMENT_FRAGMENT_NODE_TYPE)) ? "development" !== 'production' ? invariant(false, 'mountComponentIntoNode(...): Target container is not valid.') : invariant(false) : void 0; 86093 86094 if (shouldReuseMarkup) { 86095 var rootElement = getReactRootElementInContainer(container); 86096 if (ReactMarkupChecksum.canReuseMarkup(markup, rootElement)) { 86097 ReactDOMComponentTree.precacheNode(instance, rootElement); 86098 return; 86099 } else { 86100 var checksum = rootElement.getAttribute(ReactMarkupChecksum.CHECKSUM_ATTR_NAME); 86101 rootElement.removeAttribute(ReactMarkupChecksum.CHECKSUM_ATTR_NAME); 86102 86103 var rootMarkup = rootElement.outerHTML; 86104 rootElement.setAttribute(ReactMarkupChecksum.CHECKSUM_ATTR_NAME, checksum); 86105 86106 var normalizedMarkup = markup; 86107 if ("development" !== 'production') { 86108 // because rootMarkup is retrieved from the DOM, various normalizations 86109 // will have occurred which will not be present in `markup`. Here, 86110 // insert markup into a <div> or <iframe> depending on the container 86111 // type to perform the same normalizations before comparing. 86112 var normalizer; 86113 if (container.nodeType === ELEMENT_NODE_TYPE) { 86114 normalizer = document.createElement('div'); 86115 normalizer.innerHTML = markup; 86116 normalizedMarkup = normalizer.innerHTML; 86117 } else { 86118 normalizer = document.createElement('iframe'); 86119 document.body.appendChild(normalizer); 86120 normalizer.contentDocument.write(markup); 86121 normalizedMarkup = normalizer.contentDocument.documentElement.outerHTML; 86122 document.body.removeChild(normalizer); 86123 } 86124 } 86125 86126 var diffIndex = firstDifferenceIndex(normalizedMarkup, rootMarkup); 86127 var difference = ' (client) ' + normalizedMarkup.substring(diffIndex - 20, diffIndex + 20) + '\n (server) ' + rootMarkup.substring(diffIndex - 20, diffIndex + 20); 86128 86129 !(container.nodeType !== DOC_NODE_TYPE) ? "development" !== 'production' ? invariant(false, 'You\'re trying to render a component to the document using ' + '
86129server rendering but the checksum was invalid. This usually ' + 'means you rendered a different component type or props on ' + 'the client from the one on the server, or your render() ' + 'methods are impure. React cannot handle this case due to ' + 'cross-browser quirks by rendering at the document root. You ' + 'should look for environment dependent code in your components ' + 'and ensure the props are the same client and server side:\n%s', difference) : invariant(false) : void 0; 86130 86131 if ("development" !== 'production') { 86132 "development" !== 'production' ? warning(false, 'React attempted to reuse markup in a container but the ' + 'checksum was invalid. This generally means that you are ' + 'using server rendering and the markup generated on the ' + 'server was not what the client was expecting. React injected ' + 'new markup to compensate which works but you have lost many ' + 'of the benefits of server rendering. Instead, figure out ' + 'why the markup being generated is different on the client ' + 'or server:\n%s', difference) : void 0; 86133 } 86134 } 86135 } 86136 86137 !(container.nodeType !== DOC_NODE_TYPE) ? "development" !== 'production' ? invariant(false, 'You\'re trying to render a component to the document but ' + 'you didn\'t use server rendering. We can\'t do this ' + 'without using server rendering due to cross-browser quirks. ' + 'See ReactDOMServer.renderToString() for server rendering.') : invariant(false) : void 0; 86138 86139 if (transaction.useCreateElement) { 86140 while (container.lastChild) { 86141 container.removeChild(container.lastChild); 86142 } 86143 DOMLazyTree.insertTreeBefore(container, markup, null); 86144 } else { 86145 setInnerHTML(container, markup); 86146 ReactDOMComponentTree.precacheNode(instance, container.firstChild); 86147 } 86148 } 86149}; 86150 86151ReactPerf.measureMethods(ReactMount, 'ReactMount', { 86152 _renderNewRootComponent: '_renderNewRootComponent', 86153 _mountImageIntoNode: '_mountImageIntoNode' 86154}); 86155 86156module.exports = ReactMount; 86157},{"10":10,"132":132,"138":138,"140":140,"151":151,"158":158,"168":168,"27":27,"35":35,"40":40,"41":41,"45":45,"62":62,"68":68,"72":72,"74":74,"8":8,"82":82,"87":87,"93":93,"94":94}],76:[function(_dereq_,module,exports){ 86158/** 86159 * Copyright 2013-present, Facebook, Inc. 86160 * All rights reserved. 86161 * 86162 * This source code is licensed under the BSD-style license found in the 86163 * LICENSE file in the root directory of this source tree. An additional grant 86164 * of patent rights can be found in the PATENTS file in the same directory. 86165 * 86166 * @providesModule ReactMultiChild 86167 */ 86168 86169 86170 86171var ReactComponentEnvironment = _dereq_(33); 86172var ReactMultiChildUpdateTypes = _dereq_(77); 86173 86174var ReactCurrentOwner = _dereq_(35); 86175var ReactReconciler = _dereq_(87); 86176var ReactChildReconciler = _dereq_(28); 86177 86178var flattenChildren = _dereq_(121); 86179var invariant = _dereq_(158); 86180 86181/** 86182 * Make an update for markup to be rendered and inserted at a supplied index. 86183 * 86184 * @param {string} markup Markup that renders into an element. 86185 * @param {number} toIndex Destination index. 86186 * @private 86187 */ 86188function makeInsertMarkup(markup, afterNode, toIndex) { 86189 // NOTE: Null values reduce hidden classes. 86190 return { 86191 type: ReactMultiChildUpdateTypes.INSERT_MARKUP, 86192 content: markup, 86193 fromIndex: null, 86194 fromNode: null, 86195 toIndex: toIndex, 86196 afterNode: afterNode 86197 }; 86198} 86199 86200/** 86201 * Make an update for moving an existing element to another index. 86202 * 86203 * @param {number} fromIndex Source index of the existing element. 86204 * @param {number} toIndex Destination index of the element. 86205 * @private 86206 */ 86207function makeMove(child, afterNode, toIndex) { 86208 // NOTE: Null values reduce hidden classes. 86209 return { 86210 type: ReactMultiChildUpdateTypes.MOVE_EXISTING, 86211 content: null, 86212 fromIndex: child._mountIndex, 86213 fromNode: ReactReconciler.getNativeNode(child), 86214 toIndex: toIndex, 86215 afterNode: afterNode 86216 }; 86217} 86218 86219/** 86220 * Make an update for removing an element at an index. 86221 * 86222 * @param {number} fromIndex Index of the element to remove. 86223 * @private 86224 */ 86225function makeRemove(child, node) { 86226 // NOTE: Null values reduce hidden classes. 86227 return { 86228 type: ReactMultiChildUpdateTypes.REMOVE_NODE, 86229 content: null, 86230 fromIndex: child._mountIndex, 86231 fromNode: node, 86232 toIndex: null, 86233 afterNode: null 86234 }; 86235} 86236 86237/** 86238 * Make an update for setting the markup of a node. 86239 * 86240 * @param {string} markup Markup that renders into an element. 86241 * @private 86242 */ 86243function makeSetMarkup(markup) { 86244 // NOTE: Null values reduce hidden classes. 86245 return { 86246 type: ReactMultiChildUpdateTypes.SET_MARKUP, 86247 content: markup, 86248 fromIndex: null, 86249 fromNode: null, 86250 toIndex: null, 86251 afterNode: null 86252 }; 86253} 86254 86255/** 86256 * Make an update for setting the text content. 86257 * 86258 * @param {string} textContent Text content to set. 86259 * @private 86260 */ 86261function makeTextContent(textContent) { 86262 // NOTE: Null values reduce hidden classes. 86263 return { 86264 type: ReactMultiChildUpdateTypes.TEXT_CONTENT, 86265 content: textContent, 86266 fromIndex: null, 86267 fromNode: null, 86268 toIndex: null, 86269 afterNode: null 86270 }; 86271} 86272 86273/** 86274 * Push an update, if any, onto the queue. Creates a new queue if none is 86275 * passed and always returns the queue. Mutative. 86276 */ 86277function enqueue(queue, update) { 86278 if (update) { 86279 queue = queue || []; 86280 queue.push(update); 86281 } 86282 return queue; 86283} 86284 86285/** 86286 * Processes any enqueued updates. 86287 * 86288 * @private 86289 */ 86290function processQueue(inst, updateQueue) { 86291 ReactComponentEnvironment.processChildrenUpdates(inst, updateQueue); 86292} 86293 86294/** 86295 * ReactMultiChild are capable of reconciling multiple children. 86296 * 86297 * @class ReactMultiChild 86298 * @internal 86299 */ 86300var ReactMultiChild = { 86301 86302 /** 86303 * Provides common functionality for components that must reconcile multiple 86304 * children. This is used by `ReactDOMComponent` to mount, update, and 86305 * unmount child components. 86306 * 86307 * @lends {ReactMultiChild.prototype} 86308 */ 86309 Mixin: { 86310 86311 _reconcilerInstantiateChildren: function (nestedChildren, transaction, context) { 86312 if ("development" !== 'production') { 86313 if (this._currentElement) { 86314 try { 86315 ReactCurrentOwner.current = this._currentElement._owner; 86316 return ReactChildReconciler.instantiateChildren(nestedChildren, transaction, context); 86317 } finally { 86318 ReactCurrentOwner.current = null; 86319 } 86320 } 86321 } 86322 return ReactChildReconciler.instantiateChildren(nestedChildren, transaction, context); 86323 }, 86324 86325 _reconcilerUpdateChildren: function (prevChildren, nextNestedChildrenElements, removedNodes, transaction, context) { 86326 var nextChildren; 86327 if ("development" !== 'production') { 86328 if (this._currentElement) { 86329 try { 86330 ReactCurrentOwner.current = this._currentElement._owner; 86331 nextChildren = flattenChildren(nextNestedChildrenElements); 86332 } finally { 86333 ReactCurrentOwner.current = null; 86334 } 86335 ReactChildReconciler.updateChildren(prevChildren, nextChildren, removedNodes, transaction, context); 86336 return nextChildren; 86337 } 86338 } 86339 nextChildren = flattenChildren(nextNestedChildrenElements); 86340 ReactChildReconciler.updateChildren(prevChildren, nextChildren, removedNodes, transaction, context); 86341 return nextChildren; 86342 }, 86343 86344 /** 86345 * Generates a "mount image" for each of the supplied children. In the case 86346 * of `ReactDOMComponent`, a mount image is a string of markup. 86347 * 86348 * @param {?object} nestedChildren Nested child maps. 86349 * @return {array} An array of mounted representations. 86350 * @internal 86351 */ 86352 mountChildren: function (nestedChildren, transaction, context) { 86353 var children = this._reconcilerInstantiateChildren(nestedChildren, transaction, context); 86354 this._renderedChildren = children; 86355 var mountImages = []; 86356 var index = 0; 86357 for (var name in children) { 86358 if (children.hasOwnProperty(name)) { 86359 var child = children[name]; 86360 var mountImage = ReactReconciler.mountComponent(child, transaction, this, this._nativeContainerInfo, context); 86361 child._mountIndex = index++; 86362 mountImages.push(mountImage); 86363 } 86364 } 86365 return mountImages; 86366 }, 86367 86368 /** 86369 * Replaces any rendered children with a text content string. 86370 * 86371 * @param {string} nextContent String of content. 86372 * @internal 86373 */ 86374 updateTextContent: function (nextContent) { 86375 var prevChildren = this._renderedChildren; 86376 // Remove any rendered children. 86377 ReactChildReconciler.unmountChildren(prevChildren, false); 86378 for (var name in prevChildren) { 86379 if (prevChildren.hasOwnProperty(name)) { 86380 !false ? "development" !== 'production' ? invariant(false, 'updateTextContent called on non-empty component.') : invariant(false) : void 0; 86381 } 86382 } 86383 // Set new text content. 86384 var updates = [makeTextContent(nextContent)]; 86385 processQueue(this, updates); 86386 }, 86387 86388 /** 86389 * Replaces any rendered children with a markup string. 86390 * 86391 * @param {string} nextMarkup String of markup. 86392 * @internal 86393 */ 86394 updateMarkup: function (nextMarkup) { 86395 var prevChildren = this._renderedChildren; 86396 // Remove any rendered children. 86397 ReactChildReconciler.unmountChildren(prevChildren, false); 86398 for (var name in prevChildren) { 86399 if (prevChildren.hasOwnProperty(name)) { 86400 !false ? "development" !== 'production' ? invariant(false, 'updateTextContent called on non-empty component.') : invariant(false) : void 0; 86401 } 86402 } 86403 var updates = [makeSetMarkup(nextMarkup)]; 86404 processQueue(this, updates); 86405 }, 86406 86407 /** 86408 * Updates the rendered children with new children. 86409 * 86410 * @param {?object} nextNestedChildrenElements Nested child element maps. 86411 * @param {ReactReconcileTransaction} transaction 86412 * @internal 86413 */ 86414 updateChildren: function (nextNestedChildrenElements, transaction, context) { 86415 // Hook used by React ART 86416 this._updateChildren(nextNestedChildrenElements, transaction, context); 86417 }, 86418 86419 /** 86420 * @param {?object} nextNestedChildrenElements Nested child element maps. 86421 * @param {ReactReconcileTransaction} transaction 86422 * @final 86423 * @protected 86424 */ 86425 _updateChildren: function (nextNestedChildrenElements, transaction, context) { 86426 var prevChildren = this._renderedChildren; 86427 var removedNodes = {}; 86428 var nextChildren = this._reconcilerUpdateChildren(prevChildren, nextNestedChildrenElements, removedNodes, transaction, context); 86429 if (!nextChildren && !prevChildren) { 86430 return; 86431 } 86432 var updates = null; 86433 var name; 86434 // `nextIndex` will increment for each child in `nextChildren`, but 86435 // `lastIndex` will be the last index visited in `prevChildren`. 86436 var lastIndex = 0; 86437 var nextIndex = 0; 86438 var lastPlacedNode = null; 86439 for (name in nextChildren) { 86440 if (!nextChildren.hasOwnProperty(name)) { 86441 continue; 86442 } 86443 var prevChild = prevChildren && prevChildren[name]; 86444 var nextChild = nextChildren[name]; 86445 if (prevChild === nextChild) { 86446 updates = enqueue(updates, this.moveChild(prevChild, lastPlacedNode, nextIndex, lastIndex)); 86447 lastIndex = Math.max(prevChild._mountIndex, lastIndex); 86448 prevChild._mountIndex = nextIndex; 86449 } else { 86450 if (prevChild) { 86451 // Update `lastIndex` before `_mountIndex` gets unset by unmounting. 86452 lastIndex = Math.max(prevChild._mountIndex, lastIndex); 86453 // The `removedNodes` loop below will actually remove the child. 86454 } 86455 // The child must be instantiated before it's mounted. 86456 updates = enqueue(updates, this._mountChildAtIndex(nextChild, lastPlacedNode, nextIndex, transaction, context)); 86457 } 86458 nextIndex++; 86459 lastPlacedNode = ReactReconciler.getNativeNode(nextChild); 86460 } 86461 // Remove children that are no longer present.
86462 for (name in removedNodes) { 86463 if (removedNodes.hasOwnProperty(name)) { 86464 updates = enqueue(updates, this._unmountChild(prevChildren[name], removedNodes[name])); 86465 } 86466 } 86467 if (updates) { 86468 processQueue(this, updates); 86469 } 86470 this._renderedChildren = nextChildren; 86471 }, 86472 86473 /** 86474 * Unmounts all rendered children. This should be used to clean up children 86475 * when this component is unmounted. It does not actually perform any 86476 * backend operations. 86477 * 86478 * @internal 86479 */ 86480 unmountChildren: function (safely) { 86481 var renderedChildren = this._renderedChildren; 86482 ReactChildReconciler.unmountChildren(renderedChildren, safely); 86483 this._renderedChildren = null; 86484 }, 86485 86486 /** 86487 * Moves a child component to the supplied index. 86488 * 86489 * @param {ReactComponent} child Component to move. 86490 * @param {number} toIndex Destination index of the element. 86491 * @param {number} lastIndex Last index visited of the siblings of `child`. 86492 * @protected 86493 */ 86494 moveChild: function (child, afterNode, toIndex, lastIndex) { 86495 // If the index of `child` is less than `lastIndex`, then it needs to 86496 // be moved. Otherwise, we do not need to move it because a child will be 86497 // inserted or moved before `child`. 86498 if (child._mountIndex < lastIndex) { 86499 return makeMove(child, afterNode, toIndex); 86500 } 86501 }, 86502 86503 /** 86504 * Creates a child component. 86505 * 86506 * @param {ReactComponent} child Component to create. 86507 * @param {string} mountImage Markup to insert. 86508 * @protected 86509 */ 86510 createChild: function (child, afterNode, mountImage) { 86511 return makeInsertMarkup(mountImage, afterNode, child._mountIndex); 86512 }, 86513 86514 /** 86515 * Removes a child component. 86516 * 86517 * @param {ReactComponent} child Child to remove. 86518 * @protected 86519 */ 86520 removeChild: function (child, node) { 86521 return makeRemove(child, node); 86522 }, 86523 86524 /** 86525 * Mounts a child with the supplied name. 86526 * 86527 * NOTE: This is part of `updateChildren` and is here for readability. 86528 * 86529 * @param {ReactComponent} child Component to mount. 86530 * @param {string} name Name of the child. 86531 * @param {number} index Index at which to insert the child. 86532 * @param {ReactReconcileTransaction} transaction 86533 * @private 86534 */ 86535 _mountChildAtIndex: function (child, afterNode, index, transaction, context) { 86536 var mountImage = ReactReconciler.mountComponent(child, transaction, this, this._nativeContainerInfo, context); 86537 child._mountIndex = index; 86538 return this.createChild(child, afterNode, mountImage); 86539 }, 86540 86541 /** 86542 * Unmounts a rendered child. 86543 * 86544 * NOTE: This is part of `updateChildren` and is here for readability. 86545 * 86546 * @param {ReactComponent} child Component to unmount. 86547 * @private 86548 */ 86549 _unmountChild: function (child, node) { 86550 var update = this.removeChild(child, node); 86551 child._mountIndex = null; 86552 return update; 86553 } 86554 86555 } 86556 86557}; 86558 86559module.exports = ReactMultiChild; 86560},{"121":121,"158":158,"28":28,"33":33,"35":35,"77":77,"87":87}],77:[function(_dereq_,module,exports){ 86561/** 86562 * Copyright 2013-present, Facebook, Inc. 86563 * All rights reserved. 86564 * 86565 * This source code is licensed under the BSD-style license found in the 86566 * LICENSE file in the root directory of this source tree. An additional grant 86567 * of patent rights can be found in the PATENTS file in the same directory. 86568 * 86569 * @providesModule ReactMultiChildUpdateTypes 86570 */ 86571 86572 86573 86574var keyMirror = _dereq_(161); 86575 86576/** 86577 * When a component's children are updated, a series of update configuration 86578 * objects are created in order to batch and serialize the required changes. 86579 * 86580 * Enumerates all the possible types of update configurations. 86581 * 86582 * @internal 86583 */ 86584var ReactMultiChildUpdateTypes = keyMirror({ 86585 INSERT_MARKUP: null, 86586 MOVE_EXISTING: null, 86587 REMOVE_NODE: null, 86588 SET_MARKUP: null, 86589 TEXT_CONTENT: null 86590}); 86591 86592module.exports = ReactMultiChildUpdateTypes; 86593},{"161":161}],78:[function(_dereq_,module,exports){ 86594/** 86595 * Copyright 2014-present, Facebook, Inc. 86596 * All rights reserved. 86597 * 86598 * This source code is licensed under the BSD-style license found in the 86599 * LICENSE file in the root directory of this source tree. An additional grant 86600 * of patent rights can be found in the PATENTS file in the same directory. 86601 * 86602 * @providesModule ReactNativeComponent 86603 */ 86604 86605 86606 86607var _assign = _dereq_(169); 86608 86609var invariant = _dereq_(158); 86610 86611var autoGenerateWrapperClass = null; 86612var genericComponentClass = null; 86613// This registry keeps track of wrapper classes around native tags. 86614var tagToComponentClass = {}; 86615var textComponentClass = null; 86616 86617var ReactNativeComponentInjection = { 86618 // This accepts a class that receives the tag string. This is a catch all 86619 // that can render any kind of tag. 86620 injectGenericComponentClass: function (componentClass) { 86621 genericComponentClass = componentClass; 86622 }, 86623 // This accepts a text component class that takes the text str
86623ing to be 86624 // rendered as props. 86625 injectTextComponentClass: function (componentClass) { 86626 textComponentClass = componentClass; 86627 }, 86628 // This accepts a keyed object with classes as values. Each key represents a 86629 // tag. That particular tag will use this class instead of the generic one. 86630 injectComponentClasses: function (componentClasses) { 86631 _assign(tagToComponentClass, componentClasses); 86632 } 86633}; 86634 86635/** 86636 * Get a composite component wrapper class for a specific tag. 86637 * 86638 * @param {ReactElement} element The tag for which to get the class. 86639 * @return {function} The React class constructor function. 86640 */ 86641function getComponentClassForElement(element) { 86642 if (typeof element.type === 'function') { 86643 return element.type; 86644 } 86645 var tag = element.type; 86646 var componentClass = tagToComponentClass[tag]; 86647 if (componentClass == null) { 86648 tagToComponentClass[tag] = componentClass = autoGenerateWrapperClass(tag); 86649 } 86650 return componentClass; 86651} 86652 86653/** 86654 * Get a native internal component class for a specific tag. 86655 * 86656 * @param {ReactElement} element The element to create. 86657 * @return {function} The internal class constructor function. 86658 */ 86659function createInternalComponent(element) { 86660 !genericComponentClass ? "development" !== 'production' ? invariant(false, 'There is no registered component for the tag %s', element.type) : invariant(false) : void 0; 86661 return new genericComponentClass(element); 86662} 86663 86664/** 86665 * @param {ReactText} text 86666 * @return {ReactComponent} 86667 */ 86668function createInstanceForText(text) { 86669 return new textComponentClass(text); 86670} 86671 86672/** 86673 * @param {ReactComponent} component 86674 * @return {boolean} 86675 */ 86676function isTextComponent(component) { 86677 return component instanceof textComponentClass; 86678} 86679 86680var ReactNativeComponent = { 86681 getComponentClassForElement: getComponentClassForElement, 86682 createInternalComponent: createInternalComponent, 86683 createInstanceForText: createInstanceForText, 86684 isTextComponent: isTextComponent, 86685 injection: ReactNativeComponentInjection 86686}; 86687 86688module.exports = ReactNativeComponent; 86689},{"158":158,"169":169}],79:[function(_dereq_,module,exports){ 86690/** 86691 * Copyright 2013-present, Facebook, Inc. 86692 * All rights reserved. 86693 * 86694 * This source code is licensed under the BSD-style license found in the 86695 * LICENSE file in the root directory of this source tree. An additional grant 86696 * of patent rights can be found in the PATENTS file in the same directory. 86697 * 86698 * @providesModule ReactNodeTypes 86699 */ 86700 86701 86702 86703var ReactElement = _dereq_(62); 86704 86705var invariant = _dereq_(158); 86706 86707var ReactNodeTypes = { 86708 NATIVE: 0, 86709 COMPOSITE: 1, 86710 EMPTY: 2, 86711 86712 getType: function (node) { 86713 if (node === null || node === false) { 86714 return ReactNodeTypes.EMPTY; 86715 } else if (ReactElement.isValidElement(node)) { 86716 if (typeof node.type === 'function') { 86717 return ReactNodeTypes.COMPOSITE; 86718 } else { 86719 return ReactNodeTypes.NATIVE; 86720 } 86721 } 86722 !false ? "development" !== 'production' ? invariant(false, 'Unexpected node: %s', node) : invariant(false) : void 0; 86723 } 86724}; 86725 86726module.exports = ReactNodeTypes; 86727},{"158":158,"62":62}],80:[function(_dereq_,module,exports){ 86728/** 86729 * Copyright 2015-present, Facebook, Inc. 86730 * All rights reserved. 86731 * 86732 * This source code is licensed under the BSD-style license found in the 86733 * LICENSE file in the root directory of this source tree. An additional grant 86734 * of patent rights can be found in the PATENTS file in the same directory. 86735 * 86736 * @providesModule ReactNoopUpdateQueue 86737 */ 86738 86739 86740 86741var warning = _dereq_(168); 86742 86743function warnTDZ(publicInstance, callerName) { 86744 if ("development" !== 'production') { 86745 "development" !== 'production' ? warning(false, '%s(...): Can only update a mounted or mounting component. ' + 'This usually means you called %s() on an unmounted component. ' + 'This is a no-op. Please check the code for the %s component.', callerName, callerName, publicInstance.constructor && publicInstance.constructor.displayName || '') : void 0; 86746 } 86747} 86748 86749/** 86750 * This is the abstract API for an update queue. 86751 */ 86752var ReactNoopUpdateQueue = { 86753 86754 /** 86755 * Checks whether or not this composite component is mounted. 86756 * @param {ReactClass} publicInstance The instance we want to test. 86757 * @return {boolean} True if mounted, false otherwise. 86758 * @protected 86759 * @final 86760 */ 86761 isMounted: function (publicInstance) { 86762 return false;
86763 }, 86764 86765 /** 86766 * Enqueue a callback that will be executed after all the pending updates 86767 * have processed. 86768 * 86769 * @param {ReactClass} publicInstance The instance to use as `this` context. 86770 * @param {?function} callback Called after state is updated. 86771 * @internal 86772 */ 86773 enqueueCallback: function (publicInstance, callback) {}, 86774 86775 /** 86776 * Forces an update. This should only be invoked when it is known with 86777 * certainty that we are **not** in a DOM transaction. 86778 * 86779 * You may want to call this when you know that some deeper aspect of the 86780 * component's state has changed but `setState` was not called. 86781 * 86782 * This will not invoke `shouldComponentUpdate`, but it will invoke 86783 * `componentWillUpdate` and `componentDidUpdate`. 86784 * 86785 * @param {ReactClass} publicInstance The instance that should rerender. 86786 * @internal 86787 */ 86788 enqueueForceUpdate: function (publicInstance) { 86789 warnTDZ(publicInstance, 'forceUpdate'); 86790 }, 86791 86792 /** 86793 * Replaces all of the state. Always use this or `setState` to mutate state. 86794 * You should treat `this.state` as immutable. 86795 * 86796 * There is no guarantee that `this.state` will be immediately updated, so 86797 * accessing `this.state` after calling this method may return the old value. 86798 * 86799 * @param {ReactClass} publicInstance The instance that should rerender. 86800 * @param {object} completeState Next state. 86801 * @internal 86802 */ 86803 enqueueReplaceState: function (publicInstance, completeState) { 86804 warnTDZ(publicInstance, 'replaceState'); 86805 }, 86806 86807 /** 86808 * Sets a subset of the state. This only exists because _pendingState is 86809 * internal. This provides a merging strategy that is not available to deep 86810 * properties which is confusing. TODO: Expose pendingState or don't use it 86811 * during the merge. 86812 * 86813 * @param {ReactClass} publicInstance The instance that should rerender. 86814 * @param {object} partialState Next partial state to be merged with state. 86815 * @internal 86816 */ 86817 enqueueSetState: function (publicInstance, partialState) { 86818 warnTDZ(publicInstance, 'setState'); 86819 } 86820}; 86821 86822module.exports = ReactNoopUpdateQueue; 86823},{"168":168}],81:[function(_dereq_,module,exports){ 86824/** 86825 * Copyright 2013-present, Facebook, Inc. 86826 * All rights reserved. 86827 * 86828 * This source code is licensed under the BSD-style license found in the 86829 * LICENSE file in the root directory of this source tree. An additional grant 86830 * of patent rights can be found in the PATENTS file in the same directory. 86831 * 86832 * @providesModule ReactOwner 86833 */ 86834 86835 86836 86837var invariant = _dereq_(158); 86838 86839/** 86840 * ReactOwners are capable of storing references to owned components. 86841 * 86842 * All components are capable of //being// referenced by owner components, but 86843 * only ReactOwner components are capable of //referencing// owned components. 86844 * The named reference is known as a "ref". 86845 * 86846 * Refs are available when mounted and updated during reconciliation. 86847 * 86848 * var MyComponent = React.createClass({ 86849 * render: function() { 86850 * return ( 86851 * <div onClick={this.handleClick}> 86852 * <CustomComponent ref="custom" /> 86853 * </div> 86854 * ); 86855 * }, 86856 * handleClick: function() { 86857 * this.refs.custom.handleClick(); 86858 * }, 86859 * componentDidMount: function() { 86860 * this.refs.custom.initialize(); 86861 * } 86862 * }); 86863 * 86864 * Refs should rarely be used. When refs are used, they should only be done to 86865 * control data that is not handled by React's data flow. 86866 * 86867 * @class ReactOwner 86868 */ 86869var ReactOwner = { 86870 86871 /** 86872 * @param {?object} object 86873 * @return {boolean} True if `object` is a valid owner. 86874 * @final 86875 */ 86876 isValidOwner: function (object) { 86877 return !!(object && typeof object.attachRef === 'function' && typeof object.detachRef === 'function'); 86878 }, 86879 86880 /** 86881 * Adds a component by ref to an owner component. 86882 * 86883 * @param {ReactComponent} component Component to reference. 86884 * @param {string} ref Name by which to refer to the component. 86885 * @param {ReactOwner} owner Component on which to record the ref. 86886 * @final 86887 * @internal 86888 */ 86889 addComponentAsRefTo: function (component, ref, owner) { 86890 !ReactOwner.isValidOwner(owner) ? "development" !== 'production' ? invariant(false, 'addComponentAsRefTo(...): Only a ReactOwner can have refs. You might ' + 'be adding a ref to a component that was not created inside a component\'s ' + '`render` method, or you have multiple copies of React loaded ' + '(details: https://fb.me/react-refs-must-have-owner).') : invariant(false) : void 0; 86891 owner.attachRef(ref, component); 86892 }, 86893 86894 /** 86895 * Removes a component by ref from an owner component. 86896 * 86897 * @param {ReactComponent} component Component to dereference. 86898 * @param {string} ref Name of the ref to remove. 86899 * @param {ReactOwner} owner Component on which the ref is recorded. 86900 * @final 86901 * @internal 86902 */ 86903 removeComponentAsRefFrom: function (component, ref, owner) { 86904 !ReactOwner.isValidOwner(owner) ? "development" !== 'production' ? invariant(false, 'removeComponentAsRefFrom(...): Only a ReactOwner can have refs. You might ' + 'be removing a ref to a component that was not created inside a component\'s ' + '`render` method, or you have multiple copies of React loaded ' + '(details: https://fb.me/react-refs-must-have-owner).') : invariant(false) : void 0; 86905 var ownerPublicInstance = owner.getPublicInstance(); 86906 // Check that `component`'s owner is still alive and that `component` is still the current ref 86907 // because we do not want to detach the ref if another component stole it. 86908 if (ownerPublicInstance && ownerPublicInstance.refs[ref] === component.getPublicInstance()) { 86909 owner.detachRef(ref); 86910 } 86911 } 86912 86913}; 86914 86915module.exports = ReactOwner; 86916},{"158":158}],82:[function(_dereq_,module,exports){ 86917/** 86918 * Copyright 2013-present, Facebook, Inc. 86919 * All rights reserved. 86920 * 86921 * This source code is licensed under the BSD-style license found in the 86922 * LICENSE file in the root directory of this source tree. An additional grant 86923 * of patent rights can be found in the PATENTS file in the same directory. 86924 * 86925 * @providesModule ReactPerf 86926 */ 86927 86928 86929 86930/** 86931 * ReactPerf is a general AOP system designed to measure performance. This 86932 * module only has the hooks: see ReactDefaultPerf for the analysis tool. 86933 */ 86934 86935var ReactPerf = { 86936 /** 86937 * Boolean to enable/disable measurement. Set to false by default to prevent 86938 * accidental logging and perf loss. 86939 */ 86940 enableMeasure: false, 86941 86942 /** 86943 * Holds onto the measure function in use. By default, don't measure 86944 * anything, but we'll override this if we inject a measure function. 86945 */ 86946 storedMeasure: _noMeasure, 86947 86948 /** 86949 * @param {object} object 86950 * @param {string} objectName 86951 * @param {object<string>} methodNames 86952 */ 86953 measureMethods: function (object, objectName, methodNames) { 86954 if ("development" !== 'production') { 86955 for (var key in methodNames) { 86956 if (!methodNames.hasOwnProperty(key)) { 86957 continue; 86958 } 86959 object[key] = ReactPerf.measure(objectName, methodNames[key], object[key]); 86960 } 86961 } 86962 }, 86963 86964 /** 86965 * Use this to wrap methods you want to measure. Zero overhead in production. 86966 * 86967 * @param {string} objName 86968 * @param {string} fnName 86969 * @param {function} func 86970 * @return {function} 86971 */ 86972 measure: function (objName, fnName, func) { 86973 if ("development" !== 'production') { 86974 var measuredFunc = null; 86975 var wrapper = function () { 86976 if (ReactPerf.enableMeasure) { 86977 if (!measuredFunc) { 86978 measuredFunc = ReactPerf.storedMeasure(objName, fnName, func); 86979 } 86980 return measuredFunc.apply(this, arguments); 86981 } 86982 return func.apply(this, arguments); 86983 }; 86984 wrapper.displayName = objName + '_' + fnName; 86985 return wrapper; 86986 } 86987 return func; 86988 }, 86989 86990 injection: { 86991 /** 86992 * @param {function} measure 86993 */ 86994 injectMeasure: function (measure) { 86995 ReactPerf.storedMeasure = measure; 86996 } 86997 } 86998}; 86999 87000/** 87001 * Simply passes through the measured function, without measuring it. 87002 * 87003 * @param {string} objName 87004 * @param {string} fnName 87005 * @param {function} func 87006 * @return {function} 87007 */ 87008function _noMeasure(objName, fnName, func) { 87009 return func; 87010} 87011 87012module.exports = ReactPerf; 87013},{}],83:[function(_dereq_,module,exports){ 87014/** 87015 * Copyright 2013-present, Facebook, Inc. 87016 * All rights reserved. 87017 * 87018 * This source code is licensed under the BSD-style license found in the 87019 * LICENSE file in the root directory of this source tree. An additional grant 87020 * of patent rights can be found in the PATENTS file in the same directory. 87021 * 87022 * @providesModule ReactPropTypeLocationNames 87023 */ 87024 87025 87026 87027var ReactPropTypeLocationNames = {}; 87028 87029if ("development" !== 'production') { 87030 ReactPropTypeLocationNames = { 87031 prop: 'prop', 87032 context: 'context', 87033 childContext: 'child context' 87034 }; 87035} 87036 87037module.exports = ReactPropTypeLocationNames; 87038},{}],84:[function(_dereq_,module,exports){ 87039/** 87040 * Copyright 2013-present, Facebook, Inc. 87041 * All rights reserved. 87042 * 87043 * This source code is licensed under the BSD-style license found in the 87044 * LICENSE file in the root directory of this source tree. An additional grant 87045 * of patent rights can be found in the PATENTS file in the same directory. 87046 * 87047 * @providesModule ReactPropTypeLocations 87048 */ 87049 87050 87051 87052var keyMirror = _dereq_(161); 87053 87054var ReactPropTypeLocations = keyMirror({ 87055 prop: null, 87056 context: null, 87057 childContext: null 87058}); 87059 87060module.exports = ReactPropTypeLocations; 87061},{"161":161}],85:[function(_dereq_,module,exports){ 87062/** 87063 * Copyright 2013-present, Facebook, Inc. 87064 * All rights reserved. 87065 * 87066 * This source code is licensed under the BSD-style license found in the 87067 * LICENSE file in the root directory of this source tree. An additional grant 87068 * of patent rights can be found in the PATENTS file in the same directory. 87069 * 87070 * @providesModule ReactPropTypes 87071 */ 87072 87073 87074 87075var ReactElement = _dereq_(62); 87076var ReactPropTypeLocationNames = _dereq_(83); 87077 87078var emptyFunction = _dereq_(150); 87079var getIteratorFn = _dereq_(127); 87080 87081/** 87082 * Collection of methods that allow declaration and validation of props that are 87083 * supplied to React components. Example usage: 87084 * 87085 * var Props = require('ReactPropTypes'); 87086 * var MyArticle = React.createClass({ 87087 * propTypes: { 87088 * // An optional string prop named "description". 87089 * description: Props.string, 87090 * 87091 * // A required enum prop named "category". 87092 * category: Props.oneOf(['News','Photos']).isRequired, 87093 * 87094 * // A prop named "dialog" that requires an instance of Dialog. 87095 * dialog: Props.instanceOf(Dialog).isRequired 87096 * }, 87097 * render: function() { ... } 87098 * }); 87099 * 87100 * A more formal specification of how these methods are used: 87101 * 87102 * type := array|bool|func|object|number|string|oneOf([...])|instanceOf(...) 87103 * decl := ReactPropTypes.{type}(.isRequired)? 87104 * 87105 * Each and every declaration produces a function with the same signature. This 87106 * allows the creation of custom validation functions. For example: 87107 * 87108 * var MyLink = React.createClass({ 87109 * propTypes: { 87110 * // An optional string or URI prop named "href". 87111 * href: function(props, propName, componentName) { 87112 * var propValue = props[propName]; 87113 * if (propValue != null && typeof propValue !== 'string' && 87114 * !(propValue instanceof URI)) { 87115 * return new Error( 87116 * 'Expected a string or an URI for ' + propName + ' in ' + 87117 * componentName 87118 * ); 87119 * } 87120 * } 87121 * }, 87122 * render: function() {...} 87123 * }); 87124 * 87125 * @internal 87126 */ 87127 87128var ANONYMOUS = '<<anonymous>>'; 87129 87130var ReactPropTypes = { 87131 array: createPrimitiveTypeChecker('array'), 87132 bool: createPrimitiveTypeChecker('boolean'), 87133 func: createPrimitiveTypeChecker('function'), 87134 number: createPrimitiveTypeChecker('number'), 87135 object: createPrimitiveTypeChecker('object'), 87136 string: createPrimitiveTypeChecker('string'), 87137 87138 any: createAnyTypeChecker(), 87139 arrayOf: createArrayOfTypeChecker, 87140 element: createElementTypeChecker(), 87141 instanceOf: createInstanceTypeChecker, 87142 node: createNodeChecker(), 87143 objectOf: createObjectOfTypeChecker, 87144 oneOf: createEnumTypeChecker, 87145 oneOfType: createUnionTypeChecker, 87146 shape: createShapeTypeChecker 87147}; 87148 87149/** 87150 * inlined Object.is polyfill to avoid requiring consumers ship their own 87151 * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is 87152 */ 87153/*eslint-disable no-self-compare*/ 87154function is(x, y) { 87155 // SameValue algorithm 87156 if (x === y) { 87157 // Steps 1-5, 7-10 87158 // Steps 6.b-6.e: +0 != -0 87159 return x !== 0 || 1 / x === 1 / y; 87160 } else { 87161 // Step 6.a: NaN == NaN 87162 return x !== x && y !== y; 87163 } 87164} 87165/*eslint-enable no-self-compare*/ 87166 87167function createChainableTypeChecker(validate) { 87168 function checkType(isRequired, props, propName, componentName, location, propFullName) { 87169 componentName = componentName || ANONYMOUS; 87170 propFullName = propFullName || propName; 87171 if (props[propName] == null) { 87172 var locationName = ReactPropTypeLocationNames[location]; 87173 if (isRequired) { 87174 return new Error('Required ' + locationName + ' `' + propFullName + '` was not specified in ' + ('`' + componentName + '`.')); 87175 } 87176 return null; 87177 } else { 87178 return validate(props, propName, componentName, location, propFullName); 87179 } 87180 } 87181 87182 var chainedCheckType = checkType.bind(null, false); 87183 chainedCheckType.isRequired = checkType.bind(null, true); 87184 87185 return chainedCheckType; 87186} 87187 87188function createPrimitiveTypeChecker(expectedType) { 87189 function validate(props, propName, componentName, location, propFullName) { 87190 var propValue = props[propName]; 87191 var propType = getPropType(propValue); 87192 if (propType !== expectedType) { 87193 var locationName = ReactPropTypeLocationNames[location]; 87194 // `propValue` being instance of, say, date/regexp, pass the 'object' 87195 // check, but we can offer a more precise error message here rather than 87196 // 'of type `object`'. 87197 var preciseType = getPreciseType(propValue); 87198 87199 return new Error('Invalid ' + locationName + ' `' + propFullName + '` of type ' + ('`' + preciseType + '` supplied to `' + componentName + '`, expected ') + ('`' + expectedType + '`.')); 87200 } 87201 return null; 87202 } 87203 return createChainableTypeChecker(validate); 87204} 87205 87206function createAnyTypeChecker() { 87207 return createChainableTypeChecker(emptyFunction.thatReturns(null)); 87208} 87209 87210function createArrayOfTypeChecker(typeChecker) { 87211 function validate(props, propName, componentName, location, propFullName) { 87212 if (typeof typeChecker !== 'function') { 87213 return new Error('Property `' + propFullName + '` of component `' + componentName + '` has invali
87213d PropType notation inside arrayOf.'); 87214 } 87215 var propValue = props[propName]; 87216 if (!Array.isArray(propValue)) { 87217 var locationName = ReactPropTypeLocationNames[location]; 87218 var propType = getPropType(propValue); 87219 return new Error('Invalid ' + locationName + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected an array.')); 87220 } 87221 for (var i = 0; i < propValue.length; i++) { 87222 var error = typeChecker(propValue, i, componentName, location, propFullName + '[' + i + ']'); 87223 if (error instanceof Error) { 87224 return error; 87225 } 87226 } 87227 return null; 87228 } 87229 return createChainableTypeChecker(validate); 87230} 87231 87232function createElementTypeChecker() { 87233 function validate(props, propName, componentName, location, propFullName) { 87234 if (!ReactElement.isValidElement(props[propName])) { 87235 var locationName = ReactPropTypeLocationNames[location]; 87236 return new Error('Invalid ' + locationName + ' `' + propFullName + '` supplied to ' + ('`' + componentName + '`, expected a single ReactElement.')); 87237 } 87238 return null; 87239 } 87240 return createChainableTypeChecker(validate); 87241} 87242 87243function createInstanceTypeChecker(expectedClass) { 87244 function validate(props, propName, componentName, location, propFullName) { 87245 if (!(props[propName] instanceof expectedClass)) { 87246 var locationName = ReactPropTypeLocationNames[location]; 87247 var expectedClassName = expectedClass.name || ANONYMOUS; 87248 var actualClassName = getClassName(props[propName]); 87249 return new Error('Invalid ' + locationName + ' `' + propFullName + '` of type ' + ('`' + actualClassName + '` supplied to `' + componentName + '`, expected ') + ('instance of `' + expectedClassName + '`.')); 87250 } 87251 return null; 87252 } 87253 return createChainableTypeChecker(validate); 87254} 87255 87256function createEnumTypeChecker(expectedValues) { 87257 if (!Array.isArray(expectedValues)) { 87258 return createChainableTypeChecker(function () { 87259 return new Error('Invalid argument supplied to oneOf, expected an instance of array.'); 87260 }); 87261 } 87262 87263 function validate(props, propName, componentName, location, propFullName) { 87264 var propValue = props[propName]; 87265 for (var i = 0; i < expectedValues.length; i++) { 87266 if (is(propValue, expectedValues[i])) { 87267 return null; 87268 } 87269 } 87270 87271 var locationName = ReactPropTypeLocationNames[location]; 87272 var valuesString = JSON.stringify(expectedValues); 87273 return new Error('Invalid ' + locationName + ' `' + propFullName + '` of value `' + propValue + '` ' + ('supplied to `' + componentName + '`, expected one of ' + valuesString + '.')); 87274 } 87275 return createChainableTypeChecker(validate); 87276} 87277 87278function createObjectOfTypeChecker(typeChecker) { 87279 function validate(props, propName, componentName, location, propFullName) { 87280 if (typeof typeChecker !== 'function') { 87281 return new Error('Property `' + propFullName + '` of component `' + componentName + '` has invalid PropType notation inside objectOf.'); 87282 } 87283 var propValue = props[propName]; 87284 var propType = getPropType(propValue); 87285 if (propType !== 'object') { 87286 var locationName = ReactPropTypeLocationNames[location]; 87287 return new Error('Invalid ' + locationName + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected an object.')); 87288 } 87289 for (var key in propValue) { 87290 if (propValue.hasOwnProperty(key)) { 87291 var error = typeChecker(propValue, key, componentName, location, propFullName + '.' + key); 87292 if (error instanceof Error) { 87293 return error; 87294 } 87295 } 87296 } 87297 return null; 87298 } 87299 return createChainableTypeChecker(validate); 87300} 87301 87302function createUnionTypeChecker(arrayOfTypeCheckers) { 87303 if (!Array.isArray(arrayOfTypeCheckers)) { 87304 return createChainableTypeChecker(function () { 87305 return new Error('Invalid argument supplied to oneOfType, expected an instance of array.'); 87306 }); 87307 } 87308 87309 function validate(props, propName, componentName, location, propFullName) { 87310 for (var i = 0; i < arrayOfTypeCheckers.length; i++) { 87311 var checker = arrayOfTypeCheckers[i]; 87312 if (checker(props, propName, componentName, location, propFullName) == null) { 87313 return null; 87314 } 87315 } 87316 87317 var locationName = ReactPropTypeLocationNames[location]; 87318 return new Error('Invalid ' + locationName + ' `' + propFullName + '` supplied to ' + ('`' + componentName + '`.')); 87319 } 87320 return createChainableTypeChecker(validate); 87321} 87322 87323function createNodeChecker() { 87324 function validate(props, propName, componentName, location, propFullName) { 87325 if (!isNode(props[propName])) { 87326 var locationName = ReactPropTypeLocationNames[location]; 87327 return new Error('Invalid ' + locationName + ' `' + propFullName + '` supplied to ' + ('`' + componentName + '`, expected a ReactNode.')); 87328 } 87329 return null; 87330 } 87331 return createChainableTypeChecker(validate); 87332} 87333 87334function createShapeTypeChecker(shapeTypes) { 87335 function validate(props, propName, componentName, location, propFullName) { 87336 var propValue = props[propName]; 87337 var propType = getPropType(propValue); 87338 if (propType !== 'object') { 87339 var locationName = ReactPropTypeLocationNames[location]; 87340 return new Error('Invalid ' + locationName + ' `' + propFullName + '` of type `' + propT
vendor: 6,165 bytes, lines 87340-87553
87340ype + '` ' + ('supplied to `' + componentName + '`, expected `object`.')); 87341 } 87342 for (var key in shapeTypes) { 87343 var checker = shapeTypes[key]; 87344 if (!checker) { 87345 continue; 87346 } 87347 var error = checker(propValue, key, componentName, location, propFullName + '.' + key); 87348 if (error) { 87349 return error; 87350 } 87351 } 87352 return null; 87353 } 87354 return createChainableTypeChecker(validate); 87355} 87356 87357function isNode(propValue) { 87358 switch (typeof propValue) { 87359 case 'number': 87360 case 'string': 87361 case 'undefined': 87362 return true; 87363 case 'boolean': 87364 return !propValue; 87365 case 'object': 87366 if (Array.isArray(propValue)) { 87367 return propValue.every(isNode); 87368 } 87369 if (propValue === null || ReactElement.isValidElement(propValue)) { 87370 return true; 87371 } 87372 87373 var iteratorFn = getIteratorFn(propValue); 87374 if (iteratorFn) { 87375 var iterator = iteratorFn.call(propValue); 87376 var step; 87377 if (iteratorFn !== propValue.entries) { 87378 while (!(step = iterator.next()).done) { 87379 if (!isNode(step.value)) { 87380 return false; 87381 } 87382 } 87383 } else { 87384 // Iterator will provide entry [k,v] tuples rather than values. 87385 while (!(step = iterator.next()).done) { 87386 var entry = step.value; 87387 if (entry) { 87388 if (!isNode(entry[1])) { 87389 return false; 87390 } 87391 } 87392 } 87393 } 87394 } else { 87395 return false; 87396 } 87397 87398 return true; 87399 default: 87400 return false; 87401 } 87402} 87403 87404// Equivalent of `typeof` but with special handling for array and regexp. 87405function getPropType(propValue) { 87406 var propType = typeof propValue; 87407 if (Array.isArray(propValue)) { 87408 return 'array'; 87409 } 87410 if (propValue instanceof RegExp) { 87411 // Old webkits (at least until Android 4.0) return 'function' rather than 87412 // 'object' for typeof a RegExp. We'll normalize this here so that /bla/ 87413 // passes PropTypes.object. 87414 return 'object'; 87415 } 87416 return propType; 87417} 87418 87419// This handles more types than `getPropType`. Only used for error messages. 87420// See `createPrimitiveTypeChecker`. 87421function getPreciseType(propValue) { 87422 var propType = getPropType(propValue); 87423 if (propType === 'object') { 87424 if (propValue instanceof Date) { 87425 return 'date'; 87426 } else if (propValue instanceof RegExp) { 87427 return 'regexp'; 87428 } 87429 } 87430 return propType; 87431} 87432 87433// Returns class name of the object, if any. 87434function getClassName(propValue) { 87435 if (!propValue.constructor || !propValue.constructor.name) { 87436 return ANONYMOUS; 87437 } 87438 return propValue.constructor.name; 87439} 87440 87441module.exports = ReactPropTypes; 87442},{"127":127,"150":150,"62":62,"83":83}],86:[function(_dereq_,module,exports){ 87443/** 87444 * Copyright 2013-present, Facebook, Inc. 87445 * All rights reserved. 87446 * 87447 * This source code is licensed under the BSD-style license found in the 87448 * LICENSE file in the root directory of this source tree. An additional grant 87449 * of patent rights can be found in the PATENTS file in the same directory. 87450 * 87451 * @providesModule ReactReconcileTransaction 87452 */ 87453 87454 87455 87456var _assign = _dereq_(169); 87457 87458var CallbackQueue = _dereq_(5); 87459var PooledClass = _dereq_(25); 87460var ReactBrowserEventEmitter = _dereq_(27); 87461var ReactInputSelection = _dereq_(70); 87462var Transaction = _dereq_(112); 87463 87464/** 87465 * Ensures that, when possible, the selection range (currently selected text 87466 * input) is not disturbed by performing the transaction. 87467 */ 87468var SELECTION_RESTORATION = { 87469 /** 87470 * @return {Selection} Selection information. 87471 */ 87472 initialize: ReactInputSelection.getSelectionInformation, 87473 /** 87474 * @param {Selection} sel Selection information returned from `initialize`. 87475 */ 87476 close: ReactInputSelection.restoreSelection 87477}; 87478 87479/** 87480 * Suppresses events (blur/focus) that could be inadvertently dispatched due to 87481 * high level DOM manipulations (like temporarily removing a text input from the 87482 * DOM). 87483 */ 87484var EVENT_SUPPRESSION = { 87485 /** 87486 * @return {boolean} The enabled status of `ReactBrowserEventEmitter` before 87487 * the reconciliation. 87488 */ 87489 initialize: function () { 87490 var currentlyEnabled = ReactBrowserEventEmitter.isEnabled(); 87491 ReactBrowserEventEmitter.setEnabled(false); 87492 return currentlyEnabled; 87493 }, 87494 87495 /** 87496 * @param {boolean} previouslyEnabled Enabled status of 87497 * `ReactBrowserEventEmitter` before the reconciliation occurred. `close` 87498 * restores the previous value. 87499 */ 87500 close: function (previouslyEnabled) { 87501 ReactBrowserEventEmitter.setEnabled(previouslyEnabled); 87502 } 87503}; 87504 87505/** 87506 * Provides a queue for collecting `componentDidMount` and 87507 * `componentDidUpdate` callbacks during the transaction. 87508 */ 87509var ON_DOM_READY_QUEUEING = { 87510 /** 87511 * Initializes the internal `onDOMReady` queue. 87512 */ 87513 initialize: function () { 87514 this.reactMountReady.reset(); 87515 }, 87516 87517 /** 87518 * After DOM is flushed, invoke all registered `onDOMReady` callbacks. 87519 */ 87520 close: function () { 87521 this.reactMountReady.notifyAll(); 87522 } 87523}; 87524 87525/** 87526 * Executed within the scope of the `Transaction` instance. Consider these as 87527 * being member methods, but with an implied ordering while being isolated from 87528 * each other. 87529 */ 87530var TRANSACTION_WRAPPERS = [SELECTION_RESTORATION, EVENT_SUPPRESSION, ON_DOM_READY_QUEUEING]; 87531 87532/** 87533 * Currently: 87534 * - The order that these are listed in the transaction is critical: 87535 * - Suppresses events. 87536 * - Restores selection range. 87537 * 87538 * Future: 87539 * - Restore document/overflow scroll positions that were unintentionally 87540 * modified via DOM insertions above the top viewport boundary. 87541 * - Implement/integrate with customized constraint based layout system and keep 87542 * track of which dimensions must be remeasured. 87543 * 87544 * @class ReactReconcileTransaction 87545 */ 87546function ReactReconcileTransaction(useCreateElement) { 87547 this.reinitializeTransaction(); 87548 // Only server-side rendering really needs this option (see 87549 // `ReactServerRendering`), but server-side uses 87550 // `ReactServerRenderingTransaction` instead. This option is here so that it's 87551 // accessible and defaults to false when `ReactDOMComponent` and 87552 // `ReactTextComponent` checks it in `mountComponent`.` 87553 this.renderToStaticMarkup = false;
87554 this.reactMountReady = CallbackQueue.getPooled(null); 87555 this.useCreateElement = useCreateElement; 87556} 87557 87558var Mixin = { 87559 /** 87560 * @see Transaction 87561 * @abstract 87562 * @final 87563 * @return {array<object>} List of operation wrap procedures. 87564 * TODO: convert to array<TransactionWrapper> 87565 */ 87566 getTransactionWrappers: function () { 87567 return TRANSACTION_WRAPPERS; 87568 }, 87569 87570 /** 87571 * @return {object} The queue to collect `onDOMReady` callbacks with. 87572 */ 87573 getReactMountReady: function () { 87574 return this.reactMountReady; 87575 }, 87576 87577 /** 87578 * Save current transaction state -- if the return value from this method is 87579 * passed to `rollback`, the transaction will be reset to that state. 87580 */ 87581 checkpoint: function () { 87582 // reactMountReady is the our only stateful wrapper 87583 return this.reactMountReady.checkpoint(); 87584 }, 87585 87586 rollback: function (checkpoint) { 87587 this.reactMountReady.rollback(checkpoint); 87588 }, 87589 87590 /** 87591 * `PooledClass` looks for this, and will invoke this before allowing this 87592 * instance to be reused. 87593 */ 87594 destructor: function () { 87595 CallbackQueue.release(this.reactMountReady); 87596 this.reactMountReady = null; 87597 } 87598}; 87599 87600_assign(ReactReconcileTransaction.prototype, Transaction.Mixin, Mixin); 87601 87602PooledClass.addPoolingTo(ReactReconcileTransaction); 87603 87604module.exports = ReactReconcileTransaction; 87605},{"112":112,"169":169,"25":25,"27":27,"5":5,"70":70}],87:[function(_dereq_,module,exports){ 87606/** 87607 * Copyright 2013-present, Facebook, Inc. 87608 * All rights reserved. 87609 * 87610 * This source code is licensed under the BSD-style license found in the 87611 * LICENSE file in the root directory of this source tree. An additional grant 87612 * of patent rights can be found in the PATENTS file in the same directory. 87613 * 87614 * @providesModule ReactReconciler 87615 */ 87616 87617 87618 87619var ReactRef = _dereq_(88); 87620var ReactInstrumentation = _dereq_(72); 87621 87622/** 87623 * Helper to call ReactRef.attachRefs with this composite component, split out 87624 * to avoid allocations in the transaction mount-ready queue. 87625 */ 87626function attachRefs() { 87627 ReactRef.attachRefs(this, this._currentElement); 87628} 87629 87630var ReactReconciler = { 87631 87632 /** 87633 * Initializes the component, renders markup, and registers event listeners. 87634 * 87635 * @param {ReactComponent} internalInstance 87636 * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction 87637 * @param {?object} the containing native component instance 87638 * @param {?object} info about the native container 87639 * @return {?string} Rendered markup to be inserted into the DOM. 87640 * @final 87641 * @internal 87642 */ 87643 mountComponent: function (internalInstance, transaction, nativeParent, nativeContainerInfo, context) { 87644 var markup = internalInstance.mountComponent(transaction, nativeParent, nativeContainerInfo, context); 87645 if (internalInstance._currentElement && internalInstance._currentElement.ref != null) { 87646 transaction.getReactMountReady().enqueue(attachRefs, internalInstance); 87647 } 87648 if ("development" !== 'production') { 87649 ReactInstrumentation.debugTool.onMountComponent(internalInstance); 87650 } 87651 return markup; 87652 }, 87653 87654 /** 87655 * Returns a value that can be passed to 87656 * ReactComponentEnvironment.replaceNodeWithMarkup. 87657 */ 87658 getNativeNode: function (internalInstance) { 87659 return internalInstance.getNativeNode(); 87660 }, 87661 87662 /** 87663 * Releases any resources allocated by `mountComponent`. 87664 * 87665 * @final 87666 * @internal 87667 */ 87668 unmountComponent: function (internalInstance, safely) { 87669 ReactRef.detachRefs(internalInstance, internalInstance._currentElement); 87670 internalInstance.unmountComponent(safely); 87671 if ("development" !== 'production') { 87672 ReactInstrumentation.debugTool.onUnmountComponent(internalInstance); 87673 } 87674 }, 87675 87676 /** 87677 * Update a component using a new element. 87678 * 87679 * @param {ReactComponent} internalInstance 87680 * @param {ReactElement} nextElement 87681 * @param {ReactReconcileTransaction} transaction 87682 * @param {object} context 87683 * @internal 87684 */ 87685 receiveComponent: function (internalInstance, nextElement, transaction, context) { 87686 var prevElement = internalInstance._currentElement; 87687 87688 if (nextElement === prevElement && context === internalInstance._context) { 87689 // Since elements are immutable after the owner is rendered, 87690 // we can do a cheap identity compare here to determine if this is a 87691 // superfluous reconcile. It's possible for state to be mutable but such 87692 // change should trigger an update of the owner which would recreate 87693 // the element. We explicitly check for the existence of an owner since 87694 // it's possible for an element created outside a composite to be 87695 // deeply mutated and reused. 87696 87697 // TODO: Bailing out early is just a perf optimization right? 87698 // TODO: Removing the return statement should affect correctness? 87699 return; 87700 } 87701 87702 var refsChanged = ReactRef.shouldUpdateRefs(prevElement, nextElement); 87703 87704 if (refsChanged) { 87705 ReactRef.detachRefs(internalInstance, prevElement); 87706 } 87707 87708 internalInstance.receiveComponent(nextElement, transaction, context); 87709 87710 if (refsChanged && internalInstance._currentElement && internalInstance._currentElement.ref != null) { 87711 transaction.getReactMountReady().enqueue(attachRefs, internalInstance); 87712 } 87713 87714 if ("development" !== 'production') { 87715 ReactInstrumentation.debugTool.onUpdateComponent(internalInstance); 87716 } 87717 }, 87718 87719 /** 87720 * Flush any dirty changes in a component. 87721 * 87722 * @param {ReactComponent} internalInstance 87723 * @param {ReactReconcileTransaction} transaction 87724 * @internal 87725 */ 87726 performUpdateIfNecessary: function (internalInstance, transaction) { 87727 internalInstance.performUpdateIfNecessary(transaction); 87728 if ("development" !== 'production') { 87729 ReactInstrumentation.debugTool.onUpdateComponent(internalInstance); 87730 } 87731 } 87732 87733}; 87734 87735module.exports = ReactReconciler; 87736},{"72":72,"88":88}],88:[function(_dereq_,module,exports){ 87737/** 87738 * Copyright 2013-present, Facebook, Inc. 87739 * All rights reserved. 87740 * 87741 * This source code is licensed under the BSD-style license found in the 87742 * LICENSE file in the root directory of this source tree. An additional grant 87743 * of patent rights can be found in the PATENTS file in the same directory. 87744 * 87745 * @providesModule ReactRef 87746 */ 87747 87748 87749 87750var ReactOwner = _dereq_(81); 87751 87752var ReactRef = {}; 87753 87754function attachRef(ref, component, owner) { 87755 if (typeof ref === 'function') { 87756 ref(component.getPublicInstance()); 87757 } else { 87758 // Legacy ref 87759 ReactOwner.addComponentAsRefTo(component, ref, owner); 87760 } 87761} 87762 87763function detachRef(ref, component, owner) { 87764 if (typeof ref === 'function') { 87765 ref(null); 87766 } else { 87767 // Legacy ref 87768 ReactOwner.removeComponentAsRefFrom(component, ref, owner); 87769 } 87770} 87771 87772ReactRef.attachRefs = function (instance, element) { 87773 if (element === null || element === false) { 87774 return; 87775 } 87776 var ref = element.ref; 87777 if (ref != null) { 87778 attachRef(ref, instance, element._owner); 87779 } 87780}; 87781 87782ReactRef.shouldUpdateRefs = function (prevElement, nextElement) { 87783 // If either the owner or a `ref` has changed, make sure the newest owner 87784 // has stored a reference to `this`, and the previous owner (if different) 87785 // has forgotten the reference to `this`. We use the element instead 87786 // of the public this.props because the post processing cannot determine 87787 // a ref. The ref conceptually lives on the element. 87788 87789 // TODO: Should this even be possible? The owner cannot change because 87790 // it's forbidden by shouldUpdateReactComponent. The ref can change 87791 // if you swap the keys of but not the refs. Reconsider where this check 87792 // is made. It probably belongs where the key checking and 87793 // instantiateReactComponent is done. 87794 87795 var prevEmpty = prevElement === null || prevElement === false; 87796 var nextEmpty = nextElement === null || nextElement === false; 87797 87798 return( 87799 // This has a few false positives w/r/t empty components. 87800 prevEmpty || nextEmpty || nextElement._owner !== prevElement._owner || nextElement.ref !== prevElement.ref 87801 ); 87802}; 87803 87804ReactRef.detachRefs = function (instance, element) { 87805 if (element === null || element === false) { 87806 return; 87807 } 87808 var ref = element.ref; 87809 if (ref != null) { 87810 detachRef(ref, instance, element._owner); 87811 } 87812}; 87813 87814module.exports = ReactRef; 87815},{"81":81}],89:[function(_dereq_,module,exports){ 87816/** 87817 * Copyright 2014-present, Facebook, Inc. 87818 * All rights reserved. 87819 * 87820 * This source code is licensed under the BSD-style license found in the 87821 * LICENSE file in the root directory of this source tree. An additional grant 87822 * of patent rights can be found in the PATENTS file in the same directory. 87823 * 87824 * @providesModule ReactServerBatchingStrategy 87825 */ 87826 87827 87828 87829var ReactServerBatchingStrategy = { 87830 isBatchingUpdates: false, 87831 batchedUpdates: function (callback) { 87832 // Don't do anything here. During the server rendering we don't want to 87833 // schedule any updates. We will simply ignore them. 87834 } 87835}; 87836 87837module.exports = ReactServerBatchingStrategy; 87838},{}],90:[function(_dereq_,module,exports){ 87839/** 87840 * Copyright 2013-present, Facebook, Inc. 87841 * All rights reserved. 87842 * 87843 * This source code is licensed under the BSD-style license found in the 87844 * LICENSE file in the root directory of this source tree. An additional grant 87845 * of patent rights can be found in the PATENTS file in the same directory. 87846 * 87847 * @providesModule ReactServerRendering 87848 */ 87849 87850 87851var ReactDOMContainerInfo = _dereq_(41); 87852var ReactDefaultBatchingStrategy = _dereq_(58); 87853var ReactElement = _dereq_(62); 87854var ReactMarkupChecksum = _dereq_(74); 87855var ReactServerBatchingStrategy = _dereq_(89); 87856var ReactServerRenderingTransaction = _dereq_(91); 87857var ReactUpdates = _dereq_(94); 87858 87859var emptyObject = _dereq_(151); 87860var instantiateReactComponent = _dereq_(132); 87861var invariant = _dereq_(158); 87862 87863/** 87864 * @param {ReactElement} element 87865 * @return {string} the HTML markup 87866 */ 87867function renderToStringImpl(element, makeStaticMarkup) { 87868 var transaction; 87869 try { 87870 ReactUpdates.injection.injectBatchingStrategy(ReactServerBatchingStrategy); 87871 87872 transaction = ReactServerRenderingTransaction.getPooled(makeStaticMarkup); 87873 87874 return transaction.perform(function () { 87875 var componentInstance = instantiateReactComponent(element); 87876 var markup = componentInstance.mountComponent(transaction, null, ReactDOMContainerInfo(), emptyObject); 87877 if (!makeStaticMarkup) { 87878 markup = ReactMarkupChecksum.addChecksumToMarkup(markup); 87879 } 87880 return markup; 87881 }, null); 87882 } finally { 87883 ReactServerRenderingTransaction.release(transaction); 87884 // Revert to the DOM batching strategy since these two renderers 87885 // currently share these stateful modules. 87886 ReactUpdates.injection.injectBatchingStrategy(ReactDefaultBatchingStrategy); 87887 } 87888} 87889 87890function renderToString(element) { 87891 !ReactElement.isValidElement(element) ? "development" !== 'production' ? invariant(false, 'renderToString(): You must pass a valid ReactElement.') : invariant(false) : void 0; 87892 return renderToStringImpl(element, false); 87893} 87894 87895function renderToStaticMarkup(element) { 87896 !ReactElement.isValidElement(element) ? "development" !== 'production' ? invariant(false, 'renderToStaticMarkup(): You must pass a valid ReactElement.') : invariant(false) : void 0; 87897 return renderToStringImpl(element, true); 87898} 87899 87900module.exports = { 87901 renderToString: renderToString, 87902 renderToStaticMarkup: renderToStaticMarkup 87903}; 87904},{"132":132,"151":151,"158":158,"41":41,"58":58,"62":62,"74":74,"89":89,"91":91,"94":94}],91:[function(_dereq_,module,exports){ 87905/** 87906 * Copyright 2014-present, Facebook, Inc. 87907 * All rights reserved. 87908 * 87909 * This source code is licensed under the BSD-style license found in the 87910 * LICENSE file in the root directory of this source tree. An additional grant 87911 * of patent rights can be found in the PATENTS file in the same directory. 87912 * 87913 * @providesModule ReactServerRenderingTransaction 87914 */ 87915 87916 87917 87918var _assign = _dereq_(169); 87919 87920var PooledClass = _dereq_(25); 87921var Transaction = _dereq_(112); 87922 87923/** 87924 * Executed within the scope of the `Transaction` instance. Consider these as 87925 * being member methods, but with an implied ordering while being isolated from 87926 * each other. 87927 */ 87928var TRANSACTION_WRAPPERS = []; 87929 87930var noopCallbackQueue = { 87931 enqueue: function () {} 87932}; 87933 87934/** 87935 * @class ReactServerRenderingTransaction 87936 * @param {boolean} renderToStaticMarkup 87937 */ 87938function ReactServerRenderingTransaction(renderToStaticMarkup) { 87939 this.reinitializeTransaction(); 87940 this.renderToStaticMarkup = renderToStaticMarkup; 87941 this.useCreateElement = false;
87942} 87943 87944var Mixin = { 87945 /** 87946 * @see Transaction 87947 * @abstract 87948 * @final 87949 * @return {array} Empty list of operation wrap procedures. 87950 */ 87951 getTransactionWrappers: function () { 87952 return TRANSACTION_WRAPPERS; 87953 }, 87954 87955 /** 87956 * @return {object} The queue to collect `onDOMReady` callbacks with. 87957 */ 87958 getReactMountReady: function () { 87959 return noopCallbackQueue; 87960 }, 87961 87962 /** 87963 * `PooledClass` looks for this, and will invoke this before allowing this 87964 * instance to be reused. 87965 */ 87966 destructor: function () {} 87967}; 87968 87969_assign(ReactServerRenderingTransaction.prototype, Transaction.Mixin, Mixin); 87970 87971PooledClass.addPoolingTo(ReactServerRenderingTransaction); 87972 87973module.exports = ReactServerRenderingTransaction; 87974},{"112":112,"169":169,"25":25}],92:[function(_dereq_,module,exports){ 87975/** 87976 * Copyright 2013-present, Facebook, Inc. 87977 * All rights reserved. 87978 * 87979 * This source code is licensed under the BSD-style license found in the 87980 * LICENSE file in the root directory of this source tree. An additional grant 87981 * of patent rights can be found in the PATENTS file in the same directory. 87982 * 87983 * @providesModule ReactUMDEntry 87984 */ 87985 87986 87987 87988var _assign = _dereq_(169); 87989 87990var ReactDOM = _dereq_(36); 87991var ReactDOMServer = _dereq_(52); 87992var React = _dereq_(26); 87993 87994// `version` will be added here by ReactIsomorphic. 87995var ReactUMDEntry = _assign({ 87996 __SECRET_DOM_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: ReactDOM, 87997 __SECRET_DOM_SERVER_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: ReactDOMServer 87998}, React); 87999 88000module.exports = ReactUMDEntry; 88001},{"169":169,"26":26,"36":36,"52":52}],93:[function(_dereq_,module,exports){ 88002/** 88003 * Copyright 2015-present, Facebook, Inc. 88004 * All rights reserved. 88005 * 88006 * This source code is licensed under the BSD-style license found in the 88007 * LICENSE file in the root directory of this source tree. An additional grant 88008 * of patent rights can be found in the PATENTS file in the same directory. 88009 * 88010 * @providesModule ReactUpdateQueue 88011 */ 88012 88013 88014 88015var ReactCurrentOwner = _dereq_(35); 88016var ReactInstanceMap = _dereq_(71); 88017var ReactUpdates = _dereq_(94); 88018 88019var invariant = _dereq_(158); 88020var warning = _dereq_(168); 88021 88022function enqueueUpdate(internalInstance) { 88023 ReactUpdates.enqueueUpdate(internalInstance); 88024} 88025 88026function formatUnexpectedArgument(arg) { 88027 var type = typeof arg; 88028 if (type !== 'object') { 88029 return type; 88030 } 88031 var displayName = arg.constructor && arg.constructor.name || type; 88032 var keys = Object.keys(arg); 88033 if (keys.length > 0 && keys.length < 20) { 88034 return displayName + ' (keys: ' + keys.join(', ') + ')'; 88035 }
88036 return displayName; 88037} 88038 88039function getInternalInstanceReadyForUpdate(publicInstance, callerName) { 88040 var internalInstance = ReactInstanceMap.get(publicInstance); 88041 if (!internalInstance) { 88042 if ("development" !== 'production') { 88043 // Only warn when we have a callerName. Otherwise we should be silent. 88044 // We're probably calling from enqueueCallback. We don't want to warn 88045 // there because we already warned for the corresponding lifecycle method. 88046 "development" !== 'production' ? warning(!callerName, '%s(...): Can only update a mounted or mounting component. ' + 'This usually means you called %s() on an unmounted component. ' + 'This is a no-op. Please check the code for the %s component.', callerName, callerName, publicInstance.constructor.displayName) : void 0; 88047 } 88048 return null; 88049 } 88050 88051 if ("development" !== 'production') { 88052 "development" !== 'production' ? warning(ReactCurrentOwner.current == null, '%s(...): Cannot update during an existing state transition (such as ' + 'within `render` or another component\'s constructor). Render methods ' + 'should be a pure function of props and state; constructor ' + 'side-effects are an anti-pattern, but can be moved to ' + '`componentWillMount`.', callerName) : void 0; 88053 } 88054 88055 return internalInstance; 88056} 88057 88058/** 88059 * ReactUpdateQueue allows for state updates to be scheduled into a later 88060 * reconciliation step. 88061 */ 88062var ReactUpdateQueue = { 88063 88064 /** 88065 * Checks whether or not this composite component is mounted. 88066 * @param {ReactClass} publicInstance The instance we want to test. 88067 * @return {boolean} True if mounted, false otherwise. 88068 * @protected 88069 * @final 88070 */ 88071 isMounted: function (publicInstance) { 88072 if ("development" !== 'production') { 88073 var owner = ReactCurrentOwner.current; 88074 if (owner !== null) { 88075 "development" !== 'production' ? warning(owner._warnedAboutRefsInRender, '%s is accessing isMounted inside its render() function. ' + 'render() should be a pure function of props and state. It should ' + 'never access something that requires stale data from the previous ' + 'render, such as refs. Move this logic to componentDidMount and ' + 'componentDidUpdate instead.', owner.getName() || 'A c
88075omponent') : void 0; 88076 owner._warnedAboutRefsInRender = true; 88077 } 88078 } 88079 var internalInstance = ReactInstanceMap.get(publicInstance); 88080 if (internalInstance) { 88081 // During componentWillMount and render this will still be null but after 88082 // that will always render to something. At least for now. So we can use 88083 // this hack. 88084 return !!internalInstance._renderedComponent; 88085 } else { 88086 return false; 88087 } 88088 }, 88089 88090 /** 88091 * Enqueue a callback that will be executed after all the pending updates 88092 * have processed. 88093 * 88094 * @param {ReactClass} publicInstance The instance to use as `this` context. 88095 * @param {?function} callback Called after state is updated. 88096 * @param {string} callerName Name of the calling function in the public API. 88097 * @internal 88098 */ 88099 enqueueCallback: function (publicInstance, callback, callerName) { 88100 ReactUpdateQueue.validateCallback(callback, callerName); 88101 var internalInstance = getInternalInstanceReadyForUpdate(publicInstance); 88102 88103 // Previously we would throw an error if we didn't have an internal 88104 // instance. Since we want to make it a no-op instead, we mirror the same 88105 // behavior we have in other enqueue* methods. 88106 // We also need to ignore callbacks in componentWillMount. See 88107 // enqueueUpdates. 88108 if (!internalInstance) { 88109 return null; 88110 } 88111 88112 if (internalInstance._pendingCallbacks) { 88113 internalInstance._pendingCallbacks.push(callback); 88114 } else { 88115 internalInstance._pendingCallbacks = [callback]; 88116 } 88117 // TODO: The callback here is ignored when setState is called from 88118 // componentWillMount. Either fix it or disallow doing so completely in 88119 // favor of getInitialState. Alternatively, we can disallow 88120 // componentWillMount during server-side rendering. 88121 enqueueUpdate(internalInstance); 88122 }, 88123 88124 enqueueCallbackInternal: function (internalInstance, callback) { 88125 if (internalInstance._pendingCallbacks) { 88126 internalInstance._pendingCallbacks.push(callback); 88127 } else { 88128 internalInstance._pendingCallbacks = [callback]; 88129 } 88130 enqueueUpdate(internalInstance); 88131 }, 88132 88133 /** 88134 * Forces an update. This should only be invoked when it is known with 88135 * certainty that we are **not** in a DOM transaction. 88136 * 88137 * You may want to call this when you know that some deeper aspect of the 88138 * component's state has changed but `setState` was not called. 88139 * 88140 * This will not invoke `shouldComponentUpdate`, but it will invoke 88141 * `componentWillUpdate` and `componentDidUpdate`. 88142 * 88143 * @param {ReactClass} publicInstance The instance that should rerender. 88144 * @internal 88145 */ 88146 enqueueForceUpdate: function (publicInstance) { 88147 var internalInstance = getInternalInstanceReadyForUpdate(publicInstance, 'forceUpdate'); 88148 88149 if (!internalInstance) { 88150 return; 88151 } 88152 88153 internalInstance._pendingForceUpdate = true; 88154 88155 enqueueUpdate(internalInstance); 88156 }, 88157 88158 /** 88159 * Replaces all of the state. Always use this or `setState` to mutate state. 88160 * You should treat `this.state` as immutable. 88161 * 88162 * There is no guarantee that `this.state` will be immediately updated, so 88163 * accessing `this.state` after calling this method may return the old value. 88164 * 88165 * @param {ReactClass} publicInstance The instance that should rerender. 88166 * @param {object} completeState Next state. 88167 * @internal 88168 */ 88169 enqueueReplaceState: function (publicInstance, completeState) { 88170 var internalInstance = getInternalInstanceReadyForUpdate(publicInstance, 'replaceState'); 88171 88172 if (!internalInstance) { 88173 return; 88174 } 88175 88176 internalInstance._pendingStateQueue = [completeState]; 88177 internalInstance._pendingReplaceState = true; 88178 88179 enqueueUpdate(internalInstance); 88180 }, 88181 88182 /** 88183 * Sets a subset of the state. This only exists because _pendingState is 88184 * internal. This provides a merging strategy that is not available to deep 88185 * properties which is confusing. TODO: Expose pendingState or don't use it 88186 * during the merge. 88187 * 88188 * @param {ReactClass} publicInstance The instance that should rerender. 88189 * @param {object} partialState Next partial state to be merged with state. 88190 * @internal 88191 */ 88192 enqueueSetState: function (publicInstance, partialState) { 88193 var internalInstance = getInternalInstanceReadyForUpdate(publicInstance, 'setState'); 88194 88195 if (!internalInstance) { 88196 return; 88197 } 88198 88199 var queue = internalInstance._pendingStateQueue || (internalInstance._pendingStateQueue = []); 88200 queue.push(partialState); 88201 88202 enqueueUpdate(internalInstance); 88203 }, 88204 88205 enqueueElementInternal: function (internalInstance, newElement) { 88206 internalInstance._pendingElement = newElement; 88207 enqueueUpdate(internalInstance); 88208 }, 88209 88210 validateCallback: function (callback, callerName) { 88211 !(!callback || typeof callback === 'function') ? "development" !== 'production' ? invariant(false, '%s(...): Expected the last optional `callback` argument to be a ' + 'function. Instead received: %s.', callerName, formatUnexpectedArgument(callback)) : invariant(false) : void 0; 88212 } 88213 88214}; 88215 88216module.exports = ReactUpdateQueue; 88217},{"158":158,"168":168,"35":35,"71":71,"94":94}],94:[function(_dereq_,module,exports){ 88218/** 88219 * Copyright 2013-present, Facebook, Inc. 88220 * All rights reserved. 88221 * 88222 * This source code is licensed under the BSD-style license found in the 88223 * LICENSE file in the root directory of this source tree. An additional grant 88224 * of patent rights can be found in the PATENTS file in the same directory. 88225 * 88226 * @providesModule ReactUpdates 88227 */ 88228 88229 88230 88231var _assign = _dereq_(169); 88232 88233var CallbackQueue = _dereq_(5); 88234var PooledClass = _dereq_(25); 88235var ReactFeatureFlags = _dereq_(68); 88236var ReactPerf = _dereq_(82); 88237var ReactReconciler = _dereq_(87); 88238var Transaction = _dereq_(112); 88239 88240var invariant = _dereq_(158); 88241 88242var dirtyComponents = []; 88243var asapCallbackQueue = CallbackQueue.getPooled(); 88244var asapEnqueued = false;
88245 88246var batchingStrategy = null; 88247 88248function ensureInjected() { 88249 !(ReactUpdates.ReactReconcileTransaction && batchingStrategy) ? "development" !== 'production' ? invariant(false, 'ReactUpdates: must inject a reconcile transaction class and batching ' + 'strategy') : invariant(false) : void 0; 88250} 88251 88252var NESTED_UPDATES = { 88253 initialize: function () { 88254 this.dirtyComponentsLength = dirtyComponents.length; 88255 }, 88256 close: function () { 88257 if (this.dirtyComponentsLength !== dirtyComponents.length) { 88258 // Additional updates were enqueued by componentDidUpdate handlers or 88259 // similar; before our own UPDATE_QUEUEING wrapper closes, we want to run 88260 // these new updates so that if A's componentDidUpdate calls setState on 88261 // B, B will update before the callback A's updater provided when calling 88262 // setState. 88263 dirtyComponents.splice(0, this.dirtyComponentsLength); 88264 flushBatchedUpdates(); 88265 } else { 88266 dirtyComponents.length = 0; 88267 } 88268 } 88269}; 88270 88271var UPDATE_QUEUEING = { 88272 initialize: function () { 88273 this.callbackQueue.reset(); 88274 }, 88275 close: function () { 88276 this.callbackQueue.notifyAll(); 88277 } 88278}; 88279 88280var TRANSACTION_WRAPPERS = [NESTED_UPDATES, UPDATE_QUEUEING]; 88281 88282function ReactUpdatesFlushTransaction() { 88283 this.reinitializeTransaction(); 88284 this.dirtyComponentsLength = null; 88285 this.callbackQueue = CallbackQueue.getPooled(); 88286 this.reconcileTransaction = ReactUpdates.ReactReconcileTransaction.getPooled( 88287 /* useCreateElement */true); 88288} 88289 88290_assign(ReactUpdatesFlushTransaction.prototype, Transaction.Mixin, { 88291 getTransactionWrappers: function () { 88292 return TRANSACTION_WRAPPERS; 88293 }, 88294 88295 destructor: function () { 88296 this.dirtyComponentsLength = null; 88297 CallbackQueue.release(this.callbackQueue); 88298 this.callbackQueue = null; 88299 ReactUpdates.ReactReconcileTransaction.release(this.reconcileTransaction); 88300 this.reconcileTransaction = null; 88301 }, 88302 88303 perform: function (method, scope, a) { 88304 // Essentially calls `this.reconcileTransaction.perform(method, scope, a)` 88305 // with this transaction's wrappers around it. 88306 return Transaction.Mixin.perform.call(this, this.reconcileTransaction.perform, this.reconcileTransaction, method, scope, a); 88307 } 88308}); 88309 88310PooledClass.addPoolingTo(ReactUpdatesFlushTransaction); 88311 88312function batchedUpdates(callback, a, b, c, d, e) { 88313 ensureInjected(); 88314 batchingStrategy.batchedUpdates(callback, a, b, c, d, e); 88315} 88316 88317/** 88318 * Array comparator for ReactComponents by mount ordering. 88319 * 88320 * @param {ReactComponent} c1 first component you're comparing 88321 * @param {ReactComponent} c2 second component you're comparing 88322 * @return {number} Return value usable by Array.prototype.sort(). 88323 */ 88324function mountOrderComparator(c1, c2) { 88325 return c1._mountOrder - c2._mountOrder; 88326} 88327 88328function runBatchedUpdates(transaction) { 88329 var len = transaction.dirtyComponentsLength; 88330 !(len === dirtyComponents.length) ? "development" !== 'production' ? invariant(false, 'Expected flush transaction\'s stored dirty-components length (%s) to ' + 'match dirty-components array length (%s).', len, dirtyComponents.length) : invariant(false) : void 0; 88331 88332 // Since reconciling a component higher in the owner hierarchy usually (not 88333 // always -- see shouldComponentUpdate()) will reconcile children, reconcile 88334 // them before their children by sorting the array. 88335 dirtyComponents.sort(mountOrderComparator); 88336 88337 for (var i = 0; i < len; i++) { 88338 // If a component is unmounted before pending changes apply, it will still 88339 // be here, but we assume that it has cleared its _pendingCallbacks and 88340 // that performUpdateIfNecessary is a noop. 88341 var component = dirtyComponents[i]; 88342 88343 // If performUpdateIfNecessary happens to enqueue any new updates, we 88344 // shouldn't execute the callbacks until the next render happens, so 88345 // stash the callbacks first 88346 var callbacks = component._pendingCallbacks; 88347 component._pendingCallbacks = null; 88348 88349 var markerName; 88350 if (ReactFeatureFlags.logTopLevelRenders) { 88351 var namedComponent = component; 88352 // Duck type TopLevelWrapper. This is probably always true. 88353 if (component._currentElement.props === component._renderedComponent._currentElement) { 88354 namedComponent = component._renderedComponent; 88355 } 88356 markerName = 'React update: ' + namedComponent.getName(); 88357 console.time(markerName); 88358 } 88359 88360 ReactReconciler.performUpdateIfNecessary(component, transaction.reconcileTransaction); 88361 88362 if (markerName) { 88363 console.timeEnd(markerName); 88364 } 88365 88366 if (callbacks) { 88367 for (var j = 0; j < callbacks.length; j++) { 88368 transaction.callbackQueue.enqueue(callbacks[j], component.getPublicInstance()); 88369 } 88370 } 88371 } 88372} 88373
88374var flushBatchedUpdates = function () { 88375 // ReactUpdatesFlushTransaction's wrappers will clear the dirtyComponents 88376 // array and perform any updates enqueued by mount-ready handlers (i.e., 88377 // componentDidUpdate) but we need to check here too in order to catch 88378 // updates enqueued by setState callbacks and asap calls. 88379 while (dirtyComponents.length || asapEnqueued) { 88380 if (dirtyComponents.length) { 88381 var transaction = ReactUpdatesFlushTransaction.getPooled(); 88382 transaction.perform(runBatchedUpdates, null, transaction); 88383 ReactUpdatesFlushTransaction.release(transaction); 88384 } 88385 88386 if (asapEnqueued) { 88387 asapEnqueued = false; 88388 var queue = asapCallbackQueue; 88389 asapCallbackQueue = CallbackQueue.getPooled(); 88390 queue.notifyAll(); 88391 CallbackQueue.release(queue); 88392 } 88393 } 88394}; 88395flushBatchedUpdates = ReactPerf.measure('ReactUpdates', 'flushBatchedUpdates', flushBatchedUpdates); 88396 88397/** 88398 * Mark a component as needing a rerender, adding an optional callback to a 88399 * list of functions which will be executed once the rerender occurs. 88400 */ 88401function enqueueUpdate(component) { 88402 ensureInjected(); 88403 88404 // Various parts of our code (such as ReactCompositeComponent's 88405 // _renderValidatedComponent) assume that calls to render aren't nested; 88406 // verify that that's the case. (This is called by each top-level update 88407 // function, like setProps, setState, forceUpdate, etc.; creation and 88408 // destruction of top-level components is guarded in ReactMount.) 88409 88410 if (!batchingStrategy.isBatchingUpdates) { 88411 batchingStrategy.batchedUpdates(enqueueUpdate, component); 88412 return; 88413 } 88414 88415 dirtyComponents.push(component); 88416} 88417 88418/** 88419 * Enqueue a callback to be run at the end of the current batching cycle. Throws 88420 * if no updates are currently being performed. 88421 */ 88422function asap(callback, context) { 88423 !batchingStrategy.isBatchingUpdates ? "development" !== 'production' ? invariant(false, 'ReactUpdates.asap: Can\'t enqueue an asap callback in a context where' + 'updates are not being batched.') : invariant(false) : void 0; 88424 asapCallbackQueue.enqueue(callback, context); 88425 asapEnqueued = true; 88426} 88427 88428var ReactUpdatesInjection = { 88429 injectReconcileTransaction: function (ReconcileTransaction) { 88430 !ReconcileTransaction ? "development" !== 'production' ? invariant(false, 'ReactUpdates: must provide a reconcile transaction class') : invariant(false) : void 0; 88431 ReactUpdates.ReactReconcileTransaction = ReconcileTransaction; 88432 }, 88433 88434 injectBatchingStrategy: function (_batchingStrategy) { 88435 !_batchingStrategy ? "development" !== 'production' ? invariant(false, 'ReactUpdates: must provide a batching strategy') : invariant(false) : void 0; 88436 !(typeof _batchingStrategy.batchedUpdates === 'function') ? "development" !== 'production' ? invariant(false, 'ReactUpdates: must provide a batchedUpdates() function') : invariant(false) : void 0; 88437 !(typeof _batchingStrategy.isBatchingUpdates === 'boolean') ? "development" !== 'production' ? invariant(false, 'ReactUpdates: must provide an isBatchingUpdates boolean attribute') : invariant(false) : void 0; 88438 batchingStrategy = _batchingStrategy; 88439 } 88440}; 88441 88442var ReactUpdates = { 88443 /** 88444 * React references `ReactReconcileTransaction` using this property in order 88445 * to allow dependency injection. 88446 * 88447 * @internal 88448 */ 88449 ReactReconcileTransaction: null, 88450 88451 batchedUpdates: batchedUpdates, 88452 enqueueUpdate: enqueueUpdate, 88453 flushBatchedUpdates: flushBatchedUpdates, 88454 injection: ReactUpdatesInjection, 88455 asap: asap 88456}; 88457 88458module.exports = ReactUpdates; 88459},{"112":112,"158":158,"169":169,"25":25,"5":5,"68":68,"82":82,"87":87}],95:[function(_dereq_,module,exports){ 88460/** 88461 * Copyright 2013-present, Facebook, Inc. 88462 * All rights reserved. 88463 * 88464 * This source code is licensed under the BSD-style license found in the 88465 * LICENSE file in the root directory of this source tree. An additional grant 88466 * of patent rights can be found in the PATENTS file in the same directory. 88467 * 88468 * @providesModule ReactVersion 88469 */ 88470 88471 88472 88473module.exports = '15.0.2'; 88474},{}],96:[function(_dereq_,module,exports){ 88475/** 88476 * Copyright 2013-present, Facebook, Inc. 88477 * All rights reserved. 88478 * 88479 * This source code is licensed under the BSD-style license found in the 88480 * LICENSE file in the root directory of this source tree. An additional grant 88481 * of patent rights can be found in the PATENTS file in the same directory. 88482 * 88483 * @providesModule SVGDOMPropertyConfig 88484 */ 88485 88486 88487 88488var NS = { 88489 xlink: 'http://www.w3.org/1999/xlink', 88490 xml: 'http://www.w3.org/XML/1998/namespace' 88491}; 88492 88493// We use attributes for everything SVG so let's avoid some duplication and run 88494// code instead. 88495// The following are all specified in the HTML config already so we exclude here. 88496// - class (as className) 88497// - color 88498// - height 88499// - id
88500// - lang 88501// - max 88502// - media 88503// - method 88504// - min 88505// - name 88506// - style 88507// - target 88508// - type 88509// - width 88510var ATTRS = { 88511 accentHeight: 'accent-height', 88512 accumulate: 0, 88513 additive: 0, 88514 alignmentBaseline: 'alignment-baseline', 88515 allowReorder: 'allowReorder', 88516 alphabetic: 0, 88517 amplitude: 0, 88518 arabicForm: 'arabic-form', 88519 ascent: 0, 88520 attributeName: 'attributeName', 88521 attributeType: 'attributeType', 88522 autoReverse: 'autoReverse', 88523 azimuth: 0, 88524 baseFrequency: 'baseFrequency', 88525 baseProfile: 'baseProfile', 88526 baselineShift: 'baseline-shift', 88527 bbox: 0, 88528 begin: 0, 88529 bias: 0, 88530 by: 0, 88531 calcMode: 'calcMode', 88532 capHeight: 'cap-height', 88533 clip: 0, 88534 clipPath: 'clip-path', 88535 clipRule: 'clip-rule', 88536 clipPathUnits: 'clipPathUnits', 88537 colorInterpolation: 'color-interpolation', 88538 colorInterpolationFilters: 'color-interpolation-filters', 88539 colorProfile: 'color-profile', 88540 colorRendering: 'color-rendering', 88541 contentScriptType: 'contentScriptType', 88542 contentStyleType: 'contentStyleType', 88543 cursor: 0, 88544 cx: 0, 88545 cy: 0, 88546 d: 0, 88547 decelerate: 0, 88548 descent: 0, 88549 diffuseConstant: 'diffuseConstant', 88550 direction: 0, 88551 display: 0, 88552 divisor: 0, 88553 dominantBaseline: 'dominant-baseline', 88554 dur: 0, 88555 dx: 0, 88556 dy: 0, 88557 edgeMode: 'edgeMode', 88558 elevation: 0, 88559 enableBackground: 'enable-background', 88560 end: 0, 88561 exponent: 0, 88562 externalResourcesRequired: 'externalResourcesRequired', 88563 fill: 0, 88564 fillOpacity: 'fill-opacity', 88565 fillRule: 'fill-rule', 88566 filter: 0, 88567 filterRes: 'filterRes', 88568 filterUnits: 'filterUnits', 88569 floodColor: 'flood-color', 88570 floodOpacity: 'flood-opacity', 88571 focusable: 0, 88572 fontFamily: 'font-family', 88573 fontSize: 'font-size', 88574 fontSizeAdjust: 'font-size-adjust', 88575 fontStretch: 'font-stretch', 88576 fontStyle: 'font-style', 88577 fontVariant: 'font-variant', 88578 fontWeight: 'font-weight', 88579 format: 0, 88580 from: 0, 88581 fx: 0, 88582 fy: 0, 88583 g1: 0, 88584 g2: 0, 88585 glyphName: 'glyph-name', 88586 glyphOrientationHorizontal: 'glyph-orientation-horizontal', 88587 glyphOrientationVertical: 'glyph-orientation-vertical', 88588 glyphRef: 'glyphRef', 88589 gradientTransform: 'gradientTransform', 88590 gradientUnits: 'gradientUnits', 88591 hanging: 0, 88592 horizAdvX: 'horiz-adv-x', 88593 horizOriginX: 'horiz-origin-x', 88594 ideographic: 0, 88595 imageRendering: 'image-rendering', 88596 'in': 0, 88597 in2: 0, 88598 intercept: 0, 88599 k: 0, 88600 k1: 0, 88601 k2: 0, 88602 k3: 0, 88603 k4: 0, 88604 kernelMatrix: 'kernelMatrix', 88605 kernelUnitLength: 'kernelUnitLength', 88606 kerning: 0, 88607 keyPoints: 'keyPoints', 88608 keySplines: 'keySplines', 88609 keyTimes: 'keyTimes', 88610 lengthAdjust: 'lengthAdjust', 88611 letterSpacing: 'letter-spacing', 88612 lightingColor: 'lighting-color', 88613 limitingConeAngle: 'limitingConeAngle', 88614 local: 0, 88615 markerEnd: 'marker-end', 88616 markerMid: 'marker-mid', 88617 markerStart: 'marker-start', 88618 markerHeight: 'markerHeight', 88619 markerUnits: 'markerUnits', 88620 markerWidth: 'markerWidth', 88621 mask: 0, 88622 maskContentUnits: 'maskContentUnits', 88623 maskUnits: 'maskUnits', 88624 mathematical: 0, 88625 mode: 0, 88626 numOctaves: 'numOctaves', 88627 offset: 0, 88628 opacity: 0, 88629 operator: 0, 88630 order: 0, 88631 orient: 0, 88632 orientation: 0, 88633 origin: 0, 88634 overflow: 0, 88635 overlinePosition: 'overline-position', 88636 overlineThickness: 'overline-thickness', 88637 paintOrder: 'paint-order', 88638 panose1: 'panose-1', 88639 pathLength: 'pathLength', 88640 patternContentUnits: 'patternContentUnits', 88641 patternTransform: 'patternTransform', 88642 patternUnits: 'patternUnits', 88643 pointerEvents: 'pointer-events', 88644 points: 0, 88645 pointsAtX: 'pointsAtX', 88646 pointsAtY: 'pointsAtY', 88647 pointsAtZ: 'pointsAtZ', 88648 preserveAlpha: 'preserveAlpha', 88649 preserveAspectRatio: 'preserveAspectRatio', 88650 primitiveUnits: 'primitiveUnits', 88651 r: 0, 88652 radius: 0, 88653 refX: 'refX', 88654 refY: 'refY', 88655 renderingIntent: 'rendering-intent', 88656 repeatCount: 'repeatCount', 88657 repeatDur: 'repeatDur', 88658 requiredExtensions: 'requiredExtensions', 88659 requiredFeatures: 'requiredFeatures', 88660 restart: 0, 88661 result: 0, 88662 rotate: 0, 88663 rx: 0, 88664 ry: 0, 88665 scale: 0, 88666 seed: 0, 88667 shapeRendering: 'shape-rendering', 88668 slope: 0, 88669 spacing: 0, 88670 specularConstant: 'specularConstant', 88671 specularExponent: 'specularExponent', 88672 speed: 0, 88673 spreadMethod: 'spreadMethod', 88674 startOffset: 'startOffset', 88675 stdDeviation: 'stdDeviation', 88676 stemh: 0, 88677 stemv: 0, 88678 stitchTiles: 'stitchTiles', 88679 stopColor: 'stop-color', 88680 stopOpacity: 'stop-opacity', 88681 strikethroughPosition: 'strikethrough-position', 88682 strikethroughThickness: 'strikethrough-thickness', 88683 string: 0, 88684 stroke: 0, 88685 strokeDasharray: 'stroke-dasharray', 88686 strokeDashoffset: 'stroke-dashoffset', 88687 strokeLinecap: 'stroke-linecap', 88688 strokeLinejoin: 'stroke-linejoin', 88689 strokeMiterlimit: 'stroke-miterlimit', 88690 strokeOpacity: 'stroke-opacity', 88691 strokeWidth: 'stroke-width', 88692 surfaceScale: 'surfaceScale', 88693 systemLanguage: 'systemLanguage', 88694 tableValues: 'tableValues', 88695 targetX: 'targetX', 88696 targetY: 'targetY', 88697 textAnchor: 'text-anchor', 88698 textDecoration: 'text-decoration', 88699 textRendering: 'text-rendering', 88700 textLength: 'textLength', 88701 to: 0, 88702 transform: 0, 88703 u1: 0, 88704 u2: 0, 88705 underlinePosition: 'underline-position', 88706 underlineThickness: 'underline-thickness', 88707 unicode: 0,
88708 unicodeBidi: 'unicode-bidi', 88709 unicodeRange: 'unicode-range', 88710 unitsPerEm: 'units-per-em', 88711 vAlphabetic: 'v-alphabetic', 88712 vHanging: 'v-hanging', 88713 vIdeographic: 'v-ideographic', 88714 vMathematical: 'v-mathematical', 88715 values: 0, 88716 vectorEffect: 'vector-effect', 88717 version: 0, 88718 vertAdvY: 'vert-adv-y', 88719 vertOriginX: 'vert-origin-x', 88720 vertOriginY: 'vert-origin-y', 88721 viewBox: 'viewBox', 88722 viewTarget: 'viewTarget', 88723 visibility: 0, 88724 widths: 0, 88725 wordSpacing: 'word-spacing', 88726 writingMode: 'writing-mode', 88727 x: 0, 88728 xHeight: 'x-height', 88729 x1: 0, 88730 x2: 0, 88731 xChannelSelector: 'xChannelSelector', 88732 xlinkActuate: 'xlink:actuate', 88733 xlinkArcrole: 'xlink:arcrole', 88734 xlinkHref: 'xlink:href', 88735 xlinkRole: 'xlink:role', 88736 xlinkShow: 'xlink:show', 88737 xlinkTitle: 'xlink:title', 88738 xlinkType: 'xlink:type', 88739 xmlBase: 'xml:base', 88740 xmlLang: 'xml:lang', 88741 xmlSpace: 'xml:space', 88742 y: 0, 88743 y1: 0, 88744 y2: 0, 88745 yChannelSelector: 'yChannelSelector', 88746 z: 0, 88747 zoomAndPan: 'zoomAndPan' 88748}; 88749 88750var SVGDOMPropertyConfig = { 88751 Properties: {}, 88752 DOMAttributeNamespaces: { 88753 xlinkActuate: NS.xlink, 88754 xlinkArcrole: NS.xlink, 88755 xlinkHref: NS.xlink, 88756 xlinkRole: NS.xlink, 88757 xlinkShow: NS.xlink, 88758 xlinkTitle: NS.xlink, 88759 xlinkType: NS.xlink, 88760 xmlBase: NS.xml, 88761 xmlLang: NS.xml, 88762 xmlSpace: NS.xml 88763 }, 88764 DOMAttributeNames: {} 88765}; 88766 88767Object.keys(ATTRS).forEach(function (key) { 88768 SVGDOMPropertyConfig.Properties[key] = 0; 88769 if (ATTRS[key]) { 88770 SVGDOMPropertyConfig.DOMAttributeNames[key] = ATTRS[key]; 88771 } 88772}); 88773 88774module.exports = SVGDOMPropertyConfig; 88775},{}],97:[function(_dereq_,module,exports){ 88776/** 88777 * Copyright 2013-present, Facebook, Inc. 88778 * All rights reserved. 88779 * 88780 * This source code is licensed under the BSD-style license found in the 88781 * LICENSE file in the root directory of this source tree. An additional grant 88782 * of patent rights can be found in the PATENTS file in the same directory. 88783 * 88784 * @providesModule SelectEventPlugin 88785 */ 88786 88787 88788 88789var EventConstants = _dereq_(16); 88790var EventPropagators = _dereq_(20); 88791var ExecutionEnvironment = _dereq_(144); 88792var ReactDOMComponentTree = _dereq_(40); 88793var ReactInputSelection = _dereq_(70); 88794var SyntheticEvent = _dereq_(103); 88795 88796var getActiveElement = _dereq_(153); 88797var isTextInputElement = _dereq_(134); 88798var keyOf = _dereq_(162); 88799var shallowEqual = _dereq_(167); 88800 88801var topLevelTypes = EventConstants.topLevelTypes; 88802 88803var skipSelectionChangeEvent = ExecutionEnvironment.canUseDOM && 'documentMode' in document && document.documentMode <= 11; 88804 88805var eventTypes = { 88806 select: { 88807 phasedRegistrationNames: { 88808 bubbled: keyOf({ onSelect: null }), 88809 captured: keyOf({ onSelectCapture: null }) 88810 }, 88811 dependencies: [topLevelTypes.topBlur, topLevelTypes.topContextMenu, topLevelTypes.topFocus, topLevelTypes.topKeyDown, topLevelTypes.topMouseDown, topLevelTypes.topMouseUp, topLevelTypes.topSelectionChange] 88812 } 88813}; 88814 88815var activeElement = null; 88816var activeElementInst = null; 88817var lastSelection = null; 88818var mouseDown = false; 88819 88820// Track whether a listener exists for this plugin. If none exist, we do 88821// not extract events. See #3639. 88822var hasListener = false;
88823var ON_SELECT_KEY = keyOf({ onSelect: null }); 88824 88825/** 88826 * Get an object which is a unique representation of the current selection. 88827 * 88828 * The return value will not be consistent across nodes or browsers, but 88829 * two identical selections on the same node will return identical objects. 88830 * 88831 * @param {DOMElement} node 88832 * @return {object} 88833 */ 88834function getSelection(node) { 88835 if ('selectionStart' in node && ReactInputSelection.hasSelectionCapabilities(node)) { 88836 return { 88837 start: node.selectionStart, 88838 end: node.selectionEnd 88839 }; 88840 } else if (window.getSelection) { 88841 var selection = window.getSelection(); 88842 return { 88843 anchorNode: selection.anchorNode, 88844 anchorOffset: selection.anchorOffset, 88845 focusNode: selection.focusNode, 88846 focusOffset: selection.focusOffset 88847 }; 88848 } else if (document.selection) { 88849 var range = document.selection.createRange(); 88850 return { 88851 parentElement: range.parentElement(), 88852 text: range.text, 88853 top: range.boundingTop, 88854 left: range.boundingLeft 88855 }; 88856 } 88857} 88858 88859/** 88860 * Poll selection to see whether it's changed. 88861 * 88862 * @param {object} nativeEvent 88863 * @return {?SyntheticEvent} 88864 */ 88865function constructSelectEvent(nativeEvent, nativeEventTarget) { 88866 // Ensure we have the right element, and that the user is not dragging a 88867 // selection (this matches native `select` event behavior). In HTML5, select 88868 // fires only on input and textarea thus if there's no focused element we 88869 // won't dispatch. 88870 if (mouseDown || activeElement == null || activeElement !== getActiveElement()) { 88871 return null; 88872 } 88873 88874 // Only fire when selection has actually changed. 88875 var currentSelection = getSelection(activeElement); 88876 if (!lastSelection || !shallowEqual(lastSelection, currentSelection)) { 88877 lastSelection = currentSelection; 88878 88879 var syntheticEvent = SyntheticEvent.getPooled(eventTypes.select, activeElementInst, nativeEvent, nativeEventTarget); 88880 88881 syntheticEvent.type = 'select'; 88882 syntheticEvent.target = activeElement; 88883 88884 EventPropagators.accumulateTwoPhaseDispatches(syntheticEvent); 88885 88886 return syntheticEvent; 88887 } 88888 88889 return null; 88890} 88891 88892/** 88893 * This plugin creates an `onSelect` event that normalizes select events 88894 * across form elements. 88895 * 88896 * Supported elements are: 88897 * - input (see `isTextInputElement`) 88898 * - textarea 88899 * - contentEditable 88900 * 88901 * This differs from native browser implementations in the following ways: 88902 * - Fires on contentEditable fields as well as inputs. 88903 * - Fires for collapsed selection. 88904 * - Fires after user input. 88905 */ 88906var SelectEventPlugin = { 88907 88908 eventTypes: eventTypes, 88909 88910 extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) { 88911 if (!hasListener) { 88912 return null; 88913 } 88914 88915 var targetNode = targetInst ? ReactDOMComponentTree.getNodeFromInstance(targetInst) : window; 88916 88917 switch (topLevelType) { 88918 // Track the input node that has focus. 88919 case topLevelTypes.topFocus: 88920 if (isTextInputElement(targetNode) || targetNode.contentEditable === 'true') { 88921 activeElement = targetNode; 88922 activeElementInst = targetInst; 88923 lastSelection = null; 88924 } 88925 break; 88926 case topLevelTypes.topBlur: 88927 activeElement = null; 88928 activeElementInst = null; 88929 lastSelection = null; 88930 break; 88931 88932 // Don't fire the event while the user is dragging. This matches the 88933 // semantics of the native select event. 88934 case topLevelTypes.topMouseDown: 88935 mouseDown = true; 88936 break; 88937 case topLevelTypes.topContextMenu: 88938 case topLevelTypes.topMouseUp: 88939 mouseDown = false; 88940 return constructSelectEvent(nativeEvent, nativeEventTarget); 88941 88942 // Chrome and IE fire non-standard event when selection is changed (and 88943 // sometimes when it hasn't). IE's event fires out of order with respect 88944 // to key and input events on deletion, so we discard it. 88945 // 88946 // Firefox doesn't support selectionchange, so check selection status 88947 // after each key entry. The selection changes after keydown and before 88948 // keyup, but we check on keydown as well in the case of holding down a 88949 // key, when multiple keydown events are fired but only one keyup is. 88950 // This is also our approach for IE handling, for the reason above. 88951 case topLevelTypes.topSelectionChange: 88952 if (skipSelectionChangeEvent) { 88953 break; 88954 } 88955 // falls through 88956 case topLevelTypes.topKeyDown: 88957 case topLevelTypes.topKeyUp: 88958 return constructSelectEvent(nativeEvent, nativeEventTarget); 88959 } 88960 88961 return null; 88962 }, 88963 88964 didPutListener: function (inst, registrationName, listener) { 88965 if (registrationName === ON_SELECT_KEY) { 88966 hasListener = true; 88967 } 88968 } 88969}; 88970 88971module.exports = SelectEventPlugin; 88972},{"103":103,"134":134,"144":144,"153":153,"16":16,"162":162,"167":167,"20":20,"40":40,"70":70}],98:[function(_dereq_,module,exports){ 88973/** 88974 * Copyright 2013-present, Facebook, Inc. 88975 * All rights reserved. 88976 * 88977 * This source code is licensed under the BSD-style license found in the 88978 * LICENSE file in the root directory of this source tree. An additional grant 88979 * of patent rights can be found in the PATENTS file in the same directory. 88980 * 88981 * @providesModule SimpleEventPlugin 88982 */ 88983 88984 88985 88986var EventConstants = _dereq_(16); 88987var EventListener = _dereq_(143); 88988var EventPropagators = _dereq_(20); 88989var ReactDOMComponentTree = _dereq_(40); 88990var SyntheticAnimationEvent = _dereq_(99); 88991var SyntheticClipboardEvent = _dereq_(100); 88992var SyntheticEvent = _dereq_(103); 88993var SyntheticFocusEvent = _dereq_(104); 88994var SyntheticKeyboardEvent = _dereq_(106); 88995var SyntheticMouseEvent = _dereq_(107); 88996var SyntheticDragEvent = _dereq_(102); 88997var SyntheticTouchEvent = _dereq_(108); 88998var SyntheticTransitionEvent = _dereq_(109); 88999var SyntheticUIEvent = _dereq_(110); 89000var SyntheticWheelEvent = _dereq_(111); 89001 89002var emptyFunction = _dereq_(150);
89003var getEventCharCode = _dereq_(123); 89004var invariant = _dereq_(158); 89005var keyOf = _dereq_(162); 89006 89007var topLevelTypes = EventConstants.topLevelTypes; 89008 89009var eventTypes = { 89010 abort: { 89011 phasedRegistrationNames: { 89012 bubbled: keyOf({ onAbort: true }), 89013 captured: keyOf({ onAbortCapture: true }) 89014 } 89015 }, 89016 animationEnd: { 89017 phasedRegistrationNames: { 89018 bubbled: keyOf({ onAnimationEnd: true }), 89019 captured: keyOf({ onAnimationEndCapture: true }) 89020 } 89021 }, 89022 animationIteration: { 89023 phasedRegistrationNames: { 89024 bubbled: keyOf({ onAnimationIteration: true }), 89025 captured: keyOf({ onAnimationIterationCapture: true }) 89026 } 89027 }, 89028 animationStart: { 89029 phasedRegistrationNames: { 89030 bubbled: keyOf({ onAnimationStart: true }), 89031 captured: keyOf({ onAnimationStartCapture: true }) 89032 } 89033 }, 89034 blur: { 89035 phasedRegistrationNames: { 89036 bubbled: keyOf({ onBlur: true }), 89037 captured: keyOf({ onBlurCapture: true }) 89038 } 89039 }, 89040 canPlay: { 89041 phasedRegistrationNames: { 89042 bubbled: keyOf({ onCanPlay: true }), 89043 captured: keyOf({ onCanPlayCapture: true }) 89044 } 89045 }, 89046 canPlayThrough: { 89047 phasedRegistrationNames: { 89048 bubbled: keyOf({ onCanPlayThrough: true }), 89049 captured: keyOf({ onCanPlayThroughCapture: true }) 89050 } 89051 }, 89052 click: { 89053 phasedRegistrationNames: { 89054 bubbled: keyOf({ onClick: true }), 89055 captured: keyOf({ onClickCapture: true }) 89056 } 89057 }, 89058 contextMenu: { 89059 phasedRegistrationNames: { 89060 bubbled: keyOf({ onContextMenu: true }), 89061 captured: keyOf({ onContextMenuCapture: true }) 89062 } 89063 }, 89064 copy: { 89065 phasedRegistrationNames: { 89066 bubbled: keyOf({ onCopy: true }), 89067 captured: keyOf({ onCopyCapture: true }) 89068 } 89069 }, 89070 cut: { 89071 phasedRegistrationNames: { 89072 bubbled: keyOf({ onCut: true }), 89073 captured: keyOf({ onCutCapture: true }) 89074 } 89075 }, 89076 doubleClick: { 89077 phasedRegistrationNames: { 89078 bubbled: keyOf({ onDoubleClick: true }), 89079 captured: keyOf({ onDoubleClickCapture: true }) 89080 } 89081 }, 89082 drag: { 89083 phasedRegistrationNames: { 89084 bubbled: keyOf({ onDrag: true }), 89085 captured: keyOf({ onDragCapture: true }) 89086 } 89087 }, 89088 dragEnd: { 89089 phasedRegistrationNames: { 89090 bubbled: keyOf({ onDragEnd: true }), 89091 captured: keyOf({ onDragEndCapture: true }) 89092 } 89093 }, 89094 dragEnter: { 89095 phasedRegistrationNames: { 89096 bubbled: keyOf({ onDragEnter: true }), 89097 captured: keyOf({ onDragEnterCapture: true }) 89098 } 89099 }, 89100 dragExit: { 89101 phasedRegistrationNames: { 89102 bubbled: keyOf({ onDragExit: true }), 89103 captured: keyOf({ onDragExitCapture: true }) 89104 } 89105 }, 89106 dragLeave: { 89107 phasedRegistrationNames: { 89108 bubbled: keyOf({ onDragLeave: true }), 89109 captured: keyOf({ onDragLeaveCapture: true }) 89110 } 89111 }, 89112 dragOver: { 89113 phasedRegistrationNames: { 89114 bubbled: keyOf({ onDragOver: true }), 89115 captured: keyOf({ onDragOverCapture: true }) 89116 } 89117 }, 89118 dragStart: { 89119 phasedRegistrationNames: { 89120 bubbled: keyOf({ onDragStart: true }), 89121 captured: keyOf({ onDragStartCapture: true }) 89122 } 89123 }, 89124 drop: { 89125 phasedRegistrationNames: { 89126 bubbled: keyOf({ onDrop: true }), 89127 captured: keyOf({ onDropCapture: true }) 89128 } 89129 }, 89130 durationChange: { 89131 phasedRegistrationNames: { 89132 bubbled: keyOf({ onDurationChange: true }), 89133 captured: keyOf({ onDurationChangeCapture: true }) 89134 } 89135 }, 89136 emptied: { 89137 phasedRegistrationNames: { 89138 bubbled: keyOf({ onEmptied: true }), 89139 captured: keyOf({ onEmptiedCapture: true }) 89140 } 89141 }, 89142 encrypted: { 89143 phasedRegistrationNames: { 89144 bubbled: keyOf({ onEncrypted: true }), 89145 captured: keyOf({ onEncryptedCapture: true }) 89146 } 89147 }, 89148 ended: { 89149 phasedRegistrationNames: { 89150 bubbled: keyOf({ onEnded: true }), 89151 captured: keyOf({ onEndedCapture: true }) 89152 } 89153 }, 89154 error: { 89155 phasedRegistrationNames: { 89156 bubbled: keyOf({ onError: true }), 89157 captured: keyOf({ onErrorCapture: true }) 89158 } 89159 }, 89160 focus: { 89161 phasedRegistrationNames: { 89162 bubbled: keyOf({ onFocus: true }), 89163 captured: keyOf({ onFocusCapture: true }) 89164 } 89165 }, 89166 input: {
89167 phasedRegistrationNames: { 89168 bubbled: keyOf({ onInput: true }), 89169 captured: keyOf({ onInputCapture: true }) 89170 } 89171 }, 89172 invalid: { 89173 phasedRegistrationNames: { 89174 bubbled: keyOf({ onInvalid: true }), 89175 captured: keyOf({ onInvalidCapture: true }) 89176 } 89177 }, 89178 keyDown: { 89179 phasedRegistrationNames: { 89180 bubbled: keyOf({ onKeyDown: true }), 89181 captured: keyOf({ onKeyDownCapture: true }) 89182 } 89183 }, 89184 keyPress: { 89185 phasedRegistrationNames: { 89186 bubbled: keyOf({ onKeyPress: true }), 89187 captured: keyOf({ onKeyPressCapture: true }) 89188 } 89189 }, 89190 keyUp: { 89191 phasedRegistrationNames: { 89192 bubbled: keyOf({ onKeyUp: true }), 89193 captured: keyOf({ onKeyUpCapture: true }) 89194 } 89195 }, 89196 load: { 89197 phasedRegistrationNames: { 89198 bubbled: keyOf({ onLoad: true }), 89199 captured: keyOf({ onLoadCapture: true }) 89200 } 89201 }, 89202 loadedData: { 89203 phasedRegistrationNames: { 89204 bubbled: keyOf({ onLoadedData: true }), 89205 captured: keyOf({ onLoadedDataCapture: true }) 89206 } 89207 }, 89208 loadedMetadata: { 89209 phasedRegistrationNames: { 89210 bubbled: keyOf({ onLoadedMetadata: true }), 89211 captured: keyOf({ onLoadedMetadataCapture: true }) 89212 } 89213 }, 89214 loadStart: { 89215 phasedRegistrationNames: { 89216 bubbled: keyOf({ onLoadStart: true }), 89217 captured: keyOf({ onLoadStartCapture: true }) 89218 } 89219 }, 89220 // Note: We do not allow listening to mouseOver events. Instead, use the 89221 // onMouseEnter/onMouseLeave created by `EnterLeaveEventPlugin`. 89222 mouseDown: { 89223 phasedRegistrationNames: { 89224 bubbled: keyOf({ onMouseDown: true }), 89225 captured: keyOf({ onMouseDownCapture: true }) 89226 } 89227 }, 89228 mouseMove: { 89229 phasedRegistrationNames: { 89230 bubbled: keyOf({ onMouseMove: true }), 89231 captured: keyOf({ onMouseMoveCapture: true }) 89232 } 89233 }, 89234 mouseOut: { 89235 phasedRegistrationNames: { 89236 bubbled: keyOf({ onMouseOut: true }), 89237 captured: keyOf({ onMouseOutCapture: true }) 89238 } 89239 }, 89240 mouseOver: { 89241 phasedRegistrationNames: { 89242 bubbled: keyOf({ onMouseOver: true }), 89243 captured: keyOf({ onMouseOverCapture: true }) 89244 } 89245 }, 89246 mouseUp: { 89247 phasedRegistrationNames: { 89248 bubbled: keyOf({ onMouseUp: true }), 89249 captured: keyOf({ onMouseUpCapture: true }) 89250 } 89251 }, 89252 paste: { 89253 phasedRegistrationNames: { 89254 bubbled: keyOf({ onPaste: true }), 89255 captured: keyOf({ onPasteCapture: true }) 89256 } 89257 }, 89258 pause: { 89259 phasedRegistrationNames: { 89260 bubbled: keyOf({ onPause: true }), 89261 captured: keyOf({ onPauseCapture: true }) 89262 } 89263 }, 89264 play: { 89265 phasedRegistrationNames: { 89266 bubbled: keyOf({ onPlay: true }), 89267 captured: keyOf({ onPlayCapture: true }) 89268 } 89269 }, 89270 playing: { 89271 phasedRegistrationNames: { 89272 bubbled: keyOf({ onPlaying: true }), 89273 captured: keyOf({ onPlayingCapture: true }) 89274 } 89275 }, 89276 progress: { 89277 phasedRegistrationNames: { 89278 bubbled: keyOf({ onProgress: true }), 89279 captured: keyOf({ onProgressCapture: true }) 89280 } 89281 }, 89282 rateChange: { 89283 phasedRegistrationNames: { 89284 bubbled: keyOf({ onRateChange: true }), 89285 captured: keyOf({ onRateChangeCapture: true }) 89286 } 89287 }, 89288 reset: { 89289 phasedRegistrationNames: { 89290 bubbled: keyOf({ onReset: true }), 89291 captured: keyOf({ onResetCapture: true }) 89292 } 89293 }, 89294 scroll: { 89295 phasedRegistrationNames: { 89296 bubbled: keyOf({ onScroll: true }), 89297 captured: keyOf({ onScrollCapture: true }) 89298 } 89299 }, 89300 seeked: { 89301 phasedRegistrationNames: { 89302 bubbled: keyOf({ onSeeked: true }), 89303 captured: keyOf({ onSeekedCapture: true }) 89304 } 89305 }, 89306 seeking: { 89307 phasedRegistrationNames: { 89308 bubbled: keyOf({ onSeeking: true }), 89309 captured: keyOf({ onSeekingCapture: true }) 89310 } 89311 }, 89312 stalled: { 89313 phasedRegistrationNames: { 89314 bubbled: keyOf({ onStalled: true }), 89315 captured: keyOf({ onStalledCapture: true }) 89316 } 89317 }, 89318 submit: { 89319 phasedRegistrationNames: { 89320 bubbled: keyOf({ onSubmit: true }), 89321 captured: keyOf({ onSubmitCapture: true }) 89322 } 89323 }, 89324 suspend: { 89325 phasedRegistrationNames: { 89326 bubbled: keyOf({ onSuspend: true }), 89327 captured: keyOf({ onSuspendCapture: true }) 89328 } 89329 }, 89330 timeUpdate: {
89331 phasedRegistrationNames: { 89332 bubbled: keyOf({ onTimeUpdate: true }), 89333 captured: keyOf({ onTimeUpdateCapture: true }) 89334 } 89335 }, 89336 touchCancel: { 89337 phasedRegistrationNames: { 89338 bubbled: keyOf({ onTouchCancel: true }), 89339 captured: keyOf({ onTouchCancelCapture: true }) 89340 } 89341 }, 89342 touchEnd: { 89343 phasedRegistrationNames: { 89344 bubbled: keyOf({ onTouchEnd: true }), 89345 captured: keyOf({ onTouchEndCapture: true }) 89346 } 89347 }, 89348 touchMove: { 89349 phasedRegistrationNames: { 89350 bubbled: keyOf({ onTouchMove: true }), 89351 captured: keyOf({ onTouchMoveCapture: true }) 89352 } 89353 }, 89354 touchStart: { 89355 phasedRegistrationNames: { 89356 bubbled: keyOf({ onTouchStart: true }), 89357 captured: keyOf({ onTouchStartCapture: true }) 89358 } 89359 }, 89360 transitionEnd: { 89361 phasedRegistrationNames: { 89362 bubbled: keyOf({ onTransitionEnd: true }), 89363 captured: keyOf({ onTransitionEndCapture: true }) 89364 } 89365 }, 89366 volumeChange: { 89367 phasedRegistrationNames: { 89368 bubbled: keyOf({ onVolumeChange: true }), 89369 captured: keyOf({ onVolumeChangeCapture: true }) 89370 } 89371 }, 89372 waiting: { 89373 phasedRegistrationNames: { 89374 bubbled: keyOf({ onWaiting: true }), 89375 captured: keyOf({ onWaitingCapture: true }) 89376 } 89377 }, 89378 wheel: { 89379 phasedRegistrationNames: { 89380 bubbled: keyOf({ onWheel: true }), 89381 captured: keyOf({ onWheelCapture: true }) 89382 } 89383 } 89384}; 89385 89386var topLevelEventsToDispatchConfig = { 89387 topAbort: eventTypes.abort, 89388 topAnimationEnd: eventTypes.animationEnd, 89389 topAnimationIteration: eventTypes.animationIteration, 89390 topAnimationStart: eventTypes.animationStart, 89391 topBlur: eventTypes.blur, 89392 topCanPlay: eventTypes.canPlay, 89393 topCanPlayThrough: eventTypes.canPlayThrough, 89394 topClick: eventTypes.click, 89395 topContextMenu: eventTypes.contextMenu, 89396 topCopy: eventTypes.copy, 89397 topCut: eventTypes.cut, 89398 topDoubleClick: eventTypes.doubleClick, 89399 topDrag: eventTypes.drag, 89400 topDragEnd: eventTypes.dragEnd, 89401 topDragEnter: eventTypes.dragEnter, 89402 topDragExit: eventTypes.dragExit, 89403 topDragLeave: eventTypes.dragLeave, 89404 topDragOver: eventTypes.dragOver, 89405 topDragStart: eventTypes.dragStart, 89406 topDrop: eventTypes.drop, 89407 topDurationChange: eventTypes.durationChange, 89408 topEmptied: eventTypes.emptied, 89409 topEncrypted: eventTypes.encrypted, 89410 topEnded: eventTypes.ended, 89411 topError: eventTypes.error, 89412 topFocus: eventTypes.focus, 89413 topInput: eventTypes.input, 89414 topInvalid: eventTypes.invalid, 89415 topKeyDown: eventTypes.keyDown, 89416 topKeyPress: eventTypes.keyPress, 89417 topKeyUp: eventTypes.keyUp, 89418 topLoad: eventTypes.load, 89419 topLoadedData: eventTypes.loadedData, 89420 topLoadedMetadata: eventTypes.loadedMetadata, 89421 topLoadStart: eventTypes.loadStart, 89422 topMouseDown: eventTypes.mouseDown, 89423 topMouseMove: eventTypes.mouseMove, 89424 topMouseOut: eventTypes.mouseOut, 89425 topMouseOver: eventTypes.mouseOver, 89426 topMouseUp: eventTypes.mouseUp, 89427 topPaste: eventTypes.paste, 89428 topPause: eventTypes.pause, 89429 topPlay: eventTypes.play, 89430 topPlaying: eventTypes.playing, 89431 topProgress: eventTypes.progress, 89432 topRateChange: eventTypes.rateChange, 89433 topReset: eventTypes.reset, 89434 topScroll: eventTypes.scroll, 89435 topSeeked: eventTypes.seeked, 89436 topSeeking: eventTypes.seeking, 89437 topStalled: eventTypes.stalled, 89438 topSubmit: eventTypes.submit, 89439 topSuspend: eventTypes.suspend, 89440 topTimeUpdate: eventTypes.timeUpdate, 89441 topTouchCancel: eventTypes.touchCancel, 89442 topTouchEnd: eventTypes.touchEnd, 89443 topTouchMove: eventTypes.touchMove, 89444 topTouchStart: eventTypes.touchStart, 89445 topTransitionEnd: eventTypes.transitionEnd, 89446 topVolumeChange: eventTypes.volumeChange, 89447 topWaiting: eventTypes.waiting, 89448 topWheel: eventTypes.wheel 89449}; 89450 89451for (var type in topLevelEventsToDispatchConfig) { 89452 topLevelEventsToDispatchConfig[type].dependencies = [type]; 89453} 89454 89455var ON_CLICK_KEY = keyOf({ onClick: null }); 89456var onClickListeners = {}; 89457 89458var SimpleEventPlugin = { 89459 89460 eventTypes: eventTypes, 89461 89462 extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) { 89463 var dispatchConfig = topLevelEventsToDispatchConfig[topLevelType]; 89464 if (!dispatchConfig) { 89465 return null; 89466 } 89467 var EventConstructor; 89468 switch (topLevelType) { 89469 case topLevelTypes.topAbort: 89470 case topLevelTypes.topCanPlay: 89471 case topLevelTypes.topCanPlayThrough: 89472 case topLevelTypes.topDurationChange: 89473 case topLevelTypes.topEmptied: 89474 case topLevelTypes.topEncrypted: 89475 case topLevelTypes.topEnded: 89476 case topLevelTypes.topError: 89477 case topLevelTypes.topInput: 89478 case topLevelTypes.topInvalid: 89479 case topLevelTypes.topLoad: 89480 case topLevelTypes.topLoadedData: 89481 case topLevelTypes.topLoadedMetadata: 89482 case topLevelTypes.topLoadStart: 89483 case topLevelTypes.topPause: 89484 case topLevelTypes.topPlay: 89485 case topLevelTypes.topPlaying: 89486 case topLevelTypes.topProgress: 89487 case topLevelTypes.topRateChange: 89488 case topLevelTypes.topReset: 89489 case topLevelTypes.topSeeked: 89490 case topLevelTypes.topSeeking: 89491 case topLevelTypes.topStalled: 89492 case topLevelTypes.topSubmit: 89493 case topLevelTypes.topSuspend: 89494 case topLevelTypes.topTimeUpdate: 89495 case topLevelTypes.topVolumeChange: 89496 case topLevelTypes.topWaiting: 89497 // HTML Events 89498 // @see http://www.w3.org/TR/html5/index.html#events-0 89499 EventConstructor = SyntheticEvent; 89500 break; 89501 case topLevelTypes.topKeyPress: 89502 // Firefox creates a keypress event for function keys too. This removes 89503 // the unwanted keypress events. Enter is however both printable and 89504 // non-printable. One would expect Tab to be as well (but it isn't).
89505 if (getEventCharCode(nativeEvent) === 0) { 89506 return null; 89507 } 89508 /* falls through */ 89509 case topLevelTypes.topKeyDown: 89510 case topLevelTypes.topKeyUp: 89511 EventConstructor = SyntheticKeyboardEvent; 89512 break; 89513 case topLevelTypes.topBlur: 89514 case topLevelTypes.topFocus: 89515 EventConstructor = SyntheticFocusEvent; 89516 break; 89517 case topLevelTypes.topClick: 89518 // Firefox creates a click event on right mouse clicks. This removes the 89519 // unwanted click events. 89520 if (nativeEvent.button === 2) { 89521 return null; 89522 } 89523 /* falls through */ 89524 case topLevelTypes.topContextMenu: 89525 case topLevelTypes.topDoubleClick: 89526 case topLevelTypes.topMouseDown: 89527 case topLevelTypes.topMouseMove: 89528 case topLevelTypes.topMouseOut: 89529 case topLevelTypes.topMouseOver: 89530 case topLevelTypes.topMouseUp: 89531 EventConstructor = SyntheticMouseEvent; 89532 break; 89533 case topLevelTypes.topDrag: 89534 case topLevelTypes.topDragEnd: 89535 case topLevelTypes.topDragEnter: 89536 case topLevelTypes.topDragExit: 89537 case topLevelTypes.topDragLeave: 89538 case topLevelTypes.topDragOver: 89539 case topLevelTypes.topDragStart: 89540 case topLevelTypes.topDrop: 89541 EventConstructor = SyntheticDragEvent; 89542 break; 89543 case topLevelTypes.topTouchCancel: 89544 case topLevelTypes.topTouchEnd: 89545 case topLevelTypes.topTouchMove: 89546 case topLevelTypes.topTouchStart: 89547 EventConstructor = SyntheticTouchEvent; 89548 break; 89549 case topLevelTypes.topAnimationEnd: 89550 case topLevelTypes.topAnimationIteration: 89551 case topLevelTypes.topAnimationStart: 89552 EventConstructor = SyntheticAnimationEvent; 89553 break; 89554 case topLevelTypes.topTransitionEnd: 89555 EventConstructor = SyntheticTransitionEvent; 89556 break; 89557 case topLevelTypes.topScroll: 89558 EventConstructor = SyntheticUIEvent; 89559 break; 89560 case topLevelTypes.topWheel: 89561 EventConstructor = SyntheticWheelEvent; 89562 break; 89563 case topLevelTypes.topCopy: 89564 case topLevelTypes.topCut: 89565 case topLevelTypes.topPaste: 89566 EventConstructor = SyntheticClipboardEvent; 89567 break; 89568 } 89569 !EventConstructor ? "development" !== 'production' ? invariant(false, 'SimpleEventPlugin: Unhandled event type, `%s`.', topLevelType) : invariant(false) : void 0; 89570 var event = EventConstructor.getPooled(dispatchConfig, targetInst, nativeEvent, nativeEventTarget); 89571 EventPropagators.accumulateTwoPhaseDispatches(event); 89572 return event; 89573 }, 89574 89575 didPutListener: function (inst, registrationName, listener) { 89576 // Mobile Safari does not fire properly bubble click events on 89577 // non-interactive elements, which means delegated click listeners do not 89578 // fire. The workaround for this bug involves attaching an empty click 89579 // listener on the target node. 89580 if (registrationName === ON_CLICK_KEY) { 89581 var id = inst._rootNodeID; 89582 var node = ReactDOMComponentTree.getNodeFromInstance(inst); 89583 if (!onClickListeners[id]) { 89584 onClickListeners[id] = EventListener.listen(node, 'click', emptyFunction); 89585 } 89586 } 89587 }, 89588 89589 willDeleteListener: function (inst, registrationName) { 89590 if (registrationName === ON_CLICK_KEY) { 89591 var id = inst._rootNodeID; 89592 onClickListeners[id].remove(); 89593 delete onClickListeners[id]; 89594 } 89595 } 89596 89597}; 89598 89599module.exports = SimpleEventPlugin; 89600},{"100":100,"102":102,"103":103,"104":104,"106":106,"107":107,"108":108,"109":109,"110":110,"111":111,"123":123,"143":143,"150":150,"158":158,"16":16,"162":162,"20":20,"40":40,"99":99}],99:[function(_dereq_,module,exports){ 89601/** 89602 * Copyright 2013-present, Facebook, Inc. 89603 * All rights reserved. 89604 * 89605 * This source code is licensed under the BSD-style license found in the 89606 * LICENSE file in the root directory of this source tree. An additional grant 89607 * of patent rights can be found in the PATENTS file in the same directory. 89608 * 89609 * @providesModule SyntheticAnimationEvent 89610 */ 89611 89612 89613 89614var SyntheticEvent = _dereq_(103); 89615 89616/** 89617 * @interface Event 89618 * @see http://www.w3.org/TR/css3-animations/#AnimationEvent-interface 89619 * @see https://developer.mozilla.org/en-US/docs/Web/API/AnimationEvent 89620 */ 89621var AnimationEventInterface = { 89622 animationName: null, 89623 elapsedTime: null, 89624 pseudoElement: null 89625}; 89626 89627/** 89628 * @param {object} dispatchConfig Configuration used to dispatch this event. 89629 * @param {string} dispatchMarker Marker identifying the event target. 89630 * @param {object} nativeEvent Native browser event. 89631 * @extends {SyntheticEvent} 89632 */
89633function SyntheticAnimationEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) { 89634 return SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget); 89635} 89636 89637SyntheticEvent.augmentClass(SyntheticAnimationEvent, AnimationEventInterface); 89638 89639module.exports = SyntheticAnimationEvent; 89640},{"103":103}],100:[function(_dereq_,module,exports){ 89641/** 89642 * Copyright 2013-present, Facebook, Inc. 89643 * All rights reserved. 89644 * 89645 * This source code is licensed under the BSD-style license found in the 89646 * LICENSE file in the root directory of this source tree. An additional grant 89647 * of patent rights can be found in the PATENTS file in the same directory. 89648 * 89649 * @providesModule SyntheticClipboardEvent 89650 */ 89651 89652 89653 89654var SyntheticEvent = _dereq_(103); 89655 89656/** 89657 * @interface Event 89658 * @see http://www.w3.org/TR/clipboard-apis/ 89659 */ 89660var ClipboardEventInterface = { 89661 clipboardData: function (event) { 89662 return 'clipboardData' in event ? event.clipboardData : window.clipboardData; 89663 } 89664}; 89665 89666/** 89667 * @param {object} dispatchConfig Configuration used to dispatch this event. 89668 * @param {string} dispatchMarker Marker identifying the event target. 89669 * @param {object} nativeEvent Native browser event. 89670 * @extends {SyntheticUIEvent} 89671 */ 89672function SyntheticClipboardEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) { 89673 return SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget); 89674} 89675 89676SyntheticEvent.augmentClass(SyntheticClipboardEvent, ClipboardEventInterface); 89677 89678module.exports = SyntheticClipboardEvent; 89679},{"103":103}],101:[function(_dereq_,module,exports){ 89680/** 89681 * Copyright 2013-present, Facebook, Inc. 89682 * All rights reserved. 89683 * 89684 * This source code is licensed under the BSD-style license found in the 89685 * LICENSE file in the root directory of this source tree. An additional grant 89686 * of patent rights can be found in the PATENTS file in the same directory. 89687 * 89688 * @providesModule SyntheticCompositionEvent 89689 */ 89690 89691 89692 89693var SyntheticEvent = _dereq_(103); 89694 89695/** 89696 * @interface Event 89697 * @see http://www.w3.org/TR/DOM-Level-3-Events/#events-compositionevents 89698 */ 89699var CompositionEventInterface = { 89700 data: null 89701}; 89702 89703/** 89704 * @param {object} dispatchConfig Configuration used to dispatch this event. 89705 * @param {string} dispatchMarker Marker identifying the event target. 89706 * @param {object} nativeEvent Native browser event. 89707 * @extends {SyntheticUIEvent} 89708 */ 89709function SyntheticCompositionEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) { 89710 return SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget); 89711} 89712 89713SyntheticEvent.augmentClass(SyntheticCompositionEvent, CompositionEventInterface); 89714 89715module.exports = SyntheticCompositionEvent; 89716},{"103":103}],102:[function(_dereq_,module,exports){ 89717/** 89718 * Copyright 2013-present, Facebook, Inc. 89719 * All rights reserved. 89720 * 89721 * This source code is licensed under the BSD-style license found in the 89722 * LICENSE file in the root directory of this source tree. An additional grant 89723 * of patent rights can be found in the PATENTS file in the same directory. 89724 * 89725 * @providesModule SyntheticDragEvent 89726 */ 89727 89728 89729 89730var SyntheticMouseEvent = _dereq_(107); 89731 89732/** 89733 * @interface DragEvent 89734 * @see http://www.w3.org/TR/DOM-Level-3-Events/ 89735 */ 89736var DragEventInterface = { 89737 dataTransfer: null 89738}; 89739 89740/** 89741 * @param {object} dispatchConfig Configuration used to dispatch this event. 89742 * @param {string} dispatchMarker Marker identifying the event target. 89743 * @param {object} nativeEvent Native browser event. 89744 * @extends {SyntheticUIEvent} 89745 */ 89746function SyntheticDragEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) { 89747 return SyntheticMouseEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget); 89748} 89749 89750SyntheticMouseEvent.augmentClass(SyntheticDragEvent, DragEventInterface); 89751 89752module.exports = SyntheticDragEvent; 89753},{"107":107}],103:[function(_dereq_,module,exports){ 89754/** 89755 * Copyright 2013-present, Facebook, Inc. 89756 * All rights reserved. 89757 * 89758 * This source code is licensed under the BSD-style license found in the 89759 * LICENSE file in the root directory of this source tree. An additional grant 89760 * of patent rights can be found in the PATENTS file in the same directory. 89761 * 89762 * @providesModule SyntheticEvent 89763 */ 89764 89765 89766 89767var _assign = _dereq_(169); 89768 89769var PooledClass = _dereq_(25); 89770 89771var emptyFunction = _dereq_(150); 89772var warning = _dereq_(168); 89773 89774var didWarnForAddedNewProperty = false;
89775var isProxySupported = typeof Proxy === 'function'; 89776 89777var shouldBeReleasedProperties = ['dispatchConfig', '_targetInst', 'nativeEvent', 'isDefaultPrevented', 'isPropagationStopped', '_dispatchListeners', '_dispatchInstances']; 89778 89779/** 89780 * @interface Event 89781 * @see http://www.w3.org/TR/DOM-Level-3-Events/ 89782 */ 89783var EventInterface = { 89784 type: null, 89785 target: null, 89786 // currentTarget is set when dispatching; no use in copying it here 89787 currentTarget: emptyFunction.thatReturnsNull, 89788 eventPhase: null, 89789 bubbles: null, 89790 cancelable: null, 89791 timeStamp: function (event) { 89792 return event.timeStamp || Date.now(); 89793 }, 89794 defaultPrevented: null, 89795 isTrusted: null 89796}; 89797 89798/** 89799 * Synthetic events are dispatched by event plugins, typically in response to a 89800 * top-level event delegation handler. 89801 * 89802 * These systems should generally use pooling to reduce the frequency of garbage 89803 * collection. The system should check `isPersistent` to determine whether the 89804 * event should be released into the pool after being dispatched. Users that 89805 * need a persisted event should invoke `persist`. 89806 * 89807 * Synthetic events (and subclasses) implement the DOM Level 3 Events API by 89808 * normalizing browser quirks. Subclasses do not necessarily have to implement a 89809 * DOM interface; custom application-specific events can also subclass this. 89810 * 89811 * @param {object} dispatchConfig Configuration used to dispatch this event. 89812 * @param {*} targetInst Marker identifying the event target. 89813 * @param {object} nativeEvent Native browser event. 89814 * @param {DOMEventTarget} nativeEventTarget Target node. 89815 */ 89816function SyntheticEvent(dispatchConfig, targetInst, nativeEvent, nativeEventTarget) { 89817 if ("development" !== 'production') { 89818 // these have a getter/setter for warnings 89819 delete this.nativeEvent; 89820 delete this.preventDefault; 89821 delete this.stopPropagation; 89822 } 89823 89824 this.dispatchConfig = dispatchConfig; 89825 this._targetInst = targetInst; 89826 this.nativeEvent = nativeEvent; 89827 89828 var Interface = this.constructor.Interface; 89829 for (var propName in Interface) { 89830 if (!Interface.hasOwnProperty(propName)) { 89831 continue; 89832 } 89833 if ("development" !== 'production') { 89834 delete this[propName]; // this has a getter/setter for warnings 89835 } 89836 var normalize = Interface[propName]; 89837 if (normalize) { 89838 this[propName] = normalize(nativeEvent); 89839 } else { 89840 if (propName === 'target') { 89841 this.target = nativeEventTarget; 89842 } else { 89843 this[propName] = nativeEvent[propName]; 89844 } 89845 } 89846 } 89847 89848 var defaultPrevented = nativeEvent.defaultPrevented != null ? nativeEvent.defaultPrevented : nativeEvent.returnValue === false; 89849 if (defaultPrevented) { 89850 this.isDefaultPrevented = emptyFunction.thatReturnsTrue; 89851 } else { 89852 this.isDefaultPrevented = emptyFunction.thatReturnsFalse; 89853 } 89854 this.isPropagationStopped = emptyFunction.thatReturnsFalse; 89855 return this; 89856} 89857 89858_assign(SyntheticEvent.prototype, { 89859 89860 preventDefault: function () { 89861 this.defaultPrevented = true; 89862 var event = this.nativeEvent; 89863 if (!event) { 89864 return; 89865 } 89866 89867 if (event.preventDefault) { 89868 event.preventDefault(); 89869 } else { 89870 event.returnValue = false; 89871 } 89872 this.isDefaultPrevented = emptyFunction.thatReturnsTrue; 89873 }, 89874 89875 stopPropagation: function () { 89876 var event = this.nativeEvent; 89877 if (!event) { 89878 return; 89879 } 89880 89881 if (event.stopPropagation) { 89882 event.stopPropagation(); 89883 } else { 89884 event.cancelBubble = true; 89885 } 89886 this.isPropagationStopped = emptyFunction.thatReturnsTrue; 89887 }, 89888 89889 /** 89890 * We release all dispatched `SyntheticEvent`s after each event loop, adding 89891 * them back into the pool. This allows a way to hold onto a reference that 89892 * won't be added back into the pool. 89893 */ 89894 persist: function () { 89895 this.isPersistent = emptyFunction.thatReturnsTrue; 89896 }, 89897 89898 /** 89899 * Checks if this event should be released back into the pool. 89900 * 89901 * @return {boolean} True if this should not be released, false otherwise. 89902 */ 89903 isPersistent: emptyFunction.thatReturnsFalse, 89904 89905 /** 89906 * `PooledClass` looks for `destructor` on each instance it releases. 89907 */ 89908 destructor: function () { 89909 var Interface = this.constructor.Interface; 89910 for (var propName in Interface) { 89911 if ("development" !== 'production') { 89912 Object.defineProperty(this, propName, getPooledWarningPropertyDefinition(propName, Interface[propName])); 89913 } else { 89914 this[propName] = null; 89915 } 89916 } 89917 for (var i = 0; i < shouldBeReleasedProperties.length; i++) { 89918 this[shouldBeReleasedProperties[i]] = null; 89919 } 89920 if ("development" !== 'production') { 89921 var noop = _dereq_(150); 89922 Object.defineProperty(this, 'nativeEvent', getPooledWarningPropertyDefinition('nativeEvent', null)); 89923 Object.defineProperty(this, 'preventDefault', getPooledWarningPropertyDefinition('preventDefault', no
89923op)); 89924 Object.defineProperty(this, 'stopPropagation', getPooledWarningPropertyDefinition('stopPropagation', noop)); 89925 } 89926 } 89927 89928}); 89929 89930SyntheticEvent.Interface = EventInterface; 89931 89932if ("development" !== 'production') { 89933 if (isProxySupported) { 89934 /*eslint-disable no-func-assign */ 89935 SyntheticEvent = new Proxy(SyntheticEvent, { 89936 construct: function (target, args) { 89937 return this.apply(target, Object.create(target.prototype), args); 89938 }, 89939 apply: function (constructor, that, args) { 89940 return new Proxy(constructor.apply(that, args), { 89941 set: function (target, prop, value) { 89942 if (prop !== 'isPersistent' && !target.constructor.Interface.hasOwnProperty(prop) && shouldBeReleasedProperties.indexOf(prop) === -1) { 89943 "development" !== 'production' ? warning(didWarnForAddedNewProperty || target.isPersistent(), 'This synthetic event is reused for performance reasons. If you\'re ' + 'seeing this, you\'re adding a new property in the synthetic event object. ' + 'The property is never released. See ' + 'https://fb.me/react-event-pooling for more information.') : void 0; 89944 didWarnForAddedNewProperty = true; 89945 } 89946 target[prop] = value; 89947 return true; 89948 } 89949 }); 89950 } 89951 }); 89952 /*eslint-enable no-func-assign */ 89953 } 89954} 89955/** 89956 * Helper to reduce boilerplate when creating subclasses. 89957 * 89958 * @param {function} Class 89959 * @param {?object} Interface 89960 */ 89961SyntheticEvent.augmentClass = function (Class, Interface) { 89962 var Super = this; 89963 89964 var E = function () {}; 89965 E.prototype = Super.prototype; 89966 var prototype = new E(); 89967 89968 _assign(prototype, Class.prototype); 89969 Class.prototype = prototype; 89970 Class.prototype.constructor = Class; 89971 89972 Class.Interface = _assign({}, Super.Interface, Interface); 89973 Class.augmentClass = Super.augmentClass; 89974 89975 PooledClass.addPoolingTo(Class, PooledClass.fourArgumentPooler); 89976}; 89977 89978PooledClass.addPoolingTo(SyntheticEvent, PooledClass.fourArgumentPooler); 89979 89980module.exports = SyntheticEvent; 89981 89982/** 89983 * Helper to nullify syntheticEvent instance properties when destructing 89984 * 89985 * @param {object} SyntheticEvent 89986 * @param {String} propName 89987 * @return {object} defineProperty object 89988 */ 89989function getPooledWarningPropertyDefinition(propName, getVal) { 89990 var isFunction = typeof getVal === 'function'; 89991 return { 89992 configurable: true, 89993 set: set, 89994 get: get 89995 }; 89996 89997 function set(val) { 89998 var action = isFunction ? 'setting the method' : 'setting the property'; 89999 warn(action, 'This is effectively a no-op'); 90000 return val; 90001 } 90002 90003 function get() { 90004 var action = isFunction ? 'accessing the method' : 'accessing the property'; 90005 var result = isFunction ? 'This is a no-op function' : 'This is set to null'; 90006 warn(action, result); 90007 return getVal; 90008 } 90009 90010 function warn(action, result) { 90011 var warningCondition = false; 90012 "development" !== 'production' ? warning(warningCondition, 'This synthetic event is reused for performance reasons. If you\'re seeing this, ' + 'you\'re %s `%s` on a released/nullified synthetic event. %s. ' + 'If you must keep the original synthetic event around, use event.persist(). ' + 'See https://fb.me/react-event-pooling for more information.', action, propName, result) : void 0; 90013 } 90014} 90015},{"150":150,"168":168,"169":169,"25":25}],104:[function(_dereq_,module,exports){ 90016/** 90017 * Copyright 2013-present, Facebook, Inc. 90018 * All rights reserved. 90019 * 90020 * This source code is licensed under the BSD-style license found in the 90021 * LICENSE file in the root directory of this source tree. An additional grant 90022 * of patent rights can be found in the PATENTS file in the same directory. 90023 * 90024 * @providesModule SyntheticFocusEvent 90025 */ 90026 90027 90028 90029var SyntheticUIEvent = _dereq_(110); 90030 90031/** 90032 * @interface FocusEvent 90033 * @see http://www.w3.org/TR/DOM-Level-3-Events/ 90034 */ 90035var FocusEventInterface = { 90036 relatedTarget: null 90037}; 90038 90039/** 90040 * @param {object} dispatchConfig Configuration used to dispatch this event. 90041 * @param {string} dispatchMarker Marker identifying the event target. 90042 * @param {object} nativeEvent Native browser event. 90043 * @extends {SyntheticUIEvent} 90044 */
90045function SyntheticFocusEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) { 90046 return SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget); 90047} 90048 90049SyntheticUIEvent.augmentClass(SyntheticFocusEvent, FocusEventInterface); 90050 90051module.exports = SyntheticFocusEvent; 90052},{"110":110}],105:[function(_dereq_,module,exports){ 90053/** 90054 * Copyright 2013-present, Facebook, Inc. 90055 * All rights reserved. 90056 * 90057 * This source code is licensed under the BSD-style license found in the 90058 * LICENSE file in the root directory of this source tree. An additional grant 90059 * of patent rights can be found in the PATENTS file in the same directory. 90060 * 90061 * @providesModule SyntheticInputEvent 90062 */ 90063 90064 90065 90066var SyntheticEvent = _dereq_(103); 90067 90068/** 90069 * @interface Event 90070 * @see http://www.w3.org/TR/2013/WD-DOM-Level-3-Events-20131105 90071 * /#events-inputevents 90072 */ 90073var InputEventInterface = { 90074 data: null 90075}; 90076 90077/** 90078 * @param {object} dispatchConfig Configuration used to dispatch this event. 90079 * @param {string} dispatchMarker Marker identifying the event target. 90080 * @param {object} nativeEvent Native browser event. 90081 * @extends {SyntheticUIEvent} 90082 */ 90083function SyntheticInputEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) { 90084 return SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget); 90085} 90086 90087SyntheticEvent.augmentClass(SyntheticInputEvent, InputEventInterface); 90088 90089module.exports = SyntheticInputEvent; 90090},{"103":103}],106:[function(_dereq_,module,exports){ 90091/** 90092 * Copyright 2013-present, Facebook, Inc. 90093 * All rights reserved. 90094 * 90095 * This source code is licensed under the BSD-style license found in the 90096 * LICENSE file in the root directory of this source tree. An additional grant 90097 * of patent rights can be found in the PATENTS file in the same directory. 90098 * 90099 * @providesModule SyntheticKeyboardEvent 90100 */ 90101 90102 90103 90104var SyntheticUIEvent = _dereq_(110); 90105 90106var getEventCharCode = _dereq_(123); 90107var getEventKey = _dereq_(124); 90108var getEventModifierState = _dereq_(125); 90109 90110/** 90111 * @interface KeyboardEvent 90112 * @see http://www.w3.org/TR/DOM-Level-3-Events/ 90113 */ 90114var KeyboardEventInterface = { 90115 key: getEventKey, 90116 location: null, 90117 ctrlKey: null, 90118 shiftKey: null, 90119 altKey: null, 90120 metaKey: null, 90121 repeat: null, 90122 locale: null, 90123 getModifierState: getEventModifierState, 90124 // Legacy Interface 90125 charCode: function (event) { 90126 // `charCode` is the result of a KeyPress event and represents the value of 90127 // the actual printable character. 90128 90129 // KeyPress is deprecated, but its replacement is not yet final and n
90129ot 90130 // implemented in any major browser. Only KeyPress has charCode. 90131 if (event.type === 'keypress') { 90132 return getEventCharCode(event); 90133 } 90134 return 0; 90135 }, 90136 keyCode: function (event) { 90137 // `keyCode` is the result of a KeyDown/Up event and represents the value of 90138 // physical keyboard key. 90139 90140 // The actual meaning of the value depends on the users' keyboard layout 90141 // which cannot be detected. Assuming that it is a US keyboard layout 90142 // provides a surprisingly accurate mapping for US and European users. 90143 // Due to this, it is left to the user to implement at this time. 90144 if (event.type === 'keydown' || event.type === 'keyup') { 90145 return event.keyCode; 90146 } 90147 return 0; 90148 }, 90149 which: function (event) { 90150 // `which` is an alias for either `keyCode` or `charCode` depending on the 90151 // type of the event. 90152 if (event.type === 'keypress') { 90153 return getEventCharCode(event); 90154 } 90155 if (event.type === 'keydown' || event.type === 'keyup') { 90156 return event.keyCode; 90157 } 90158 return 0; 90159 } 90160}; 90161 90162/** 90163 * @param {object} dispatchConfig Configuration used to dispatch this event. 90164 * @param {string} dispatchMarker Marker identifying the event target. 90165 * @param {object} nativeEvent Native browser event. 90166 * @extends {SyntheticUIEvent} 90167 */ 90168function SyntheticKeyboardEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) { 90169 return SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget); 90170} 90171 90172SyntheticUIEvent.augmentClass(SyntheticKeyboardEvent, KeyboardEventInterface); 90173 90174module.exports = SyntheticKeyboardEvent; 90175},{"110":110,"123":123,"124":124,"125":125}],107:[function(_dereq_,module,exports){ 90176/** 90177 * Copyright 2013-present, Facebook, Inc. 90178 * All rights reserved. 90179 * 90180 * This source code is licensed under the BSD-style license found in the 90181 * LICENSE file in the root directory of this source tree. An additional grant 90182 * of patent rights can be found in the PATENTS file in the same directory. 90183 * 90184 * @providesModule SyntheticMouseEvent 90185 */ 90186 90187 90188 90189var SyntheticUIEvent = _dereq_(110); 90190var ViewportMetrics = _dereq_(113); 90191 90192var getEventModifierState = _dereq_(125); 90193 90194/** 90195 * @interface MouseEvent 90196 * @see http://www.w3.org/TR/DOM-Level-3-Events/ 90197 */ 90198var MouseEventInterface = { 90199 screenX: null, 90200 screenY: null, 90201 clientX: null, 90202 clientY: null, 90203 ctrlKey: null, 90204 shiftKey: null, 90205 altKey: null, 90206 metaKey: null, 90207 getModifierState: getEventModifierState, 90208 button: function (event) { 90209 // Webkit, Firefox, IE9+ 90210 // which: 1 2 3 90211 // button: 0 1 2 (standard) 90212 var button = event.button; 90213 if ('which' in event) { 90214 return button; 90215 } 90216 // IE<9 90217 // which: undefined 90218 // button: 0 0 0 90219 // button: 1 4 2 (onmouseup) 90220 return button === 2 ? 2 : button === 4 ? 1 : 0; 90221 }, 90222 buttons: null, 90223 relatedTarget: function (event) { 90224 return event.relatedTarget || (event.fromElement === event.srcElement ? event.toElement : event.fromElement); 90225 }, 90226 // "Proprietary" Interface. 90227 pageX: function (event) { 90228 return 'pageX' in event ? event.pageX : event.clientX + ViewportMetrics.currentScrollLeft; 90229 }, 90230 pageY: function (event) { 90231 return 'pageY' in event ? event.pageY : event.clientY + ViewportMetrics.currentScrollTop; 90232 } 90233}; 90234 90235/** 90236 * @param {object} dispatchConfig Configuration used to dispatch this event. 90237 * @param {string} dispatchMarker Marker identifying the event target. 90238 * @param {object} nativeEvent Native browser event. 90239 * @extends {SyntheticUIEvent} 90240 */ 90241function SyntheticMouseEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) { 90242 return SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget); 90243} 90244 90245SyntheticUIEvent.augmentClass(SyntheticMouseEvent, MouseEventInterface); 90246 90247module.exports = SyntheticMouseEvent; 90248},{"110":110,"113":113,"125":125}],108:[function(_dereq_,module,exports){ 90249/** 90250 * Copyright 2013-present, Facebook, Inc. 90251 * All rights reserved. 90252 * 90253 * This source code is licensed under the BSD-style license found in the 90254 * LICENSE file in the root directory of this source tree. An additional grant 90255 * of patent rights can be found in the PATENTS file in the same directory. 90256 * 90257 * @providesModule SyntheticTouchEvent 90258 */ 90259 90260 90261 90262var SyntheticUIEvent = _dereq_(110); 90263 90264var getEventModifierState = _dereq_(125); 90265 90266/** 90267 * @interface TouchEvent 90268 * @see http://www.w3.org/TR/touch-events/ 90269 */ 90270var TouchEventInterface = { 90271 touches: null, 90272 targetTouches: null, 90273 changedTouches: null, 90274 altKey: null, 90275 metaKey: null, 90276 ctrlKey: null, 90277 shiftKey: null, 90278 getModifierState: getEventModifierState 90279}; 90280 90281/** 90282 * @param {object} dispatchConfig Configuration used to dispatch this event. 90283 * @param {string} dispatchMarker Marker identifying the event target. 90284 * @param {object} nativeEvent Native browser event. 90285 * @extends {SyntheticUIEvent} 90286 */
90287function SyntheticTouchEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) { 90288 return SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget); 90289} 90290 90291SyntheticUIEvent.augmentClass(SyntheticTouchEvent, TouchEventInterface); 90292 90293module.exports = SyntheticTouchEvent; 90294},{"110":110,"125":125}],109:[function(_dereq_,module,exports){ 90295/** 90296 * Copyright 2013-present, Facebook, Inc. 90297 * All rights reserved. 90298 * 90299 * This source code is licensed under the BSD-style license found in the 90300 * LICENSE file in the root directory of this source tree. An additional grant 90301 * of patent rights can be found in the PATENTS file in the same directory. 90302 * 90303 * @providesModule SyntheticTransitionEvent 90304 */ 90305 90306 90307 90308var SyntheticEvent = _dereq_(103); 90309 90310/** 90311 * @interface Event 90312 * @see http://www.w3.org/TR/2009/WD-css3-transitions-20090320/#transition-events- 90313 * @see https://developer.mozilla.org/en-US/docs/Web/API/TransitionEvent 90314 */ 90315var TransitionEventInterface = { 90316 propertyName: null, 90317 elapsedTime: null, 90318 pseudoElement: null 90319}; 90320 90321/** 90322 * @param {object} dispatchConfig Configuration used to dispatch this event. 90323 * @param {string} dispatchMarker Marker identifying the event target. 90324 * @param {object} nativeEvent Native browser event. 90325 * @extends {SyntheticEvent} 90326 */ 90327function SyntheticTransitionEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) { 90328 return SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget); 90329} 90330 90331SyntheticEvent.augmentClass(SyntheticTransitionEvent, TransitionEventInterface); 90332 90333module.exports = SyntheticTransitionEvent; 90334},{"103":103}],110:[function(_dereq_,module,exports){ 90335/** 90336 * Copyright 2013-present, Facebook, Inc. 90337 * All rights reserved. 90338 * 90339 * This source code is licensed under the BSD-style license found in the 90340 * LICENSE file in the root directory of this source tree. An additional grant 90341 * of patent rights can be found in the PATENTS file in the same directory. 90342 * 90343 * @providesModule SyntheticUIEvent 90344 */ 90345 90346 90347 90348var SyntheticEvent = _dereq_(103); 90349 90350var getEventTarget = _dereq_(126); 90351 90352/** 90353 * @interface UIEvent 90354 * @see http://www.w3.org/TR/DOM-Level-3-Events/ 90355 */ 90356var UIEventInterface = { 90357 view: function (event) { 90358 if (event.view) { 90359 return event.view; 90360 } 90361 90362 var target = getEventTarget(event); 90363 if (target != null && target.window === target) { 90364 // target is a window object 90365 return target; 90366 } 90367 90368 var doc = target.ownerDocument; 90369 // TODO: Figure out why `ownerDocument` is sometimes undefined in IE8. 90370 if (doc) { 90371 return doc.defaultView || doc.parentWindow; 90372 } else { 90373 return window; 90374 } 90375 }, 90376 detail: function (event) { 90377 return event.detail || 0; 90378 } 90379}; 90380 90381/** 90382 * @param {object} dispatchConfig Configuration used to dispatch this event. 90383 * @param {string} dispatchMarker Marker identifying the event target. 90384 * @param {object} nativeEvent Native browser event. 90385 * @extends {SyntheticEvent} 90386 */ 90387function SyntheticUIEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) { 90388 return SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget); 90389} 90390 90391SyntheticEvent.augmentClass(SyntheticUIEvent, UIEventInterface); 90392 90393module.exports = SyntheticUIEvent; 90394},{"103":103,"126":126}],111:[function(_dereq_,module,exports){ 90395/** 90396 * Copyright 2013-present, Facebook, Inc. 90397 * All rights reserved. 90398 * 90399 * This source code is licensed under the BSD-style license found in the 90400 * LICENSE file in the root directory of this source tree. An additional grant 90401 * of patent rights can be found in the PATENTS file in the same directory. 90402 * 90403 * @providesModule SyntheticWheelEvent 90404 */ 90405 90406 90407 90408var SyntheticMouseEvent = _dereq_(107); 90409 90410/** 90411 * @interface WheelEvent 90412 * @see http://www.w3.org/TR/DOM-Level-3-Events/ 90413 */ 90414var WheelEventInterface = { 90415 deltaX: function (event) { 90416 return 'deltaX' in event ? event.deltaX : 90417 // Fallback to `wheelDeltaX` for Webkit and normalize (right is positive). 90418 'wheelDeltaX' in event ? -event.wheelDeltaX : 0; 90419 }, 90420 deltaY: function (event) { 90421 return 'deltaY' in event ? event.deltaY : 90422 // Fallback to `wheelDeltaY` for Webkit and normalize (down is positive). 90423 'wheelDeltaY' in event ? -event.wheelDeltaY :
90424 // Fallback to `wheelDelta` for IE<9 and normalize (down is positive). 90425 'wheelDelta' in event ? -event.wheelDelta : 0; 90426 }, 90427 deltaZ: null, 90428 90429 // Browsers without "deltaMode" is reporting in raw wheel delta where one 90430 // notch on the scroll is always +/- 120, roughly equivalent to pixels. 90431 // A good approximation of DOM_DELTA_LINE (1) is 5% of viewport size or 90432 // ~40 pixels, for DOM_DELTA_SCREEN (2) it is 87.5% of viewport size. 90433 deltaMode: null 90434}; 90435 90436/** 90437 * @param {object} dispatchConfig Configuration used to dispatch this event. 90438 * @param {string} dispatchMarker Marker identifying the event target. 90439 * @param {object} nativeEvent Native browser event. 90440 * @extends {SyntheticMouseEvent} 90441 */ 90442function SyntheticWheelEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) { 90443 return SyntheticMouseEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget); 90444} 90445 90446SyntheticMouseEvent.augmentClass(SyntheticWheelEvent, WheelEventInterface); 90447 90448module.exports = SyntheticWheelEvent; 90449},{"107":107}],112:[function(_dereq_,module,exports){ 90450/** 90451 * Copyright 2013-present, Facebook, Inc. 90452 * All rights reserved. 90453 * 90454 * This source code is licensed under the BSD-style license found in the 90455 * LICENSE file in the root directory of this source tree. An additional grant 90456 * of patent rights can be found in the PATENTS file in the same directory. 90457 * 90458 * @providesModule Transaction 90459 */ 90460 90461 90462 90463var invariant = _dereq_(158); 90464 90465/** 90466 * `Transaction` creates a black box that is able to wrap any method such that 90467 * certain invariants are maintained before and after the method is invoked 90468 * (Even if an exception is thrown while invoking the wrapped method). Whoever 90469 * instantiates a transaction can provide enforcers of the invariants at 90470 * creation time. The `Transaction` class itself will supply one additional 90471 * automatic invariant for you - the invariant that any transaction instance 90472 * should not be run while it is already being run. You would typically create a 90473 * single instance of a `Transaction` for reuse multiple times, that potentially 90474 * is used to wrap several different methods. Wrappers are extremely simple - 90475 * they only require implementing two methods. 90476 * 90477 * <pre> 90478 * wrappers (injected at creation time) 90479 * + + 90480 * | | 90481 * +-----------------|--------|--------------+ 90482 * | v | | 90483 * | +---------------+ | | 90484 * | +--| wrapper1 |---|----+ | 90485 * | | +---------------+ v | | 90486 * | | +-------------+ | | 90487 * | | +----| wrapper2 |--------+ | 90488 * | | | +-------------+ | | | 90489 * | | | | | | 90490 * | v v v v | wrapper 90491 * | +---+ +---+ +---------+ +---+ +---+ | invariants 90492 * perform(anyMethod) | | | | | | | | | | | | maintained 90493 * +----------------->|-|---|-|---|-->|anyMethod|---|---|-|---|-|--------> 90494 * | | | | | | | | | | | | 90495 * | | | | | | | | | | | | 90496 * | | | | | | | | | | | | 90497 * | +---+ +---+ +---------+ +---+ +---+ | 90498 * | initialize close | 90499 * +-----------------------------------------+ 90500 * </pre> 90501 * 90502 * Use cases: 90503 * - Preserving the input selection ranges before/after reconciliation. 90504 * Restoring selection even in the event of an unexpected error. 90505 * - Deactivating events while rearranging the DOM, preventing blurs/focuses, 90506 * while guaranteeing that afterwards, the event system is reactivated. 90507 * - Flushing a queue of collected DOM mutations to the main UI thread after a 90508 * reconciliation takes place in a worker thread. 90509 * - Invoking any collected `componentDidUpdate` callbacks after rendering new 90510 * content. 90511 * - (Future use case): Wrapping particular flushes of the `ReactWorker` queue 90512 * to preserve the `scrollTop` (an automatic scroll aware DOM). 90513 * - (Future use case): Layout calculations before and after DOM updates. 90514 * 90515 * Transactional plugin API: 90516 * - A module that has an `initialize` method that returns any precomputation. 90517 * - and a `close` method that accepts the precomputation. `close` is invoked 90518 * when the wrapped process is completed, or has failed. 90519 * 90520 * @param {Array<TransactionalWrapper>} transactionWrapper Wrapper modules 90521 * that implement `initialize` and `close`. 90522 * @return {Transaction} Single transaction for reuse in thread. 90523 * 90524 * @class Transaction 90525 */ 90526var Mixin = { 90527 /** 90528 * Sets up this instance so that it is prepared for collecting metrics. Does 90529 * so such that this setup method may be used on an instance that is already 90530 * initialized, in a way that does not consume additional memory upon reuse. 90531 * That can be useful if you decide to make your subclass of this mixin a 90532 * "PooledClass". 90533 */ 90534 reinitializeTransaction: function () { 90535 this.transactionWrappers = this.getTransactionWrappers(); 90536 if (this.wrapperInitData) { 90537 this.wrapperInitData.length = 0; 90538 } else { 90539 this.wrapperInitData = []; 90540 } 90541 this._isInTransaction = false;
90542 }, 90543 90544 _isInTransaction: false, 90545 90546 /** 90547 * @abstract 90548 * @return {Array<TransactionWrapper>} Array of transaction wrappers. 90549 */ 90550 getTransactionWrappers: null, 90551 90552 isInTransaction: function () { 90553 return !!this._isInTransaction; 90554 }, 90555 90556 /** 90557 * Executes the function within a safety window. Use this for the top level 90558 * methods that result in large amounts of computation/mutations that would 90559 * need to be safety checked. The optional arguments helps prevent the need 90560 * to bind in many cases. 90561 * 90562 * @param {function} method Member of scope to call. 90563 * @param {Object} scope Scope to invoke from. 90564 * @param {Object?=} a Argument to pass to the method. 90565 * @param {Object?=} b Argument to pass to the method. 90566 * @param {Object?=} c Argument to pass to the method. 90567 * @param {Object?=} d Argument to pass to the method. 90568 * @param {Object?=} e Argument to pass to the method. 90569 * @param {Object?=} f Argument to pass to the method. 90570 * 90571 * @return {*} Return value from `method`. 90572 */ 90573 perform: function (method, scope, a, b, c, d, e, f) { 90574 !!this.isInTransaction() ? "development" !== 'production' ? invariant(false, 'Transaction.perform(...): Cannot initialize a transaction when there ' + 'is already an outstanding transaction.') : invariant(false) : void 0; 90575 var errorThrown; 90576 var ret; 90577 try { 90578 this._isInTransaction = true; 90579 // Catching errors makes debugging more difficult, so we start with 90580 // errorThrown set to true before setting it to false after calling 90581 // close -- if it's still set to true in the finally block, it means 90582 // one of these calls threw. 90583 errorThrown = true; 90584 this.initializeAll(0); 90585 ret = method.call(scope, a, b, c, d, e, f); 90586 errorThrown = false; 90587 } finally { 90588 try { 90589 if (errorThrown) { 90590 // If `method` throws, prefer to show that stack trace over any thrown 90591 // by invoking `closeAll`. 90592 try { 90593 this.closeAll(0); 90594 } catch (err) {} 90595 } else { 90596 // Since `method` didn't throw, we don't want to silence the exception 90597 // here. 90598 this.closeAll(0); 90599 } 90600 } finally { 90601 this._isInTransaction = false; 90602 } 90603 } 90604 return ret; 90605 }, 90606 90607 initializeAll: function (startIndex) { 90608 var transactionWrappers = this.transactionWrappers; 90609 for (var i = startIndex; i < transactionWrappers.length; i++) { 90610 var wrapper = transactionWrappers[i]; 90611 try { 90612 // Catching errors makes debugging more difficult, so we start with the 90613 // OBSERVED_ERROR state before overwriting it with the real return value 90614 // of initialize -- if it's still set to OBSERVED_ERROR in the finally 90615 // block, it means wrapper.initialize threw. 90616 this.wrapperInitData[i] = Transaction.OBSERVED_ERROR; 90617 this.wrapperInitData[i] = wrapper.initialize ? wrapper.initialize.call(this) : null; 90618 } finally { 90619 if (this.wrapperInitData[i] === Transaction.OBSERVED_ERROR) { 90620 // The initializer for wrapper i threw an error; initialize the 90621 // remaining wrappers but silence any exceptions from them to ensure 90622 // that the first error is the one to bubble up. 90623 try { 90624 this.initializeAll(i + 1); 90625 } catch (err) {} 90626 } 90627 } 90628 } 90629 }, 90630 90631 /** 90632 * Invokes each of `this.transactionWrappers.close[i]` functions, passing into 90633 * them the respective return values of `this.transactionWrappers.init[i]` 90634 * (`close`rs that correspond to initializers that failed will not be 90635 * invoked). 90636 */ 90637 closeAll: function (startIndex) { 90638 !this.isInTransaction() ? "development" !== 'production' ? invariant(false, 'Transaction.closeAll(): Cannot close transaction when none are open.') : invariant(false) : void 0; 90639 var transactionWrappers = this.transactionWrappers; 90640 for (var i = startIndex; i < transactionWrappers.length; i++) { 90641 var wrapper = transactionWrappers[i]; 90642 var initData = this.wrapperInitData[i]; 90643 var errorThrown; 90644 try { 90645 // Catching errors makes debugging more difficult, so we start with
90646 // errorThrown set to true before setting it to false after calling 90647 // close -- if it's still set to true in the finally block, it means 90648 // wrapper.close threw. 90649 errorThrown = true; 90650 if (initData !== Transaction.OBSERVED_ERROR && wrapper.close) { 90651 wrapper.close.call(this, initData); 90652 } 90653 errorThrown = false; 90654 } finally { 90655 if (errorThrown) { 90656 // The closer for wrapper i threw an error; close the remaining 90657 // wrappers but silence any exceptions from them to ensure that the 90658 // first error is the one to bubble up. 90659 try { 90660 this.closeAll(i + 1); 90661 } catch (e) {} 90662 } 90663 } 90664 } 90665 this.wrapperInitData.length = 0; 90666 } 90667}; 90668 90669var Transaction = { 90670 90671 Mixin: Mixin, 90672 90673 /** 90674 * Token to look for to determine if an error occurred. 90675 */ 90676 OBSERVED_ERROR: {} 90677 90678}; 90679 90680module.exports = Transaction; 90681},{"158":158}],113:[function(_dereq_,module,exports){ 90682/** 90683 * Copyright 2013-present, Facebook, Inc. 90684 * All rights reserved. 90685 * 90686 * This source code is licensed under the BSD-style license found in the 90687 * LICENSE file in the root directory of this source tree. An additional grant 90688 * of patent rights can be found in the PATENTS file in the same directory. 90689 * 90690 * @providesModule ViewportMetrics 90691 */ 90692 90693 90694 90695var ViewportMetrics = { 90696 90697 currentScrollLeft: 0, 90698 90699 currentScrollTop: 0, 90700 90701 refreshScrollValues: function (scrollPosition) { 90702 ViewportMetrics.currentScrollLeft = scrollPosition.x; 90703 ViewportMetrics.currentScrollTop = scrollPosition.y; 90704 } 90705 90706}; 90707 90708module.exports = ViewportMetrics; 90709},{}],114:[function(_dereq_,module,exports){ 90710/** 90711 * Copyright 2014-present, Facebook, Inc. 90712 * All rights reserved. 90713 * 90714 * This source code is licensed under the BSD-style license found in the 90715 * LICENSE file in the root directory of this source tree. An additional grant 90716 * of patent rights can be found in the PATENTS file in the same directory. 90717 * 90718 * @providesModule accumulateInto 90719 */ 90720 90721 90722 90723var invariant = _dereq_(158); 90724 90725/** 90726 * 90727 * Accumulates items that must not be null or undefined into the first one. This 90728 * is used to conserve memory by avoiding array allocations, and thus sacrifices 90729 * API cleanness. Since `current` can be null before being passed in and not 90730 * null after this function, make sure to assign it back to `current`: 90731 * 90732 * `a = accumulateInto(a, b);` 90733 * 90734 * This API should be sparingly used. Try `accumulate` for something cleaner. 90735 * 90736 * @return {*|array<*>} An accumulation of items. 90737 */ 90738 90739function accumulateInto(current, next) { 90740 !(next != null) ? "development" !== 'production' ? invariant(false, 'accumulateInto(...): Accumulated items must not be null or undefined.') : invariant(false) : void 0; 90741 if (current == null) { 90742 return next; 90743 } 90744 90745 // Both are not empty. Warning: Never call x.concat(y) when you are not 90746 // certain that x is an Array (x could be a string with concat method). 90747 var currentIsArray = Array.isArray(current); 90748 var nextIsArray = Array.isArray(next); 90749 90750 if (currentIsArray && nextIsArray) { 90751 current.push.apply(current, next); 90752 return current; 90753 } 90754 90755 if (currentIsArray) { 90756 current.push(next); 90757 return current; 90758 } 90759 90760 if (nextIsArray) { 90761 // A bit too dangerous to mutate `next`. 90762 return [current].concat(next); 90763 } 90764 90765 return [current, next]; 90766} 90767 90768module.exports = accumulateInto; 90769},{"158":158}],115:[function(_dereq_,module,exports){ 90770/** 90771 * Copyright 2013-present, Facebook, Inc. 90772 * All rights reserved. 90773 * 90774 * This source code is licensed under the BSD-style license found in the 90775 * LICENSE file in the root directory of this source tree. An additional grant 90776 * of patent rights can be found in the PATENTS file in the same directory. 90777 * 90778 * @providesModule adler32 90779 */ 90780 90781 90782 90783var MOD = 65521; 90784 90785// adler32 is not cryptographically strong, and is only used to sanity check that 90786// markup generated on the server matches the markup generated on the client. 90787// This implementation (a modified version of the SheetJS version) has been optimized 90788// for our use case, at the expense of conforming to the adler32 specification 90789// for non-ascii inputs. 90790function adler32(data) { 90791 var a = 1; 90792 var b = 0; 90793 var i = 0; 90794 var l = data.length; 90795 var m = l & ~0x3; 90796 while (i < m) { 90797 var n = Math.min(i + 4096, m); 90798 for (; i < n; i += 4) { 90799 b += (a += data.charCodeAt(i)) + (a += data.charCodeAt(i + 1)) + (a += data.charCodeAt(i + 2)) + (a += data.charCodeAt(i + 3)); 90800 } 90801 a %= MOD; 90802 b %= MOD; 90803 } 90804 for (; i < l; i++) { 90805 b += a += data.charCodeAt(i); 90806 } 90807 a %= MOD; 90808 b %= MOD; 90809 return a | b << 16; 90810} 90811 90812module.exports = adler32; 90813},{}],116:[function(_dereq_,module,exports){ 90814/** 90815 * Copyright 2013-present, Facebook, Inc. 90816 * All rights reserved. 90817 * 90818 * This source code is licensed under the BSD-style license found in the 90819 * LICENSE file in the root directory of this source tree. An additional grant 90820 * of patent rights can be found in the PATENTS file in the same directory. 90821 * 90822 * @providesModule canDefineProperty 90823 */ 90824 90825 90826 90827var canDefineProperty = false;
90828if ("development" !== 'production') { 90829 try { 90830 Object.defineProperty({}, 'x', { get: function () {} }); 90831 canDefineProperty = true; 90832 } catch (x) { 90833 // IE will fail on defineProperty 90834 } 90835} 90836 90837module.exports = canDefineProperty; 90838},{}],117:[function(_dereq_,module,exports){ 90839/** 90840 * Copyright 2013-present, Facebook, Inc. 90841 * All rights reserved. 90842 * 90843 * This source code is licensed under the BSD-style license found in the 90844 * LICENSE file in the root directory of this source tree. An additional grant 90845 * of patent rights can be found in the PATENTS file in the same directory. 90846 * 90847 * @providesModule createMicrosoftUnsafeLocalFunction 90848 */ 90849 90850/* globals MSApp */ 90851 90852 90853 90854/** 90855 * Create a function which has 'unsafe' privileges (required by windows8 apps) 90856 */ 90857 90858var createMicrosoftUnsafeLocalFunction = function (func) { 90859 if (typeof MSApp !== 'undefined' && MSApp.execUnsafeLocalFunction) { 90860 return function (arg0, arg1, arg2, arg3) { 90861 MSApp.execUnsafeLocalFunction(function () { 90862 return func(arg0, arg1, arg2, arg3); 90863 }); 90864 }; 90865 } else { 90866 return func; 90867 } 90868}; 90869 90870module.exports = createMicrosoftUnsafeLocalFunction; 90871},{}],118:[function(_dereq_,module,exports){ 90872/** 90873 * Copyright 2013-present, Facebook, Inc. 90874 * All rights reserved. 90875 * 90876 * This source code is licensed under the BSD-style license found in the 90877 * LICENSE file in the root directory of this source tree. An additional grant 90878 * of patent rights can be found in the PATENTS file in the same directory. 90879 * 90880 * @providesModule dangerousStyleValue 90881 */ 90882 90883 90884 90885var CSSProperty = _dereq_(3); 90886var warning = _dereq_(168); 90887 90888var isUnitlessNumber = CSSProperty.isUnitlessNumber; 90889var styleWarnings = {}; 90890 90891/** 90892 * Convert a value into the proper css writable value. The style name `name` 90893 * should be logical (no hyphens), as specified 90894 * in `CSSProperty.isUnitlessNumber`. 90895 * 90896 * @param {string} name CSS property name such as `topMargin`. 90897 * @param {*} value CSS property value such as `10px`. 90898 * @param {ReactDOMComponent} component 90899 * @return {string} Normalized style value with dimensions applied. 90900 */ 90901function dangerousStyleValue(name, value, component) { 90902 // Note that we've removed escapeTextForBrowser() calls here since the 90903 // whole string will be escaped when the attribute is injected into 90904 // the markup. If you provide unsafe user data here they can inject 90905 // arbitrary CSS which may be problematic (I couldn't repro this): 90906 // https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet 90907 // http://www.thespanner.co.uk/2007/11/26/ultimate-xss-css-injection/ 90908 // This is not an XSS hole but instead a potential CSS injection issue 90909 // which has lead to a greater discussion about how we're going to 90910 // trust URLs moving forward. See #2115901 90911 90912 var isEmpty = value == null || typeof value === 'boolean' || value === ''; 90913 if (isEmpty) { 90914 return ''; 90915 } 90916 90917 var isNonNumeric = isNaN(value); 90918 if (isNonNumeric || value === 0 || isUnitlessNumber.hasOwnProperty(name) && isUnitlessNumber[name]) { 90919 return '' + value; // cast to string 90920 } 90921 90922 if (typeof value === 'string') { 90923 if ("development" !== 'production') { 90924 if (component) { 90925 var owner = component._currentElement._owner; 90926 var ownerName = owner ? owner.getName() : null; 90927 if (ownerName && !styleWarnings[ownerName]) { 90928 styleWarnings[ownerName] = {}; 90929 } 90930 var warned = false; 90931 if (ownerName) { 90932 var warnings = styleWarnings[ownerName]; 90933 warned = warnings[name]; 90934 if (!warned) { 90935 warnings[name] = true; 90936 } 90937 } 90938 if (!warned) { 90939 "development" !== 'production' ? warning(false, 'a `%s` tag (owner: `%s`) was passed a numeric string value ' + 'for CSS property `%s` (value: `%s`) which will be treated ' + 'as a unitless number in a future version of React.', component._currentElement.type, ownerName || 'unknown', name, value) : void 0; 90940 } 90941 } 90942 } 90943 value = value.trim(); 90944 } 90945 return value + 'px'; 90946} 90947 90948module.exports = dangerousStyleValue; 90949},{"168":168,"3":3}],119:[function(_dereq_,module,exports){ 90950/** 90951 * Copyright 2013-present, Facebook, Inc. 90952 * All rights reserved. 90953 * 90954 * This source code is licensed under the BSD-style license found in the 90955 * LICENSE file in the root directory of this source tree. An additional grant 90956 * of patent rights can be found in the PATENTS file in the same directory. 90957 * 90958 * @providesModule escapeTextContentForBrowser 90959 */ 90960 90961 90962 90963var ESCAPE_LOOKUP = { 90964 '&': '&', 90965 '>': '>', 90966 '<': '<', 90967 '"': '"', 90968 '\'': ''' 90969}; 90970 90971var ESCAPE_REGEX = /[&><"']/g; 90972 90973function escaper(match) { 90974 return ESCAPE_LOOKUP[match]; 90975} 90976 90977/** 90978 * Escapes text to prevent scripting attacks. 90979 * 90980 * @param {*} text Text value to escape. 90981 * @return {string} An escaped string. 90982 */ 90983function escapeTextContentForBrowser(text) { 90984 return ('' + text).replace(ESCAPE_REGEX, escaper); 90985} 90986 90987module.exports = escapeTextContentForBrowser; 90988},{}],120:[function(_dereq_,module,exports){ 90989/** 90990 * Copyright 2013-present, Facebook, Inc. 90991 * All rights reserved. 90992 * 90993 * This source code is licensed under the BSD-style license found in the 90994 * LICENSE file in the root directory of this source tree. An additional grant 90995 * of patent rights can be found in the PATENTS file in the same directory. 90996 * 90997 * @providesModule findDOMNode 90998 */ 90999 91000 91001 91002var ReactCurrentOwner = _dereq_(35); 91003var ReactDOMComponentTree = _dereq_(40); 91004var ReactInstanceMap = _dereq_(71); 91005 91006var getNativeComponentFromComposite = _dereq_(128); 91007var invariant = _dereq_(158); 91008var warning = _dereq_(168); 91009 91010/** 91011 * Returns the DOM node rendered by this element. 91012 * 91013 * @param {ReactComponent|DOMElement} componentOrElement 91014 * @return {?DOMElement} The root node of this element. 91015 */ 91016function findDOMNode(componentOrElement) { 91017 if ("development" !== 'production') { 91018 var owner = ReactCurrentOwner.current; 91019 if (owner !== null) { 91020 "development" !== 'production' ? warning(owner._warnedAboutRefsInRender, '%s is accessing findDOMNode inside its render(). ' + 'render() should be a pure function of props and state. It should ' + 'never access something that requires stale data from the previous ' + 'render, such as refs. Move this logic to componentDidMount and ' + 'componentDidUpdate instead.', owner.getName() || 'A c
91020omponent') : void 0; 91021 owner._warnedAboutRefsInRender = true; 91022 } 91023 } 91024 if (componentOrElement == null) { 91025 return null; 91026 } 91027 if (componentOrElement.nodeType === 1) { 91028 return componentOrElement; 91029 } 91030 91031 var inst = ReactInstanceMap.get(componentOrElement); 91032 if (inst) { 91033 inst = getNativeComponentFromComposite(inst); 91034 return inst ? ReactDOMComponentTree.getNodeFromInstance(inst) : null; 91035 } 91036 91037 if (typeof componentOrElement.render === 'function') { 91038 !false ? "development" !== 'production' ? invariant(false, 'findDOMNode was called on an unmounted component.') : invariant(false) : void 0; 91039 } else { 91040 !false ? "development" !== 'production' ? invariant(false, 'Element appears to be neither ReactComponent nor DOMNode (keys: %s)', Object.keys(componentOrElement)) : invariant(false) : void 0; 91041 } 91042} 91043 91044module.exports = findDOMNode; 91045},{"128":128,"158":158,"168":168,"35":35,"40":40,"71":71}],121:[function(_dereq_,module,exports){ 91046/** 91047 * Copyright 2013-present, Facebook, Inc. 91048 * All rights reserved. 91049 * 91050 * This source code is licensed under the BSD-style license found in the 91051 * LICENSE file in the root directory of this source tree. An additional grant 91052 * of patent rights can be found in the PATENTS file in the same directory. 91053 * 91054 * @providesModule flattenChildren 91055 */ 91056 91057 91058 91059var KeyEscapeUtils = _dereq_(23); 91060var traverseAllChildren = _dereq_(141); 91061var warning = _dereq_(168); 91062 91063/** 91064 * @param {function} traverseContext Context passed through traversal. 91065 * @param {?ReactComponent} child React child component. 91066 * @param {!string} name String name of key path to child. 91067 */ 91068function flattenSingleChildIntoContext(traverseContext, child, name) { 91069 // We found a component instance. 91070 var result = traverseContext; 91071 var keyUnique = result[name] === undefined; 91072 if ("development" !== 'production') { 91073 "development" !== 'production' ? warning(keyUnique, 'flattenChildren(...): Encountered two children with the same key, ' + '`%s`. Child keys must be unique; when two children share a key, only ' + 'the first child will be used.', KeyEscapeUtils.unescape(name)) : void 0; 91074 } 91075 if (keyUnique && child != null) { 91076 result[name] = child; 91077 } 91078} 91079 91080/** 91081 * Flattens children that are typically specified as `props.children`. Any null 91082 * children will not be included in the resulting object. 91083 * @return {!object} flattened children keyed by name. 91084 */ 91085function flattenChildren(children) { 91086 if (children == null) { 91087 return children; 91088 } 91089 var result = {}; 91090 traverseAllChildren(children, flattenSingleChildIntoContext, result); 91091 return result; 91092} 91093 91094module.exports = flattenChildren; 91095},{"141":141,"168":168,"23":23}],122:[function(_dereq_,module,exports){ 91096/** 91097 * Copyright 2013-present, Facebook, Inc. 91098 * All rights reserved. 91099 * 91100 * This source code is licensed under the BSD-style license found in the 91101 * LICENSE file in the root directory of this source tree. An additional grant 91102 * of patent rights can be found in the PATENTS file in the same directory. 91103 * 91104 * @providesModule forEachAccumulated 91105 */ 91106 91107 91108 91109/** 91110 * @param {array} arr an "accumulation" of items which is either an Array or 91111 * a single item. Useful when paired with the `accumulate` module. This is a 91112 * simple utility that allows us to reason about a collection of items, but 91113 * handling the case when there is exactly one item (and we do not need to 91114 * allocate an array). 91115 */ 91116 91117var forEachAccumulated = function (arr, cb, scope) { 91118 if (Array.isArray(arr)) { 91119 arr.forEach(cb, scope); 91120 } else if (arr) { 91121 cb.call(scope, arr); 91122 } 91123}; 91124 91125module.exports = forEachAccumulated; 91126},{}],123:[function(_dereq_,module,exports){ 91127/** 91128 * Copyright 2013-present, Facebook, Inc. 91129 * All rights reserved. 91130 * 91131 * This source code is licensed under the BSD-style license found in the 91132 * LICENSE file in the root directory of this source tree. An additional grant 91133 * of patent rights can be found in the PATENTS file in the same directory. 91134 * 91135 * @providesModule getEventCharCode 91136 */ 91137 91138 91139 91140/** 91141 * `charCode` represents the actual "character code" and is safe to use with 91142 * `String.fromCharCode`. As such, only keys that correspond to printable 91143 * characters produce a valid `charCode`, the only exception to this is Enter. 91144 * The Tab-key is considered non-printable and does not have a `charCode`, 91145 * presumably because it does not produce a tab-character in browsers. 91146 * 91147 * @param {object} nativeEvent Native browser event. 91148 * @return {number} Normalized `charCode` property. 91149 */ 91150
91151function getEventCharCode(nativeEvent) { 91152 var charCode; 91153 var keyCode = nativeEvent.keyCode; 91154 91155 if ('charCode' in nativeEvent) { 91156 charCode = nativeEvent.charCode; 91157 91158 // FF does not set `charCode` for the Enter-key, check against `keyCode`. 91159 if (charCode === 0 && keyCode === 13) { 91160 charCode = 13; 91161 } 91162 } else { 91163 // IE8 does not implement `charCode`, but `keyCode` has the correct value. 91164 charCode = keyCode; 91165 } 91166 91167 // Some non-printable keys are reported in `charCode`/`keyCode`, discard them. 91168 // Must not discard the (non-)printable Enter-key. 91169 if (charCode >= 32 || charCode === 13) { 91170 return charCode; 91171 } 91172 91173 return 0; 91174} 91175 91176module.exports = getEventCharCode; 91177},{}],124:[function(_dereq_,module,exports){ 91178/** 91179 * Copyright 2013-present, Facebook, Inc. 91180 * All rights reserved. 91181 * 91182 * This source code is licensed under the BSD-style license found in the 91183 * LICENSE file in the root directory of this source tree. An additional grant 91184 * of patent rights can be found in the PATENTS file in the same directory. 91185 * 91186 * @providesModule getEventKey 91187 */ 91188 91189 91190 91191var getEventCharCode = _dereq_(123); 91192 91193/** 91194 * Normalization of deprecated HTML5 `key` values 91195 * @see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent#Key_names 91196 */ 91197var normalizeKey = { 91198 'Esc': 'Escape', 91199 'Spacebar': ' ', 91200 'Left': 'ArrowLeft', 91201 'Up': 'ArrowUp', 91202 'Right': 'ArrowRight', 91203 'Down': 'ArrowDown', 91204 'Del': 'Delete', 91205 'Win': 'OS', 91206 'Menu': 'ContextMenu', 91207 'Apps': 'ContextMenu', 91208 'Scroll': 'ScrollLock', 91209 'MozPrintableKey': 'Unidentified' 91210}; 91211 91212/** 91213 * Translation from legacy `keyCode` to HTML5 `key` 91214 * Only special keys supported, all others depend on keyboard layout or browser 91215 * @see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent#Key_names 91216 */ 91217var translateToKey = { 91218 8: 'Backspace', 91219 9: 'Tab', 91220 12: 'Clear', 91221 13: 'Enter', 91222 16: 'Shift', 91223 17: 'Control', 91224 18: 'Alt', 91225 19: 'Pause', 91226 20: 'CapsLock', 91227 27: 'Escape', 91228 32: ' ', 91229 33: 'PageUp', 91230 34: 'PageDown', 91231 35: 'End', 91232 36: 'Home', 91233 37: 'ArrowLeft', 91234 38: 'ArrowUp', 91235 39: 'ArrowRight', 91236 40: 'ArrowDown', 91237 45: 'Insert', 91238 46: 'Delete', 91239 112: 'F1', 113: 'F2', 114: 'F3', 115: 'F4', 116: 'F5', 117: 'F6', 91240 118: 'F7', 119: 'F8', 120: 'F9', 121: 'F10', 122: 'F11', 123: 'F12', 91241 144: 'NumLock', 91242 145: 'ScrollLock', 91243 224: 'Meta' 91244}; 91245 91246/** 91247 * @param {object} nativeEvent Native browser event. 91248 * @return {string} Normalized `key` property. 91249 */ 91250function getEventKey(nativeEvent) { 91251 if (nativeEvent.key) { 91252 // Normalize inconsistent values reported by browsers due to 91253 // implementations of a working draft specification. 91254 91255 // FireFox implements `key` but returns `MozPrintableKey` for all 91256 // printable characters (normalized to `Unidentified`), ignore it. 91257 var key = normalizeKey[nativeEvent.key] || nativeEvent.key; 91258 if (key !== 'Unidentified') { 91259 return key; 91260 } 91261 } 91262 91263 // Browser does not implement `key`, polyfill as much of it as we can. 91264 if (nativeEvent.type === 'keypress') { 91265 var charCode = getEventCharCode(nativeEvent); 91266 91267 // The enter-key is technically both printable and non-printable and can 91268 // thus be captured by `keypress`, no other non-printable key should. 91269 return charCode === 13 ? 'Enter' : String.fromCharCode(charCode); 91270 } 91271 if (nativeEvent.type === 'keydown' || nativeEvent.type === 'keyup') { 91272 // While user keyboard layout determines the actual meaning of each 91273 // `keyCode` value, almost all function keys have a universal value. 91274 return translateToKey[nativeEvent.keyCode] || 'Unidentified'; 91275 } 91276 return ''; 91277} 91278 91279module.exports = getEventKey; 91280},{"123":123}],125:[function(_dereq_,module,exports){ 91281/** 91282 * Copyright 2013-present, Facebook, Inc. 91283 * All rights reserved. 91284 * 91285 * This source code is licensed under the BSD-style license found in the 91286 * LICENSE file in the root directory of this source tree. An additional grant 91287 * of patent rights can be found in the PATENTS file in the same directory. 91288 * 91289 * @providesModule getEventModifierState 91290 */ 91291 91292 91293 91294/** 91295 * Translation from modifier key to the associated property in the event. 91296 * @see http://www.w3.org/TR/DOM-Level-3-Events/#keys-Modifiers 91297 */ 91298 91299var modifierKeyToProp = { 91300 'Alt': 'altKey', 91301 'Control': 'ctrlKey', 91302 'Meta': 'metaKey', 91303 'Shift': 'shiftKey' 91304}; 91305 91306// IE8 does not implement getModifierState so we simply map it to the only 91307// modifier keys exposed by the event itself, does not support Lock-keys. 91308// Currently, all major browsers except Chrome seems to support Lock-keys. 91309function modifierStateGetter(keyArg) { 91310 var syntheticEvent = this; 91311 var nativeEvent = syntheticEvent.nativeEvent; 91312 if (nativeEvent.getModifierState) { 91313 return nativeEvent.getModifierState(keyArg); 91314 } 91315 var keyProp = modifierKeyToProp[keyArg];
91316 return keyProp ? !!nativeEvent[keyProp] : false; 91317} 91318 91319function getEventModifierState(nativeEvent) { 91320 return modifierStateGetter; 91321} 91322 91323module.exports = getEventModifierState; 91324},{}],126:[function(_dereq_,module,exports){ 91325/** 91326 * Copyright 2013-present, Facebook, Inc. 91327 * All rights reserved. 91328 * 91329 * This source code is licensed under the BSD-style license found in the 91330 * LICENSE file in the root directory of this source tree. An additional grant 91331 * of patent rights can be found in the PATENTS file in the same directory. 91332 * 91333 * @providesModule getEventTarget 91334 */ 91335 91336 91337 91338/** 91339 * Gets the target node from a native browser event by accounting for 91340 * inconsistencies in browser DOM APIs. 91341 * 91342 * @param {object} nativeEvent Native browser event. 91343 * @return {DOMEventTarget} Target node. 91344 */ 91345 91346function getEventTarget(nativeEvent) { 91347 var target = nativeEvent.target || nativeEvent.srcElement || window; 91348 91349 // Normalize SVG <use> element events #4963 91350 if (target.correspondingUseElement) { 91351 target = target.correspondingUseElement; 91352 } 91353 91354 // Safari may fire events on text nodes (Node.TEXT_NODE is 3). 91355 // @see http://www.quirksmode.org/js/events_properties.html 91356 return target.nodeType === 3 ? target.parentNode : target; 91357} 91358 91359module.exports = getEventTarget; 91360},{}],127:[function(_dereq_,module,exports){ 91361/** 91362 * Copyright 2013-present, Facebook, Inc. 91363 * All rights reserved. 91364 * 91365 * This source code is licensed under the BSD-style license found in the 91366 * LICENSE file in the root directory of this source tree. An additional grant 91367 * of patent rights can be found in the PATENTS file in the same directory. 91368 * 91369 * @providesModule getIteratorFn 91370 */ 91371 91372 91373 91374/* global Symbol */ 91375 91376var ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator; 91377var FAUX_ITERATOR_SYMBOL = '@@iterator'; // Before Symbol spec. 91378 91379/** 91380 * Returns the iterator method function contained on the iterable object. 91381 * 91382 * Be sure to invoke the function with the iterable as context: 91383 * 91384 * var iteratorFn = getIteratorFn(myIterable); 91385 * if (iteratorFn) { 91386 * var iterator = iteratorFn.call(myIterable); 91387 * ... 91388 * } 91389 * 91390 * @param {?object} maybeIterable 91391 * @return {?function} 91392 */ 91393function getIteratorFn(maybeIterable) { 91394 var iteratorFn = maybeIterable && (ITERATOR_SYMBOL && maybeIterable[ITERATOR_SYMBOL] || maybeIterable[FAUX_ITERATOR_SYMBOL]); 91395 if (typeof iteratorFn === 'function') { 91396 return iteratorFn; 91397 } 91398} 91399 91400module.exports = getIteratorFn; 91401},{}],128:[function(_dereq_,module,exports){ 91402/** 91403 * Copyright 2013-present, Facebook, Inc. 91404 * All rights reserved. 91405 * 91406 * This source code is licensed under the BSD-style license found in the 91407 * LICENSE file in the root directory of this source tree. An additional grant 91408 * of patent rights can be found in the PATENTS file in the same directory. 91409 * 91410 * @providesModule getNativeComponentFromComposite 91411 */ 91412 91413 91414 91415var ReactNodeTypes = _dereq_(79); 91416 91417function getNativeComponentFromComposite(inst) { 91418 var type; 91419 91420 while ((type = inst._renderedNodeType) === ReactNodeTypes.COMPOSITE) { 91421 inst = inst._renderedComponent; 91422 } 91423 91424 if (type === ReactNodeTypes.NATIVE) { 91425 return inst._renderedComponent; 91426 } else if (type === ReactNodeTypes.EMPTY) { 91427 return null; 91428 } 91429} 91430 91431module.exports = getNativeComponentFromComposite; 91432},{"79":79}],129:[function(_dereq_,module,exports){ 91433/** 91434 * Copyright 2013-present, Facebook, Inc. 91435 * All rights reserved. 91436 * 91437 * This source code is licensed under the BSD-style license found in the 91438 * LICENSE file in the root directory of this source tree. An additional grant 91439 * of patent rights can be found in the PATENTS file in the same directory. 91440 * 91441 * @providesModule getNodeForCharacterOffset 91442 */ 91443 91444 91445 91446/** 91447 * Given any node return the first leaf node without children. 91448 * 91449 * @param {DOMElement|DOMTextNode} node 91450 * @return {DOMElement|DOMTextNode} 91451 */ 91452 91453function getLeafNode(node) { 91454 while (node && node.firstChild) { 91455 node = node.firstChild; 91456 } 91457 return node; 91458} 91459 91460/** 91461 * Get the next sibling within a container. This will walk up the 91462 * DOM if a node's siblings have been exhausted. 91463 * 91464 * @param {DOMElement|DOMTextNode} node 91465 * @return {?DOMElement|DOMTextNode} 91466 */ 91467function getSiblingNode(node) { 91468 while (node) { 91469 if (node.nextSibling) { 91470 return node.nextSibling; 91471 } 91472 node = node.parentNode; 91473 } 91474} 91475 91476/** 91477 * Get object describing the nodes which contain characters at offset. 91478 * 91479 * @param {DOMElement|DOMTextNode} root 91480 * @param {number} offset 91481 * @return {?object} 91482 */ 91483function getNodeForCharacterOffset(root, offset) { 91484 var node = getLeafNode(root); 91485 var nodeStart = 0; 91486 var nodeEnd = 0; 91487 91488 while (node) { 91489 if (node.nodeType === 3) { 91490 nodeEnd = nodeStart + node.textContent.length; 91491 91492 if (nodeStart <= offset && nodeEnd >= offset) { 91493 return { 91494 node: node, 91495 offset: offset - nodeStart 91496 }; 91497 } 91498 91499 nodeStart = nodeEnd; 91500 } 91501 91502 node = getLeafNode(getSiblingNode(node)); 91503 } 91504} 91505 91506module.exports = getNodeForCharacterOffset; 91507},{}],130:[function(_dereq_,module,exports){ 91508/** 91509 * Copyright 2013-present, Facebook, Inc. 91510 * All rights reserved. 91511 * 91512 * This source code is licensed under the BSD-style license found in the 91513 * LICENSE file in the root directory of this source tree. An additional grant 91514 * of patent rights can be found in the PATENTS file in the same directory. 91515 * 91516 * @providesModule getTextContentAccessor 91517 */ 91518 91519 91520 91521var ExecutionEnvironment = _dereq_(144); 91522
91523var contentKey = null; 91524 91525/** 91526 * Gets the key used to access text content on a DOM node. 91527 * 91528 * @return {?string} Key used to access text content. 91529 * @internal 91530 */ 91531function getTextContentAccessor() { 91532 if (!contentKey && ExecutionEnvironment.canUseDOM) { 91533 // Prefer textContent to innerText because many browsers support both but 91534 // SVG <text> elements don't support innerText even when <div> does. 91535 contentKey = 'textContent' in document.documentElement ? 'textContent' : 'innerText'; 91536 } 91537 return contentKey; 91538} 91539 91540module.exports = getTextContentAccessor; 91541},{"144":144}],131:[function(_dereq_,module,exports){ 91542/** 91543 * Copyright 2013-present, Facebook, Inc. 91544 * All rights reserved. 91545 * 91546 * This source code is licensed under the BSD-style license found in the 91547 * LICENSE file in the root directory of this source tree. An additional grant 91548 * of patent rights can be found in the PATENTS file in the same directory. 91549 * 91550 * @providesModule getVendorPrefixedEventName 91551 */ 91552 91553 91554 91555var ExecutionEnvironment = _dereq_(144); 91556 91557/** 91558 * Generate a mapping of standard vendor prefixes using the defined style property and event name. 91559 * 91560 * @param {string} styleProp 91561 * @param {string} eventName 91562 * @returns {object} 91563 */ 91564function makePrefixMap(styleProp, eventName) { 91565 var prefixes = {}; 91566 91567 prefixes[styleProp.toLowerCase()] = eventName.toLowerCase(); 91568 prefixes['Webkit' + styleProp] = 'webkit' + eventName; 91569 prefixes['Moz' + styleProp] = 'moz' + eventName; 91570 prefixes['ms' + styleProp] = 'MS' + eventName; 91571 prefixes['O' + styleProp] = 'o' + eventName.toLowerCase(); 91572 91573 return prefixes; 91574} 91575 91576/** 91577 * A list of event names to a configurable list of vendor prefixes. 91578 */ 91579var vendorPrefixes = { 91580 animationend: makePrefixMap('Animation', 'AnimationEnd'), 91581 animationiteration: makePrefixMap('Animation', 'AnimationIteration'), 91582 animationstart: makePrefixMap('Animation', 'AnimationStart'), 91583 transitionend: makePrefixMap('Transition', 'TransitionEnd') 91584}; 91585 91586/** 91587 * Event names that have already been detected and prefixed (if applicable). 91588 */ 91589var prefixedEventNames = {}; 91590 91591/** 91592 * Element to check for prefixes on. 91593 */ 91594var style = {}; 91595 91596/** 91597 * Bootstrap if a DOM exists. 91598 */ 91599if (ExecutionEnvironment.canUseDOM) { 91600 style = document.createElement('div').style; 91601 91602 // On some platforms, in particular some releases of Android 4.x, 91603 // the un-prefixed "animation" and "transition" properties are defined on the 91604 // style object but the events that fire will still be prefixed, so we need 91605 // to check if the un-prefixed events are usable, and if not remove them from the map. 91606 if (!('AnimationEvent' in window)) { 91607 delete vendorPrefixes.animationend.animation; 91608 delete vendorPrefixes.animationiteration.animation; 91609 delete vendorPrefixes.animationstart.animation; 91610 } 91611 91612 // Same as above 91613 if (!('TransitionEvent' in window)) { 91614 delete vendorPrefixes.transitionend.transition; 91615 } 91616} 91617 91618/** 91619 * Attempts to determine the correct vendor prefixed event name. 91620 * 91621 * @param {string} eventName 91622 * @returns {string} 91623 */ 91624function getVendorPrefixedEventName(eventName) { 91625 if (prefixedEventNames[eventName]) { 91626 return prefixedEventNames[eventName]; 91627 } else if (!vendorPrefixes[eventName]) { 91628 return eventName; 91629 } 91630 91631 var prefixMap = vendorPrefixes[eventName]; 91632 91633 for (var styleProp in prefixMap) { 91634 if (prefixMap.hasOwnProperty(styleProp) && styleProp in style) { 91635 return prefixedEventNames[eventName] = prefixMap[styleProp]; 91636 } 91637 } 91638 91639 return ''; 91640} 91641 91642module.exports = getVendorPrefixedEventName; 91643},{"144":144}],132:[function(_dereq_,module,exports){ 91644/** 91645 * Copyright 2013-present, Facebook, Inc. 91646 * All rights reserved. 91647 * 91648 * This source code is licensed under the BSD-style license found in the 91649 * LICENSE file in the root directory of this source tree. An additional grant 91650 * of patent rights can be found in the PATENTS file in the same directory. 91651 * 91652 * @providesModule instantiateReactComponent 91653 */ 91654 91655 91656 91657var _assign = _dereq_(169); 91658 91659var ReactCompositeComponent = _dereq_(34); 91660var ReactEmptyComponent = _dereq_(64); 91661var ReactNativeComponent = _dereq_(78); 91662 91663var invariant = _dereq_(158); 91664var warning = _dereq_(168); 91665 91666// To avoid a cyclic dependency, we create the final class in this module 91667var ReactCompositeComponentWrapper = function (element) { 91668 this.construct(element); 91669}; 91670_assign(ReactCompositeComponentWrapper.prototype, ReactCompositeComponent.Mixin, { 91671 _instantiateReactComponent: instantiateReactComponent 91672}); 91673 91674function getDeclarationErrorAddendum(owner) { 91675 if (owner) { 91676 var name = owner.getName(); 91677 if (name) { 91678 return ' Check the render method of `' + name + '`.'; 91679 } 91680 } 91681 return ''; 91682} 91683 91684/** 91685 * Check if the type reference is a known internal type. I.e. not a user 91686 * provided composite type. 91687 * 91688 * @param {function} type 91689 * @return {boolean} Returns true if this is a valid internal type. 91690 */ 91691function isInternalComponentType(type) { 91692 return typeof type === 'function' && typeof type.prototype !== 'undefined' && typeof type.prototype.mountComponent === 'function' && typeof type.prototype.receiveComponent === 'function'; 91693} 91694 91695/** 91696 * Given a ReactNode, create an instance that will actually be mounted. 91697 * 91698 * @param {ReactNode} node 91699 * @return {object} A new instance of the element's constructor. 91700 * @protected 91701 */ 91702function instantiateReactComponent(node) { 91703 var instance; 91704 91705 if (node === null || node === false) { 91706 instance = ReactEmptyComponent.create(instantiateReactComponent); 91707 } else if (typeof node === 'object') { 91708 var element = node; 91709 !(element && (typeof element.type === 'function' || typeof element.type === 'string')) ? "development" !== 'production' ? invariant(false, 'Element type is invali
91709d: expected a string (for built-in components) ' + 'or a class/function (for composite components) but got: %s.%s', element.type == null ? element.type : typeof element.type, getDeclarationErrorAddendum(element._owner)) : invariant(false) : void 0; 91710 91711 // Special case string values 91712 if (typeof element.type === 'string') { 91713 instance = ReactNativeComponent.createInternalComponent(element); 91714 } else if (isInternalComponentType(element.type)) { 91715 // This is temporarily available for custom components that are not string 91716 // representations. I.e. ART. Once those are updated to use the string 91717 // representation, we can drop this code path. 91718 instance = new element.type(element); 91719 } else { 91720 instance = new ReactCompositeComponentWrapper(element); 91721 } 91722 } else if (typeof node === 'string' || typeof node === 'number') { 91723 instance = ReactNativeComponent.createInstanceForText(node); 91724 } else { 91725 !false ? "development" !== 'production' ? invariant(false, 'Encountered invalid React node of type %s', typeof node) : invariant(false) : void 0; 91726 } 91727 91728 if ("development" !== 'production') { 91729 "development" !== 'production' ? warning(typeof instance.mountComponent === 'function' && typeof instance.receiveComponent === 'function' && typeof instance.getNativeNode === 'function' && typeof instance.unmountComponent === 'function', 'Only React Components can be mounted.') : void 0; 91730 } 91731 91732 // These two fields are used by the DOM and ART diffing algorithms 91733 // respectively. Instead of using expandos on components, we should be 91734 // storing the state needed by the diffing algorithms elsewhere. 91735 instance._mountIndex = 0; 91736 instance._mountImage = null; 91737 91738 if ("development" !== 'production') { 91739 instance._isOwnerNecessary = false; 91740 instance._warnedAboutRefsInRender = false;
91741 } 91742 91743 // Internal instances should fully constructed at this point, so they should 91744 // not get any new fields added to them at this point. 91745 if ("development" !== 'production') { 91746 if (Object.preventExtensions) { 91747 Object.preventExtensions(instance); 91748 } 91749 } 91750 91751 return instance; 91752} 91753 91754module.exports = instantiateReactComponent; 91755},{"158":158,"168":168,"169":169,"34":34,"64":64,"78":78}],133:[function(_dereq_,module,exports){ 91756/** 91757 * Copyright 2013-present, Facebook, Inc. 91758 * All rights reserved. 91759 * 91760 * This source code is licensed under the BSD-style license found in the 91761 * LICENSE file in the root directory of this source tree. An additional grant 91762 * of patent rights can be found in the PATENTS file in the same directory. 91763 * 91764 * @providesModule isEventSupported 91765 */ 91766 91767 91768 91769var ExecutionEnvironment = _dereq_(144); 91770 91771var useHasFeature; 91772if (ExecutionEnvironment.canUseDOM) { 91773 useHasFeature = document.implementation && document.implementation.hasFeature && 91774 // always returns true in newer browsers as per the standard. 91775 // @see http://dom.spec.whatwg.org/#dom-domimplementation-hasfeature 91776 document.implementation.hasFeature('', '') !== true; 91777} 91778 91779/** 91780 * Checks if an event is supported in the current execution environment. 91781 * 91782 * NOTE: This will not work correctly for non-generic events such as `change`, 91783 * `reset`, `load`, `error`, and `select`. 91784 * 91785 * Borrows from Modernizr. 91786 * 91787 * @param {string} eventNameSuffix Event name, e.g. "click". 91788 * @param {?boolean} capture Check if the capture phase is supported. 91789 * @return {boolean} True if the event is supported. 91790 * @internal 91791 * @license Modernizr 3.0.0pre (Custom Build) | MIT 91792 */ 91793function isEventSupported(eventNameSuffix, capture) { 91794 if (!ExecutionEnvironment.canUseDOM || capture && !('addEventListener' in document)) { 91795 return false; 91796 } 91797 91798 var eventName = 'on' + eventNameSuffix; 91799 var isSupported = eventName in document; 91800 91801 if (!isSupported) { 91802 var element = document.createElement('div'); 91803 element.setAttribute(eventName, 'return;'); 91804 isSupported = typeof element[eventName] === 'function'; 91805 } 91806 91807 if (!isSupported && useHasFeature && eventNameSuffix === 'wheel') { 91808 // This is the only way to test support for the `wheel` event in IE9+. 91809 isSupported = document.implementation.hasFeature('Events.wheel', '3.0'); 91810 } 91811 91812 return isSupported; 91813} 91814 91815module.exports = isEventSupported; 91816},{"144":144}],134:[function(_dereq_,module,exports){ 91817/** 91818 * Copyright 2013-present, Facebook, Inc. 91819 * All rights reserved. 91820 * 91821 * This source code is licensed under the BSD-style license found in the 91822 * LICENSE file in the root directory of this source tree. An additional grant 91823 * of patent rights can be found in the PATENTS file in the same directory. 91824 * 91825 * @providesModule isTextInputElement 91826 */ 91827 91828 91829 91830/** 91831 * @see http://www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html#input-type-attr-summary 91832 */ 91833 91834var supportedInputTypes = { 91835 'color': true, 91836 'date': true, 91837 'datetime': true, 91838 'datetime-local': true, 91839 'email': true, 91840 'month': true, 91841 'number': true, 91842 'password': true, 91843 'range': true, 91844 'search': true, 91845 'tel': true, 91846 'text': true, 91847 'time': true, 91848 'url': true, 91849 'week': true 91850}; 91851 91852function isTextInputElement(elem) { 91853 var nodeName = elem && elem.nodeName && elem.nodeName.toLowerCase(); 91854 return nodeName && (nodeName === 'input' && supportedInputTypes[elem.type] || nodeName === 'textarea'); 91855} 91856 91857module.exports = isTextInputElement; 91858},{}],135:[function(_dereq_,module,exports){ 91859/** 91860 * Copyright 2013-present, Facebook, Inc. 91861 * All rights reserved. 91862 * 91863 * This source code is licensed under the BSD-style license found in the 91864 * LICENSE file in the root directory of this source tree. An additional grant 91865 * of patent rights can be found in the PATENTS file in the same directory. 91866 * 91867 * @providesModule onlyChild 91868 */ 91869 91870 91871var ReactElement = _dereq_(62); 91872 91873var invariant = _dereq_(158); 91874 91875/** 91876 * Returns the first child in a collection of children and verifies that there 91877 * is only one child in the collection. The current implementation of this 91878 * function assumes that a single child gets passed without a wrapper, but the 91879 * purpose of this helper function is to abstract away the particular structure 91880 * of children. 91881 * 91882 * @param {?object} children Child collection structure. 91883 * @return {ReactElement} The first and only `ReactElement` contained in the 91884 * structure. 91885 */ 91886function onlyChild(children) { 91887 !ReactElement.isValidElement(children) ? "development" !== 'production' ? invariant(false, 'onlyChild must be passed a children with exactly one child.') : invariant(false) : void 0; 91888 return children; 91889} 91890 91891module.exports = onlyChild; 91892},{"158":158,"62":62}],136:[function(_dereq_,module,exports){ 91893/** 91894 * Copyright 2013-present, Facebook, Inc. 91895 * All rights reserved. 91896 * 91897 * This source code is licensed under the BSD-style license found in the 91898 * LICENSE file in the root directory of this source tree. An additional grant 91899 * of patent rights can be found in the PATENTS file in the same directory. 91900 * 91901 * @providesModule quoteAttributeValueForBrowser 91902 */ 91903 91904 91905 91906var escapeTextContentForBrowser = _dereq_(119); 91907 91908/** 91909 * Escapes attribute value to prevent scripting attacks. 91910 * 91911 * @param {*} value Value to escape. 91912 * @return {string} An escaped string. 91913 */ 91914function quoteAttributeValueForBrowser(value) { 91915 return '"' + escapeTextContentForBrowser(value) + '"'; 91916} 91917 91918module.exports = quoteAttributeValueForBrowser; 91919},{"119":119}],137:[function(_dereq_,module,exports){ 91920/** 91921 * Copyright 2013-present, Facebook, Inc. 91922 * All rights reserved. 91923 * 91924 * This source code is licensed under the BSD-style license found in the 91925 * LICENSE file in the root directory of this source tree. An additional grant 91926 * of patent rights can be found in the PATENTS file in the same directory. 91927 * 91928* @providesModule renderSubtreeIntoContainer 91929*/ 91930 91931 91932 91933var ReactMount = _dereq_(75); 91934
91935module.exports = ReactMount.renderSubtreeIntoContainer; 91936},{"75":75}],138:[function(_dereq_,module,exports){ 91937/** 91938 * Copyright 2013-present, Facebook, Inc. 91939 * All rights reserved. 91940 * 91941 * This source code is licensed under the BSD-style license found in the 91942 * LICENSE file in the root directory of this source tree. An additional grant 91943 * of patent rights can be found in the PATENTS file in the same directory. 91944 * 91945 * @providesModule setInnerHTML 91946 */ 91947 91948 91949 91950var ExecutionEnvironment = _dereq_(144); 91951 91952var WHITESPACE_TEST = /^[ \r\n\t\f]/; 91953var NONVISIBLE_TEST = /<(!--|link|noscript|meta|script|style)[ \r\n\t\f\/>]/; 91954 91955var createMicrosoftUnsafeLocalFunction = _dereq_(117); 91956 91957/** 91958 * Set the innerHTML property of a node, ensuring that whitespace is preserved 91959 * even in IE8. 91960 * 91961 * @param {DOMElement} node 91962 * @param {string} html 91963 * @internal 91964 */ 91965var setInnerHTML = createMicrosoftUnsafeLocalFunction(function (node, html) { 91966 node.innerHTML = html; 91967}); 91968 91969if (ExecutionEnvironment.canUseDOM) { 91970 // IE8: When updating a just created node with innerHTML only leading 91971 // whitespace is removed. When updating an existing node with innerHTML 91972 // whitespace in root TextNodes is also collapsed. 91973 // @see quirksmode.org/bugreports/archives/2004/11/innerhtml_and_t.html 91974 91975 // Feature detection; only IE8 is known to behave improperly like this. 91976 var testElement = document.createElement('div'); 91977 testElement.innerHTML = ' '; 91978 if (testElement.innerHTML === '') { 91979 setInnerHTML = function (node, html) { 91980 // Magic theory: IE8 supposedly differentiates between added and updated 91981 // nodes when processing innerHTML, innerHTML on updated nodes suffers 91982 // from worse whitespace behavior. Re-adding a node like this triggers 91983 // the initial and more favorable whitespace behavior. 91984 // TODO: What to do on a detached node? 91985 if (node.parentNode) { 91986 node.parentNode.replaceChild(node, node); 91987 } 91988 91989 // We also implement a workaround for non-visible tags disappearing into 91990 // thin air on IE8, this only happens if there is no visible text 91991 // in-front of the non-visible tags. Piggyback on the whitespace fix 91992 // and simply check if any non-visible tags appear in the source. 91993 if (WHITESPACE_TEST.test(html) || html[0] === '<' && NONVISIBLE_TEST.test(html)) { 91994 // Recover leading whitespace by temporarily prepending any character. 91995 // \uFEFF has the potential advantage of being zero-width/invisible. 91996 // UglifyJS drops U+FEFF chars when parsing, so use String.fromCharCode 91997 // in hopes that this is preserved even if "\uFEFF" is transformed to 91998 // the actual Unicode character (by Babel, for example). 91999 // https://github.com/mishoo/UglifyJS2/blob/v2.4.20/lib/parse.js#L216 92000 node.innerHTML = String.fromCharCode(0xFEFF) + html; 92001 92002 // deleteData leaves an empty `TextNode` which offsets the index of all 92003 // children. Definitely want to avoid this. 92004 var textNode = node.firstChild; 92005 if (textNode.data.length === 1) { 92006 node.removeChild(textNode); 92007 } else { 92008 textNode.deleteData(0, 1); 92009 } 92010 } else { 92011 node.innerHTML = html; 92012 } 92013 }; 92014 } 92015 testElement = null; 92016} 92017 92018module.exports = setInnerHTML; 92019},{"117":117,"144":144}],139:[function(_dereq_,module,exports){ 92020/** 92021 * Copyright 2013-present, Facebook, Inc. 92022 * All rights reserved. 92023 * 92024 * This source code is licensed under the BSD-style license found in the 92025 * LICENSE file in the root directory of this source tree. An additional grant 92026 * of patent rights can be found in the PATENTS file in the same directory. 92027 * 92028 * @providesModule setTextContent 92029 */ 92030 92031 92032 92033var ExecutionEnvironment = _dereq_(144); 92034var escapeTextContentForBrowser = _dereq_(119); 92035var setInnerHTML = _dereq_(138); 92036 92037/** 92038 * Set the textContent property of a node, ensuring that whitespace is preserved 92039 * even in IE8. innerText is a poor substitute for textContent and, among many 92040 * issues, inserts <br> instead of the literal newline chars. innerHTML behaves 92041 * as it should. 92042 * 92043 * @param {DOMElement} node 92044 * @param {string} text 92045 * @internal 92046 */ 92047var setTextContent = function (node, text) { 92048 node.textContent = text; 92049}; 92050 92051if (ExecutionEnvironment.canUseDOM) { 92052 if (!('textContent' in document.documentElement)) { 92053 setTextContent = function (node, text) { 92054 setInnerHTML(node, escapeTextContentForBrowser(text)); 92055 }; 92056 } 92057} 92058 92059module.exports = setTextContent; 92060},{"119":119,"138":138,"144":144}],140:[function(_dereq_,module,exports){ 92061/** 92062 * Copyright 2013-present, Facebook, Inc. 92063 * All rights reserved. 92064 * 92065 * This source code is licensed under the BSD-style license found in the 92066 * LICENSE file in the root directory of this source tree. An additional grant 92067 * of patent rights can be found in the PATENTS file in the same directory. 92068 * 92069 * @providesModule shouldUpdateReactComponent 92070 */ 92071 92072 92073 92074/** 92075 * Given a `prevElement` and `nextElement`, determines if the existing 92076 * instance should be updated as opposed to being destroyed or replaced by a new 92077 * instance. Both arguments are elements. This ensures that this logic can 92078 * operate on stateless trees without any backing instance. 92079 * 92080 * @param {?object} prevElement 92081 * @param {?object} nextElement 92082 * @return {boolean} True if the existing instance should be updated. 92083 * @protected 92084 */ 92085 92086function shouldUpdateReactComponent(prevElement, nextElement) { 92087 var prevEmpty = prevElement === null || prevElement === false; 92088 var nextEmpty = nextElement === null || nextElement === false; 92089 if (prevEmpty || nextEmpty) { 92090 return prevEmpty === nextEmpty; 92091 } 92092 92093 var prevType = typeof prevElement; 92094 var nextType = typeof nextElement; 92095 if (prevType === 'string' || prevType === 'number') { 92096 return nextType === 'string' || nextType === 'number'; 92097 } else { 92098 return nextType === 'object' && prevElement.type === nextElement.type && prevElement.key === nextElement.key; 92099 } 92100} 92101 92102module.exports = shouldUpdateReactComponent; 92103},{}],141:[function(_dereq_,module,exports){ 92104/** 92105 * Copyright 2013-present, Facebook, Inc. 92106 * All rights reserved. 92107 * 92108 * This source code is licensed under the BSD-style license found in the 92109 * LICENSE file in the root directory of this source tree. An additional grant 92110 * of patent rights can be found in the PATENTS file in the same directory. 92111 * 92112 * @providesModule traverseAllChildren 92113 */ 92114 92115 92116 92117var ReactCurrentOwner = _dereq_(35); 92118var ReactElement = _dereq_(62); 92119 92120var getIteratorFn = _dereq_(127); 92121var invariant = _dereq_(158); 92122var KeyEscapeUtils = _dereq_(23); 92123var warning = _dereq_(168); 92124 92125var SEPARATOR = '.'; 92126var SUBSEPARATOR = ':'; 92127 92128/** 92129 * TODO: Test that a single child and an array with one item have the same key 92130 * pattern. 92131 */ 92132 92133var didWarnAboutMaps = false;
92134 92135/** 92136 * Generate a key string that identifies a component within a set. 92137 * 92138 * @param {*} component A component that could contain a manual key. 92139 * @param {number} index Index that is used if a manual key is not provided. 92140 * @return {string} 92141 */ 92142function getComponentKey(component, index) { 92143 // Do some typechecking here since we call this blindly. We want to ensure 92144 // that we don't block potential future ES APIs. 92145 if (component && typeof component === 'object' && component.key != null) { 92146 // Explicit key 92147 return KeyEscapeUtils.escape(component.key); 92148 } 92149 // Implicit key determined by the index in the set 92150 return index.toString(36); 92151} 92152 92153/** 92154 * @param {?*} children Children tree container. 92155 * @param {!string} nameSoFar Name of the key path so far. 92156 * @param {!function} callback Callback to invoke with each child found. 92157 * @param {?*} traverseContext Used to pass information throughout the traversal 92158 * process. 92159 * @return {!number} The number of children in this subtree. 92160 */ 92161function traverseAllChildrenImpl(children, nameSoFar, callback, traverseContext) { 92162 var type = typeof children; 92163 92164 if (type === 'undefined' || type === 'boolean') { 92165 // All of the above are perceived as null. 92166 children = null; 92167 } 92168 92169 if (children === null || type === 'string' || type === 'number' || ReactElement.isValidElement(children)) { 92170 callback(traverseContext, children, 92171 // If it's the only child, treat the name as if it was wrapped in an array 92172 // so that it's consistent if the number of children grows. 92173 nameSoFar === '' ? SEPARATOR + getComponentKey(children, 0) : nameSoFar); 92174 return 1; 92175 } 92176 92177 var child; 92178 var nextName; 92179 var subtreeCount = 0; // Count of children found in the current subtree.
92180 var nextNamePrefix = nameSoFar === '' ? SEPARATOR : nameSoFar + SUBSEPARATOR; 92181 92182 if (Array.isArray(children)) { 92183 for (var i = 0; i < children.length; i++) { 92184 child = children[i]; 92185 nextName = nextNamePrefix + getComponentKey(child, i); 92186 subtreeCount += traverseAllChildrenImpl(child, nextName, callback, traverseContext); 92187 } 92188 } else { 92189 var iteratorFn = getIteratorFn(children); 92190 if (iteratorFn) { 92191 var iterator = iteratorFn.call(children); 92192 var step; 92193 if (iteratorFn !== children.entries) { 92194 var ii = 0; 92195 while (!(step = iterator.next()).done) { 92196 child = step.value; 92197 nextName = nextNamePrefix + getComponentKey(child, ii++); 92198 subtreeCount += traverseAllChildrenImpl(child, nextName, callback, traverseContext); 92199 } 92200 } else { 92201 if ("development" !== 'production') { 92202 "development" !== 'production' ? warning(didWarnAboutMaps, 'Using Maps as children is not yet fully supported. It is an ' + 'experimental feature that might be removed. Convert it to a ' + 'sequence / iterable of keyed ReactElements instead.') : void 0; 92203 didWarnAboutMaps = true; 92204 } 92205 // Iterator will provide entry [k,v] tuples rather than values. 92206 while (!(step = iterator.next()).done) { 92207 var entry = step.value; 92208 if (entry) { 92209 child = entry[1]; 92210 nextName = nextNamePrefix + KeyEscapeUtils.escape(entry[0]) + SUBSEPARATOR + getComponentKey(child, 0); 92211 subtreeCount += traverseAllChildrenImpl(child, nextName, callback, traverseContext); 92212 } 92213 } 92214 } 92215 } else if (type === 'object') { 92216 var addendum = ''; 92217 if ("development" !== 'production') { 92218 addendum = ' If you meant to render a collection of children, use an array ' + 'instead or wrap the object using createFragment(object) from the ' + 'React add-ons.'; 92219 if (children._isReactElement) { 92220 addendum = ' It looks like you\'re using an element created by a different ' + 'version of React. Make sure to use only one copy of React.'; 92221 } 92222 if (ReactCurrentOwner.current) { 92223 var name = ReactCurrentOwner.current.getName(); 92224 if (name) { 92225 addendum += ' Check the render method of `' + name + '`.'; 92226 } 92227 } 92228 } 92229 var childrenString = String(children); 92230 !false ? "development" !== 'production' ? invariant(false, 'Objects are not valid as a React child (found: %s).%s', childrenString === '[object Object]' ? 'object with keys {' + Object.keys(children).join(', ') + '}' : childrenString, addendum) : invariant(false) : void 0; 92231 } 92232 } 92233 92234 return subtreeCount; 92235} 92236 92237/** 92238 * Traverses children that are typically specified as `props.children`, but 92239 * might also be specified through attributes: 92240 * 92241 * - `traverseAllChildren(this.props.children, ...)` 92242 * - `traverseAllChildren(this.props.leftPanelChildren, ...)` 92243 * 92244 * The `traverseContext` is an optional argument that is passed through the 92245 * entire traversal. It can be used to store accumulations or anything else that 92246 * the callback might find relevant. 92247 * 92248 * @param {?*} children Children tree object. 92249 * @param {!function} callback To invoke upon traversing each child. 92250 * @param {?*} traverseContext Context for traversal. 92251 * @return {!number} The number of children in this subtree. 92252 */ 92253function traverseAllChildren(children, callback, traverseContext) { 92254 if (children == null) { 92255 return 0; 92256 } 92257 92258 return traverseAllChildrenImpl(children, '', callback, traverseContext); 92259} 92260 92261module.exports = traverseAllChildren; 92262},{"127":127,"158":158,"168":168,"23":23,"35":35,"62":62}],142:[function(_dereq_,module,exports){ 92263/** 92264 * Copyright 2015-present, Facebook, Inc. 92265 * All rights reserved. 92266 * 92267 * This source code is licensed under the BSD-style license found in the 92268 * LICENSE file in the root directory of this source tree. An additional grant 92269 * of patent rights can be found in the PATENTS file in the same directory. 92270 * 92271 * @providesModule validateDOMNesting 92272 */ 92273 92274 92275 92276var _assign = _dereq_(169); 92277 92278var emptyFunction = _dereq_(150); 92279var warning = _dereq_(168); 92280 92281var validateDOMNesting = emptyFunction; 92282 92283if ("development" !== 'production') { 92284 // This validation code was written based on the HTML5 parsing spec: 92285 // https://html.spec.whatwg.org/multipage/syntax.html#has-an-element-in-scope 92286 // 92287 // Note: this does not catch all invalid nesting, nor does it try to (as it's 92288 // not clear what practical benefit doing so provides); instead, we warn only 92289 // for cases where the parser will give a parse tree differing from what React 92290 // intended. For example, <b><div></div></b>
vendor: 6,723 bytes, lines 92290-92452
92290 is invalid but we don't warn 92291 // because it still parses correctly; we do warn for other cases like nested 92292 // <p> tags where the beginning of the second element implicitly closes the 92293 // first, causing a confusing mess. 92294 92295 // https://html.spec.whatwg.org/multipage/syntax.html#special 92296 var specialTags = ['address', 'applet', 'area', 'article', 'aside', 'base', 'basefont', 'bgsound', 'blockquote', 'body', 'br', 'button', 'caption', 'center', 'col', 'colgroup', 'dd', 'details', 'dir', 'div', 'dl', 'dt', 'embed', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'frame', 'frameset', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 'html', 'iframe', 'img', 'input', 'isindex', 'li', 'link', 'listing', 'main', 'marquee', 'menu', 'menuitem', 'meta', 'nav', 'noembed', 'noframes', 'noscript', 'object', 'ol', 'p', 'param', 'plaintext', 'pre', 'script', 'section', 'select', 'source', 'style', 'summary', 'table', 'tbody', 'td', 'template', 'textarea', 'tfoot', 'th', 'thead', 'title', 'tr', 'track', 'ul', 'wbr', 'xmp']; 92297 92298 // https://html.spec.whatwg.org/multipage/syntax.html#has-an-element-in-scope 92299 var inScopeTags = ['applet', 'caption', 'html', 'table', 'td', 'th', 'marquee', 'object', 'template', 92300 92301 // https://html.spec.whatwg.org/multipage/syntax.html#html-integration-point 92302 // TODO: Distinguish by namespace here -- for <title>, including it here 92303 // errs on the side of fewer warnings 92304 'foreignObject', 'desc', 'title']; 92305 92306 // https://html.spec.whatwg.org/multipage/syntax.html#has-an-element-in-button-scope 92307 var buttonScopeTags = inScopeTags.concat(['button']); 92308 92309 // https://html.spec.whatwg.org/multipage/syntax.html#generate-implied-end-tags 92310 var impliedEndTags = ['dd', 'dt', 'li', 'option', 'optgroup', 'p', 'rp', 'rt']; 92311 92312 var emptyAncestorInfo = { 92313 current: null, 92314 92315 formTag: null, 92316 aTagInScope: null, 92317 buttonTagInScope: null, 92318 nobrTagInScope: null, 92319 pTagInButtonScope: null, 92320 92321 listItemTagAutoclosing: null, 92322 dlItemTagAutoclosing: null 92323 }; 92324 92325 var updatedAncestorInfo = function (oldInfo, tag, instance) { 92326 var ancestorInfo = _assign({}, oldInfo || emptyAncestorInfo); 92327 var info = { tag: tag, instance: instance }; 92328 92329 if (inScopeTags.indexOf(tag) !== -1) { 92330 ancestorInfo.aTagInScope = null; 92331 ancestorInfo.buttonTagInScope = null; 92332 ancestorInfo.nobrTagInScope = null; 92333 } 92334 if (buttonScopeTags.indexOf(tag) !== -1) { 92335 ancestorInfo.pTagInButtonScope = null; 92336 } 92337 92338 // See rules for 'li', 'dd', 'dt' start tags in 92339 // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inbody 92340 if (specialTags.indexOf(tag) !== -1 && tag !== 'address' && tag !== 'div' && tag !== 'p') { 92341 ancestorInfo.listItemTagAutoclosing = null; 92342 ancestorInfo.dlItemTagAutoclosing = null; 92343 } 92344 92345 ancestorInfo.current = info; 92346 92347 if (tag === 'form') { 92348 ancestorInfo.formTag = info; 92349 } 92350 if (tag === 'a') { 92351 ancestorInfo.aTagInScope = info; 92352 } 92353 if (tag === 'button') { 92354 ancestorInfo.buttonTagInScope = info; 92355 } 92356 if (tag === 'nobr') { 92357 ancestorInfo.nobrTagInScope = info; 92358 } 92359 if (tag === 'p') { 92360 ancestorInfo.pTagInButtonScope = info; 92361 } 92362 if (tag === 'li') { 92363 ancestorInfo.listItemTagAutoclosing = info; 92364 } 92365 if (tag === 'dd' || tag === 'dt') { 92366 ancestorInfo.dlItemTagAutoclosing = info; 92367 } 92368 92369 return ancestorInfo; 92370 }; 92371 92372 /** 92373 * Returns whether 92374 */ 92375 var isTagValidWithParent = function (tag, parentTag) { 92376 // First, let's check if we're in an unusual parsing mode... 92377 switch (parentTag) { 92378 // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inselect 92379 case 'select': 92380 return tag === 'option' || tag === 'optgroup' || tag === '#text'; 92381 case 'optgroup': 92382 return tag === 'option' || tag === '#text'; 92383 // Strictly speaking, seeing an <option> doesn't mean we're in a <select> 92384 // but 92385 case 'option': 92386 return tag === '#text'; 92387 92388 // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intd 92389 // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-incaption 92390 // No special behavior since these rules fall back to "in body" mode for 92391 // all except special table nodes which cause bad parsing behavior anyway. 92392 92393 // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intr 92394 case 'tr': 92395 return tag === 'th' || tag === 'td' || tag === 'style' || tag === 'script' || tag === 'template'; 92396 92397 // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intbody 92398 case 'tbody': 92399 case 'thead': 92400 case 'tfoot': 92401 return tag === 'tr' || tag === 'style' || tag === 'script' || tag === 'template'; 92402 92403 // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-incolgroup 92404 case 'colgroup': 92405 return tag === 'col' || tag === 'template'; 92406 92407 // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intable 92408 case 'table': 92409 return tag === 'caption' || tag === 'colgroup' || tag === 'tbody' || tag === 'tfoot' || tag === 'thead' || tag === 'style' || tag === 'script' || tag === 'template'; 92410 92411 // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inhead 92412 case 'head': 92413 return tag === 'base' || tag === 'basefont' || tag === 'bgsound' || tag === 'link' || tag === 'meta' || tag === 'title' || tag === 'noscript' || tag === 'noframes' || tag === 'style' || tag === 'script' || tag === 'template'; 92414 92415 // https://html.spec.whatwg.org/multipage/semantics.html#the-html-element 92416 case 'html': 92417 return tag === 'head' || tag === 'body'; 92418 case '#document': 92419 return tag === 'html'; 92420 } 92421 92422 // Probably in the "in body" parsing mode, so we outlaw only tag combos 92423 // where the parsing rules cause implicit opens or closes to be added. 92424 // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inbody 92425 switch (tag) { 92426 case 'h1': 92427 case 'h2': 92428 case 'h3': 92429 case 'h4': 92430 case 'h5': 92431 case 'h6': 92432 return parentTag !== 'h1' && parentTag !== 'h2' && parentTag !== 'h3' && parentTag !== 'h4' && parentTag !== 'h5' && parentTag !== 'h6'; 92433 92434 case 'rp': 92435 case 'rt': 92436 return impliedEndTags.indexOf(parentTag) === -1; 92437 92438 case 'body': 92439 case 'caption': 92440 case 'col': 92441 case 'colgroup': 92442 case 'frame': 92443 case 'head': 92444 case 'html': 92445 case 'tbody': 92446 case 'td': 92447 case 'tfoot': 92448 case 'th': 92449 case 'thead': 92450 case 'tr': 92451 // These tags are only valid with a few parents that have special child 92452 // parsing rules -- if we're down here, then none of those matched and
92453 // so we allow it only if we don't know what the parent is, as all other 92454 // cases are invalid. 92455 return parentTag == null; 92456 } 92457 92458 return true; 92459 }; 92460 92461 /** 92462 * Returns whether 92463 */ 92464 var findInvalidAncestorForTag = function (tag, ancestorInfo) { 92465 switch (tag) { 92466 case 'address': 92467 case 'article': 92468 case 'aside': 92469 case 'blockquote': 92470 case 'center': 92471 case 'details': 92472 case 'dialog': 92473 case 'dir': 92474 case 'div': 92475 case 'dl': 92476 case 'fieldset': 92477 case 'figcaption': 92478 case 'figure': 92479 case 'footer': 92480 case 'header': 92481 case 'hgroup': 92482 case 'main': 92483 case 'menu': 92484 case 'nav': 92485 case 'ol': 92486 case 'p': 92487 case 'section': 92488 case 'summary': 92489 case 'ul': 92490 92491 case 'pre': 92492 case 'listing': 92493 92494 case 'table': 92495 92496 case 'hr': 92497 92498 case 'xmp': 92499 92500 case 'h1': 92501 case 'h2': 92502 case 'h3': 92503 case 'h4': 92504 case 'h5': 92505 case 'h6': 92506 return ancestorInfo.pTagInButtonScope; 92507 92508 case 'form': 92509 return ancestorInfo.formTag || ancestorInfo.pTagInButtonScope; 92510 92511 case 'li': 92512 return ancestorInfo.listItemTagAutoclosing; 92513 92514 case 'dd': 92515 case 'dt': 92516 return ancestorInfo.dlItemTagAutoclosing; 92517 92518 case 'button': 92519 return ancestorInfo.buttonTagInScope; 92520 92521 case 'a': 92522 // Spec says something about storing a list of markers, but it sounds 92523 // equivalent to this check. 92524 return ancestorInfo.aTagInScope; 92525 92526 case 'nobr': 92527 return ancestorInfo.nobrTagInScope; 92528 } 92529 92530 return null; 92531 }; 92532 92533 /** 92534 * Given a ReactCompositeComponent instance, return a list of its recursive 92535 * owners, starting at the root and ending with the instance itself. 92536 */ 92537 var findOwnerStack = function (instance) { 92538 if (!instance) { 92539 return []; 92540 } 92541 92542 var stack = []; 92543 do { 92544 stack.push(instance); 92545 } while (instance = instance._currentElement._owner); 92546 stack.reverse(); 92547 return stack; 92548 }; 92549 92550 var didWarn = {}; 92551 92552 validateDOMNesting = function (childTag, childInstance, ancestorInfo) { 92553 ancestorInfo = ancestorInfo || emptyAncestorInfo; 92554 var parentInfo = ancestorInfo.current; 92555 var parentTag = parentInfo && parentInfo.tag; 92556 92557 var invalidParent = isTagValidWithParent(childTag, parentTag) ? null : parentInfo; 92558 var invalidAncestor = invalidParent ? null : findInvalidAncestorForTag(childTag, ancestorInfo); 92559 var problematic = invalidParent || invalidAncestor; 92560 92561 if (problematic) { 92562 var ancestorTag = problematic.tag; 92563 var ancestorInstance = problematic.instance; 92564 92565 var childOwner = childInstance && childInstance._currentElement._owner; 92566 var ancestorOwner = ancestorInstance && ancestorInstance._currentElement._owner; 92567 92568 var childOwners = findOwnerStack(childOwner); 92569 var ancestorOwners = findOwnerStack(ancestorOwner); 92570 92571 var minStackLen = Math.min(childOwners.length, ancestorOwners.length); 92572 var i; 92573 92574 var deepestCommon = -1; 92575 for (i = 0; i < minStackLen; i++) { 92576 if (childOwners[i] === ancestorOwners[i]) { 92577 deepestCommon = i; 92578 } else { 92579 break; 92580 } 92581 } 92582 92583 var UNKNOWN = '(unknown)'; 92584 var childOwnerNames = childOwners.slice(deepestCommon + 1).map(function (inst) { 92585 return inst.getName() || UNKNOWN; 92586 }); 92587 var ancestorOwnerNames = ancestorOwners.slice(deepestCommon + 1).map(function (inst) { 92588 return inst.getName() || UNKNOWN; 92589 }); 92590 var ownerInfo = [].concat( 92591 // If the parent and child instances have a common owner ancestor, start 92592 // with that -- otherwise we just start with the parent's owners. 92593 deepestCommon !== -1 ? childOwners[deepestCommon].getName() || UNKNOWN : [], ancestorOwnerNames, ancestorTag, 92594 // If we're warning about an invalid (non-parent) ancestry, add '...' 92595 invalidAncestor ? ['...'] : [], childOwnerNames, childTag).join(' > '); 92596 92597 var warnKey = !!invalidParent + '|' + childTag + '|' + ancestorTag + '|' + ownerInfo; 92598 if (didWarn[warnKey]) { 92599 return; 92600 } 92601 didWarn[warnKey] = true; 92602 92603 var tagDisplayName = childTag; 92604 if (childTag !== '#text') { 92605 tagDisplayName = '<' + childTag + '>'; 92606 } 92607 92608 if (invalidParent) { 92609 var info = ''; 92610 if (ancestorTag === 'table' && childTag === 'tr') { 92611 info += ' Add a <tbody> to your code to match the DOM tree generated by ' + 'the browser.'; 92612 } 92613 "development" !== 'production' ? warning(false, 'validateDOMNesting(...): %s cannot appear as a child of <%s>. ' + 'See %s.%s', tagDisplayName, ancestorTag, ownerInfo, info) : void 0; 92614 } else { 92615 "development" !== 'production' ? warning(false, 'validateDOMNesting(...): %s cannot appear as a descendant of ' + '<%s>. See %s.', tagDisplayName, ancestorTag, ownerInfo) : void 0; 92616 } 92617 } 92618 }; 92619 92620 validateDOMNesting.updatedAncestorInfo = updatedAncestorInfo; 92621 92622 // For testing 92623 validateDOMNesting.isTagValidInContext = function (tag, ancestorInfo) { 92624 ancestorInfo = ancestorInfo || emptyAncestorInfo; 92625 var parentInfo = ancestorInfo.current; 92626 var parentTag = parentInfo && parentInfo.tag;
92627 return isTagValidWithParent(tag, parentTag) && !findInvalidAncestorForTag(tag, ancestorInfo); 92628 }; 92629} 92630 92631module.exports = validateDOMNesting; 92632},{"150":150,"168":168,"169":169}],143:[function(_dereq_,module,exports){ 92633'use strict'; 92634 92635/** 92636 * Copyright (c) 2013-present, Facebook, Inc. 92637 * 92638 * Licensed under the Apache License, Version 2.0 (the "License"); 92639 * you may not use this file except in compliance with the License. 92640 * You may obtain a copy of the License at 92641 * 92642 * http://www.apache.org/licenses/LICENSE-2.0 92643 * 92644 * Unless required by applicable law or agreed to in writing, software 92645 * distributed under the License is distributed on an "AS IS" BASIS, 92646 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 92647 * See the License for the specific language governing permissions and 92648 * limitations under the License. 92649 * 92650 * @typechecks 92651 */ 92652 92653var emptyFunction = _dereq_(150); 92654 92655/** 92656 * Upstream version of event listener. Does not take into account specific 92657 * nature of platform. 92658 */ 92659var EventListener = { 92660 /** 92661 * Listen to DOM events during the bubble phase. 92662 * 92663 * @param {DOMEventTarget} target DOM element to register listener on. 92664 * @param {string} eventType Event type, e.g. 'click' or 'mouseover'. 92665 * @param {function} callback Callback function. 92666 * @return {object} Object with a `remove` method. 92667 */ 92668 listen: function (target, eventType, callback) { 92669 if (target.addEventListener) { 92670 target.addEventListener(eventType, callback, false); 92671 return { 92672 remove: function () { 92673 target.removeEventListener(eventType, callback, false); 92674 } 92675 }; 92676 } else if (target.attachEvent) { 92677 target.attachEvent('on' + eventType, callback); 92678 return { 92679 remove: function () { 92680 target.detachEvent('on' + eventType, callback); 92681 } 92682 }; 92683 } 92684 }, 92685 92686 /** 92687 * Listen to DOM events during the capture phase. 92688 * 92689 * @param {DOMEventTarget} target DOM element to register listener on. 92690 * @param {string} eventType Event type, e.g. 'click' or 'mouseover'. 92691 * @param {function} callback Callback function. 92692 * @return {object} Object with a `remove` method. 92693 */ 92694 capture: function (target, eventType, callback) { 92695 if (target.addEventListener) { 92696 target.addEventListener(eventType, callback, true); 92697 return { 92698 remove: function () { 92699 target.removeEventListener(eventType, callback, true); 92700 } 92701 }; 92702 } else { 92703 if ("development" !== 'production') { 92704 console.error('Attempted to listen to events during the capture phase on a ' + 'browser that does not support the capture phase. Your application ' + 'will not receive some events.'); 92705 } 92706 return { 92707 remove: emptyFunction 92708 }; 92709 } 92710 }, 92711 92712 registerDefault: function () {} 92713}; 92714 92715module.exports = EventListener; 92716},{"150":150}],144:[function(_dereq_,module,exports){ 92717/** 92718 * Copyright (c) 2013-present, Facebook, Inc. 92719 * All rights reserved. 92720 * 92721 * This source code is licensed under the BSD-style license found in the 92722 * LICENSE file in the root directory of this source tree. An additional grant 92723 * of patent rights can be found in the PATENTS file in the same directory. 92724 * 92725 */ 92726 92727 92728 92729var canUseDOM = !!(typeof window !== 'undefined' && window.document && window.document.createElement); 92730 92731/** 92732 * Simple, lightweight module assisting with the detection and context of 92733 * Worker. Helps avoid circular dependencies and allows code to reason about 92734 * whether or not they are in a Worker, even if they never include the main 92735 * `ReactWorker` dependency. 92736 */ 92737var ExecutionEnvironment = { 92738 92739 canUseDOM: canUseDOM, 92740 92741 canUseWorkers: typeof Worker !== 'undefined', 92742 92743 canUseEventListeners: canUseDOM && !!(window.addEventListener || window.attachEvent), 92744 92745 canUseViewport: canUseDOM && !!window.screen, 92746 92747 isInWorker: !canUseDOM // For now, this is true - might change in the future. 92748 92749}; 92750 92751module.exports = ExecutionEnvironment; 92752},{}],145:[function(_dereq_,module,exports){ 92753"use strict"; 92754 92755/** 92756 * Copyright (c) 2013-present, Facebook, Inc. 92757 * All rights reserved. 92758 * 92759 * This source code is licensed under the BSD-style license found in the 92760 * LICENSE file in the root directory of this source tree. An additional grant 92761 * of patent rights can be found in the PATENTS file in the same directory. 92762 * 92763 * @typechecks 92764 */ 92765 92766var _hyphenPattern = /-(.)/g; 92767 92768/** 92769 * Camelcases a hyphenated string, for example: 92770 * 92771 * > camelize('background-color') 92772 * < "backgroundColor" 92773 * 92774 * @param {string} string 92775 * @return {string} 92776 */ 92777function camelize(string) { 92778 return string.replace(_hyphenPattern, function (_, character) { 92779 return character.toUpperCase(); 92780 }); 92781} 92782 92783module.exports = camelize; 92784},{}],146:[function(_dereq_,module,exports){ 92785/** 92786 * Copyright (c) 2013-present, Facebook, Inc. 92787 * All rights reserved. 92788 * 92789 * This source code is licensed under the BSD-style license found in the 92790 * LICENSE file in the root directory of this source tree. An additional grant 92791 * of patent rights can be found in the PATENTS file in the same directory. 92792 * 92793 * @typechecks 92794 */ 92795 92796 92797 92798var camelize = _dereq_(145); 92799 92800var msPattern = /^-ms-/; 92801 92802/** 92803 * Camelcases a hyphenated CSS property name, for example: 92804 * 92805 * > camelizeStyleName('background-color') 92806 * < "backgroundColor" 92807 * > camelizeStyleName('-moz-transition') 92808 * < "MozTransition" 92809 * > camelizeStyleName('-ms-transition') 92810 * < "msTransition" 92811 * 92812 * As Andi Smith suggests 92813 * (http://www.andismith.com/blog/2012/02/modernizr-prefixed/), an `-ms` prefix 92814 * is converted to lowercase `ms`. 92815 * 92816 * @param {string} string 92817 * @return {string} 92818 */ 92819function camelizeStyleName(string) { 92820 return camelize(string.replace(msPattern, 'ms-')); 92821} 92822 92823module.exports = camelizeStyleName; 92824},{"145":145}],147:[function(_dereq_,module,exports){ 92825'use strict'; 92826 92827/** 92828 * Copyright (c) 2013-present, Facebook, Inc. 92829 * All rights reserved. 92830 * 92831 * This source code is licensed under the BSD-style license found in the 92832 * LICENSE file in the root directory of this source tree. An additional grant 92833 * of patent rights can be found in the PATENTS file in the same directory. 92834 * 92835 * @typechecks 92836 */ 92837 92838var isTextNode = _dereq_(160); 92839 92840/*eslint-disable no-bitwise */ 92841 92842/** 92843 * Checks if a given DOM node contains or is another DOM node. 92844 * 92845 * @param {?DOMNode} outerNode Outer DOM node. 92846 * @param {?DOMNode} innerNode Inner DOM node. 92847 * @return {boolean} True if `outerNode` contains or is `innerNode`. 92848 */
92849function containsNode(outerNode, innerNode) { 92850 if (!outerNode || !innerNode) { 92851 return false; 92852 } else if (outerNode === innerNode) { 92853 return true; 92854 } else if (isTextNode(outerNode)) { 92855 return false; 92856 } else if (isTextNode(innerNode)) { 92857 return containsNode(outerNode, innerNode.parentNode); 92858 } else if (outerNode.contains) { 92859 return outerNode.contains(innerNode); 92860 } else if (outerNode.compareDocumentPosition) { 92861 return !!(outerNode.compareDocumentPosition(innerNode) & 16); 92862 } else { 92863 return false; 92864 } 92865} 92866 92867module.exports = containsNode; 92868},{"160":160}],148:[function(_dereq_,module,exports){ 92869'use strict'; 92870 92871/** 92872 * Copyright (c) 2013-present, Facebook, Inc. 92873 * All rights reserved. 92874 * 92875 * This source code is licensed under the BSD-style license found in the 92876 * LICENSE file in the root directory of this source tree. An additional grant 92877 * of patent rights can be found in the PATENTS file in the same directory. 92878 * 92879 * @typechecks 92880 */ 92881 92882var invariant = _dereq_(158); 92883 92884/** 92885 * Convert array-like objects to arrays. 92886 * 92887 * This API assumes the caller knows the contents of the data type. For less 92888 * well defined inputs use createArrayFromMixed. 92889 * 92890 * @param {object|function|filelist} obj 92891 * @return {array} 92892 */ 92893function toArray(obj) { 92894 var length = obj.length; 92895 92896 // Some browsers builtin objects can report typeof 'function' (e.g. NodeList 92897 // in old versions of Safari). 92898 !(!Array.isArray(obj) && (typeof obj === 'object' || typeof obj === 'function')) ? "development" !== 'production' ? invariant(false, 'toArray: Array-like object expected') : invariant(false) : void 0; 92899 92900 !(typeof length === 'number') ? "development" !== 'production' ? invariant(false, 'toArray: Object needs a length property') : invariant(false) : void 0; 92901 92902 !(length === 0 || length - 1 in obj) ? "development" !== 'production' ? invariant(false, 'toArray: Object should have keys for indices') : invariant(false) : void 0; 92903 92904 !(typeof obj.callee !== 'function') ? "development" !== 'production' ? invariant(false, 'toArray: Object can\'t be `arguments`. Use rest params ' + '(function(...args) {}) or Array.from() instead.') : invariant(false) : void 0; 92905 92906 // Old IE doesn't give collections access to hasOwnProperty. Assume inputs 92907 // without method will throw during the slice call and skip straight to the 92908 // fallback. 92909 if (obj.hasOwnProperty) { 92910 try { 92911 return Array.prototype.slice.call(obj); 92912 } catch (e) { 92913 // IE < 9 does not support Array#slice on collections objects 92914 } 92915 } 92916 92917 // Fall back to copying key by key. This assumes all keys have a value, 92918 // so will not preserve sparsely populated inputs. 92919 var ret = Array(length); 92920 for (var ii = 0; ii < length; ii++) { 92921 ret[ii] = obj[ii]; 92922 } 92923 return ret; 92924} 92925 92926/** 92927 * Perform a heuristic test to determine if an object is "array-like". 92928 * 92929 * A monk asked Joshu, a Zen master, "Has a dog Buddha nature?" 92930 * Joshu replied: "Mu." 92931 * 92932 * This function determines if its argument has "array nature": it returns 92933 * true if the argument is an actual array, an `arguments' object, or an 92934 * HTMLCollection (e.g. node.childNodes or node.getElementsByTagName()). 92935 * 92936 * It will return false for other array-like objects like Filelist. 92937 * 92938 * @param {*} obj 92939 * @return {boolean} 92940 */ 92941function hasArrayNature(obj) { 92942 return( 92943 // not null/false 92944 !!obj && ( 92945 // arrays are objects, NodeLists are functions in Safari 92946 typeof obj == 'object' || typeof obj == 'function') && 92947 // quacks like an array 92948 'length' in obj && 92949 // not window 92950 !('setInterval' in obj) && 92951 // no DOM node should be considered an array-like 92952 // a 'select' element has 'length' and 'item' properties on IE8 92953 typeof obj.nodeType != 'number' && ( 92954 // a real array 92955 Array.isArray(obj) || 92956 // arguments 92957 'callee' in obj || 92958 // HTMLCollection/NodeList 92959 'item' in obj) 92960 ); 92961} 92962 92963/** 92964 * Ensure that the argument is an array by wrapping it in an array if it is not. 92965 * Creates a copy of the argument if it is already an array. 92966 * 92967 * This is mostly useful idiomatically: 92968 * 92969 * var createArrayFromMixed = require('createArrayFromMixed'); 92970 * 92971 * function takesOneOrMoreThings(things) { 92972 * things = createArrayFromMixed(things); 92973 * ... 92974 * } 92975 * 92976 * This allows you to treat `things' as an array, but accept scalars in the API. 92977 * 92978 * If you need to convert an array-like object, like `arguments`, into an array 92979 * use toArray instead. 92980 * 92981 * @param {*} obj 92982 * @return {array} 92983 */ 92984function createArrayFromMixed(obj) { 92985 if (!hasArrayNature(obj)) { 92986 return [obj]; 92987 } else if (Array.isArray(obj)) { 92988 return obj.slice(); 92989 } else { 92990 return toArray(obj); 92991 } 92992} 92993 92994module.exports = createArrayFromMixed; 92995},{"158":158}],149:[function(_dereq_,module,exports){ 92996'use strict'; 92997 92998/** 92999 * Copyright (c) 2013-present, Facebook, Inc. 93000 * All rights reserved. 93001 * 93002 * This source code is licensed under the BSD-style license found in the 93003 * LICENSE file in the root directory of this source tree. An additional grant 93004 * of patent rights can be found in the PATENTS file in the same directory. 93005 * 93006 * @typechecks 93007 */ 93008 93009/*eslint-disable fb-www/unsafe-html*/ 93010 93011var ExecutionEnvironment = _dereq_(144); 93012 93013var createArrayFromMixed = _dereq_(148); 93014var getMarkupWrap = _dereq_(154); 93015var invariant = _dereq_(158); 93016 93017/** 93018 * Dummy container used to render all markup. 93019 */ 93020var dummyNode = ExecutionEnvironment.canUseDOM ? document.createElement('div') : null; 93021 93022/** 93023 * Pattern used by `getNodeName`. 93024 */ 93025var nodeNamePattern = /^\s*<(\w+)/; 93026 93027/** 93028 * Extracts the `nodeName` of the first element in a string of markup. 93029 * 93030 * @param {string} markup String of markup. 93031 * @return {?string} Node name of the supplied markup. 93032 */ 93033function getNodeName(markup) { 93034 var nodeNameMatch = markup.match(nodeNamePattern); 93035 return nodeNameMatch && nodeNameMatch[1].toLowerCase(); 93036} 93037 93038/** 93039 * Creates an array containing the nodes rendered from the supplied markup. The 93040 * optionally supplied `handleScript` function will be invoked once for each 93041 * <script> element that is rendered. If no `handleScript` function is supplied, 93042 * an exception is thrown if any <script> elements are rendered. 93043 * 93044 * @param {string} markup A string of valid HTML markup. 93045 * @param {?function} handleScript Invoked once for each rendered <script>. 93046 * @return {array<DOMElement|DOMTextNode>} An array of rendered nodes. 93047 */ 93048function createNodesFromMarkup(markup, handleScript) { 93049 var node = dummyNode; 93050 !!!dummyNode ? "development" !== 'production' ? invariant(false, 'createNodesFromMarkup dummy not initialized') : invariant(false) : void 0; 93051 var nodeName = getNodeName(markup); 93052 93053 var wrap = nodeName && getMarkupWrap(nodeName); 93054 if (wrap) { 93055 node.innerHTML = wrap[1] + markup + wrap[2]; 93056 93057 var wrapDepth = wrap[0]; 93058 while (wrapDepth--) { 93059 node = node.lastChild; 93060 } 93061 } else { 93062 node.innerHTML = markup; 93063 } 93064 93065 var scripts = node.getElementsByTagName('script'); 93066 if (scripts.length) { 93067 !handleScript ? "development" !== 'production' ? invariant(false, 'createNodesFromMarkup(...): Unexpected <script> element rendered.') : invariant(false) : void 0;
93068 createArrayFromMixed(scripts).forEach(handleScript); 93069 } 93070 93071 var nodes = Array.from(node.childNodes); 93072 while (node.lastChild) { 93073 node.removeChild(node.lastChild); 93074 } 93075 return nodes; 93076} 93077 93078module.exports = createNodesFromMarkup; 93079},{"144":144,"148":148,"154":154,"158":158}],150:[function(_dereq_,module,exports){ 93080"use strict"; 93081 93082/** 93083 * Copyright (c) 2013-present, Facebook, Inc. 93084 * All rights reserved. 93085 * 93086 * This source code is licensed under the BSD-style license found in the 93087 * LICENSE file in the root directory of this source tree. An additional grant 93088 * of patent rights can be found in the PATENTS file in the same directory. 93089 * 93090 */ 93091 93092function makeEmptyFunction(arg) { 93093 return function () { 93094 return arg; 93095 }; 93096} 93097 93098/** 93099 * This function accepts and discards inputs; it has no side effects. This is 93100 * primarily useful idiomatically for overridable function endpoints which 93101 * always need to be callable, since JS lacks a null-call idiom ala Cocoa. 93102 */ 93103function emptyFunction() {} 93104 93105emptyFunction.thatReturns = makeEmptyFunction; 93106emptyFunction.thatReturnsFalse = makeEmptyFunction(false); 93107emptyFunction.thatReturnsTrue = makeEmptyFunction(true); 93108emptyFunction.thatReturnsNull = makeEmptyFunction(null); 93109emptyFunction.thatReturnsThis = function () { 93110 return this; 93111}; 93112emptyFunction.thatReturnsArgument = function (arg) { 93113 return arg; 93114}; 93115 93116module.exports = emptyFunction; 93117},{}],151:[function(_dereq_,module,exports){ 93118/** 93119 * Copyright (c) 2013-present, Facebook, Inc. 93120 * All rights reserved. 93121 * 93122 * This source code is licensed under the BSD-style license found in the 93123 * LICENSE file in the root directory of this source tree. An additional grant 93124 * of patent rights can be found in the PATENTS file in the same directory. 93125 * 93126 */ 93127 93128 93129 93130var emptyObject = {}; 93131 93132if ("development" !== 'production') { 93133 Object.freeze(emptyObject); 93134} 93135 93136module.exports = emptyObject; 93137},{}],152:[function(_dereq_,module,exports){ 93138/** 93139 * Copyright (c) 2013-present, Facebook, Inc. 93140 * All rights reserved. 93141 * 93142 * This source code is licensed under the BSD-style license found in the 93143 * LICENSE file in the root directory of this source tree. An additional grant 93144 * of patent rights can be found in the PATENTS file in the same directory. 93145 * 93146 */ 93147 93148 93149 93150/** 93151 * @param {DOMElement} node input/textarea to focus 93152 */ 93153 93154function focusNode(node) { 93155 // IE8 can throw "Can't move focus to the control because it is invisible, 93156 // not enabled, or of a type that does not accept the focus." for all kinds of 93157 // reasons that are too expensive and fragile to test. 93158 try { 93159 node.focus(); 93160 } catch (e) {} 93161} 93162 93163module.exports = focusNode; 93164},{}],153:[function(_dereq_,module,exports){ 93165'use strict'; 93166 93167/** 93168 * Copyright (c) 2013-present, Facebook, Inc. 93169 * All rights reserved. 93170 * 93171 * This source code is licensed under the BSD-style license found in the 93172 * LICENSE file in the root directory of this source tree. An additional grant 93173 * of patent rights can be found in the PATENTS file in the same directory. 93174 * 93175 * @typechecks 93176 */ 93177 93178/* eslint-disable fb-www/typeof-undefined */ 93179 93180/** 93181 * Same as document.activeElement but wraps in a try-catch block. In IE it is 93182 * not safe to call document.activeElement if there is nothing focused. 93183 * 93184 * The activeElement will be null only if the document or document body is not 93185 * yet defined. 93186 */ 93187function getActiveElement() /*?DOMElement*/{ 93188 if (typeof document === 'undefined') { 93189 return null; 93190 } 93191 try { 93192 return document.activeElement || document.body; 93193 } catch (e) { 93194 return document.body; 93195 } 93196} 93197 93198module.exports = getActiveElement; 93199},{}],154:[function(_dereq_,module,exports){ 93200'use strict'; 93201 93202/** 93203 * Copyright (c) 2013-present, Facebook, Inc. 93204 * All rights reserved. 93205 * 93206 * This source code is licensed under the BSD-style license found in the 93207 * LICENSE file in the root directory of this source tree. An additional grant 93208 * of patent rights can be found in the PATENTS file in the same directory. 93209 * 93210 */ 93211 93212/*eslint-disable fb-www/unsafe-html */ 93213 93214var ExecutionEnvironment = _dereq_(144); 93215 93216var invariant = _dereq_(158); 93217 93218/** 93219 * Dummy container used to detect which wraps are necessary. 93220 */ 93221var dummyNode = ExecutionEnvironment.canUseDOM ? document.createElement('div') : null; 93222 93223/** 93224 * Some browsers cannot use `innerHTML` to render certain elements standalone,
93225 * so we wrap them, render the wrapped nodes, then extract the desired node. 93226 * 93227 * In IE8, certain elements cannot render alone, so wrap all elements ('*'). 93228 */ 93229 93230var shouldWrap = {}; 93231 93232var selectWrap = [1, '<select multiple="true">', '</select>']; 93233var tableWrap = [1, '<table>', '</table>']; 93234var trWrap = [3, '<table><tbody><tr>', '</tr></tbody></table>']; 93235 93236var svgWrap = [1, '<svg xmlns="http://www.w3.org/2000/svg">', '</svg>']; 93237 93238var markupWrap = { 93239 '*': [1, '?<div>', '</div>'], 93240 93241 'area': [1, '<map>', '</map>'], 93242 'col': [2, '<table><tbody></tbody><colgroup>', '</colgroup></table>'], 93243 'legend': [1, '<fieldset>', '</fieldset>'], 93244 'param': [1, '<object>', '</object>'], 93245 'tr': [2, '<table><tbody>', '</tbody></table>'], 93246 93247 'optgroup': selectWrap, 93248 'option': selectWrap, 93249 93250 'caption': tableWrap, 93251 'colgroup': tableWrap, 93252 'tbody': tableWrap, 93253 'tfoot': tableWrap, 93254 'thead': tableWrap, 93255 93256 'td': trWrap, 93257 'th': trWrap 93258}; 93259 93260// Initialize the SVG elements since we know they'll always need to be wrapped 93261// consistently. If they are created inside a <div> they will be initialized in 93262// the wrong namespace (and will not display). 93263var svgElements = ['circle', 'clipPath', 'defs', 'ellipse', 'g', 'image', 'line', 'linearGradient', 'mask', 'path', 'pattern', 'polygon', 'polyline', 'radialGradient', 'rect', 'stop', 'text', 'tspan']; 93264svgElements.forEach(function (nodeName) { 93265 markupWrap[nodeName] = svgWrap; 93266 shouldWrap[nodeName] = true; 93267}); 93268 93269/** 93270 * Gets the markup wrap configuration for the supplied `nodeName`. 93271 * 93272 * NOTE: This lazily detects which wraps are necessary for the current browser. 93273 * 93274 * @param {string} nodeName Lowercase `nodeName`. 93275 * @return {?array} Markup wrap configuration, if applicable. 93276 */ 93277function getMarkupWrap(nodeName) { 93278 !!!dummyNode ? "development" !== 'production' ? invariant(false, 'Markup wrapping node not initialized') : invariant(false) : void 0; 93279 if (!markupWrap.hasOwnProperty(nodeName)) { 93280 nodeName = '*'; 93281 } 93282 if (!shouldWrap.hasOwnProperty(nodeName)) { 93283 if (nodeName === '*') { 93284 dummyNode.innerHTML = '<link />'; 93285 } else { 93286 dummyNode.innerHTML = '<' + nodeName + '></' + nodeName + '>'; 93287 } 93288 shouldWrap[nodeName] = !dummyNode.firstChild; 93289 } 93290 return shouldWrap[nodeName] ? markupWrap[nodeName] : null; 93291} 93292 93293module.exports = getMarkupWrap; 93294},{"144":144,"158":158}],155:[function(_dereq_,module,exports){ 93295/** 93296 * Copyright (c) 2013-present, Facebook, Inc. 93297 * All rights reserved. 93298 * 93299 * This source code is licensed under the BSD-style license found in the 93300 * LICENSE file in the root directory of this source tree. An additional grant 93301 * of patent rights can be found in the PATENTS file in the same directory. 93302 * 93303 * @typechecks 93304 */ 93305 93306 93307 93308/** 93309 * Gets the scroll position of the supplied element or window. 93310 * 93311 * The return values are unbounded, unlike `getScrollPosition`. This means they 93312 * may be negative or exceed the element boundaries (which is possible using 93313 * inertial scrolling). 93314 * 93315 * @param {DOMWindow|DOMElement} scrollable 93316 * @return {object} Map with `x` and `y` keys. 93317 */ 93318 93319function getUnboundedScrollPosition(scrollable) { 93320 if (scrollable === window) { 93321 return { 93322 x: window.pageXOffset || document.documentElement.scrollLeft, 93323 y: window.pageYOffset || document.documentElement.scrollTop 93324 }; 93325 } 93326 return { 93327 x: scrollable.scrollLeft, 93328 y: scrollable.scrollTop 93329 }; 93330} 93331 93332module.exports = getUnboundedScrollPosition; 93333},{}],156:[function(_dereq_,module,exports){ 93334'use strict'; 93335 93336/** 93337 * Copyright (c) 2013-present, Facebook, Inc. 93338 * All rights reserved. 93339 * 93340 * This source code is licensed under the BSD-style license found in the 93341 * LICENSE file in the root directory of this source tree. An additional grant 93342 * of patent rights can be found in the PATENTS file in the same directory. 93343 * 93344 * @typechecks 93345 */ 93346 93347var _uppercasePattern = /([A-Z])/g; 93348 93349/** 93350 * Hyphenates a camelcased string, for example: 93351 * 93352 * > hyphenate('backgroundColor') 93353 * < "background-color" 93354 * 93355 * For CSS style names, use `hyphenateStyleName` instead which works properly 93356 * with all vendor prefixes, including `ms`. 93357 * 93358 * @param {string} string 93359 * @return {string} 93360 */ 93361function hyphenate(string) { 93362 return string.replace(_uppercasePattern, '-$1').toLowerCase(); 93363} 93364 93365module.exports = hyphenate; 93366},{}],157:[function(_dereq_,module,exports){ 93367/** 93368 * Copyright (c) 2013-present, Facebook, Inc. 93369 * All rights reserved. 93370 * 93371 * This source code is licensed under the BSD-style license found in the 93372 * LICENSE file in the root directory of this source tree. An additional grant 93373 * of patent rights can be found in the PATENTS file in the same directory. 93374 * 93375 * @typechecks 93376 */ 93377 93378 93379 93380var hyphenate = _dereq_(156); 93381 93382var msPattern = /^ms-/; 93383 93384/** 93385 * Hyphenates a camelcased CSS property name, for example: 93386 * 93387 * > hyphenateStyleName('backgroundColor') 93388 * < "background-color" 93389 * > hyphenateStyleName('MozTransition') 93390 * < "-moz-transition" 93391 * > hyphenateStyleName('msTransition') 93392 * < "-ms-transition" 93393 * 93394 * As Modernizr suggests (http://modernizr.com/docs/#prefixed), an `ms` prefix 93395 * is converted to `-ms-`. 93396 * 93397 * @param {string} string 93398 * @return {string} 93399 */ 93400function hyphenateStyleName(string) { 93401 return hyphenate(string).replace(msPattern, '-ms-'); 93402} 93403 93404module.exports = hyphenateStyleName; 93405},{"156":156}],158:[function(_dereq_,module,exports){ 93406/** 93407 * Copyright (c) 2013-present, Facebook, Inc. 93408 * All rights reserved. 93409 * 93410 * This source code is licensed under the BSD-style license found in the 93411 * LICENSE file in the root directory of this source tree. An additional grant 93412 * of patent rights can be found in the PATENTS file in the same directory. 93413 * 93414 */ 93415 93416 93417 93418/** 93419 * Use invariant() to assert state which your program assumes to be true. 93420 * 93421 * Provide sprintf-style format (only %s is supported) and arguments 93422 * to provide information about what broke and what you were 93423 * expecting. 93424 * 93425 * The invariant message will be stripped in production, but the invariant 93426 * will remain to ensure logic does not differ in production. 93427 */ 93428 93429function invariant(condition, format, a, b, c, d, e, f) { 93430 if ("development" !== 'production') { 93431 if (format === undefined) { 93432 throw new Error('invariant requires an error message argument'); 93433 } 93434 } 93435 93436 if (!condition) { 93437 var error; 93438 if (format === undefined) { 93439 error = new Error('Minified exception occurred; use the non-minified dev environment ' + 'for the full error message and additional helpful warnings.'); 93440 } else { 93441 var args = [a, b, c, d, e, f]; 93442 var argIndex = 0; 93443 error = new Error(format.replace(/%s/g, function () { 93444 return args[argIndex++]; 93445 }));
93446 error.name = 'Invariant Violation'; 93447 } 93448 93449 error.framesToPop = 1; // we don't care about invariant's own frame 93450 throw error; 93451 } 93452} 93453 93454module.exports = invariant; 93455},{}],159:[function(_dereq_,module,exports){ 93456'use strict'; 93457 93458/** 93459 * Copyright (c) 2013-present, Facebook, Inc. 93460 * All rights reserved. 93461 * 93462 * This source code is licensed under the BSD-style license found in the 93463 * LICENSE file in the root directory of this source tree. An additional grant 93464 * of patent rights can be found in the PATENTS file in the same directory. 93465 * 93466 * @typechecks 93467 */ 93468 93469/** 93470 * @param {*} object The object to check. 93471 * @return {boolean} Whether or not the object is a DOM node. 93472 */ 93473function isNode(object) { 93474 return !!(object && (typeof Node === 'function' ? object instanceof Node : typeof object === 'object' && typeof object.nodeType === 'number' && typeof object.nodeName === 'string')); 93475} 93476 93477module.exports = isNode; 93478},{}],160:[function(_dereq_,module,exports){ 93479'use strict'; 93480 93481/** 93482 * Copyright (c) 2013-present, Facebook, Inc. 93483 * All rights reserved. 93484 * 93485 * This source code is licensed under the BSD-style license found in the 93486 * LICENSE file in the root directory of this source tree. An additional grant 93487 * of patent rights can be found in the PATENTS file in the same directory. 93488 * 93489 * @typechecks 93490 */ 93491 93492var isNode = _dereq_(159); 93493 93494/** 93495 * @param {*} object The object to check. 93496 * @return {boolean} Whether or not the object is a DOM text node. 93497 */ 93498function isTextNode(object) { 93499 return isNode(object) && object.nodeType == 3; 93500} 93501 93502module.exports = isTextNode; 93503},{"159":159}],161:[function(_dereq_,module,exports){ 93504/** 93505 * Copyright (c) 2013-present, Facebook, Inc. 93506 * All rights reserved. 93507 * 93508 * This source code is licensed under the BSD-style license found in the 93509 * LICENSE file in the root directory of this source tree. An additional grant 93510 * of patent rights can be found in the PATENTS file in the same directory. 93511 * 93512 * @typechecks static-only 93513 */ 93514 93515 93516 93517var invariant = _dereq_(158); 93518 93519/** 93520 * Constructs an enumeration with keys equal to their value. 93521 * 93522 * For example: 93523 * 93524 * var COLORS = keyMirror({blue: null, red: null}); 93525 * var myColor = COLORS.blue; 93526 * var isColorValid = !!COLORS[myColor]; 93527 * 93528 * The last line could not be performed if the values of the generated enum were 93529 * not equal to their keys. 93530 * 93531 * Input: {key1: val1, key2: val2} 93532 * Output: {key1: key1, key2: key2} 93533 * 93534 * @param {object} obj 93535 * @return {object} 93536 */ 93537var keyMirror = function (obj) { 93538 var ret = {}; 93539 var key; 93540 !(obj instanceof Object && !Array.isArray(obj)) ? "development" !== 'production' ? invariant(false, 'keyMirror(...): Argument must be an object.') : invariant(false) : void 0; 93541 for (key in obj) { 93542 if (!obj.hasOwnProperty(key)) { 93543 continue; 93544 } 93545 ret[key] = key; 93546 } 93547 return ret; 93548}; 93549 93550module.exports = keyMirror; 93551},{"158":158}],162:[function(_dereq_,module,exports){ 93552"use strict"; 93553 93554/** 93555 * Copyright (c) 2013-present, Facebook, Inc. 93556 * All rights reserved. 93557 * 93558 * This source code is licensed under the BSD-style license found in the 93559 * LICENSE file in the root directory of this source tree. An additional grant 93560 * of patent rights can be found in the PATENTS file in the same directory. 93561 * 93562 */ 93563 93564/** 93565 * Allows extraction of a minified key. Let's the build system minify keys 93566 * without losing the ability to dynamically use key strings as values 93567 * themselves. Pass in an object with a single key/val pair and it will return 93568 * you the string key of that single record. Suppose you want to grab the 93569 * value for a key 'className' inside of an object. Key/val minification may 93570 * have aliased that key to be 'xa12'. keyOf({className: null}) will return 93571 * 'xa12' in that case. Resolve keys you want to use once at startup time, then 93572 * reuse those resolutions. 93573 */ 93574var keyOf = function (oneKeyObj) { 93575 var key; 93576 for (key in oneKeyObj) { 93577 if (!oneKeyObj.hasOwnProperty(key)) { 93578 continue; 93579 } 93580 return key; 93581 } 93582 return null; 93583}; 93584 93585module.exports = keyOf; 93586},{}],163:[function(_dereq_,module,exports){ 93587/** 93588 * Copyright (c) 2013-present, Facebook, Inc. 93589 * All rights reserved. 93590 * 93591 * This source code is licensed under the BSD-style license found in the 93592 * LICENSE file in the root directory of this source tree. An additional grant 93593 * of patent rights can be found in the PATENTS file in the same directory. 93594 * 93595 */ 93596 93597 93598 93599var hasOwnProperty = Object.prototype.hasOwnProperty; 93600 93601/** 93602 * Executes the provided `callback` once for each enumerable own property in the 93603 * object and constructs a new object from the results. The `callback` is 93604 * invoked with three arguments: 93605 * 93606 * - the property value 93607 * - the property name 93608 * - the object being traversed 93609 * 93610 * Properties that are added after the call to `mapObject` will not be visited 93611 * by `callback`. If the values of existing properties are changed, the value 93612 * passed to `callback` will be the value at the time `mapObject` visits them. 93613 * Properties that are deleted before being visited are not visited. 93614 * 93615 * @grep function objectMap() 93616 * @grep function objMap() 93617 * 93618 * @param {?object} object 93619 * @param {function} callback 93620 * @param {*} context 93621 * @return {?object} 93622 */ 93623function mapObject(object, callback, context) { 93624 if (!object) { 93625 return null; 93626 } 93627 var result = {}; 93628 for (var name in object) { 93629 if (hasOwnProperty.call(object, name)) { 93630 result[name] = callback.call(context, object[name], name, object); 93631 } 93632 } 93633 return result; 93634} 93635 93636module.exports = mapObject; 93637},{}],164:[function(_dereq_,module,exports){ 93638/** 93639 * Copyright (c) 2013-present, Facebook, Inc. 93640 * All rights reserved. 93641 * 93642 * This source code is licensed under the BSD-style license found in the 93643 * LICENSE file in the root directory of this source tree. An additional grant 93644 * of patent rights can be found in the PATENTS file in the same directory. 93645 * 93646 * @typechecks static-only 93647 */ 93648 93649 93650 93651/** 93652 * Memoizes the return value of a function that accepts one string argument. 93653 * 93654 * @param {function} callback 93655 * @return {function} 93656 */ 93657 93658function memoizeStringOnly(callback) { 93659 var cache = {}; 93660 return function (string) { 93661 if (!cache.hasOwnProperty(string)) { 93662 cache[string] = callback.call(this, string); 93663 } 93664 return cache[string]; 93665 }; 93666} 93667 93668module.exports = memoizeStringOnly; 93669},{}],165:[function(_dereq_,module,exports){ 93670/** 93671 * Copyright (c) 2013-present, Facebook, Inc. 93672 * All rights reserved. 93673 * 93674 * This source code is licensed under the BSD-style license found in the 93675 * LICENSE file in the root directory of this source tree. An additional grant 93676 * of patent rights can be found in the PATENTS file in the same directory. 93677 * 93678 * @typechecks 93679 */ 93680 93681 93682 93683var ExecutionEnvironment = _dereq_(144); 93684 93685var performance; 93686 93687if (ExecutionEnvironment.canUseDOM) { 93688 performance = window.performance || window.msPerformance || window.webkitPerformance; 93689} 93690 93691module.exports = performance || {}; 93692},{"144":144}],166:[function(_dereq_,module,exports){ 93693'use strict'; 93694 93695/** 93696 * Copyright (c) 2013-present, Facebook, Inc. 93697 * All rights reserved. 93698 * 93699 * This source code is licensed under the BSD-style license found in the 93700 * LICENSE file in the root directory of this source tree. An additional grant 93701 * of patent rights can be found in the PATENTS file in the same directory. 93702 * 93703 * @typechecks 93704 */ 93705 93706var performance = _dereq_(165); 93707 93708var performanceNow; 93709 93710/** 93711 * Detect if we can use `window.performance.now()` and gracefully fallback to 93712 * `Date.now()` if it doesn't exist. We need to support Firefox < 15 for now
93713 * because of Facebook's testing infrastructure. 93714 */ 93715if (performance.now) { 93716 performanceNow = function () { 93717 return performance.now(); 93718 }; 93719} else { 93720 performanceNow = function () { 93721 return Date.now(); 93722 }; 93723} 93724 93725module.exports = performanceNow; 93726},{"165":165}],167:[function(_dereq_,module,exports){ 93727/** 93728 * Copyright (c) 2013-present, Facebook, Inc. 93729 * All rights reserved. 93730 * 93731 * This source code is licensed under the BSD-style license found in the 93732 * LICENSE file in the root directory of this source tree. An additional grant 93733 * of patent rights can be found in the PATENTS file in the same directory. 93734 * 93735 * @typechecks 93736 * 93737 */ 93738 93739/*eslint-disable no-self-compare */ 93740 93741 93742 93743var hasOwnProperty = Object.prototype.hasOwnProperty; 93744 93745/** 93746 * inlined Object.is polyfill to avoid requiring consumers ship their own 93747 * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is 93748 */ 93749function is(x, y) { 93750 // SameValue algorithm 93751 if (x === y) { 93752 // Steps 1-5, 7-10 93753 // Steps 6.b-6.e: +0 != -0 93754 return x !== 0 || 1 / x === 1 / y; 93755 } else { 93756 // Step 6.a: NaN == NaN 93757 return x !== x && y !== y; 93758 } 93759} 93760 93761/** 93762 * Performs equality by iterating through keys on an object and returning false 93763 * when any key has values which are not strictly equal between the arguments. 93764 * Returns true when the values of all keys are strictly equal. 93765 */ 93766function shallowEqual(objA, objB) { 93767 if (is(objA, objB)) { 93768 return true; 93769 } 93770 93771 if (typeof objA !== 'object' || objA === null || typeof objB !== 'object' || objB === null) { 93772 return false; 93773 } 93774 93775 var keysA = Object.keys(objA); 93776 var keysB = Object.keys(objB); 93777 93778 if (keysA.length !== keysB.length) { 93779 return false; 93780 } 93781 93782 // Test for A's keys different from B. 93783 for (var i = 0; i < keysA.length; i++) { 93784 if (!hasOwnProperty.call(objB, keysA[i]) || !is(objA[keysA[i]], objB[keysA[i]])) { 93785 return false; 93786 } 93787 } 93788 93789 return true; 93790} 93791 93792module.exports = shallowEqual; 93793},{}],168:[function(_dereq_,module,exports){ 93794/** 93795 * Copyright 2014-2015, Facebook, Inc. 93796 * All rights reserved. 93797 * 93798 * This source code is licensed under the BSD-style license found in the 93799 * LICENSE file in the root directory of this source tree. An additional grant 93800 * of patent rights can be found in the PATENTS file in the same directory. 93801 * 93802 */ 93803 93804 93805 93806var emptyFunction = _dereq_(150); 93807 93808/** 93809 * Similar to invariant but only logs a warning if the condition is not met. 93810 * This can be used to log issues in development environments in critical 93811 * paths. Removing the logging code for production environments will keep the 93812 * same logic and follow the same code paths. 93813 */ 93814 93815var warning = emptyFunction; 93816 93817if ("development" !== 'production') { 93818 warning = function (condition, format) { 93819 for (var _len = arguments.length, args = Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) { 93820 args[_key - 2] = arguments[_key]; 93821 } 93822 93823 if (format === undefined) { 93824 throw new Error('`warning(condition, format, ...args)` requires a warning ' + 'message argument'); 93825 } 93826 93827 if (format.indexOf('Failed Composite propType: ') === 0) { 93828 return; // Ignore CompositeComponent proptype check. 93829 } 93830 93831 if (!condition) { 93832 var argIndex = 0; 93833 var message = 'Warning: ' + format.replace(/%s/g, function () { 93834 return args[argIndex++]; 93835 }); 93836 if (typeof console !== 'undefined') { 93837 console.error(message); 93838 } 93839 try { 93840 // --- Welcome to debugging React --- 93841 // This error was thrown as a convenience so that you can use this stack 93842 // to find the callsite that caused this warning to fire. 93843 throw new Error(message); 93844 } catch (x) {} 93845 } 93846 }; 93847} 93848 93849module.exports = warning; 93850},{"150":150}],169:[function(_dereq_,module,exports){ 93851/* eslint-disable no-unused-vars */ 93852 93853var hasOwnProperty = Object.prototype.hasOwnProperty; 93854var propIsEnumerable = Object.prototype.propertyIsEnumerable; 93855 93856function toObject(val) { 93857 if (val === null || val === undefined) { 93858 throw new TypeError('Object.assign cannot be called with null or undefined'); 93859 } 93860 93861 return Object(val); 93862} 93863 93864module.exports = Object.assign || function (target, source) { 93865 var from; 93866 var to = toObject(target); 93867 var symbols; 93868 93869 for (var s = 1; s < arguments.length; s++) { 93870 from = Object(arguments[s]); 93871 93872 for (var key in from) { 93873 if (hasOwnProperty.call(from, key)) { 93874 to[key] = from[key]; 93875 } 93876 } 93877 93878 if (Object.getOwnPropertySymbols) { 93879 symbols = Object.getOwnPropertySymbols(from); 93880 for (var i = 0; i < symbols.length; i++) { 93881 if (propIsEnumerable.call(from, symbols[i])) { 93882 to[symbols[i]] = from[symbols[i]]; 93883 } 93884 } 93885 } 93886 } 93887 93888 return to; 93889}; 93890 93891},{}]},{},[92])(92) 93892}); 93893/** 93894 * ReactDOM v15.0.2 93895 * 93896 * Copyright 2013-present, Facebook, Inc. 93897 * All rights reserved. 93898 * 93899 * This source code is licensed under the BSD-style license found in the 93900 * LICENSE file in the root directory of this source tree. An additional grant 93901 * of patent rights can be found in the PATENTS file in the same directory. 93902 * 93903 */ 93904// Based off https://github.com/ForbesLindesay/umd/blob/master/template.js 93905;(function(f) { 93906 // CommonJS 93907 if (typeof exports === "object" && typeof module !== "undefined") { 93908 module.exports = f(require('react')); 93909 93910 // RequireJS 93911 } else if (typeof define === "function" && define.amd) { 93912 define('reactDom',['react'], f); 93913 93914 // <script> 93915 } else { 93916 var g; 93917 if (typeof window !== "undefined") { 93918 g = window; 93919 } else if (typeof global !== "undefined") { 93920 g = global; 93921 } else if (typeof self !== "undefined") { 93922 g = self; 93923 } else { 93924 // works providing we're not in "use strict"; 93925 // needed for Java 8 Nashorn 93926 // see https://github.com/facebook/react/issues/3037 93927 g = this; 93928 } 93929 g.ReactDOM = f(g.React); 93930 } 93931 93932})(function(React) { 93933 return React.__SECRET_DOM_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; 93934}); 93935 93936/* jquery.signalR.core.js */ 93937/*global window:false */ 93938/*! 93939 * ASP.NET SignalR JavaScript Library v2.2.1 93940 * http://signalr.net/ 93941 * 93942 * Copyright (c) .NET Foundation. All rights reserved. 93943 * Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 93944 * 93945 */ 93946 93947///// <reference path="Scripts/jquery-1.6.4.js" />
vendor: 4,466 bytes, lines 93948-94040
93948///// <reference path="jquery.signalR.version.js" /> 93949(function ($, window, undefined) { 93950 93951 var resources = { 93952 nojQuery: "jQuery was not found. Please ensure jQuery is referenced before the SignalR client JavaScript file.", 93953 noTransportOnInit: "No transport could be initialized successfully. Try specifying a different transport or none at all for auto initialization.", 93954 errorOnNegotiate: "Error during negotiation request.", 93955 stoppedWhileLoading: "The connection was stopped during page load.", 93956 stoppedWhileNegotiating: "The connection was stopped during the negotiate request.", 93957 errorParsingNegotiateResponse: "Error parsing negotiate response.", 93958 errorDuringStartRequest: "Error during start request. Stopping the connection.", 93959 stoppedDuringStartRequest: "The connection was stopped during the start request.", 93960 errorParsingStartResponse: "Error parsing start response: '{0}'. Stopping the connection.", 93961 invalidStartResponse: "Invalid start response: '{0}'. Stopping the connection.", 93962 protocolIncompatible: "You are using a version of the client that isn't compatible with the server. Client version {0}, server version {1}.", 93963 sendFailed: "Send failed.", 93964 parseFailed: "Failed at parsing response: {0}", 93965 longPollFailed: "Long polling request failed.", 93966 eventSourceFailedToConnect: "EventSource failed to connect.", 93967 eventSourceError: "Error raised by EventSource", 93968 webSocketClosed: "WebSocket closed.", 93969 pingServerFailedInvalidResponse: "Invalid ping response when pinging server: '{0}'.", 93970 pingServerFailed: "Failed to ping server.", 93971 pingServerFailedStatusCode: "Failed to ping server. Server responded with status code {0}, stopping the connection.", 93972 pingServerFailedParse: "Failed to parse ping server response, stopping the connection.", 93973 noConnectionTransport: "Connection is in an invalid state, there is no transport active.", 93974 webSocketsInvalidState: "The Web Socket transport is in an invalid state, transitioning into reconnecting.", 93975 reconnectTimeout: "Couldn't reconnect within the configured timeout of {0} ms, disconnecting.", 93976 reconnectWindowTimeout: "The client has been inactive since {0} and it has exceeded the inactivity timeout of {1} ms. Stopping the connection." 93977 }; 93978 93979 if (typeof ($) !== "function") { 93980 // no jQuery! 93981 throw new Error(resources.nojQuery); 93982 } 93983 93984 var signalR, 93985 _connection, 93986 _pageLoaded = (window.document.readyState === "complete"), 93987 _pageWindow = $(window), 93988 _negotiateAbortText = "__Negotiate Aborted__", 93989 events = { 93990 onStart: "onStart", 93991 onStarting: "onStarting", 93992 onReceived: "onReceived", 93993 onError: "onError", 93994 onConnectionSlow: "onConnectionSlow", 93995 onReconnecting: "onReconnecting", 93996 onReconnect: "onReconnect", 93997 onStateChanged: "onStateChanged", 93998 onDisconnect: "onDisconnect" 93999 }, 94000 ajaxDefaults = { 94001 processData: true, 94002 timeout: null, 94003 async: true, 94004 global: false, 94005 cache: false 94006 }, 94007 log = function (msg, logging) { 94008 if (logging === false) { 94009 return; 94010 } 94011 var m; 94012 if (typeof (window.console) === "undefined") { 94013 return; 94014 } 94015 m = "[" + new Date().toTimeString() + "] SignalR: " + msg; 94016 if (window.console.debug) { 94017 window.console.debug(m); 94018 } else if (window.console.log) { 94019 window.console.log(m); 94020 } 94021 }, 94022 94023 changeState = function (connection, expectedState, newState) { 94024 if (expectedState === connection.state) { 94025 connection.state = newState; 94026 94027 $(connection).triggerHandler(events.onStateChanged, [{ oldState: expectedState, newState: newState }]); 94028 return true; 94029 } 94030 94031 return false; 94032 }, 94033 94034 isDisconnecting = function (connection) { 94035 return connection.state === signalR.connectionState.disconnected; 94036 }, 94037 94038 supportsKeepAlive = function (connection) { 94039 return connection._.keepAliveData.activated && 94040
vendor: 6,071 bytes, lines 94040-94188
94040 connection.transport.supportsKeepAlive(connection); 94041 }, 94042 94043 configureStopReconnectingTimeout = function (connection) { 94044 var stopReconnectingTimeout, 94045 onReconnectTimeout; 94046 94047 // Check if this connection has already been configured to stop reconnecting after a specified timeout. 94048 // Without this check if a connection is stopped then started events will be bound multiple times. 94049 if (!connection._.configuredStopReconnectingTimeout) { 94050 onReconnectTimeout = function (connection) { 94051 var message = signalR._.format(signalR.resources.reconnectTimeout, connection.disconnectTimeout); 94052 connection.log(message); 94053 $(connection).triggerHandler(events.onError, [signalR._.error(message, /* source */ "TimeoutException")]); 94054 connection.stop(/* async */ false, /* notifyServer */ false); 94055 }; 94056 94057 connection.reconnecting(function () { 94058 var connection = this; 94059 94060 // Guard against state changing in a previous user defined even handler 94061 if (connection.state === signalR.connectionState.reconnecting) { 94062 stopReconnectingTimeout = window.setTimeout(function () { onReconnectTimeout(connection); }, connection.disconnectTimeout); 94063 } 94064 }); 94065 94066 connection.stateChanged(function (data) { 94067 if (data.oldState === signalR.connectionState.reconnecting) { 94068 // Clear the pending reconnect timeout check 94069 window.clearTimeout(stopReconnectingTimeout); 94070 } 94071 }); 94072 94073 connection._.configuredStopReconnectingTimeout = true; 94074 } 94075 }; 94076 94077 signalR = function (url, qs, logging) { 94078 /// <summary>Creates a new SignalR connection for the given url</summary> 94079 /// <param name="url" type="String">The URL of the long polling endpoint</param> 94080 /// <param name="qs" type="Object"> 94081 /// [Optional] Custom querystring parameters to add to the connection URL. 94082 /// If an object, every non-function member will be added to the querystring. 94083 /// If a string, it's added to the QS as specified. 94084 /// </param> 94085 /// <param name="logging" type="Boolean"> 94086 /// [Optional] A flag indicating whether connection logging is enabled to the browser 94087 /// console/log. Defaults to false. 94088 /// </param> 94089 94090 return new signalR.fn.init(url, qs, logging); 94091 }; 94092 94093 signalR._ = { 94094 defaultContentType: "application/x-www-form-urlencoded; charset=UTF-8", 94095 94096 ieVersion: (function () { 94097 var version, 94098 matches; 94099 94100 if (window.navigator.appName === 'Microsoft Internet Explorer') { 94101 // Check if the user agent has the pattern "MSIE (one or more numbers).(one or more numbers)"; 94102 matches = /MSIE ([0-9]+\.[0-9]+)/.exec(window.navigator.userAgent); 94103 94104 if (matches) { 94105 version = window.parseFloat(matches[1]); 94106 } 94107 } 94108 94109 // undefined value means not IE 94110 return version; 94111 })(), 94112 94113 error: function (message, source, context) { 94114 var e = new Error(message); 94115 e.source = source; 94116 94117 if (typeof context !== "undefined") { 94118 e.context = context; 94119 } 94120 94121 return e; 94122 }, 94123 94124 transportError: function (message, transport, source, context) { 94125 var e = this.error(message, source, context); 94126 e.transport = transport ? transport.name : undefined; 94127 return e; 94128 }, 94129 94130 format: function () { 94131 /// <summary>Usage: format("Hi {0}, you are {1}!", "Foo", 100) </summary> 94132 var s = arguments[0]; 94133 for (var i = 0; i < arguments.length - 1; i++) { 94134 s = s.replace("{" + i + "}", arguments[i + 1]); 94135 } 94136 return s; 94137 }, 94138 94139 firefoxMajorVersion: function (userAgent) { 94140 // Firefox user agents: http://useragentstring.com/pages/Firefox/ 94141 var matches = userAgent.match(/Firefox\/(\d+)/); 94142 if (!matches || !matches.length || matches.length < 2) { 94143 return 0; 94144 } 94145 return parseInt(matches[1], 10 /* radix */); 94146 }, 94147 94148 configurePingInterval: function (connection) { 94149 var config = connection._.config, 94150 onFail = function (error) { 94151 $(connection).triggerHandler(events.onError, [error]); 94152 }; 94153 94154 if (config && !connection._.pingIntervalId && config.pingInterval) { 94155 connection._.pingIntervalId = window.setInterval(function () { 94156 signalR.transports._logic.pingServer(connection).fail(onFail); 94157 }, config.pingInterval); 94158 } 94159 } 94160 }; 94161 94162 signalR.events = events; 94163 94164 signalR.resources = resources; 94165 94166 signalR.ajaxDefaults = ajaxDefaults; 94167 94168 signalR.changeState = changeState; 94169 94170 signalR.isDisconnecting = isDisconnecting; 94171 94172 signalR.connectionState = { 94173 connecting: 0, 94174 connected: 1, 94175 reconnecting: 2, 94176 disconnected: 4 94177 }; 94178 94179 signalR.hub = { 94180 start: function () { 94181 // This will get replaced with the real hub connection start method when hubs is referenced correctly 94182 throw new Error("SignalR: Error loading hubs. Ensure your hubs reference is correct, e.g. <script src='/signalr/js'></script>."); 94183 } 94184 }; 94185 94186 // .on() was added in version 1.7.0, .load() was removed in version 3.0.0 so we fallback to .load() if .on() does 94187 // not exist to not break existing applications 94188 if (typeof _pageWindow.on ==
vendor: 32,723 bytes, lines 94188-94887
94188 "function") { 94189 _pageWindow.on("load", function () { _pageLoaded = true; }); 94190 } 94191 else { 94192 _pageWindow.load(function () { _pageLoaded = true; }); 94193 } 94194 94195 function validateTransport(requestedTransport, connection) { 94196 /// <summary>Validates the requested transport by cross checking it with the pre-defined signalR.transports</summary> 94197 /// <param name="requestedTransport" type="Object">The designated transports that the user has specified.</param> 94198 /// <param name="connection" type="signalR">The connection that will be using the requested transports. Used for logging purposes.</param> 94199 /// <returns type="Object" /> 94200 94201 if ($.isArray(requestedTransport)) { 94202 // Go through transport array and remove an "invalid" tranports 94203 for (var i = requestedTransport.length - 1; i >= 0; i--) { 94204 var transport = requestedTransport[i]; 94205 if ($.type(transport) !== "string" || !signalR.transports[transport]) { 94206 connection.log("Invalid transport: " + transport + ", removing it from the transports list."); 94207 requestedTransport.splice(i, 1); 94208 } 94209 } 94210 94211 // Verify we still have transports left, if we dont then we have invalid transports 94212 if (requestedTransport.length === 0) { 94213 connection.log("No transports remain within the specified transport array."); 94214 requestedTransport = null; 94215 } 94216 } else if (!signalR.transports[requestedTransport] && requestedTransport !== "auto") { 94217 connection.log("Invalid transport: " + requestedTransport.toString() + "."); 94218 requestedTransport = null; 94219 } else if (requestedTransport === "auto" && signalR._.ieVersion <= 8) { 94220 // If we're doing an auto transport and we're IE8 then force longPolling, #1764 94221 return ["longPolling"]; 94222 94223 } 94224 94225 return requestedTransport; 94226 } 94227 94228 function getDefaultPort(protocol) { 94229 if (protocol === "http:") { 94230 return 80; 94231 } else if (protocol === "https:") { 94232 return 443; 94233 } 94234 } 94235 94236 function addDefaultPort(protocol, url) { 94237 // Remove ports from url. We have to check if there's a / or end of line 94238 // following the port in order to avoid removing ports such as 8080. 94239 if (url.match(/:\d+$/)) { 94240 return url; 94241 } else { 94242 return url + ":" + getDefaultPort(protocol); 94243 } 94244 } 94245 94246 function ConnectingMessageBuffer(connection, drainCallback) { 94247 var that = this, 94248 buffer = []; 94249 94250 that.tryBuffer = function (message) { 94251 if (connection.state === $.signalR.connectionState.connecting) { 94252 buffer.push(message); 94253 94254 return true; 94255 } 94256 94257 return false; 94258 }; 94259 94260 that.drain = function () { 94261 // Ensure that the connection is connected when we drain (do not want to drain while a connection is not active) 94262 if (connection.state === $.signalR.connectionState.connected) { 94263 while (buffer.length > 0) { 94264 drainCallback(buffer.shift()); 94265 } 94266 } 94267 }; 94268 94269 that.clear = function () { 94270 buffer = []; 94271 }; 94272 } 94273 94274 signalR.fn = signalR.prototype = { 94275 init: function (url, qs, logging) { 94276 var $connection = $(this); 94277 94278 this.url = url; 94279 this.qs = qs; 94280 this.lastError = null; 94281 this._ = { 94282 keepAliveData: {}, 94283 connectingMessageBuffer: new ConnectingMessageBuffer(this, function (message) { 94284 $connection.triggerHandler(events.onReceived, [message]); 94285 }), 94286 lastMessageAt: new Date().getTime(), 94287 lastActiveAt: new Date().getTime(), 94288 beatInterval: 5000, // Default value, will only be overridden if keep alive is enabled, 94289 beatHandle: null, 94290 totalTransportConnectTimeout: 0 // This will be the sum of the TransportConnectTimeout sent in response to negotiate and connection.transportConnectTimeout 94291 }; 94292 if (typeof (logging) === "boolean") { 94293 this.logging = logging; 94294 } 94295 }, 94296 94297 _parseResponse: function (response) { 94298 var that = this; 94299 94300 if (!response) { 94301 return response; 94302 } else if (typeof response === "string") { 94303 return that.json.parse(response); 94304 } else { 94305 return response; 94306 } 94307 }, 94308 94309 _originalJson: window.JSON, 94310 94311 json: window.JSON, 94312 94313 isCrossDomain: function (url, against) { 94314 /// <summary>Checks if url is cross domain</summary> 94315 /// <param name="url" type="String">The base URL</param> 94316 /// <param name="against" type="Object"> 94317 /// An optional argument to compare the URL against, if not specified it will be set to window.location. 94318 /// If specified it must contain a protocol and a host property. 94319 /// </param> 94320 var link; 94321 94322 url = $.trim(url); 94323 94324 against = against || window.location; 94325 94326 if (url.indexOf("http") !== 0) { 94327 return false; 94328 } 94329 94330 // Create an anchor tag. 94331 link = window.document.createElement("a"); 94332 link.href = url; 94333 94334 // When checking for cross domain we have to special case port 80 because the window.location will remove the 94335 return link.protocol + addDefaultPort(link.protocol, link.host) !== against.protocol + addDefaultPort(against.protocol, against.host); 94336 }, 94337 94338 ajaxDataType: "text", 94339 94340 contentType: "application/json; charset=UTF-8", 94341 94342 logging: false, 94343 94344 state: signalR.connectionState.disconnected, 94345 94346 clientProtocol: "1.5", 94347 94348 reconnectDelay: 2000, 94349 94350 transportConnectTimeout: 0, 94351 94352 disconnectTimeout: 30000, // This should be set by the server in response to the negotiate request (30s default) 94353 94354 reconnectWindow: 30000, // This should be set by the server in response to the negotiate request 94355 94356 keepAliveWarnAt: 2 / 3, // Warn user of slow connection if we breach the X% mark of the keep alive timeout 94357 94358 start: function (options, callback) { 94359 /// <summary>Starts the connection</summary> 94360 /// <param name="options" type="Object">Options map</param> 94361 /// <param name="callback" type="Function">A callback function to execute when the connection has started</param> 94362 var connection = this, 94363 config = { 94364 pingInterval: 300000, 94365 waitForPageLoad: true, 94366 transport: "auto", 94367 jsonp: false 94368 }, 94369 initialize, 94370 deferred = connection._deferral || $.Deferred(), // Check to see if there is a pre-existing deferral that's being built on, if so we want to keep using it 94371 parser = window.document.createElement("a"); 94372 94373 connection.lastError = null; 94374 94375 // Persist the deferral so that if start is called multiple times the same deferral is used. 94376 connection._deferral = deferred; 94377 94378 if (!connection.json) { 94379 // no JSON! 94380 throw new Error("SignalR: No JSON parser found. Please ensure json2.js is referenced before the SignalR.js file if you need to support clients without native JSON parsing support, e.g. IE<8."); 94381 } 94382 94383 if ($.type(options) === "function") { 94384 // Support calling with single callback parameter 94385 callback = options; 94386 } else if ($.type(options) === "object") { 94387 $.extend(config, options); 94388 if ($.type(config.callback) === "function") { 94389 callback = config.callback; 94390 } 94391 } 94392 94393 config.transport = validateTransport(config.transport, connection); 94394 94395 // If the transport is invalid throw an error and abort start 94396 if (!config.transport) { 94397 throw new Error("SignalR: Invalid transport(s) specified, aborting start."); 94398 } 94399 94400 connection._.config = config; 94401 94402 // Check to see if start is being called prior to page load 94403 // If waitForPageLoad is true we then want to re-direct function call to the window load event 94404 if (!_pageLoaded && config.waitForPageLoad === true) { 94405 connection._.deferredStartHandler = function () { 94406 connection.start(options, callback); 94407 }; 94408 _pageWindow.bind("load", connection._.deferredStartHandler); 94409 94410 return deferred.promise(); 94411 } 94412 94413 // If we're already connecting just return the same deferral as the original connection start 94414 if (connection.state === signalR.connectionState.connecting) { 94415 return deferred.promise(); 94416 } else if (changeState(connection, 94417 signalR.connectionState.disconnected, 94418 signalR.connectionState.connecting) === false) { 94419 // We're not connecting so try and transition into connecting. 94420 // If we fail to transition then we're either in connected or reconnecting. 94421 94422 deferred.resolve(connection); 94423 return deferred.promise(); 94424 } 94425 94426 configureStopReconnectingTimeout(connection); 94427 94428 // Resolve the full url 94429 parser.href = connection.url; 94430 if (!parser.protocol || parser.protocol === ":") { 94431 connection.protocol = window.document.location.protocol; 94432 connection.host = parser.host || window.document.location.host; 94433 } else { 94434 connection.protocol = parser.protocol; 94435 connection.host = parser.host; 94436 } 94437 94438 connection.baseUrl = connection.protocol + "//" + connection.host; 94439 94440 // Set the websocket protocol 94441 connection.wsProtocol = connection.protocol === "https:" ? "wss://" : "ws://"; 94442 94443 // If jsonp with no/auto transport is specified, then set the transport to long polling 94444 // since that is the only transport for which jsonp really makes sense. 94445 // Some developers might actually choose to specify jsonp for same origin requests 94446 // as demonstrated by Issue #623. 94447 if (config.transport === "auto" && config.jsonp === true) { 94448 config.transport = "longPolling"; 94449 } 94450 94451 // If the url is protocol relative, prepend the current windows protocol to the url. 94452 if (connection.url.indexOf("//") === 0) { 94453 connection.url = window.location.protocol + connection.url; 94454 connection.log("Protocol relative URL detected, normalizing it to '" + connection.url + "'."); 94455 } 94456 94457 if (this.isCrossDomain(connection.url)) { 94458 connection.log("Auto detected cross domain url."); 94459 94460 if (config.transport === "auto") { 94461 // TODO: Support XDM with foreverFrame 94462 config.transport = ["webSockets", "serverSentEvents", "longPolling"]; 94463 } 94464 94465 if (typeof (config.withCredentials) === "undefined") { 94466 config.withCredentials = true; 94467 } 94468 94469 // Determine if jsonp is the only choice for negotiation, ajaxSend and ajaxAbort. 94470 // i.e. if the browser doesn't supports CORS 94471 // If it is, ignore any preference to the contrary, and switch to jsonp. 94472 if (!config.jsonp) { 94473 config.jsonp = !$.support.cors; 94474 94475 if (config.jsonp) { 94476 connection.log("Using jsonp because this browser doesn't support CORS."); 94477 } 94478 } 94479 94480 connection.contentType = signalR._.defaultContentType; 94481 } 94482 94483 connection.withCredentials = config.withCredentials; 94484 94485 connection.ajaxDataType = config.jsonp ? "jsonp" : "text"; 94486 94487 $(connection).bind(events.onStart, function (e, data) { 94488 if ($.type(callback) === "function") { 94489 callback.call(connection); 94490 } 94491 deferred.resolve(connection); 94492 }); 94493 94494 connection._.initHandler = signalR.transports._logic.initHandler(connection); 94495 94496 initialize = function (transports, index) { 94497 var noTransportError = signalR._.error(resources.noTransportOnInit); 94498 94499 index = index || 0; 94500 if (index >= transports.length) { 94501 if (index === 0) { 94502 connection.log("No transports supported by the server were selected."); 94503 } else if (index === 1) { 94504 connection.log("No fallback transports were selected."); 94505 } else { 94506 connection.log("Fallback transports exhausted."); 94507 } 94508 94509 // No transport initialized successfully 94510 $(connection).triggerHandler(events.onError, [noTransportError]); 94511 deferred.reject(noTransportError); 94512 // Stop the connection if it has connected and move it into the disconnected state 94513 connection.stop(); 94514 return; 94515 } 94516 94517 // The connection was aborted 94518 if (connection.state === signalR.connectionState.disconnected) { 94519 return; 94520 } 94521 94522 var transportName = transports[index], 94523 transport = signalR.transports[transportName], 94524 onFallback = function () { 94525 initialize(transports, index + 1); 94526 }; 94527 94528 connection.transport = transport; 94529 94530 try { 94531 connection._.initHandler.start(transport, function () { // success 94532 // Firefox 11+ doesn't allow sync XHR withCredentials: https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest#withCredentials 94533 var isFirefox11OrGreater = signalR._.firefoxMajorVersion(window.navigator.userAgent) >= 11, 94534 asyncAbort = !!connection.withCredentials && isFirefox11OrGreater; 94535 94536 connection.log("The start request succeeded. Transitioning to the connected state."); 94537 94538 if (supportsKeepAlive(connection)) { 94539 signalR.transports._logic.monitorKeepAlive(connection); 94540 } 94541 94542 signalR.transports._logic.startHeartbeat(connection); 94543 94544 // Used to ensure low activity clients maintain their authentication. 94545 // Must be configured once a transport has been decided to perform valid ping requests. 94546 signalR._.configurePingInterval(connection); 94547 94548 if (!changeState(connection, 94549 signalR.connectionState.connecting, 94550 signalR.connectionState.connected)) { 94551 connection.log("WARNING! The connection was not in the connecting state."); 94552 } 94553 94554 // Drain any incoming buffered messages (messages that came in prior to connect) 94555 connection._.connectingMessageBuffer.drain(); 94556 94557 $(connection).triggerHandler(events.onStart); 94558 94559 // wire the stop handler for when the user leaves the page 94560 _pageWindow.bind("unload", function () { 94561 connection.log("Window unloading, stopping the connection."); 94562 94563 connection.stop(asyncAbort); 94564 }); 94565 94566 if (isFirefox11OrGreater) { 94567 // Firefox does not fire cross-domain XHRs in the normal unload handler on tab close. 94568 // #2400 94569 _pageWindow.bind("beforeunload", function () { 94570 // If connection.stop() runs runs in beforeunload and fails, it will also fail 94571 // in unload unless connection.stop() runs after a timeout. 94572 window.setTimeout(function () { 94573 connection.stop(asyncAbort); 94574 }, 0); 94575 }); 94576 } 94577 }, onFallback); 94578 } 94579 catch (error) { 94580 connection.log(transport.name + " transport threw '" + error.message + "' when attempting to start."); 94581 onFallback(); 94582 } 94583 }; 94584 94585 var url = connection.url + "/negotiate", 94586 onFailed = function (error, connection) { 94587 var err = signalR._.error(resources.errorOnNegotiate, error, connection._.negotiateRequest); 94588 94589 $(connection).triggerHandler(events.onError, err); 94590 deferred.reject(err); 94591 // Stop the connection if negotiate failed 94592 connection.stop(); 94593 }; 94594 94595 $(connection).triggerHandler(events.onStarting); 94596 94597 url = signalR.transports._logic.prepareQueryString(connection, url); 94598 94599 connection.log("Negotiating with '" + url + "'."); 94600 94601 // Save the ajax negotiate request object so we can abort it if stop is called while the request is in flight. 94602 connection._.negotiateRequest = signalR.transports._logic.ajax(connection, { 94603 url: url, 94604 error: function (error, statusText) { 94605 // We don't want to cause any errors if we're aborting our own negotiate request. 94606 if (statusText !== _negotiateAbortText) { 94607 onFailed(error, connection); 94608 } else { 94609 // This rejection will noop if the deferred has already been resolved or rejected. 94610 deferred.reject(signalR._.error(resources.stoppedWhileNegotiating, null /* error */, connection._.negotiateRequest)); 94611 } 94612 }, 94613 success: function (result) { 94614 var res, 94615 keepAliveData, 94616 protocolError, 94617 transports = [], 94618 supportedTransports = []; 94619 94620 try { 94621 res = connection._parseResponse(result); 94622 } catch (error) { 94623 onFailed(signalR._.error(resources.errorParsingNegotiateResponse, error), connection); 94624 return; 94625 } 94626 94627 keepAliveData = connection._.keepAliveData; 94628 connection.appRelativeUrl = res.Url; 94629 connection.id = res.ConnectionId; 94630 connection.token = res.ConnectionToken; 94631 connection.webSocketServerUrl = res.WebSocketServerUrl; 94632 94633 // The long poll timeout is the ConnectionTimeout plus 10 seconds 94634 connection._.pollTimeout = res.ConnectionTimeout * 1000 + 10000; // in ms 94635 94636 // Once the server has labeled the PersistentConnection as Disconnected, we should stop attempting to reconnect 94637 // after res.DisconnectTimeout seconds. 94638 connection.disconnectTimeout = res.DisconnectTimeout * 1000; // in ms 94639 94640 // Add the TransportConnectTimeout from the response to the transportConnectTimeout from the client to calculate the total timeout 94641 connection._.totalTransportConnectTimeout = connection.transportConnectTimeout + res.TransportConnectTimeout * 1000; 94642 94643 // If we have a keep alive 94644 if (res.KeepAliveTimeout) { 94645 // Register the keep alive data as activated 94646 keepAliveData.activated = true; 94647 94648 // Timeout to designate when to force the connection into reconnecting converted to milliseconds 94649 keepAliveData.timeout = res.KeepAliveTimeout * 1000; 94650 94651 // Timeout to designate when to warn the developer that the connection may be dead or is not responding. 94652 keepAliveData.timeoutWarning = keepAliveData.timeout * connection.keepAliveWarnAt; 94653 94654 // Instantiate the frequency in which we check the keep alive. It must be short in order to not miss/pick up any changes 94655 connection._.beatInterval = (keepAliveData.timeout - keepAliveData.timeoutWarning) / 3; 94656 } else { 94657 keepAliveData.activated = false; 94658 } 94659 94660 connection.reconnectWindow = connection.disconnectTimeout + (keepAliveData.timeout || 0); 94661 94662 if (!res.ProtocolVersion || res.ProtocolVersion !== connection.clientProtocol) { 94663 protocolError = signalR._.error(signalR._.format(resources.protocolIncompatible, connection.clientProtocol, res.ProtocolVersion)); 94664 $(connection).triggerHandler(events.onError, [protocolError]); 94665 deferred.reject(protocolError); 94666 94667 return; 94668 } 94669 94670 $.each(signalR.transports, function (key) { 94671 if ((key.indexOf("_") === 0) || (key === "webSockets" && !res.TryWebSockets)) { 94672 return true; 94673 } 94674 supportedTransports.push(key); 94675 }); 94676 94677 if ($.isArray(config.transport)) { 94678 $.each(config.transport, function (_, transport) { 94679 if ($.inArray(transport, supportedTransports) >= 0) { 94680 transports.push(transport); 94681 } 94682 }); 94683 } else if (config.transport === "auto") { 94684 transports = supportedTransports; 94685 } else if ($.inArray(config.transport, supportedTransports) >= 0) { 94686 transports.push(config.transport); 94687 } 94688 94689 initialize(transports); 94690 } 94691 }); 94692 94693 return deferred.promise(); 94694 }, 94695 94696 starting: function (callback) { 94697 /// <summary>Adds a callback that will be invoked before anything is sent over the connection</summary> 94698 /// <param name="callback" type="Function">A callback function to execute before the connection is fully instantiated.</param> 94699 /// <returns type="signalR" /> 94700 var connection = this; 94701 $(connection).bind(events.onStarting, function (e, data) { 94702 callback.call(connection); 94703 }); 94704 return connection; 94705 }, 94706 94707 send: function (data) { 94708 /// <summary>Sends data over the connection</summary> 94709 /// <param name="data" type="String">The data to send over the connection</param> 94710 /// <returns type="signalR" /> 94711 var connection = this; 94712 94713 if (connection.state === signalR.connectionState.disconnected) { 94714 // Connection hasn't been started yet 94715 throw new Error("SignalR: Connection must be started before data can be sent. Call .start() before .send()"); 94716 } 94717 94718 if (connection.state === signalR.connectionState.connecting) { 94719 // Connection hasn't been started yet 94720 throw new Error("SignalR: Connection has not been fully initialized. Use .start().done() or .start().fail() to run logic after the connection has started."); 94721 } 94722 94723 connection.transport.send(connection, data); 94724 // REVIEW: Should we return deferred here? 94725 return connection; 94726 }, 94727 94728 received: function (callback) { 94729 /// <summary>Adds a callback that will be invoked after anything is received over the connection</summary> 94730 /// <param name="callback" type="Function">A callback function to execute when any data is received on the connection</param> 94731 /// <returns type="signalR" /> 94732 var connection = this; 94733 $(connection).bind(events.onReceived, function (e, data) { 94734 callback.call(connection, data); 94735 }); 94736 return connection; 94737 }, 94738 94739 stateChanged: function (callback) { 94740 /// <summary>Adds a callback that will be invoked when the connection state changes</summary> 94741 /// <param name="callback" type="Function">A callback function to execute when the connection state changes</param> 94742 /// <returns type="signalR" /> 94743 var connection = this; 94744 $(connection).bind(events.onStateChanged, function (e, data) { 94745 callback.call(connection, data); 94746 }); 94747 return connection; 94748 }, 94749 94750 error: function (callback) { 94751 /// <summary>Adds a callback that will be invoked after an error occurs with the connection</summary> 94752 /// <param name="callback" type="Function">A callback function to execute when an error occurs on the connection</param> 94753 /// <returns type="signalR" /> 94754 var connection = this; 94755 $(connection).bind(events.onError, function (e, errorData, sendData) { 94756 connection.lastError = errorData; 94757 // In practice 'errorData' is the SignalR built error object. 94758 // In practice 'sendData' is undefined for all error events except those triggered by 94759 // 'ajaxSend' and 'webSockets.send'.'sendData' is the original send payload. 94760 callback.call(connection, errorData, sendData); 94761 }); 94762 return connection; 94763 }, 94764 94765 disconnected: function (callback) { 94766 /// <summary>Adds a callback that will be invoked when the client disconnects</summary> 94767 /// <param name="callback" type="Function">A callback function to execute when the connection is broken</param> 94768 /// <returns type="signalR" /> 94769 var connection = this; 94770 $(connection).bind(events.onDisconnect, function (e, data) { 94771 callback.call(connection); 94772 }); 94773 return connection; 94774 }, 94775 94776 connectionSlow: function (callback) { 94777 /// <summary>Adds a callback that will be invoked when the client detects a slow connection</summary> 94778 /// <param name="callback" type="Function">A callback function to execute when the connection is slow</param> 94779 /// <returns type="signalR" /> 94780 var connection = this; 94781 $(connection).bind(events.onConnectionSlow, function (e, data) { 94782 callback.call(connection); 94783 }); 94784 94785 return connection; 94786 }, 94787 94788 reconnecting: function (callback) { 94789 /// <summary>Adds a callback that will be invoked when the underlying transport begins reconnecting</summary> 94790 /// <param name="callback" type="Function">A callback function to execute when the connection enters a reconnecting state</param> 94791 /// <returns type="signalR" /> 94792 var connection = this; 94793 $(connection).bind(events.onReconnecting, function (e, data) { 94794 callback.call(connection); 94795 }); 94796 return connection; 94797 }, 94798 94799 reconnected: function (callback) { 94800 /// <summary>Adds a callback that will be invoked when the underlying transport reconnects</summary> 94801 /// <param name="callback" type="Function">A callback function to execute when the connection is restored</param> 94802 /// <returns type="signalR" /> 94803 var connection = this; 94804 $(connection).bind(events.onReconnect, function (e, data) { 94805 callback.call(connection); 94806 }); 94807 return connection; 94808 }, 94809 94810 stop: function (async, notifyServer) { 94811 /// <summary>Stops listening</summary> 94812 /// <param name="async" type="Boolean">Whether or not to asynchronously abort the connection</param> 94813 /// <param name="notifyServer" type="Boolean">Whether we want to notify the server that we are aborting the connection</param> 94814 /// <returns type="signalR" /> 94815 var connection = this, 94816 // Save deferral because this is always cleaned up 94817 deferral = connection._deferral; 94818 94819 // Verify that we've bound a load event. 94820 if (connection._.deferredStartHandler) { 94821 // Unbind the event. 94822 _pageWindow.unbind("load", connection._.deferredStartHandler); 94823 } 94824 94825 // Always clean up private non-timeout based state. 94826 delete connection._.config; 94827 delete connection._.deferredStartHandler; 94828 94829 // This needs to be checked despite the connection state because a connection start can be deferred until page load. 94830 // If we've deferred the start due to a page load we need to unbind the "onLoad" -> start event. 94831 if (!_pageLoaded && (!connection._.config || connection._.config.waitForPageLoad === true)) { 94832 connection.log("Stopping connection prior to negotiate."); 94833 94834 // If we have a deferral we should reject it 94835 if (deferral) { 94836 deferral.reject(signalR._.error(resources.stoppedWhileLoading)); 94837 } 94838 94839 // Short-circuit because the start has not been fully started. 94840 return; 94841 } 94842 94843 if (connection.state === signalR.connectionState.disconnected) { 94844 return; 94845 } 94846 94847 connection.log("Stopping connection."); 94848 94849 // Clear this no matter what 94850 window.clearTimeout(connection._.beatHandle); 94851 window.clearInterval(connection._.pingIntervalId); 94852 94853 if (connection.transport) { 94854 connection.transport.stop(connection); 94855 94856 if (notifyServer !== false) { 94857 connection.transport.abort(connection, async); 94858 } 94859 94860 if (supportsKeepAlive(connection)) { 94861 signalR.transports._logic.stopMonitoringKeepAlive(connection); 94862 } 94863 94864 connection.transport = null; 94865 } 94866 94867 if (connection._.negotiateRequest) { 94868 // If the negotiation request has already completed this will noop. 94869 connection._.negotiateRequest.abort(_negotiateAbortText); 94870 delete connection._.negotiateRequest; 94871 } 94872 94873 // Ensure that initHandler.stop() is called before connection._deferral is deleted 94874 if (connection._.initHandler) { 94875 connection._.initHandler.stop(); 94876 } 94877 94878 delete connection._deferral; 94879 delete connection.messageId; 94880 delete connection.groupsToken; 94881 delete connection.id; 94882 delete connection._.pingIntervalId; 94883 delete connection._.lastMessageAt; 94884 delete connection._.lastActiveAt; 94885 94886 // Clear out our message buffer 94887 connection._.connectingMessageBuffer.clear()
vendor: 8,847 bytes, lines 94887-95123
94887; 94888 94889 // Trigger the disconnect event 94890 changeState(connection, connection.state, signalR.connectionState.disconnected); 94891 $(connection).triggerHandler(events.onDisconnect); 94892 94893 return connection; 94894 }, 94895 94896 log: function (msg) { 94897 log(msg, this.logging); 94898 } 94899 }; 94900 94901 signalR.fn.init.prototype = signalR.fn; 94902 94903 signalR.noConflict = function () { 94904 /// <summary>Reinstates the original value of $.connection and returns the signalR object for manual assignment</summary> 94905 /// <returns type="signalR" /> 94906 if ($.connection === signalR) { 94907 $.connection = _connection; 94908 } 94909 return signalR; 94910 }; 94911 94912 if ($.connection) { 94913 _connection = $.connection; 94914 } 94915 94916 $.connection = $.signalR = signalR; 94917 94918}(window.jQuery, window)); 94919/* jquery.signalR.transports.common.js */ 94920// Copyright (c) .NET Foundation. All rights reserved. 94921// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 94922 94923/*global window:false */ 94924/// <reference path="jquery.signalR.core.js" /> 94925 94926(function ($, window, undefined) { 94927 94928 var signalR = $.signalR, 94929 events = $.signalR.events, 94930 changeState = $.signalR.changeState, 94931 startAbortText = "__Start Aborted__", 94932 transportLogic; 94933 94934 signalR.transports = {}; 94935 94936 function beat(connection) { 94937 if (connection._.keepAliveData.monitoring) { 94938 checkIfAlive(connection); 94939 } 94940 94941 // Ensure that we successfully marked active before continuing the heartbeat. 94942 if (transportLogic.markActive(connection)) { 94943 connection._.beatHandle = window.setTimeout(function () { 94944 beat(connection); 94945 }, connection._.beatInterval); 94946 } 94947 } 94948 94949 function checkIfAlive(connection) { 94950 var keepAliveData = connection._.keepAliveData, 94951 timeElapsed; 94952 94953 // Only check if we're connected 94954 if (connection.state === signalR.connectionState.connected) { 94955 timeElapsed = new Date().getTime() - connection._.lastMessageAt; 94956 94957 // Check if the keep alive has completely timed out 94958 if (timeElapsed >= keepAliveData.timeout) { 94959 connection.log("Keep alive timed out. Notifying transport that connection has been lost."); 94960 94961 // Notify transport that the connection has been lost 94962 connection.transport.lostConnection(connection); 94963 } else if (timeElapsed >= keepAliveData.timeoutWarning) { 94964 // This is to assure that the user only gets a single warning 94965 if (!keepAliveData.userNotified) { 94966 connection.log("Keep alive has been missed, connection may be dead/slow."); 94967 $(connection).triggerHandler(events.onConnectionSlow); 94968 keepAliveData.userNotified = true; 94969 } 94970 } else { 94971 keepAliveData.userNotified = false; 94972 } 94973 } 94974 } 94975 94976 function getAjaxUrl(connection, path) { 94977 var url = connection.url + path; 94978 94979 if (connection.transport) { 94980 url += "?transport=" + connection.transport.name; 94981 } 94982 94983 return transportLogic.prepareQueryString(connection, url); 94984 } 94985 94986 function InitHandler(connection) { 94987 this.connection = connection; 94988 94989 this.startRequested = false; 94990 this.startCompleted = false; 94991 this.connectionStopped = false; 94992 } 94993 94994 InitHandler.prototype = { 94995 start: function (transport, onSuccess, onFallback) { 94996 var that = this, 94997 connection = that.connection, 94998 failCalled = false; 94999 95000 if (that.startRequested || that.connectionStopped) { 95001 connection.log("WARNING! " + transport.name + " transport cannot be started. Initialization ongoing or completed."); 95002 return; 95003 } 95004 95005 connection.log(transport.name + " transport starting."); 95006 95007 transport.start(connection, function () { 95008 if (!failCalled) { 95009 that.initReceived(transport, onSuccess); 95010 } 95011 }, function (error) { 95012 // Don't allow the same transport to cause onFallback to be called twice 95013 if (!failCalled) { 95014 failCalled = true; 95015 that.transportFailed(transport, error, onFallback); 95016 } 95017 95018 // Returns true if the transport should stop; 95019 // false if it should attempt to reconnect 95020 return !that.startCompleted || that.connectionStopped; 95021 }); 95022 95023 that.transportTimeoutHandle = window.setTimeout(function () { 95024 if (!failCalled) { 95025 failCalled = true; 95026 connection.log(transport.name + " transport timed out when trying to connect."); 95027 that.transportFailed(transport, undefined, onFallback); 95028 } 95029 }, connection._.totalTransportConnectTimeout); 95030 }, 95031 95032 stop: function () { 95033 this.connectionStopped = true; 95034 window.clearTimeout(this.transportTimeoutHandle); 95035 signalR.transports._logic.tryAbortStartRequest(this.connection); 95036 }, 95037 95038 initReceived: function (transport, onSuccess) { 95039 var that = this, 95040 connection = that.connection; 95041 95042 if (that.startRequested) { 95043 connection.log("WARNING! The client received multiple init messages."); 95044 return; 95045 } 95046 95047 if (that.connectionStopped) { 95048 return; 95049 } 95050 95051 that.startRequested = true; 95052 window.clearTimeout(that.transportTimeoutHandle); 95053 95054 connection.log(transport.name + " transport connected. Initiating start request."); 95055 signalR.transports._logic.ajaxStart(connection, function () { 95056 that.startCompleted = true; 95057 onSuccess(); 95058 }); 95059 }, 95060 95061 transportFailed: function (transport, error, onFallback) { 95062 var connection = this.connection, 95063 deferred = connection._deferral, 95064 wrappedError; 95065 95066 if (this.connectionStopped) { 95067 return; 95068 } 95069 95070 window.clearTimeout(this.transportTimeoutHandle); 95071 95072 if (!this.startRequested) { 95073 transport.stop(connection); 95074 95075 connection.log(transport.name + " transport failed to connect. Attempting to fall back."); 95076 onFallback(); 95077 } else if (!this.startCompleted) { 95078 // Do not attempt to fall back if a start request is ongoing during a transport failure. 95079 // Instead, trigger an error and stop the connection. 95080 wrappedError = signalR._.error(signalR.resources.errorDuringStartRequest, error); 95081 95082 connection.log(transport.name + " transport failed during the start request. Stopping the connection."); 95083 $(connection).triggerHandler(events.onError, [wrappedError]); 95084 if (deferred) { 95085 deferred.reject(wrappedError); 95086 } 95087 95088 connection.stop(); 95089 } else { 95090 // The start request has completed, but the connection has not stopped. 95091 // No need to do anything here. The transport should attempt its normal reconnect logic. 95092 } 95093 } 95094 }; 95095 95096 transportLogic = signalR.transports._logic = { 95097 ajax: function (connection, options) { 95098 return $.ajax( 95099 $.extend(/*deep copy*/ true, {}, $.signalR.ajaxDefaults, { 95100 type: "GET", 95101 data: {}, 95102 xhrFields: { withCredentials: connection.withCredentials }, 95103 contentType: connection.contentType, 95104 dataType: connection.ajaxDataType 95105 }, options)); 95106 }, 95107 95108 pingServer: function (connection) { 95109 /// <summary>Pings the server</summary> 95110 /// <param name="connection" type="signalr">Connection associated with the server ping</param> 95111 /// <returns type="signalR" /> 95112 var url, 95113 xhr, 95114 deferral = $.Deferred(); 95115 95116 if (connection.transport) { 95117 url = connection.url + "/ping"; 95118 95119 url = transportLogic.addQs(url, connection.qs); 95120 95121 xhr = transportLogic.ajax(connection, { 95122 url: url, 95123
95123success: function (result) { 95124 var data; 95125 95126 try { 95127 data = connection._parseResponse(result); 95128 } 95129 catch (error) { 95130 deferral.reject( 95131 signalR._.transportError( 95132 signalR.resources.pingServerFailedParse, 95133 connection.transport, 95134 error, 95135 xhr 95136 ) 95137 ); 95138 connection.stop(); 95139 return; 95140 } 95141 95142 if (data.Response === "pong") { 95143 deferral.resolve(); 95144 } 95145 else { 95146 deferral.reject( 95147 signalR._.transportError( 95148 signalR._.format(signalR.resources.pingServerFailedInvalidResponse, result), 95149 connection.transport, 95150 null /* error */, 95151 xhr 95152 ) 95153 ); 95154 } 95155 }, 95156 error: function (error) { 95157 if (error.status === 401 || error.status === 403) { 95158 deferral.reject( 95159 signalR._.transportError( 95160 signalR._.format(signalR.resources.pingServerFailedStatusCode, error.status), 95161 connection.transport, 95162 error, 95163 xhr 95164 ) 95165 ); 95166 connection.stop(); 95167 } 95168 else { 95169 deferral.reject( 95170 signalR._.transportError( 95171 signalR.resources.pingServerFailed, 95172 connection.transport,
vendor: 15,235 bytes, lines 95173-95554
95173 error, 95174 xhr 95175 ) 95176 ); 95177 } 95178 } 95179 }); 95180 } 95181 else { 95182 deferral.reject( 95183 signalR._.transportError( 95184 signalR.resources.noConnectionTransport, 95185 connection.transport 95186 ) 95187 ); 95188 } 95189 95190 return deferral.promise(); 95191 }, 95192 95193 prepareQueryString: function (connection, url) { 95194 var preparedUrl; 95195 95196 // Use addQs to start since it handles the ?/& prefix for us 95197 preparedUrl = transportLogic.addQs(url, "clientProtocol=" + connection.clientProtocol); 95198 95199 // Add the user-specified query string params if any 95200 preparedUrl = transportLogic.addQs(preparedUrl, connection.qs); 95201 95202 if (connection.token) { 95203 preparedUrl += "&connectionToken=" + window.encodeURIComponent(connection.token); 95204 } 95205 95206 if (connection.data) { 95207 preparedUrl += "&connectionData=" + window.encodeURIComponent(connection.data); 95208 } 95209 95210 return preparedUrl; 95211 }, 95212 95213 addQs: function (url, qs) { 95214 var appender = url.indexOf("?") !== -1 ? "&" : "?", 95215 firstChar; 95216 95217 if (!qs) { 95218 return url; 95219 } 95220 95221 if (typeof (qs) === "object") { 95222 return url + appender + $.param(qs); 95223 } 95224 95225 if (typeof (qs) === "string") { 95226 firstChar = qs.charAt(0); 95227 95228 if (firstChar === "?" || firstChar === "&") { 95229 appender = ""; 95230 } 95231 95232 return url + appender + qs; 95233 } 95234 95235 throw new Error("Query string property must be either a string or object."); 95236 }, 95237 95238 // BUG #2953: The url needs to be same otherwise it will cause a memory leak 95239 getUrl: function (connection, transport, reconnecting, poll, ajaxPost) { 95240 /// <summary>Gets the url for making a GET based connect request</summary> 95241 var baseUrl = transport === "webSockets" ? "" : connection.baseUrl, 95242 url = baseUrl + connection.appRelativeUrl, 95243 qs = "transport=" + transport; 95244 95245 if (!ajaxPost && connection.groupsToken) { 95246 qs += "&groupsToken=" + window.encodeURIComponent(connection.groupsToken); 95247 } 95248 95249 if (!reconnecting) { 95250 url += "/connect"; 95251 } else { 95252 if (poll) { 95253 // longPolling transport specific 95254 url += "/poll"; 95255 } else { 95256 url += "/reconnect"; 95257 } 95258 95259 if (!ajaxPost && connection.messageId) { 95260 qs += "&messageId=" + window.encodeURIComponent(connection.messageId); 95261 } 95262 } 95263 url += "?" + qs; 95264 url = transportLogic.prepareQueryString(connection, url); 95265 95266 if (!ajaxPost) { 95267 url += "&tid=" + Math.floor(Math.random() * 11); 95268 } 95269 95270 return url; 95271 }, 95272 95273 maximizePersistentResponse: function (minPersistentResponse) { 95274 return { 95275 MessageId: minPersistentResponse.C, 95276 Messages: minPersistentResponse.M, 95277 Initialized: typeof (minPersistentResponse.S) !== "undefined" ? true : false, 95278 ShouldReconnect: typeof (minPersistentResponse.T) !== "undefined" ? true : false, 95279 LongPollDelay: minPersistentResponse.L, 95280 GroupsToken: minPersistentResponse.G 95281 }; 95282 }, 95283 95284 updateGroups: function (connection, groupsToken) { 95285 if (groupsToken) { 95286 connection.groupsToken = groupsToken; 95287 } 95288 }, 95289 95290 stringifySend: function (connection, message) { 95291 if (typeof (message) === "string" || typeof (message) === "undefined" || message === null) { 95292 return message; 95293 } 95294 return connection.json.stringify(message); 95295 }, 95296 95297 ajaxSend: function (connection, data) { 95298 var payload = transportLogic.stringifySend(connection, data), 95299 url = getAjaxUrl(connection, "/send"), 95300 xhr, 95301 onFail = function (error, connection) { 95302 $(connection).triggerHandler(events.onError, [signalR._.transportError(signalR.resources.sendFailed, connection.transport, error, xhr), data]); 95303 }; 95304 95305 95306 xhr = transportLogic.ajax(connection, { 95307 url: url, 95308 type: connection.ajaxDataType === "jsonp" ? "GET" : "POST", 95309 contentType: signalR._.defaultContentType, 95310 data: { 95311 data: payload 95312 }, 95313 success: function (result) { 95314 var res; 95315 95316 if (result) { 95317 try { 95318 res = connection._parseResponse(result); 95319 } 95320 catch (error) { 95321 onFail(error, connection); 95322 connection.stop(); 95323 return; 95324 } 95325 95326 transportLogic.triggerReceived(connection, res); 95327 } 95328 }, 95329 error: function (error, textStatus) { 95330 if (textStatus === "abort" || textStatus === "parsererror") { 95331 // The parsererror happens for sends that don't return any data, and hence 95332 // don't write the jsonp callback to the response. This is harder to fix on the server 95333 // so just hack around it on the client for now. 95334 return; 95335 } 95336 95337 onFail(error, connection); 95338 } 95339 }); 95340 95341 return xhr; 95342 }, 95343 95344 ajaxAbort: function (connection, async) { 95345 if (typeof (connection.transport) === "undefined") { 95346 return; 95347 } 95348 95349 // Async by default unless explicitly overidden 95350 async = typeof async === "undefined" ? true : async; 95351 95352 var url = getAjaxUrl(connection, "/abort"); 95353 95354 transportLogic.ajax(connection, { 95355 url: url, 95356 async: async, 95357 timeout: 1000, 95358 type: "POST" 95359 }); 95360 95361 connection.log("Fired ajax abort async = " + async + "."); 95362 }, 95363 95364 ajaxStart: function (connection, onSuccess) { 95365 var rejectDeferred = function (error) { 95366 var deferred = connection._deferral; 95367 if (deferred) { 95368 deferred.reject(error); 95369 } 95370 }, 95371 triggerStartError = function (error) { 95372 connection.log("The start request failed. Stopping the connection."); 95373 $(connection).triggerHandler(events.onError, [error]); 95374 rejectDeferred(error); 95375 connection.stop(); 95376 }; 95377 95378 connection._.startRequest = transportLogic.ajax(connection, { 95379 url: getAjaxUrl(connection, "/start"), 95380 success: function (result, statusText, xhr) { 95381 var data; 95382 95383 try { 95384 data = connection._parseResponse(result); 95385 } catch (error) { 95386 triggerStartError(signalR._.error( 95387 signalR._.format(signalR.resources.errorParsingStartResponse, result), 95388 error, xhr)); 95389 return; 95390 } 95391 95392 if (data.Response === "started") { 95393 onSuccess(); 95394 } else { 95395 triggerStartError(signalR._.error( 95396 signalR._.format(signalR.resources.invalidStartResponse, result), 95397 null /* error */, xhr)); 95398 } 95399 }, 95400 error: function (xhr, statusText, error) { 95401 if (statusText !== startAbortText) { 95402 triggerStartError(signalR._.error( 95403 signalR.resources.errorDuringStartRequest, 95404 error, xhr)); 95405 } else { 95406 // Stop has been called, no need to trigger the error handler 95407 // or stop the connection again with onStartError 95408 connection.log("The start request aborted because connection.stop() was called."); 95409 rejectDeferred(signalR._.error( 95410 signalR.resources.stoppedDuringStartRequest, 95411 null /* error */, xhr)); 95412 } 95413 } 95414 }); 95415 }, 95416 95417 tryAbortStartRequest: function (connection) { 95418 if (connection._.startRequest) { 95419 // If the start request has already completed this will noop. 95420 connection._.startRequest.abort(startAbortText); 95421 delete connection._.startRequest; 95422 } 95423 }, 95424 95425 tryInitialize: function (connection, persistentResponse, onInitialized) { 95426 if (persistentResponse.Initialized && onInitialized) { 95427 onInitialized(); 95428 } else if (persistentResponse.Initialized) { 95429 connection.log("WARNING! The client received an init message after reconnecting."); 95430 } 95431 95432 }, 95433 95434 triggerReceived: function (connection, data) { 95435 if (!connection._.connectingMessageBuffer.tryBuffer(data)) { 95436 $(connection).triggerHandler(events.onReceived, [data]); 95437 } 95438 }, 95439 95440 processMessages: function (connection, minData, onInitialized) { 95441 var data; 95442 95443 // Update the last message time stamp 95444 transportLogic.markLastMessage(connection); 95445 95446 if (minData) { 95447 data = transportLogic.maximizePersistentResponse(minData); 95448 95449 transportLogic.updateGroups(connection, data.GroupsToken); 95450 95451 if (data.MessageId) { 95452 connection.messageId = data.MessageId; 95453 } 95454 95455 if (data.Messages) { 95456 $.each(data.Messages, function (index, message) { 95457 transportLogic.triggerReceived(connection, message); 95458 }); 95459 95460 transportLogic.tryInitialize(connection, data, onInitialized); 95461 } 95462 } 95463 }, 95464 95465 monitorKeepAlive: function (connection) { 95466 var keepAliveData = connection._.keepAliveData; 95467 95468 // If we haven't initiated the keep alive timeouts then we need to 95469 if (!keepAliveData.monitoring) { 95470 keepAliveData.monitoring = true; 95471 95472 transportLogic.markLastMessage(connection); 95473 95474 // Save the function so we can unbind it on stop 95475 connection._.keepAliveData.reconnectKeepAliveUpdate = function () { 95476 // Mark a new message so that keep alive doesn't time out connections 95477 transportLogic.markLastMessage(connection); 95478 }; 95479 95480 // Update Keep alive on reconnect 95481 $(connection).bind(events.onReconnect, connection._.keepAliveData.reconnectKeepAliveUpdate); 95482 95483 connection.log("Now monitoring keep alive with a warning timeout of " + keepAliveData.timeoutWarning + ", keep alive timeout of " + keepAliveData.timeout + " and disconnecting timeout of " + connection.disconnectTimeout); 95484 } else { 95485 connection.log("Tried to monitor keep alive but it's already being monitored."); 95486 } 95487 }, 95488 95489 stopMonitoringKeepAlive: function (connection) { 95490 var keepAliveData = connection._.keepAliveData; 95491 95492 // Only attempt to stop the keep alive monitoring if its being monitored 95493 if (keepAliveData.monitoring) { 95494 // Stop monitoring 95495 keepAliveData.monitoring = false; 95496 95497 // Remove the updateKeepAlive function from the reconnect event 95498 $(connection).unbind(events.onReconnect, connection._.keepAliveData.reconnectKeepAliveUpdate); 95499 95500 // Clear all the keep alive data 95501 connection._.keepAliveData = {}; 95502 connection.log("Stopping the monitoring of the keep alive."); 95503 } 95504 }, 95505 95506 startHeartbeat: function (connection) { 95507 connection._.lastActiveAt = new Date().getTime(); 95508 beat(connection); 95509 }, 95510 95511 markLastMessage: function (connection) { 95512 connection._.lastMessageAt = new Date().getTime(); 95513 }, 95514 95515 markActive: function (connection) { 95516 if (transportLogic.verifyLastActive(connection)) { 95517 connection._.lastActiveAt = new Date().getTime(); 95518 return true; 95519 } 95520 95521 return false; 95522 }, 95523 95524 isConnectedOrReconnecting: function (connection) { 95525 return connection.state === signalR.connectionState.connected || 95526 connection.state === signalR.connectionState.reconnecting; 95527 }, 95528 95529 ensureReconnectingState: function (connection) { 95530 if (changeState(connection, 95531 signalR.connectionState.connected, 95532 signalR.connectionState.reconnecting) === true) { 95533 $(connection).triggerHandler(events.onReconnecting); 95534 } 95535 return connection.state === signalR.connectionState.reconnecting; 95536 }, 95537 95538 clearReconnectTimeout: function (connection) { 95539 if (connection && connection._.reconnectTimeout) { 95540 window.clearTimeout(connection._.reconnectTimeout); 95541 delete connection._.reconnectTimeout; 95542 } 95543 }, 95544 95545 verifyLastActive: function (connection) { 95546 if (new Date().getTime() - connection._.lastActiveAt >= connection.reconnectWindow) { 95547 var message = signalR._.format(signalR.resources.reconnectWindowTimeout, new Date(connection._.lastActiveAt), connection.reconnectWindow); 95548 connection.log(message); 95549 $(connection).triggerHandler(events.onError, [signalR._.error(message, /* source */ "TimeoutException")]); 95550 connection.stop(/* async */ false, /* notifyServer */ false); 95551 return false; 95552 } 95553 95554 return tru
vendor: 6,932 bytes, lines 95554-95729
95554e; 95555 }, 95556 95557 reconnect: function (connection, transportName) { 95558 var transport = signalR.transports[transportName]; 95559 95560 // We should only set a reconnectTimeout if we are currently connected 95561 // and a reconnectTimeout isn't already set. 95562 if (transportLogic.isConnectedOrReconnecting(connection) && !connection._.reconnectTimeout) { 95563 // Need to verify before the setTimeout occurs because an application sleep could occur during the setTimeout duration. 95564 if (!transportLogic.verifyLastActive(connection)) { 95565 return; 95566 } 95567 95568 connection._.reconnectTimeout = window.setTimeout(function () { 95569 if (!transportLogic.verifyLastActive(connection)) { 95570 return; 95571 } 95572 95573 transport.stop(connection); 95574 95575 if (transportLogic.ensureReconnectingState(connection)) { 95576 connection.log(transportName + " reconnecting."); 95577 transport.start(connection); 95578 } 95579 }, connection.reconnectDelay); 95580 } 95581 }, 95582 95583 handleParseFailure: function (connection, result, error, onFailed, context) { 95584 var wrappedError = signalR._.transportError( 95585 signalR._.format(signalR.resources.parseFailed, result), 95586 connection.transport, 95587 error, 95588 context); 95589 95590 // If we're in the initialization phase trigger onFailed, otherwise stop the connection. 95591 if (onFailed && onFailed(wrappedError)) { 95592 connection.log("Failed to parse server response while attempting to connect."); 95593 } else { 95594 $(connection).triggerHandler(events.onError, [wrappedError]); 95595 connection.stop(); 95596 } 95597 }, 95598 95599 initHandler: function (connection) { 95600 return new InitHandler(connection); 95601 }, 95602 95603 foreverFrame: { 95604 count: 0, 95605 connections: {} 95606 } 95607 }; 95608 95609}(window.jQuery, window)); 95610/* jquery.signalR.transports.webSockets.js */ 95611// Copyright (c) .NET Foundation. All rights reserved. 95612// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 95613 95614 95615/*global window:false */ 95616/// <reference path="jquery.signalR.transports.common.js" /> 95617 95618(function ($, window, undefined) { 95619 95620 var signalR = $.signalR, 95621 events = $.signalR.events, 95622 changeState = $.signalR.changeState, 95623 transportLogic = signalR.transports._logic; 95624 95625 signalR.transports.webSockets = { 95626 name: "webSockets", 95627 95628 supportsKeepAlive: function () { 95629 return true; 95630 }, 95631 95632 send: function (connection, data) { 95633 var payload = transportLogic.stringifySend(connection, data); 95634 95635 try { 95636 connection.socket.send(payload); 95637 } catch (ex) { 95638 $(connection).triggerHandler(events.onError, 95639 [signalR._.transportError( 95640 signalR.resources.webSocketsInvalidState, 95641 connection.transport, 95642 ex, 95643 connection.socket 95644 ), 95645 data]); 95646 } 95647 }, 95648 95649 start: function (connection, onSuccess, onFailed) { 95650 var url, 95651 opened = false, 95652 that = this, 95653 reconnecting = !onSuccess, 95654 $connection = $(connection); 95655 95656 if (!window.WebSocket) { 95657 onFailed(); 95658 return; 95659 } 95660 95661 if (!connection.socket) { 95662 if (connection.webSocketServerUrl) { 95663 url = connection.webSocketServerUrl; 95664 } else { 95665 url = connection.wsProtocol + connection.host; 95666 } 95667 95668 url += transportLogic.getUrl(connection, this.name, reconnecting); 95669 95670 connection.log("Connecting to websocket endpoint '" + url + "'."); 95671 connection.socket = new window.WebSocket(url); 95672 95673 connection.socket.onopen = function () { 95674 opened = true; 95675 connection.log("Websocket opened."); 95676 95677 transportLogic.clearReconnectTimeout(connection); 95678 95679 if (changeState(connection, 95680 signalR.connectionState.reconnecting, 95681 signalR.connectionState.connected) === true) { 95682 $connection.triggerHandler(events.onReconnect); 95683 } 95684 }; 95685 95686 connection.socket.onclose = function (event) { 95687 var error; 95688 95689 // Only handle a socket close if the close is from the current socket. 95690 // Sometimes on disconnect the server will push down an onclose event 95691 // to an expired socket. 95692 95693 if (this === connection.socket) { 95694 if (opened && typeof event.wasClean !== "undefined" && event.wasClean === false) { 95695 // Ideally this would use the websocket.onerror handler (rather than checking wasClean in onclose) but 95696 // I found in some circumstances Chrome won't call onerror. This implementation seems to work on all browsers. 95697 error = signalR._.transportError( 95698 signalR.resources.webSocketClosed, 95699 connection.transport, 95700 event); 95701 95702 connection.log("Unclean disconnect from websocket: " + (event.reason || "[no reason given].")); 95703 } else { 95704 connection.log("Websocket closed."); 95705 } 95706 95707 if (!onFailed || !onFailed(error)) { 95708 if (error) { 95709 $(connection).triggerHandler(events.onError, [error]); 95710 } 95711 95712 that.reconnect(connection); 95713 } 95714 } 95715 }; 95716 95717 connection.socket.onmessage = function (event) { 95718 var data; 95719 95720 try { 95721 data = connection._parseResponse(event.data); 95722 } 95723 catch (error) { 95724 transportLogic.handleParseFailure(connection, event.data, error, onFailed, event); 95725 return; 95726 } 95727 95728 if (data) { 95729
95729// data.M is PersistentResponse.Messages 95730 if ($.isEmptyObject(data) || data.M) { 95731 transportLogic.processMessages(connection, data, onSuccess); 95732 } else { 95733 // For websockets we need to trigger onReceived 95734 // for callbacks to outgoing hub calls. 95735 transportLogic.triggerReceived(connection, data); 95736 }
vendor: 11,128 bytes, lines 95736-96022
95736 95737 } 95738 }; 95739 } 95740 }, 95741 95742 reconnect: function (connection) { 95743 transportLogic.reconnect(connection, this.name); 95744 }, 95745 95746 lostConnection: function (connection) { 95747 this.reconnect(connection); 95748 }, 95749 95750 stop: function (connection) { 95751 // Don't trigger a reconnect after stopping 95752 transportLogic.clearReconnectTimeout(connection); 95753 95754 if (connection.socket) { 95755 connection.log("Closing the Websocket."); 95756 connection.socket.close(); 95757 connection.socket = null; 95758 } 95759 }, 95760 95761 abort: function (connection, async) { 95762 transportLogic.ajaxAbort(connection, async); 95763 } 95764 }; 95765 95766}(window.jQuery, window)); 95767/* jquery.signalR.transports.serverSentEvents.js */ 95768// Copyright (c) .NET Foundation. All rights reserved. 95769// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 95770 95771 95772/*global window:false */ 95773/// <reference path="jquery.signalR.transports.common.js" /> 95774 95775(function ($, window, undefined) { 95776 95777 var signalR = $.signalR, 95778 events = $.signalR.events, 95779 changeState = $.signalR.changeState, 95780 transportLogic = signalR.transports._logic, 95781 clearReconnectAttemptTimeout = function (connection) { 95782 window.clearTimeout(connection._.reconnectAttemptTimeoutHandle); 95783 delete connection._.reconnectAttemptTimeoutHandle; 95784 }; 95785 95786 signalR.transports.serverSentEvents = { 95787 name: "serverSentEvents", 95788 95789 supportsKeepAlive: function () { 95790 return true; 95791 }, 95792 95793 timeOut: 3000, 95794 95795 start: function (connection, onSuccess, onFailed) { 95796 var that = this, 95797 opened = false, 95798 $connection = $(connection), 95799 reconnecting = !onSuccess, 95800 url; 95801 95802 if (connection.eventSource) { 95803 connection.log("The connection already has an event source. Stopping it."); 95804 connection.stop(); 95805 } 95806 95807 if (!window.EventSource) { 95808 if (onFailed) { 95809 connection.log("This browser doesn't support SSE."); 95810 onFailed(); 95811 } 95812 return; 95813 } 95814 95815 url = transportLogic.getUrl(connection, this.name, reconnecting); 95816 95817 try { 95818 connection.log("Attempting to connect to SSE endpoint '" + url + "'."); 95819 connection.eventSource = new window.EventSource(url, { withCredentials: connection.withCredentials }); 95820 } 95821 catch (e) { 95822 connection.log("EventSource failed trying to connect with error " + e.Message + "."); 95823 if (onFailed) { 95824 // The connection failed, call the failed callback 95825 onFailed(); 95826 } else { 95827 $connection.triggerHandler(events.onError, [signalR._.transportError(signalR.resources.eventSourceFailedToConnect, connection.transport, e)]); 95828 if (reconnecting) { 95829 // If we were reconnecting, rather than doing initial connect, then try reconnect again 95830 that.reconnect(connection); 95831 } 95832 } 95833 return; 95834 } 95835 95836 if (reconnecting) { 95837 connection._.reconnectAttemptTimeoutHandle = window.setTimeout(function () { 95838 if (opened === false) { 95839 // If we're reconnecting and the event source is attempting to connect, 95840 // don't keep retrying. This causes duplicate connections to spawn. 95841 if (connection.eventSource.readyState !== window.EventSource.OPEN) { 95842 // If we were reconnecting, rather than doing initial connect, then try reconnect again 95843 that.reconnect(connection); 95844 } 95845 } 95846 }, 95847 that.timeOut); 95848 } 95849 95850 connection.eventSource.addEventListener("open", function (e) { 95851 connection.log("EventSource connected."); 95852 95853 clearReconnectAttemptTimeout(connection); 95854 transportLogic.clearReconnectTimeout(connection); 95855 95856 if (opened === false) { 95857 opened = true; 95858 95859 if (changeState(connection, 95860 signalR.connectionState.reconnecting, 95861 signalR.connectionState.connected) === true) { 95862 $connection.triggerHandler(events.onReconnect); 95863 } 95864 } 95865 }, false); 95866 95867 connection.eventSource.addEventListener("message", function (e) { 95868 var res; 95869 95870 // process messages 95871 if (e.data === "initialized") { 95872 return; 95873 } 95874 95875 try { 95876 res = connection._parseResponse(e.data); 95877 } 95878 catch (error) { 95879 transportLogic.handleParseFailure(connection, e.data, error, onFailed, e); 95880 return; 95881 } 95882 95883 transportLogic.processMessages(connection, res, onSuccess); 95884 }, false); 95885 95886 connection.eventSource.addEventListener("error", function (e) { 95887 var error = signalR._.transportError( 95888 signalR.resources.eventSourceError, 95889 connection.transport, 95890 e); 95891 95892 // Only handle an error if the error is from the current Event Source. 95893 // Sometimes on disconnect the server will push down an error event 95894 // to an expired Event Source. 95895 if (this !== connection.eventSource) { 95896 return; 95897 } 95898 95899 if (onFailed && onFailed(error)) { 95900 return; 95901 } 95902 95903 connection.log("EventSource readyState: " + connection.eventSource.readyState + "."); 95904 95905 if (e.eventPhase === window.EventSource.CLOSED) { 95906 // We don't use the EventSource's native reconnect function as it 95907 // doesn't allow us to change the URL when reconnecting. We need 95908 // to change the URL to not include the /connect suffix, and pass 95909 // the last message id we received. 95910 connection.log("EventSource reconnecting due to the server connection ending."); 95911 that.reconnect(connection); 95912 } else { 95913 // connection error 95914 connection.log("EventSource error."); 95915 $connection.triggerHandler(events.onError, [error]); 95916 } 95917 }, false); 95918 }, 95919 95920 reconnect: function (connection) { 95921 transportLogic.reconnect(connection, this.name); 95922 }, 95923 95924 lostConnection: function (connection) { 95925 this.reconnect(connection); 95926 }, 95927 95928 send: function (connection, data) { 95929 transportLogic.ajaxSend(connection, data); 95930 }, 95931 95932 stop: function (connection) { 95933 // Don't trigger a reconnect after stopping 95934 clearReconnectAttemptTimeout(connection); 95935 transportLogic.clearReconnectTimeout(connection); 95936 95937 if (connection && connection.eventSource) { 95938 connection.log("EventSource calling close()."); 95939 connection.eventSource.close(); 95940 connection.eventSource = null; 95941 delete connection.eventSource; 95942 } 95943 }, 95944 95945 abort: function (connection, async) { 95946 transportLogic.ajaxAbort(connection, async); 95947 } 95948 }; 95949 95950}(window.jQuery, window)); 95951/* jquery.signalR.transports.foreverFrame.js */ 95952// Copyright (c) .NET Foundation. All rights reserved. 95953// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 95954 95955 95956/*global window:false */ 95957/// <reference path="jquery.signalR.transports.common.js" /> 95958 95959(function ($, window, undefined) { 95960 95961 var signalR = $.signalR, 95962 events = $.signalR.events, 95963 changeState = $.signalR.changeState, 95964 transportLogic = signalR.transports._logic, 95965 createFrame = function () { 95966 var frame = window.document.createElement("iframe"); 95967 frame.setAttribute("style", "position:absolute;top:0;left:0;width:0;height:0;visibility:hidden;"); 95968 return frame; 95969 }, 95970 // Used to prevent infinite loading icon spins in older versions of ie 95971 // We build this object inside a closure so we don't pollute the rest of 95972 // the foreverFrame transport with unnecessary functions/utilities. 95973 loadPreventer = (function () { 95974 var loadingFixIntervalId = null, 95975 loadingFixInterval = 1000, 95976 attachedTo = 0; 95977 95978 return { 95979 prevent: function () { 95980 // Prevent additional iframe removal procedures from newer browsers 95981 if (signalR._.ieVersion <= 8) { 95982 // We only ever want to set the interval one time, so on the first attachedTo 95983 if (attachedTo === 0) { 95984 // Create and destroy iframe every 3 seconds to prevent loading icon, super hacky 95985 loadingFixIntervalId = window.setInterval(function () { 95986 var tempFrame = createFrame(); 95987 95988 window.document.body.appendChild(tempFrame); 95989 window.document.body.removeChild(tempFrame); 95990 95991 tempFrame = null; 95992 }, loadingFixInterval); 95993 } 95994 95995 attachedTo++; 95996 } 95997 }, 95998 cancel: function () { 95999 // Only clear the interval if there's only one more object that the loadPreventer is attachedTo 96000 if (attachedTo === 1) { 96001 window.clearInterval(loadingFixIntervalId); 96002 } 96003 96004 if (attachedTo > 0) { 96005 attachedTo--; 96006 } 96007 } 96008 }; 96009 })(); 96010 96011 signalR.transports.foreverFrame = { 96012 name: "foreverFrame", 96013 96014 supportsKeepAlive: function () { 96015 return true; 96016 }, 96017 96018 // Added as a value here so we can create tests to verify functionality 96019 iframeClearThreshold: 50, 96020 96021 start: function (connection, onSuccess, onFailed) { 96022
vendor: 11,846 bytes, lines 96022-96306
96022var that = this, 96023 frameId = (transportLogic.foreverFrame.count += 1), 96024 url, 96025 frame = createFrame(), 96026 frameLoadHandler = function () { 96027 connection.log("Forever frame iframe finished loading and is no longer receiving messages."); 96028 if (!onFailed || !onFailed()) { 96029 that.reconnect(connection); 96030 } 96031 }; 96032 96033 if (window.EventSource) { 96034 // If the browser supports SSE, don't use Forever Frame 96035 if (onFailed) { 96036 connection.log("Forever Frame is not supported by SignalR on browsers with SSE support."); 96037 onFailed(); 96038 } 96039 return; 96040 } 96041 96042 frame.setAttribute("data-signalr-connection-id", connection.id); 96043 96044 // Start preventing loading icon 96045 // This will only perform work if the loadPreventer is not attached to another connection. 96046 loadPreventer.prevent(); 96047 96048 // Build the url 96049 url = transportLogic.getUrl(connection, this.name); 96050 url += "&frameId=" + frameId; 96051 96052 // add frame to the document prior to setting URL to avoid caching issues. 96053 window.document.documentElement.appendChild(frame); 96054 96055 connection.log("Binding to iframe's load event."); 96056 96057 if (frame.addEventListener) { 96058 frame.addEventListener("load", frameLoadHandler, false); 96059 } else if (frame.attachEvent) { 96060 frame.attachEvent("onload", frameLoadHandler); 96061 } 96062 96063 frame.src = url; 96064 transportLogic.foreverFrame.connections[frameId] = connection; 96065 96066 connection.frame = frame; 96067 connection.frameId = frameId; 96068 96069 if (onSuccess) { 96070 connection.onSuccess = function () { 96071 connection.log("Iframe transport started."); 96072 onSuccess(); 96073 }; 96074 } 96075 }, 96076 96077 reconnect: function (connection) { 96078 var that = this; 96079 96080 // Need to verify connection state and verify before the setTimeout occurs because an application sleep could occur during the setTimeout duration. 96081 if (transportLogic.isConnectedOrReconnecting(connection) && transportLogic.verifyLastActive(connection)) { 96082 window.setTimeout(function () { 96083 // Verify that we're ok to reconnect. 96084 if (!transportLogic.verifyLastActive(connection)) { 96085 return; 96086 } 96087 96088 if (connection.frame && transportLogic.ensureReconnectingState(connection)) { 96089 var frame = connection.frame, 96090 src = transportLogic.getUrl(connection, that.name, true) + "&frameId=" + connection.frameId; 96091 connection.log("Updating iframe src to '" + src + "'."); 96092 frame.src = src; 96093 } 96094 }, connection.reconnectDelay); 96095 } 96096 }, 96097 96098 lostConnection: function (connection) { 96099 this.reconnect(connection); 96100 }, 96101 96102 send: function (connection, data) { 96103 transportLogic.ajaxSend(connection, data); 96104 }, 96105 96106 receive: function (connection, data) { 96107 var cw, 96108 body, 96109 response; 96110 96111 if (connection.json !== connection._originalJson) { 96112 // If there's a custom JSON parser configured then serialize the object 96113 // using the original (browser) JSON parser and then deserialize it using 96114 // the custom parser (connection._parseResponse does that). This is so we 96115 // can easily send the response from the server as "raw" JSON but still 96116 // support custom JSON deserialization in the browser. 96117 data = connection._originalJson.stringify(data); 96118 } 96119 96120 response = connection._parseResponse(data); 96121 96122 transportLogic.processMessages(connection, response, connection.onSuccess); 96123 96124 // Protect against connection stopping from a callback trigger within the processMessages above. 96125 if (connection.state === $.signalR.connectionState.connected) { 96126 // Delete the script & div elements 96127 connection.frameMessageCount = (connection.frameMessageCount || 0) + 1; 96128 if (connection.frameMessageCount > signalR.transports.foreverFrame.iframeClearThreshold) { 96129 connection.frameMessageCount = 0; 96130 cw = connection.frame.contentWindow || connection.frame.contentDocument; 96131 if (cw && cw.document && cw.document.body) { 96132 body = cw.document.body; 96133 96134 // Remove all the child elements from the iframe's body to conserver memory 96135 while (body.firstChild) { 96136 body.removeChild(body.firstChild); 96137 } 96138 } 96139 } 96140 } 96141 }, 96142 96143 stop: function (connection) { 96144 var cw = null; 96145 96146 // Stop attempting to prevent loading icon 96147 loadPreventer.cancel(); 96148 96149 if (connection.frame) { 96150 if (connection.frame.stop) { 96151 connection.frame.stop(); 96152 } else { 96153 try { 96154 cw = connection.frame.contentWindow || connection.frame.contentDocument; 96155 if (cw.document && cw.document.execCommand) { 96156 cw.document.execCommand("Stop"); 96157 } 96158 } 96159 catch (e) { 96160 connection.log("Error occurred when stopping foreverFrame transport. Message = " + e.message + "."); 96161 } 96162 } 96163 96164 // Ensure the iframe is where we left it 96165 if (connection.frame.parentNode === window.document.body) { 96166 window.document.body.removeChild(connection.frame); 96167 } 96168 96169 delete transportLogic.foreverFrame.connections[connection.frameId]; 96170 connection.frame = null; 96171 connection.frameId = null; 96172 delete connection.frame; 96173 delete connection.frameId; 96174 delete connection.onSuccess; 96175 delete connection.frameMessageCount; 96176 connection.log("Stopping forever frame."); 96177 } 96178 }, 96179 96180 abort: function (connection, async) { 96181 transportLogic.ajaxAbort(connection, async); 96182 }, 96183 96184 getConnection: function (id) { 96185 return transportLogic.foreverFrame.connections[id]; 96186 }, 96187 96188 started: function (connection) { 96189 if (changeState(connection, 96190 signalR.connectionState.reconnecting, 96191 signalR.connectionState.connected) === true) { 96192 96193 $(connection).triggerHandler(events.onReconnect); 96194 } 96195 } 96196 }; 96197 96198}(window.jQuery, window)); 96199/* jquery.signalR.transports.longPolling.js */ 96200// Copyright (c) .NET Foundation. All rights reserved. 96201// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 96202 96203 96204/*global window:false */ 96205/// <reference path="jquery.signalR.transports.common.js" /> 96206 96207(function ($, window, undefined) { 96208 96209 var signalR = $.signalR, 96210 events = $.signalR.events, 96211 changeState = $.signalR.changeState, 96212 isDisconnecting = $.signalR.isDisconnecting, 96213 transportLogic = signalR.transports._logic; 96214 96215 signalR.transports.longPolling = { 96216 name: "longPolling", 96217 96218 supportsKeepAlive: function () { 96219 return false; 96220 }, 96221 96222 reconnectDelay: 3000, 96223 96224 start: function (connection, onSuccess, onFailed) { 96225 /// <summary>Starts the long polling connection</summary> 96226 /// <param name="connection" type="signalR">The SignalR connection to start</param> 96227 var that = this, 96228 fireConnect = function () { 96229 fireConnect = $.noop; 96230 96231 connection.log("LongPolling connected."); 96232 96233 if (onSuccess) { 96234 onSuccess(); 96235 } else { 96236 connection.log("WARNING! The client received an init message after reconnecting."); 96237 } 96238 }, 96239 tryFailConnect = function (error) { 96240 if (onFailed(error)) { 96241 connection.log("LongPolling failed to connect."); 96242 return true; 96243 } 96244 96245 return false; 96246 }, 96247 privateData = connection._, 96248 reconnectErrors = 0, 96249 fireReconnected = function (instance) { 96250 window.clearTimeout(privateData.reconnectTimeoutId); 96251 privateData.reconnectTimeoutId = null; 96252 96253 if (changeState(instance, 96254 signalR.connectionState.reconnecting, 96255 signalR.connectionState.connected) === true) { 96256 // Successfully reconnected! 96257 instance.log("Raising the reconnect event"); 96258 $(instance).triggerHandler(events.onReconnect); 96259 } 96260 }, 96261 // 1 hour 96262 maxFireReconnectedTimeout = 3600000; 96263 96264 if (connection.pollXhr) { 96265 connection.log("Polling xhr requests already exists, aborting."); 96266 connection.stop(); 96267 } 96268 96269 connection.messageId = null; 96270 96271 privateData.reconnectTimeoutId = null; 96272 96273 privateData.pollTimeoutId = window.setTimeout(function () { 96274 (function poll(instance, raiseReconnect) { 96275 var messageId = instance.messageId, 96276 connect = (messageId === null), 96277 reconnecting = !connect, 96278 polling = !raiseReconnect, 96279 url = transportLogic.getUrl(instance, that.name, reconnecting, polling, true /* use Post for longPolling */), 96280 postData = {}; 96281 96282 if (instance.messageId) { 96283 postData.messageId = instance.messageId; 96284 } 96285 96286 if (instance.groupsToken) { 96287 postData.groupsToken = instance.groupsToken; 96288 } 96289 96290 // If we've disconnected during the time we've tried to re-instantiate the poll then stop. 96291 if (isDisconnecting(instance) === true) { 96292 return; 96293 } 96294 96295 connection.log("Opening long polling request to '" + url + "'."); 96296 instance.pollXhr = transportLogic.ajax(connection, { 96297 xhrFields: { 96298 onprogress: function () { 96299 transportLogic.markLastMessage(connection); 96300 } 96301 }, 96302 url: url, 96303 type: "POST", 96304 contentType: signalR._.defaultContentType, 96305 data: postData, 96306 timeout: connection._.pollTimeout
vendor: 8,663 bytes, lines 96306-96470
96306, 96307 success: function (result) { 96308 var minData, 96309 delay = 0, 96310 data, 96311 shouldReconnect; 96312 96313 connection.log("Long poll complete."); 96314 96315 // Reset our reconnect errors so if we transition into a reconnecting state again we trigger 96316 // reconnected quickly 96317 reconnectErrors = 0; 96318 96319 try { 96320 // Remove any keep-alives from the beginning of the result 96321 minData = connection._parseResponse(result); 96322 } 96323 catch (error) { 96324 transportLogic.handleParseFailure(instance, result, error, tryFailConnect, instance.pollXhr); 96325 return; 96326 } 96327 96328 // If there's currently a timeout to trigger reconnect, fire it now before processing messages 96329 if (privateData.reconnectTimeoutId !== null) { 96330 fireReconnected(instance); 96331 } 96332 96333 if (minData) { 96334 data = transportLogic.maximizePersistentResponse(minData); 96335 } 96336 96337 transportLogic.processMessages(instance, minData, fireConnect); 96338 96339 if (data && 96340 $.type(data.LongPollDelay) === "number") { 96341 delay = data.LongPollDelay; 96342 } 96343 96344 if (isDisconnecting(instance) === true) { 96345 return; 96346 } 96347 96348 shouldReconnect = data && data.ShouldReconnect; 96349 if (shouldReconnect) { 96350 // Transition into the reconnecting state 96351 // If this fails then that means that the user transitioned the connection into a invalid state in processMessages. 96352 if (!transportLogic.ensureReconnectingState(instance)) { 96353 return; 96354 } 96355 } 96356 96357 // We never want to pass a raiseReconnect flag after a successful poll. This is handled via the error function 96358 if (delay > 0) { 96359 privateData.pollTimeoutId = window.setTimeout(function () { 96360 poll(instance, shouldReconnect); 96361 }, delay); 96362 } else { 96363 poll(instance, shouldReconnect); 96364 } 96365 }, 96366 96367 error: function (data, textStatus) { 96368 var error = signalR._.transportError(signalR.resources.longPollFailed, connection.transport, data, instance.pollXhr); 96369 96370 // Stop trying to trigger reconnect, connection is in an error state 96371 // If we're not in the reconnect state this will noop 96372 window.clearTimeout(privateData.reconnectTimeoutId); 96373 privateData.reconnectTimeoutId = null; 96374 96375 if (textStatus === "abort") { 96376 connection.log("Aborted xhr request."); 96377 return; 96378 } 96379 96380 if (!tryFailConnect(error)) { 96381 96382 // Increment our reconnect errors, we assume all errors to be reconnect errors 96383 // In the case that it's our first error this will cause Reconnect to be fired 96384 // after 1 second due to reconnectErrors being = 1. 96385 reconnectErrors++; 96386 96387 if (connection.state !== signalR.connectionState.reconnecting) { 96388 connection.log("An error occurred using longPolling. Status = " + textStatus + ". Response = " + data.responseText + "."); 96389 $(instance).triggerHandler(events.onError, [error]); 96390 } 96391 96392 // We check the state here to verify that we're not in an invalid state prior to verifying Reconnect. 96393 // If we're not in connected or reconnecting then the next ensureReconnectingState check will fail and will return. 96394 // Therefore we don't want to change that failure code path. 96395 if ((connection.state === signalR.connectionState.connected || 96396 connection.state === signalR.connectionState.reconnecting) && 96397 !transportLogic.verifyLastActive(connection)) { 96398 return; 96399 } 96400 96401 // Transition into the reconnecting state 96402 // If this fails then that means that the user transitioned the connection into the disconnected or connecting state within the above error handler trigger. 96403 if (!transportLogic.ensureReconnectingState(instance)) { 96404 return; 96405 } 96406 96407 // Call poll with the raiseReconnect flag as true after the reconnect delay 96408 privateData.pollTimeoutId = window.setTimeout(function () { 96409 poll(instance, true); 96410 }, that.reconnectDelay); 96411 } 96412 } 96413 }); 96414 96415 // This will only ever pass after an error has occurred via the poll ajax procedure. 96416 if (reconnecting && raiseReconnect === true) { 96417 // We wait to reconnect depending on how many times we've failed to reconnect. 96418 // This is essentially a heuristic that will exponentially increase in wait time before 96419 // triggering reconnected. This depends on the "error" handler of Poll to cancel this 96420 // timeout if it triggers before the Reconnected event fires. 96421 // The Math.min at the end is to ensure that the reconnect timeout does not overflow. 96422 privateData.reconnectTimeoutId = window.setTimeout(function () { fireReconnected(instance); }, Math.min(1000 * (Math.pow(2, reconnectErrors) - 1), maxFireReconnectedTimeout)); 96423 } 96424 }(connection)); 96425 }, 250); // Have to delay initial poll so Chrome doesn't show loader spinner in tab 96426 }, 96427 96428 lostConnection: function (connection) { 96429 if (connection.pollXhr) { 96430 connection.pollXhr.abort("lostConnection"); 96431 } 96432 }, 96433 96434 send: function (connection, data) { 96435 transportLogic.ajaxSend(connection, data); 96436 }, 96437 96438 stop: function (connection) { 96439 /// <summary>Stops the long polling connection</summary> 96440 /// <param name="connection" type="signalR">The SignalR connection to stop</param> 96441 96442 window.clearTimeout(connection._.pollTimeoutId); 96443 window.clearTimeout(connection._.reconnectTimeoutId); 96444 96445 delete connection._.pollTimeoutId; 96446 delete connection._.reconnectTimeoutId; 96447 96448 if (connection.pollXhr) { 96449 connection.pollXhr.abort(); 96450 connection.pollXhr = null; 96451 delete connection.pollXhr; 96452 } 96453 }, 96454 96455 abort: function (connection, async) { 96456 transportLogic.ajaxAbort(connection, async); 96457 } 96458 }; 96459 96460}(window.jQuery, window)); 96461/* jquery.signalR.hubs.js */ 96462// Copyright (c) .NET Foundation. All rights reserved. 96463// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 96464 96465/*global window:false */ 96466/// <reference path="jquery.signalR.core.js" /> 96467 96468(function ($, window, undefined) { 96469 96470 var
vendor: 2,287 bytes, lines 96470-96533
96470eventNamespace = ".hubProxy", 96471 signalR = $.signalR; 96472 96473 function makeEventName(event) { 96474 return event + eventNamespace; 96475 } 96476 96477 // Equivalent to Array.prototype.map 96478 function map(arr, fun, thisp) { 96479 var i, 96480 length = arr.length, 96481 result = []; 96482 for (i = 0; i < length; i += 1) { 96483 if (arr.hasOwnProperty(i)) { 96484 result[i] = fun.call(thisp, arr[i], i, arr); 96485 } 96486 } 96487 return result; 96488 } 96489 96490 function getArgValue(a) { 96491 return $.isFunction(a) ? null : ($.type(a) === "undefined" ? null : a); 96492 } 96493 96494 function hasMembers(obj) { 96495 for (var key in obj) { 96496 // If we have any properties in our callback map then we have callbacks and can exit the loop via return 96497 if (obj.hasOwnProperty(key)) { 96498 return true; 96499 } 96500 } 96501 96502 return false; 96503 } 96504 96505 function clearInvocationCallbacks(connection, error) { 96506 /// <param name="connection" type="hubConnection" /> 96507 var callbacks = connection._.invocationCallbacks, 96508 callback; 96509 96510 if (hasMembers(callbacks)) { 96511 connection.log("Clearing hub invocation callbacks with error: " + error + "."); 96512 } 96513 96514 // Reset the callback cache now as we have a local var referencing it 96515 connection._.invocationCallbackId = 0; 96516 delete connection._.invocationCallbacks; 96517 connection._.invocationCallbacks = {}; 96518 96519 // Loop over the callbacks and invoke them. 96520 // We do this using a local var reference and *after* we've cleared the cache 96521 // so that if a fail callback itself tries to invoke another method we don't 96522 // end up with its callback in the list we're looping over. 96523 for (var callbackId in callbacks) { 96524 callback = callbacks[callbackId]; 96525 callback.method.call(callback.scope, { E: error }); 96526 } 96527 } 96528 96529 // hubProxy 96530 function hubProxy(hubConnection, hubName) { 96531 /// <summary> 96532 /// Creates a new proxy object for the given hub connection that can be used to invoke 96533 /// methods on server hubs and handle client method invocation requests from the server.
96534 /// </summary> 96535 return new hubProxy.fn.init(hubConnection, hubName); 96536 } 96537 96538 hubProxy.fn = hubProxy.prototype = { 96539 init: function (connection, hubName) { 96540 this.state = {}; 96541 this.connection = connection; 96542 this.hubName = hubName; 96543 this._ = { 96544 callbackMap: {} 96545 }; 96546 }, 96547 96548 constructor: hubProxy, 96549 96550 hasSubscriptions: function () { 96551 return hasMembers(this._.callbackMap); 96552 }, 96553 96554 on: function (eventName, callback) { 96555 /// <summary>Wires up a callback to be invoked when a invocation request is received from the server hub.</summary> 96556 /// <param name="eventName" type="String">The name of the hub event to register the callback for.</param> 96557 /// <param name="callback" type="Function">The callback to be invoked.</param> 96558 var that = this, 96559 callbackMap = that._.callbackMap; 96560 96561 // Normalize the event name to lowercase 96562 eventName = eventName.toLowerCase(); 96563 96564 // If there is not an event registered for this callback yet we want to create its event space in the callback map. 96565 if (!callbackMap[eventName]) { 96566 callbackMap[eventName] = {}; 96567 } 96568 96569 // Map the callback to our encompassed function 96570 callbackMap[eventName][callback] = function (e, data) { 96571 callback.apply(that, data); 96572 }; 96573 96574 $(that).bind(makeEventName(eventName), callbackMap[eventName][callback]); 96575 96576 return that; 96577 }, 96578 96579 off: function (eventName, callback) { 96580 /// <summary>Removes the callback invocation request from the server hub for the given event name.</summary> 96581 /// <param name="eventName" type="String">The name of the hub event to unregister the callback for.</param> 96582 /// <param name="callback" type="Function">The callback to be invoked.</param> 96583 var that = this, 96584 callbackMap = that._.callbackMap, 96585 callbackSpace; 96586 96587 // Normalize the event name to lowercase 96588 eventName = eventName.toLowerCase(); 96589 96590 callbackSpace = callbackMap[eventName]; 96591 96592 // Verify that there is an event space to unbind 96593 if (callbackSpace) { 96594 // Only unbind if there's an event bound with eventName and a callback with the specified callback 96595 if (callbackSpace[callback]) { 96596 $(that).unbind(makeEventName(eventName), callbackSpace[callback]); 96597 96598 // Remove the callback from the callback map 96599 delete callbackSpace[callback]; 96600 96601 // Check if there are any members left on the event, if not we need to destroy it. 96602 if (!hasMembers(callbackSpace)) { 96603 delete callbackMap[eventName]; 96604 } 96605 } else if (!callback) { // Check if we're removing the whole event and we didn't error because of an invalid callback 96606 $(that).unbind(makeEventName(eventName)); 96607 96608 delete callbackMap[eventName]; 96609 } 96610 } 96611 96612 return that; 96613 }, 96614 96615 invoke: function (methodName) { 96616 /// <summary>Invokes a server hub method with the given arguments.</summary> 96617 /// <param name="methodName" type="String">The name of the server hub method.</param> 96618 96619 var that = this, 96620 connection = that.connection, 96621 args = $.makeArray(arguments).slice(1), 96622 argValues = map(args, getArgValue), 96623 data = { H: that.hubName, M: methodName, A: argValues, I: connection._.invocationCallbackId }, 96624 d = $.Deferred(), 96625 callback = function (minResult) { 96626 var result = that._maximizeHubResponse(minResult), 96627 source, 96628 error; 96629 96630 // Update the hub state 96631 $.extend(that.state, result.State); 96632 96633 if (result.Progress) { 96634 if (d.notifyWith) {
vendor: 8,250 bytes, lines 96635-96825
96635 // Progress is only supported in jQuery 1.7+ 96636 d.notifyWith(that, [result.Progress.Data]); 96637 } else if(!connection._.progressjQueryVersionLogged) { 96638 connection.log("A hub method invocation progress update was received but the version of jQuery in use (" + $.prototype.jquery + ") does not support progress updates. Upgrade to jQuery 1.7+ to receive progress notifications."); 96639 connection._.progressjQueryVersionLogged = true; 96640 } 96641 } else if (result.Error) { 96642 // Server hub method threw an exception, log it & reject the deferred 96643 if (result.StackTrace) { 96644 connection.log(result.Error + "\n" + result.StackTrace + "."); 96645 } 96646 96647 // result.ErrorData is only set if a HubException was thrown 96648 source = result.IsHubException ? "HubException" : "Exception"; 96649 error = signalR._.error(result.Error, source); 96650 error.data = result.ErrorData; 96651 96652 connection.log(that.hubName + "." + methodName + " failed to execute. Error: " + error.message); 96653 d.rejectWith(that, [error]); 96654 } else { 96655 // Server invocation succeeded, resolve the deferred 96656 connection.log("Invoked " + that.hubName + "." + methodName); 96657 d.resolveWith(that, [result.Result]); 96658 } 96659 }; 96660 96661 connection._.invocationCallbacks[connection._.invocationCallbackId.toString()] = { scope: that, method: callback }; 96662 connection._.invocationCallbackId += 1; 96663 96664 if (!$.isEmptyObject(that.state)) { 96665 data.S = that.state; 96666 } 96667 96668 connection.log("Invoking " + that.hubName + "." + methodName); 96669 connection.send(data); 96670 96671 return d.promise(); 96672 }, 96673 96674 _maximizeHubResponse: function (minHubResponse) { 96675 return { 96676 State: minHubResponse.S, 96677 Result: minHubResponse.R, 96678 Progress: minHubResponse.P ? { 96679 Id: minHubResponse.P.I, 96680 Data: minHubResponse.P.D 96681 } : null, 96682 Id: minHubResponse.I, 96683 IsHubException: minHubResponse.H, 96684 Error: minHubResponse.E, 96685 StackTrace: minHubResponse.T, 96686 ErrorData: minHubResponse.D 96687 }; 96688 } 96689 }; 96690 96691 hubProxy.fn.init.prototype = hubProxy.fn; 96692 96693 // hubConnection 96694 function hubConnection(url, options) { 96695 /// <summary>Creates a new hub connection.</summary> 96696 /// <param name="url" type="String">[Optional] The hub route url, defaults to "/signalr".</param> 96697 /// <param name="options" type="Object">[Optional] Settings to use when creating the hubConnection.</param> 96698 var settings = { 96699 qs: null, 96700 logging: false, 96701 useDefaultPath: true 96702 }; 96703 96704 $.extend(settings, options); 96705 96706 if (!url || settings.useDefaultPath) { 96707 url = (url || "") + "/signalr"; 96708 } 96709 return new hubConnection.fn.init(url, settings); 96710 } 96711 96712 hubConnection.fn = hubConnection.prototype = $.connection(); 96713 96714 hubConnection.fn.init = function (url, options) { 96715 var settings = { 96716 qs: null, 96717 logging: false, 96718 useDefaultPath: true 96719 }, 96720 connection = this; 96721 96722 $.extend(settings, options); 96723 96724 // Call the base constructor 96725 $.signalR.fn.init.call(connection, url, settings.qs, settings.logging); 96726 96727 // Object to store hub proxies for this connection 96728 connection.proxies = {}; 96729 96730 connection._.invocationCallbackId = 0; 96731 connection._.invocationCallbacks = {}; 96732 96733 // Wire up the received handler 96734 connection.received(function (minData) { 96735 var data, proxy, dataCallbackId, callback, hubName, eventName; 96736 if (!minData) { 96737 return; 96738 } 96739 96740 // We have to handle progress updates first in order to ensure old clients that receive 96741 // progress updates enter the return value branch and then no-op when they can't find 96742 // the callback in the map (because the minData.I value will not be a valid callback ID) 96743 if (typeof (minData.P) !== "undefined") { 96744 // Process progress notification 96745 dataCallbackId = minData.P.I.toString(); 96746 callback = connection._.invocationCallbacks[dataCallbackId]; 96747 if (callback) { 96748 callback.method.call(callback.scope, minData); 96749 } 96750 } else if (typeof (minData.I) !== "undefined") { 96751 // We received the return value from a server method invocation, look up callback by id and call it 96752 dataCallbackId = minData.I.toString(); 96753 callback = connection._.invocationCallbacks[dataCallbackId]; 96754 if (callback) { 96755 // Delete the callback from the proxy 96756 connection._.invocationCallbacks[dataCallbackId] = null; 96757 delete connection._.invocationCallbacks[dataCallbackId]; 96758 96759 // Invoke the callback 96760 callback.method.call(callback.scope, minData); 96761 } 96762 } else { 96763 data = this._maximizeClientHubInvocation(minData); 96764 96765 // We received a client invocation request, i.e. broadcast from server hub 96766 connection.log("Triggering client hub event '" + data.Method + "' on hub '" + data.Hub + "'."); 96767 96768 // Normalize the names to lowercase 96769 hubName = data.Hub.toLowerCase(); 96770 eventName = data.Method.toLowerCase(); 96771 96772 // Trigger the local invocation event 96773 proxy = this.proxies[hubName]; 96774 96775 // Update the hub state 96776 $.extend(proxy.state, data.State); 96777 $(proxy).triggerHandler(makeEventName(eventName), [data.Args]); 96778 } 96779 }); 96780 96781 connection.error(function (errData, origData) { 96782 var callbackId, callback; 96783 96784 if (!origData) { 96785 // No original data passed so this is not a send error 96786 return; 96787 } 96788 96789 callbackId = origData.I; 96790 callback = connection._.invocationCallbacks[callbackId]; 96791 96792 // Verify that there is a callback bound (could have been cleared) 96793 if (callback) { 96794 // Delete the callback 96795 connection._.invocationCallbacks[callbackId] = null; 96796 delete connection._.invocationCallbacks[callbackId]; 96797 96798 // Invoke the callback with an error to reject the promise 96799 callback.method.call(callback.scope, { E: errData }); 96800 } 96801 }); 96802 96803 connection.reconnecting(function () { 96804 if (connection.transport && connection.transport.name === "webSockets") { 96805 clearInvocationCallbacks(connection, "Connection started reconnecting before invocation result was received."); 96806 } 96807 }); 96808 96809 connection.disconnected(function () { 96810 clearInvocationCallbacks(connection, "Connection was disconnected before invocation result was received."); 96811 }); 96812 }; 96813 96814 hubConnection.fn._maximizeClientHubInvocation = function (minClientHubInvocation) { 96815 return { 96816 Hub: minClientHubInvocation.H, 96817 Method: minClientHubInvocation.M, 96818 Args: minClientHubInvocation.A, 96819 State: minClientHubInvocation.S 96820 }; 96821 }; 96822 96823 hubConnection.fn._registerSubscribedHubs = function () { 96824 /// <summary> 96825 /// Sets the starting event to loop through the known hub
96825s and register any new hubs 96826 /// that have been added to the proxy. 96827 /// </summary> 96828 var connection = this; 96829 96830 if (!connection._subscribedToHubs) { 96831 connection._subscribedToHubs = true; 96832 connection.starting(function () { 96833 // Set the connection's data object with all the hub proxies with active subscriptions. 96834 // These proxies will receive notifications from the server. 96835 var subscribedHubs = []; 96836 96837 $.each(connection.proxies, function (key) { 96838 if (this.hasSubscriptions()) { 96839 subscribedHubs.push({ name: key }); 96840 connection.log("Client subscribed to hub '" + key + "'."); 96841 } 96842 }); 96843 96844 if (subscribedHubs.length === 0) { 96845 connection.log("No hubs have been subscribed to. The client will not receive data from hubs. To fix, declare at least one client side function prior to connection start for each hub you wish to subscribe to."); 96846 } 96847 96848 connection.data = connection.json.stringify(subscribedHubs); 96849 }); 96850 } 96851 }; 96852 96853 hubConnection.fn.createHubProxy = function (hubName) { 96854 /// <summary> 96855 /// Creates a new proxy object for the given hub connection that can be used to invoke 96856 /// methods on server hubs and handle client method invocation requests from the server. 96857 /// </summary> 96858 /// <param name="hubName" type="String"> 96859 /// The name of the hub on the server to create the proxy for. 96860 /// </param> 96861 96862 // Normalize the name to lowercase 96863 hubName = hubName.toLowerCase(); 96864 96865 var proxy = this.proxies[hubName]; 96866 if (!proxy) { 96867 proxy = hubProxy(this, hubName); 96868 this.proxies[hubName] = proxy; 96869 } 96870 96871 this._registerSubscribedHubs(); 96872 96873 return proxy; 96874 }; 96875 96876 hubConnection.fn.init.prototype = hubConnection.fn; 96877 96878 $.hubConnection = hubConnection; 96879 96880}(window.jQuery, window)); 96881/* jquery.signalR.version.js */ 96882// Copyright (c) .NET Foundation. All rights reserved. 96883// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 96884 96885 96886/*global window:false */ 96887/// <reference path="jquery.signalR.core.js" /> 96888(function ($, undefined) { 96889 $.signalR.version = "2.2.1"; 96890}(window.jQuery)); 96891 96892define("signalr", ["jquery"], (function (global) { 96893 return function () { 96894 var ret, fn; 96895 return ret || global.$.connection; 96896 }; 96897}(this))); 96898 96899// Edited by Simon Woodhead on 21061116 to remove exports code which was causing issues in the browser. 96900 96901/*! 96902 * Retina.js v2.0.0 96903 * 96904 * Copyright 2016 Axial, LLC 96905 * Released under the MIT license 96906 * 96907 * Retina.js is an open source script that makes it easy to serve 96908 * high-resolution images to devices with retina displays. 96909 */ 96910 96911 96912//Object.defineProperty(exports, "__esModule", { 96913// value: true 96914//}); 96915/* 96916 * Determine whether or not `window` is available. 96917 */ 96918var hasWindow = typeof window !== 'undefined'; 96919 96920/* 96921 * Get the device pixel ratio per our environment. 96922 * Default to 1. 96923 */ 96924var environment = hasWindow ? parseInt(window.devicePixelRatio + 0.5, 10) || 1 : 1; 96925 96926/* 96927 * Define a pattern for capturing src url suffixes. 96928 */ 96929var srcReplace = /(\.[A-z]{3,4}\/?(\?.*)?)$/; 96930var inlineReplace = /url\(('|")?([^\)'"]+)('|")?\)/i; 96931 96932/* 96933 * Define our selectors for elements to target. 96934 */ 96935var selector = '[data-rjs]'; 96936 96937/** 96938 * Chooses the actual image size to fetch, (for example 2 or 3) that 96939 * will be used to create a suffix like "@2x" or "@3x". 96940 * 96941 * @param {String|Number} cap The number the user provided indicating that 96942 * they have prepared images up to this size. 96943 * 96944 * @return {Number} The number we'll be using to create a suffix. 96945 */ 96946function chooseCap(cap) { 96947 var numericCap = parseInt(cap, 10); 96948 96949 /* 96950 * If the environment's device pixel ratio is less than what the user 96951 * provided, we'll only grab images at that size. 96952 */ 96953 if (environment < numericCap) { 96954 return environment; 96955 96956 /* 96957 * If the device pixel ratio is greater than or equal to what the 96958 * user provided, we'll use what the user provided. 96959 */ 96960 } else { 96961 return numericCap; 96962 } 96963} 96964 96965/** 96966 * Makes sure that, since we are going to swap out the source of an image, 96967 * the image does not change size on the page. 96968 * 96969 * @param {Element} image An image element in the DOM. 96970 * 96971 * @return {Element} The same element that was passed in. 96972 */ 96973function forceOriginalDimensions(image) { 96974 if (!image.hasAttribute('data-no-resize')) { 96975 if (image.offsetWidth === 0 && image.offsetHeight === 0) {
96976 image.setAttribute('width', image.naturalWidth); 96977 image.setAttribute('height', image.naturalHeight); 96978 } else { 96979 image.setAttribute('width', image.offsetWidth); 96980 image.setAttribute('height', image.offsetHeight); 96981 } 96982 } 96983 return image; 96984} 96985 96986/** 96987 * Determines whether the retina image actually exists on the server. 96988 * If so, swaps out the retina image for the standard one. If not, 96989 * leaves the original image alone. 96990 * 96991 * @param {Element} image An image element in the DOM. 96992 * @param {String} newSrc The url to the retina image. 96993 * 96994 * @return {undefined} 96995 */ 96996function setSourceIfAvailable(image, retinaURL) { 96997 var imgType = image.nodeName.toLowerCase(); 96998 96999 /* 97000 * Create a new image element and give it a load listener. When the 97001 * load listener fires, it means the URL is correct and we will then 97002 * attach it to the user's image. 97003 */ 97004 var testImage = document.createElement('img'); 97005 testImage.addEventListener('load', function () { 97006 /* 97007 * If we're dealing with an image tag, force it's dimensions 97008 * and set the source attribute. If not, go after the background-image 97009 * inline style. 97010 */ 97011 if (imgType === 'img') { 97012 forceOriginalDimensions(image).setAttribute('src', retinaURL); 97013 } else { 97014 image.style.backgroundImage = 'url(' + retinaURL + ')'; 97015 } 97016 }); 97017 97018 /* 97019 * Attach the retina URL to our proxy image to load in the new 97020 * image resource. 97021 */ 97022 testImage.setAttribute('src', retinaURL); 97023} 97024 97025/** 97026 * Attempts to do an image url swap on a given image. 97027 * 97028 * @param {Element} image An image in the DOM. 97029 * @param {String} src The original image source attribute. 97030 * @param {String|Number} rjs The pixel density cap for images provided. 97031 * 97032 * @return {undefined} 97033 */ 97034function dynamicSwapImage(image, src) { 97035 var rjs = arguments.length <= 2 || arguments[2] === undefined ? 1 : arguments[2]; 97036 97037 var cap = chooseCap(rjs); 97038 97039 /* 97040 * Don't do anything if the cap is less than 2 or there is no src. 97041 */ 97042 if (src && cap > 1) { 97043 var newSrc = src.replace(srcReplace, '@' + cap + 'x$1'); 97044 setSourceIfAvailable(image, newSrc); 97045 } 97046} 97047 97048/** 97049 * Performs an image url swap on a given image with a provided url. 97050 * 97051 * @param {Element} image An image in the DOM. 97052 * @param {String} src The original image source attribute. 97053 * @param {String} hdsrc The path for a 2x image. 97054 * 97055 * @return {undefined} 97056 */ 97057function manualSwapImage(image, src, hdsrc) { 97058 if (environment > 1) { 97059 setSourceIfAvailable(image, hdsrc); 97060 } 97061} 97062 97063/** 97064 * Collects all images matching our selector, and converts our 97065 * NodeList into an Array so that Array methods will be available to it. 97066 * 97067 * @return {Array} Contains all elements matching our selector. 97068 */ 97069function getImages() { 97070 return typeof document !== 'undefined' ? Array.prototype.slice.call(document.querySelectorAll(selector)) : []; 97071} 97072 97073/** 97074 * Converts a string like "url(hello.png)" into "hello.png". 97075 * 97076 * @param {Element} img An HTML element with a background image. 97077 * 97078 * @return {String} 97079 */ 97080function cleanBgImg(img) { 97081 return img.style.backgroundImage.replace(inlineReplace, '$2'); 97082} 97083 97084/** 97085 * Gets all participating images and dynamically swaps out each one for its 97086 * retina equivalent taking into account the environment capabilities and 97087 * the densities for which the user has provided images. 97088 * 97089 * @return {undefined} 97090 */ 97091function retina() {
vendor: 12,318 bytes, lines 97092-97142
97092 getImages().forEach(function (img) { 97093 var isImg = img.nodeName.toLowerCase() === 'img'; 97094 var src = isImg ? img.getAttribute('src') : cleanBgImg(img); 97095 var rjs = img.getAttribute('data-rjs'); 97096 var rjsIsNumber = !isNaN(parseInt(rjs, 10)); 97097 97098 /* 97099 * If the user provided a number, dynamically swap out the image. 97100 * If the user provided a url, do it manually. 97101 */ 97102 if (rjsIsNumber) { 97103 dynamicSwapImage(img, src, rjs); 97104 } else { 97105 manualSwapImage(img, src, rjs); 97106 } 97107 }); 97108} 97109 97110/* 97111 * If this environment has `window`, activate the plugin. 97112 */ 97113if (hasWindow) { 97114 window.addEventListener('load', retina); 97115 window.retinajs = retina; 97116} 97117 97118//exports.default = retina; 97119define("retinajs", (function (global) { 97120 return function () { 97121 var ret, fn; 97122 return ret || global.retinajs; 97123 }; 97124}(this))); 97125 97126/* 97127 _ _ _ _ 97128 ___| (_) ___| | __ (_)___ 97129/ __| | |/ __| |/ / | / __| 97130\__ \ | | (__| < _ | \__ \ 97131|___/_|_|\___|_|\_(_)/ |___/ 97132 |__/ 97133 97134 Version: 1.6.0 97135 Author: Ken Wheeler 97136 Website: http://kenwheeler.github.io 97137 Docs: http://kenwheeler.github.io/slick 97138 Repo: http://github.com/kenwheeler/slick 97139 Issues: http://github.com/kenwheeler/slick/issues 97140 97141 */ 97142!function(a){"use strict";"function"==typeof define&&define.amd?define('slick',["jquery"],a):"undefined"!=typeof exports?module.exports=a(require("jquery")):a(jQuery)}(function(a){"use strict";var b=window.Slick||{};b=function(){function c(c,d){var f,e=this;e.defaults={accessibility:!0,adaptiveHeight:!1,appendArrows:a(c),appendDots:a(c),arrows:!0,asNavFor:null,prevArrow:'<button type="button" data-role="none" class="slick-prev" aria-label="Previous" tabindex="0" role="button">Previous</button>',nextArrow:'<button type="button" data-role="none" class="slick-next" aria-label="Next" tabindex="0" role="button">Next</button>',autoplay:!1,autoplaySpeed:3e3,centerMode:!1,centerPadding:"50px",cssEase:"ease",customPaging:function(b,c){return a('<button type="button" data-role="none" role="button" tabindex="0" />').text(c+1)},dots:!1,dotsClass:"slick-dots",draggable:!0,easing:"linear",edgeFriction:.35,fade:!1,focusOnSelect:!1,infinite:!0,initialSlide:0,lazyLoad:"ondemand",mobileFirst:!1,pauseOnHover:!0,pauseOnFocus:!0,pauseOnDotsHover:!1,respondTo:"window",responsive:null,rows:1,rtl:!1,slide:"",slidesPerRow:1,slidesToShow:1,slidesToScroll:1,speed:500,swipe:!0,swipeToSlide:!1,touchMove:!0,touchThreshold:5,useCSS:!0,useTransform:!0,variableWidth:!1,vertical:!1,verticalSwiping:!1,waitForAnimate:!0,zIndex:1e3},e.initials={animating:!1,dragging:!1,autoPlayTimer:null,currentDirection:0,currentLeft:null,currentSlide:0,direction:1,$dots:null,listWidth:null,listHeight:null,loadIndex:0,$nextArrow:null,$prevArrow:null,slideCount:null,slideWidth:null,$slideTrack:null,$slides:null,sliding:!1,slideOffset:0,swipeLeft:null,$list:null,touchObject:{},transformsEnabled:!1,unslicked:!1},a.extend(e,e.initials),e.activeBreakpoint=null,e.animType=null,e.animProp=null,e.breakpoints=[],e.breakpointSettings=[],e.cssTransitions=!1,e.focussed=!1,e.interrupted=!1,e.hidden="hidden",e.paused=!0,e.positionProp=null,e.respondTo=null,e.rowCount=1,e.shouldClick=!0,e.$slider=a(c),e.$slidesCache=null,e.transformType=null,e.transitionType=null,e.visibilityChange="visibilitychange",e.windowWidth=0,e.windowTimer=null,f=a(c).data("slick")||{},e.options=a.extend({},e.defaults,d,f),e.currentSlide=e.options.initialSlide,e.originalSettings=e.options,"undefined"!=typeof document.mozHidden?(e.hidden="mozHidden",e.visibilityChange="mozvisibilitychange"):"undefined"!=typeof document.webkitHidden&&(e.hidden="webkitHidden",e.visibilityChange="webkitvisibilitychange"),e.autoPlay=a.proxy(e.autoPlay,e),e.autoPlayClear=a.proxy(e.autoPlayClear,e),e.autoPlayIterator=a.proxy(e.autoPlayIterator,e),e.changeSlide=a.proxy(e.changeSlide,e),e.clickHandler=a.proxy(e.clickHandler,e),e.selectHandler=a.proxy(e.selectHandler,e),e.setPosition=a.proxy(e.setPosition,e),e.swipeHandler=a.proxy(e.swipeHandler,e),e.dragHandler=a.proxy(e.dragHandler,e),e.keyHandler=a.proxy(e.keyHandler,e),e.instanceUid=b++,e.htmlExpr=/^(?:\s*(<[\w\W]+>)[^>]*)$/,e.registerBreakpoints(),e.init(!0)}var b=0;return c}(),b.prototype.activateADA=function(){var a=this;a.$slideTrack.find(".slick-active").attr({"aria-hidden":"false"}).find("a, input, button, select").attr({tabindex:"0"})},b.prototype.addSlide=b.prototype.slickAdd=function(b,c,d){var e=this;if("boolean"==typeof c)d=c,c=null;else if(0>c||c>=e.slideCount)return!1;e.unload(),"number"==typeof c?0===c&&0===e.$slides.length?a(b).appendTo(e.$slideTrack):d?a(b).insertBefore(e.$slides.eq(c)):a(b).insertAfter(e.$slides.eq(c)):d===!0?a(b).prependTo(e.$slideTrack):a(b).appendTo(e.$slideTrack),e.$slides=e.$slideTrack.children(this.options.slide),e.$slideTrack.children(this.options.slide).detach(),e.$slideTrack.append(e.$slides),e.$slides.each(function(b,c){a(c).attr("data-slick-index",b)}),e.$slidesCache=e.$slides,e.reinit()},b.prototype.animateHeight=function(){var a=this;if(1===a.options.slidesToShow&&a.options.adaptiveHeight===!0&&a.options.vertical===!1){var b=a.$slides.eq(a.currentSlide).outerHeight(!0);a.$list.animate({height:b},a.options.speed)}},b.prototype.animateSlide=function(b,c){var d={},e=this;e.animateHeight(),e.options.rtl===!0&&e.options.vertical===!1&&(b=-b),e.transformsEnabled===!1?e.options.vertical===!1?e.$slideTrack.animate({left:b},e.options.speed,e.options.easing,c):e.$slideTrack.animate({top:b},e.options.speed,e.options.easing,c):e.cssTransitions===!1?(e.options.rtl===!0&&(e.currentLeft=-e.currentLeft),a({animStart:e.currentLeft}).animate({animStart:b},{duration:e.options.speed,easing:e.options.easing,step:function(a){a=Math.ceil(a),e.options.vertical===!1?(d[e.animType]="translate("+a+"px, 0px)",e.$slideTrack.css(d)):(d[e.animType]="translate(0px,"+a+"px)",e.$slideTrack.css(d))},complete:function(){c&&c.call()}})):(e.applyTransition(),b=Math.ceil(b),e.options.vertical===!1?d[e.animType]="translate3d("+b+"px, 0px, 0px)":d[e.animType]="translate3d(0px,"+b+"px, 0px)",e.$slideTrack.css(d),c&&setTimeout(function(){e.disableTransition(),c.call()},e.options.speed))},b.prototype.getNavTarget=function(){var b=this,c=b.options.asNavFor;return c&&null!==c&&(c=a(c).not(b.$slider)),c},b.prototype.asNavFor=function(b){var c=this,d=c.getNavTarget();null!==d&&"object"==typeof d&&d.each(function(){var c=a(this).slick("getSlick");c.unslicked||c.slideHandler(b,!0)})},b.prototype.applyTransition=function(a){var b=this,c={};b.options.fade===!1?c[b.transitionType]=b.transformType+" "+b.options.speed+"ms "+b.options.cssEase:c[b.transitionType]="opacity "+b.options.speed+"ms "+b.options.cssEase,b.options.fade===!1?b.$slideTrack.css(c):b.$slides.eq(a).css(c)},b.prototype.autoPlay=function(){var a=this;a.autoPlayClear(),a.slideCount>a.options.slidesToShow&&(a.autoPlayTimer=setInterval(a.autoPlayIterator,a.options.autoplaySpeed))},b.prototype.autoPlayClear=function(){var a=this;a.autoPlayTimer&&clearInterval(a.autoPlayTimer)},b.prototype.autoPlayIterator=function(){var a=this,b=a.currentSlide+a.options.slidesToScroll;a.paused||a.interrupted||a.focussed||(a.options.infinite===!1&&(1===a.direction&&a.currentSlide+1===a.slideCount-1?a.direction=0:0===a.direction&&(b=a.currentSlide-a.options.slidesToScroll,a.currentSlide-1===0&&(a.direction=1))),a.slideHandler(b))},b.prototype.buildArrows=function(){var b=this;b.options.arrows===!0&&(b.$prevArrow=a(b.options.prevArrow).addClass("slick-arrow"),b.$nextArrow=a(b.options.nextArrow).addClass("slick-arrow"),b.slideCount>b.options.slidesToShow?(b.$prevArrow.removeClass("slick-hidden").removeAttr("aria-hidden tabindex"),b.$nextArrow.removeClass("slick-hidden").removeAttr("aria-hidden tabindex"),b.htmlExpr.test(b.options.prevArrow)&&b.$prevArrow.prependTo(b.options.appendArrows),b.htmlExpr.test(b.options.nextArrow)&&b.$nextArrow.appendTo(b.options.appendArrows),b.options.infinite!==!0&&b.$prevArrow.addClass("slick-disabled").attr("aria-disabled","true")):b.$prevArrow.add(b.$nextArrow).addClass("slick-hidden").attr({"aria-disabled":"true",tabindex:"-1"}))},b.prototype.buildDots=function(){var c,d,b=this;if(b.options.dots===!0&&b.slideCount>b.options.slidesToShow){for(b.$slider.addClass("slick-dotted"),d=a("<ul />").addClass(b.options.dotsClass),c=0;c<=b.getDotCount();c+=1)d.append(a("<li />").append(b.options.customPaging.call(this,b,c)));b.$dots=d.appendTo(b.options.appendDots),b.$dots.find("li").first().addClass("slick-active").attr("aria-hidden","false")}},b.prototype.buildOut=function(){var b=this;b.$slides=b.$slider.children(b.options.slide+":not(.slick-cloned)").addClass("slick-slide"),b.slideCount=b.$slides.length,b.$slides.each(function(b,c){a(c).attr("data-slick-index",b).data("originalStyling",a(c).attr("style")||"")}),b.$slider.addClass("slick-slider"),b.$slideTrack=0===b.slideCount?a('<div class="slick-track"/>').appendTo(b.$slider):b.$slides.wrapAll('<div class="slick-track"/>').parent(),b.$list=b.$slideTrack.wrap('<div aria-live="polite" class="slick-list"/>').parent(),b.$slideTrack.css("opacity",0),(b.options.centerMode===!0||b.options.swipeToSlide===!0)&&(b.options.slidesToScroll=1),a("img[data-lazy]",b.$slider).not("[src]").addClass("slick-loading"),b.setupInfinite(),b.buildArrows(),b.buildDots(),b.updateDots(),b.setSlideClasses("number"==typeof b.currentSlide?b.currentSlide:0),b.options.draggable===!0&&b.$list.addClass("draggable")},b.prototype.buildRows=function(){var b,c,d,e,f,g,h,a=this;if(e=document.createDocumentFragment(),g=a.$slider.children(),a.options.rows>1){for(h=a.options.slidesPerRow*a.options.rows,f=Math.ceil(g.length/h),b=0;f>b;b++){var i=document.createElement("div");for(c=0;c<a.options.rows;c++){var j=document.createElement("div");for(d=0;d<a.options.slidesPerRow;d++){var k=b*h+(c*a.options.slidesPerRow+d);g.get(k)&&j.appendChild(g.get(k))}i.appendChild(j)}e.appendChild(i)}a.$slider.empty().append(e),a.$slider.children().children().children().css({width:100/a.options.slidesPerRow+"%",display:"inline-block"})}},b.prototype.checkResponsive=function(b,c){var e,f,g,d=this,h=!1,i=d.$slider.width(),j=window.innerWidth||a(window).width();if("window"===d.respondTo?g=j:"slider"===d.respondTo?g=i:"min"===d.respondTo&&(g=Math.min(j,i)),d.options.responsive&&d.options.responsive.length&&null!==d.options.responsive){f=null;for(e in d.breakpoints)d.breakpoints.hasOwnProperty(e)&&(d.originalSettings.mobileFirst===!1?g<d.breakpoints[e]&&(f=d.breakpoints[e]):g>d.breakpoints[e]&&(f=d.breakpoints[e]));null!==f?null!==d.activeBreakpoint?(f!==d.activeBreakpoint||c)&&(d.activeBreakpoint=f,"unslick"===d.breakpointSettings[f]?d.unslick(f):(d.options=a.extend({},d.originalSettings,d.breakpointSettings[f]),b===!0&&(d.currentSlide=d.options.initialSlide),d.refresh(b)),h=f):(d.activeBreakpoint=f,"unslick"===d.breakpointSettings[f]?d.unslick(f):(d.options=a.extend({},d.originalSettings,d.breakpointSettings[f]),b===!0&&(d.currentSlide=d.options.initialSlide),d.refresh(b)),h=f):null!==d.activeBreakpoint&&(d.activeBreakpoint=null,d.options=d.originalSettings,b===!0&&(d.currentSlide=d.options.initialSlide),d.refresh(b),h=f),b||h===!1||d.$slider.trigger("breakpoint",[d,h])}},b.prototype.changeSlide=function(b,c){var f,g,h,d=this,e=a(b.currentTarget);switch(e.is("a")&&b.preventDefault(),e.is("li")||(e=e.closest("li")),h=d.slideCount%d.options.slidesToScroll!==0,f=h?0:(d.slideCount-d.currentSlide)%d.options.slidesToScroll,b.data.message){case"previous":g=0===f?d.options.slidesToScroll:d.options.slidesToShow-f,d.slideCount>d.options.slidesToShow&&d.slideHandler(d.currentSlide-g,!1,c);break;case"next":g=0===f?d.options.slidesToScroll:f,d.slideCount>d.options.slidesToShow&&d.slideHandler(d.currentSlide+g,!1,c);break;case"index":var i=0===b.data.index?0:b.data.index||e.index()*d.options.slidesToScroll;d.slideHandler(d.checkNavigable(i),!1,c),e.children().trigger("focus");break;default:return}},b.prototype.checkNavigable=function(a){var c,d,b=this;if(c=b.getNavigableIndexes(),d=0,a>c[c.length-1])a=c[c.length-1];else for(var e in c){if(a<c[e]){a=d;break}d=c[e]}return a},b.prototype.cleanUpEvents=function(){var b=this;b.options.dots&&null!==b.$dots&&a("li",b.$dots).off("click.slick",b.changeSlide).off("mouseenter.slick",a.proxy(b.interrupt,b,!0)).off("mouseleave.
97142slick",a.proxy(b.interrupt,b,!1)),b.$slider.off("focus.slick blur.slick"),b.options.arrows===!0&&b.slideCount>b.options.slidesToShow&&(b.$prevArrow&&b.$prevArrow.off("click.slick",b.changeSlide),b.$nextArrow&&b.$nextArrow.off("click.slick",b.changeSlide)),b.$list.off("touchstart.slick mousedown.slick",b.swipeHandler),b.$list.off("touchmove.slick mousemove.slick",b.swipeHandler),b.$list.off("touchend.slick mouseup.slick",b.swipeHandler),b.$list.off("touchcancel.slick mouseleave.slick",b.swipeHandler),b.$list.off("click.slick",b.clickHandler),a(document).off(b.visibilityChange,b.visibility),b.cleanUpSlideEvents(),b.options.accessibility===!0&&b.$list.off("keydown.slick",b.keyHandler),b.options.focusOnSelect===!0&&a(b.$slideTrack).children().off("click.slick",b.selectHandler),a(window).off("orientationchange.slick.slick-"+b.instanceUid,b.orientationChange),a(window).off("resize.slick.slick-"+b.instanceUid,b.resize),a("[draggable!=true]",b.$slideTrack).off("dragstart",b.preventDefault),a(window).off("load.slick.slick-"+b.instanceUid,b.setPosition),a(document).off("ready.slick.slick-"+b.instanceUid,b.setPosition)},b.prototype.cleanUpSlideEvents=function(){var b=this;b.$list.off("mouseenter.slick",a.proxy(b.interrupt,b,!0)),b.$list.off("mouseleave.slick",a.proxy(b.interrupt,b,!1))},b.prototype.cleanUpRows=function(){var b,a=this;a.options.rows>1&&(b=a.$slides.children().children(),b.removeAttr("style"),a.$slider.empty().append(b))},b.prototype.clickHandler=function(a){var b=this;b.shouldClick===!1&&(a.stopImmediatePropagation(),a.stopPropagation(),a.preventDefault())},b.prototype.destroy=function(b){var c=this;c.autoPlayClear(),c.touchObject={},c.cleanUpEvents(),a(".slick-cloned",c.$slider).detach(),c.$dots&&c.$dots.remove(),c.$prevArrow&&c.$prevArrow.length&&(c.$prevArrow.removeClass("slick-disabled slick-arrow slick-hidden").removeAttr("aria-hidden aria-disabled tabindex").css("display",""),c.htmlExpr.test(c.options.prevArrow)&&c.$prevArrow.remove()),c.$nextArrow&&c.$nextArrow.length&&(c.$nextArrow.removeClass("slick-disabled slick-arrow slick-hidden").removeAttr("aria-hidden aria-disabled tabindex").css("display",""),c.htmlExpr.test(c.options.nextArrow)&&c.$nextArrow.remove()),c.$slides&&(c.$slides.removeClass("slick-slide slick-active slick-center slick-visible slick-current").removeAttr("aria-hidden").removeAttr("data-slick-index").each(function(){a(this).attr("style",a(this).data("originalStyling"))}),c.$slideTrack.children(this.options.slide).detach(),c.$slideTrack.detach(),c.$list.detach(),c.$slider.append(c.$slides)),c.cleanUpRows(),c.$slider.removeClass("slick-slider"),c.$slider.removeClass("slick-initialized"),c.$slider.removeClass("slick-dotted"),c.unslicked=!0,b||c.$slider.trigger("destroy",[c])},b.prototype.disableTransition=function(a){var b=this,c={};c[b.transitionType]="",b.options.fade===!1?b.$slideTrack.css(c):b.$slides.eq(a).css(c)},b.prototype.fadeSlide=function(a,b){var c=this;c.cssTransitions===!1?(c.$slides.eq(a).css({zIndex:c.options.zIndex}),c.$slides.eq(a).animate({opacity:1},c.options.speed,c.options.easing,b)):(c.applyTransition(a),c.$slides.eq(a).css({opacity:1,zIndex:c.options.zIndex}),b&&setTimeout(function(){c.disableTransition(a),b.call()},c.options.speed))},b.prototype.fadeSlideOut=function(a){var b=this;b.cssTransitions===!1?b.$slides.eq(a).animate({opacity:0,zIndex:b.options.zIndex-2},b.options.speed,b.options.easing):(b.applyTransition(a),b.$slides.eq(a).css({opacity:0,zIndex:b.options.zIndex-2}))},b.prototype.filterSlides=b.prototype.slickFilter=function(a){var b=this;null!==a&&(b.$slidesCache=b.$slides,b.unload(),b.$slideTrack.children(this.options.slide).detach(),b.$slidesCache.filter(a).appendTo(b.$slideTrack),b.reinit())},b.prototype.focusHandler=function(){var b=this;b.$slider.off("focus.slick blur.slick").on("focus.slick blur.slick","*:not(.slick-arrow)",function(c){c.stopImmediatePropagation();var d=a(this);setTimeout(function(){b.options.pauseOnFocus&&(b.focussed=d.is(":focus"),b.autoPlay())},0)})},b.prototype.getCurrent=b.prototype.slickCurrentSlide=function(){var a=this;return a.currentSlide},b.prototype.getDotCount=function(){var a=this,b=0,c=0,d=0;if(a.options.infinite===!0)for(;b<a.slideCount;)++d,b=c+a.options.slidesToScroll,c+=a.options.slidesToScroll<=a.options.slidesToShow?a.options.slidesToScroll:a.options.slidesToShow;else if(a.options.centerMode===!0)d=a.slideCount;else if(a.options.asNavFor)for(;b<a.slideCount;)++d,b=c+a.options.slidesToScroll,c+=a.options.slidesToScroll<=a.options.slidesToShow?a.options.slidesToScroll:a.options.slidesToShow;else d=1+Math.ceil((a.slideCount-a.options.slidesToShow)/a.options.slidesToScroll);return d-1},b.prototype.getLeft=function(a){var c,d,f,b=this,e=0;return b.slideOffset=0,d=b.$slides.first().outerHeight(!0),b.options.infinite===!0?(b.slideCount>b.options.slidesToShow&&(b.slideOffset=b.slideWidth*b.options.slidesToShow*-1,e=d*b.options.slidesToShow*-1),b.slideCount%b.options.slidesToScroll!==0&&a+b.options.slidesToScroll>b.slideCount&&b.slideCount>b.options.slidesToShow&&(a>b.slideCount?(b.slideOffset=(b.options.slidesToShow-(a-b.slideCount))*b.slideWidth*-1,e=(b.options.slidesToShow-(a-b.slideCount))*d*-1):(b.slideOffset=b.slideCount%b.options.slidesToScroll*b.slideWidth*-1,e=b.slideCount%b.options.slidesToScroll*d*-1))):a+b.o
vendor: 4,100 bytes, line 97142
97142ptions.slidesToShow>b.slideCount&&(b.slideOffset=(a+b.options.slidesToShow-b.slideCount)*b.slideWidth,e=(a+b.options.slidesToShow-b.slideCount)*d),b.slideCount<=b.options.slidesToShow&&(b.slideOffset=0,e=0),b.options.centerMode===!0&&b.options.infinite===!0?b.slideOffset+=b.slideWidth*Math.floor(b.options.slidesToShow/2)-b.slideWidth:b.options.centerMode===!0&&(b.slideOffset=0,b.slideOffset+=b.slideWidth*Math.floor(b.options.slidesToShow/2)),c=b.options.vertical===!1?a*b.slideWidth*-1+b.slideOffset:a*d*-1+e,b.options.variableWidth===!0&&(f=b.slideCount<=b.options.slidesToShow||b.options.infinite===!1?b.$slideTrack.children(".slick-slide").eq(a):b.$slideTrack.children(".slick-slide").eq(a+b.options.slidesToShow),c=b.options.rtl===!0?f[0]?-1*(b.$slideTrack.width()-f[0].offsetLeft-f.width()):0:f[0]?-1*f[0].offsetLeft:0,b.options.centerMode===!0&&(f=b.slideCount<=b.options.slidesToShow||b.options.infinite===!1?b.$slideTrack.children(".slick-slide").eq(a):b.$slideTrack.children(".slick-slide").eq(a+b.options.slidesToShow+1),c=b.options.rtl===!0?f[0]?-1*(b.$slideTrack.width()-f[0].offsetLeft-f.width()):0:f[0]?-1*f[0].offsetLeft:0,c+=(b.$list.width()-f.outerWidth())/2)),c},b.prototype.getOption=b.prototype.slickGetOption=function(a){var b=this;return b.options[a]},b.prototype.getNavigableIndexes=function(){var e,a=this,b=0,c=0,d=[];for(a.options.infinite===!1?e=a.slideCount:(b=-1*a.options.slidesToScroll,c=-1*a.options.slidesToScroll,e=2*a.slideCount);e>b;)d.push(b),b=c+a.options.slidesToScroll,c+=a.options.slidesToScroll<=a.options.slidesToShow?a.options.slidesToScroll:a.options.slidesToShow;return d},b.prototype.getSlick=function(){return this},b.prototype.getSlideCount=function(){var c,d,e,b=this;return e=b.options.centerMode===!0?b.slideWidth*Math.floor(b.options.slidesToShow/2):0,b.options.swipeToSlide===!0?(b.$slideTrack.find(".slick-slide").each(function(c,f){return f.offsetLeft-e+a(f).outerWidth()/2>-1*b.swipeLeft?(d=f,!1):void 0}),c=Math.abs(a(d).attr("data-slick-index")-b.currentSlide)||1):b.options.slidesToScroll},b.prototype.goTo=b.prototype.slickGoTo=function(a,b){var c=this;c.changeSlide({data:{message:"index",index:parseInt(a)}},b)},b.prototype.init=function(b){var c=this;a(c.$slider).hasClass("slick-initialized")||(a(c.$slider).addClass("slick-initialized"),c.buildRows(),c.buildOut(),c.setProps(),c.startLoad(),c.loadSlider(),c.initializeEvents(),c.updateArrows(),c.updateDots(),c.checkResponsive(!0),c.focusHandler()),b&&c.$slider.trigger("init",[c]),c.options.accessibility===!0&&c.initADA(),c.options.autoplay&&(c.paused=!1,c.autoPlay())},b.prototype.initADA=function(){var b=this;b.$slides.add(b.$slideTrack.find(".slick-cloned")).attr({"aria-hidden":"true",tabindex:"-1"}).find("a, input, button, select").attr({tabindex:"-1"}),b.$slideTrack.attr("role","listbox"),b.$slides.not(b.$slideTrack.find(".slick-cloned")).each(function(c){a(this).attr({role:"option","aria-describedby":"slick-slide"+b.instanceUid+c})}),null!==b.$dots&&b.$dots.attr("role","tablist").find("li").each(function(c){a(this).attr({role:"presentation","aria-selected":"false","aria-controls":"navigation"+b.instanceUid+c,id:"slick-slide"+b.instanceUid+c})}).first().attr("aria-selected","true").end().find("button").attr("role","button").end().closest("div").attr("role","toolbar"),b.activateADA()},b.prototype.initArrowEvents=function(){var a=this;a.options.arrows===!0&&a.slideCount>a.options.slidesToShow&&(a.$prevArrow.off("click.slick").on("click.slick",{message:"previous"},a.changeSlide),a.$nextArrow.off("click.slick").on("click.slick",{message:"next"},a.changeSlide))},b.prototype.initDotEvents=function(){var b=this;b.options.dots===!0&&b.slideCount>b.options.slidesToShow&&a("li",b.$dots).on("click.slick",{message:"index"},b.changeSlide),b.options.dots===!0&&b.options.pauseOnDotsHover===!0&&a("li",b.$dots).on("mouseenter.slick",a.proxy(b.interrupt,b,!0)).on("mouseleave.slick",a.proxy(b.interrupt,b,!1))},b.prototype.initSlideEvents=function(){var b=this;b.options.pauseOnHover&&(b.$list.on("mouseenter.slick",a.proxy(b.interrupt,b,!0)),b.$list.on("mouseleave.
97142slick",a.proxy(b.interrupt,b,!1)))},b.prototype.initializeEvents=function(){var b=this;b.initArrowEvents(),b.initDotEvents(),b.initSlideEvents(),b.$list.on("touchstart.slick mousedown.slick",{action:"start"},b.swipeHandler),b.$list.on("touchmove.slick mousemove.slick",{action:"move"},b.swipeHandler),b.$list.on("touchend.slick mouseup.slick",{action:"end"},b.swipeHandler),b.$list.on("touchcancel.slick mouseleave.slick",{action:"end"},b.swipeHandler),b.$list.on("click.slick",b.clickHandler),a(document).on(b.visibilityChange,a.proxy(b.visibility,b)),b.options.accessibility===!0&&b.$list.on("keydown.slick",b.keyHandler),b.options.focusOnSelect===!0&&a(b.$slideTrack).children().on("click.slick",b.selectHandler),a(window).on("orientationchange.slick.slick-"+b.instanceUid,a.proxy(b.orientationChange,b)),a(window).on("resize.slick.slick-"+b.instanceUid,a.proxy(b.resize,b)),a("[draggable!=true]",b.$slideTrack).on("dragstart",b.preventDefault),a(window).on("load.slick.slick-"+b.instanceUid,b.setPosition),a(document).on("ready.slick.slick-"+b.instanceUid,b.setPosition)},b.prototype.initUI=function(){var a=this;a.options.arrows===!0&&a.slideCount>a.options.slidesToShow&&(a.$prevArrow.show(),a.$nextArrow.show()),a.options.dots===!0&&a.slideCount>a.options.slidesToShow&&a.$dots.show()},b.prototype.keyHandler=function(a){var b=this;a.target.tagName.match("TEXTAREA|INPUT|SELECT")||(37===a.keyCode&&b.options.accessibility===!0?b.changeSlide({data:{message:b.options.rtl===!0?"next":"previous"}}):39===a.keyCode&&b.options.accessibility===!0&&b.changeSlide({data:{message:b.options.rtl===!0?"previous":"next"}}))},b.prototype.lazyLoad=function(){function g(c){a("img[data-lazy]",c).each(function(){var c=a(this),d=a(this).attr("data-lazy"),e=document.createElement("img");e.onload=function(){c.animate({opacity:0}
vendor: 4,284 bytes, line 97142
97142,100,function(){c.attr("src",d).animate({opacity:1},200,function(){c.removeAttr("data-lazy").removeClass("slick-loading")}),b.$slider.trigger("lazyLoaded",[b,c,d])})},e.onerror=function(){c.removeAttr("data-lazy").removeClass("slick-loading").addClass("slick-lazyload-error"),b.$slider.trigger("lazyLoadError",[b,c,d])},e.src=d})}var c,d,e,f,b=this;b.options.centerMode===!0?b.options.infinite===!0?(e=b.currentSlide+(b.options.slidesToShow/2+1),f=e+b.options.slidesToShow+2):(e=Math.max(0,b.currentSlide-(b.options.slidesToShow/2+1)),f=2+(b.options.slidesToShow/2+1)+b.currentSlide):(e=b.options.infinite?b.options.slidesToShow+b.currentSlide:b.currentSlide,f=Math.ceil(e+b.options.slidesToShow),b.options.fade===!0&&(e>0&&e--,f<=b.slideCount&&f++)),c=b.$slider.find(".slick-slide").slice(e,f),g(c),b.slideCount<=b.options.slidesToShow?(d=b.$slider.find(".slick-slide"),g(d)):b.currentSlide>=b.slideCount-b.options.slidesToShow?(d=b.$slider.find(".slick-cloned").slice(0,b.options.slidesToShow),g(d)):0===b.currentSlide&&(d=b.$slider.find(".slick-cloned").slice(-1*b.options.slidesToShow),g(d))},b.prototype.loadSlider=function(){var a=this;a.setPosition(),a.$slideTrack.css({opacity:1}),a.$slider.removeClass("slick-loading"),a.initUI(),"progressive"===a.options.lazyLoad&&a.progressiveLazyLoad()},b.prototype.next=b.prototype.slickNext=function(){var a=this;a.changeSlide({data:{message:"next"}})},b.prototype.orientationChange=function(){var a=this;a.checkResponsive(),a.setPosition()},b.prototype.pause=b.prototype.slickPause=function(){var a=this;a.autoPlayClear(),a.paused=!0},b.prototype.play=b.prototype.slickPlay=function(){var a=this;a.autoPlay(),a.options.autoplay=!0,a.paused=!1,a.focussed=!1,a.interrupted=!1},b.prototype.postSlide=function(a){var b=this;b.unslicked||(b.$slider.trigger("afterChange",[b,a]),b.animating=!1,b.setPosition(),b.swipeLeft=null,b.options.autoplay&&b.autoPlay(),b.options.accessibility===!0&&b.initADA())},b.prototype.prev=b.prototype.slickPrev=function(){var a=this;a.changeSlide({data:{message:"previous"}})},b.prototype.preventDefault=function(a){a.preventDefault()},b.prototype.progressiveLazyLoad=function(b){b=b||1;var e,f,g,c=this,d=a("img[data-lazy]",c.$slider);d.length?(e=d.first(),f=e.attr("data-lazy"),g=document.createElement("img"),g.onload=function(){e.attr("src",f).removeAttr("data-lazy").removeClass("slick-loading"),c.options.adaptiveHeight===!0&&c.setPosition(),c.$slider.trigger("lazyLoaded",[c,e,f]),c.progressiveLazyLoad()},g.onerror=function(){3>b?setTimeout(function(){c.progressiveLazyLoad(b+1)},500):(e.removeAttr("data-lazy").removeClass("slick-loading").addClass("slick-lazyload-error"),c.$slider.trigger("lazyLoadError",[c,e,f]),c.progressiveLazyLoad())},g.src=f):c.$slider.trigger("allImagesLoaded",[c])},b.prototype.refresh=function(b){var d,e,c=this;e=c.slideCount-c.options.slidesToShow,!c.options.infinite&&c.currentSlide>e&&(c.currentSlide=e),c.slideCount<=c.options.slidesToShow&&(c.currentSlide=0),d=c.currentSlide,c.destroy(!0),a.extend(c,c.initials,{currentSlide:d}),c.init(),b||c.changeSlide({data:{message:"index",index:d}},!1)},b.prototype.registerBreakpoints=function(){var c,d,e,b=this,f=b.options.responsive||null;if("array"===a.type(f)&&f.length){b.respondTo=b.options.respondTo||"window";for(c in f)if(e=b.breakpoints.length-1,d=f[c].breakpoint,f.hasOwnProperty(c)){for(;e>=0;)b.breakpoints[e]&&b.breakpoints[e]===d&&b.breakpoints.splice(e,1),e--;b.breakpoints.push(d),b.breakpointSettings[d]=f[c].settings}b.breakpoints.sort(function(a,c){return b.options.mobileFirst?a-c:c-a})}},b.prototype.reinit=function(){var b=this;b.$slides=b.$slideTrack.children(b.options.slide).addClass("slick-slide"),b.slideCount=b.$slides.length,b.currentSlide>=b.slideCount&&0!==b.currentSlide&&(b.currentSlide=b.currentSlide-b.options.slidesToScroll),b.slideCount<=b.options.slidesToShow&&(b.currentSlide=0),b.registerBreakpoints(),b.setProps(),b.setupInfinite(),b.buildArrows(),b.updateArrows(),b.initArrowEvents(),b.buildDots(),b.updateDots(),b.initDotEvents(),b.cleanUpSlideEvents(),b.initSlideEvents(),b.checkResponsive(!1,!0),b.options.focusOnSelect===!0&&a(b.$slideTrack).children().on("click.slick",b.selectHandler),b.setSlideClasses("number"==typeof b.currentSlide?b.currentSlide:0),b.setPosition(),b.focu
vendor: 2,346 bytes, line 97142
97142sHandler(),b.paused=!b.options.autoplay,b.autoPlay(),b.$slider.trigger("reInit",[b])},b.prototype.resize=function(){var b=this;a(window).width()!==b.windowWidth&&(clearTimeout(b.windowDelay),b.windowDelay=window.setTimeout(function(){b.windowWidth=a(window).width(),b.checkResponsive(),b.unslicked||b.setPosition()},50))},b.prototype.removeSlide=b.prototype.slickRemove=function(a,b,c){var d=this;return"boolean"==typeof a?(b=a,a=b===!0?0:d.slideCount-1):a=b===!0?--a:a,d.slideCount<1||0>a||a>d.slideCount-1?!1:(d.unload(),c===!0?d.$slideTrack.children().remove():d.$slideTrack.children(this.options.slide).eq(a).remove(),d.$slides=d.$slideTrack.children(this.options.slide),d.$slideTrack.children(this.options.slide).detach(),d.$slideTrack.append(d.$slides),d.$slidesCache=d.$slides,void d.reinit())},b.prototype.setCSS=function(a){var d,e,b=this,c={};b.options.rtl===!0&&(a=-a),d="left"==b.positionProp?Math.ceil(a)+"px":"0px",e="top"==b.positionProp?Math.ceil(a)+"px":"0px",c[b.positionProp]=a,b.transformsEnabled===!1?b.$slideTrack.css(c):(c={},b.cssTransitions===!1?(c[b.animType]="translate("+d+", "+e+")",b.$slideTrack.css(c)):(c[b.animType]="translate3d("+d+", "+e+", 0px)",b.$slideTrack.css(c)))},b.prototype.setDimensions=function(){var a=this;a.options.vertical===!1?a.options.centerMode===!0&&a.$list.css({padding:"0px "+a.options.centerPadding}):(a.$list.height(a.$slides.first().outerHeight(!0)*a.options.slidesToShow),a.options.centerMode===!0&&a.$list.css({padding:a.options.centerPadding+" 0px"})),a.listWidth=a.$list.width(),a.listHeight=a.$list.height(),a.options.vertical===!1&&a.options.variableWidth===!1?(a.slideWidth=Math.ceil(a.listWidth/a.options.slidesToShow),a.$slideTrack.width(Math.ceil(a.slideWidth*a.$slideTrack.children(".slick-slide").length))):a.options.variableWidth===!0?a.$slideTrack.width(5e3*a.slideCount):(a.slideWidth=Math.ceil(a.listWidth),a.$slideTrack.height(Math.ceil(a.$slides.first().outerHeight(!0)*a.$slideTrack.children(".slick-slide").length)));var b=a.$slides.first().outerWidth(!0)-a.$slides.first().width();a.options.variableWidth===!1&&a.$slideTrack.children(".slick-slide").width(a.slideWidth-b)},b.prototype.setFade=function(){var c,b=this;b.$slides.each(function(d,e){c=b.slideWidth*d*-1,b.options.rtl===!0?a(e).css({position:"relative",right:c,top:0,zIndex:b.options.zIndex-2,opacity:0}
vendor: 3,178 bytes, line 97142
97142):a(e).css({position:"relative",left:c,top:0,zIndex:b.options.zIndex-2,opacity:0})}),b.$slides.eq(b.currentSlide).css({zIndex:b.options.zIndex-1,opacity:1})},b.prototype.setHeight=function(){var a=this;if(1===a.options.slidesToShow&&a.options.adaptiveHeight===!0&&a.options.vertical===!1){var b=a.$slides.eq(a.currentSlide).outerHeight(!0);a.$list.css("height",b)}},b.prototype.setOption=b.prototype.slickSetOption=function(){var c,d,e,f,h,b=this,g=!1;if("object"===a.type(arguments[0])?(e=arguments[0],g=arguments[1],h="multiple"):"string"===a.type(arguments[0])&&(e=arguments[0],f=arguments[1],g=arguments[2],"responsive"===arguments[0]&&"array"===a.type(arguments[1])?h="responsive":"undefined"!=typeof arguments[1]&&(h="single")),"single"===h)b.options[e]=f;else if("multiple"===h)a.each(e,function(a,c){b.options[a]=c});else if("responsive"===h)for(d in f)if("array"!==a.type(b.options.responsive))b.options.responsive=[f[d]];else{for(c=b.options.responsive.length-1;c>=0;)b.options.responsive[c].breakpoint===f[d].breakpoint&&b.options.responsive.splice(c,1),c--;b.options.responsive.push(f[d])}g&&(b.unload(),b.reinit())},b.prototype.setPosition=function(){var a=this;a.setDimensions(),a.setHeight(),a.options.fade===!1?a.setCSS(a.getLeft(a.currentSlide)):a.setFade(),a.$slider.trigger("setPosition",[a])},b.prototype.setProps=function(){var a=this,b=document.body.style;a.positionProp=a.options.vertical===!0?"top":"left","top"===a.positionProp?a.$slider.addClass("slick-vertical"):a.$slider.removeClass("slick-vertical"),(void 0!==b.WebkitTransition||void 0!==b.MozTransition||void 0!==b.msTransition)&&a.options.useCSS===!0&&(a.cssTransitions=!0),a.options.fade&&("number"==typeof a.options.zIndex?a.options.zIndex<3&&(a.options.zIndex=3):a.options.zIndex=a.defaults.zIndex),void 0!==b.OTransform&&(a.animType="OTransform",a.transformType="-o-transform",a.transitionType="OTransition",void 0===b.perspectiveProperty&&void 0===b.webkitPerspective&&(a.animType=!1)),void 0!==b.MozTransform&&(a.animType="MozTransform",a.transformType="-moz-transform",a.transitionType="MozTransition",void 0===b.perspectiveProperty&&void 0===b.MozPerspective&&(a.animType=!1)),void 0!==b.webkitTransform&&(a.animType="webkitTransform",a.transformType="-webkit-transform",a.transitionType="webkitTransition",void 0===b.perspectiveProperty&&void 0===b.webkitPerspective&&(a.animType=!1)),void 0!==b.msTransform&&(a.animType="msTransform",a.transformType="-ms-transform",a.transitionType="msTransition",void 0===b.msTransform&&(a.animType=!1)),void 0!==b.transform&&a.animType!==!1&&(a.animType="transform",a.transformType="transform",a.transitionType="transition"),a.transformsEnabled=a.options.useTransform&&null!==a.animType&&a.animType!==!1},b.prototype.setSlideClasses=function(a){var c,d,e,f,b=this;d=b.$slider.find(".slick-slide").removeClass("slick-active slick-center slick-current").attr("aria-hidden","true"),b.$slides.eq(a).addClass("slick-current"),b.options.centerMode===!0?(c=Math.floor(b.options.slidesToShow/2),b.options.infinite===!0&&(a>=c&&a<=b.slideCount-1-c?b.$slides.slice(a-c,a+c+1).addClass("slick-active").attr("aria-hidden","false"):(e=b.options.slidesToShow+a,
vendor: 1,607 bytes, line 97143
97143d.slice(e-c+1,e+c+2).addClass("slick-active").attr("aria-hidden","false")),0===a?d.eq(d.length-1-b.options.slidesToShow).addClass("slick-center"):a===b.slideCount-1&&d.eq(b.options.slidesToShow).addClass("slick-center")),b.$slides.eq(a).addClass("slick-center")):a>=0&&a<=b.slideCount-b.options.slidesToShow?b.$slides.slice(a,a+b.options.slidesToShow).addClass("slick-active").attr("aria-hidden","false"):d.length<=b.options.slidesToShow?d.addClass("slick-active").attr("aria-hidden","false"):(f=b.slideCount%b.options.slidesToShow,e=b.options.infinite===!0?b.options.slidesToShow+a:a,b.options.slidesToShow==b.options.slidesToScroll&&b.slideCount-a<b.options.slidesToShow?d.slice(e-(b.options.slidesToShow-f),e+f).addClass("slick-active").attr("aria-hidden","false"):d.slice(e,e+b.options.slidesToShow).addClass("slick-active").attr("aria-hidden","false")),"ondemand"===b.options.lazyLoad&&b.lazyLoad()},b.prototype.setupInfinite=function(){var c,d,e,b=this;if(b.options.fade===!0&&(b.options.centerMode=!1),b.options.infinite===!0&&b.options.fade===!1&&(d=null,b.slideCount>b.options.slidesToShow)){for(e=b.options.centerMode===!0?b.options.slidesToShow+1:b.options.slidesToShow,c=b.slideCount;c>b.slideCount-e;c-=1)d=c-1,a(b.$slides[d]).clone(!0).attr("id","").attr("data-slick-index",d-b.slideCount).prependTo(b.$slideTrack).addClass("slick-cloned");for(c=0;e>c;c+=1)d=c,a(b.$slides[d]).clone(!0).attr("id","").attr("data-slick-index",d+b.slideCount).appendTo(b.$slideTrack).addClass("slick-cloned");b.$slideTrack.find(".slick-cloned").find("[id]").each(function(){a(this).attr("id","")})}},b.prototype.
vendor: 8,958 bytes, lines 97143-97185
97143interrupt=function(a){var b=this;a||b.autoPlay(),b.interrupted=a},b.prototype.selectHandler=function(b){var c=this,d=a(b.target).is(".slick-slide")?a(b.target):a(b.target).parents(".slick-slide"),e=parseInt(d.attr("data-slick-index"));return e||(e=0),c.slideCount<=c.options.slidesToShow?(c.setSlideClasses(e),void c.asNavFor(e)):void c.slideHandler(e)},b.prototype.slideHandler=function(a,b,c){var d,e,f,g,j,h=null,i=this;return b=b||!1,i.animating===!0&&i.options.waitForAnimate===!0||i.options.fade===!0&&i.currentSlide===a||i.slideCount<=i.options.slidesToShow?void 0:(b===!1&&i.asNavFor(a),d=a,h=i.getLeft(d),g=i.getLeft(i.currentSlide),i.currentLeft=null===i.swipeLeft?g:i.swipeLeft,i.options.infinite===!1&&i.options.centerMode===!1&&(0>a||a>i.getDotCount()*i.options.slidesToScroll)?void(i.options.fade===!1&&(d=i.currentSlide,c!==!0?i.animateSlide(g,function(){i.postSlide(d)}):i.postSlide(d))):i.options.infinite===!1&&i.options.centerMode===!0&&(0>a||a>i.slideCount-i.options.slidesToScroll)?void(i.options.fade===!1&&(d=i.currentSlide,c!==!0?i.animateSlide(g,function(){i.postSlide(d)}):i.postSlide(d))):(i.options.autoplay&&clearInterval(i.autoPlayTimer),e=0>d?i.slideCount%i.options.slidesToScroll!==0?i.slideCount-i.slideCount%i.options.slidesToScroll:i.slideCount+d:d>=i.slideCount?i.slideCount%i.options.slidesToScroll!==0?0:d-i.slideCount:d,i.animating=!0,i.$slider.trigger("beforeChange",[i,i.currentSlide,e]),f=i.currentSlide,i.currentSlide=e,i.setSlideClasses(i.currentSlide),i.options.asNavFor&&(j=i.getNavTarget(),j=j.slick("getSlick"),j.slideCount<=j.options.slidesToShow&&j.setSlideClasses(i.currentSlide)),i.updateDots(),i.updateArrows(),i.options.fade===!0?(c!==!0?(i.fadeSlideOut(f),i.fadeSlide(e,function(){i.postSlide(e)})):i.postSlide(e),void i.animateHeight()):void(c!==!0?i.animateSlide(h,function(){i.postSlide(e)}):i.postSlide(e))))},b.prototype.startLoad=function(){var a=this;a.options.arrows===!0&&a.slideCount>a.options.slidesToShow&&(a.$prevArrow.hide(),a.$nextArrow.hide()),a.options.dots===!0&&a.slideCount>a.options.slidesToShow&&a.$dots.hide(),a.$slider.addClass("slick-loading")},b.prototype.swipeDirection=function(){var a,b,c,d,e=this;return a=e.touchObject.startX-e.touchObject.curX,b=e.touchObject.startY-e.touchObject.curY,c=Math.atan2(b,a),d=Math.round(180*c/Math.PI),0>d&&(d=360-Math.abs(d)),45>=d&&d>=0?e.options.rtl===!1?"left":"right":360>=d&&d>=315?e.options.rtl===!1?"left":"right":d>=135&&225>=d?e.options.rtl===!1?"right":"left":e.options.verticalSwiping===!0?d>=35&&135>=d?"down":"up":"vertical"},b.prototype.swipeEnd=function(a){var c,d,b=this;if(b.dragging=!1,b.interrupted=!1,b.shouldClick=b.touchObject.swipeLength>10?!1:!0,void 0===b.touchObject.curX)return!1;if(b.touchObject.edgeHit===!0&&b.$slider.trigger("edge",[b,b.swipeDirection()]),b.touchObject.swipeLength>=b.touchObject.minSwipe){switch(d=b.swipeDirection()){case"left":case"down":c=b.options.swipeToSlide?b.checkNavigable(b.currentSlide+b.getSlideCount()):b.currentSlide+b.getSlideCount(),b.currentDirection=0;break;case"right":case"up":c=b.options.swipeToSlide?b.checkNavigable(b.currentSlide-b.getSlideCount()):b.currentSlide-b.getSlideCount(),b.currentDirection=1}"vertical"!=d&&(b.slideHandler(c),b.touchObject={},b.$slider.trigger("swipe",[b,d]))}else b.touchObject.startX!==b.touchObject.curX&&(b.slideHandler(b.currentSlide),b.touchObject={})},b.prototype.swipeHandler=function(a){var b=this;if(!(b.options.swipe===!1||"ontouchend"in document&&b.options.swipe===!1||b.options.draggable===!1&&-1!==a.type.indexOf("mouse")))switch(b.touchObject.fingerCount=a.originalEvent&&void 0!==a.originalEvent.touches?a.originalEvent.touches.length:1,b.touchObject.minSwipe=b.listWidth/b.options.touchThreshold,b.options.verticalSwiping===!0&&(b.touchObject.minSwipe=b.listHeight/b.options.touchThreshold),a.data.action){case"start":b.swipeStart(a);break;case"move":b.swipeMove(a);break;case"end":b.swipeEnd(a)}},b.prototype.swipeMove=function(a){var d,e,f,g,h,b=this;return h=void 0!==a.originalEvent?a.originalEvent.touches:null,!b.dragging||h&&1!==h.length?!1:(d=b.getLeft(b.currentSlide),b.touchObject.curX=void 0!==h?h[0].pageX:a.clientX,b.touchObject.curY=void 0!==h?h[0].pageY:a.clientY,b.touchObject.swipeLength=Math.round(Math.sqrt(Math.pow(b.touchObject.curX-b.touchObject.startX,2))),b.options.verticalSwiping===!0&&(b.touchObject.swipeLength=Math.round(Math.sqrt(Math.pow(b.touchObject.curY-b.touchObject.startY,2)))),e=b.swipeDirection(),"vertical"!==e?(void 0!==a.originalEvent&&b.touchObject.swipeLength>4&&a.preventDefault(),g=(b.options.rtl===!1?1:-1)*(b.touchObject.curX>b.touchObject.startX?1:-1),b.options.verticalSwiping===!0&&(g=b.touchObject.curY>b.touchObject.startY?1:-1),f=b.touchObject.swipeLength,b.touchObject.edgeHit=!1,b.options.infinite===!1&&(0===b.currentSlide&&"right"===e||b.currentSlide>=b.getDotCount()&&"left"===e)&&(f=b.touchObject.swipeLength*b.options.edgeFriction,b.touchObject.edgeHit=!0),b.options.vertical===!1?b.swipeLeft=d+f*g:b.swipeLeft=d+f*(b.$list.height()/b.listWidth)*g,b.options.verticalSwiping===!0&&(b.swipeLeft=d+f*g),b.options.fade===!0||b.options.touchMove===!1?!1:b.animating===!0?(b.swipeLeft=null,!1):void b.setCSS(b.swipeLeft)):void 0)},b.prototype.swipeStart=function(a){var c,b=this;return b.interrupted=!0,1!==b.touchObject.fingerCount||b.slideCount<=b.options.slidesToShow?(b.touchObject={},!1):(void 0!==a.originalEvent&&void 0!==a.originalEvent.touches&&(c=a.originalEvent.touches[0]),b.touchObject.startX=b.touchObject.curX=void 0!==c?c.pageX:a.clientX,b.touchObject.startY=b.touchObject.curY=void 0!==c?c.pageY:a.clientY,void(b.dragging=!0))},b.prototype.unfilterSlides=b.prototype.slickUnfilter=function(){var a=this;null!==a.$slidesCache&&(a.unload(),a.$slideTrack.children(this.options.slide).detach(),a.$slidesCache.appendTo(a.$slideTrack),a.reinit())},b.prototype.unload=function(){var b=this;a(".slick-cloned",b.$slider).remove(),b.$dots&&b.$dots.remove(),b.$prevArrow&&b.htmlExpr.test(b.options.prevArrow)&&b.$prevArrow.remove(),b.$nextArrow&&b.htmlExpr.test(b.options.nextArrow)&&b.$nextArrow.remove(),b.$slides.removeClass("slick-slide slick-active slick-visible slick-current").attr("aria-hidden","true").css("width","")},b.prototype.unslick=function(a){var b=this;b.$slider.trigger("unslick",[b,a]),b.destroy()},b.prototype.updateArrows=function(){var b,a=this;b=Math.floor(a.options.slidesToShow/2),a.options.arrows===!0&&a.slideCount>a.options.slidesToShow&&!a.options.infinite&&(a.$prevArrow.removeClass("slick-disabled").attr("aria-disabled","false"),a.$nextArrow.removeClass("slick-disabled").attr("aria-disabled","false"),0===a.currentSlide?(a.$prevArrow.addClass("slick-disabled").attr("aria-disabled","true"),a.$nextArrow.removeClass("slick-disabled").attr("aria-disabled","false")):a.currentSlide>=a.slideCount-a.options.slidesToShow&&a.options.centerMode===!1?(a.$nextArrow.addClass("slick-disabled").attr("aria-disabled","true"),a.$prevArrow.removeClass("slick-disabled").attr("aria-disabled","false")):a.currentSlide>=a.slideCount-1&&a.options.centerMode===!0&&(a.$nextArrow.addClass("slick-disabled").attr("aria-disabled","true"),a.$prevArrow.removeClass("slick-disabled").attr("aria-disabled","false")))},b.prototype.updateDots=function(){var a=this;null!==a.$dots&&(a.$dots.find("li").removeClass("slick-active").attr("aria-hidden","true"),a.$dots.find("li").eq(Math.floor(a.currentSlide/a.options.slidesToScroll)).addClass("slick-active").attr("aria-hidden","false"))},b.prototype.visibility=function(){var a=this;a.options.autoplay&&(document[a.hidden]?a.interrupted=!0:a.interrupted=!1)},a.fn.slick=function(){var f,g,a=this,c=arguments[0],d=Array.prototype.slice.call(arguments,1),e=a.length;for(f=0;e>f;f++)if("object"==typeof c||"undefined"==typeof c?a[f].slick=new b(a[f],c):g=a[f].slick[c].apply(a[f].slick,d),"undefined"!=typeof g)return g;return a}}); 97144// Spectrum Colorpicker v1.1.2 97145// https://github.com/bgrins/spectrum 97146// Author: Brian Grinstead 97147// License: MIT 97148 97149(function (window, $, undefined) { 97150 var defaultOpts = { 97151 97152 // Callbacks 97153 beforeShow: noop, 97154 move: noop, 97155 change: noop, 97156 show: noop, 97157 hide: noop, 97158 97159 // Options 97160 color: false, 97161 flat: false, 97162 showInput: false, 97163 showButtons: true, 97164 clickoutFiresChange: false, 97165 showInitial: false, 97166 showPalette: false, 97167 showPaletteOnly: false, 97168 showSelectionPalette: true, 97169 localStorageKey: false, 97170 appendTo: "body", 97171 maxSelectionSize: 7, 97172 cancelText: "cancel", 97173 chooseText: "choose", 97174 preferredFormat: false, 97175 className: "", 97176 showAlpha: false, 97177 theme: "sp-light", 97178 palette: ['fff', '000'], 97179 selectionPalette: [], 97180 disabled: false 97181 }, 97182 spectrums = [], 97183 IE = !!/msie/i.exec( window.navigator.userAgent ), 97184 rgbaSupport = (function() { 97185 function contains( str, substr ) {
vendor: 4,456 bytes, lines 97186-97292
97186 return !!~('' + str).indexOf(substr); 97187 } 97188 97189 var elem = document.createElement('div'); 97190 var style = elem.style; 97191 style.cssText = 'background-color:rgba(0,0,0,.5)'; 97192 return contains(style.backgroundColor, 'rgba') || contains(style.backgroundColor, 'hsla'); 97193 })(), 97194 replaceInput = [ 97195 "<div class='sp-replacer'>", 97196 "<div class='sp-preview'><div class='sp-preview-inner'></div></div>", 97197 "<div class='sp-dd'>▼</div>", 97198 "</div>" 97199 ].join(''), 97200 markup = (function () { 97201 97202 // IE does not support gradients with multiple stops, so we need to simulate 97203 // that for the rainbow slider with 8 divs that each have a single gradient 97204 var gradientFix = ""; 97205 if (IE) { 97206 for (var i = 1; i <= 6; i++) { 97207 gradientFix += "<div class='sp-" + i + "'></div>"; 97208 } 97209 } 97210 97211 return [ 97212 "<div class='sp-container sp-hidden'>", 97213 "<div class='sp-palette-container'>", 97214 "<div class='sp-palette sp-thumb sp-cf'></div>", 97215 "</div>", 97216 "<div class='sp-picker-container'>", 97217 "<div class='sp-top sp-cf'>", 97218 "<div class='sp-fill'></div>", 97219 "<div class='sp-top-inner'>", 97220 "<div class='sp-color'>", 97221 "<div class='sp-sat'>", 97222 "<div class='sp-val'>", 97223 "<div class='sp-dragger'></div>", 97224 "</div>", 97225 "</div>", 97226 "</div>", 97227 "<div class='sp-hue'>", 97228 "<div class='sp-slider'></div>", 97229 gradientFix, 97230 "</div>", 97231 "</div>", 97232 "<div class='sp-alpha'><div class='sp-alpha-inner'><div class='sp-alpha-handle'></div></div></div>", 97233 "</div>", 97234 "<div class='sp-input-container sp-cf'>", 97235 "<input class='sp-input' type='text' spellcheck='false' />", 97236 "</div>", 97237 "<div class='sp-initial sp-thumb sp-cf'></div>", 97238 "<div class='sp-button-container sp-cf'>", 97239 "<a class='sp-cancel' href='#'></a>", 97240 "<button class='sp-choose'></button>", 97241 "</div>", 97242 "</div>", 97243 "</div>" 97244 ].join(""); 97245 })(); 97246 97247 function paletteTemplate (p, color, className) { 97248 var html = []; 97249 for (var i = 0; i < p.length; i++) { 97250 var tiny = tinycolor(p[i]); 97251 var c = tiny.toHsl().l < 0.5 ? "sp-thumb-el sp-thumb-dark" : "sp-thumb-el sp-thumb-light"; 97252 c += (tinycolor.equals(color, p[i])) ? " sp-thumb-active" : ""; 97253 97254 var swatchStyle = rgbaSupport ? ("background-color:" + tiny.toRgbString()) : "filter:" + tiny.toFilter(); 97255 html.push('<span title="' + tiny.toRgbString() + '" data-color="' + tiny.toRgbString() + '" class="' + c + '"><span class="sp-thumb-inner" style="' + swatchStyle + ';" /></span>'); 97256 } 97257 return "<div class='sp-cf " + className + "'>" + html.join('') + "</div>"; 97258 } 97259 97260 function hideAll() { 97261 for (var i = 0; i < spectrums.length; i++) { 97262 if (spectrums[i]) { 97263 spectrums[i].hide(); 97264 } 97265 } 97266 } 97267 97268 function instanceOptions(o, callbackContext) { 97269 var opts = $.extend({}, defaultOpts, o); 97270 opts.callbacks = { 97271 'move': bind(opts.move, callbackContext), 97272 'change': bind(opts.change, callbackContext), 97273 'show': bind(opts.show, callbackContext), 97274 'hide': bind(opts.hide, callbackContext), 97275 'beforeShow': bind(opts.beforeShow, callbackContext) 97276 }; 97277 97278 return opts; 97279 } 97280 97281 function spectrum(element, o) { 97282 97283 var opts = instanceOptions(o, element), 97284 flat = opts.flat, 97285 showSelectionPalette = opts.showSelectionPalette, 97286 localStorageKey = opts.localStorageKey, 97287 theme = opts.theme, 97288 callbacks = opts.callbacks, 97289 resize = throttle(reflow, 10), 97290 visible = false, 97291 dragWidth = 0, 97292 dragHeight = 0,
vendor: 7,994 bytes, lines 97293-97507
97293 dragHelperHeight = 0, 97294 slideHeight = 0, 97295 slideWidth = 0, 97296 alphaWidth = 0, 97297 alphaSlideHelperWidth = 0, 97298 slideHelperHeight = 0, 97299 currentHue = 0, 97300 currentSaturation = 0, 97301 currentValue = 0, 97302 currentAlpha = 1, 97303 palette = opts.palette.slice(0), 97304 paletteArray = $.isArray(palette[0]) ? palette : [palette], 97305 selectionPalette = opts.selectionPalette.slice(0), 97306 maxSelectionSize = opts.maxSelectionSize, 97307 draggingClass = "sp-dragging", 97308 shiftMovementDirection = null; 97309 97310 var doc = element.ownerDocument, 97311 body = doc.body, 97312 boundElement = $(element), 97313 disabled = false, 97314 container = $(markup, doc).addClass(theme), 97315 dragger = container.find(".sp-color"), 97316 dragHelper = container.find(".sp-dragger"), 97317 slider = container.find(".sp-hue"), 97318 slideHelper = container.find(".sp-slider"), 97319 alphaSliderInner = container.find(".sp-alpha-inner"), 97320 alphaSlider = container.find(".sp-alpha"), 97321 alphaSlideHelper = container.find(".sp-alpha-handle"), 97322 textInput = container.find(".sp-input"), 97323 paletteContainer = container.find(".sp-palette"), 97324 initialColorContainer = container.find(".sp-initial"), 97325 cancelButton = container.find(".sp-cancel"), 97326 chooseButton = container.find(".sp-choose"), 97327 isInput = boundElement.is("input"), 97328 shouldReplace = isInput && !flat, 97329 replacer = (shouldReplace) ? $(replaceInput).addClass(theme).addClass(opts.className) : $([]), 97330 offsetElement = (shouldReplace) ? replacer : boundElement, 97331 previewElement = replacer.find(".sp-preview-inner"), 97332 initialColor = opts.color || (isInput && boundElement.val()), 97333 colorOnShow = false, 97334 preferredFormat = opts.preferredFormat, 97335 currentPreferredFormat = preferredFormat, 97336 clickoutFiresChange = !opts.showButtons || opts.clickoutFiresChange; 97337 97338 97339 function applyOptions() { 97340 97341 if (opts.showPaletteOnly) { 97342 opts.showPalette = true; 97343 } 97344 97345 container.toggleClass("sp-flat", flat); 97346 container.toggleClass("sp-input-disabled", !opts.showInput); 97347 container.toggleClass("sp-alpha-enabled", opts.showAlpha); 97348 container.toggleClass("sp-buttons-disabled", !opts.showButtons); 97349 container.toggleClass("sp-palette-disabled", !opts.showPalette); 97350 container.toggleClass("sp-palette-only", opts.showPaletteOnly); 97351 container.toggleClass("sp-initial-disabled", !opts.showInitial); 97352 container.addClass(opts.className); 97353 97354 reflow(); 97355 } 97356 97357 function initialize() { 97358 97359 if (IE) { 97360 container.find("*:not(input)").attr("unselectable", "on"); 97361 } 97362 97363 applyOptions(); 97364 97365 if (shouldReplace) { 97366 boundElement.after(replacer).hide(); 97367 } 97368 97369 if (flat) { 97370 boundElement.after(container).hide(); 97371 } 97372 else { 97373 97374 var appendTo = opts.appendTo === "parent" ? boundElement.parent() : $(opts.appendTo); 97375 if (appendTo.length !== 1) { 97376 appendTo = $("body"); 97377 } 97378 97379 appendTo.append(container); 97380 } 97381 97382 if (localStorageKey && window.localStorage) { 97383 97384 // Migrate old palettes over to new format. May want to remove this eventually. 97385 try { 97386 var oldPalette = window.localStorage[localStorageKey].split(",#"); 97387 if (oldPalette.length > 1) { 97388 delete window.localStorage[localStorageKey]; 97389 $.each(oldPalette, function(i, c) { 97390 addColorToSelectionPalette(c); 97391 }); 97392 } 97393 } 97394 catch(e) { } 97395 97396 try { 97397 selectionPalette = window.localStorage[localStorageKey].split(";"); 97398 } 97399 catch (e) { } 97400 } 97401 97402 offsetElement.bind("click.spectrum touchstart.spectrum", function (e) { 97403 if (!disabled) { 97404 toggle(); 97405 } 97406 97407 e.stopPropagation(); 97408 97409 if (!$(e.target).is("input")) { 97410 e.preventDefault(); 97411 } 97412 }); 97413 97414 if(boundElement.is(":disabled") || (opts.disabled === true)) { 97415 disable(); 97416 } 97417 97418 // Prevent clicks from bubbling up to document. This would cause it to be hidden. 97419 container.click(stopPropagation); 97420 97421 // Handle user typed input 97422 textInput.change(setFromTextInput); 97423 textInput.bind("paste", function () { 97424 setTimeout(setFromTextInput, 1); 97425 }); 97426 textInput.keydown(function (e) { if (e.keyCode == 13) { setFromTextInput(); } }); 97427 97428 cancelButton.text(opts.cancelText); 97429 cancelButton.bind("click.spectrum", function (e) { 97430 e.stopPropagation(); 97431 e.preventDefault(); 97432 hide("cancel"); 97433 }); 97434 97435 chooseButton.text(opts.chooseText); 97436 chooseButton.bind("click.spectrum", function (e) { 97437 e.stopPropagation(); 97438 e.preventDefault(); 97439 97440 if (isValid()) { 97441 updateOriginalInput(true); 97442 hide(); 97443 } 97444 }); 97445 97446 draggable(alphaSlider, function (dragX, dragY, e) { 97447 currentAlpha = (dragX / alphaWidth); 97448 if (e.shiftKey) { 97449 currentAlpha = Math.round(currentAlpha * 10) / 10; 97450 } 97451 97452 move(); 97453 }); 97454 97455 draggable(slider, function (dragX, dragY) { 97456 currentHue = parseFloat(dragY / slideHeight); 97457 move(); 97458 }, dragStart, dragStop); 97459 97460 draggable(dragger, function (dragX, dragY, e) { 97461 97462 // shift+drag should snap the movement to either the x or y axis. 97463 if (!e.shiftKey) { 97464 shiftMovementDirection = null; 97465 } 97466 else if (!shiftMovementDirection) { 97467 var oldDragX = currentSaturation * dragWidth; 97468 var oldDragY = dragHeight - (currentValue * dragHeight); 97469 var furtherFromX = Math.abs(dragX - oldDragX) > Math.abs(dragY - oldDragY); 97470 97471 shiftMovementDirection = furtherFromX ? "x" : "y"; 97472 } 97473 97474 var setSaturation = !shiftMovementDirection || shiftMovementDirection === "x"; 97475 var setValue = !shiftMovementDirection || shiftMovementDirection === "y"; 97476 97477 if (setSaturation) { 97478 currentSaturation = parseFloat(dragX / dragWidth); 97479 } 97480 if (setValue) { 97481 currentValue = parseFloat((dragHeight - dragY) / dragHeight); 97482 } 97483 97484 move(); 97485 97486 }, dragStart, dragStop); 97487 97488 if (!!initialColor) { 97489 set(initialColor); 97490 97491 // In case color was black - update the preview UI and set the format 97492 // since the set function will not run (default color is black). 97493 updateUI(); 97494 currentPreferredFormat = preferredFormat || tinycolor(initialColor).format; 97495 97496 addColorToSelectionPalette(initialColor); 97497 } 97498 else { 97499 updateUI(); 97500 } 97501 97502 if (flat) { 97503 show(); 97504 } 97505 97506 function palletElementClick(e) { 97507 if (e.data && e.data.ignore) {
97508 set($(this).data("color")); 97509 move(); 97510 } 97511 else { 97512 set($(this).data("color")); 97513 updateOriginalInput(true); 97514 move(); 97515 hide(); 97516 } 97517 97518 return false; 97519 } 97520 97521 var paletteEvent = IE ? "mousedown.spectrum" : "click.spectrum touchstart.spectrum"; 97522 paletteContainer.delegate(".sp-thumb-el", paletteEvent, palletElementClick); 97523 initialColorContainer.delegate(".sp-thumb-el:nth-child(1)", paletteEvent, { ignore: true }, palletElementClick); 97524 } 97525 97526 function addColorToSelectionPalette(color) { 97527 if (showSelectionPalette) { 97528 var colorRgb = tinycolor(color).toRgbString(); 97529 if ($.inArray(colorRgb, selectionPalette) === -1) { 97530 selectionPalette.push(colorRgb); 97531 while(selectionPalette.length > maxSelectionSize) { 97532 selectionPalette.shift(); 97533 } 97534 } 97535 97536 if (localStorageKey && window.localStorage) { 97537 try { 97538 window.localStorage[localStorageKey] = selectionPalette.join(";"); 97539 } 97540 catch(e) { } 97541 } 97542 } 97543 } 97544 97545 function getUniqueSelectionPalette() { 97546 var unique = []; 97547 var p = selectionPalette; 97548 var paletteLookup = {}; 97549 var rgb; 97550 97551 if (opts.showPalette) { 97552 97553 for (var i = 0; i < paletteArray.length; i++) { 97554 for (var j = 0; j < paletteArray[i].length; j++) { 97555 rgb = tinycolor(paletteArray[i][j]).toRgbString(); 97556 paletteLookup[rgb] = true; 97557 } 97558 } 97559 97560 for (i = 0; i < p.length; i++) { 97561 rgb = tinycolor(p[i]).toRgbString(); 97562 97563 if (!paletteLookup.hasOwnProperty(rgb)) { 97564 unique.push(p[i]); 97565 paletteLookup[rgb] = true; 97566 } 97567 } 97568 } 97569 97570 return unique.reverse().slice(0, opts.maxSelectionSize); 97571 } 97572 97573 function drawPalette() { 97574 97575 var currentColor = get(); 97576 97577 var html = $.map(paletteArray, function (palette, i) { 97578 return paletteTemplate(palette, currentColor, "sp-palette-row sp-palette-row-" + i); 97579 }); 97580 97581 if (selectionPalette) { 97582 html.push(paletteTemplate(getUniqueSelectionPalette(), currentColor, "sp-palette-row sp-palette-row-selection")); 97583 } 97584 97585 paletteContainer.html(html.join("")); 97586 } 97587 97588 function drawInitial() { 97589 if (opts.showInitial) { 97590 var initial = colorOnShow; 97591 var current = get(); 97592 initialColorContainer.html(paletteTemplate([initial, current], current, "sp-palette-row-initial")); 97593 } 97594 } 97595 97596 function dragStart() { 97597 if (dragHeight <= 0 || dragWidth <= 0 || slideHeight <= 0) { 97598 reflow(); 97599 } 97600 container.addClass(draggingClass); 97601 shiftMovementDirection = null; 97602 } 97603 97604 function dragStop() { 97605 container.removeClass(draggingClass); 97606 } 97607 97608 function setFromTextInput() { 97609 var tiny = tinycolor(textInput.val()); 97610 if (tiny.ok) { 97611 set(tiny); 97612 } 97613 else { 97614 textInput.addClass("sp-validation-error"); 97615 } 97616 } 97617 97618 function toggle() { 97619 if (visible) { 97620 hide(); 97621 } 97622 else { 97623 show(); 97624 } 97625 } 97626 97627 function show() { 97628 var event = $.Event('beforeShow.spectrum'); 97629 97630 if (visible) { 97631 reflow(); 97632 return; 97633 } 97634 97635 boundElement.trigger(event, [ get() ]); 97636 97637 if (callbacks.beforeShow(get()) === false || event.isDefaultPrevented()) { 97638 return; 97639 } 97640 97641 hideAll(); 97642 visible = true; 97643 97644 $(doc).bind("click.spectrum", hide); 97645 $(window).bind("resize.spectrum", resize); 97646 replacer.addClass("sp-active"); 97647 container.removeClass("sp-hidden"); 97648 97649 if (opts.showPalette) { 97650 drawPalette(); 97651 } 97652 reflow(); 97653 updateUI(); 97654 97655 colorOnShow = get(); 97656 97657 drawInitial(); 97658 callbacks.show(colorOnShow); 97659 boundElement.trigger('show.spectrum', [ colorOnShow ]); 97660 } 97661 97662 function hide(e) { 97663 97664 // Return on right click 97665 if (e && e.type == "click" && e.button == 2) { return; } 97666 97667 // Return if hiding is unnecessary 97668 if (!visible || flat) { return; } 97669 visible = false;
97670 97671 $(doc).unbind("click.spectrum", hide); 97672 $(window).unbind("resize.spectrum", resize); 97673 97674 replacer.removeClass("sp-active"); 97675 container.addClass("sp-hidden"); 97676 97677 var colorHasChanged = !tinycolor.equals(get(), colorOnShow); 97678 97679 if (colorHasChanged) { 97680 if (clickoutFiresChange && e !== "cancel") { 97681 updateOriginalInput(true); 97682 } 97683 else { 97684 revert(); 97685 } 97686 } 97687 97688 callbacks.hide(get()); 97689 boundElement.trigger('hide.spectrum', [ get() ]); 97690 } 97691 97692 function revert() { 97693 set(colorOnShow, true); 97694 } 97695 97696 function set(color, ignoreFormatChange) { 97697 if (tinycolor.equals(color, get())) { 97698 return; 97699 } 97700 97701 var newColor = tinycolor(color); 97702 var newHsv = newColor.toHsv(); 97703 97704 currentHue = (newHsv.h % 360) / 360; 97705 currentSaturation = newHsv.s; 97706 currentValue = newHsv.v; 97707 currentAlpha = newHsv.a; 97708 97709 updateUI(); 97710 97711 if (newColor.ok && !ignoreFormatChange) { 97712 currentPreferredFormat = preferredFormat || newColor.format; 97713 } 97714 } 97715 97716 function get(opts) { 97717 opts = opts || { }; 97718 return tinycolor.fromRatio({ 97719 h: currentHue, 97720 s: currentSaturation, 97721 v: currentValue, 97722 a: Math.round(currentAlpha * 100) / 100 97723 }, { format: opts.format || currentPreferredFormat }); 97724 } 97725 97726 function isValid() { 97727 return !textInput.hasClass("sp-validation-error"); 97728 } 97729 97730 function move() { 97731 updateUI(); 97732 97733 callbacks.move(get()); 97734 boundElement.trigger('move.spectrum', [ get() ]); 97735 } 97736 97737 function updateUI() { 97738 97739 textInput.removeClass("sp-validation-error"); 97740 97741 updateHelperLocations(); 97742 97743 // Update dragger background color (gradients take care of saturation and value). 97744 var flatColor = tinycolor.fromRatio({ h: currentHue, s: 1, v: 1 }); 97745 dragger.css("background-color", flatColor.toHexString()); 97746 97747 // Get a format that alpha will be included in (hex and names ignore alpha) 97748 var format = currentPreferredFormat; 97749 if (currentAlpha < 1) { 97750 if (format === "hex" || format === "hex3" || format === "hex6" || format === "name") { 97751 format = "rgb"; 97752 } 97753 } 97754 97755 var realColor = get({ format: format }), 97756 realHex = realColor.toHexString(), 97757 realRgb = realColor.toRgbString(); 97758 97759 // Update the replaced elements background color (with actual selected color) 97760 if (rgbaSupport || realColor.alpha === 1) { 97761 previewElement.css("background-color", realRgb); 97762 } 97763 else { 97764 previewElement.css("background-color", "transparent"); 97765 previewElement.css("filter", realColor.toFilter()); 97766 } 97767 97768 if (opts.showAlpha) { 97769 var rgb = realColor.toRgb(); 97770 rgb.a = 0; 97771 var realAlpha = tinycolor(rgb).toRgbString(); 97772 var gradient = "linear-gradient(left, " + realAlpha + ", " + realHex + ")"; 97773 97774 if (IE) { 97775 alphaSliderInner.css("filter", tinycolor(realAlpha).toFilter({ gradientType: 1 }, realHex)); 97776 } 97777 else { 97778 alphaSliderInner.css("background", "-webkit-" + gradient); 97779 alphaSliderInner.css("background", "-moz-" + gradient); 97780 alphaSliderInner.css("background", "-ms-" + gradient); 97781 alphaSliderInner.css("background", gradient); 97782 } 97783 } 97784 97785 97786 // Update the text entry input as it changes happen 97787 if (opts.showInput) { 97788 textInput.val(realColor.toString(format)); 97789 } 97790 97791 if (opts.showPalette) { 97792 drawPalette(); 97793 } 97794 97795 drawInitial(); 97796 } 97797 97798 function updateHelperLocations() { 97799 var s = currentSaturation; 97800 var v = currentValue; 97801 97802 // Where to show the little circle in that displays your current selected color 97803 var dragX = s * dragWidth; 97804 var dragY = dragHeight - (v * dragHeight); 97805 dragX = Math.max(
97806 -dragHelperHeight, 97807 Math.min(dragWidth - dragHelperHeight, dragX - dragHelperHeight) 97808 ); 97809 dragY = Math.max( 97810 -dragHelperHeight, 97811 Math.min(dragHeight - dragHelperHeight, dragY - dragHelperHeight) 97812 ); 97813 dragHelper.css({ 97814 "top": dragY, 97815 "left": dragX 97816 }); 97817 97818 var alphaX = currentAlpha * alphaWidth; 97819 alphaSlideHelper.css({ 97820 "left": alphaX - (alphaSlideHelperWidth / 2) 97821 }); 97822 97823 // Where to show the bar that displays your current selected hue 97824 var slideY = (currentHue) * slideHeight; 97825 slideHelper.css({ 97826 "top": slideY - slideHelperHeight 97827 }); 97828 } 97829 97830 function updateOriginalInput(fireCallback) { 97831 var color = get(); 97832 97833 if (isInput) { 97834 boundElement.val(color.toString(currentPreferredFormat)); 97835 } 97836 97837 var hasChanged = !tinycolor.equals(color, colorOnShow); 97838 colorOnShow = color; 97839 97840 // Update the selection palette with the current color 97841 addColorToSelectionPalette(color); 97842 if (fireCallback && hasChanged) { 97843 callbacks.change(color); 97844 boundElement.trigger('change', [ color ]); 97845 } 97846 } 97847 97848 function reflow() { 97849 dragWidth = dragger.width(); 97850 dragHeight = dragger.height(); 97851 dragHelperHeight = dragHelper.height(); 97852 slideWidth = slider.width(); 97853 slideHeight = slider.height(); 97854 slideHelperHeight = slideHelper.height(); 97855 alphaWidth = alphaSlider.width(); 97856 alphaSlideHelperWidth = alphaSlideHelper.width(); 97857 97858 if (!flat) { 97859 container.css("position", "absolute"); 97860 container.offset(getOffset(container, offsetElement)); 97861 } 97862 97863 updateHelperLocations(); 97864 } 97865 97866 function destroy() { 97867 boundElement.show(); 97868 offsetElement.unbind("click.spectrum touchstart.spectrum"); 97869 container.remove(); 97870 replacer.remove(); 97871 spectrums[spect.id] = null; 97872 } 97873 97874 function option(optionName, optionValue) { 97875 if (optionName === undefined) { 97876 return $.extend({}, opts); 97877 } 97878 if (optionValue === undefined) { 97879 return opts[optionName]; 97880 } 97881 97882 opts[optionName] = optionValue; 97883 applyOptions(); 97884 } 97885 97886 function enable() { 97887 disabled = false; 97888 boundElement.attr("disabled", false); 97889 offsetElement.removeClass("sp-disabled"); 97890 } 97891 97892 function disable() { 97893 hide(); 97894 disabled = true; 97895 boundElement.attr("disabled", true); 97896 offsetElement.addClass("sp-disabled"); 97897 } 97898 97899 initialize(); 97900 97901 var spect = { 97902 show: show, 97903 hide: hide, 97904 toggle: toggle, 97905 reflow: reflow, 97906 option: option, 97907 enable: enable, 97908 disable: disable, 97909 set: function (c) { 97910 set(c); 97911 updateOriginalInput(); 97912 }, 97913 get: get, 97914 destroy: destroy, 97915 container: container 97916 }; 97917 97918 spect.id = spectrums.push(spect) - 1; 97919 97920 return spect; 97921 } 97922 97923 /** 97924 * checkOffset - get the offset below/above and left/right element depending on screen position 97925 * Thanks https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.datepicker.js 97926 */ 97927 function getOffset(picker, input) { 97928 var extraY = 0; 97929 var dpWidth = picker.outerWidth(); 97930 var dpHeight = picker.outerHeight(); 97931 var inputHeight = input.outerHeight(); 97932 var doc = picker[0].ownerDocument; 97933 var docElem = doc.documentElement; 97934 var viewWidth = docElem.clientWidth + $(doc).scrollLeft(); 97935 var viewHeight = docElem.clientHeight + $(doc).scrollTop(); 97936 var offset = input.offset(); 97937 offset.top += inputHeight; 97938 97939 offset.left -= 97940 Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ? 97941 Math.abs(offset.left + dpWidth - viewWidth) : 0); 97942 97943 offset.top -= 97944 Math.min(offset.top, ((offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ? 97945 Math.abs(dpHeight + inputHeight - extraY) : extraY)); 97946 97947 return offset; 97948 } 97949 97950 /** 97951 * noop - do nothing 97952 */ 97953 function noop() { 97954 97955 } 97956 97957 /** 97958 * stopPropagation - makes the code only doing this a little easier to read in line 97959 */ 97960 function stopPropagation(e) { 97961 e.stopPropagation(); 97962 } 97963 97964 /** 97965 * Create a function bound to a given object 97966 * Thanks to underscore.js 97967 */ 97968 function bind(func, obj) { 97969 var slice = Array.prototype.slice; 97970 var args = slice.call(arguments, 2); 97971 return function () { 97972 return func.apply(obj, args.concat(slice.call(arguments))); 97973 }; 97974 } 97975 97976 /** 97977 * Lightweight drag helper. Handles containment within the element, so that 97978 * when dragging, the x is within [0,element.width] and y is within [0,element.height] 97979 */ 97980 function draggable(element, onmove, onstart, onstop) { 97981 onmove = onmove || function () { }; 97982 onstart = onstart || function () { }; 97983 onstop = onstop || function () { }; 97984 var doc = element.ownerDocument || document; 97985 var dragging = false;
vendor: 5,687 bytes, lines 97986-98164
97986 var offset = {}; 97987 var maxHeight = 0; 97988 var maxWidth = 0; 97989 var hasTouch = ('ontouchstart' in window); 97990 97991 var duringDragEvents = {}; 97992 duringDragEvents["selectstart"] = prevent; 97993 duringDragEvents["dragstart"] = prevent; 97994 duringDragEvents["touchmove mousemove"] = move; 97995 duringDragEvents["touchend mouseup"] = stop; 97996 97997 function prevent(e) { 97998 if (e.stopPropagation) { 97999 e.stopPropagation(); 98000 } 98001 if (e.preventDefault) { 98002 e.preventDefault(); 98003 } 98004 e.returnValue = false; 98005 } 98006 98007 function move(e) { 98008 if (dragging) { 98009 // Mouseup happened outside of window 98010 if (IE && document.documentMode < 9 && !e.button) { 98011 return stop(); 98012 } 98013 98014 var touches = e.originalEvent.touches; 98015 var pageX = touches ? touches[0].pageX : e.pageX; 98016 var pageY = touches ? touches[0].pageY : e.pageY; 98017 98018 var dragX = Math.max(0, Math.min(pageX - offset.left, maxWidth)); 98019 var dragY = Math.max(0, Math.min(pageY - offset.top, maxHeight)); 98020 98021 if (hasTouch) { 98022 // Stop scrolling in iOS 98023 prevent(e); 98024 } 98025 98026 onmove.apply(element, [dragX, dragY, e]); 98027 } 98028 } 98029 function start(e) { 98030 var rightclick = (e.which) ? (e.which == 3) : (e.button == 2); 98031 var touches = e.originalEvent.touches; 98032 98033 if (!rightclick && !dragging) { 98034 if (onstart.apply(element, arguments) !== false) { 98035 dragging = true; 98036 maxHeight = $(element).height(); 98037 maxWidth = $(element).width(); 98038 offset = $(element).offset(); 98039 98040 $(doc).bind(duringDragEvents); 98041 $(doc.body).addClass("sp-dragging"); 98042 98043 if (!hasTouch) { 98044 move(e); 98045 } 98046 98047 prevent(e); 98048 } 98049 } 98050 } 98051 function stop() { 98052 if (dragging) { 98053 $(doc).unbind(duringDragEvents); 98054 $(doc.body).removeClass("sp-dragging"); 98055 onstop.apply(element, arguments); 98056 } 98057 dragging = false; 98058 } 98059 98060 $(element).bind("touchstart mousedown", start); 98061 } 98062 98063 function throttle(func, wait, debounce) { 98064 var timeout; 98065 return function () { 98066 var context = this, args = arguments; 98067 var throttler = function () { 98068 timeout = null; 98069 func.apply(context, args); 98070 }; 98071 if (debounce) clearTimeout(timeout); 98072 if (debounce || !timeout) timeout = setTimeout(throttler, wait); 98073 }; 98074 } 98075 98076 98077 function log(){/* jshint -W021 */if(window.console){if(Function.prototype.bind)log=Function.prototype.bind.call(console.log,console);else log=function(){Function.prototype.apply.call(console.log,console,arguments);};log.apply(this,arguments);}} 98078 98079 /** 98080 * Define a jQuery plugin 98081 */ 98082 var dataID = "spectrum.id"; 98083 $.fn.spectrum = function (opts, extra) { 98084 98085 if (typeof opts == "string") { 98086 98087 var returnValue = this; 98088 var args = Array.prototype.slice.call( arguments, 1 ); 98089 98090 this.each(function () { 98091 var spect = spectrums[$(this).data(dataID)]; 98092 if (spect) { 98093 98094 var method = spect[opts]; 98095 if (!method) { 98096 throw new Error( "Spectrum: no such method: '" + opts + "'" ); 98097 } 98098 98099 if (opts == "get") { 98100 returnValue = spect.get(); 98101 } 98102 else if (opts == "container") { 98103 returnValue = spect.container; 98104 } 98105 else if (opts == "option") { 98106 returnValue = spect.option.apply(spect, args); 98107 } 98108 else if (opts == "destroy") { 98109 spect.destroy(); 98110 $(this).removeData(dataID); 98111 } 98112 else { 98113 method.apply(spect, args); 98114 } 98115 } 98116 }); 98117 98118 return returnValue; 98119 } 98120 98121 // Initializing a new instance of spectrum 98122 return this.spectrum("destroy").each(function () { 98123 var spect = spectrum(this, opts); 98124 $(this).data(dataID, spect.id); 98125 }); 98126 }; 98127 98128 $.fn.spectrum.load = true; 98129 $.fn.spectrum.loadOpts = {}; 98130 $.fn.spectrum.draggable = draggable; 98131 $.fn.spectrum.defaults = defaultOpts; 98132 98133 $.spectrum = { }; 98134 $.spectrum.localization = { }; 98135 $.spectrum.palettes = { }; 98136 98137 $.fn.spectrum.processNativeColorInputs = function () { 98138 var colorInput = $("<input type='color' value='!' />")[0]; 98139 var supportsColor = colorInput.type === "color" && colorInput.value != "!"; 98140 98141 if (!supportsColor) { 98142 $("input[type=color]").spectrum({ 98143 preferredFormat: "hex6" 98144 }); 98145 } 98146 }; 98147 98148 // TinyColor v0.9.16 98149 // https://github.com/bgrins/TinyColor 98150 // 2013-08-10, Brian Grinstead, MIT License 98151 98152 (function() { 98153 98154 var trimLeft = /^[\s,#]+/, 98155 trimRight = /\s+$/, 98156 tinyCounter = 0, 98157 math = Math, 98158 mathRound = math.round, 98159 mathMin = math.min, 98160 mathMax = math.max, 98161 mathRandom = math.random; 98162 98163 function tinycolor (color, opts) { 98164
98165 color = (color) ? color : ''; 98166 opts = opts || { }; 98167 98168 // If input is already a tinycolor, return itself 98169 if (typeof color == "object" && color.hasOwnProperty("_tc_id")) { 98170 return color; 98171 } 98172 98173 var rgb = inputToRGB(color); 98174 var r = rgb.r, 98175 g = rgb.g, 98176 b = rgb.b, 98177 a = rgb.a, 98178 roundA = mathRound(100*a) / 100, 98179 format = opts.format || rgb.format; 98180 98181 // Don't let the range of [0,255] come back in [0,1]. 98182 // Potentially lose a little bit of precision here, but will fix issues where 98183 // .5 gets interpreted as half of the total, instead of half of 1 98184 // If it was supposed to be 128, this was already taken care of by `inputToRgb` 98185 if (r < 1) { r = mathRound(r); } 98186 if (g < 1) { g = mathRound(g); } 98187 if (b < 1) { b = mathRound(b); } 98188 98189 return { 98190 ok: rgb.ok, 98191 format: format, 98192 _tc_id: tinyCounter++, 98193 alpha: a, 98194 getAlpha: function() { 98195 return a; 98196 }, 98197 setAlpha: function(value) { 98198 a = boundAlpha(value); 98199 roundA = mathRound(100*a) / 100; 98200 }, 98201 toHsv: function() { 98202 var hsv = rgbToHsv(r, g, b); 98203 return { h: hsv.h * 360, s: hsv.s, v: hsv.v, a: a }; 98204 }, 98205 toHsvString: function() { 98206 var hsv = rgbToHsv(r, g, b); 98207 var h = mathRound(hsv.h * 360), s = mathRound(hsv.s * 100), v = mathRound(hsv.v * 100); 98208 return (a == 1) ? 98209 "hsv(" + h + ", " + s + "%, " + v + "%)" : 98210 "hsva(" + h + ", " + s + "%, " + v + "%, "+ roundA + ")"; 98211 }, 98212 toHsl: function() { 98213 var hsl = rgbToHsl(r, g, b); 98214 return { h: hsl.h * 360, s: hsl.s, l: hsl.l, a: a }; 98215 }, 98216 toHslString: function() { 98217 var hsl = rgbToHsl(r, g, b); 98218 var h = mathRound(hsl.h * 360), s = mathRound(hsl.s * 100), l = mathRound(hsl.l * 100); 98219 return (a == 1) ? 98220 "hsl(" + h + ", " + s + "%, " + l + "%)" : 98221 "hsla(" + h + ", " + s + "%, " + l + "%, "+ roundA + ")"; 98222 }, 98223 toHex: function(allow3Char) { 98224 return rgbToHex(r, g, b, allow3Char); 98225 }, 98226 toHexString: function(allow3Char) { 98227 return '#' + rgbToHex(r, g, b, allow3Char); 98228 }, 98229 toRgb: function() { 98230 return { r: mathRound(r), g: mathRound(g), b: mathRound(b), a: a }; 98231 }, 98232 toRgbString: function() { 98233 return (a == 1) ? 98234 "rgb(" + mathRound(r) + ", " + mathRound(g) + ", " + mathRound(b) + ")" : 98235 "rgba(" + mathRound(r) + ", " + mathRound(g) + ", " + mathRound(b) + ", " + roundA + ")"; 98236 }, 98237 toPercentageRgb: function() { 98238 return { r: mathRound(bound01(r, 255) * 100) + "%", g: mathRound(bound01(g, 255) * 100) + "%", b: mathRound(bound01(b, 255) * 100) + "%", a: a }; 98239 }, 98240 toPercentageRgbString: function() { 98241 return (a == 1) ? 98242 "rgb(" + mathRound(bound01(r, 255) * 100) + "%, " + mathRound(bound01(g, 255) * 100) + "%, " + mathRound(bound01(b, 255) * 100) + "%)" : 98243 "rgba(" + mathRound(bound01(r, 255) * 100) + "%, " + mathRound(bound01(g, 255) * 100) + "%, " + mathRound(bound01(b, 255) * 100) + "%, " + roundA + ")"; 98244 }, 98245 toName: function() { 98246 if (a === 0) { 98247 return "transparent"; 98248 } 98249 98250 return hexNames[rgbToHex(r, g, b, true)] || false; 98251 }, 98252 toFilter: function(secondColor) { 98253 var hex = rgbToHex(r, g, b); 98254 var secondHex = hex; 98255 var alphaHex = Math.round(parseFloat(a) * 255).toString(16); 98256 var secondAlphaHex = alphaHex; 98257 var gradientType = opts && opts.gradientType ? "GradientType = 1, " : ""; 98258 98259 if (secondColor) { 98260 var s = tinycolor(secondColor); 98261 secondHex = s.toHex(); 98262 secondAlphaHex = Math.round(parseFloat(s.alpha) * 255).toString(16); 98263 } 98264 98265 return "progid:DXImageTransform.Microsoft.gradient("+gradientType+"startColorstr=#" + pad2(alphaHex) + hex + ",endColorstr=#" + pad2(secondAlphaHex) + secondHex + ")"; 98266 }, 98267 toString: function(format) { 98268 var formatSet = !!format; 98269 format = format || this.format; 98270 98271 var formattedString = false;
vendor: 26,266 bytes, lines 98272-99084
98272 var hasAlphaAndFormatNotSet = !formatSet && a < 1 && a > 0; 98273 var formatWithAlpha = hasAlphaAndFormatNotSet && (format === "hex" || format === "hex6" || format === "hex3" || format === "name"); 98274 98275 if (format === "rgb") { 98276 formattedString = this.toRgbString(); 98277 } 98278 if (format === "prgb") { 98279 formattedString = this.toPercentageRgbString(); 98280 } 98281 if (format === "hex" || format === "hex6") { 98282 formattedString = this.toHexString(); 98283 } 98284 if (format === "hex3") { 98285 formattedString = this.toHexString(true); 98286 } 98287 if (format === "name") { 98288 formattedString = this.toName(); 98289 } 98290 if (format === "hsl") { 98291 formattedString = this.toHslString(); 98292 } 98293 if (format === "hsv") { 98294 formattedString = this.toHsvString(); 98295 } 98296 98297 if (formatWithAlpha) { 98298 return this.toRgbString(); 98299 } 98300 98301 return formattedString || this.toHexString(); 98302 } 98303 }; 98304 } 98305 98306 // If input is an object, force 1 into "1.0" to handle ratios properly 98307 // String input requires "1.0" as input, so 1 will be treated as 1 98308 tinycolor.fromRatio = function(color, opts) { 98309 if (typeof color == "object") { 98310 var newColor = {}; 98311 for (var i in color) { 98312 if (color.hasOwnProperty(i)) { 98313 if (i === "a") { 98314 newColor[i] = color[i]; 98315 } 98316 else { 98317 newColor[i] = convertToPercentage(color[i]); 98318 } 98319 } 98320 } 98321 color = newColor; 98322 } 98323 98324 return tinycolor(color, opts); 98325 }; 98326 98327 // Given a string or object, convert that input to RGB 98328 // Possible string inputs: 98329 // 98330 // "red" 98331 // "#f00" or "f00" 98332 // "#ff0000" or "ff0000" 98333 // "rgb 255 0 0" or "rgb (255, 0, 0)" 98334 // "rgb 1.0 0 0" or "rgb (1, 0, 0)" 98335 // "rgba (255, 0, 0, 1)" or "rgba 255, 0, 0, 1" 98336 // "rgba (1.0, 0, 0, 1)" or "rgba 1.0, 0, 0, 1" 98337 // "hsl(0, 100%, 50%)" or "hsl 0 100% 50%" 98338 // "hsla(0, 100%, 50%, 1)" or "hsla 0 100% 50%, 1" 98339 // "hsv(0, 100%, 100%)" or "hsv 0 100% 100%" 98340 // 98341 function inputToRGB(color) { 98342 98343 var rgb = { r: 0, g: 0, b: 0 }; 98344 var a = 1; 98345 var ok = false; 98346 var format = false; 98347 98348 if (typeof color == "string") { 98349 color = stringInputToObject(color); 98350 } 98351 98352 if (typeof color == "object") { 98353 if (color.hasOwnProperty("r") && color.hasOwnProperty("g") && color.hasOwnProperty("b")) { 98354 rgb = rgbToRgb(color.r, color.g, color.b); 98355 ok = true; 98356 format = String(color.r).substr(-1) === "%" ? "prgb" : "rgb"; 98357 } 98358 else if (color.hasOwnProperty("h") && color.hasOwnProperty("s") && color.hasOwnProperty("v")) { 98359 color.s = convertToPercentage(color.s); 98360 color.v = convertToPercentage(color.v); 98361 rgb = hsvToRgb(color.h, color.s, color.v); 98362 ok = true; 98363 format = "hsv"; 98364 } 98365 else if (color.hasOwnProperty("h") && color.hasOwnProperty("s") && color.hasOwnProperty("l")) { 98366 color.s = convertToPercentage(color.s); 98367 color.l = convertToPercentage(color.l); 98368 rgb = hslToRgb(color.h, color.s, color.l); 98369 ok = true; 98370 format = "hsl"; 98371 } 98372 98373 if (color.hasOwnProperty("a")) { 98374 a = color.a; 98375 } 98376 } 98377 98378 a = boundAlpha(a); 98379 98380 return { 98381 ok: ok, 98382 format: color.format || format, 98383 r: mathMin(255, mathMax(rgb.r, 0)), 98384 g: mathMin(255, mathMax(rgb.g, 0)), 98385 b: mathMin(255, mathMax(rgb.b, 0)), 98386 a: a 98387 }; 98388 } 98389 98390 98391 // Conversion Functions 98392 // -------------------- 98393 98394 // `rgbToHsl`, `rgbToHsv`, `hslToRgb`, `hsvToRgb` modified from: 98395 // <http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript> 98396 98397 // `rgbToRgb` 98398 // Handle bounds / percentage checking to conform to CSS color spec 98399 // <http://www.w3.org/TR/css3-color/> 98400 // *Assumes:* r, g, b in [0, 255] or [0, 1] 98401 // *Returns:* { r, g, b } in [0, 255] 98402 function rgbToRgb(r, g, b){ 98403 return { 98404 r: bound01(r, 255) * 255, 98405 g: bound01(g, 255) * 255, 98406 b: bound01(b, 255) * 255 98407 }; 98408 } 98409 98410 // `rgbToHsl` 98411 // Converts an RGB color value to HSL. 98412 // *Assumes:* r, g, and b are contained in [0, 255] or [0, 1] 98413 // *Returns:* { h, s, l } in [0,1] 98414 function rgbToHsl(r, g, b) { 98415 98416 r = bound01(r, 255); 98417 g = bound01(g, 255); 98418 b = bound01(b, 255); 98419 98420 var max = mathMax(r, g, b), min = mathMin(r, g, b); 98421 var h, s, l = (max + min) / 2; 98422 98423 if(max == min) { 98424 h = s = 0; // achromatic 98425 } 98426 else { 98427 var d = max - min; 98428 s = l > 0.5 ? d / (2 - max - min) : d / (max + min); 98429 switch(max) { 98430 case r: h = (g - b) / d + (g < b ? 6 : 0); break; 98431 case g: h = (b - r) / d + 2; break; 98432 case b: h = (r - g) / d + 4; break; 98433 } 98434 98435 h /= 6; 98436 } 98437 98438 return { h: h, s: s, l: l }; 98439 } 98440 98441 // `hslToRgb` 98442 // Converts an HSL color value to RGB. 98443 // *Assumes:* h is contained in [0, 1] or [0, 360] and s and l are contained [0, 1] or [0, 100] 98444 // *Returns:* { r, g, b } in the set [0, 255] 98445 function hslToRgb(h, s, l) { 98446 var r, g, b; 98447 98448 h = bound01(h, 360); 98449 s = bound01(s, 100); 98450 l = bound01(l, 100); 98451 98452 function hue2rgb(p, q, t) { 98453 if(t < 0) t += 1; 98454 if(t > 1) t -= 1; 98455 if(t < 1/6) return p + (q - p) * 6 * t; 98456 if(t < 1/2) return q; 98457 if(t < 2/3) return p + (q - p) * (2/3 - t) * 6; 98458 return p; 98459 } 98460 98461 if(s === 0) { 98462 r = g = b = l; // achromatic 98463 } 98464 else { 98465 var q = l < 0.5 ? l * (1 + s) : l + s - l * s; 98466 var p = 2 * l - q; 98467 r = hue2rgb(p, q, h + 1/3); 98468 g = hue2rgb(p, q, h); 98469 b = hue2rgb(p, q, h - 1/3); 98470 } 98471 98472 return { r: r * 255, g: g * 255, b: b * 255 }; 98473 } 98474 98475 // `rgbToHsv` 98476 // Converts an RGB color value to HSV 98477 // *Assumes:* r, g, and b are contained in the set [0, 255] or [0, 1] 98478 // *Returns:* { h, s, v } in [0,1] 98479 function rgbToHsv(r, g, b) { 98480 98481 r = bound01(r, 255); 98482 g = bound01(g, 255); 98483 b = bound01(b, 255); 98484 98485 var max = mathMax(r, g, b), min = mathMin(r, g, b); 98486 var h, s, v = max; 98487 98488 var d = max - min; 98489 s = max === 0 ? 0 : d / max; 98490 98491 if(max == min) { 98492 h = 0; // achromatic 98493 } 98494 else { 98495 switch(max) { 98496 case r: h = (g - b) / d + (g < b ? 6 : 0); break; 98497 case g: h = (b - r) / d + 2; break; 98498 case b: h = (r - g) / d + 4; break; 98499 } 98500 h /= 6; 98501 } 98502 return { h: h, s: s, v: v }; 98503 } 98504 98505 // `hsvToRgb` 98506 // Converts an HSV color value to RGB. 98507 // *Assumes:* h is contained in [0, 1] or [0, 360] and s and v are contained in [0, 1] or [0, 100] 98508 // *Returns:* { r, g, b } in the set [0, 255] 98509 function hsvToRgb(h, s, v) { 98510 98511 h = bound01(h, 360) * 6; 98512 s = bound01(s, 100); 98513 v = bound01(v, 100); 98514 98515 var i = math.floor(h), 98516 f = h - i, 98517 p = v * (1 - s), 98518 q = v * (1 - f * s), 98519 t = v * (1 - (1 - f) * s), 98520 mod = i % 6, 98521 r = [v, q, p, p, t, v][mod], 98522 g = [t, v, v, q, p, p][mod], 98523 b = [p, p, t, v, v, q][mod]; 98524 98525 return { r: r * 255, g: g * 255, b: b * 255 }; 98526 } 98527 98528 // `rgbToHex` 98529 // Converts an RGB color to hex 98530 // Assumes r, g, and b are contained in the set [0, 255] 98531 // Returns a 3 or 6 character hex 98532 function rgbToHex(r, g, b, allow3Char) { 98533 98534 var hex = [ 98535 pad2(mathRound(r).toString(16)), 98536 pad2(mathRound(g).toString(16)), 98537 pad2(mathRound(b).toString(16)) 98538 ]; 98539 98540 // Return a 3 character hex if possible 98541 if (allow3Char && hex[0].charAt(0) == hex[0].charAt(1) && hex[1].charAt(0) == hex[1].charAt(1) && hex[2].charAt(0) == hex[2].charAt(1)) { 98542 return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0); 98543 } 98544 98545 return hex.join(""); 98546 } 98547 98548 // `equals` 98549 // Can be called with any tinycolor input 98550 tinycolor.equals = function (color1, color2) { 98551 if (!color1 || !color2) { return false; } 98552 return tinycolor(color1).toRgbString() == tinycolor(color2).toRgbString(); 98553 }; 98554 tinycolor.random = function() { 98555 return tinycolor.fromRatio({ 98556 r: mathRandom(), 98557 g: mathRandom(), 98558 b: mathRandom() 98559 }); 98560 }; 98561 98562 98563 // Modification Functions 98564 // ---------------------- 98565 // Thanks to less.js for some of the basics here 98566 // <https://github.com/cloudhead/less.js/blob/master/lib/less/functions.js> 98567 98568 tinycolor.desaturate = function (color, amount) { 98569 amount = (amount === 0) ? 0 : (amount || 10); 98570 var hsl = tinycolor(color).toHsl(); 98571 hsl.s -= amount / 100; 98572 hsl.s = clamp01(hsl.s); 98573 return tinycolor(hsl); 98574 }; 98575 tinycolor.saturate = function (color, amount) { 98576 amount = (amount === 0) ? 0 : (amount || 10); 98577 var hsl = tinycolor(color).toHsl(); 98578 hsl.s += amount / 100; 98579 hsl.s = clamp01(hsl.s); 98580 return tinycolor(hsl); 98581 }; 98582 tinycolor.greyscale = function(color) { 98583 return tinycolor.desaturate(color, 100); 98584 }; 98585 tinycolor.lighten = function(color, amount) { 98586 amount = (amount === 0) ? 0 : (amount || 10); 98587 var hsl = tinycolor(color).toHsl(); 98588 hsl.l += amount / 100; 98589 hsl.l = clamp01(hsl.l); 98590 return tinycolor(hsl); 98591 }; 98592 tinycolor.darken = function (color, amount) { 98593 amount = (amount === 0) ? 0 : (amount || 10); 98594 var hsl = tinycolor(color).toHsl(); 98595 hsl.l -= amount / 100; 98596 hsl.l = clamp01(hsl.l); 98597 return tinycolor(hsl); 98598 }; 98599 tinycolor.complement = function(color) { 98600 var hsl = tinycolor(color).toHsl(); 98601 hsl.h = (hsl.h + 180) % 360; 98602 return tinycolor(hsl); 98603 }; 98604 98605 98606 // Combination Functions 98607 // --------------------- 98608 // Thanks to jQuery xColor for some of the ideas behind these 98609 // <https://github.com/infusion/jQuery-xcolor/blob/master/jquery.xcolor.js> 98610 98611 tinycolor.triad = function(color) { 98612 var hsl = tinycolor(color).toHsl(); 98613 var h = hsl.h; 98614 return [ 98615 tinycolor(color), 98616 tinycolor({ h: (h + 120) % 360, s: hsl.s, l: hsl.l }), 98617 tinycolor({ h: (h + 240) % 360, s: hsl.s, l: hsl.l }) 98618 ]; 98619 }; 98620 tinycolor.tetrad = function(color) { 98621 var hsl = tinycolor(color).toHsl(); 98622 var h = hsl.h; 98623 return [ 98624 tinycolor(color), 98625 tinycolor({ h: (h + 90) % 360, s: hsl.s, l: hsl.l }), 98626 tinycolor({ h: (h + 180) % 360, s: hsl.s, l: hsl.l }), 98627 tinycolor({ h: (h + 270) % 360, s: hsl.s, l: hsl.l }) 98628 ]; 98629 }; 98630 tinycolor.splitcomplement = function(color) { 98631 var hsl = tinycolor(color).toHsl(); 98632 var h = hsl.h; 98633 return [ 98634 tinycolor(color), 98635 tinycolor({ h: (h + 72) % 360, s: hsl.s, l: hsl.l}), 98636 tinycolor({ h: (h + 216) % 360, s: hsl.s, l: hsl.l}) 98637 ]; 98638 }; 98639 tinycolor.analogous = function(color, results, slices) { 98640 results = results || 6; 98641 slices = slices || 30; 98642 98643 var hsl = tinycolor(color).toHsl(); 98644 var part = 360 / slices; 98645 var ret = [tinycolor(color)]; 98646 98647 for (hsl.h = ((hsl.h - (part * results >> 1)) + 720) % 360; --results; ) { 98648 hsl.h = (hsl.h + part) % 360; 98649 ret.push(tinycolor(hsl)); 98650 } 98651 return ret; 98652 }; 98653 tinycolor.monochromatic = function(color, results) { 98654 results = results || 6; 98655 var hsv = tinycolor(color).toHsv(); 98656 var h = hsv.h, s = hsv.s, v = hsv.v; 98657 var ret = []; 98658 var modification = 1 / results; 98659 98660 while (results--) { 98661 ret.push(tinycolor({ h: h, s: s, v: v})); 98662 v = (v + modification) % 1; 98663 } 98664 98665 return ret; 98666 }; 98667 98668 98669 // Readability Functions 98670 // --------------------- 98671 // <http://www.w3.org/TR/AERT#color-contrast> 98672 98673 // `readability` 98674 // Analyze the 2 colors and returns an object with the following properties: 98675 // `brightness`: difference in brightness between the two colors 98676 // `color`: difference in color/hue between the two colors 98677 tinycolor.readability = function(color1, color2) { 98678 var a = tinycolor(color1).toRgb(); 98679 var b = tinycolor(color2).toRgb(); 98680 var brightnessA = (a.r * 299 + a.g * 587 + a.b * 114) / 1000; 98681 var brightnessB = (b.r * 299 + b.g * 587 + b.b * 114) / 1000; 98682 var colorDiff = ( 98683 Math.max(a.r, b.r) - Math.min(a.r, b.r) + 98684 Math.max(a.g, b.g) - Math.min(a.g, b.g) + 98685 Math.max(a.b, b.b) - Math.min(a.b, b.b) 98686 ); 98687 98688 return { 98689 brightness: Math.abs(brightnessA - brightnessB), 98690 color: colorDiff 98691 }; 98692 }; 98693 98694 // `readable` 98695 // http://www.w3.org/TR/AERT#color-contrast 98696 // Ensure that foreground and background color combinations provide sufficient contrast. 98697 // *Example* 98698 // tinycolor.readable("#000", "#111") => false 98699 tinycolor.readable = function(color1, color2) { 98700 var readability = tinycolor.readability(color1, color2); 98701 return readability.brightness > 125 && readability.color > 500; 98702 }; 98703 98704 // `mostReadable` 98705 // Given a base color and a list of possible foreground or background 98706 // colors for that base, returns the most readable color. 98707 // *Example* 98708 // tinycolor.mostReadable("#123", ["#fff", "#000"]) => "#000" 98709 tinycolor.mostReadable = function(baseColor, colorList) { 98710 var bestColor = null; 98711 var bestScore = 0; 98712 var bestIsReadable = false; 98713 for (var i=0; i < colorList.length; i++) { 98714 98715 // We normalize both around the "acceptable" breaking point, 98716 // but rank brightness constrast higher than hue. 98717 98718 var readability = tinycolor.readability(baseColor, colorList[i]); 98719 var readable = readability.brightness > 125 && readability.color > 500; 98720 var score = 3 * (readability.brightness / 125) + (readability.color / 500); 98721 98722 if ((readable && ! bestIsReadable) || 98723 (readable && bestIsReadable && score > bestScore) || 98724 ((! readable) && (! bestIsReadable) && score > bestScore)) { 98725 bestIsReadable = readable; 98726 bestScore = score; 98727 bestColor = tinycolor(colorList[i]); 98728 } 98729 } 98730 return bestColor; 98731 }; 98732 98733 98734 // Big List of Colors 98735 // ------------------ 98736 // <http://www.w3.org/TR/css3-color/#svg-color> 98737 var names = tinycolor.names = { 98738 aliceblue: "f0f8ff", 98739 antiquewhite: "faebd7", 98740 aqua: "0ff", 98741 aquamarine: "7fffd4", 98742 azure: "f0ffff", 98743 beige: "f5f5dc", 98744 bisque: "ffe4c4", 98745 black: "000", 98746 blanchedalmond: "ffebcd", 98747 blue: "00f", 98748 blueviolet: "8a2be2", 98749 brown: "a52a2a", 98750 burlywood: "deb887", 98751 burntsienna: "ea7e5d", 98752 cadetblue: "5f9ea0", 98753 chartreuse: "7fff00", 98754 chocolate: "d2691e", 98755 coral: "ff7f50", 98756 cornflowerblue: "6495ed", 98757 cornsilk: "fff8dc", 98758 crimson: "dc143c", 98759 cyan: "0ff", 98760 darkblue: "00008b", 98761 darkcyan: "008b8b", 98762 darkgoldenrod: "b8860b", 98763 darkgray: "a9a9a9", 98764 darkgreen: "006400", 98765 darkgrey: "a9a9a9", 98766 darkkhaki: "bdb76b", 98767 darkmagenta: "8b008b", 98768 darkolivegreen: "556b2f", 98769 darkorange: "ff8c00", 98770 darkorchid: "9932cc", 98771 darkred: "8b0000", 98772 darksalmon: "e9967a", 98773 darkseagreen: "8fbc8f", 98774 darkslateblue: "483d8b", 98775 darkslategray: "2f4f4f", 98776 darkslategrey: "2f4f4f", 98777 darkturquoise: "00ced1", 98778 darkviolet: "9400d3", 98779 deeppink: "ff1493", 98780 deepskyblue: "00bfff", 98781 dimgray: "696969", 98782 dimgrey: "696969", 98783 dodgerblue: "1e90ff", 98784 firebrick: "b22222", 98785 floralwhite: "fffaf0", 98786 forestgreen: "228b22", 98787 fuchsia: "f0f", 98788 gainsboro: "dcdcdc", 98789 ghostwhite: "f8f8ff", 98790 gold: "ffd700", 98791 goldenrod: "daa520", 98792 gray: "808080", 98793 green: "008000", 98794 greenyellow: "adff2f", 98795 grey: "808080", 98796 honeydew: "f0fff0", 98797 hotpink: "ff69b4", 98798 indianred: "cd5c5c", 98799 indigo: "4b0082", 98800 ivory: "fffff0", 98801 khaki: "f0e68c", 98802 lavender: "e6e6fa", 98803 lavenderblush: "fff0f5", 98804 lawngreen: "7cfc00", 98805 lemonchiffon: "fffacd", 98806 lightblue: "add8e6", 98807 lightcoral: "f08080", 98808 lightcyan: "e0ffff", 98809 lightgoldenrodyellow: "fafad2", 98810 lightgray: "d3d3d3", 98811 lightgreen: "90ee90", 98812 lightgrey: "d3d3d3", 98813 lightpink: "ffb6c1", 98814 lightsalmon: "ffa07a", 98815 lightseagreen: "20b2aa", 98816 lightskyblue: "87cefa", 98817 lightslategray: "789", 98818 lightslategrey: "789", 98819 lightsteelblue: "b0c4de", 98820 lightyellow: "ffffe0", 98821 lime: "0f0", 98822 limegreen: "32cd32", 98823 linen: "faf0e6", 98824 magenta: "f0f", 98825 maroon: "800000", 98826 mediumaquamarine: "66cdaa", 98827 mediumblue: "0000cd", 98828 mediumorchid: "ba55d3", 98829 mediumpurple: "9370db", 98830 mediumseagreen: "3cb371", 98831 mediumslateblue: "7b68ee", 98832 mediumspringgreen: "00fa9a", 98833 mediumturquoise: "48d1cc", 98834 mediumvioletred: "c71585", 98835 midnightblue: "191970", 98836 mintcream: "f5fffa", 98837 mistyrose: "ffe4e1", 98838 moccasin: "ffe4b5", 98839 navajowhite: "ffdead", 98840 navy: "000080", 98841 oldlace: "fdf5e6", 98842 olive: "808000", 98843 olivedrab: "6b8e23", 98844 orange: "ffa500", 98845 orangered: "ff4500", 98846 orchid: "da70d6", 98847 palegoldenrod: "eee8aa", 98848 palegreen: "98fb98", 98849 paleturquoise: "afeeee", 98850 palevioletred: "db7093", 98851 papayawhip: "ffefd5", 98852 peachpuff: "ffdab9", 98853 peru: "cd853f", 98854 pink: "ffc0cb", 98855 plum: "dda0dd", 98856 powderblue: "b0e0e6", 98857 purple: "800080", 98858 red: "f00", 98859 rosybrown: "bc8f8f", 98860 royalblue: "4169e1", 98861 saddlebrown: "8b4513", 98862 salmon: "fa8072", 98863 sandybrown: "f4a460", 98864 seagreen: "2e8b57", 98865 seashell: "fff5ee", 98866 sienna: "a0522d", 98867 silver: "c0c0c0", 98868 skyblue: "87ceeb", 98869 slateblue: "6a5acd", 98870 slategray: "708090", 98871 slategrey: "708090", 98872 snow: "fffafa", 98873 springgreen: "00ff7f", 98874 steelblue: "4682b4", 98875 tan: "d2b48c", 98876 teal: "008080", 98877 thistle: "d8bfd8", 98878 tomato: "ff6347", 98879 turquoise: "40e0d0", 98880 violet: "ee82ee", 98881 wheat: "f5deb3", 98882 white: "fff", 98883 whitesmoke: "f5f5f5", 98884 yellow: "ff0", 98885 yellowgreen: "9acd32" 98886 }; 98887 98888 // Make it easy to access colors via `hexNames[hex]` 98889 var hexNames = tinycolor.hexNames = flip(names); 98890 98891 98892 // Utilities 98893 // --------- 98894 98895 // `{ 'name1': 'val1' }` becomes `{ 'val1': 'name1' }` 98896 function flip(o) { 98897 var flipped = { }; 98898 for (var i in o) { 98899 if (o.hasOwnProperty(i)) { 98900 flipped[o[i]] = i; 98901 } 98902 } 98903 return flipped; 98904 } 98905 98906 // Return a valid alpha value [0,1] with all invalid values being set to 1 98907 function boundAlpha(a) { 98908 a = parseFloat(a); 98909 98910 if (isNaN(a) || a < 0 || a > 1) { 98911 a = 1; 98912 } 98913 98914 return a; 98915 } 98916 98917 // Take input from [0, n] and return it as [0, 1] 98918 function bound01(n, max) { 98919 if (isOnePointZero(n)) { n = "100%"; } 98920 98921 var processPercent = isPercentage(n); 98922 n = mathMin(max, mathMax(0, parseFloat(n))); 98923 98924 // Automatically convert percentage into number 98925 if (processPercent) { 98926 n = parseInt(n * max, 10) / 100; 98927 } 98928 98929 // Handle floating point rounding errors 98930 if ((math.abs(n - max) < 0.000001)) { 98931 return 1; 98932 } 98933 98934 // Convert into [0, 1] range if it isn't already 98935 return (n % max) / parseFloat(max); 98936 } 98937 98938 // Force a number between 0 and 1 98939 function clamp01(val) { 98940 return mathMin(1, mathMax(0, val)); 98941 } 98942 98943 // Parse an integer into hex 98944 function parseHex(val) { 98945 return parseInt(val, 16); 98946 } 98947 98948 // Need to handle 1.0 as 100%, since once it is a number, there is no difference between it and 1 98949 // <http://stackoverflow.com/questions/7422072/javascript-how-to-detect-number-as-a-decimal-including-1-0> 98950 function isOnePointZero(n) { 98951 return typeof n == "string" && n.indexOf('.') != -1 && parseFloat(n) === 1; 98952 } 98953 98954 // Check to see if string passed in is a percentage 98955 function isPercentage(n) { 98956 return typeof n === "string" && n.indexOf('%') != -1; 98957 } 98958 98959 // Force a hex value to have 2 characters 98960 function pad2(c) { 98961 return c.length == 1 ? '0' + c : '' + c; 98962 } 98963 98964 // Replace a decimal with it's percentage value 98965 function convertToPercentage(n) { 98966 if (n <= 1) { 98967 n = (n * 100) + "%"; 98968 } 98969 98970 return n; 98971 } 98972 98973 var matchers = (function() { 98974 98975 // <http://www.w3.org/TR/css3-values/#integers> 98976 var CSS_INTEGER = "[-\\+]?\\d+%?"; 98977 98978 // <http://www.w3.org/TR/css3-values/#number-value> 98979 var CSS_NUMBER = "[-\\+]?\\d*\\.\\d+%?"; 98980 98981 // Allow positive/negative integer/number. Don't capture the either/or, just the entire outcome. 98982 var CSS_UNIT = "(?:" + CSS_NUMBER + ")|(?:" + CSS_INTEGER + ")"; 98983 98984 // Actual matching. 98985 // Parentheses and commas are optional, but not required. 98986 // Whitespace can take the place of commas or opening paren 98987 var PERMISSIVE_MATCH3 = "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?"; 98988 var PERMISSIVE_MATCH4 = "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?"; 98989 98990 return { 98991 rgb: new RegExp("rgb" + PERMISSIVE_MATCH3), 98992 rgba: new RegExp("rgba" + PERMISSIVE_MATCH4), 98993 hsl: new RegExp("hsl" + PERMISSIVE_MATCH3), 98994 hsla: new RegExp("hsla" + PERMISSIVE_MATCH4), 98995 hsv: new RegExp("hsv" + PERMISSIVE_MATCH3), 98996 hex3: /^([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/, 98997 hex6: /^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/ 98998 }; 98999 })(); 99000 99001 // `stringInputToObject` 99002 // Permissive string parsing. Take in a number of formats, and output an object 99003 // based on detected format. Returns `{ r, g, b }` or `{ h, s, l }` or `{ h, s, v}` 99004 function stringInputToObject(color) { 99005 99006 color = color.replace(trimLeft,'').replace(trimRight, '').toLowerCase(); 99007 var named = false; 99008 if (names[color]) { 99009 color = names[color]; 99010 named = true; 99011 } 99012 else if (color == 'transparent') { 99013 return { r: 0, g: 0, b: 0, a: 0, format: "name" }; 99014 } 99015 99016 // Try to match string input using regular expressions. 99017 // Keep most of the number bounding out of this function - don't worry about [0,1] or [0,100] or [0,360] 99018 // Just return an object and let the conversion functions handle that. 99019 // This way the result will be the same whether the tinycolor is initialized with string or object. 99020 var match; 99021 if ((match = matchers.rgb.exec(color))) { 99022 return { r: match[1], g: match[2], b: match[3] }; 99023 } 99024 if ((match = matchers.rgba.exec(color))) { 99025 return { r: match[1], g: match[2], b: match[3], a: match[4] }; 99026 } 99027 if ((match = matchers.hsl.exec(color))) { 99028 return { h: match[1], s: match[2], l: match[3] }; 99029 } 99030 if ((match = matchers.hsla.exec(color))) { 99031 return { h: match[1], s: match[2], l: match[3], a: match[4] }; 99032 } 99033 if ((match = matchers.hsv.exec(color))) { 99034 return { h: match[1], s: match[2], v: match[3] }; 99035 } 99036 if ((match = matchers.hex6.exec(color))) { 99037 return { 99038 r: parseHex(match[1]), 99039 g: parseHex(match[2]), 99040 b: parseHex(match[3]), 99041 format: named ? "name" : "hex" 99042 }; 99043 } 99044 if ((match = matchers.hex3.exec(color))) { 99045 return { 99046 r: parseHex(match[1] + '' + match[1]), 99047 g: parseHex(match[2] + '' + match[2]), 99048 b: parseHex(match[3] + '' + match[3]), 99049 format: named ? "name" : "hex" 99050 }; 99051 } 99052 99053 return false; 99054 } 99055 99056 // Expose tinycolor to window, does not need to run in non-browser context. 99057 window.tinycolor = tinycolor; 99058 99059 })(); 99060 99061 99062 $(function () { 99063 if ($.fn.spectrum.load) { 99064 $.fn.spectrum.processNativeColorInputs(); 99065 } 99066 }); 99067 99068})(window, jQuery); 99069 99070define("spectrum", ["jquery"], function(){}); 99071 99072// SweetAlert 99073// 2014 (c) - Tristan Edwards 99074// github.com/t4t5/sweetalert 99075(function(window, document) { 99076 99077 var modalClass = '.sweet-alert', 99078 overlayClass = '.sweet-overlay', 99079 alertTypes = ['error', 'warning', 'info', 'success'], 99080 defaultParams = { 99081 title: '', 99082 text: '', 99083 type: null, 99084 allowOutsideClick: false,
99085 showCancelButton: false, 99086 showConfirmButton: true, 99087 closeOnConfirm: true, 99088 closeOnCancel: true, 99089 confirmButtonText: 'OK', 99090 confirmButtonClass: 'btn-primary', 99091 cancelButtonText: 'Cancel', 99092 cancelButtonClass: 'btn-default', 99093 containerClass: '', 99094 titleClass: '', 99095 textClass: '', 99096 imageUrl: null, 99097 imageSize: null, 99098 timer: null 99099 }; 99100 99101 99102 /* 99103 * Manipulate DOM 99104 */ 99105 99106 var getModal = function() { 99107 return document.querySelector(modalClass); 99108 }, 99109 getOverlay = function() { 99110 return document.querySelector(overlayClass); 99111 }, 99112 hasClass = function(elem, className) { 99113 return new RegExp(' ' + className + ' ').test(' ' + elem.className + ' '); 99114 }, 99115 addClass = function(elem, className) { 99116 if (className && !hasClass(elem, className)) { 99117 elem.className += ' ' + className; 99118 } 99119 }, 99120 removeClass = function(elem, className) { 99121 var newClass = ' ' + elem.className.replace(/[\t\r\n]/g, ' ') + ' '; 99122 if (hasClass(elem, className)) { 99123 while (newClass.indexOf(' ' + className + ' ') >= 0) { 99124 newClass = newClass.replace(' ' + className + ' ', ' '); 99125 } 99126 elem.className = newClass.replace(/^\s+|\s+$/g, ''); 99127 } 99128 }, 99129 escapeHtml = function(str) { 99130 var div = document.createElement('div'); 99131 div.appendChild(document.createTextNode(str)); 99132 return div.innerHTML; 99133 }, 99134 _show = function(elem) { 99135 elem.style.opacity = ''; 99136 elem.style.display = 'block'; 99137 }, 99138 show = function(elems) { 99139 if (elems && !elems.length) { 99140 return _show(elems); 99141 } 99142 for (var i = 0; i < elems.length; ++i) { 99143 _show(elems[i]); 99144 } 99145 }, 99146 _hide = function(elem) { 99147 elem.style.opacity = ''; 99148 elem.style.display = 'none'; 99149 }, 99150 hide = function(elems) { 99151 if (elems && !elems.length) { 99152 return _hide(elems); 99153 } 99154 for (var i = 0; i < elems.length; ++i) { 99155 _hide(elems[i]); 99156 } 99157 }, 99158 isDescendant = function(parent, child) { 99159 var node = child.parentNode; 99160 while (node !== null) { 99161 if (node === parent) { 99162 return true; 99163 } 99164 node = node.parentNode; 99165 } 99166 return false; 99167 }, 99168 getTopMargin = function(elem) { 99169 elem.style.left = '-9999px'; 99170 elem.style.display = 'block'; 99171 99172 var height = elem.clientHeight; 99173 var padding = parseInt(getComputedStyle(elem).getPropertyValue('padding'), 10); 99174 99175 elem.style.left = ''; 99176 elem.style.display = 'none'; 99177 return ('-' + parseInt(height / 2 + padding) + 'px'); 99178 }, 99179 fadeIn = function(elem, interval) { 99180 if(+elem.style.opacity < 1) { 99181 interval = interval || 16; 99182 elem.style.opacity = 0; 99183 elem.style.display = 'block'; 99184 var last = +new Date(); 99185 var tick = function() { 99186 elem.style.opacity = +elem.style.opacity + (new Date() - last) / 100; 99187 last = +new Date(); 99188 99189 if (+elem.style.opacity < 1) { 99190 setTimeout(tick, interval); 99191 } 99192 }; 99193 tick(); 99194 } 99195 }, 99196 fadeOut = function(elem, interval) { 99197 interval = interval || 16; 99198 elem.style.opacity = 1; 99199 var last = +new Date(); 99200 var tick = function() { 99201 elem.style.opacity = +elem.style.opacity - (new Date() - last) / 100; 99202 last = +new Date(); 99203 99204 if (+elem.style.opacity > 0) { 99205 setTimeout(tick, interval); 99206 } else { 99207 elem.style.display = 'none'; 99208 } 99209 }; 99210 tick(); 99211 }, 99212 fireClick = function(node) { 99213 // Taken from http://www.nonobtrusive.com/2011/11/29/programatically-fire-crossbrowser-click-event-with-javascript/ 99214 // Then fixed for today's Chrome browser. 99215 if (MouseEvent) { 99216 // Up-to-date approach 99217 var mevt = new MouseEvent('click', { 99218 view: window, 99219 bubbles: false, 99220 cancelable: true 99221 }); 99222 node.dispatchEvent(mevt); 99223 } else if ( document.createEvent ) { 99224 // Fallback 99225 var evt = document.createEvent('MouseEvents'); 99226 evt.initEvent('click', false, false); 99227 node.dispatchEvent(evt); 99228 } else if( document.createEventObject ) { 99229 node.fireEvent('onclick') ; 99230 } else if (typeof node.onclick === 'function' ) { 99231 node.onclick(); 99232 } 99233 }, 99234 stopEventPropagation = function(e) { 99235 // In particular, make sure the space bar doesn't scroll the main window. 99236 if (typeof e.stopPropagation === 'function') { 99237 e.stopPropagation(); 99238 e.preventDefault(); 99239 } else if (window.event && window.event.hasOwnProperty('cancelBubble')) { 99240 window.event.cancelBubble = true; 99241 } 99242 }; 99243 99244 // Remember state in cases where opening and handling a modal will fiddle with it. 99245 var previousActiveElement, 99246 previousDocumentClick, 99247 previousWindowKeyDown, 99248 lastFocusedButton; 99249 99250 /* 99251 * Add modal + overlay to DOM 99252 */ 99253 99254 window.sweetAlertInitialize = function() { 99255 var sweetHTML = '<div class="sweet-overlay" tabIndex="-1"></div><div class="sweet-alert" tabIndex="-1"><div class="icon error"><span class="x-mark"><span class="line left"></span><span class="line right"></span></span></div><div class="icon warning"> <span class="body"></span> <span class="dot"></span> </div> <div class="icon info"></div> <div class="icon success"> <span class="line tip"></span> <span class="line long"></span> <div class="placeholder"></div> <div class="fix"></div> </div> <div class="icon custom"></div> <h2>Title</h2><p class="lead text-muted">Text</p><p><button class="cancel btn btn-lg" tabIndex="2">Cancel</button> <button class="confirm btn btn-lg" tabIndex="1">OK</button></p></div>', 99256 sweetWrap = document.createElement('div'); 99257 99258 sweetWrap.innerHTML = sweetHTML; 99259
99260 // For readability: check sweet-alert.html 99261 document.body.appendChild(sweetWrap); 99262 99263 // For development use only! 99264 /*jQuery.ajax({ 99265 url: '../lib/sweet-alert.html', // Change path depending on file location 99266 dataType: 'html' 99267 }) 99268 .done(function(html) { 99269 jQuery('body').append(html); 99270 });*/ 99271 } 99272 99273 /* 99274 * Global sweetAlert function 99275 */ 99276 99277 window.sweetAlert = window.swal = function() { 99278 if (arguments[0] === undefined) { 99279 window.console.error('sweetAlert expects at least 1 attribute!'); 99280 return false; 99281 } 99282 99283 var params = extend({}, defaultParams); 99284 99285 switch (typeof arguments[0]) { 99286 99287 case 'string': 99288 params.title = arguments[0]; 99289 params.text = arguments[1] || ''; 99290 params.type = arguments[2] || ''; 99291 99292 break; 99293 99294 case 'object': 99295 if (arguments[0].title === undefined) { 99296 window.console.error('Missing "title" argument!'); 99297 return false; 99298 } 99299 99300 params.title = arguments[0].title; 99301 params.text = arguments[0].text || defaultParams.text; 99302 params.type = arguments[0].type || defaultParams.type; 99303 params.allowOutsideClick = arguments[0].allowOutsideClick || defaultParams.allowOutsideClick; 99304 params.showCancelButton = arguments[0].showCancelButton !== undefined ? arguments[0].showCancelButton : defaultParams.showCancelButton; 99305 params.showConfirmButton = arguments[0].showConfirmButton !== undefined ? arguments[0].showConfirmButton : defaultParams.showConfirmButton; 99306 params.closeOnConfirm = arguments[0].closeOnConfirm !== undefined ? arguments[0].closeOnConfirm : defaultParams.closeOnConfirm; 99307 params.closeOnCancel = arguments[0].closeOnCancel !== undefined ? arguments[0].closeOnCancel : defaultParams.closeOnCancel; 99308 params.timer = arguments[0].timer || defaultParams.timer; 99309 99310 // Show "Confirm" instead of "OK" if cancel button is visible 99311 params.confirmButtonText = (defaultParams.showCancelButton) ? 'Confirm' : defaultParams.confirmButtonText; 99312 params.confirmButtonText = arguments[0].confirmButtonText || defaultParams.confirmButtonText; 99313 params.confirmButtonClass = arguments[0].confirmButtonClass || (arguments[0].type ? 'btn-' + arguments[0].type : null) || defaultParams.confirmButtonClass; 99314 params.cancelButtonText = arguments[0].cancelButtonText || defaultParams.cancelButtonText; 99315 params.cancelButtonClass = arguments[0].cancelButtonClass || defaultParams.cancelButtonClass; 99316 params.containerClass = arguments[0].containerClass || defaultParams.containerClass; 99317 params.titleClass = arguments[0].titleClass || defaultParams.titleClass; 99318 params.textClass = arguments[0].textClass || defaultParams.textClass; 99319 params.imageUrl = arguments[0].imageUrl || defaultParams.imageUrl; 99320 params.imageSize = arguments[0].imageSize || defaultParams.imageSize; 99321 params.doneFunction = arguments[1] || null; 99322 99323 break; 99324 99325 default: 99326 window.console.error('Unexpected type of argument! Expected "string" or "object", got ' + typeof arguments[0]); 99327 return false; 99328 99329 } 99330 99331 setParameters(params); 99332 fixVerticalPosition(); 99333 openModal(); 99334 99335 99336 // Modal interactions 99337 var modal = getModal(); 99338 99339 // Mouse interactions 99340 var onButtonEvent = function(e) { 99341 99342 var target = e.target || e.srcElement, 99343 targetedConfirm = (target.className.indexOf('confirm') > -1), 99344 modalIsVisible = hasClass(modal, 'visible'), 99345 doneFunctionExists = (params.doneFunction && modal.getAttribute('data-has-done-function') === 'true'); 99346 99347 switch (e.type) { 99348 case ("click"): 99349 if (targetedConfirm && doneFunctionExists && modalIsVisible) { // Clicked "confirm" 99350 99351 params.doneFunction(true); 99352 99353 if (params.closeOnConfirm) { 99354 closeModal(); 99355 } 99356 } else if (doneFunctionExists && modalIsVisible) { // Clicked "cancel" 99357 99358 // Check if callback function expects a parameter (to track cancel actions) 99359 var functionAsStr = String(params.doneFunction).replace(/\s/g, ''); 99360 var functionHandlesCancel = functionAsStr.substring(0, 9) === "function(" && functionAsStr.substring(9, 10) !== ")"; 99361 99362 if (functionHandlesCancel) { 99363 params.doneFunction(false); 99364 } 99365 99366 if (params.closeOnCancel) { 99367 closeModal(); 99368 } 99369 } else { 99370 closeModal(); 99371 } 99372 99373 break; 99374 } 99375 }; 99376 99377 var $buttons = modal.querySelectorAll('button'); 99378 for (var i = 0; i < $buttons.length; i++) { 99379 $buttons[i].onclick = onButtonEvent; 99380 } 99381 99382 // Remember the current document.onclick event. 99383 previousDocumentClick = document.onclick; 99384 document.onclick = function(e) { 99385 var target = e.target || e.srcElement; 99386 99387 var clickedOnModal = (modal === target), 99388 clickedOnModalChild = isDescendant(modal, e.target), 99389 modalIsVisible = hasClass(modal, 'visible'), 99390 outsideClickIsAllowed = modal.getAttribute('data-allow-ouside-click') === 'true'; 99391 99392 if (!clickedOnModal && !clickedOnModalChild && modalIsVisible && outsideClickIsAllowed) { 99393 closeModal(); 99394 } 99395 }; 99396 99397 99398 // Keyboard interactions 99399 var $okButton = modal.querySelector('button.confirm'), 99400 $cancelButton = modal.querySelector('button.cancel'), 99401 $modalButtons = modal.querySelectorAll('button:not([type=hidden])'); 99402 99403 99404 function handleKeyDown(e) { 99405 var keyCode = e.keyCode || e.which; 99406 99407 if ([9,13,32,27].indexOf(keyCode) === -1) { 99408 // Don't do work on keys we don't care about. 99409 return; 99410 } 99411 99412 var $targetElement = e.target || e.srcElement; 99413 99414 var btnIndex = -1; // Find the button - note, this is a nodelist, not an array.
99415 for (var i = 0; i < $modalButtons.length; i++) { 99416 if ($targetElement === $modalButtons[i]) { 99417 btnIndex = i; 99418 break; 99419 } 99420 } 99421 99422 if (keyCode === 9) { 99423 // TAB 99424 if (btnIndex === -1) { 99425 // No button focused. Jump to the confirm button. 99426 $targetElement = $okButton; 99427 } else { 99428 // Cycle to the next button 99429 if (btnIndex === $modalButtons.length - 1) { 99430 $targetElement = $modalButtons[0]; 99431 } else { 99432 $targetElement = $modalButtons[btnIndex + 1]; 99433 } 99434 } 99435 99436 stopEventPropagation(e); 99437 $targetElement.focus(); 99438 99439 } else { 99440 if (keyCode === 13 || keyCode === 32) { 99441 if (btnIndex === -1) { 99442 // ENTER/SPACE clicked outside of a button. 99443 $targetElement = $okButton; 99444 } else { 99445 // Do nothing - let the browser handle it. 99446 $targetElement = undefined; 99447 } 99448 } else if (keyCode === 27 && !($cancelButton.hidden || $cancelButton.style.display === 'none')) { 99449 // ESC to cancel only if there's a cancel button displayed (like the alert() window). 99450 $targetElement = $cancelButton; 99451 } else { 99452 // Fallback - let the browser handle it. 99453 $targetElement = undefined; 99454 } 99455 99456 if ($targetElement !== undefined) { 99457 fireClick($targetElement, e); 99458 } 99459 } 99460 } 99461 99462 previousWindowKeyDown = window.onkeydown; 99463 window.onkeydown = handleKeyDown; 99464 99465 function handleOnBlur(e) { 99466 var $targetElement = e.target || e.srcElement, 99467 $focusElement = e.relatedTarget, 99468 modalIsVisible = hasClass(modal, 'visible'); 99469 99470 if (modalIsVisible) { 99471 var btnIndex = -1; // Find the button - note, this is a nodelist, not an array. 99472 99473 if ($focusElement !== null) { 99474 // If we picked something in the DOM to focus to, let's see if it was a button. 99475 for (var i = 0; i < $modalButtons.length; i++) { 99476 if ($focusElement === $modalButtons[i]) { 99477 btnIndex = i; 99478 break; 99479 } 99480 } 99481 99482 if (btnIndex === -1) { 99483 // Something in the dom, but not a visible button. Focus back on the button. 99484 $targetElement.focus(); 99485 } 99486 } else { 99487 // Exiting the DOM (e.g. clicked in the URL bar); 99488 lastFocusedButton = $targetElement; 99489 } 99490 } 99491 } 99492 99493 $okButton.onblur = handleOnBlur; 99494 $cancelButton.onblur = handleOnBlur; 99495 99496 window.onfocus = function() { 99497 // When the user has focused away and focused back from the whole window. 99498 window.setTimeout(function() { 99499 // Put in a timeout to jump out of the event sequence. Calling focus() in the event 99500 // sequence confuses things. 99501 if (lastFocusedButton !== undefined) { 99502 lastFocusedButton.focus(); 99503 lastFocusedButton = undefined; 99504 } 99505 }, 0); 99506 }; 99507 }; 99508 99509 /** 99510 * Set default params for each popup 99511 * @param {Object} userParams 99512 */ 99513 window.swal.setDefaults = function(userParams) { 99514 if (!userParams) { 99515 throw new Error('userParams is required'); 99516 } 99517 if (typeof userParams !== 'object') { 99518 throw new Error('userParams has to be a object'); 99519 } 99520 99521 extend(defaultParams, userParams); 99522 }; 99523 99524 /** 99525 * Closes the current modal 99526 */ 99527 window.swal.close = function() { 99528 closeModal(); 99529 } 99530 99531 /* 99532 * Set type, text and actions on modal 99533 */ 99534 99535 function setParameters(params) { 99536 var modal = getModal(); 99537 99538 var $title = modal.querySelector('h2'), 99539 $text = modal.querySelector('p'), 99540 $cancelBtn = modal.querySelector('button.cancel'), 99541 $confirmBtn = modal.querySelector('button.confirm'); 99542 99543 // Title 99544 $title.innerHTML = escapeHtml(params.title).split("\n").join("<br>"); 99545 99546 // Text 99547 $text.innerHTML = escapeHtml(params.text || '').split("\n").join("<br>"); 99548 if (params.text) { 99549 show($text); 99550 } 99551 99552 // Icon 99553 hide(modal.querySelectorAll('.icon')); 99554 if (params.type) {
99555 var validType = false; 99556 for (var i = 0; i < alertTypes.length; i++) { 99557 if (params.type === alertTypes[i]) { 99558 validType = true; 99559 break; 99560 } 99561 } 99562 if (!validType) { 99563 window.console.error('Unknown alert type: ' + params.type); 99564 return false; 99565 } 99566 var $icon = modal.querySelector('.icon.' + params.type); 99567 show($icon); 99568 99569 // Animate icon 99570 switch (params.type) { 99571 case "success": 99572 addClass($icon, 'animate'); 99573 addClass($icon.querySelector('.tip'), 'animateSuccessTip'); 99574 addClass($icon.querySelector('.long'), 'animateSuccessLong'); 99575 break; 99576 case "error": 99577 addClass($icon, 'animateErrorIcon'); 99578 addClass($icon.querySelector('.x-mark'), 'animateXMark'); 99579 break; 99580 case "warning": 99581 addClass($icon, 'pulseWarning'); 99582 addClass($icon.querySelector('.body'), 'pulseWarningIns'); 99583 addClass($icon.querySelector('.dot'), 'pulseWarningIns'); 99584 break; 99585 } 99586 99587 } 99588 99589 // Custom image 99590 if (params.imageUrl) { 99591 var $customIcon = modal.querySelector('.icon.custom'); 99592 99593 $customIcon.style.backgroundImage = 'url(' + params.imageUrl + ')'; 99594 show($customIcon); 99595 99596 var _imgWidth = 80, 99597 _imgHeight = 80; 99598 99599 if (params.imageSize) { 99600 var imgWidth = params.imageSize.split('x')[0]; 99601 var imgHeight = params.imageSize.split('x')[1]; 99602 99603 if (!imgWidth || !imgHeight) { 99604 window.console.error("Parameter imageSize expects value with format WIDTHxHEIGHT, got " + params.imageSize); 99605 } else { 99606 _imgWidth = imgWidth; 99607 _imgHeight = imgHeight; 99608 99609 $customIcon.css({ 99610 'width': imgWidth + 'px', 99611 'height': imgHeight + 'px' 99612 }); 99613 } 99614 } 99615 $customIcon.setAttribute('style', $customIcon.getAttribute('style') + 'width:' + _imgWidth + 'px; height:' + _imgHeight + 'px'); 99616 } 99617 99618 // Cancel button 99619 modal.setAttribute('data-has-cancel-button', params.showCancelButton); 99620 if (params.showCancelButton) { 99621 $cancelBtn.style.display = 'inline-block'; 99622 } else { 99623 hide($cancelBtn); 99624 } 99625 99626 //Confirm button 99627 modal.setAttribute('data-has-confirm-button', params.showConfirmButton); 99628 if (params.showConfirmButton) { 99629 $confirmBtn.style.display = 'inline-block'; 99630 } else { 99631 hide($confirmBtn); 99632 } 99633 99634 99635 // Edit text on cancel and confirm buttons 99636 if (params.cancelButtonText) { 99637 $cancelBtn.innerHTML = escapeHtml(params.cancelButtonText); 99638 } 99639 if (params.confirmButtonText) { 99640 $confirmBtn.innerHTML = escapeHtml(params.confirmButtonText); 99641 } 99642 99643 // Reset confirm buttons to default class (Ugly fix) 99644 $confirmBtn.className = 'confirm btn btn-lg'; 99645 99646 // Attach selected class to the sweet alert modal 99647 addClass(modal, params.containerClass); 99648 99649 // Set confirm button to selected class 99650 addClass($confirmBtn, params.confirmButtonClass); 99651 99652 // Set cancel button to selected class 99653 addClass($cancelBtn, params.cancelButtonClass); 99654 99655 // Set title to selected class 99656 addClass($title, params.titleClass); 99657 99658 // Set text to selected class 99659 addClass($text, params.textClass); 99660 99661 // Allow outside click? 99662 modal.setAttribute('data-allow-ouside-click', params.allowOutsideClick); 99663 99664 // Done-function 99665 var hasDoneFunction = (params.doneFunction) ? true : false; 99666 modal.setAttribute('data-has-done-function', hasDoneFunction); 99667 99668 // Close timer 99669 modal.setAttribute('data-timer', params.timer); 99670 } 99671 99672 99673 /* 99674 * Set hover, active and focus-states for buttons (source: http://www.sitepoint.com/javascript-generate-lighter-darker-color) 99675 */ 99676 99677 function colorLuminance(hex, lum) { 99678 // Validate hex string 99679 hex = String(hex).replace(/[^0-9a-f]/gi, ''); 99680 if (hex.length < 6) { 99681 hex = hex[0]+hex[0]+hex[1]+hex[1]+hex[2]+hex[2]; 99682 } 99683 lum = lum || 0; 99684 99685 // Convert to decimal and change luminosity 99686 var rgb = "#", c, i; 99687 for (i = 0; i < 3; i++) { 99688 c = parseInt(hex.substr(i*2,2), 16); 99689 c = Math.round(Math.min(Math.max(0, c + (c * lum)), 255)).toString(16); 99690 rgb += ("00"+c).substr(c.length); 99691 } 99692 99693 return rgb; 99694 } 99695 99696 function extend(a, b){ 99697 for (var key in b) { 99698 if (b.hasOwnProperty(key)) { 99699 a[key] = b[key]; 99700 } 99701 } 99702 99703 return a; 99704 } 99705 99706 function hexToRgb(hex) { 99707 var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); 99708 return result ? parseInt(result[1], 16) + ', ' + parseInt(result[2], 16) + ', ' + parseInt(result[3], 16) : null; 99709 } 99710 99711 // Add box-shadow style to button (depending on its chosen bg-color) 99712 function setFocusStyle($button, bgColor) { 99713 var rgbColor = hexToRgb(bgColor); 99714 $button.style.boxShadow = '0 0 2px rgba(' + rgbColor +', 0.8), inset 0 0 0 1px rgba(0, 0, 0, 0.05)'; 99715 } 99716 99717 99718 /* 99719 * Animations 99720 */ 99721 99722 function openModal() { 99723 var modal = getModal(); 99724 fadeIn(getOverlay(), 10); 99725 show(modal); 99726 addClass(modal, 'showSweetAlert'); 99727 removeClass(modal, 'hideSweetAlert'); 99728 99729 previousActiveElement = document.activeElement; 99730 var $okButton = modal.querySelector('button.confirm'); 99731 $okButton.focus(); 99732 99733 setTimeout(function() { 99734 addClass(modal, 'visible'); 99735 }, 500); 99736 99737 var timer = modal.getAttribute('data-timer'); 99738 if (timer !== "null" && timer !== "") { 99739 setTimeout(function() { 99740 closeModal(); 99741 }, timer); 99742 } 99743 } 99744 99745 function closeModal() { 99746 var modal = getModal(); 99747 fadeOut(getOverlay(), 5); 99748 fadeOut(modal, 5); 99749 removeClass(modal, 'showSweetAlert'); 99750 addClass(modal, 'hideSweetAlert'); 99751 removeClass(modal, 'visible'); 99752 99753 99754 // Reset icon animations 99755 99756 var $successIcon = modal.querySelector('.icon.success'); 99757 removeClass($successIcon, 'animate'); 99758 removeClass($successIcon.querySelector('.tip'), 'animateSuccessTip'); 99759 removeClass($successIcon.querySelector('.long'), 'animateSuccessLong'); 99760 99761 var $errorIcon = modal.querySelector('.icon.error'); 99762 removeClass($errorIcon, 'animateErrorIcon'); 99763 removeClass($errorIcon.querySelector('.x-mark'), 'animateXMark'); 99764 99765 var $warningIcon = modal.querySelector('.icon.warning'); 99766 removeClass($warningIcon, 'pulseWarning'); 99767 removeClass($warningIcon.querySelector('.body'), 'pulseWarningIns'); 99768 removeClass($warningIcon.querySelector('.dot'), 'pulseWarningIns'); 99769 99770 99771 // Reset the page to its previous state 99772 window.onkeydown = previousWindowKeyDown; 99773 document.onclick = previousDocumentClick; 99774 if (previousActiveElement) { 99775 previousActiveElement.focus(); 99776 } 99777 lastFocusedButton = undefined; 99778 } 99779 99780 99781 /* 99782 * Set "margin-top"-property on modal based on its computed height 99783 */ 99784 99785 function fixVerticalPosition() { 99786 var modal = getModal(); 99787 modal.style.marginTop = getTopMargin(getModal()); 99788 } 99789 99790 99791 /* 99792 * If library is injected after page has loaded 99793 */ 99794 99795 (function () { 99796 if (document.readyState === "complete" || document.readyState === "interactive" && document.body) { 99797 sweetAlertInitialize(); 99798 } else { 99799 if (document.addEventListener) { 99800 document.addEventListener('DOMContentLoaded', function handler() { 99801 document.removeEventListener('DOMContentLoaded', handler, false); 99802 sweetAlertInitialize(); 99803 }, false); 99804 } else if (document.attachEvent) { 99805 document.attachEvent('onreadystatechange', function handler() { 99806 if (document.readyState === 'complete') { 99807 document.detachEvent('onreadystatechange', handler); 99808 sweetAlertInitialize(); 99809 } 99810 }); 99811 } 99812 } 99813 })(); 99814 99815})(window, document); 99816 99817define("sweetalert", (function (global) { 99818 return function () { 99819 var ret, fn; 99820 return ret || global.swal; 99821 }; 99822}(this))); 99823 99824(function(factory) { 99825 if (typeof define === 'function' && define.amd) { 99826 define('tablesorter',['jquery'], factory); 99827 } else if (typeof module === 'object' && typeof module.exports === 'object') { 99828 module.exports = factory(require('jquery')); 99829 } else { 99830 factory(jQuery); 99831 } 99832}(function($) { 99833 99834/*! TableSorter (FORK) v2.22.5 *//* 99835* Client-side table sorting with ease! 99836* @requires jQuery v1.2.6+ 99837* 99838* Copyright (c) 2007 Christian Bach 99839* fork maintained by Rob Garrison 99840* 99841* Examples and docs at: http://tablesorter.com 99842* Dual licensed under the MIT and GPL licenses: 99843* http://www.opensource.org/licenses/mit-license.php 99844* http://www.gnu.org/licenses/gpl.html 99845* 99846* @type jQuery 99847* @name tablesorter (FORK) 99848* @cat Plugins/Tablesorter 99849* @author Christian Bach - [email protected] 99850* @contributor Rob Garrison - https://github.com/Mottie/tablesorter 99851*/ 99852/*jshint browser:true, jquery:true, unused:false, expr: true */ 99853/*global console:false */ 99854;(function($){ 99855 'use strict'; 99856 $.extend({ 99857 /*jshint supernew:true */ 99858 tablesorter: new function() { 99859 99860 var ts = this; 99861 99862 ts.version = '2.22.5'; 99863 99864 ts.parsers = []; 99865 ts.widgets = []; 99866 ts.defaults = { 99867 99868 // *** appearance 99869 theme : 'default', // adds tablesorter-{theme} to the table for styling 99870 widthFixed : false, // adds colgroup to fix widths of columns 99871 showProcessing : false, // show an indeterminate timer icon in the header when the table is sorted or filtered. 99872 99873 headerTemplate : '{content}',// header layout template (HTML ok); {content} = innerHTML, {icon} = <i/> (class from cssIcon) 99874 onRenderTemplate : null, // function(index, template){ return template; }, (template is a string) 99875 onRenderHeader : null, // function(index){}, (nothing to return) 99876 99877 // *** functionality
99878 cancelSelection : true, // prevent text selection in the header 99879 tabIndex : true, // add tabindex to header for keyboard accessibility 99880 dateFormat : 'mmddyyyy', // other options: 'ddmmyyy' or 'yyyymmdd' 99881 sortMultiSortKey : 'shiftKey', // key used to select additional columns 99882 sortResetKey : 'ctrlKey', // key used to remove sorting on a column 99883 usNumberFormat : true, // false for German '1.234.567,89' or French '1 234 567,89' 99884 delayInit : false, // if false, the parsed table contents will not update until the first sort 99885 serverSideSorting: false, // if true, server-side sorting should be performed because client-side sorting will be disabled, but the ui and events will still be used. 99886 resort : true, // default setting to trigger a resort after an 'update', 'addRows', 'updateCell', etc has completed 99887 99888 // *** sort options 99889 headers : {}, // set sorter, string, empty, locked order, sortInitialOrder, filter, etc. 99890 ignoreCase : true, // ignore case while sorting 99891 sortForce : null, // column(s) first sorted; always applied 99892 sortList : [], // Initial sort order; applied initially; updated when manually sorted 99893 sortAppend : null, // column(s) sorted last; always applied 99894 sortStable : false, // when sorting two rows with exactly the same content, the original sort order is maintained 99895 99896 sortInitialOrder : 'asc', // sort direction on first click 99897 sortLocaleCompare: false, // replace equivalent character (accented characters) 99898 sortReset : false, // third click on the header will reset column to default - unsorted 99899 sortRestart : false, // restart sort to 'sortInitialOrder' when clicking on previously unsorted columns 99900 99901 emptyTo : 'bottom', // sort empty cell to bottom, top, none, zero, emptyMax, emptyMin 99902 stringTo : 'max', // sort strings in numerical column as max, min, top, bottom, zero 99903 textExtraction : 'basic', // text extraction method/function - function(node, table, cellIndex){} 99904 textAttribute : 'data-text',// data-attribute that contains alternate cell text (used in default textExtraction function) 99905 textSorter : null, // choose overall or specific column sorter function(a, b, direction, table, columnIndex) [alt: ts.sortText] 99906 numberSorter : null, // choose overall numeric sorter function(a, b, direction, maxColumnValue) 99907 99908 // *** widget options 99909 widgets: [], // method to add widgets, e.g. widgets: ['zebra'] 99910 widgetOptions : { 99911 zebra : [ 'even', 'odd' ] // zebra widget alternating row class names 99912 }, 99913 initWidgets : true, // apply widgets on tablesorter initialization 99914 widgetClass : 'widget-{name}', // table class name template to match to include a widget 99915 99916 // *** callbacks 99917 initialized : null, // function(table){}, 99918 99919 // *** extra css class names 99920 tableClass : '', 99921 cssAsc : '', 99922 cssDesc : '', 99923 cssNone : '', 99924 cssHeader : '', 99925 cssHeaderRow : '', 99926 cssProcessing : '', // processing icon applied to header during sort/filter 99927 99928 cssChildRow : 'tablesorter-childRow', // class name indiciating that a row is to be attached to the its parent 99929 cssIcon : 'tablesorter-icon', // if this class does not exist, the {icon} will not be added from the headerTemplate 99930 cssIconNone : '', // class name added to the icon when there is no column sort 99931 cssIconAsc : '', // class name added to the icon when the column has an ascending sort 99932 cssIconDesc : '', // class name added to the icon when the column has a descending sort 99933 cssInfoBlock : 'tablesorter-infoOnly', // don't sort tbody with this class name (only one class name allowed here!) 99934 cssNoSort : 'tablesorter-noSort', // class name added to element inside header;
vendor: 6,380 bytes, lines 99934-100112
99934 clicking on it won't cause a sort 99935 cssIgnoreRow : 'tablesorter-ignoreRow', // header row to ignore; cells within this row will not be added to c.$headers 99936 99937 // *** events 99938 pointerClick : 'click', 99939 pointerDown : 'mousedown', 99940 pointerUp : 'mouseup', 99941 99942 // *** selectors 99943 selectorHeaders : '> thead th, > thead td', 99944 selectorSort : 'th, td', // jQuery selector of content within selectorHeaders that is clickable to trigger a sort 99945 selectorRemove : '.remove-me', 99946 99947 // *** advanced 99948 debug : false, 99949 99950 // *** Internal variables 99951 headerList: [], 99952 empties: {}, 99953 strings: {}, 99954 parsers: [] 99955 99956 // removed: widgetZebra: { css: ['even', 'odd'] } 99957 99958 }; 99959 99960 // internal css classes - these will ALWAYS be added to 99961 // the table and MUST only contain one class name - fixes #381 99962 ts.css = { 99963 table : 'tablesorter', 99964 cssHasChild: 'tablesorter-hasChildRow', 99965 childRow : 'tablesorter-childRow', 99966 colgroup : 'tablesorter-colgroup', 99967 header : 'tablesorter-header', 99968 headerRow : 'tablesorter-headerRow', 99969 headerIn : 'tablesorter-header-inner', 99970 icon : 'tablesorter-icon', 99971 processing : 'tablesorter-processing', 99972 sortAsc : 'tablesorter-headerAsc', 99973 sortDesc : 'tablesorter-headerDesc', 99974 sortNone : 'tablesorter-headerUnSorted' 99975 }; 99976 99977 // labels applied to sortable headers for accessibility (aria) support 99978 ts.language = { 99979 sortAsc : 'Ascending sort applied, ', 99980 sortDesc : 'Descending sort applied, ', 99981 sortNone : 'No sort applied, ', 99982 nextAsc : 'activate to apply an ascending sort', 99983 nextDesc : 'activate to apply a descending sort', 99984 nextNone : 'activate to remove the sort' 99985 }; 99986 99987 // These methods can be applied on table.config instance 99988 ts.instanceMethods = {}; 99989 99990 // $.isEmptyObject from jQuery v1.4 99991 function isEmptyObject(obj) { 99992 /*jshint forin: false */ 99993 for (var name in obj) { 99994 return false; 99995 } 99996 return true; 99997 } 99998 99999 ts.getElementText = function(c, node, cellIndex) { 100000 if (!node) { return ''; } 100001 var te, 100002 t = c.textExtraction || '', 100003 // node could be a jquery object 100004 // http://jsperf.com/jquery-vs-instanceof-jquery/2 100005 $node = node.jquery ? node : $(node); 100006 if (typeof t === 'string') { 100007 // check data-attribute first when set to 'basic'; don't use node.innerText - it's really slow! 100008 // http://www.kellegous.com/j/2013/02/27/innertext-vs-textcontent/ 100009 if ( t === 'basic' && typeof ( te = $node.attr(c.textAttribute) ) !== 'undefined' ) { 100010 return $.trim( te ); 100011 } 100012 return $.trim( node.textContent || $node.text() ); 100013 } else { 100014 if (typeof t === 'function') { 100015 return $.trim( t($node[0], c.table, cellIndex) ); 100016 } else if (typeof (te = ts.getColumnData( c.table, t, cellIndex )) === 'function') { 100017 return $.trim( te($node[0], c.table, cellIndex) ); 100018 } 100019 } 100020 // fallback 100021 return $.trim( $node[0].textContent || $node.text() ); 100022 }; 100023 100024 function detectParserForColumn(c, rows, rowIndex, cellIndex) { 100025 var cur, $node, 100026 i = ts.parsers.length, 100027 node = false, 100028 nodeValue = '', 100029 keepLooking = true; 100030 while (nodeValue === '' && keepLooking) { 100031 rowIndex++; 100032 if (rows[rowIndex]) { 100033 node = rows[rowIndex].cells[cellIndex]; 100034 nodeValue = ts.getElementText(c, node, cellIndex); 100035 $node = $(node); 100036 if (c.debug) { 100037 console.log('Checking if value was empty on row ' + rowIndex + ', column: ' + cellIndex + ': "' + nodeValue + '"'); 100038 } 100039 } else { 100040 keepLooking = false; 100041 } 100042 } 100043 while (--i >= 0) { 100044 cur = ts.parsers[i]; 100045 // ignore the default text parser because it will always be true 100046 if (cur && cur.id !== 'text' && cur.is && cur.is(nodeValue, c.table, node, $node)) { 100047 return cur; 100048 } 100049 } 100050 // nothing found, return the generic parser (text) 100051 return ts.getParserById('text'); 100052 } 100053 100054 // centralized function to extract/parse cell contents 100055 ts.getParsedText = function( c, cell, colIndex, txt ) { 100056 if ( typeof txt === 'undefined' ) { 100057 txt = ts.getElementText( c, cell, colIndex ); 100058 } 100059 // if no parser, make sure to return the txt 100060 var val = '' + txt, 100061 parser = c.parsers[ colIndex ], 100062 extractor = c.extractors[ colIndex ]; 100063 if ( parser ) { 100064 // do extract before parsing, if there is one 100065 if ( extractor && typeof extractor.format === 'function' ) { 100066 txt = extractor.format( txt, c.table, cell, colIndex ); 100067 } 100068 // allow parsing if the string is empty, previously parsing would change it to zero, 100069 // in case the parser needs to extract data from the table cell attributes 100070 val = parser.id === 'no-parser' ? '' : 100071 // make sure txt is a string (extractor may have converted it) 100072 parser.format( '' + txt, c.table, cell, colIndex ); 100073 if ( c.ignoreCase && typeof val === 'string' ) { 100074 val = val.toLowerCase(); 100075 } 100076 } 100077 return val; 100078 }; 100079 100080 function buildParserCache( c, $tbodies ) { 100081 var rows, list, l, i, h, ch, np, p, e, time, tb, len, 100082 table = c.table, 100083 j = 0, 100084 debug = {}; 100085 // update table bodies in case we start with an empty table 100086 c.$tbodies = c.$table.children('tbody:not(.' + c.cssInfoBlock + ')'); 100087 tb = typeof $tbodies === 'undefined' ? c.$tbodies : $tbodies; 100088 len = tb.length; 100089 if ( len === 0) { 100090 return c.debug ? console.warn('Warning: *Empty table!* Not building a parser cache') : ''; 100091 } else if (c.debug) { 100092 time = new Date(); 100093 console[ console.group ? 'group' : 'log' ]('Detecting parsers for each column'); 100094 } 100095 list = { 100096 extractors: [], 100097 parsers: [] 100098 }; 100099 while (j < len) { 100100 rows = tb[j].rows; 100101 if (rows.length) { 100102 l = c.columns; // rows[j].cells.length; 100103 for (i = 0; i < l; i++) { 100104 h = c.$headerIndexed[i]; 100105 // get column indexed table cell 100106 ch = ts.getColumnData( table, c.headers, i ); 100107 // get column parser/extractor 100108 e = ts.getParserById( ts.getData(h, ch, 'extractor') ); 100109 p = ts.getParserById( ts.getData(h, ch, 'sorter') ); 100110 np = ts.getData(h, ch, 'parser') === 'false'; 100111 // empty cells behaviour - keeping emptyToBottom for backwards compatibility 100112 c.empties[i] = ( ts.getData(h, ch, 'empty') || c.emptyTo || (c.emptyToBottom ? 'bottom' : 'top' ) ).toLowerCase();
100113 // text strings behaviour in numerical sorts 100114 c.strings[i] = ( ts.getData(h, ch, 'string') || c.stringTo || 'max' ).toLowerCase(); 100115 if (np) { 100116 p = ts.getParserById('no-parser'); 100117 } 100118 if (!e) { 100119 // For now, maybe detect someday 100120 e = false; 100121 } 100122 if (!p) { 100123 p = detectParserForColumn(c, rows, -1, i); 100124 } 100125 if (c.debug) { 100126 debug[ '(' + i + ') ' + h.text() ] = { 100127 parser : p.id, 100128 extractor : e ? e.id : 'none', 100129 string : c.strings[i], 100130 empty : c.empties[i] 100131 }; 100132 } 100133 list.parsers[i] = p; 100134 list.extractors[i] = e; 100135 } 100136 } 100137 j += (list.parsers.length) ? len : 1; 100138 } 100139 if ( c.debug ) { 100140 if ( !isEmptyObject( debug ) ) { 100141 console[ console.table ? 'table' : 'log' ]( debug ); 100142 } else { 100143 console.warn( ' No parsers detected!' ); 100144 } 100145 console.log( 'Completed detecting parsers' + ts.benchmark( time ) ); 100146 if ( console.groupEnd ) { console.groupEnd(); } 100147 } 100148 c.parsers = list.parsers; 100149 c.extractors = list.extractors; 100150 } 100151 100152 /* utils */ 100153 function buildCache(table, $tbodies) { 100154 var cc, t, v, i, j, k, $tb, $row, cols, cacheTime, 100155 totalRows, rowData, prevRowData, colMax, 100156 c = table.config, 100157 parsers = c.parsers; 100158 // update tbody variable 100159 c.$tbodies = c.$table.children('tbody:not(.' + c.cssInfoBlock + ')'); 100160 $tb = typeof $tbodies === 'undefined' ? c.$tbodies : $tbodies, 100161 c.cache = {}; 100162 c.totalRows = 0; 100163 // if no parsers found, return - it's an empty table. 100164 if (!parsers) { 100165 return c.debug ? console.warn('Warning: *Empty table!* Not building a cache') : ''; 100166 } 100167 if (c.debug) { 100168 cacheTime = new Date(); 100169 } 100170 // processing icon 100171 if (c.showProcessing) { 100172 ts.isProcessing(table, true); 100173 } 100174 for (k = 0; k < $tb.length; k++) { 100175 colMax = []; // column max value per tbody 100176 cc = c.cache[k] = { 100177 normalized: [] // array of normalized row data; last entry contains 'rowData' above 100178 // colMax: # // added at the end 100179 }; 100180 100181 totalRows = ($tb[k] && $tb[k].rows.length) || 0; 100182 for (i = 0; i < totalRows; ++i) { 100183 rowData = { 100184 // order: original row order # 100185 // $row : jQuery Object[] 100186 child: [], // child row text (filter widget) 100187 raw: [] // original row text 100188 }; 100189 /** Add the table data to main data array */ 100190 $row = $( $tb[ k ].rows[ i ] ); 100191 cols = []; 100192 // if this is a child row, add it to the last row's children and continue to the next row 100193 // ignore child row class, if it is the first row 100194 if ( $row.hasClass( c.cssChildRow ) && i !== 0 ) { 100195 t = cc.normalized.length - 1; 100196 prevRowData = cc.normalized[ t ][ c.columns ]; 100197 prevRowData.$row = prevRowData.$row.add( $row ); 100198 // add 'hasChild' class name to parent row 100199 if ( !$row.prev().hasClass( c.cssChildRow ) ) { 100200 $row.prev().addClass( ts.css.cssHasChild ); 100201 } 100202 // save child row content (un-parsed!) 100203 v = $row.children( 'th, td' ); 100204 t = prevRowData.child.length; 100205 prevRowData.child[ t ] = []; 100206 // child row content does not account for colspans/rowspans; so indexing may be off 100207 for ( j = 0; j < c.columns; j++ ) { 100208 prevRowData.child[ t ][ j ] = ts.getParsedText( c, v[ j ], j ); 100209 } 100210 // go to the next for loop 100211 continue; 100212 } 100213 rowData.$row = $row; 100214 rowData.order = i; // add original row position to rowCache 100215 for ( j = 0; j < c.columns; ++j ) { 100216 if (typeof parsers[ j ] === 'undefined') { 100217 if ( c.debug ) { 100218 console.warn( 'No parser found for cell:', $row[ 0 ].cells[ j ], 'does it have a header?' ); 100219 } 100220 continue; 100221 } 100222 t = ts.getElementText( c, $row[ 0 ].cells[j], j ); 100223 rowData.raw.push( t ); // save original row text 100224 v = ts.getParsedText( c, $row[ 0 ].cells[ j ], j, t ); 100225 cols.push( v ); 100226 if ( ( parsers[ j ].type || '' ).toLowerCase() === 'numeric' ) { 100227 // determine column max value (ignore sign) 100228 colMax[ j ] = Math.max( Math.abs( v ) || 0, colMax[ j ] || 0 ); 100229 } 100230 } 100231 // ensure rowData is always in the same location (after the last column) 100232 cols[ c.columns ] = rowData; 100233 cc.normalized.push( cols ); 100234 } 100235 cc.colMax = colMax; 100236 // total up rows, not including child rows 100237 c.totalRows += cc.normalized.length; 100238 100239 } 100240 if ( c.showProcessing ) { 100241 ts.isProcessing( table ); // remove processing icon 100242 } 100243 if ( c.debug ) { 100244 console.log( 'Building cache for ' + totalRows + ' rows' + ts.benchmark( cacheTime ) ); 100245 } 100246 } 100247 100248 // init flag (true) used by pager plugin to prevent widget application 100249 function appendToTable(table, init) { 100250 var c = table.config, 100251 wo = c.widgetOptions, 100252 $tbodies = c.$tbodies, 100253 rows = [], 100254 cc = c.cache, 100255 n, totalRows, $bk, $tb, 100256 i, k, appendTime; 100257 // empty table - fixes #206/#346 100258 if (isEmptyObject(cc)) { 100259 // run pager appender in case the table was just emptied 100260 return c.appender ? c.appender(table, rows) : 100261 table.isUpdating ? c.$table.trigger('updateComplete', table) : ''; // Fixes #532 100262 } 100263 if (c.debug) { 100264 appendTime = new Date(); 100265 } 100266 for (k = 0; k < $tbodies.length; k++) { 100267 $bk = $tbodies.eq(k); 100268 if ($bk.length) { 100269 // get tbody 100270 $tb = ts.processTbody(table, $bk, true); 100271 n = cc[k].normalized; 100272 totalRows = n.length; 100273 for (i = 0; i < totalRows; i++) { 100274 rows.push(n[i][c.columns].$row); 100275 // removeRows used by the pager plugin; don't render if using ajax - fixes #411 100276 if (!c.appender || (c.pager && (!c.pager.removeRows || !wo.pager_removeRows) && !c.pager.ajax)) { 100277 $tb.append(n[i][c.columns].$row); 100278 } 100279 } 100280 // restore tbody 100281 ts.processTbody(table, $tb, false); 100282 } 100283 } 100284 if (c.appender) { 100285 c.appender(table, rows); 100286 } 100287 if (c.debug) { 100288 console.log( 'Rebuilt table' + ts.benchmark(appendTime) ); 100289 } 100290 // apply table widgets; but not before ajax completes 100291 if (!init && !c.appender) { ts.applyWidget(table); } 100292 if (table.isUpdating) { 100293 c.$table.trigger('updateComplete', table); 100294 } 100295 } 100296 100297 function formatSortingOrder(v) { 100298 // look for 'd' in 'desc' order; return true 100299 return (/^d/i.test(v) || v === 1); 100300 } 100301 100302 function buildHeaders(table) { 100303 var ch, $t, h, i, t, lock, time, indx, 100304 c = table.config; 100305 c.headerList = []; 100306 c.headerContent = []; 100307 if (c.debug) { 100308 time = new Date(); 100309 } 100310 // children tr in tfoot - see issue #196 & #547 100311 c.columns = ts.computeColumnIndex( c.$table.children('thead, tfoot').children('tr') ); 100312 // add icon if cssIcon option exists 100313 i = c.cssIcon ? '<i class="' + ( c.cssIcon === ts.css.icon ? ts.css.icon : c.cssIcon + ' ' + ts.css.icon ) + '"></i>' : ''; 100314 // redefine c.$headers here in case of an updateAll that replaces or adds an entire header cell - see #683 100315 c.$headers = $( $.map( $(table).find(c.selectorHeaders), function(elem, index) { 100316 $t = $(elem); 100317 // ignore cell (don't add it to c.$headers) if row has ignoreRow class 100318 if ($t.parent().hasClass(c.cssIgnoreRow)) { return; } 100319 // make sure to get header cell & not column indexed cell 100320 ch = ts.getColumnData( table, c.headers, index, true ); 100321 // save original header content 100322 c.headerContent[index] = $t.html(); 100323 // if headerTemplate is empty, don't reformat the header cell 100324 if ( c.headerTemplate !== '' && !$t.find('.' + ts.css.headerIn).length ) { 100325 // set up header template
100326 t = c.headerTemplate.replace(/\{content\}/g, $t.html()).replace(/\{icon\}/g, $t.find('.' + ts.css.icon).length ? '' : i); 100327 if (c.onRenderTemplate) { 100328 h = c.onRenderTemplate.apply( $t, [ index, t ] ); 100329 if (h && typeof h === 'string') { t = h; } // only change t if something is returned 100330 } 100331 $t.html('<div class="' + ts.css.headerIn + '">' + t + '</div>'); // faster than wrapInner 100332 } 100333 if (c.onRenderHeader) { c.onRenderHeader.apply( $t, [ index, c, c.$table ] ); } 100334 // *** remove this.column value if no conflicts found 100335 elem.column = parseInt( $t.attr('data-column'), 10); 100336 elem.order = formatSortingOrder( ts.getData( $t, ch, 'sortInitialOrder' ) || c.sortInitialOrder ) ? 100337 [ 1, 0, 2 ] : // desc, asc, unsorted 100338 [ 0, 1, 2 ]; // asc, desc, unsorted 100339 elem.count = -1; // set to -1 because clicking on the header automatically adds one 100340 elem.lockedOrder = false; 100341 lock = ts.getData($t, ch, 'lockedOrder') || false; 100342 if (typeof lock !== 'undefined' && lock !== false) { 100343 elem.order = elem.lockedOrder = formatSortingOrder(lock) ? [ 1, 1, 1 ] : [ 0, 0, 0 ]; 100344 } 100345 $t.addClass(ts.css.header + ' ' + c.cssHeader); 100346 // add cell to headerList 100347 c.headerList[index] = elem; 100348 // add to parent in case there are multiple rows 100349 $t.parent().addClass(ts.css.headerRow + ' ' + c.cssHeaderRow).attr('role', 'row'); 100350 // allow keyboard cursor to focus on element 100351 if (c.tabIndex) { $t.attr('tabindex', 0); } 100352 return elem; 100353 })); 100354 // cache headers per column 100355 c.$headerIndexed = []; 100356 for (indx = 0; indx < c.columns; indx++) { 100357 $t = c.$headers.filter('[data-column="' + indx + '"]'); 100358 // target sortable column cells, unless there are none, then use non-sortable cells 100359 // .last() added in jQuery 1.4; use .filter(':last') to maintain compatibility with jQuery v1.2.6 100360 c.$headerIndexed[indx] = $t.not('.sorter-false').length ? $t.not('.sorter-false').filter(':last') : $t.filter(':last'); 100361 } 100362 $(table).find(c.selectorHeaders).attr({ 100363 scope: 'col', 100364 role : 'columnheader' 100365 }); 100366 // enable/disable sorting 100367 updateHeader(table); 100368 if (c.debug) { 100369 console.log( 'Built headers:' + ts.benchmark( time ) ); 100370 console.log( c.$headers ); 100371 } 100372 } 100373 100374 function commonUpdate(table, resort, callback) { 100375 var c = table.config; 100376 // remove rows/elements before update 100377 c.$table.find(c.selectorRemove).remove(); 100378 // rebuild parsers 100379 buildParserCache(c); 100380 // rebuild the cache map 100381 buildCache(table); 100382 checkResort(c, resort, callback); 100383 } 100384 100385 function updateHeader(table) { 100386 var index, s, $th, col, 100387 c = table.config, 100388 len = c.$headers.length; 100389 for ( index = 0; index < len; index++ ) { 100390 $th = c.$headers.eq( index ); 100391 col = ts.getColumnData( table, c.headers, index, true ); 100392 // add 'sorter-false' class if 'parser-false' is set 100393 s = ts.getData( $th, col, 'sorter' ) === 'false' || ts.getData( $th, col, 'parser' ) === 'false'; 100394 $th[0].sortDisabled = s; 100395 $th[ s ? 'addClass' : 'removeClass' ]('sorter-false').attr('aria-disabled', '' + s); 100396 // aria-controls - requires table ID 100397 if (table.id) { 100398 if (s) { 100399 $th.removeAttr('aria-controls'); 100400 } else { 100401 $th.attr('aria-controls', table.id); 100402 } 100403 } 100404 } 100405 } 100406 100407 function setHeadersCss(table) { 100408 var f, h, i, j, $headers, $h, nextSort, txt, 100409 c = table.config, 100410 list = c.sortList, 100411 len = list.length, 100412 none = ts.css.sortNone + ' ' + c.cssNone, 100413 css = [ ts.css.sortAsc + ' ' + c.cssAsc, ts.css.sortDesc + ' ' + c.cssDesc ], 100414 cssIcon = [ c.cssIconAsc, c.cssIconDesc, c.cssIconNone ], 100415 aria = [ 'ascending', 'descending' ], 100416 // find the footer 100417 $t = $(table).find('tfoot tr').children() 100418 .add( $( c.namespace + '_extra_headers' ) ) 100419 .removeClass( css.join( ' ' ) ); 100420 // remove all header information 100421 c.$headers 100422 .removeClass(css.join(' ')) 100423 .addClass(none).attr('aria-sort', 'none') 100424 .find('.' + ts.css.icon) 100425 .removeClass(cssIcon.join(' ')) 100426 .addClass(cssIcon[2]); 100427 for (i = 0; i < len; i++) { 100428 // direction = 2 means reset! 100429 if (list[i][1] !== 2) {
100430 // multicolumn sorting updating - choose the :last in case there are nested columns 100431 f = c.$headers.not('.sorter-false').filter('[data-column="' + list[i][0] + '"]' + (len === 1 ? ':last' : '') ); 100432 if (f.length) { 100433 for (j = 0; j < f.length; j++) { 100434 if (!f[j].sortDisabled) { 100435 f.eq(j) 100436 .removeClass(none) 100437 .addClass(css[list[i][1]]) 100438 .attr('aria-sort', aria[list[i][1]]) 100439 .find('.' + ts.css.icon) 100440 .removeClass(cssIcon[2]) 100441 .addClass(cssIcon[list[i][1]]); 100442 } 100443 } 100444 // add sorted class to footer & extra headers, if they exist 100445 if ($t.length) { 100446 $t.filter('[data-column="' + list[i][0] + '"]').removeClass(none).addClass(css[list[i][1]]); 100447 } 100448 } 100449 } 100450 } 100451 // add verbose aria labels 100452 len = c.$headers.length; 100453 $headers = c.$headers.not('.sorter-false'); 100454 for ( i = 0; i < len; i++ ) { 100455 $h = $headers.eq( i ); 100456 if ( $h.length ) { 100457 h = $headers[ i ]; 100458 nextSort = h.order[ ( h.count + 1 ) % ( c.sortReset ? 3 : 2 ) ], 100459 txt = $.trim( $h.text() ) + ': ' + 100460 ts.language[ $h.hasClass( ts.css.sortAsc ) ? 'sortAsc' : $h.hasClass( ts.css.sortDesc ) ? 'sortDesc' : 'sortNone' ] + 100461 ts.language[ nextSort === 0 ? 'nextAsc' : nextSort === 1 ? 'nextDesc' : 'nextNone' ]; 100462 $h.attr( 'aria-label', txt ); 100463 } 100464 } 100465 } 100466 100467 function updateHeaderSortCount( table, list ) { 100468 var col, dir, group, header, indx, primary, temp, val, 100469 c = table.config, 100470 sortList = list || c.sortList, 100471 len = sortList.length; 100472 c.sortList = []; 100473 for (indx = 0; indx < len; indx++) { 100474 val = sortList[indx]; 100475 // ensure all sortList values are numeric - fixes #127 100476 col = parseInt(val[0], 10); 100477 // prevents error if sorton array is wrong 100478 if ( col < c.columns && c.$headerIndexed[col] ) { 100479 // make sure header exists 100480 header = c.$headerIndexed[col][0]; 100481 // o.count = o.count + 1; 100482 dir = ('' + val[1]).match(/^(1|d|s|o|n)/); 100483 dir = dir ? dir[0] : ''; 100484 // 0/(a)sc (default), 1/(d)esc, (s)ame, (o)pposite, (n)ext 100485 switch (dir) { 100486 case '1': case 'd': // descending 100487 dir = 1; 100488 break; 100489 case 's': // same direction (as primary column) 100490 // if primary sort is set to 's', make it ascending 100491 dir = primary || 0; 100492 break; 100493 case 'o': 100494 temp = header.order[(primary || 0) % (c.sortReset ? 3 : 2)]; 100495 // opposite of primary column; but resets if primary resets 100496 dir = temp === 0 ? 1 : temp === 1 ? 0 : 2; 100497 break; 100498 case 'n': 100499 header.count = header.count + 1; 100500 dir = header.order[(header.count) % (c.sortReset ? 3 : 2)]; 100501 break; 100502 default: // ascending 100503 dir = 0; 100504 break; 100505 } 100506 primary = indx === 0 ? dir : primary; 100507 group = [ col, parseInt(dir, 10) || 0 ]; 100508 c.sortList.push(group); 100509 dir = $.inArray(group[1], header.order); // fixes issue #167 100510 header.count = dir >= 0 ? dir : group[1] % (c.sortReset ? 3 : 2); 100511 } 100512 } 100513 } 100514 100515 function getCachedSortType(parsers, i) { 100516 return (parsers && parsers[i]) ? parsers[i].type || '' : ''; 100517 } 100518 100519 function initSort(table, cell, event){ 100520 if (table.isUpdating) { 100521 // let any updates complete before initializing a sort 100522 return setTimeout(function(){ initSort(table, cell, event); }, 50); 100523 } 100524 var arry, indx, i, col, order, s, $header, 100525 c = table.config, 100526 key = !event[c.sortMultiSortKey], 100527 $table = c.$table, 100528 len = c.$headers.length; 100529 // Only call sortStart if sorting is enabled 100530 $table.trigger('sortStart', table); 100531 // get current column sort order 100532 cell.count = event[c.sortResetKey] ? 2 : (cell.count + 1) % (c.sortReset ? 3 : 2); 100533 // reset all sorts on non-current column - issue #30 100534 if (c.sortRestart) { 100535 indx = cell; 100536 for ( i = 0; i < len; i++ ) { 100537 $header = c.$headers.eq( i ); 100538 // only reset counts on columns that weren't just clicked on and if not included in a multisort 100539 if ( $header[0] !== indx && ( key || !$header.is('.' + ts.css.sortDe
100539sc + ',.' + ts.css.sortAsc) ) ) { 100540 $header[0].count = -1; 100541 } 100542 } 100543 } 100544 // get current column index 100545 indx = parseInt( $(cell).attr('data-column'), 10 ); 100546 // user only wants to sort on one column 100547 if (key) { 100548 // flush the sort list 100549 c.sortList = []; 100550 if (c.sortForce !== null) { 100551 arry = c.sortForce; 100552 for (col = 0; col < arry.length; col++) { 100553 if (arry[col][0] !== indx) { 100554 c.sortList.push(arry[col]); 100555 } 100556 } 100557 } 100558 // add column to sort list 100559 order = cell.order[cell.count]; 100560 if (order < 2) { 100561 c.sortList.push([ indx, order ]); 100562 // add other columns if header spans across multiple 100563 if (cell.colSpan > 1) { 100564 for (col = 1; col < cell.colSpan; col++) { 100565 c.sortList.push([ indx + col, order ]); 100566 } 100567 } 100568 } 100569 // multi column sorting 100570 } else { 100571 // get rid of the sortAppend before adding more - fixes issue #115 & #523 100572 if (c.sortAppend && c.sortList.length > 1) { 100573 for (col = 0; col < c.sortAppend.length; col++) { 100574 s = ts.isValueInArray(c.sortAppend[col][0], c.sortList); 100575 if (s >= 0) { 100576 c.sortList.splice(s, 1); 100577 } 100578 } 100579 } 100580 // the user has clicked on an already sorted column 100581 if (ts.isValueInArray(indx, c.sortList) >= 0) { 100582 // reverse the sorting direction 100583 for (col = 0; col < c.sortList.length; col++) { 100584 s = c.sortList[col]; 100585 order = c.$headerIndexed[ s[0] ][0]; 100586 if (s[0] === indx) { 100587 // order.count seems to be incorrect when compared to cell.count 100588 s[1] = order.order[cell.count]; 100589 if (s[1] === 2) { 100590 c.sortList.splice(col, 1); 100591 order.count = -1; 100592 } 100593 } 100594 } 100595 } else { 100596 // add column to sort list array 100597 order = cell.order[cell.count]; 100598 if (order < 2) { 100599 c.sortList.push([ indx, order ]); 100600 // add other columns if header spans across multiple 100601 if (cell.colSpan > 1) { 100602 for (col = 1; col < cell.colSpan; col++) { 100603 c.sortList.push([ indx + col, order ]); 100604 } 100605 } 100606 } 100607 } 100608 } 100609 if (c.sortAppend !== null) { 100610 arry = c.sortAppend; 100611 for (col = 0; col < arry.length; col++) { 100612 if (arry[col][0] !== indx) { 100613 c.sortList.push(arry[col]); 100614 } 100615 } 100616 } 100617 // sortBegin event triggered immediately before the sort 100618 $table.trigger('sortBegin', table); 100619 // setTimeout needed so the processing icon shows up 100620 setTimeout(function(){ 100621 // set css for headers 100622 setHeadersCss(table); 100623 multisort(table); 100624 appendToTable(table); 100625 $table.trigger('sortEnd', table); 100626 }, 1); 100627 } 100628 100629 // sort multiple columns 100630 function multisort(table) { /*jshint loopfunc:true */ 100631 var i, k, num, col, sortTime, colMax, 100632 rows, order, sort, x, y, 100633 dir = 0, 100634 c = table.config, 100635 cts = c.textSorter || '', 100636 sortList = c.sortList, 100637 l = sortList.length, 100638 bl = c.$tbodies.length; 100639 if (c.serverSideSorting || isEmptyObject(c.cache)) { // empty table - fixes #206/#346 100640 return; 100641 } 100642 if (c.debug) { sortTime = new Date(); } 100643 for (k = 0; k < bl; k++) { 100644 colMax = c.cache[k].colMax; 100645 rows = c.cache[k].normalized; 100646 100647 rows.sort(function(a, b) { 100648 // rows is undefined here in IE, so don't use it! 100649 for (i = 0; i < l; i++) { 100650 col = sortList[i][0]; 100651 order = sortList[i][1]; 100652 // sort direction, true = asc, false = desc 100653 dir = order === 0; 100654 100655 if (c.sortStable && a[col] === b[col] && l === 1) { 100656 return a[c.columns].order - b[c.columns].order; 100657 } 100658 100659 // fallback to natural sort since it is more robust 100660 num = /n/i.test(getCachedSortType(c.parsers, col)); 100661 if (num && c.strings[col]) { 100662 // sort strings in numerical columns 100663 if (typeof (c.string[c.strings[col]]) === 'boolean') { 100664 num = (dir ? 1 : -1) * (c.string[c.strings[col]] ? -1 : 1); 100665 } else { 100666 num = (c.strings[col]) ? c.string[c.strings[col]] || 0 : 0; 100667 } 100668 // fall back to built-in numeric sort 100669 // var sort = $.tablesorter['sort' + s]( a[c], b[c], dir, colMax[c], table); 100670 sort = c.numberSorter ? c.numberSorter(a[col], b[col], dir, colMax[col], table) : 100671 ts[ 'sortNumeric' + (dir ? 'Asc' : 'Desc') ](a[col], b[col], num, colMax[col], col, table); 100672 } else { 100673 // set a & b depending on sort direction 100674 x = dir ? a : b; 100675 y = dir ? b : a; 100676 // text sort function 100677 if (typeof cts === 'function') { 100678 // custom OVERALL text sorter 100679 sort = cts(x[col], y[col], dir, col, table); 100680 } else if (typeof cts === 'object' && cts.hasOwnProperty(col)) { 100681 // custom text sorter for a SPECIFIC COLUMN 100682 sort = cts[col](x[col], y[col], dir, col, table); 100683 } else { 100684 // fall back to natural sort 100685 sort = ts[ 'sortNatural' + (dir ? 'Asc' : 'Desc') ](a[col], b[col], col, table, c); 100686 } 100687 } 100688 if (sort) { return sort; } 100689 } 100690 return a[c.columns].order - b[c.columns].order;
100691 }); 100692 } 100693 if (c.debug) { 100694 console.log( 'Sorting on ' + sortList.toString() + ' and dir ' + order + ' time' + ts.benchmark(sortTime) ); 100695 } 100696 } 100697 100698 function resortComplete(c, callback){ 100699 if (c.table.isUpdating) { 100700 c.$table.trigger('updateComplete', c.table); 100701 } 100702 if ($.isFunction(callback)) { 100703 callback(c.table); 100704 } 100705 } 100706 100707 function checkResort(c, resort, callback) { 100708 var sl = $.isArray(resort) ? resort : c.sortList, 100709 // if no resort parameter is passed, fallback to config.resort (true by default) 100710 resrt = typeof resort === 'undefined' ? c.resort : resort; 100711 // don't try to resort if the table is still processing 100712 // this will catch spamming of the updateCell method 100713 if (resrt !== false && !c.serverSideSorting && !c.table.isProcessing) { 100714 if (sl.length) { 100715 c.$table.trigger('sorton', [ sl, function(){ 100716 resortComplete(c, callback); 100717 }, true ]); 100718 } else { 100719 c.$table.trigger('sortReset', [ function(){ 100720 resortComplete(c, callback); 100721 ts.applyWidget(c.table, false); 100722 } ]); 100723 } 100724 } else { 100725 resortComplete(c, callback); 100726 ts.applyWidget(c.table, false); 100727 } 100728 } 100729 100730 function bindMethods(table){ 100731 var c = table.config, 100732 $table = c.$table, 100733 events = ('sortReset update updateRows updateCell updateAll addRows updateComplete sorton appendCache ' + 100734 'updateCache applyWidgetId applyWidgets refreshWidgets destroy mouseup mouseleave ').split(' ') 100735 .join(c.namespace + ' '); 100736 // apply easy methods that trigger bound events 100737 $table 100738 .unbind( events.replace(/\s+/g, ' ') ) 100739 .bind('sortReset' + c.namespace, function(e, callback){ 100740 e.stopPropagation(); 100741 c.sortList = []; 100742 setHeadersCss(table); 100743 multisort(table); 100744 appendToTable(table); 100745 if ($.isFunction(callback)) { 100746 callback(table); 100747 } 100748 }) 100749 .bind('updateAll' + c.namespace, function(e, resort, callback){ 100750 e.stopPropagation(); 100751 table.isUpdating = true; 100752 ts.refreshWidgets(table, true, true); 100753 buildHeaders(table); 100754 ts.bindEvents(table, c.$headers, true); 100755 bindMethods(table); 100756 commonUpdate(table, resort, callback); 100757 }) 100758 .bind('update' + c.namespace + ' updateRows' + c.namespace, function(e, resort, callback) { 100759 e.stopPropagation(); 100760 table.isUpdating = true; 100761 // update sorting (if enabled/disabled) 100762 updateHeader(table); 100763 commonUpdate(table, resort, callback); 100764 }) 100765 .bind('updateCell' + c.namespace, function(e, cell, resort, callback) { 100766 e.stopPropagation(); 100767 table.isUpdating = true; 100768 $table.find(c.selectorRemove).remove(); 100769 // get position from the dom 100770 var t, row, icell, cache, 100771 $tb = c.$tbodies, 100772 $cell = $(cell), 100773 // update cache - format: function(s, table, cell, cellIndex) 100774 // no closest in jQuery v1.2.6 - tbdy = $tb.index( $(cell).closest('tbody') ),$row = $(cell).closest('tr'); 100775 tbdy = $tb.index( $.fn.closest ? $cell.closest('tbody') : $cell.parents('tbody').filter(':first') ), 100776 tbcache = c.cache[ tbdy ], 100777 $row = $.fn.closest ? $cell.closest('tr') : $cell.parents('tr').filter(':first'); 100778 cell = $cell[0]; // in case cell is a jQuery object 100779 // tbody may not exist if update is initialized while tbody is removed for processing 100780 if ($tb.length && tbdy >= 0) { 100781 row = $tb.eq( tbdy ).find( 'tr' ).index( $row ); 100782 cache = tbcache.normalized[ row ]; 100783 icell = $cell.index(); 100784 t = ts.getParsedText( c, cell, icell ); 100785 cache[ icell ] = t; 100786 cache[ c.columns ].$row = $row; 100787 if ( (c.parsers[icell].type || '').toLowerCase() === 'numeric' ) { 100788 // update column max value (ignore sign) 100789 tbcache.colMax[icell] = Math.max(Math.abs(t) || 0, tbcache.colMax[icell] || 0); 100790 } 100791 t = resort !== 'undefined' ? resort : c.resort; 100792 if (t !== false) { 100793 // widgets will be reapplied 100794 checkResort(c, t, callback); 100795 } else { 100796 // don't reapply widgets is resort is false, just in case it causes 100797 // problems with element focus 100798 if ($.isFunction(callback)) { 100799 callback(table); 100800 } 100801 c.$table.trigger('updateComplete', c.table); 100802 } 100803 } 100804 }) 100805 .bind('addRows' + c.namespace, function(e, $row, resort, callback) { 100806 e.stopPropagation(); 100807 table.isUpdating = true; 100808 if (isEmptyObject(c.cache)) { 100809 // empty table, do an update instead - fixes #450 100810 updateHeader(table); 100811 commonUpdate(table, resort, callback); 100812 } else { 100813 $row = $($row).attr('role', 'row'); // make sure we're using a jQuery object 100814 var i, j, l, rowData, cells, 100815 rows = $row.filter('tr').length, 100816 tbdy = c.$tbodies.index( $row.parents('tbody').filter(':first') ); 100817 // fixes adding rows to an empty table - see issue #179 100818 if (!(c.parsers && c.parsers.length)) { 100819 buildParserCache(c); 100820 } 100821 // add each row 100822 for (i = 0; i < rows; i++) { 100823 l = $row[i].cells.length; 100824 cells = []; 100825 rowData = { 100826 child: [], 100827 $row : $row.eq(i), 100828 order: c.cache[tbdy].normalized.length 100829 }; 100830 // add each cell 100831 for (j = 0; j < l; j++) { 100832 cells[j] = ts.getParsedText( c, $row[i].cells[j], j ); 100833 if ((c.parsers[j].type || '').toLowerCase() === 'numeric') { 100834 // update column max value (ignore sign) 100835 c.cache[tbdy].colMax[j] = Math.max(Math.abs(cells[j]) || 0, c.cache[tbdy].colMax[j] || 0); 100836 } 100837 } 100838 // add the row data to the end 100839 cells.push(rowData); 100840 // update cache 100841 c.cache[tbdy].normalized.push(cells); 100842 } 100843 // resort using current settings 100844 checkResort(c, resort, callback); 100845 } 100846 }) 100847 .bind('updateComplete' + c.namespace, function(){ 100848 table.isUpdating = false;
100849 }) 100850 .bind('sorton' + c.namespace, function(e, list, callback, init) { 100851 var c = table.config; 100852 e.stopPropagation(); 100853 $table.trigger('sortStart', this); 100854 // update header count index 100855 updateHeaderSortCount(table, list); 100856 // set css for headers 100857 setHeadersCss(table); 100858 // fixes #346 100859 if (c.delayInit && isEmptyObject(c.cache)) { buildCache(table); } 100860 $table.trigger('sortBegin', this); 100861 // sort the table and append it to the dom 100862 multisort(table); 100863 appendToTable(table, init); 100864 $table.trigger('sortEnd', this); 100865 ts.applyWidget(table); 100866 if ($.isFunction(callback)) { 100867 callback(table); 100868 } 100869 }) 100870 .bind('appendCache' + c.namespace, function(e, callback, init) { 100871 e.stopPropagation(); 100872 appendToTable(table, init); 100873 if ($.isFunction(callback)) { 100874 callback(table); 100875 } 100876 }) 100877 // $tbodies variable is used by the tbody sorting widget 100878 .bind('updateCache' + c.namespace, function(e, callback, $tbodies){ 100879 // rebuild parsers 100880 if (!(c.parsers && c.parsers.length)) { 100881 buildParserCache(c, $tbodies); 100882 } 100883 // rebuild the cache map 100884 buildCache(table, $tbodies); 100885 if ($.isFunction(callback)) { 100886 callback(table); 100887 } 100888 }) 100889 .bind('applyWidgetId' + c.namespace, function(e, id) { 100890 e.stopPropagation(); 100891 ts.getWidgetById(id).format(table, c, c.widgetOptions); 100892 }) 100893 .bind('applyWidgets' + c.namespace, function(e, init) { 100894 e.stopPropagation(); 100895 // apply widgets 100896 ts.applyWidget(table, init); 100897 }) 100898 .bind('refreshWidgets' + c.namespace, function(e, all, dontapply){ 100899 e.stopPropagation(); 100900 ts.refreshWidgets(table, all, dontapply); 100901 }) 100902 .bind('destroy' + c.namespace, function(e, c, cb){ 100903 e.stopPropagation(); 100904 ts.destroy(table, c, cb); 100905 }) 100906 .bind('resetToLoadState' + c.namespace, function(){ 100907 // remove all widgets 100908 ts.removeWidget(table, true, false); 100909 // restore original settings; this clears out current settings, but does not clear 100910 // values saved to storage. 100911 c = $.extend(true, ts.defaults, c.originalSettings); 100912 table.hasInitialized = false; 100913 // setup the entire table again 100914 ts.setup( table, c ); 100915 }); 100916 } 100917 100918 /* public methods */ 100919 ts.construct = function(settings) { 100920 return this.each(function() { 100921 var table = this, 100922 // merge & extend config options 100923 c = $.extend(true, {}, ts.defaults, settings, ts.instanceMethods); 100924 // save initial settings 100925 c.originalSettings = settings; 100926 // create a table from data (build table widget) 100927 if (!table.hasInitialized && ts.buildTable && this.nodeName !== 'TABLE') { 100928 // return the table (in case the original target is the table's container) 100929 ts.buildTable(table, c); 100930 } else { 100931 ts.setup(table, c); 100932 } 100933 }); 100934 }; 100935 100936 ts.setup = function(table, c) { 100937 // if no thead or tbody, or tablesorter is already present, quit 100938 if (!table || !table.tHead || table.tBodies.length === 0 || table.hasInitialized === true) { 100939 if ( c.debug ) { 100940 if ( table.hasInitialized ) { 100941 console.warn( 'Stopping initialization. Tablesorter has already been initialized' ); 100942 } else { 100943 console.error( 'Stopping initialization! No table, thead or tbody' ); 100944 } 100945 } 100946 return; 100947 } 100948 100949 var k = '', 100950 $table = $(table), 100951 m = $.metadata; 100952 // initialization flag 100953 table.hasInitialized = false; 100954 // table is being processed flag 100955 table.isProcessing = true; 100956 // make sure to store the config object 100957 table.config = c; 100958 // save the settings where they read 100959 $.data(table, 'tablesorter', c); 100960 if (c.debug) { 100961 console[ console.group ? 'group' : 'log' ]( 'Initializing tablesorter' ); 100962 $.data( table, 'startoveralltimer', new Date()); 100963 } 100964 100965 // removing this in version 3 (only supports jQuery 1.7+) 100966 c.supportsDataObject = (function(version) { 100967 version[0] = parseInt(version[0], 10); 100968 return (version[0] > 1) || (version[0] === 1 && parseInt(version[1], 10) >= 4); 100969 })($.fn.jquery.split('.')); 100970 // digit sort text location; keeping max+/- for backwards compatibility 100971 c.string = { 'max': 1, 'min': -1, 'emptymin': 1, 'emptymax': -1, 'zero': 0, 'none': 0, 'null': 0, 'top': true, 'bottom': false }; 100972 // ensure case insensitivity 100973 c.emptyTo = c.emptyTo.toLowerCase(); 100974 c.stringTo = c.stringTo.toLowerCase(); 100975 // add table theme class only if there isn't already one there 100976 if (!/tablesorter\-/.test($table.attr('class'))) { 100977 k = (c.theme !== '' ? ' tablesorter-' + c.theme : ''); 100978 } 100979 c.table = table; 100980 c.$table = $table 100981 .addClass(ts.css.table + ' ' + c.tableClass + k) 100982 .attr('role', 'grid'); 100983 c.$headers = $table.find(c.selectorHeaders); 100984 100985 // give the table a unique id, which will be used in namespace binding 100986 if (!c.namespace) { 100987 c.namespace = '.tablesorter' + Math.random().toString(16).slice(2); 100988 } else { 100989 // make sure namespace starts with a period & doesn't have weird characters 100990 c.namespace = '.' + c.namespace.replace(/\W/g, ''); 100991 } 100992 100993 c.$table.children().children('tr').attr('role', 'row'); 100994 c.$tbodies = $table.children('tbody:not(.' + c.cssInfoBlock + ')').attr({ 100995 'aria-live' : 'polite', 100996 'aria-relevant' : 'all' 100997 }); 100998 if (c.$table.children('caption').length) { 100999 k = c.$table.children('caption')[0]; 101000 if (!k.id) { k.id = c.namespace.slice(1) + 'caption'; } 101001 c.$table.attr('aria-labelledby', k.id); 101002 } 101003 c.widgetInit = {}; // keep a list of initialized widgets 101004 // change textExtraction via data-attribute 101005 c.textExtraction = c.$table.attr('data-text-extraction') || c.textExtraction || 'basic'; 101006 // build headers 101007 buildHeaders(table); 101008 // fixate columns if the users supplies the fixedWidth option 101009 // do this after theme has been applied 101010 ts.fixColumnWidth(table); 101011 // add widget options before parsing (e.g. grouping widget has parser settings) 101012 ts.applyWidgetOptions(table, c); 101013 // try to auto detect column type, and store in tables config 101014 buildParserCache(c); 101015 // start total row count at zero 101016 c.totalRows = 0; 101017 // build the cache for the tbody cells 101018 // delayInit will delay building the cache until the user starts a sort 101019 if (!c.delayInit) { buildCache(table); } 101020 // bind all header events and methods 101021 ts.bindEvents(table, c.$headers, true); 101022 bindMethods(table); 101023 // get sort list from jQuery data or metadata 101024 // in jQuery < 1.4, an error occurs when calling $table.data()
vendor: 5,435 bytes, lines 101025-101178
101025 if (c.supportsDataObject && typeof $table.data().sortlist !== 'undefined') { 101026 c.sortList = $table.data().sortlist; 101027 } else if (m && ($table.metadata() && $table.metadata().sortlist)) { 101028 c.sortList = $table.metadata().sortlist; 101029 } 101030 // apply widget init code 101031 ts.applyWidget(table, true); 101032 // if user has supplied a sort list to constructor 101033 if (c.sortList.length > 0) { 101034 $table.trigger('sorton', [ c.sortList, {}, !c.initWidgets, true ]); 101035 } else { 101036 setHeadersCss(table); 101037 if (c.initWidgets) { 101038 // apply widget format 101039 ts.applyWidget(table, false); 101040 } 101041 } 101042 101043 // show processesing icon 101044 if (c.showProcessing) { 101045 $table 101046 .unbind('sortBegin' + c.namespace + ' sortEnd' + c.namespace) 101047 .bind('sortBegin' + c.namespace + ' sortEnd' + c.namespace, function(e) { 101048 clearTimeout(c.processTimer); 101049 ts.isProcessing(table); 101050 if (e.type === 'sortBegin') { 101051 c.processTimer = setTimeout(function(){ 101052 ts.isProcessing(table, true); 101053 }, 500); 101054 } 101055 }); 101056 } 101057 101058 // initialized 101059 table.hasInitialized = true; 101060 table.isProcessing = false; 101061 if (c.debug) { 101062 console.log( 'Overall initialization time: ' + ts.benchmark( $.data( table, 'startoveralltimer') ) ); 101063 if ( c.debug && console.groupEnd ) { console.groupEnd(); } 101064 } 101065 $table.trigger('tablesorter-initialized', table); 101066 if (typeof c.initialized === 'function') { c.initialized(table); } 101067 }; 101068 101069 // automatically add a colgroup with col elements set to a percentage width 101070 ts.fixColumnWidth = function(table) { 101071 table = $(table)[0]; 101072 var overallWidth, percent, $tbodies, len, index, 101073 c = table.config, 101074 $colgroup = c.$table.children('colgroup'); 101075 // remove plugin-added colgroup, in case we need to refresh the widths 101076 if ($colgroup.length && $colgroup.hasClass(ts.css.colgroup)) { 101077 $colgroup.remove(); 101078 } 101079 if (c.widthFixed && c.$table.children('colgroup').length === 0) { 101080 $colgroup = $('<colgroup class="' + ts.css.colgroup + '">'); 101081 overallWidth = c.$table.width(); 101082 // only add col for visible columns - fixes #371 101083 $tbodies = c.$tbodies.find('tr:first').children(':visible'); // .each(function() 101084 len = $tbodies.length; 101085 for ( index = 0; index < len; index++ ) { 101086 percent = parseInt( ( $tbodies.eq( index ).width() / overallWidth ) * 1000, 10 ) / 10 + '%'; 101087 $colgroup.append( $('<col>').css('width', percent) ); 101088 } 101089 c.$table.prepend($colgroup); 101090 } 101091 }; 101092 101093 ts.getColumnData = function(table, obj, indx, getCell, $headers){ 101094 if (typeof obj === 'undefined' || obj === null) { return; } 101095 table = $(table)[0]; 101096 var $h, k, 101097 c = table.config, 101098 $cells = ( $headers || c.$headers ), 101099 // c.$headerIndexed is not defined initially 101100 $cell = c.$headerIndexed && c.$headerIndexed[indx] || $cells.filter('[data-column="' + indx + '"]:last'); 101101 if (obj[indx]) { 101102 return getCell ? obj[indx] : obj[$cells.index( $cell )]; 101103 } 101104 for (k in obj) { 101105 if (typeof k === 'string') { 101106 $h = $cell 101107 // header cell with class/id 101108 .filter(k) 101109 // find elements within the header cell with cell/id 101110 .add( $cell.find(k) ); 101111 if ($h.length) { 101112 return obj[k]; 101113 } 101114 } 101115 } 101116 return; 101117 }; 101118 101119 // computeTableHeaderCellIndexes from: 101120 // http://www.javascripttoolbox.com/lib/table/examples.php 101121 // http://www.javascripttoolbox.com/temp/table_cellindex.html 101122 ts.computeColumnIndex = function(trs) { 101123 var i, j, k, l, $cell, cell, cells, rowIndex, cellId, rowSpan, colSpan, firstAvailCol, 101124 matrix = [], 101125 matrixrow = [], 101126 lookup = {}; 101127 for (i = 0; i < trs.length; i++) { 101128 cells = trs[i].cells; 101129 for (j = 0; j < cells.length; j++) { 101130 cell = cells[j]; 101131 $cell = $(cell); 101132 rowIndex = cell.parentNode.rowIndex; 101133 cellId = rowIndex + '-' + $cell.index(); 101134 rowSpan = cell.rowSpan || 1; 101135 colSpan = cell.colSpan || 1; 101136 if (typeof matrix[rowIndex] === 'undefined') { 101137 matrix[rowIndex] = []; 101138 } 101139 // Find first available column in the first row 101140 for (k = 0; k < matrix[rowIndex].length + 1; k++) { 101141 if (typeof matrix[rowIndex][k] === 'undefined') { 101142 firstAvailCol = k; 101143 break; 101144 } 101145 } 101146 lookup[cellId] = firstAvailCol; 101147 // add data-column 101148 $cell.attr({ 'data-column' : firstAvailCol }); // 'data-row' : rowIndex 101149 for (k = rowIndex; k < rowIndex + rowSpan; k++) { 101150 if (typeof matrix[k] === 'undefined') { 101151 matrix[k] = []; 101152 } 101153 matrixrow = matrix[k]; 101154 for (l = firstAvailCol; l < firstAvailCol + colSpan; l++) { 101155 matrixrow[l] = 'x'; 101156 } 101157 } 101158 } 101159 } 101160 return matrixrow.length; 101161 }; 101162 101163 // *** Process table *** 101164 // add processing indicator 101165 ts.isProcessing = function( $table, toggle, $ths ) { 101166 $table = $( $table ); 101167 var c = $table[0].config, 101168 // default to all headers 101169 $h = $ths || $table.find('.' + ts.css.header); 101170 if (toggle) { 101171 // don't use sortList if custom $ths used 101172 if (typeof $ths !== 'undefined' && c.sortList.length > 0) { 101173 // get headers from the sortList 101174 $h = $h.filter(function(){ 101175 // get data-column from attr to keep compatibility with jQuery 1.2.6 101176 return this.sortDisabled ? false : ts.isValueInArray( parseFloat($(this).attr('data-column')), c.sortList) >= 0; 101177 }); 101178 }
101179 $table.add($h).addClass(ts.css.processing + ' ' + c.cssProcessing); 101180 } else { 101181 $table.add($h).removeClass(ts.css.processing + ' ' + c.cssProcessing); 101182 } 101183 }; 101184 101185 // detach tbody but save the position 101186 // don't use tbody because there are portions that look for a tbody index (updateCell) 101187 ts.processTbody = function(table, $tb, getIt){ 101188 table = $(table)[0]; 101189 var holdr; 101190 if (getIt) { 101191 table.isProcessing = true; 101192 $tb.before('<colgroup class="tablesorter-savemyplace"/>'); 101193 holdr = ($.fn.detach) ? $tb.detach() : $tb.remove(); 101194 return holdr; 101195 } 101196 holdr = $(table).find('colgroup.tablesorter-savemyplace'); 101197 $tb.insertAfter( holdr ); 101198 holdr.remove(); 101199 table.isProcessing = false; 101200 }; 101201 101202 ts.clearTableBody = function(table) { 101203 $(table)[0].config.$tbodies.children().detach(); 101204 }; 101205 101206 ts.bindEvents = function(table, $headers, core) { 101207 table = $(table)[0]; 101208 var t, downTarget = null, 101209 c = table.config; 101210 if (core !== true) { 101211 $headers.addClass( c.namespace.slice(1) + '_extra_headers' ); 101212 t = $.fn.closest ? $headers.closest('table')[0] : $headers.parents('table')[0]; 101213 if (t && t.nodeName === 'TABLE' && t !== table) { 101214 $(t).addClass( c.namespace.slice(1) + '_extra_table' ); 101215 } 101216 } 101217 t = ( c.pointerDown + ' ' + c.pointerUp + ' ' + c.pointerClick + ' sort keyup ' ) 101218 .replace(/\s+/g, ' ') 101219 .split(' ') 101220 .join(c.namespace + ' '); 101221 // apply event handling to headers and/or additional headers (stickyheaders, scroller, etc) 101222 $headers 101223 // http://stackoverflow.com/questions/5312849/jquery-find-self; 101224 .find(c.selectorSort).add( $headers.filter(c.selectorSort) ) 101225 .unbind(t) 101226 .bind(t, function(e, external) { 101227 var cell, temp, 101228 $target = $(e.target), 101229 // wrap event type in spaces, so the match doesn't trigger on inner words 101230 type = ' ' + e.type + ' '; 101231 // only recognize left clicks 101232 if ( ( ( e.which || e.button ) !== 1 && !type.match( ' ' + c.pointerClick + ' | sort | keyup ' ) ) || 101233 // allow pressing enter 101234 ( type === ' keyup ' && e.which !== 13 ) || 101235 // allow triggering a click event (e.which is undefined) & ignore physical clicks 101236 ( type.match(' ' + c.pointerClick + ' ') && typeof e.which !== 'undefined' ) ) { 101237 return; 101238 } 101239 // ignore mouseup if mousedown wasn't on the same target 101240 if ( type.match(' ' + c.pointerUp + ' ') && downTarget !== e.target && external !== true ) { return; } 101241 // set target on mousedown 101242 if ( type.match(' ' + c.pointerDown + ' ') ) { 101243 downTarget = e.target; 101244 // preventDefault needed or jQuery v1.3.2 and older throws an 101245 // "Uncaught TypeError: handler.apply is not a function" error 101246 temp = $target.jquery.split( '.' ); 101247 if ( temp[0] === '1' && temp[1] < 4 ) { e.preventDefault(); } 101248 return; 101249 } 101250 downTarget = null; 101251 // prevent sort being triggered on form elements 101252 if ( /(input|select|button|textarea)/i.test(e.target.nodeName) || 101253 // nosort class name, or elements within a nosort container 101254 $target.hasClass(c.cssNoSort) || $target.parents('.' + c.cssNoSort).length > 0 || 101255 // elements within a button 101256 $target.parents('button').length > 0 ) { 101257 return !c.cancelSelection; 101258 } 101259 if (c.delayInit && isEmptyObject(c.cache)) { buildCache(table); } 101260 // jQuery v1.2.6 doesn't have closest() 101261 cell = $.fn.closest ? $(this).closest('th, td')[0] : /TH|TD/.test(this.nodeName) ? this : $(this).parents('th, td')[0]; 101262 // reference original table headers and find the same cell 101263 cell = c.$headers[ $headers.index( cell ) ]; 101264 if (!cell.sortDisabled) { 101265 initSort(table, cell, e); 101266 } 101267 }); 101268 if (c.cancelSelection) { 101269 // cancel selection 101270 $headers 101271 .attr('unselectable', 'on') 101272 .bind('selectstart', false) 101273 .css({ 101274 'user-select': 'none', 101275 'MozUserSelect': 'none' // not needed for jQuery 1.8+ 101276 }); 101277 } 101278 }; 101279 101280 // restore headers 101281 ts.restoreHeaders = function(table){ 101282 var index, $cell, 101283 c = $(table)[0].config, 101284 $headers = c.$table.find( c.selectorHeaders ), 101285 len = $headers.length; 101286 // don't use c.$headers here in case header cells were swapped 101287 for ( index = 0; index < len; index++ ) { 101288 // c.$table.find(c.selectorHeaders).each(function(i){ 101289 $cell = $headers.eq( index );
vendor: 7,285 bytes, lines 101290-101465
101290 // only restore header cells if it is wrapped 101291 // because this is also used by the updateAll method 101292 if ( $cell.find( '.' + ts.css.headerIn ).length ) { 101293 $cell.html( c.headerContent[ index ] ); 101294 } 101295 } 101296 }; 101297 101298 ts.destroy = function(table, removeClasses, callback){ 101299 table = $(table)[0]; 101300 if (!table.hasInitialized) { return; } 101301 // remove all widgets 101302 ts.removeWidget(table, true, false); 101303 var events, 101304 $t = $(table), 101305 c = table.config, 101306 debug = c.debug, 101307 $h = $t.find('thead:first'), 101308 $r = $h.find('tr.' + ts.css.headerRow).removeClass(ts.css.headerRow + ' ' + c.cssHeaderRow), 101309 $f = $t.find('tfoot:first > tr').children('th, td'); 101310 if (removeClasses === false && $.inArray('uitheme', c.widgets) >= 0) { 101311 // reapply uitheme classes, in case we want to maintain appearance 101312 $t.trigger('applyWidgetId', [ 'uitheme' ]); 101313 $t.trigger('applyWidgetId', [ 'zebra' ]); 101314 } 101315 // remove widget added rows, just in case 101316 $h.find('tr').not($r).remove(); 101317 // disable tablesorter 101318 events = 'sortReset update updateAll updateRows updateCell addRows updateComplete sorton appendCache updateCache ' + 101319 'applyWidgetId applyWidgets refreshWidgets destroy mouseup mouseleave keypress sortBegin sortEnd resetToLoadState '.split(' ') 101320 .join(c.namespace + ' '); 101321 $t 101322 .removeData('tablesorter') 101323 .unbind( events.replace(/\s+/g, ' ') ); 101324 c.$headers.add($f) 101325 .removeClass( [ ts.css.header, c.cssHeader, c.cssAsc, c.cssDesc, ts.css.sortAsc, ts.css.sortDesc, ts.css.sortNone ].join(' ') ) 101326 .removeAttr('data-column') 101327 .removeAttr('aria-label') 101328 .attr('aria-disabled', 'true'); 101329 $r.find(c.selectorSort).unbind( ('mousedown mouseup keypress '.split(' ').join(c.namespace + ' ')).replace(/\s+/g, ' ') ); 101330 ts.restoreHeaders(table); 101331 $t.toggleClass(ts.css.table + ' ' + c.tableClass + ' tablesorter-' + c.theme, removeClasses === false); 101332 // clear flag in case the plugin is initialized again 101333 table.hasInitialized = false; 101334 delete table.config.cache; 101335 if (typeof callback === 'function') { 101336 callback(table); 101337 } 101338 if (debug) { 101339 console.log( 'tablesorter has been removed' ); 101340 } 101341 }; 101342 101343 // *** sort functions *** 101344 // regex used in natural sort 101345 ts.regex = { 101346 chunk : /(^([+\-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?)?$|^0x[0-9a-f]+$|\d+)/gi, // chunk/tokenize numbers & letters 101347 chunks: /(^\\0|\\0$)/, // replace chunks @ ends 101348 hex: /^0x[0-9a-f]+$/i // hex 101349 }; 101350 101351 // Natural sort - https://github.com/overset/javascript-natural-sort (date sorting removed) 101352 // this function will only accept strings, or you'll see 'TypeError: undefined is not a function' 101353 // I could add a = a.toString(); b = b.toString(); but it'll slow down the sort overall 101354 ts.sortNatural = function(a, b) { 101355 if (a === b) { return 0; } 101356 var xN, xD, yN, yD, xF, yF, i, mx, 101357 r = ts.regex; 101358 // first try and sort Hex codes 101359 if (r.hex.test(b)) { 101360 xD = parseInt(a.match(r.hex), 16); 101361 yD = parseInt(b.match(r.hex), 16); 101362 if ( xD < yD ) { return -1; } 101363 if ( xD > yD ) { return 1; } 101364 } 101365 // chunk/tokenize 101366 xN = a.replace(r.chunk, '\\0$1\\0').replace(r.chunks, '').split('\\0'); 101367 yN = b.replace(r.chunk, '\\0$1\\0').replace(r.chunks, '').split('\\0'); 101368 mx = Math.max(xN.length, yN.length); 101369 // natural sorting through split numeric strings and default strings 101370 for (i = 0; i < mx; i++) { 101371 // find floats not starting with '0', string or 0 if not defined 101372 xF = isNaN(xN[i]) ? xN[i] || 0 : parseFloat(xN[i]) || 0; 101373 yF = isNaN(yN[i]) ? yN[i] || 0 : parseFloat(yN[i]) || 0; 101374 // handle numeric vs string comparison - number < string - (Kyle Adams) 101375 if (isNaN(xF) !== isNaN(yF)) { return (isNaN(xF)) ? 1 : -1; } 101376 // rely on string comparison if different types - i.e. '02' < 2 != '02' < '2' 101377 if (typeof xF !== typeof yF) { 101378 xF += ''; 101379 yF += ''; 101380 } 101381 if (xF < yF) { return -1; } 101382 if (xF > yF) { return 1; } 101383 } 101384 return 0; 101385 }; 101386 101387 ts.sortNaturalAsc = function(a, b, col, table, c) { 101388 if (a === b) { return 0; } 101389 var e = c.string[ (c.empties[col] || c.emptyTo ) ]; 101390 if (a === '' && e !== 0) { return typeof e === 'boolean' ? (e ? -1 : 1) : -e || -1; } 101391 if (b === '' && e !== 0) { return typeof e === 'boolean' ? (e ? 1 : -1) : e || 1; } 101392 return ts.sortNatural(a, b); 101393 }; 101394 101395 ts.sortNaturalDesc = function(a, b, col, table, c) { 101396 if (a === b) { return 0; } 101397 var e = c.string[ (c.empties[col] || c.emptyTo ) ]; 101398 if (a === '' && e !== 0) { return typeof e === 'boolean' ? (e ? -1 : 1) : e || 1; } 101399 if (b === '' && e !== 0) { return typeof e === 'boolean' ? (e ? 1 : -1) : -e || -1; } 101400 return ts.sortNatural(b, a); 101401 }; 101402 101403 // basic alphabetical sort 101404 ts.sortText = function(a, b) { 101405 return a > b ? 1 : (a < b ? -1 : 0); 101406 }; 101407 101408 // return text string value by adding up ascii value 101409 // so the text is somewhat sorted when using a digital sort 101410 // this is NOT an alphanumeric sort 101411 ts.getTextValue = function(a, num, mx) { 101412 if (mx) { 101413 // make sure the text value is greater than the max numerical value (mx) 101414 var i, l = a ? a.length : 0, n = mx + num; 101415 for (i = 0; i < l; i++) { 101416 n += a.charCodeAt(i); 101417 } 101418 return num * n; 101419 } 101420 return 0; 101421 }; 101422 101423 ts.sortNumericAsc = function(a, b, num, mx, col, table) { 101424 if (a === b) { return 0; } 101425 var c = table.config, 101426 e = c.string[ (c.empties[col] || c.emptyTo ) ]; 101427 if (a === '' && e !== 0) { return typeof e === 'boolean' ? (e ? -1 : 1) : -e || -1; } 101428 if (b === '' && e !== 0) { return typeof e === 'boolean' ? (e ? 1 : -1) : e || 1; } 101429 if (isNaN(a)) { a = ts.getTextValue(a, num, mx); } 101430 if (isNaN(b)) { b = ts.getTextValue(b, num, mx); } 101431 return a - b; 101432 }; 101433 101434 ts.sortNumericDesc = function(a, b, num, mx, col, table) { 101435 if (a === b) { return 0; } 101436 var c = table.config, 101437 e = c.string[ (c.empties[col] || c.emptyTo ) ]; 101438 if (a === '' && e !== 0) { return typeof e === 'boolean' ? (e ? -1 : 1) : e || 1; } 101439 if (b === '' && e !== 0) { return typeof e === 'boolean' ? (e ? 1 : -1) : -e || -1; } 101440 if (isNaN(a)) { a = ts.getTextValue(a, num, mx); } 101441 if (isNaN(b)) { b = ts.getTextValue(b, num, mx); } 101442 return b - a; 101443 }; 101444 101445 ts.sortNumeric = function(a, b) { 101446 return a - b; 101447 }; 101448 101449 // used when replacing accented characters during sorting 101450 ts.characterEquivalents = { 101451 'a' : '\u00e1\u00e0\u00e2\u00e3\u00e4\u0105\u00e5', // Ã¡Ã Ã¢Ã£Ã¤Ä Ã¥ 101452 'A' : '\u00c1\u00c0\u00c2\u00c3\u00c4\u0104\u00c5', // ÃÃÃÃÃÄà 101453 'c' : '\u00e7\u0107\u010d', // çÄÄ 101454 'C' : '\u00c7\u0106\u010c', // ÃÄÄ 101455 'e' : '\u00e9\u00e8\u00ea\u00eb\u011b\u0119', // éèêëÄÄ 101456 'E' : '\u00c9\u00c8\u00ca\u00cb\u011a\u0118', // ÃÃÃÃÄÄ 101457 'i' : '\u00ed\u00ec\u0130\u00ee\u00ef\u0131', // Ãìİîïı 101458 'I' : '\u00cd\u00cc\u0130\u00ce\u00cf', // ÃÃİÃà 101459 'o' : '\u00f3\u00f2\u00f4\u00f5\u00f6\u014d', // óòôõöŠ101460 'O' : '\u00d3\u00d2\u00d4\u00d5\u00d6\u014c', // ÃÃÃÃÃÅ 101461 'ss': '\u00df', // à (s sharp) 101462 'SS': '\u1e9e', // Ạ(Capital sharp s) 101463 'u' : '\u00fa\u00f9\u00fb\u00fc\u016f', // úùûüů 101464 'U' : '\u00da\u00d9\u00db\u00dc\u016e' // ÃÃÃÃÅ® 101465 };
101466 ts.replaceAccents = function(s) { 101467 var a, acc = '[', eq = ts.characterEquivalents; 101468 if (!ts.characterRegex) { 101469 ts.characterRegexArray = {}; 101470 for (a in eq) { 101471 if (typeof a === 'string') { 101472 acc += eq[a]; 101473 ts.characterRegexArray[a] = new RegExp('[' + eq[a] + ']', 'g'); 101474 } 101475 } 101476 ts.characterRegex = new RegExp(acc + ']'); 101477 } 101478 if (ts.characterRegex.test(s)) { 101479 for (a in eq) { 101480 if (typeof a === 'string') { 101481 s = s.replace( ts.characterRegexArray[a], a ); 101482 } 101483 } 101484 } 101485 return s; 101486 }; 101487 101488 // *** utilities *** 101489 ts.isValueInArray = function( column, arry ) { 101490 var indx, 101491 len = arry && arry.length || 0; 101492 for ( indx = 0; indx < len; indx++ ) { 101493 if ( arry[ indx ][ 0 ] === column ) { 101494 return indx; 101495 } 101496 } 101497 return -1; 101498 }; 101499 101500 ts.addParser = function(parser) { 101501 var i, l = ts.parsers.length, a = true; 101502 for (i = 0; i < l; i++) { 101503 if (ts.parsers[i].id.toLowerCase() === parser.id.toLowerCase()) { 101504 a = false; 101505 } 101506 } 101507 if (a) { 101508 ts.parsers.push(parser); 101509 } 101510 }; 101511 101512 // Use it to add a set of methods to table.config which will be available for all tables. 101513 // This should be done before table initialization 101514 ts.addInstanceMethods = function(methods) { 101515 $.extend(ts.instanceMethods, methods); 101516 }; 101517 101518 ts.getParserById = function(name) { 101519 /*jshint eqeqeq:false */ 101520 if (name == 'false') { return false; } 101521 var i, l = ts.parsers.length; 101522 for (i = 0; i < l; i++) { 101523 if (ts.parsers[i].id.toLowerCase() === (name.toString()).toLowerCase()) { 101524 return ts.parsers[i]; 101525 } 101526 } 101527 return false; 101528 }; 101529 101530 ts.addWidget = function(widget) { 101531 ts.widgets.push(widget); 101532 }; 101533 101534 ts.hasWidget = function( $table, name ) { 101535 $table = $( $table ); 101536 return $table.length && $table[0].config && $table[0].config.widgetInit[name] || false; 101537 }; 101538 101539 ts.getWidgetById = function(name) { 101540 var i, w, l = ts.widgets.length; 101541 for (i = 0; i < l; i++) { 101542 w = ts.widgets[i]; 101543 if (w && w.hasOwnProperty('id') && w.id.toLowerCase() === name.toLowerCase()) { 101544 return w; 101545 } 101546 } 101547 }; 101548 101549 ts.applyWidgetOptions = function( table, c ){ 101550 var indx, widget, 101551 len = c.widgets.length, 101552 wo = c.widgetOptions; 101553 if (len) { 101554 for (indx = 0; indx < len; indx++) { 101555 widget = ts.getWidgetById( c.widgets[indx] ); 101556 if ( widget && 'options' in widget ) { 101557 wo = table.config.widgetOptions = $.extend( true, {}, widget.options, wo ); 101558 } 101559 } 101560 } 101561 }; 101562 101563 ts.applyWidget = function(table, init, callback) { 101564 table = $(table)[0]; // in case this is called externally 101565 var indx, len, names, widget, name, applied, 101566 c = table.config, 101567 wo = c.widgetOptions, 101568 tableClass = ' ' + c.table.className + ' ', 101569 widgets = [], 101570 time, time2, w, wd; 101571 // prevent numerous consecutive widget applications 101572 if (init !== false && table.hasInitialized && (table.isApplyingWidgets || table.isUpdating)) { return; } 101573 if (c.debug) { time = new Date(); } 101574 // look for widgets to apply from in table class 101575 // stop using \b otherwise this matches 'ui-widget-content' & adds 'content' widget 101576 wd = new RegExp( '\\s' + c.widgetClass.replace( /\{name\}/i, '([\\w-]+)' ) + '\\s', 'g' ); 101577 if ( tableClass.match( wd ) ) { 101578 // extract out the widget id from the table class (widget id's can include dashes) 101579 w = tableClass.match( wd ); 101580 if ( w ) { 101581 len = w.length; 101582 for (indx = 0; indx < len; indx++) { 101583 c.widgets.push( w[indx].replace( wd, '$1' ) ); 101584 } 101585 } 101586 } 101587 if (c.widgets.length) { 101588 table.isApplyingWidgets = true; 101589 // ensure unique widget ids 101590 c.widgets = $.grep(c.widgets, function(v, k){ 101591 return $.inArray(v, c.widgets) === k; 101592 }); 101593 names = c.widgets || []; 101594 len = names.length; 101595 // build widget array & add priority as needed 101596 for (indx = 0; indx < len; indx++) { 101597 wd = ts.getWidgetById(names[indx]); 101598 if (wd && wd.id) { 101599 // set priority to 10 if not defined 101600 if (!wd.priority) { wd.priority = 10; } 101601 widgets[indx] = wd; 101602 } 101603 } 101604 // sort widgets by priority 101605 widgets.sort(function(a, b){ 101606 return a.priority < b.priority ? -1 : a.priority === b.priority ? 0 : 1; 101607 }); 101608 // add/update selected widgets 101609 len = widgets.length; 101610 if (c.debug) { 101611 console[ console.group ? 'group' : 'log' ]( 'Start ' + ( init ? 'initializing' : 'applying' ) + ' widgets' ); 101612 } 101613 for (indx = 0; indx < len; indx++) { 101614 widget = widgets[indx]; 101615 if (widget) { 101616 name = widget.id; 101617 applied = false;
101618 if (c.debug) { time2 = new Date(); } 101619 101620 if ( init || !( c.widgetInit[ name ] ) ) { 101621 // set init flag first to prevent calling init more than once (e.g. pager) 101622 c.widgetInit[ name ] = true; 101623 if (table.hasInitialized) { 101624 // don't reapply widget options on tablesorter init 101625 ts.applyWidgetOptions( table, c ); 101626 } 101627 if ( 'init' in widget ) { 101628 applied = true; 101629 if (c.debug) { 101630 console[ console.group ? 'group' : 'log' ]( 'Initializing ' + name + ' widget' ); 101631 } 101632 widget.init(table, widget, c, wo); 101633 } 101634 } 101635 if ( !init && 'format' in widget ) { 101636 applied = true; 101637 if (c.debug) { 101638 console[ console.group ? 'group' : 'log' ]( 'Updating ' + name + ' widget' ); 101639 } 101640 widget.format(table, c, wo, false); 101641 } 101642 if (c.debug) { 101643 if (applied) { 101644 console.log( 'Completed ' + ( init ? 'initializing ' : 'applying ' ) + name + ' widget' + ts.benchmark( time2 ) ); 101645 if ( console.groupEnd ) { console.groupEnd(); } 101646 } 101647 } 101648 } 101649 } 101650 if ( c.debug && console.groupEnd ) { console.groupEnd(); } 101651 // callback executed on init only 101652 if (!init && typeof callback === 'function') { 101653 callback(table); 101654 } 101655 } 101656 setTimeout(function(){ 101657 table.isApplyingWidgets = false; 101658 $.data(table, 'lastWidgetApplication', new Date()); 101659 }, 0); 101660 if (c.debug) { 101661 w = c.widgets.length; 101662 console.log( 'Completed ' + (init === true ? 'initializing ' : 'applying ') + w + ' widget' + (w !== 1 ? 's' : '') + ts.benchmark(time) ); 101663 } 101664 }; 101665 101666 ts.removeWidget = function(table, name, refreshing){ 101667 table = $(table)[0]; 101668 var i, widget, indx, len, 101669 c = table.config; 101670 // if name === true, add all widgets from $.tablesorter.widgets 101671 if (name === true) { 101672 name = []; 101673 len = ts.widgets.length; 101674 for (indx = 0; indx < len; indx++) { 101675 widget = ts.widgets[indx]; 101676 if (widget && widget.id) { 101677 name.push( widget.id ); 101678 } 101679 } 101680 } else { 101681 // name can be either an array of widgets names, 101682 // or a space/comma separated list of widget names 101683 name = ( $.isArray(name) ? name.join(',') : name || '' ).toLowerCase().split( /[\s,]+/ ); 101684 } 101685 len = name.length; 101686 for (i = 0; i < len; i++) { 101687 widget = ts.getWidgetById(name[i]); 101688 indx = $.inArray( name[i], c.widgets ); 101689 if ( widget && 'remove' in widget ) { 101690 if (c.debug && indx >= 0) { console.log( 'Removing "' + name[i] + '" widget' ); } 101691 if ( c.debug ) { 101692 console.log( ( refreshing ? 'Refreshing' : 'Removing' ) + ' "' + name[i] + '" widget' ); 101693 } 101694 widget.remove(table, c, c.widgetOptions, refreshing); 101695 c.widgetInit[ name[i] ] = false; 101696 } 101697 // don't remove the widget from config.widget if refreshing 101698 if (indx >= 0 && refreshing !== true) { 101699 c.widgets.splice( indx, 1 ); 101700 } 101701 } 101702 }; 101703 101704 ts.refreshWidgets = function(table, doAll, dontapply) { 101705 table = $(table)[0]; // see issue #243 101706 var indx, 101707 c = table.config, 101708 cw = c.widgets, 101709 widgets = ts.widgets, 101710 len = widgets.length, 101711 list = [], 101712 callback = function(table){ 101713 $(table).trigger('refreshComplete'); 101714 }; 101715 // remove widgets not defined in config.widgets, unless doAll is true 101716 for (indx = 0; indx < len; indx++) { 101717 if (widgets[indx] && widgets[indx].id && (doAll || $.inArray( widgets[indx].id, cw ) < 0)) { 101718 list.push( widgets[indx].id ); 101719 } 101720 } 101721 ts.removeWidget( table, list.join(','), true ); 101722 if (dontapply !== true) { 101723 // call widget init if 101724 ts.applyWidget(table, doAll || false, callback ); 101725 if (doAll) { 101726 // apply widget format 101727 ts.applyWidget(table, false, callback); 101728 } 101729 } else { 101730 callback(table); 101731 } 101732 }; 101733 101734 ts.getColumnText = function( table, column, callback ) { 101735 table = $( table )[0]; 101736 var tbodyIndex, rowIndex, cache, row, tbodyLen, rowLen, raw, parsed, $cell, result, 101737 hasCallback = typeof callback === 'function', 101738 allColumns = column === 'all', 101739 data = { raw : [], parsed: [], $cell: [] }, 101740 c = table.config; 101741 if ( isEmptyObject( c ) ) { 101742 if ( c.debug ) {
101743 console.warn( 'No cache found - aborting getColumnText function!' ); 101744 } 101745 } else { 101746 tbodyLen = c.$tbodies.length; 101747 for ( tbodyIndex = 0; tbodyIndex < tbodyLen; tbodyIndex++ ) { 101748 cache = c.cache[ tbodyIndex ].normalized; 101749 rowLen = cache.length; 101750 for ( rowIndex = 0; rowIndex < rowLen; rowIndex++ ) { 101751 result = true; 101752 row = cache[ rowIndex ]; 101753 parsed = ( allColumns ) ? row.slice(0, c.columns) : row[ column ]; 101754 row = row[ c.columns ]; 101755 raw = ( allColumns ) ? row.raw : row.raw[ column ]; 101756 $cell = ( allColumns ) ? row.$row.children() : row.$row.children().eq( column ); 101757 if ( hasCallback ) { 101758 result = callback({ 101759 tbodyIndex: tbodyIndex, 101760 rowIndex: rowIndex, 101761 parsed: parsed, 101762 raw: raw, 101763 $row: row.$row, 101764 $cell: $cell 101765 }); 101766 } 101767 if ( result !== false ) { 101768 data.parsed.push( parsed ); 101769 data.raw.push( raw ); 101770 data.$cell.push( $cell ); 101771 } 101772 } 101773 } 101774 // return everything 101775 return data; 101776 } 101777 }; 101778 101779 // get sorter, string, empty, etc options for each column from 101780 // jQuery data, metadata, header option or header class name ('sorter-false') 101781 // priority = jQuery data > meta > headers option > header class name 101782 ts.getData = function(h, ch, key) { 101783 var val = '', $h = $(h), m, cl; 101784 if (!$h.length) { return ''; } 101785 m = $.metadata ? $h.metadata() : false; 101786 cl = ' ' + ($h.attr('class') || ''); 101787 if (typeof $h.data(key) !== 'undefined' || typeof $h.data(key.toLowerCase()) !== 'undefined'){ 101788 // 'data-lockedOrder' is assigned to 'lockedorder'; but 'data-locked-order' is assigned to 'lockedOrder' 101789 // 'data-sort-initial-order' is assigned to 'sortInitialOrder' 101790 val += $h.data(key) || $h.data(key.toLowerCase()); 101791 } else if (m && typeof m[key] !== 'undefined') { 101792 val += m[key]; 101793 } else if (ch && typeof ch[key] !== 'undefined') { 101794 val += ch[key]; 101795 } else if (cl !== ' ' && cl.match(' ' + key + '-')) { 101796 // include sorter class name 'sorter-text', etc; now works with 'sorter-my-custom-parser' 101797 val = cl.match( new RegExp('\\s' + key + '-([\\w-]+)') )[1] || ''; 101798 } 101799 return $.trim(val); 101800 }; 101801 101802 ts.formatFloat = function(s, table) { 101803 if (typeof s !== 'string' || s === '') { return s; } 101804 // allow using formatFloat without a table; defaults to US number format 101805 var i, 101806 t = table && table.config ? table.config.usNumberFormat !== false : 101807 typeof table !== 'undefined' ? table : true; 101808 if (t) { 101809 // US Format - 1,234,567.89 -> 1234567.89 101810 s = s.replace(/,/g, ''); 101811 } else { 101812 // German Format = 1.234.567,89 -> 1234567.89 101813 // French Format = 1 234 567,89 -> 1234567.89 101814 s = s.replace(/[\s|\.]/g, '').replace(/,/g, '.'); 101815 } 101816 if (/^\s*\([.\d]+\)/.test(s)) { 101817 // make (#) into a negative number -> (10) = -10 101818 s = s.replace(/^\s*\(([.\d]+)\)/, '-$1'); 101819 } 101820 i = parseFloat(s); 101821 // return the text instead of zero 101822 return isNaN(i) ? $.trim(s) : i; 101823 }; 101824 101825 ts.isDigit = function(s) { 101826 // replace all unwanted chars and match 101827 return isNaN(s) ? (/^[\-+(]?\d+[)]?$/).test(s.toString().replace(/[,.'"\s]/g, '')) : s !== ''; 101828 }; 101829 101830 }() 101831 }); 101832 101833 // make shortcut 101834 var ts = $.tablesorter; 101835 101836 // extend plugin scope 101837 $.fn.extend({ 101838 tablesorter: ts.construct 101839 }); 101840 101841 // set up debug logs 101842 if ( !( console && console.log ) ) { 101843 ts.logs = []; 101844 /*jshint -W020 */ 101845 console = {};
101846 console.log = console.warn = console.error = console.table = function() { 101847 ts.logs.push( [ Date.now(), arguments ] ); 101848 }; 101849 } 101850 101851 ts.log = function(){ 101852 console.log( arguments ); 101853 }; 101854 ts.benchmark = function( diff ) { 101855 return ( ' (' + ( new Date().getTime() - diff.getTime() ) + 'ms)' ); 101856 }; 101857 101858 // add default parsers 101859 ts.addParser({ 101860 id: 'no-parser', 101861 is: function() { 101862 return false; 101863 }, 101864 format: function() { 101865 return ''; 101866 }, 101867 type: 'text' 101868 }); 101869 101870 ts.addParser({ 101871 id: 'text', 101872 is: function() { 101873 return true; 101874 }, 101875 format: function(s, table) { 101876 var c = table.config; 101877 if (s) { 101878 s = $.trim( c.ignoreCase ? s.toLocaleLowerCase() : s ); 101879 s = c.sortLocaleCompare ? ts.replaceAccents(s) : s; 101880 } 101881 return s; 101882 }, 101883 type: 'text' 101884 }); 101885 101886 ts.addParser({ 101887 id: 'digit', 101888 is: function(s) { 101889 return ts.isDigit(s); 101890 }, 101891 format: function(s, table) { 101892 var n = ts.formatFloat((s || '').replace(/[^\w,. \-()]/g, ''), table); 101893 return s && typeof n === 'number' ? n : s ? $.trim( s && table.config.ignoreCase ? s.toLocaleLowerCase() : s ) : s; 101894 }, 101895 type: 'numeric' 101896 }); 101897 101898 ts.addParser({ 101899 id: 'currency', 101900 is: function(s) { 101901 return (/^\(?\d+[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]|[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]\d+\)?$/).test((s || '').replace(/[+\-,. ]/g, '')); // £$â¬Â¤Â¥Â¢ 101902 }, 101903 format: function(s, table) { 101904 var n = ts.formatFloat((s || '').replace(/[^\w,. \-()]/g, ''), table); 101905 return s && typeof n === 'number' ? n : s ? $.trim( s && table.config.ignoreCase ? s.toLocaleLowerCase() : s ) : s; 101906 }, 101907 type: 'numeric' 101908 }); 101909 101910 ts.addParser({ 101911 id: 'url', 101912 is: function(s) { 101913 return (/^(https?|ftp|file):\/\//).test(s); 101914 }, 101915 format: function(s) { 101916 return s ? $.trim(s.replace(/(https?|ftp|file):\/\//, '')) : s; 101917 }, 101918 parsed : true, // filter widget flag 101919 type: 'text' 101920 }); 101921 101922 ts.addParser({ 101923 id: 'isoDate', 101924 is: function(s) { 101925 return (/^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}/).test(s); 101926 }, 101927 format: function(s, table) { 101928 var date = s ? new Date( s.replace(/-/g, '/') ) : s; 101929 return date instanceof Date && isFinite(date) ? date.getTime() : s; 101930 }, 101931 type: 'numeric' 101932 }); 101933 101934 ts.addParser({ 101935 id: 'percent', 101936 is: function(s) { 101937 return (/(\d\s*?%|%\s*?\d)/).test(s) && s.length < 15; 101938 }, 101939 format: function(s, table) { 101940 return s ? ts.formatFloat(s.replace(/%/g, ''), table) : s; 101941 }, 101942 type: 'numeric' 101943 }); 101944 101945 // added image parser to core v2.17.9 101946 ts.addParser({ 101947 id: 'image', 101948 is: function(s, table, node, $node){ 101949 return $node.find('img').length > 0; 101950 }, 101951 format: function(s, table, cell) { 101952 return $(cell).find('img').attr(table.config.imgAttr || 'alt') || s; 101953 }, 101954 parsed : true, // filter widget flag 101955 type: 'text' 101956 }); 101957 101958 ts.addParser({ 101959 id: 'usLongDate', 101960 is: function(s) { 101961 // two digit years are not allowed cross-browser 101962 // Jan 01, 2013 12:34:56 PM or 01 Jan 2013 101963 return (/^[A-Z]{3,10}\.?\s+\d{1,2},?\s+(\d{4})(\s+\d{1,2}:\d{2}(:\d{2})?(\s+[AP]M)?)?$/i).test(s) || (/^\d{1,2}\s+[A-Z]{3,10}\s+\d{4}/i).test(s); 101964 }, 101965 format: function(s, table) { 101966 var date = s ? new Date( s.replace(/(\S)([AP]M)$/i, '$1 $2') ) : s; 101967 return date instanceof Date && isFinite(date) ? date.getTime() : s; 101968 }, 101969 type: 'numeric' 101970 }); 101971 101972 ts.addParser({ 101973 id: 'shortDate', // 'mmddyyyy', 'ddmmyyyy' or 'yyyymmdd' 101974 is: function(s) { 101975 // testing for ##-##-#### or ####-##-##, so it's not perfect; time can be included 101976 return (/(^\d{1,2}[\/\s]\d{1,2}[\/\s]\d{4})|(^\d{4}[\/\s]\d{1,2}[\/\s]\d{1,2})/).test((s || '').replace(/\s+/g, ' ').replace(/[\-.,]/g, '/')); 101977 }, 101978 format: function(s, table, cell, cellIndex) { 101979 if (s) { 101980 var date, d, 101981 c = table.config, 101982 ci = c.$headerIndexed[ cellIndex ], 101983 format = ci.length && ci[0].dateFormat || ts.getData( ci, ts.getColumnData( table, c.headers, cellIndex ), 'dateFormat') || c.dateFormat; 101984 d = s.replace(/\s+/g, ' ').replace(/[\-.,]/g, '/'); // escaped - because JSHint in Firefox was showing it as an error 101985 if (format === 'mmddyyyy') { 101986 d = d.replace(/(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{4})/, '$3/$1/$2'); 101987 } else if (format === 'ddmmyyyy') { 101988 d = d.replace(/(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{4})/, '$3/$2/$1'); 101989 } else if (format === 'yyyymmdd') { 101990 d = d.replace(/(\d{4})[\/\s](\d{1,2})[\/\s](\d{1,2})/, '$1/$2/$3'); 101991 } 101992 date = new Date(d); 101993 return date instanceof Date && isFinite(date) ? date.getTime() : s; 101994 } 101995 return s; 101996 }, 101997 type: 'numeric' 101998 }); 101999 102000 ts.addParser({ 102001 id: 'time', 102002 is: function(s) { 102003 return (/^(([0-2]?\d:[0-5]\d)|([0-1]?\d:[0-5]\d\s?([AP]M)))$/i).test(s); 102004 }, 102005 format: function(s, table) { 102006 var date = s ? new Date( '2000/01/01 ' + s.replace(/(\S)([AP]M)$/i, '$1 $2') ) : s; 102007 return date instanceof Date && isFinite(date) ? date.getTime() : s; 102008 }, 102009 type: 'numeric' 102010 }); 102011 102012 ts.addParser({ 102013 id: 'metadata', 102014 is: function() { 102015 return false;
102016 }, 102017 format: function(s, table, cell) { 102018 var c = table.config, 102019 p = (!c.parserMetadataName) ? 'sortValue' : c.parserMetadataName; 102020 return $(cell).metadata()[p]; 102021 }, 102022 type: 'numeric' 102023 }); 102024 102025 // add default widgets 102026 ts.addWidget({ 102027 id: 'zebra', 102028 priority: 90, 102029 format: function(table, c, wo) { 102030 var $tv, $tr, row, even, time, k, i, len, 102031 child = new RegExp(c.cssChildRow, 'i'), 102032 b = c.$tbodies.add( $( c.namespace + '_extra_table' ).children( 'tbody:not(.' + c.cssInfoBlock + ')' ) ); 102033 if (c.debug) { 102034 time = new Date(); 102035 } 102036 for (k = 0; k < b.length; k++ ) { 102037 // loop through the visible rows 102038 row = 0; 102039 $tv = b.eq( k ).children( 'tr:visible' ).not( c.selectorRemove ); 102040 len = $tv.length; 102041 for ( i = 0; i < len; i++ ) { 102042 $tr = $tv.eq( i ); 102043 // style child rows the same way the parent row was styled 102044 if ( !child.test( $tr[0].className ) ) { row++; } 102045 even = ( row % 2 === 0 ); 102046 $tr 102047 .removeClass( wo.zebra[ even ? 1 : 0 ] ) 102048 .addClass( wo.zebra[ even ? 0 : 1 ] ); 102049 } 102050 } 102051 }, 102052 remove: function(table, c, wo, refreshing){ 102053 if (refreshing) { return; } 102054 var k, $tb, 102055 b = c.$tbodies, 102056 rmv = (wo.zebra || [ 'even', 'odd' ]).join(' '); 102057 for (k = 0; k < b.length; k++ ){ 102058 $tb = ts.processTbody(table, b.eq(k), true); // remove tbody 102059 $tb.children().removeClass(rmv); 102060 ts.processTbody(table, $tb, false); // restore tbody 102061 } 102062 } 102063 }); 102064 102065})(jQuery); 102066 102067return $.tablesorter; 102068})); 102069 102070/** 102071 * @license text 2.0.16 Copyright jQuery Foundation and other contributors. 102072 * Released under MIT license, http://github.com/requirejs/text/LICENSE 102073 */ 102074/*jslint regexp: true */ 102075/*global require, XMLHttpRequest, ActiveXObject, 102076 define, window, process, Packages, 102077 java, location, Components, FileUtils */ 102078 102079define('text',['module'], function (module) { 102080 'use strict'; 102081 102082 var text, fs, Cc, Ci, xpcIsWindows, 102083 progIds = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'], 102084 xmlRegExp = /^\s*<\?xml(\s)+version=[\'\"](\d)*.(\d)*[\'\"](\s)*\?>/im, 102085 bodyRegExp = /<body[^>]*>\s*([\s\S]+)\s*<\/body>/im, 102086 hasLocation = typeof location !== 'undefined' && location.href, 102087 defaultProtocol = hasLocation && location.protocol && location.protocol.replace(/\:/, ''), 102088 defaultHostName = hasLocation && location.hostname, 102089 defaultPort = hasLocation && (location.port || undefined), 102090 buildMap = {}, 102091 masterConfig = (module.config && module.config()) || {}; 102092 102093 function useDefault(value, defaultValue) { 102094 return value === undefined || value === '' ? defaultValue : value; 102095 } 102096 102097 //Allow for default ports for http and https. 102098 function isSamePort(protocol1, port1, protocol2, port2) { 102099 if (port1 === port2) { 102100 return true; 102101 } else if (protocol1 === protocol2) { 102102 if (protocol1 === 'http') { 102103 return useDefault(port1, '80') === useDefault(port2, '80'); 102104 } else if (protocol1 === 'https') { 102105 return useDefault(port1, '443') === useDefault(port2, '443'); 102106 } 102107 } 102108 return false; 102109 } 102110 102111 text = { 102112 version: '2.0.16', 102113 102114 strip: function (content) { 102115 //Strips <?xml ...?> declarations so that external SVG and XML 102116 //documents can be added to a document without worry. Also, if the string 102117 //is an HTML document, only the part inside the body tag is returned. 102118 if (content) { 102119 content = content.replace(xmlRegExp, ""); 102120 var matches = content.match(bodyRegExp); 102121 if (matches) { 102122 content = matches[1]; 102123 } 102124 } else { 102125 content = ""; 102126 } 102127 return content; 102128 }, 102129 102130 jsEscape: function (content) { 102131 return content.replace(/(['\\])/g, '\\$1') 102132 .replace(/[\f]/g, "\\f") 102133 .replace(/[\b]/g, "\\b") 102134 .replace(/[\n]/g, "\\n") 102135 .replace(/[\t]/g, "\\t") 102136 .replace(/[\r]/g, "\\r") 102137 .replace(/[\u2028]/g, "\\u2028") 102138 .replace(/[\u2029]/g, "\\u2029"); 102139 }, 102140 102141 createXhr: masterConfig.createXhr || function () { 102142 //Would love to dump the ActiveX crap in here. Need IE 6 to die first. 102143 var xhr, i, progId; 102144 if (typeof XMLHttpRequest !== "undefined") { 102145 return new XMLHttpRequest(); 102146 } else if (typeof ActiveXObject !== "undefined") { 102147 for (i = 0; i < 3; i += 1) { 102148 progId = progIds[i]; 102149 try { 102150 xhr = new ActiveXObject(progId); 102151 } catch (e) {} 102152 102153 if (xhr) { 102154 progIds = [progId]; // so faster next time 102155 break; 102156 } 102157 } 102158 } 102159 102160 return xhr; 102161 }, 102162 102163 /**
vendor: 9,622 bytes, lines 102164-102405
102164 * Parses a resource name into its component parts. Resource names 102165 * look like: module/name.ext!strip, where the !strip part is 102166 * optional. 102167 * @param {String} name the resource name 102168 * @returns {Object} with properties "moduleName", "ext" and "strip" 102169 * where strip is a boolean. 102170 */ 102171 parseName: function (name) { 102172 var modName, ext, temp, 102173 strip = false, 102174 index = name.lastIndexOf("."), 102175 isRelative = name.indexOf('./') === 0 || 102176 name.indexOf('../') === 0; 102177 102178 if (index !== -1 && (!isRelative || index > 1)) { 102179 modName = name.substring(0, index); 102180 ext = name.substring(index + 1); 102181 } else { 102182 modName = name; 102183 } 102184 102185 temp = ext || modName; 102186 index = temp.indexOf("!"); 102187 if (index !== -1) { 102188 //Pull off the strip arg. 102189 strip = temp.substring(index + 1) === "strip"; 102190 temp = temp.substring(0, index); 102191 if (ext) { 102192 ext = temp; 102193 } else { 102194 modName = temp; 102195 } 102196 } 102197 102198 return { 102199 moduleName: modName, 102200 ext: ext, 102201 strip: strip 102202 }; 102203 }, 102204 102205 xdRegExp: /^((\w+)\:)?\/\/([^\/\\]+)/, 102206 102207 /** 102208 * Is an URL on another domain. Only works for browser use, returns 102209 * false in non-browser environments. Only used to know if an 102210 * optimized .js version of a text resource should be loaded 102211 * instead. 102212 * @param {String} url 102213 * @returns Boolean 102214 */ 102215 useXhr: function (url, protocol, hostname, port) { 102216 var uProtocol, uHostName, uPort, 102217 match = text.xdRegExp.exec(url); 102218 if (!match) { 102219 return true; 102220 } 102221 uProtocol = match[2]; 102222 uHostName = match[3]; 102223 102224 uHostName = uHostName.split(':'); 102225 uPort = uHostName[1]; 102226 uHostName = uHostName[0]; 102227 102228 return (!uProtocol || uProtocol === protocol) && 102229 (!uHostName || uHostName.toLowerCase() === hostname.toLowerCase()) && 102230 ((!uPort && !uHostName) || isSamePort(uProtocol, uPort, protocol, port)); 102231 }, 102232 102233 finishLoad: function (name, strip, content, onLoad) { 102234 content = strip ? text.strip(content) : content; 102235 if (masterConfig.isBuild) { 102236 buildMap[name] = content; 102237 } 102238 onLoad(content); 102239 }, 102240 102241 load: function (name, req, onLoad, config) { 102242 //Name has format: some.module.filext!strip 102243 //The strip part is optional. 102244 //if strip is present, then that means only get the string contents 102245 //inside a body tag in an HTML string. For XML/SVG content it means 102246 //removing the <?xml ...?> declarations so the content can be inserted 102247 //into the current doc without problems. 102248 102249 // Do not bother with the work if a build and text will 102250 // not be inlined. 102251 if (config && config.isBuild && !config.inlineText) { 102252 onLoad(); 102253 return; 102254 } 102255 102256 masterConfig.isBuild = config && config.isBuild; 102257 102258 var parsed = text.parseName(name), 102259 nonStripName = parsed.moduleName + 102260 (parsed.ext ? '.' + parsed.ext : ''), 102261 url = req.toUrl(nonStripName), 102262 useXhr = (masterConfig.useXhr) || 102263 text.useXhr; 102264 102265 // Do not load if it is an empty: url 102266 if (url.indexOf('empty:') === 0) { 102267 onLoad(); 102268 return; 102269 } 102270 102271 //Load the text. Use XHR if possible and in a browser. 102272 if (!hasLocation || useXhr(url, defaultProtocol, defaultHostName, defaultPort)) { 102273 text.get(url, function (content) { 102274 text.finishLoad(name, parsed.strip, content, onLoad); 102275 }, function (err) { 102276 if (onLoad.error) { 102277 onLoad.error(err); 102278 } 102279 }); 102280 } else { 102281 //Need to fetch the resource across domains. Assume 102282 //the resource has been optimized into a JS module. Fetch 102283 //by the module name + extension, but do not include the 102284 //!strip part to avoid file system issues. 102285 req([nonStripName], function (content) { 102286 text.finishLoad(parsed.moduleName + '.' + parsed.ext, 102287 parsed.strip, content, onLoad); 102288 }, function (err) { 102289 if (onLoad.error) { 102290 onLoad.error(err); 102291 } 102292 }); 102293 } 102294 }, 102295 102296 write: function (pluginName, moduleName, write, config) { 102297 if (buildMap.hasOwnProperty(moduleName)) { 102298 var content = text.jsEscape(buildMap[moduleName]); 102299 write.asModule(pluginName + "!" + moduleName, 102300 "define(function () { return '" + 102301 content + 102302 "';});\n"); 102303 } 102304 }, 102305 102306 writeFile: function (pluginName, moduleName, req, write, config) { 102307 var parsed = text.parseName(moduleName), 102308 extPart = parsed.ext ? '.' + parsed.ext : '', 102309 nonStripName = parsed.moduleName + extPart, 102310 //Use a '.js' file name so that it indicates it is a 102311 //script that can be loaded across domains. 102312 fileName = req.toUrl(parsed.moduleName + extPart) + '.js'; 102313 102314 //Leverage own load() method to load plugin value, but only 102315 //write out values that do not have the strip argument, 102316 //to avoid any potential issues with ! in file names. 102317 text.load(nonStripName, req, function (value) { 102318 //Use own write() method to construct full module value. 102319 //But need to create shell that translates writeFile's 102320 //write() to the right interface. 102321 var textWrite = function (contents) { 102322 return write(fileName, contents); 102323 }; 102324 textWrite.asModule = function (moduleName, contents) { 102325 return write.asModule(moduleName, fileName, contents); 102326 }; 102327 102328 text.write(pluginName, nonStripName, textWrite, config); 102329 }, config); 102330 } 102331 }; 102332 102333 if (masterConfig.env === 'node' || (!masterConfig.env && 102334 typeof process !== "undefined" && 102335 process.versions && 102336 !!process.versions.node && 102337 !process.versions['node-webkit'] && 102338 !process.versions['atom-shell'])) { 102339 //Using special require.nodeRequire, something added by r.js. 102340 fs = require.nodeRequire('fs'); 102341 102342 text.get = function (url, callback, errback) { 102343 try { 102344 var file = fs.readFileSync(url, 'utf8'); 102345 //Remove BOM (Byte Mark Order) from utf8 files if it is there. 102346 if (file[0] === '\uFEFF') { 102347 file = file.substring(1); 102348 } 102349 callback(file); 102350 } catch (e) { 102351 if (errback) { 102352 errback(e); 102353 } 102354 } 102355 }; 102356 } else if (masterConfig.env === 'xhr' || (!masterConfig.env && 102357 text.createXhr())) { 102358 text.get = function (url, callback, errback, headers) { 102359 var xhr = text.createXhr(), header; 102360 xhr.open('GET', url, true); 102361 102362 //Allow plugins direct access to xhr headers 102363 if (headers) { 102364 for (header in headers) { 102365 if (headers.hasOwnProperty(header)) { 102366 xhr.setRequestHeader(header.toLowerCase(), headers[header]); 102367 } 102368 } 102369 } 102370 102371 //Allow overrides specified in config 102372 if (masterConfig.onXhr) { 102373 masterConfig.onXhr(xhr, url); 102374 } 102375 102376 xhr.onreadystatechange = function (evt) { 102377 var status, err; 102378 //Do not explicitly handle errors, those should be 102379 //visible via console output in the browser. 102380 if (xhr.readyState === 4) { 102381 status = xhr.status || 0; 102382 if (status > 399 && status < 600) { 102383 //An http 4xx or 5xx error. Signal an error. 102384 err = new Error(url + ' HTTP status: ' + status); 102385 err.xhr = xhr; 102386 if (errback) { 102387 errback(err); 102388 } 102389 } else { 102390 callback(xhr.responseText); 102391 } 102392 102393 if (masterConfig.onXhrComplete) { 102394 masterConfig.onXhrComplete(xhr, url); 102395 } 102396 } 102397 }; 102398 xhr.send(null); 102399 }; 102400 } else if (masterConfig.env === 'rhino' || (!masterConfig.env && 102401 typeof Packages !== 'undefined' && typeof java !== 'undefined')) { 102402 //Why Java, why is this so awkward? 102403 text.get = function (url, callback) { 102404 var stringBuffer, line, 102405 encoding = "utf-8",
102406 file = new java.io.File(url), 102407 lineSeparator = java.lang.System.getProperty("line.separator"), 102408 input = new java.io.BufferedReader(new java.io.InputStreamReader(new java.io.FileInputStream(file), encoding)), 102409 content = ''; 102410 try { 102411 stringBuffer = new java.lang.StringBuffer(); 102412 line = input.readLine(); 102413 102414 // Byte Order Mark (BOM) - The Unicode Standard, version 3.0, page 324 102415 // http://www.unicode.org/faq/utf_bom.html 102416 102417 // Note that when we use utf-8, the BOM should appear as "EF BB BF", but it doesn't due to this bug in the JDK: 102418 // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4508058 102419 if (line && line.length() && line.charAt(0) === 0xfeff) { 102420 // Eat the BOM, since we've already found the encoding on this file, 102421 // and we plan to concatenating this buffer with others; the BOM should 102422 // only appear at the top of a file. 102423 line = line.substring(1); 102424 } 102425 102426 if (line !== null) { 102427 stringBuffer.append(line); 102428 } 102429 102430 while ((line = input.readLine()) !== null) { 102431 stringBuffer.append(lineSeparator); 102432 stringBuffer.append(line); 102433 } 102434 //Make sure we return a JavaScript string and not a Java string. 102435 content = String(stringBuffer.toString()); //String 102436 } finally { 102437 input.close(); 102438 } 102439 callback(content); 102440 }; 102441 } else if (masterConfig.env === 'xpconnect' || (!masterConfig.env && 102442 typeof Components !== 'undefined' && Components.classes && 102443 Components.interfaces)) { 102444 //Avert your gaze! 102445 Cc = Components.classes; 102446 Ci = Components.interfaces; 102447 Components.utils['import']('resource://gre/modules/FileUtils.jsm'); 102448 xpcIsWindows = ('@mozilla.org/windows-registry-key;1' in Cc); 102449 102450 text.get = function (url, callback) { 102451 var inStream, convertStream, fileObj, 102452 readData = {}; 102453 102454 if (xpcIsWindows) { 102455 url = url.replace(/\//g, '\\'); 102456 } 102457 102458 fileObj = new FileUtils.File(url); 102459 102460 //XPCOM, you so crazy 102461 try { 102462 inStream = Cc['@mozilla.org/network/file-input-stream;1'] 102463 .createInstance(Ci.nsIFileInputStream); 102464 inStream.init(fileObj, 1, 0, false); 102465 102466 convertStream = Cc['@mozilla.org/intl/converter-input-stream;1'] 102467 .createInstance(Ci.nsIConverterInputStream); 102468 convertStream.init(inStream, "utf-8", inStream.available(), 102469 Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER); 102470 102471 convertStream.readString(inStream.available(), readData); 102472 convertStream.close(); 102473 inStream.close(); 102474 callback(readData.value); 102475 } catch (e) { 102476 throw new Error((fileObj && fileObj.path || '') + ': ' + e); 102477 } 102478 }; 102479 } 102480 return text; 102481}); 102482 102483/* 102484 * JavaScript Templates 102485 * https://github.com/blueimp/JavaScript-Templates 102486 * 102487 * Copyright 2011, Sebastian Tschan 102488 * https://blueimp.net 102489 * 102490 * Licensed under the MIT license: 102491 * https://opensource.org/licenses/MIT 102492 * 102493 * Inspired by John Resig's JavaScript Micro-Templating: 102494 * http://ejohn.org/blog/javascript-micro-templating/ 102495 */ 102496 102497/* global define */ 102498 102499/* eslint-disable strict */ 102500 102501;(function ($) { 102502 'use strict' 102503 var tmpl = function (str, data) { 102504 var f = !/[^\w\-.:]/.test(str) 102505 ? (tmpl.cache[str] = tmpl.cache[str] || tmpl(tmpl.load(str))) 102506 : new Function( // eslint-disable-line no-new-func 102507 tmpl.arg + ',tmpl', 102508 'var _e=tmpl.encode' + 102509 tmpl.helper + 102510 ",_s='" + 102511 str.replace(tmpl.regexp, tmpl.func) + 102512 "';return _s;" 102513 ) 102514 return data 102515 ? f(data, tmpl) 102516 : function (data) { 102517 return f(data, tmpl) 102518 } 102519 } 102520 tmpl.cache = {} 102521 tmpl.load = function (id) { 102522 return document.getElementById(id).innerHTML 102523 } 102524 tmpl.regexp = 102525 /([\s'\\])(?!(?:[^{]|\{(?!%))*%\})|(?:\{%(=|#)([\s\S]+?)%\})|(\{%)|(%\})/g 102526 tmpl.func = function (s, p1, p2, p3, p4, p5) { 102527 if (p1) { 102528 // whitespace, quote and backspace in HTML context 102529 return ( 102530 { 102531 '\n': '\\n', 102532 '\r': '\\r', 102533 '\t': '\\t', 102534 ' ': ' ' 102535 }[p1] || '\\' + p1 102536 ) 102537 } 102538 if (p2) { 102539 // interpolation: {%=prop%}, or unescaped: {%#prop%} 102540 if (p2 === '=') { 102541 return "'+_e(" + p3 + ")+'" 102542 } 102543 return "'+(" + p3 + "==null?'':" + p3 + ")+'" 102544 } 102545 if (p4) { 102546 // evaluation start tag: {% 102547 return "';" 102548 } 102549 if (p5) { 102550 // evaluation end tag: %} 102551 return "_s+='" 102552 } 102553 } 102554 tmpl.encReg = /[<>&"'\x00]/g // eslint-disable-line no-control-regex 102555 tmpl.encMap = { 102556 '<': '<', 102557 '>': '>', 102558 '&': '&', 102559 '"': '"', 102560 "'": ''' 102561 } 102562 tmpl.encode = function (s) { 102563 // eslint-disable-next-line eqeqeq 102564 return (s == null ? '' : '' + s).replace(tmpl.encReg, function (c) { 102565 return tmpl.encMap[c] || '' 102566 }) 102567 } 102568 tmpl.arg = 'o' 102569 tmpl.helper = 102570 ",print=function(s,e){_s+=e?(s==null?'':s):_e(s);}" + 102571 ',include=function(s,d){_s+=tmpl(s,d);}' 102572 if (typeof define === 'function' && define.amd) { 102573 define('tmpl',[],function () { 102574 return tmpl 102575 }) 102576 } else if (typeof module === 'object' && module.exports) { 102577 module.exports = tmpl 102578 } else { 102579 $.tmpl = tmpl 102580 } 102581})(this) 102582; 102583/* 102584 * Toastr 102585 * Copyright 2012-2015 102586 * Authors: John Papa, Hans Fjällemark, and Tim Ferrell. 102587 * All Rights Reserved. 102588 * Use, reproduction, distribution, and modification of this code is subject to the terms and 102589 * conditions of the MIT license, available at http://www.opensource.org/licenses/mit-license.php 102590 * 102591 * ARIA Support: Greta Krafsig 102592 * 102593 * Project: https://github.com/CodeSeven/toastr 102594 */ 102595/* global define */ 102596(function (define) { 102597 define('toastr',['jquery'], function ($) { 102598 return (function () { 102599 var $container; 102600 var listener; 102601 var toastId = 0; 102602 var toastType = { 102603 error: 'error', 102604 info: 'info', 102605 success: 'success', 102606 warning: 'warning' 102607 }; 102608 102609 var toastr = { 102610 clear: clear, 102611 remove: remove, 102612 error: error, 102613 getContainer: getContainer, 102614 info: info,
102615 options: {}, 102616 subscribe: subscribe, 102617 success: success, 102618 version: '2.1.3
vendor: 16,635 bytes, lines 102618-103058
102618', 102619 warning: warning 102620 }; 102621 102622 var previousToast; 102623 102624 return toastr; 102625 102626 //////////////// 102627 102628 function error(message, title, optionsOverride) { 102629 return notify({ 102630 type: toastType.error, 102631 iconClass: getOptions().iconClasses.error, 102632 message: message, 102633 optionsOverride: optionsOverride, 102634 title: title 102635 }); 102636 } 102637 102638 function getContainer(options, create) { 102639 if (!options) { options = getOptions(); } 102640 $container = $('#' + options.containerId); 102641 if ($container.length) { 102642 return $container; 102643 } 102644 if (create) { 102645 $container = createContainer(options); 102646 } 102647 return $container; 102648 } 102649 102650 function info(message, title, optionsOverride) { 102651 return notify({ 102652 type: toastType.info, 102653 iconClass: getOptions().iconClasses.info, 102654 message: message, 102655 optionsOverride: optionsOverride, 102656 title: title 102657 }); 102658 } 102659 102660 function subscribe(callback) { 102661 listener = callback; 102662 } 102663 102664 function success(message, title, optionsOverride) { 102665 return notify({ 102666 type: toastType.success, 102667 iconClass: getOptions().iconClasses.success, 102668 message: message, 102669 optionsOverride: optionsOverride, 102670 title: title 102671 }); 102672 } 102673 102674 function warning(message, title, optionsOverride) { 102675 return notify({ 102676 type: toastType.warning, 102677 iconClass: getOptions().iconClasses.warning, 102678 message: message, 102679 optionsOverride: optionsOverride, 102680 title: title 102681 }); 102682 } 102683 102684 function clear($toastElement, clearOptions) { 102685 var options = getOptions(); 102686 if (!$container) { getContainer(options); } 102687 if (!clearToast($toastElement, options, clearOptions)) { 102688 clearContainer(options); 102689 } 102690 } 102691 102692 function remove($toastElement) { 102693 var options = getOptions(); 102694 if (!$container) { getContainer(options); } 102695 if ($toastElement && $(':focus', $toastElement).length === 0) { 102696 removeToast($toastElement); 102697 return; 102698 } 102699 if ($container.children().length) { 102700 $container.remove(); 102701 } 102702 } 102703 102704 // internal functions 102705 102706 function clearContainer (options) { 102707 var toastsToClear = $container.children(); 102708 for (var i = toastsToClear.length - 1; i >= 0; i--) { 102709 clearToast($(toastsToClear[i]), options); 102710 } 102711 } 102712 102713 function clearToast ($toastElement, options, clearOptions) { 102714 var force = clearOptions && clearOptions.force ? clearOptions.force : false; 102715 if ($toastElement && (force || $(':focus', $toastElement).length === 0)) { 102716 $toastElement[options.hideMethod]({ 102717 duration: options.hideDuration, 102718 easing: options.hideEasing, 102719 complete: function () { removeToast($toastElement); } 102720 }); 102721 return true; 102722 } 102723 return false; 102724 } 102725 102726 function createContainer(options) { 102727 $container = $('<div/>') 102728 .attr('id', options.containerId) 102729 .addClass(options.positionClass); 102730 102731 $container.appendTo($(options.target)); 102732 return $container; 102733 } 102734 102735 function getDefaults() { 102736 return { 102737 tapToDismiss: true, 102738 toastClass: 'toast', 102739 containerId: 'toast-container', 102740 debug: false, 102741 102742 showMethod: 'fadeIn', //fadeIn, slideDown, and show are built into jQuery 102743 showDuration: 300, 102744 showEasing: 'swing', //swing and linear are built into jQuery 102745 onShown: undefined, 102746 hideMethod: 'fadeOut', 102747 hideDuration: 1000, 102748 hideEasing: 'swing', 102749 onHidden: undefined, 102750 closeMethod: false, 102751 closeDuration: false, 102752 closeEasing: false, 102753 closeOnHover: true, 102754 102755 extendedTimeOut: 1000, 102756 iconClasses: { 102757 error: 'toast-error', 102758 info: 'toast-info', 102759 success: 'toast-success', 102760 warning: 'toast-warning' 102761 }, 102762 iconClass: 'toast-info', 102763 positionClass: 'toast-top-right', 102764 timeOut: 5000, // Set timeOut and extendedTimeOut to 0 to make it sticky 102765 titleClass: 'toast-title', 102766 messageClass: 'toast-message', 102767 escapeHtml: false, 102768 target: 'body', 102769 closeHtml: '<button type="button">×</button>', 102770 closeClass: 'toast-close-button', 102771 newestOnTop: true, 102772 preventDuplicates: false, 102773 progressBar: false, 102774 progressClass: 'toast-progress', 102775 rtl: false 102776 }; 102777 } 102778 102779 function publish(args) { 102780 if (!listener) { return; } 102781 listener(args); 102782 } 102783 102784 function notify(map) { 102785 var options = getOptions(); 102786 var iconClass = map.iconClass || options.iconClass; 102787 102788 if (typeof (map.optionsOverride) !== 'undefined') { 102789 options = $.extend(options, map.optionsOverride); 102790 iconClass = map.optionsOverride.iconClass || iconClass; 102791 } 102792 102793 if (shouldExit(options, map)) { return; } 102794 102795 toastId++; 102796 102797 $container = getContainer(options, true); 102798 102799 var intervalId = null; 102800 var $toastElement = $('<div/>'); 102801 var $titleElement = $('<div/>'); 102802 var $messageElement = $('<div/>'); 102803 var $progressElement = $('<div/>'); 102804 var $closeElement = $(options.closeHtml); 102805 var progressBar = { 102806 intervalId: null, 102807 hideEta: null, 102808 maxHideTime: null 102809 }; 102810 var response = { 102811 toastId: toastId, 102812 state: 'visible', 102813 startTime: new Date(), 102814 options: options, 102815 map: map 102816 }; 102817 102818 personalizeToast(); 102819 102820 displayToast(); 102821 102822 handleEvents(); 102823 102824 publish(response); 102825 102826 if (options.debug && console) { 102827 console.log(response); 102828 } 102829 102830 return $toastElement; 102831 102832 function escapeHtml(source) { 102833 if (source == null) { 102834 source = ''; 102835 } 102836 102837 return source 102838 .replace(/&/g, '&') 102839 .replace(/"/g, '"') 102840 .replace(/'/g, ''') 102841 .replace(/</g, '<') 102842 .replace(/>/g, '>'); 102843 } 102844 102845 function personalizeToast() { 102846 setIcon(); 102847 setTitle(); 102848 setMessage(); 102849 setCloseButton(); 102850 setProgressBar(); 102851 setRTL(); 102852 setSequence(); 102853 setAria(); 102854 } 102855 102856 function setAria() { 102857 var ariaValue = ''; 102858 switch (map.iconClass) { 102859 case 'toast-success': 102860 case 'toast-info': 102861 ariaValue = 'polite'; 102862 break; 102863 default: 102864 ariaValue = 'assertive'; 102865 } 102866 $toastElement.attr('aria-live', ariaValue); 102867 } 102868 102869 function handleEvents() { 102870 if (options.closeOnHover) { 102871 $toastElement.hover(stickAround, delayedHideToast); 102872 } 102873 102874 if (!options.onclick && options.tapToDismiss) { 102875 $toastElement.click(hideToast); 102876 } 102877 102878 if (options.closeButton && $closeElement) { 102879 $closeElement.click(function (event) { 102880 if (event.stopPropagation) { 102881 event.stopPropagation(); 102882 } else if (event.cancelBubble !== undefined && event.cancelBubble !== true) { 102883 event.cancelBubble = true; 102884 } 102885 102886 if (options.onCloseClick) { 102887 options.onCloseClick(event); 102888 } 102889 102890 hideToast(true); 102891 }); 102892 } 102893 102894 if (options.onclick) { 102895 $toastElement.click(function (event) { 102896 options.onclick(event); 102897 hideToast(); 102898 }); 102899 } 102900 } 102901 102902 function displayToast() { 102903 $toastElement.hide(); 102904 102905 $toastElement[options.showMethod]( 102906 {duration: options.showDuration, easing: options.showEasing, complete: options.onShown} 102907 ); 102908 102909 if (options.timeOut > 0) { 102910 intervalId = setTimeout(hideToast, options.timeOut); 102911 progressBar.maxHideTime = parseFloat(options.timeOut); 102912 progressBar.hideEta = new Date().getTime() + progressBar.maxHideTime; 102913 if (options.progressBar) { 102914 progressBar.intervalId = setInterval(updateProgress, 10); 102915 } 102916 } 102917 } 102918 102919 function setIcon() { 102920 if (map.iconClass) { 102921 $toastElement.addClass(options.toastClass).addClass(iconClass); 102922 } 102923 } 102924 102925 function setSequence() { 102926 if (options.newestOnTop) { 102927 $container.prepend($toastElement); 102928 } else { 102929 $container.append($toastElement); 102930 } 102931 } 102932 102933 function setTitle() { 102934 if (map.title) { 102935 var suffix = map.title; 102936 if (options.escapeHtml) { 102937 suffix = escapeHtml(map.title); 102938 } 102939 $titleElement.append(suffix).addClass(options.titleClass); 102940 $toastElement.append($titleElement); 102941 } 102942 } 102943 102944 function setMessage() { 102945 if (map.message) { 102946 var suffix = map.message; 102947 if (options.escapeHtml) { 102948 suffix = escapeHtml(map.message); 102949 } 102950 $messageElement.append(suffix).addClass(options.messageClass); 102951 $toastElement.append($messageElement); 102952 } 102953 } 102954 102955 function setCloseButton() { 102956 if (options.closeButton) { 102957 $closeElement.addClass(options.closeClass).attr('role', 'button'); 102958 $toastElement.prepend($closeElement); 102959 } 102960 } 102961 102962 function setProgressBar() { 102963 if (options.progressBar) { 102964 $progressElement.addClass(options.progressClass); 102965 $toastElement.prepend($progressElement); 102966 } 102967 } 102968 102969 function setRTL() { 102970 if (options.rtl) { 102971 $toastElement.addClass('rtl'); 102972 } 102973 } 102974 102975 function shouldExit(options, map) { 102976 if (options.preventDuplicates) { 102977 if (map.message === previousToast) { 102978 return true; 102979 } else { 102980 previousToast = map.message; 102981 } 102982 } 102983 return false; 102984 } 102985 102986 function hideToast(override) { 102987 var method = override && options.closeMethod !== false ? options.closeMethod : options.hideMethod; 102988 var duration = override && options.closeDuration !== false ? 102989 options.closeDuration : options.hideDuration; 102990 var easing = override && options.closeEasing !== false ? options.closeEasing : options.hideEasing; 102991 if ($(':focus', $toastElement).length && !override) { 102992 return; 102993 } 102994 clearTimeout(progressBar.intervalId); 102995 return $toastElement[method]({ 102996 duration: duration, 102997 easing: easing, 102998 complete: function () { 102999 removeToast($toastElement); 103000 clearTimeout(intervalId); 103001 if (options.onHidden && response.state !== 'hidden') { 103002 options.onHidden(); 103003 } 103004 response.state = 'hidden'; 103005 response.endTime = new Date(); 103006 publish(response); 103007 } 103008 }); 103009 } 103010 103011 function delayedHideToast() { 103012 if (options.timeOut > 0 || options.extendedTimeOut > 0) { 103013 intervalId = setTimeout(hideToast, options.extendedTimeOut); 103014 progressBar.maxHideTime = parseFloat(options.extendedTimeOut); 103015 progressBar.hideEta = new Date().getTime() + progressBar.maxHideTime; 103016 } 103017 } 103018 103019 function stickAround() { 103020 clearTimeout(intervalId); 103021 progressBar.hideEta = 0; 103022 $toastElement.stop(true, true)[options.showMethod]( 103023 {duration: options.showDuration, easing: options.showEasing} 103024 ); 103025 } 103026 103027 function updateProgress() { 103028 var percentage = ((progressBar.hideEta - (new Date().getTime())) / progressBar.maxHideTime) * 100; 103029 $progressElement.width(percentage + '%'); 103030 } 103031 } 103032 103033 function getOptions() { 103034 return $.extend({}, getDefaults(), toastr.options); 103035 } 103036 103037 function removeToast($toastElement) { 103038 if (!$container) { $container = getContainer(); } 103039 if ($toastElement.is(':visible')) { 103040 return; 103041 } 103042 $toastElement.remove(); 103043 $toastElement = null; 103044 if ($container.children().length === 0) { 103045 $container.remove(); 103046 previousToast = undefined; 103047 } 103048 } 103049 103050 })(); 103051 }); 103052}(typeof define === 'function' && define.amd ? define : function (deps, factory) { 103053 if (typeof module !== 'undefined' && module.exports) { //Node 103054 module.exports = factory(require('jquery')); 103055 } else { 103056 window.toastr = factory(window.jQuery); 103057 } 103058}));
103059 103060(function ($) { 103061 $.fn.uniformHeight = function () { 103062 var maxHeight = 0, 103063 wrapper, 103064 wrapperHeight; 103065 103066 return this.each(function () { 103067 103068 // TODO Doesn't take account of image scaling when in bootstrap thumbnails. 103069 // For example when you use very large images and use this plugin it 103070 // incorrectly calculates the height as very large large. This is probably 103071 // because it prevents the styles getting to the image to make it 103072 // max-width: 100%. 103073 103074 // Applying a wrapper to the contents of the current element to get reliable height 103075 wrapper = $(this).wrapInner('<div class="wrapper" />').children('.wrapper'); 103076 wrapperHeight = wrapper.outerHeight(); 103077 103078 maxHeight = Math.max(maxHeight, wrapperHeight); 103079 103080 // Remove the wrapper 103081 wrapper.children().unwrap(); 103082 103083 }).height(maxHeight); 103084 } 103085})(jQuery); 103086 103087define("uniformHeight", ["jquery"], (function (global) { 103088 return function () { 103089 var ret, fn; 103090 return ret || global.$; 103091 }; 103092}(this))); 103093 103094define('userHeartBeat',[], 103095 function () { 103096 return { 103097 heartbeat: function (token, userId, apiUrl) { 103098 if (!token || !userId || !apiUrl) { 103099 console.warn('invalid token || userId || apiUrl supplied!'); 103100 return; 103101 } 103102 103103 try { 103104 var key = `heartbeat-${userId}`; 103105 var seconds = 300 103106 var isSending = true; 103107 var now = new Date(); 103108 var lastHeartBeat = sessionStorage.getItem(key); 103109 103110 if (lastHeartBeat !== null) { 103111 var dateLastLogged = new Date(lastHeartBeat); 103112 var secondsSinceLastLogged = (now.getTime() - dateLastLogged.getTime()) / 1000; 103113 console.warn('Last hearbeat found', dateLastLogged, now, secondsSinceLastLogged); 103114 isSending = secondsSinceLastLogged > seconds; 103115 } 103116 103117 if (!isSending) return; 103118 103119 console.warn('Sending heartbeat...'); 103120 103121 sessionStorage.setItem(key, now.toISOString()); 103122 103123 var apiUri = `${apiUrl}/v3/users/${userId}/heartbeat`; 103124 var httpRequest = new XMLHttpRequest(); 103125 httpRequest.open('POST', apiUri); 103126 103127 httpRequest.setRequestHeader("Content-Type", "application/json;charset=UTF-8"); 103128 httpRequest.setRequestHeader("Authorization", "Bearer " + token); 103129 103130 httpRequest.send(JSON.stringify({ 103131 source: 'DiagnosticQuestions' 103132 })); 103133 } catch (e) { 103134 console.error(e); 103135 } 103136 } 103137 } 103138 }); 103139 103140//# sourceMappingURL=vendor-bundle.js.c0933e4a.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.