1<!DOCTYPE html> 2<html> 3<head> 4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> 5
5<script type="application/shiny-singletons"></script>
5 6
6<script type="application/html-dependencies">json2[2014.02.04];jquery[3.5.1];shiny[1.4.0.2];selectize[0.11.2];htmlwidgets[1.5.4];datatables-css[0.0.0];datatables-binding[0.13];crosstalk[1.2.0];bootstrap[3.4.1]</script>
vendor: 1 bytes, line 6
6
7<script src="shared/json2-min.js"></script>
vendor: 1 bytes, line 7
7
8<script src="jquery-3.5.1/jquery.min.js"></script>
8 9<link href="shared/shiny.css" rel="stylesheet" />
10<script src="shared/shiny.min.js"></script>
10 11<link href="shared/selectize/css/selectize.bootstrap3.css" rel="stylesheet" /> 12<!--[if lt IE 9]>
13<script src="shared/selectize/js/es5-shim.min.js"></script>
13 14<![endif]-->
15<script src="shared/selectize/js/selectize.min.js"></script>
vendor: 1 bytes, line 15
15
16<script src="htmlwidgets-1.5.4/htmlwidgets.js"></script>
16 17<link href="datatables-css-0.0.0/datatables-crosstalk.css" rel="stylesheet" />
18<script src="datatables-binding-0.13/datatables.js"></script>
18 19<link href="crosstalk-1.2.0/css/crosstalk.min.css" rel="stylesheet" />
20<script src="crosstalk-1.2.0/js/crosstalk.min.js"></script>
20 21<meta name="viewport" content="width=device-width, initial-scale=1" /> 22<link href="shared/bootstrap/css/bootstrap.min.css" rel="stylesheet" />
23<script src="shared/bootstrap/js/bootstrap.min.js"></script>
vendor: 1 bytes, line 23
23
24<script src="shared/bootstrap/shim/html5shiv.min.js"></script>
vendor: 1 bytes, line 24
24
25<script src="shared/bootstrap/shim/respond.min.js"></script>
25 <link rel="stylesheet" type="text/css" href="bootstrap.min.css"/> 26 <title>C. elegans CRISPR-Cas9 library</title>
27<script src="__assets__/sockjs-0.3.4.min.js"></script>
vendor: 1 bytes, line 27
27
28<script src="__assets__/shiny-server-client.min.js"></script>
vendor: 1 bytes, line 28
28
29<script>preShinyInit({reconnect:true,disableProtocols:[]});</script>
29 30<link rel="stylesheet" type="text/css" href="__assets__/shiny-server.css"/> 31 32</head> 33<body> 34 <div class="container-fluid"> 35 <style type="text/css">.js-irs-none .irs-single, .js-irs-none .irs-bar-edge, .js-irs-none .irs-bar { 36 background: transparent; 37 border-top-color: transparent; 38 border-bottom-color: transparent; 39 border-left-color: transparent; 40 border-right-color: transparent} 41 .navbar-default .navbar-brand:hover {color: #ffffff;} 42 </style> 43
43<script> 44 Shiny.addCustomMessageHandler('igvstat-change', function(panel) { 45 igv.visibilityChange() 46 }); 47 </script>
47 48
48<script> 49 Shiny.addCustomMessageHandler("downloadApe64", function(params) { 50 var namas = params[0]; 51 var b64 = params[1]; 52 const a = document.createElement("a"); 53 document.body.append(a); 54 //a.download = "oligo.gb"; 55 //a.download = b64.mime; 56 a.download = namas; 57 a.href = b64; 58 a.click(); 59 a.remove(); 60 }); 61 </script>
61 62 <nav class="navbar navbar-default navbar-static-top" role="navigation"> 63 <div class="container-fluid"> 64 <div class="navbar-header"> 65 <span class="navbar-brand"> 66 <a id="link_to_tabpanel_title" href="#" class="action-button"><b><i>C. elegans</i> CRISPR-Cas9 library</b></a> 67 </span> 68 </div> 69 <ul class="nav navbar-nav shiny-tab-input" id="panels" data-tabsetid="3862"> 70 <li class="active"> 71 <a href="#tab-3862-1" data-toggle="tab" data-value="Query">Query</a> 72 </li> 73 <li> 74 <a href="#tab-3862-2" data-toggle="tab" data-value="Browse">Browse</a> 75 </li> 76 <li> 77 <a href="#tab-3862-3" data-toggle="tab" data-value="Basket">Basket</a> 78 </li> 79 <li> 80 <a href="#tab-3862-4" data-toggle="tab" data-value="Downloads">Downloads</a> 81 </li> 82 <li> 83 <a href="#tab-3862-5" data-toggle="tab" data-value="About">About</a> 84 </li> 85 </ul> 86 </div> 87 </nav> 88 <div class="container-fluid"> 89 <div class="tab-content" data-tabsetid="3862"> 90 <div class="tab-pane active" data-value="Query" id="tab-3862-1"> 91 <div class="row"> 92 <h2>Search for gene targets</h2> 93 <div class="tab-pane span7" data-value="Gene search" title="Gene search"> 94 <br/> 95 <div class="form-group shiny-input-container"> 96 <label class="control-label" for="MultipleGeness">List of genes</label> 97 <textarea id="MultipleGeness" class="form-control" placeholder="Wormbase IDs, transcript or gene names separated by newlines or commas" style="width: 600px; " rows="5" cols="100"></textarea> 98 </div> 99 <div class="form-group shiny-input-container"> 100 <label class="control-label" for="crRNA_multiplegenes_type"><b>Type (location)</b></label> 101 <div> 102 <select id="crRNA_multiplegenes_type"><option value="All">All</option> 103<option value="500 bp promoter">500 bp promoter</option> 104<option value="250 bp promoter">250 bp promoter</option> 105<option value="ATG">ATG</option> 106<option value="CDS">CDS</option> 107<option value="Stop">Stop</option></select> 108
108<script type="application/json" data-for="crRNA_multiplegenes_type" data-nonempty="">{}</script>
108 109 </div> 110 </div> 111 <button id="actionmultiplesearch" type="button" class="btn btn-default action-button">Search</button> 112 <hr/> 113 <pre id="ErrorMessageMultiple" class="shiny-text-output noplaceholder"></pre> 114 <div id="crRNAMultipleTab" style="width:100%; height:auto; " class="datatables html-widget html-widget-output"></div> 115 <div id="MultipleExtraoui" class="shiny-html-output"></div> 116 </div> 117 </div> 118 </div> 119 <div class="tab-pane" data-value="Browse" id="tab-3862-2"> 120 <div class="row"> 121 <h3>Browse your favorite location</h3> 122
122<script>(function (global, factory) { 123 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : 124 typeof define === 'function' && define.amd ? define(factory) : 125 (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.igv = factory()); 126})(this, (function () { 'use strict'; 127 128 /*! 129 * jQuery JavaScript Library v3.3.1 -ajax,-ajax/jsonp,-ajax/load,-ajax/parseXML,-ajax/script,-ajax/var/location,-ajax/var/nonce,-ajax/var/rquery,-ajax/xhr,-manipulation/_evalUrl,-event/ajax,-effects,-effects/Tween,-effects/animatedSelector 130 * https://jquery.com/ 131 * 132 * Includes Sizzle.js 133 * https://sizzlejs.com/ 134 * 135 * Copyright JS Foundation and other contributors 136 * Released under the MIT license 137 * https://jquery.org/license 138 * 139 * Date: 2018-01-20T17:24Z 140 */ 141 142 var arr = []; 143 var document$2 = window.document; 144 var getProto = Object.getPrototypeOf; 145 var slice = arr.slice; 146 var concat$1 = arr.concat; 147 var push$1 = arr.push; 148 var indexOf$1 = arr.indexOf; 149 var class2type = {}; 150 var toString$3 = class2type.toString; 151 var hasOwn = class2type.hasOwnProperty; 152 var fnToString = hasOwn.toString; 153 var ObjectFunctionString = fnToString.call(Object); 154 var support = {}; 155 156 var isFunction = function isFunction(obj) { 157 // Support: Chrome <=57, Firefox <=52 158 // In some browsers, typeof returns "function" for HTML <object> elements 159 // (i.e., `typeof document.createElement( "object" ) === "function"`). 160 // We don't want to classify *any* DOM node as a function. 161 return typeof obj === "function" && typeof obj.nodeType !== "number"; 162 }; 163 164 var isWindow = function isWindow(obj) { 165 return obj != null && obj === obj.window; 166 }; 167 168 var preservedScriptAttributes = { 169 type: true, 170 src: true, 171 noModule: true 172 }; 173 174 function DOMEval(code, doc, node) { 175 doc = doc || document$2; 176 var i, 177 script = doc.createElement("script"); 178 script.text = code; 179 180 if (node) { 181 for (i in preservedScriptAttributes) { 182 if (node[i]) { 183 script[i] = node[i]; 184 } 185 } 186 } 187 188 doc.head.appendChild(script).parentNode.removeChild(script); 189 } 190 191 function toType(obj) { 192 if (obj == null) { 193 return obj + ""; 194 } // Support: Android <=2.3 only (functionish RegExp) 195 196 197 return typeof obj === "object" || typeof obj === "function" ? class2type[toString$3.call(obj)] || "object" : typeof obj; 198 } // global Symbol 199 // Defining this global in .eslintrc.json would create a danger of using the global 200 // unguarded in another place, it seems safer to define global only for this module 201 202 203 var version$2 = "3.3.1 -ajax,-ajax/jsonp,-ajax/load,-ajax/parseXML,-ajax/script,-ajax/var/location,-ajax/var/nonce,-ajax/var/rquery,-ajax/xhr,-manipulation/_evalUrl,-event/ajax,-effects,-effects/Tween,-effects/animatedSelector", 204 // Define a local copy of jQuery 205 jQuery = function (selector, context) { 206 // The jQuery object is actually just the init constructor 'enhanced' 207 // Need init if jQuery is called (just allow error to be thrown if not included) 208 return new jQuery.fn.init(selector, context); 209 }, 210 // Support: Android <=4.0 only 211 // Make sure we trim BOM and NBSP 212 rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g; 213 214 jQuery.fn = jQuery.prototype = { 215 // The current version of jQuery being used 216 jquery: version$2, 217 constructor: jQuery, 218 // The default length of a jQuery object is 0 219 length: 0, 220 toArray: function () { 221 return slice.call(this); 222 }, 223 // Get the Nth element in the matched element set OR 224 // Get the whole matched element set as a clean array 225 get: function (num) { 226 // Return all the elements in a clean array 227 if (num == null) { 228 return slice.call(this); 229 } // Return just the one element from the set 230 231 232 return num < 0 ? this[num + this.length] : this[num]; 233 }, 234 // Take an array of elements and push it onto the stack 235 // (returning the new matched element set) 236 pushStack: function (elems) { 237 // Build a new jQuery matched element set 238 var ret = jQuery.merge(this.constructor(), elems); // Add the old object onto the stack (as a reference) 239
vendor: 13,225 bytes, lines 240-633
240 ret.prevObject = this; // Return the newly-formed element set 241 242 return ret; 243 }, 244 // Execute a callback for every element in the matched set. 245 each: function (callback) { 246 return jQuery.each(this, callback); 247 }, 248 map: function (callback) { 249 return this.pushStack(jQuery.map(this, function (elem, i) { 250 return callback.call(elem, i, elem); 251 })); 252 }, 253 slice: function () { 254 return this.pushStack(slice.apply(this, arguments)); 255 }, 256 first: function () { 257 return this.eq(0); 258 }, 259 last: function () { 260 return this.eq(-1); 261 }, 262 eq: function (i) { 263 var len = this.length, 264 j = +i + (i < 0 ? len : 0); 265 return this.pushStack(j >= 0 && j < len ? [this[j]] : []); 266 }, 267 end: function () { 268 return this.prevObject || this.constructor(); 269 }, 270 // For internal use only. 271 // Behaves like an Array's method, not like a jQuery method. 272 push: push$1, 273 sort: arr.sort, 274 splice: arr.splice 275 }; 276 277 jQuery.extend = jQuery.fn.extend = function () { 278 var options, 279 name, 280 src, 281 copy, 282 copyIsArray, 283 clone, 284 target = arguments[0] || {}, 285 i = 1, 286 length = arguments.length, 287 deep = false; // Handle a deep copy situation 288 289 if (typeof target === "boolean") { 290 deep = target; // Skip the boolean and the target 291 292 target = arguments[i] || {}; 293 i++; 294 } // Handle case when target is a string or something (possible in deep copy) 295 296 297 if (typeof target !== "object" && !isFunction(target)) { 298 target = {}; 299 } // Extend jQuery itself if only one argument is passed 300 301 302 if (i === length) { 303 target = this; 304 i--; 305 } 306 307 for (; i < length; i++) { 308 // Only deal with non-null/undefined values 309 if ((options = arguments[i]) != null) { 310 // Extend the base object 311 for (name in options) { 312 src = target[name]; 313 copy = options[name]; // Prevent never-ending loop 314 315 if (target === copy) { 316 continue; 317 } // Recurse if we're merging plain objects or arrays 318 319 320 if (deep && copy && (jQuery.isPlainObject(copy) || (copyIsArray = Array.isArray(copy)))) { 321 if (copyIsArray) { 322 copyIsArray = false; 323 clone = src && Array.isArray(src) ? src : []; 324 } else { 325 clone = src && jQuery.isPlainObject(src) ? src : {}; 326 } // Never move original objects, clone them 327 328 329 target[name] = jQuery.extend(deep, clone, copy); // Don't bring in undefined values 330 } else if (copy !== undefined) { 331 target[name] = copy; 332 } 333 } 334 } 335 } // Return the modified object 336 337 338 return target; 339 }; 340 341 jQuery.extend({ 342 // Unique for each copy of jQuery on the page 343 expando: "jQuery" + (version$2 + Math.random()).replace(/\D/g, ""), 344 // Assume jQuery is ready without the ready module 345 isReady: true, 346 error: function (msg) { 347 throw new Error(msg); 348 }, 349 noop: function () {}, 350 isPlainObject: function (obj) { 351 var proto, Ctor; // Detect obvious negatives 352 // Use toString instead of jQuery.type to catch host objects 353 354 if (!obj || toString$3.call(obj) !== "[object Object]") { 355 return false; 356 } 357 358 proto = getProto(obj); // Objects with no prototype (e.g., `Object.create( null )`) are plain 359 360 if (!proto) { 361 return true; 362 } // Objects with prototype are plain iff they were constructed by a global Object function 363 364 365 Ctor = hasOwn.call(proto, "constructor") && proto.constructor; 366 return typeof Ctor === "function" && fnToString.call(Ctor) === ObjectFunctionString; 367 }, 368 isEmptyObject: function (obj) { 369 /* eslint-disable no-unused-vars */ 370 // See https://github.com/eslint/eslint/issues/6125 371 var name; 372 373 for (name in obj) { 374 return false; 375 } 376 377 return true; 378 }, 379 // Evaluates a script in a global context 380 globalEval: function (code) { 381 DOMEval(code); 382 }, 383 each: function (obj, callback) { 384 var length, 385 i = 0; 386 387 if (isArrayLike(obj)) { 388 length = obj.length; 389 390 for (; i < length; i++) { 391 if (callback.call(obj[i], i, obj[i]) === false) { 392 break; 393 } 394 } 395 } else { 396 for (i in obj) { 397 if (callback.call(obj[i], i, obj[i]) === false) { 398 break; 399 } 400 } 401 } 402 403 return obj; 404 }, 405 // Support: Android <=4.0 only 406 trim: function (text) { 407 return text == null ? "" : (text + "").replace(rtrim, ""); 408 }, 409 // results is for internal usage only 410 makeArray: function (arr, results) { 411 var ret = results || []; 412 413 if (arr != null) { 414 if (isArrayLike(Object(arr))) { 415 jQuery.merge(ret, typeof arr === "string" ? [arr] : arr); 416 } else { 417 push$1.call(ret, arr); 418 } 419 } 420 421 return ret; 422 }, 423 inArray: function (elem, arr, i) { 424 return arr == null ? -1 : indexOf$1.call(arr, elem, i); 425 }, 426 // Support: Android <=4.0 only, PhantomJS 1 only 427 // push.apply(_, arraylike) throws on ancient WebKit 428 merge: function (first, second) { 429 var len = +second.length, 430 j = 0, 431 i = first.length; 432 433 for (; j < len; j++) { 434 first[i++] = second[j]; 435 } 436 437 first.length = i; 438 return first; 439 }, 440 grep: function (elems, callback, invert) { 441 var callbackInverse, 442 matches = [], 443 i = 0, 444 length = elems.length, 445 callbackExpect = !invert; // Go through the array, only saving the items 446 // that pass the validator function 447 448 for (; i < length; i++) { 449 callbackInverse = !callback(elems[i], i); 450 451 if (callbackInverse !== callbackExpect) { 452 matches.push(elems[i]); 453 } 454 } 455 456 return matches; 457 }, 458 // arg is for internal usage only 459 map: function (elems, callback, arg) { 460 var length, 461 value, 462 i = 0, 463 ret = []; // Go through the array, translating each of the items to their new values 464 465 if (isArrayLike(elems)) { 466 length = elems.length; 467 468 for (; i < length; i++) { 469 value = callback(elems[i], i, arg); 470 471 if (value != null) { 472 ret.push(value); 473 } 474 } // Go through every key on the object, 475 476 } else { 477 for (i in elems) { 478 value = callback(elems[i], i, arg); 479 480 if (value != null) { 481 ret.push(value); 482 } 483 } 484 } // Flatten any nested arrays 485 486 487 return concat$1.apply([], ret); 488 }, 489 // A global GUID counter for objects 490 guid: 1, 491 // jQuery.support is not used in Core but other projects attach their 492 // properties to it so it needs to exist. 493 support: support 494 }); 495 496 if (typeof Symbol === "function") { 497 jQuery.fn[Symbol.iterator] = arr[Symbol.iterator]; 498 } // Populate the class2type map 499 500 501 jQuery.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "), function (i, name) { 502 class2type["[object " + name + "]"] = name.toLowerCase(); 503 }); 504 505 function isArrayLike(obj) { 506 // Support: real iOS 8.2 only (not reproducible in simulator) 507 // `in` check used to prevent JIT error (gh-2145) 508 // hasOwn isn't used here due to false negatives 509 // regarding Nodelist length in IE 510 var length = !!obj && "length" in obj && obj.length, 511 type = toType(obj); 512 513 if (isFunction(obj) || isWindow(obj)) { 514 return false; 515 } 516 517 return type === "array" || length === 0 || typeof length === "number" && length > 0 && length - 1 in obj; 518 } 519 520 var Sizzle = 521 /*! 522 * Sizzle CSS Selector Engine v2.3.3 523 * https://sizzlejs.com/ 524 * 525 * Copyright jQuery Foundation and other contributors 526 * Released under the MIT license 527 * http://jquery.org/license 528 * 529 * Date: 2016-08-08 530 */ 531 function (window) { 532 var i, 533 support, 534 Expr, 535 getText, 536 isXML, 537 tokenize, 538 compile, 539 select, 540 outermostContext, 541 sortInput, 542 hasDuplicate, 543 // Local document vars 544 setDocument, 545 document, 546 docElem, 547 documentIsHTML, 548 rbuggyQSA, 549 rbuggyMatches, 550 matches, 551 contains, 552 // Instance-specific data 553 expando = "sizzle" + 1 * new Date(), 554 preferredDoc = window.document, 555 dirruns = 0, 556 done = 0, 557 classCache = createCache(), 558 tokenCache = createCache(), 559 compilerCache = createCache(), 560 sortOrder = function (a, b) { 561 if (a === b) { 562 hasDuplicate = true; 563 } 564 565 return 0; 566 }, 567 // Instance methods 568 hasOwn = {}.hasOwnProperty, 569 arr = [], 570 pop = arr.pop, 571 push_native = arr.push, 572 push = arr.push, 573 slice = arr.slice, 574 // Use a stripped-down indexOf as it's faster than native 575 // https://jsperf.com/thor-indexof-vs-for/5 576 indexOf = function (list, elem) { 577 var i = 0, 578 len = list.length; 579 580 for (; i < len; i++) { 581 if (list[i] === elem) { 582 return i; 583 } 584 } 585 586 return -1; 587 }, 588 booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", 589 // Regular expressions 590 // http://www.w3.org/TR/css3-selectors/#whitespace 591 whitespace = "[\\x20\\t\\r\\n\\f]", 592 // http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier 593 identifier = "(?:\\\\.|[\\w-]|[^\0-\\xa0])+", 594 // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors 595 attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + // Operator (capture 2) 596 "*([*^$|!~]?=)" + whitespace + // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]" 597 "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace + "*\\]", 598 pseudos = ":(" + identifier + ")(?:\\((" + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: 599 // 1. quoted (capture 3; capture 4 or capture 5) 600 "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + // 2. simple (capture 6) 601 "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + // 3. anything else (capture 2) 602 ".*" + ")\\)|)", 603 // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter 604 rwhitespace = new RegExp(whitespace + "+", "g"), 605 rtrim = new RegExp("^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g"), 606 rcomma = new RegExp("^" + whitespace + "*," + whitespace + "*"), 607 rcombinators = new RegExp("^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*"), 608 rattributeQuotes = new RegExp("=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g"), 609 rpseudo = new RegExp(pseudos), 610 ridentifier = new RegExp("^" + identifier + "$"), 611 matchExpr = { 612 "ID": new RegExp("^#(" + identifier + ")"), 613 "CLASS": new RegExp("^\\.(" + identifier + ")"), 614 "TAG": new RegExp("^(" + identifier + "|[*])"), 615 "ATTR": new RegExp("^" + attributes), 616 "PSEUDO": new RegExp("^" + pseudos), 617 "CHILD": new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + "*(\\d+)|))" + whitespace + "*\\)|)", "i"), 618 "bool": new RegExp("^(?:" + booleans + ")$", "i"), 619 // For use in libraries implementing .is() 620 // We use this for POS matching in `select` 621 "needsContext": new RegExp("^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i") 622 }, 623 rinputs = /^(?:input|select|textarea|button)$/i, 624 rheader = /^h\d$/i, 625 rnative = /^[^{]+\{\s*\[native \w/, 626 // Easily-parseable/retrievable ID or TAG or CLASS selectors 627 rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, 628 rsibling = /[+~]/, 629 // CSS escapes 630 // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters 631 runescape = new RegExp("\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig"), 632 funescape = function (_, escaped, escapedWhitespace) { 633 var high = "0x" + escaped - 0x10000; // NaN means non-codepoint
634 // Support: Firefox<24 635 // Workaround erroneous numeric interpretation of +"0x" 636 637 return high !== high || escapedWhitespace ? escaped : high < 0 ? // BMP codepoint 638 String.fromCharCode(high + 0x10000) : // Supplemental Plane codepoint (surrogate pair) 639 String.fromCharCode(high >> 10 | 0xD800, high & 0x3FF | 0xDC00); 640 }, 641 // CSS string/identifier serialization 642 // https://drafts.csswg.org/cssom/#common-serializing-idioms 643 // eslint-disable-next-line no-control-regex 644 rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g, 645 fcssescape = function (ch, asCodePoint) { 646 if (asCodePoint) { 647 // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER 648 if (ch === "\0") { 649 return "\uFFFD"; 650 } // Control characters and (dependent upon position) numbers get escaped as code points 651 652 653 return ch.slice(0, -1) + "\\" + ch.charCodeAt(ch.length - 1).toString(16) + " "; 654 } // Other potentially-special ASCII characters get backslash-escaped 655 656 657 return "\\" + ch; 658 }, 659 // Used for iframes 660 // See setDocument() 661 // Removing the function wrapper causes a "Permission Denied" 662 // error in IE 663 unloadHandler = function () { 664 setDocument(); 665 }, 666 disabledAncestor = addCombinator(function (elem) { 667 return elem.disabled === true && ("form" in elem || "label" in elem); 668 }, { 669 dir: "parentNode", 670 next: "legend" 671 }); // Optimize for push.apply( _, NodeList ) 672 673 674 try { 675 push.apply(arr = slice.call(preferredDoc.childNodes), preferredDoc.childNodes); // Support: Android<4.0 676 // Detect silently failing push.apply 677 678 arr[preferredDoc.childNodes.length].nodeType; 679 } catch (e) { 680 push = { 681 apply: arr.length ? // Leverage slice if possible 682 function (target, els) { 683 push_native.apply(target, slice.call(els)); 684 } : // Support: IE<9 685 // Otherwise append directly 686 function (target, els) { 687 var j = target.length, 688 i = 0; // Can't trust NodeList.length 689 690 while (target[j++] = els[i++]) {} 691 692 target.length = j - 1; 693 } 694 }; 695 } 696 697 function Sizzle(selector, context, results, seed) { 698 var m, 699 i, 700 elem, 701 nid, 702 match, 703 groups, 704 newSelector, 705 newContext = context && context.ownerDocument, 706 // nodeType defaults to 9, since context defaults to document 707 nodeType = context ? context.nodeType : 9; 708 results = results || []; // Return early from calls with invalid selector or context 709 710 if (typeof selector !== "string" || !selector || nodeType !== 1 && nodeType !== 9 && nodeType !== 11) { 711 return results; 712 } // Try to shortcut find operations (as opposed to filters) in HTML documents 713 714 715 if (!seed) { 716 if ((context ? context.ownerDocument || context : preferredDoc) !== document) { 717 setDocument(context); 718 } 719 720 context = context || document; 721 722 if (documentIsHTML) { 723 // If the selector is sufficiently simple, try using a "get*By*" DOM method 724 // (excepting DocumentFragment context, where the methods don't exist) 725 if (nodeType !== 11 && (match = rquickExpr.exec(selector))) { 726 // ID selector 727 if (m = match[1]) { 728 // Document context 729 if (nodeType === 9) { 730 if (elem = context.getElementById(m)) { 731 // Support: IE, Opera, Webkit 732 // TODO: identify versions 733 // getElementById can match elements by name instead of ID 734 if (elem.id === m) { 735 results.push(elem); 736 return results; 737 } 738 } else { 739 return results; 740 } // Element context 741 742 } else {
743 // Support: IE, Opera, Webkit 744 // TODO: identify versions 745 // getElementById can match elements by name instead of ID 746 if (newContext && (elem = newContext.getElementById(m)) && contains(context, elem) && elem.id === m) { 747 results.push(elem); 748 return results; 749 } 750 } // Type selector 751 752 } else if (match[2]) { 753 push.apply(results, context.getElementsByTagName(selector)); 754 return results; // Class selector 755 } else if ((m = match[3]) && support.getElementsByClassName && context.getElementsByClassName) { 756 push.apply(results, context.getElementsByClassName(m)); 757 return results; 758 } 759 } // Take advantage of querySelectorAll 760 761 762 if (support.qsa && !compilerCache[selector + " "] && (!rbuggyQSA || !rbuggyQSA.test(selector))) { 763 if (nodeType !== 1) { 764 newContext = context; 765 newSelector = selector; // qSA looks outside Element context, which is not what we want 766 // Thanks to Andrew Dupont for this workaround technique 767 // Support: IE <=8 768 // Exclude object elements 769 } else if (context.nodeName.toLowerCase() !== "object") { 770 // Capture the context ID, setting it first if necessary 771 if (nid = context.getAttribute("id")) { 772 nid = nid.replace(rcssescape, fcssescape); 773 } else { 774 context.setAttribute("id", nid = expando); 775 } // Prefix every selector in the list 776 777 778 groups = tokenize(selector); 779 i = groups.length; 780 781 while (i--) { 782 groups[i] = "#" + nid + " " + toSelector(groups[i]); 783 } 784 785 newSelector = groups.join(","); // Expand context for sibling selectors 786 787 newContext = rsibling.test(selector) && testContext(context.parentNode) || context; 788 } 789 790 if (newSelector) { 791 try { 792 push.apply(results, newContext.querySelectorAll(newSelector)); 793 return results; 794 } catch (qsaError) {} finally { 795 if (nid === expando) { 796 context.removeAttribute("id"); 797 } 798 } 799 } 800 } 801 } 802 } // All others 803 804 805 return select(selector.replace(rtrim, "$1"), context, results, seed); 806 } 807 /** 808 * Create key-value caches of limited size 809 * @returns {function(string, object)} Returns the Object data after storing it on itself with 810 * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) 811 * deleting the oldest entry 812 */ 813 814 815 function createCache() { 816 var keys = []; 817 818 function cache(key, value) { 819 // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) 820 if (keys.push(key + " ") > Expr.cacheLength) { 821 // Only keep the most recent entries 822 delete cache[keys.shift()]; 823 } 824 825 return cache[key + " "] = value; 826 } 827 828 return cache; 829 } 830 /** 831 * Mark a function for special use by Sizzle 832 * @param {Function} fn The function to mark 833 */ 834 835 836 function markFunction(fn) { 837 fn[expando] = true; 838 return fn; 839 } 840 /** 841 * Support testing using an element 842 * @param {Function} fn Passed the created element and returns a boolean result 843 */ 844 845 846 function assert(fn) { 847 var el = document.createElement("fieldset"); 848 849 try { 850 return !!fn(el); 851 } catch (e) { 852 return false; 853 } finally { 854 // Remove from its parent by default 855 if (el.parentNode) { 856 el.parentNode.removeChild(el); 857 } // release memory in IE 858 859 860 el = null; 861 } 862 } 863 /** 864 * Checks document order of two siblings 865 * @param {Element} a 866 * @param {Element} b 867 * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b 868 */ 869 870 871 function siblingCheck(a, b) { 872 var cur = b && a, 873 diff = cur && a.nodeType === 1 && b.nodeType === 1 && a.sourceIndex - b.sourceIndex; // Use IE sourceIndex if available on both nodes 874 875 if (diff) { 876 return diff; 877 } // Check if b follows a 878 879 880 if (cur) { 881 while (cur = cur.nextSibling) { 882 if (cur === b) { 883 return -1; 884 } 885 } 886 } 887 888 return a ? 1 : -1; 889 } 890 /** 891 * Returns a function to use in pseudos for input types 892 * @param {String} type 893 */ 894 895 896 function createInputPseudo(type) { 897 return function (elem) { 898 var name = elem.nodeName.toLowerCase(); 899 return name === "input" && elem.type === type; 900 }; 901 } 902 /** 903 * Returns a function to use in pseudos for buttons 904 * @param {String} type 905 */ 906 907 908 function createButtonPseudo(type) { 909 return function (elem) { 910 var name = elem.nodeName.toLowerCase(); 911 return (name === "input" || name === "button") && elem.type === type; 912 }; 913 } 914 /** 915 * Returns a function to use in pseudos for :enabled/:disabled 916 * @param {Boolean} disabled true for :disabled; false for :enabled 917 */ 918 919 920 function createDisabledPseudo(disabled) { 921 // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable 922 return function (elem) { 923 // Only certain elements can match :enabled or :disabled 924 // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled 925 // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled 926 if ("form" in elem) { 927 // Check for inherited disabledness on relevant non-disabled elements: 928 // * listed form-associated elements in a disabled fieldset 929 // https://html.spec.whatwg.org/multipage/forms.html#category-listed 930 // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled 931 // * option elements in a disabled optgroup 932 // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled 933 // All such elements have a "form" property. 934 if (elem.parentNode && elem.disabled === false) { 935 // Option elements defer to a parent optgroup if present 936 if ("label" in elem) { 937 if ("label" in elem.parentNode) { 938 return elem.parentNode.disabled === disabled; 939 } else { 940 return elem.disabled === disabled; 941 } 942 } // Support: IE 6 - 11 943 // Use the isDisabled shortcut property to check for disabled fieldset ancestors 944 945 946 return elem.isDisabled === disabled || // Where there is no isDisabled, check manually 947 948 /* jshint -W018 */ 949 elem.isDisabled !== !disabled && disabledAncestor(elem) === disabled; 950 } 951 952 return elem.disabled === disabled; // Try to winnow out elements that can't be disabled before trusting the disabled property. 953 // Some victims get caught in our net (label, legend, menu, track), but it shouldn't 954 // even exist on them, let alone have a boolean value. 955 } else if ("label" in elem) { 956 return elem.disabled === disabled; 957 } // Remaining elements are neither :enabled nor :disabled 958 959 960 return false;
vendor: 5,066 bytes, lines 961-1091
961 }; 962 } 963 /** 964 * Returns a function to use in pseudos for positionals 965 * @param {Function} fn 966 */ 967 968 969 function createPositionalPseudo(fn) { 970 return markFunction(function (argument) { 971 argument = +argument; 972 return markFunction(function (seed, matches) { 973 var j, 974 matchIndexes = fn([], seed.length, argument), 975 i = matchIndexes.length; // Match elements found at the specified indexes 976 977 while (i--) { 978 if (seed[j = matchIndexes[i]]) { 979 seed[j] = !(matches[j] = seed[j]); 980 } 981 } 982 }); 983 }); 984 } 985 /** 986 * Checks a node for validity as a Sizzle context 987 * @param {Element|Object=} context 988 * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value 989 */ 990 991 992 function testContext(context) { 993 return context && typeof context.getElementsByTagName !== "undefined" && context; 994 } // Expose support vars for convenience 995 996 997 support = Sizzle.support = {}; 998 /** 999 * Detects XML nodes 1000 * @param {Element|Object} elem An element or a document 1001 * @returns {Boolean} True iff elem is a non-HTML XML node 1002 */ 1003 1004 isXML = Sizzle.isXML = function (elem) { 1005 // documentElement is verified for cases where it doesn't yet exist 1006 // (such as loading iframes in IE - #4833) 1007 var documentElement = elem && (elem.ownerDocument || elem).documentElement; 1008 return documentElement ? documentElement.nodeName !== "HTML" : false; 1009 }; 1010 /** 1011 * Sets document-related variables once based on the current document 1012 * @param {Element|Object} [doc] An element or document object to use to set the document 1013 * @returns {Object} Returns the current document 1014 */ 1015 1016 1017 setDocument = Sizzle.setDocument = function (node) { 1018 var hasCompare, 1019 subWindow, 1020 doc = node ? node.ownerDocument || node : preferredDoc; // Return early if doc is invalid or already selected 1021 1022 if (doc === document || doc.nodeType !== 9 || !doc.documentElement) { 1023 return document; 1024 } // Update global variables 1025 1026 1027 document = doc; 1028 docElem = document.documentElement; 1029 documentIsHTML = !isXML(document); // Support: IE 9-11, Edge 1030 // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) 1031 1032 if (preferredDoc !== document && (subWindow = document.defaultView) && subWindow.top !== subWindow) { 1033 // Support: IE 11, Edge 1034 if (subWindow.addEventListener) { 1035 subWindow.addEventListener("unload", unloadHandler, false); // Support: IE 9 - 10 only 1036 } else if (subWindow.attachEvent) { 1037 subWindow.attachEvent("onunload", unloadHandler); 1038 } 1039 } 1040 /* Attributes 1041 ---------------------------------------------------------------------- */ 1042 // Support: IE<8 1043 // Verify that getAttribute really returns attributes and not properties 1044 // (excepting IE8 booleans) 1045 1046 1047 support.attributes = assert(function (el) { 1048 el.className = "i"; 1049 return !el.getAttribute("className"); 1050 }); 1051 /* getElement(s)By* 1052 ---------------------------------------------------------------------- */ 1053 // Check if getElementsByTagName("*") returns only elements 1054 1055 support.getElementsByTagName = assert(function (el) { 1056 el.appendChild(document.createComment("")); 1057 return !el.getElementsByTagName("*").length; 1058 }); // Support: IE<9 1059 1060 support.getElementsByClassName = rnative.test(document.getElementsByClassName); // Support: IE<10 1061 // Check if getElementById returns elements by name 1062 // The broken getElementById methods don't pick up programmatically-set names, 1063 // so use a roundabout getElementsByName test 1064 1065 support.getById = assert(function (el) { 1066 docElem.appendChild(el).id = expando; 1067 return !document.getElementsByName || !document.getElementsByName(expando).length; 1068 }); // ID filter and find 1069 1070 if (support.getById) { 1071 Expr.filter["ID"] = function (id) { 1072 var attrId = id.replace(runescape, funescape); 1073 return function (elem) { 1074 return elem.getAttribute("id") === attrId; 1075 }; 1076 }; 1077 1078 Expr.find["ID"] = function (id, context) { 1079 if (typeof context.getElementById !== "undefined" && documentIsHTML) { 1080 var elem = context.getElementById(id); 1081 return elem ? [elem] : []; 1082 } 1083 }; 1084 } else { 1085 Expr.filter["ID"] = function (id) { 1086 var attrId = id.replace(runescape, funescape); 1087 return function (elem) { 1088 var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); 1089 return node && node.value === attrId; 1090 }; 1091 };
1091 // Support: IE 6 - 7 only 1092 // getElementById is not reliable as a find shortcut 1093 1094 1095 Expr.find["ID"] = function (id, context) { 1096 if (typeof context.getElementById !== "undefined" && documentIsHTML) { 1097 var node, 1098 i, 1099 elems, 1100 elem = context.getElementById(id); 1101 1102 if (elem) { 1103 // Verify the id attribute 1104 node = elem.getAttributeNode("id"); 1105 1106 if (node && node.value === id) { 1107 return [elem]; 1108 } // Fall back on getElementsByName 1109 1110 1111 elems = context.getElementsByName(id); 1112 i = 0; 1113 1114 while (elem = elems[i++]) { 1115 node = elem.getAttributeNode("id"); 1116 1117 if (node && node.value === id) { 1118 return [elem]; 1119 } 1120 } 1121 } 1122 1123 return []; 1124 } 1125 }; 1126 } // Tag 1127 1128 1129 Expr.find["TAG"] = support.getElementsByTagName ? function (tag, context) { 1130 if (typeof context.getElementsByTagName !== "undefined") { 1131 return context.getElementsByTagName(tag); // DocumentFragment nodes don't have gEBTN 1132 } else if (support.qsa) { 1133 return context.querySelectorAll(tag); 1134 } 1135 } : function (tag, context) { 1136 var elem, 1137 tmp = [], 1138 i = 0, 1139 // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too 1140 results = context.getElementsByTagName(tag); // Filter out possible comments 1141 1142 if (tag === "*") { 1143 while (elem = results[i++]) { 1144 if (elem.nodeType === 1) { 1145 tmp.push(elem); 1146 } 1147 } 1148 1149 return tmp; 1150 } 1151 1152 return results; 1153 }; // Class 1154 1155 Expr.find["CLASS"] = support.getElementsByClassName && function (className, context) { 1156 if (typeof context.getElementsByClassName !== "undefined" && documentIsHTML) { 1157 return context.getElementsByClassName(className); 1158 } 1159 }; 1160 /* QSA/matchesSelector 1161 ---------------------------------------------------------------------- */ 1162 // QSA and matchesSelector support 1163 // matchesSelector(:active) reports false when true (IE9/Opera 11.5) 1164 1165 1166 rbuggyMatches = []; // qSa(:focus) reports false when true (Chrome 21) 1167 // We allow this because of a bug in IE8/9 that throws an error 1168 // whenever `document.activeElement` is accessed on an iframe 1169 // So, we allow :focus to pass through QSA all the time to avoid the IE error 1170 // See https://bugs.jquery.com/ticket/13378 1171 1172 rbuggyQSA = []; 1173 1174 if (support.qsa = rnative.test(document.querySelectorAll)) { 1175 // Build QSA regex 1176 // Regex strategy adopted from Diego Perini 1177 assert(function (el) { 1178 // Select is set to empty string on purpose 1179 // This is to test IE's treatment of not explicitly 1180 // setting a boolean content attribute, 1181 // since its presence should be enough 1182 // https://bugs.jquery.com/ticket/12359 1183 docElem.appendChild(el).innerHTML = "<a id='" + expando + "'></a>" + "<select id='" + expando + "-\r\\' msallowcapture=''>" + "<option selected=''></option></select>"; // Support: IE8, Opera 11-12.16 1184 // Nothing should be selected when empty strings follow ^= or $= or *= 1185 // The test attribute must be unknown in Opera but "safe" for WinRT 1186 // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section 1187 1188 if (el.querySelectorAll("[msallowcapture^='']").length) { 1189 rbuggyQSA.push("[*^$]=" + whitespace + "*(?:''|\"\")"); 1190 } // Support: IE8 1191 // Boolean attributes and "value" are not treated correctly 1192 1193 1194 if (!el.querySelectorAll("[selected]").length) { 1195 rbuggyQSA.push("\\[" + whitespace + "*(?:value|" + booleans + ")"); 1196 } // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ 1197 1198 1199 if (!el.querySelectorAll("[id~=" + expando + "-]").length) { 1200 rbuggyQSA.push("~="); 1201 } // Webkit/Opera - :checked should return selected option elements 1202 // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#
vendor: 15,262 bytes, lines 1202-1609
1202checked 1203 // IE8 throws error here and will not see later tests 1204 1205 1206 if (!el.querySelectorAll(":checked").length) { 1207 rbuggyQSA.push(":checked"); 1208 } // Support: Safari 8+, iOS 8+ 1209 // https://bugs.webkit.org/show_bug.cgi?id=136851 1210 // In-page `selector#id sibling-combinator selector` fails 1211 1212 1213 if (!el.querySelectorAll("a#" + expando + "+*").length) { 1214 rbuggyQSA.push(".#.+[+~]"); 1215 } 1216 }); 1217 assert(function (el) { 1218 el.innerHTML = "<a href='' disabled='disabled'></a>" + "<select disabled='disabled'><option/></select>"; // Support: Windows 8 Native Apps 1219 // The type and name attributes are restricted during .innerHTML assignment 1220 1221 var input = document.createElement("input"); 1222 input.setAttribute("type", "hidden"); 1223 el.appendChild(input).setAttribute("name", "D"); // Support: IE8 1224 // Enforce case-sensitivity of name attribute 1225 1226 if (el.querySelectorAll("[name=d]").length) { 1227 rbuggyQSA.push("name" + whitespace + "*[*^$|!~]?="); 1228 } // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) 1229 // IE8 throws error here and will not see later tests 1230 1231 1232 if (el.querySelectorAll(":enabled").length !== 2) { 1233 rbuggyQSA.push(":enabled", ":disabled"); 1234 } // Support: IE9-11+ 1235 // IE's :disabled selector does not pick up the children of disabled fieldsets 1236 1237 1238 docElem.appendChild(el).disabled = true; 1239 1240 if (el.querySelectorAll(":disabled").length !== 2) { 1241 rbuggyQSA.push(":enabled", ":disabled"); 1242 } // Opera 10-11 does not throw on post-comma invalid pseudos 1243 1244 1245 el.querySelectorAll("*,:x"); 1246 rbuggyQSA.push(",.*:"); 1247 }); 1248 } 1249 1250 if (support.matchesSelector = rnative.test(matches = docElem.matches || docElem.webkitMatchesSelector || docElem.mozMatchesSelector || docElem.oMatchesSelector || docElem.msMatchesSelector)) { 1251 assert(function (el) { 1252 // Check to see if it's possible to do matchesSelector 1253 // on a disconnected node (IE 9) 1254 support.disconnectedMatch = matches.call(el, "*"); // This should fail with an exception 1255 // Gecko does not error, returns false instead 1256 1257 matches.call(el, "[s!='']:x"); 1258 rbuggyMatches.push("!=", pseudos); 1259 }); 1260 } 1261 1262 rbuggyQSA = rbuggyQSA.length && new RegExp(rbuggyQSA.join("|")); 1263 rbuggyMatches = rbuggyMatches.length && new RegExp(rbuggyMatches.join("|")); 1264 /* Contains 1265 ---------------------------------------------------------------------- */ 1266 1267 hasCompare = rnative.test(docElem.compareDocumentPosition); // Element contains another 1268 // Purposefully self-exclusive 1269 // As in, an element does not contain itself 1270 1271 contains = hasCompare || rnative.test(docElem.contains) ? function (a, b) { 1272 var adown = a.nodeType === 9 ? a.documentElement : a, 1273 bup = b && b.parentNode; 1274 return a === bup || !!(bup && bup.nodeType === 1 && (adown.contains ? adown.contains(bup) : a.compareDocumentPosition && a.compareDocumentPosition(bup) & 16)); 1275 } : function (a, b) { 1276 if (b) { 1277 while (b = b.parentNode) { 1278 if (b === a) { 1279 return true; 1280 } 1281 } 1282 } 1283 1284 return false; 1285 }; 1286 /* Sorting 1287 ---------------------------------------------------------------------- */ 1288 // Document order sorting 1289 1290 sortOrder = hasCompare ? function (a, b) { 1291 // Flag for duplicate removal 1292 if (a === b) { 1293 hasDuplicate = true; 1294 return 0; 1295 } // Sort on method existence if only one input has compareDocumentPosition 1296 1297 1298 var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; 1299 1300 if (compare) { 1301 return compare; 1302 } // Calculate position if both inputs belong to the same document 1303 1304 1305 compare = (a.ownerDocument || a) === (b.ownerDocument || b) ? a.compareDocumentPosition(b) : // Otherwise we know they are disconnected 1306 1; // Disconnected nodes 1307 1308 if (compare & 1 || !support.sortDetached && b.compareDocumentPosition(a) === compare) { 1309 // Choose the first element that is related to our preferred document 1310 if (a === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a)) { 1311 return -1; 1312 } 1313 1314 if (b === document || b.ownerDocument === preferredDoc && contains(preferredDoc, b)) { 1315 return 1; 1316 } // Maintain original order 1317 1318 1319 return sortInput ? indexOf(sortInput, a) - indexOf(sortInput, b) : 0; 1320 } 1321 1322 return compare & 4 ? -1 : 1; 1323 } : function (a, b) { 1324 // Exit early if the nodes are identical 1325 if (a === b) { 1326 hasDuplicate = true; 1327 return 0; 1328 } 1329 1330 var cur, 1331 i = 0, 1332 aup = a.parentNode, 1333 bup = b.parentNode, 1334 ap = [a], 1335 bp = [b]; // Parentless nodes are either documents or disconnected 1336 1337 if (!aup || !bup) { 1338 return a === document ? -1 : b === document ? 1 : aup ? -1 : bup ? 1 : sortInput ? indexOf(sortInput, a) - indexOf(sortInput, b) : 0; // If the nodes are siblings, we can do a quick check 1339 } else if (aup === bup) { 1340 return siblingCheck(a, b); 1341 } // Otherwise we need full lists of their ancestors for comparison 1342 1343 1344 cur = a; 1345 1346 while (cur = cur.parentNode) { 1347 ap.unshift(cur); 1348 } 1349 1350 cur = b; 1351 1352 while (cur = cur.parentNode) { 1353 bp.unshift(cur); 1354 } // Walk down the tree looking for a discrepancy 1355 1356 1357 while (ap[i] === bp[i]) { 1358 i++; 1359 } 1360 1361 return i ? // Do a sibling check if the nodes have a common ancestor 1362 siblingCheck(ap[i], bp[i]) : // Otherwise nodes in our document sort first 1363 ap[i] === preferredDoc ? -1 : bp[i] === preferredDoc ? 1 : 0; 1364 }; 1365 return document; 1366 }; 1367 1368 Sizzle.matches = function (expr, elements) { 1369 return Sizzle(expr, null, null, elements); 1370 }; 1371 1372 Sizzle.matchesSelector = function (elem, expr) { 1373 // Set document vars if needed 1374 if ((elem.ownerDocument || elem) !== document) { 1375 setDocument(elem); 1376 } // Make sure that attribute selectors are quoted 1377 1378 1379 expr = expr.replace(rattributeQuotes, "='$1']"); 1380 1381 if (support.matchesSelector && documentIsHTML && !compilerCache[expr + " "] && (!rbuggyMatches || !rbuggyMatches.test(expr)) && (!rbuggyQSA || !rbuggyQSA.test(expr))) { 1382 try { 1383 var ret = matches.call(elem, expr); // IE 9's matchesSelector returns false on disconnected nodes 1384 1385 if (ret || support.disconnectedMatch || // As well, disconnected nodes are said to be in a document 1386 // fragment in IE 9 1387 elem.document && elem.document.nodeType !== 11) { 1388 return ret; 1389 } 1390 } catch (e) {} 1391 } 1392 1393 return Sizzle(expr, document, null, [elem]).length > 0; 1394 }; 1395 1396 Sizzle.contains = function (context, elem) { 1397 // Set document vars if needed 1398 if ((context.ownerDocument || context) !== document) { 1399 setDocument(context); 1400 } 1401 1402 return contains(context, elem); 1403 }; 1404 1405 Sizzle.attr = function (elem, name) { 1406 // Set document vars if needed 1407 if ((elem.ownerDocument || elem) !== document) { 1408 setDocument(elem); 1409 } 1410 1411 var fn = Expr.attrHandle[name.toLowerCase()], 1412 // Don't get fooled by Object.prototype properties (jQuery #13807) 1413 val = fn && hasOwn.call(Expr.attrHandle, name.toLowerCase()) ? fn(elem, name, !documentIsHTML) : undefined; 1414 return val !== undefined ? val : support.attributes || !documentIsHTML ? elem.getAttribute(name) : (val = elem.getAttributeNode(name)) && val.specified ? val.value : null; 1415 }; 1416 1417 Sizzle.escape = function (sel) { 1418 return (sel + "").replace(rcssescape, fcssescape); 1419 }; 1420 1421 Sizzle.error = function (msg) { 1422 throw new Error("Syntax error, unrecognized expression: " + msg); 1423 }; 1424 /** 1425 * Document sorting and removing duplicates 1426 * @param {ArrayLike} results 1427 */ 1428 1429 1430 Sizzle.uniqueSort = function (results) { 1431 var elem, 1432 duplicates = [], 1433 j = 0, 1434 i = 0; // Unless we *know* we can detect duplicates, assume their presence 1435 1436 hasDuplicate = !support.detectDuplicates; 1437 sortInput = !support.sortStable && results.slice(0); 1438 results.sort(sortOrder); 1439 1440 if (hasDuplicate) { 1441 while (elem = results[i++]) { 1442 if (elem === results[i]) { 1443 j = duplicates.push(i); 1444 } 1445 } 1446 1447 while (j--) { 1448 results.splice(duplicates[j], 1); 1449 } 1450 } // Clear input after sorting to release objects 1451 // See https://github.com/jquery/sizzle/pull/225 1452 1453 1454 sortInput = null; 1455 return results; 1456 }; 1457 /** 1458 * Utility function for retrieving the text value of an array of DOM nodes 1459 * @param {Array|Element} elem 1460 */ 1461 1462 1463 getText = Sizzle.getText = function (elem) { 1464 var node, 1465 ret = "", 1466 i = 0, 1467 nodeType = elem.nodeType; 1468 1469 if (!nodeType) { 1470 // If no nodeType, this is expected to be an array 1471 while (node = elem[i++]) { 1472 // Do not traverse comment nodes 1473 ret += getText(node); 1474 } 1475 } else if (nodeType === 1 || nodeType === 9 || nodeType === 11) { 1476 // Use textContent for elements 1477 // innerText usage removed for consistency of new lines (jQuery #11153) 1478 if (typeof elem.textContent === "string") { 1479 return elem.textContent; 1480 } else { 1481 // Traverse its children 1482 for (elem = elem.firstChild; elem; elem = elem.nextSibling) { 1483 ret += getText(elem); 1484 } 1485 } 1486 } else if (nodeType === 3 || nodeType === 4) { 1487 return elem.nodeValue; 1488 } // Do not include comment or processing instruction nodes 1489 1490 1491 return ret; 1492 }; 1493 1494 Expr = Sizzle.selectors = { 1495 // Can be adjusted by the user 1496 cacheLength: 50, 1497 createPseudo: markFunction, 1498 match: matchExpr, 1499 attrHandle: {}, 1500 find: {}, 1501 relative: { 1502 ">": { 1503 dir: "parentNode", 1504 first: true 1505 }, 1506 " ": { 1507 dir: "parentNode" 1508 }, 1509 "+": { 1510 dir: "previousSibling", 1511 first: true 1512 }, 1513 "~": { 1514 dir: "previousSibling" 1515 } 1516 }, 1517 preFilter: { 1518 "ATTR": function (match) { 1519 match[1] = match[1].replace(runescape, funescape); // Move the given value to match[3] whether quoted or unquoted 1520 1521 match[3] = (match[3] || match[4] || match[5] || "").replace(runescape, funescape); 1522 1523 if (match[2] === "~=") { 1524 match[3] = " " + match[3] + " "; 1525 } 1526 1527 return match.slice(0, 4); 1528 }, 1529 "CHILD": function (match) { 1530 /* matches from matchExpr["CHILD"] 1531 1 type (only|nth|...) 1532 2 what (child|of-type) 1533 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) 1534 4 xn-component of xn+y argument ([+-]?\d*n|) 1535 5 sign of xn-component 1536 6 x of xn-component 1537 7 sign of y-component 1538 8 y of y-component 1539 */ 1540 match[1] = match[1].toLowerCase(); 1541 1542 if (match[1].slice(0, 3) === "nth") { 1543 // nth-* requires argument 1544 if (!match[3]) { 1545 Sizzle.error(match[0]); 1546 } // numeric x and y parameters for Expr.filter.CHILD 1547 // remember that false/true cast respectively to 0/1 1548 1549 1550 match[4] = +(match[4] ? match[5] + (match[6] || 1) : 2 * (match[3] === "even" || match[3] === "odd")); 1551 match[5] = +(match[7] + match[8] || match[3] === "odd"); // other types prohibit arguments 1552 } else if (match[3]) { 1553 Sizzle.error(match[0]); 1554 } 1555 1556 return match; 1557 }, 1558 "PSEUDO": function (match) { 1559 var excess, 1560 unquoted = !match[6] && match[2]; 1561 1562 if (matchExpr["CHILD"].test(match[0])) { 1563 return null; 1564 } // Accept quoted arguments as-is 1565 1566 1567 if (match[3]) { 1568 match[2] = match[4] || match[5] || ""; // Strip excess characters from unquoted arguments 1569 } else if (unquoted && rpseudo.test(unquoted) && ( // Get excess from tokenize (recursively) 1570 excess = tokenize(unquoted, true)) && ( // advance to the next closing parenthesis 1571 excess = unquoted.indexOf(")", unquoted.length - excess) - unquoted.length)) { 1572 // excess is a negative index 1573 match[0] = match[0].slice(0, excess); 1574 match[2] = unquoted.slice(0, excess); 1575 } // Return only captures needed by the pseudo filter method (type and argument) 1576 1577 1578 return match.slice(0, 3); 1579 } 1580 }, 1581 filter: { 1582 "TAG": function (nodeNameSelector) { 1583 var nodeName = nodeNameSelector.replace(runescape, funescape).toLowerCase(); 1584 return nodeNameSelector === "*" ? function () { 1585 return true; 1586 } : function (elem) { 1587 return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; 1588 }; 1589 }, 1590 "CLASS": function (className) { 1591 var pattern = classCache[className + " "]; 1592 return pattern || (pattern = new RegExp("(^|" + whitespace + ")" + className + "(" + whitespace + "|$)")) && classCache(className, function (elem) { 1593 return pattern.test(typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || ""); 1594 }); 1595 }, 1596 "ATTR": function (name, operator, check) { 1597 return function (elem) { 1598 var result = Sizzle.attr(elem, name); 1599 1600 if (result == null) { 1601 return operator === "!="; 1602 } 1603 1604 if (!operator) { 1605 return true; 1606 } 1607 1608 result += ""; 1609 return operator === "=" ? result === check : operator === "!=" ? result !== check : operator === "^=" ? check && result.indexOf(check) === 0 : operator === "*=" ? check && result.indexOf(check) > -1 : operator === "$=" ? check && result.slice(-check.length) === check : operator === "~=" ? (" " + result.replace(rwhitespace, " ") + " ").indexOf(check) > -1 : operator === "|=" ? result === check || result.slice(0, check.length + 1) === check + "-" : false;
1610 }; 1611 }, 1612 "CHILD": function (type, what, argument, first, last) { 1613 var simple = type.slice(0, 3) !== "nth", 1614 forward = type.slice(-4) !== "last", 1615 ofType = what === "of-type"; 1616 return first === 1 && last === 0 ? // Shortcut for :nth-*(n) 1617 function (elem) { 1618 return !!elem.parentNode; 1619 } : function (elem, context, xml) { 1620 var cache, 1621 uniqueCache, 1622 outerCache, 1623 node, 1624 nodeIndex, 1625 start, 1626 dir = simple !== forward ? "nextSibling" : "previousSibling", 1627 parent = elem.parentNode, 1628 name = ofType && elem.nodeName.toLowerCase(), 1629 useCache = !xml && !ofType, 1630 diff = false; 1631 1632 if (parent) { 1633 // :(first|last|only)-(child|of-type) 1634 if (simple) { 1635 while (dir) { 1636 node = elem; 1637 1638 while (node = node[dir]) { 1639 if (ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1) { 1640 return false; 1641 } 1642 } // Reverse direction for :only-* (if we haven't yet done so) 1643 1644 1645 start = dir = type === "only" && !start && "nextSibling"; 1646 } 1647 1648 return true; 1649 } 1650 1651 start = [forward ? parent.firstChild : parent.lastChild]; // non-xml :nth-child(...) stores cache data on `parent` 1652 1653 if (forward && useCache) { 1654 // Seek `elem` from a previously-cached index 1655 // ...in a gzip-friendly way 1656 node = parent; 1657 outerCache = node[expando] || (node[expando] = {}); // Support: IE <9 only 1658 // Defend against cloned attroperties (jQuery gh-1709) 1659 1660 uniqueCache = outerCache[node.uniqueID] || (outerCache[node.uniqueID] = {}); 1661 cache = uniqueCache[type] || []; 1662 nodeIndex = cache[0] === dirruns && cache[1]; 1663 diff = nodeIndex && cache[2]; 1664 node = nodeIndex && parent.childNodes[nodeIndex]; 1665 1666 while (node = ++nodeIndex && node && node[dir] || ( // Fallback to seeking `elem` from the start 1667 diff = nodeIndex = 0) || start.pop()) { 1668 // When found, cache indexes on `parent` and break 1669 if (node.nodeType === 1 && ++diff && node === elem) { 1670 uniqueCache[type] = [dirruns, nodeIndex, diff]; 1671 break; 1672 } 1673 } 1674 } else { 1675 // Use previously-cached element index if available 1676 if (useCache) { 1677 // ...in a gzip-friendly way 1678 node = elem; 1679 outerCache = node[expando] || (node[expando] = {}); // Support: IE <9 only 1680 // Defend against cloned attroperties (jQuery gh-1709) 1681 1682 uniqueCache = outerCache[node.uniqueID] || (outerCache[node.uniqueID] = {}); 1683 cache = uniqueCache[type] || []; 1684 nodeIndex = cache[0] === dirruns && cache[1]; 1685 diff = nodeIndex; 1686 } // xml :nth-child(...) 1687 // or :nth-last-child(...) or :nth(-last)?-of-type(...) 1688 1689 1690 if (diff === false) { 1691 // Use the same loop as above to seek `elem` from the start 1692 while (node = ++nodeIndex && node && node[dir] || (diff = nodeIndex = 0) || start.pop()) { 1693 if ((ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1) && ++diff) { 1694 // Cache the index of each encountered element 1695 if (useCache) { 1696 outerCache = node[expando] || (node[expando] = {}); // Support: IE <9 only 1697 // Defend against cloned attroperties (jQuery gh-1709) 1698 1699 uniqueCache = outerCache[node.uniqueID] || (outerCache[node.uniqueID] = {}); 1700 uniqueCache[type] = [dirruns, diff]; 1701 } 1702 1703 if (node === elem) { 1704 break; 1705 } 1706 } 1707 } 1708 } 1709 } // Incorporate the offset, then check against cycle size 1710 1711 1712 diff -= last; 1713 return diff === first || diff % first === 0 && diff / first >= 0; 1714 } 1715 }; 1716 }, 1717 "PSEUDO": function (pseudo, argument) { 1718 // pseudo-class names are case-insensitive
vendor: 9,072 bytes, lines 1719-1959
1719 // http://www.w3.org/TR/selectors/#pseudo-classes 1720 // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters 1721 // Remember that setFilters inherits from pseudos 1722 var args, 1723 fn = Expr.pseudos[pseudo] || Expr.setFilters[pseudo.toLowerCase()] || Sizzle.error("unsupported pseudo: " + pseudo); // The user may use createPseudo to indicate that 1724 // arguments are needed to create the filter function 1725 // just as Sizzle does 1726 1727 if (fn[expando]) { 1728 return fn(argument); 1729 } // But maintain support for old signatures 1730 1731 1732 if (fn.length > 1) { 1733 args = [pseudo, pseudo, "", argument]; 1734 return Expr.setFilters.hasOwnProperty(pseudo.toLowerCase()) ? markFunction(function (seed, matches) { 1735 var idx, 1736 matched = fn(seed, argument), 1737 i = matched.length; 1738 1739 while (i--) { 1740 idx = indexOf(seed, matched[i]); 1741 seed[idx] = !(matches[idx] = matched[i]); 1742 } 1743 }) : function (elem) { 1744 return fn(elem, 0, args); 1745 }; 1746 } 1747 1748 return fn; 1749 } 1750 }, 1751 pseudos: { 1752 // Potentially complex pseudos 1753 "not": markFunction(function (selector) { 1754 // Trim the selector passed to compile 1755 // to avoid treating leading and trailing 1756 // spaces as combinators 1757 var input = [], 1758 results = [], 1759 matcher = compile(selector.replace(rtrim, "$1")); 1760 return matcher[expando] ? markFunction(function (seed, matches, context, xml) { 1761 var elem, 1762 unmatched = matcher(seed, null, xml, []), 1763 i = seed.length; // Match elements unmatched by `matcher` 1764 1765 while (i--) { 1766 if (elem = unmatched[i]) { 1767 seed[i] = !(matches[i] = elem); 1768 } 1769 } 1770 }) : function (elem, context, xml) { 1771 input[0] = elem; 1772 matcher(input, null, xml, results); // Don't keep the element (issue #299) 1773 1774 input[0] = null; 1775 return !results.pop(); 1776 }; 1777 }), 1778 "has": markFunction(function (selector) { 1779 return function (elem) { 1780 return Sizzle(selector, elem).length > 0; 1781 }; 1782 }), 1783 "contains": markFunction(function (text) { 1784 text = text.replace(runescape, funescape); 1785 return function (elem) { 1786 return (elem.textContent || elem.innerText || getText(elem)).indexOf(text) > -1; 1787 }; 1788 }), 1789 // "Whether an element is represented by a :lang() selector 1790 // is based solely on the element's language value 1791 // being equal to the identifier C, 1792 // or beginning with the identifier C immediately followed by "-". 1793 // The matching of C against the element's language value is performed case-insensitively. 1794 // The identifier C does not have to be a valid language name." 1795 // http://www.w3.org/TR/selectors/#lang-pseudo 1796 "lang": markFunction(function (lang) { 1797 // lang value must be a valid identifier 1798 if (!ridentifier.test(lang || "")) { 1799 Sizzle.error("unsupported lang: " + lang); 1800 } 1801 1802 lang = lang.replace(runescape, funescape).toLowerCase(); 1803 return function (elem) { 1804 var elemLang; 1805 1806 do { 1807 if (elemLang = documentIsHTML ? elem.lang : elem.getAttribute("xml:lang") || elem.getAttribute("lang")) { 1808 elemLang = elemLang.toLowerCase(); 1809 return elemLang === lang || elemLang.indexOf(lang + "-") === 0; 1810 } 1811 } while ((elem = elem.parentNode) && elem.nodeType === 1); 1812 1813 return false; 1814 }; 1815 }), 1816 // Miscellaneous 1817 "target": function (elem) { 1818 var hash = window.location && window.location.hash; 1819 return hash && hash.slice(1) === elem.id; 1820 }, 1821 "root": function (elem) { 1822 return elem === docElem; 1823 }, 1824 "focus": function (elem) { 1825 return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); 1826 }, 1827 // Boolean properties 1828 "enabled": createDisabledPseudo(false), 1829 "disabled": createDisabledPseudo(true), 1830 "checked": function (elem) { 1831 // In CSS3, :checked should return both checked and selected elements 1832 // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked 1833 var nodeName = elem.nodeName.toLowerCase(); 1834 return nodeName === "input" && !!elem.checked || nodeName === "option" && !!elem.selected; 1835 }, 1836 "selected": function (elem) { 1837 // Accessing this property makes selected-by-default 1838 // options in Safari work properly 1839 if (elem.parentNode) { 1840 elem.parentNode.selectedIndex; 1841 } 1842 1843 return elem.selected === true; 1844 }, 1845 // Contents 1846 "empty": function (elem) { 1847 // http://www.w3.org/TR/selectors/#empty-pseudo 1848 // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), 1849 // but not by others (comment: 8; processing instruction: 7; etc.) 1850 // nodeType < 6 works because attributes (2) do not appear as children 1851 for (elem = elem.firstChild; elem; elem = elem.nextSibling) { 1852 if (elem.nodeType < 6) { 1853 return false; 1854 } 1855 } 1856 1857 return true; 1858 }, 1859 "parent": function (elem) { 1860 return !Expr.pseudos["empty"](elem); 1861 }, 1862 // Element/input types 1863 "header": function (elem) { 1864 return rheader.test(elem.nodeName); 1865 }, 1866 "input": function (elem) { 1867 return rinputs.test(elem.nodeName); 1868 }, 1869 "button": function (elem) { 1870 var name = elem.nodeName.toLowerCase(); 1871 return name === "input" && elem.type === "button" || name === "button"; 1872 }, 1873 "text": function (elem) { 1874 var attr; 1875 return elem.nodeName.toLowerCase() === "input" && elem.type === "text" && ( // Support: IE<8 1876 // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" 1877 (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text"); 1878 }, 1879 // Position-in-collection 1880 "first": createPositionalPseudo(function () { 1881 return [0]; 1882 }), 1883 "last": createPositionalPseudo(function (matchIndexes, length) { 1884 return [length - 1]; 1885 }), 1886 "eq": createPositionalPseudo(function (matchIndexes, length, argument) { 1887 return [argument < 0 ? argument + length : argument]; 1888 }), 1889 "even": createPositionalPseudo(function (matchIndexes, length) { 1890 var i = 0; 1891 1892 for (; i < length; i += 2) { 1893 matchIndexes.push(i); 1894 } 1895 1896 return matchIndexes; 1897 }), 1898 "odd": createPositionalPseudo(function (matchIndexes, length) { 1899 var i = 1; 1900 1901 for (; i < length; i += 2) { 1902 matchIndexes.push(i); 1903 } 1904 1905 return matchIndexes; 1906 }), 1907 "lt": createPositionalPseudo(function (matchIndexes, length, argument) { 1908 var i = argument < 0 ? argument + length : argument; 1909 1910 for (; --i >= 0;) { 1911 matchIndexes.push(i); 1912 } 1913 1914 return matchIndexes; 1915 }), 1916 "gt": createPositionalPseudo(function (matchIndexes, length, argument) { 1917 var i = argument < 0 ? argument + length : argument; 1918 1919 for (; ++i < length;) { 1920 matchIndexes.push(i); 1921 } 1922 1923 return matchIndexes; 1924 }) 1925 } 1926 }; 1927 Expr.pseudos["nth"] = Expr.pseudos["eq"]; // Add button/input type pseudos 1928 1929 for (i in { 1930 radio: true, 1931 checkbox: true, 1932 file: true, 1933 password: true, 1934 image: true 1935 }) { 1936 Expr.pseudos[i] = createInputPseudo(i); 1937 } 1938 1939 for (i in { 1940 submit: true, 1941 reset: true 1942 }) { 1943 Expr.pseudos[i] = createButtonPseudo(i); 1944 } // Easy API for creating new setFilters 1945 1946 1947 function setFilters() {} 1948 1949 setFilters.prototype = Expr.filters = Expr.pseudos; 1950 Expr.setFilters = new setFilters(); 1951 1952 tokenize = Sizzle.tokenize = function (selector, parseOnly) { 1953 var matched, 1954 match, 1955 tokens, 1956 type, 1957 soFar, 1958 groups, 1959 preFilters,
1960 cached = tokenCache[selector + " "]; 1961 1962 if (cached) { 1963 return parseOnly ? 0 : cached.slice(0); 1964 } 1965 1966 soFar = selector; 1967 groups = []; 1968 preFilters = Expr.preFilter; 1969 1970 while (soFar) { 1971 // Comma and first run 1972 if (!matched || (match = rcomma.exec(soFar))) { 1973 if (match) { 1974 // Don't consume trailing commas as valid 1975 soFar = soFar.slice(match[0].length) || soFar; 1976 } 1977 1978 groups.push(tokens = []); 1979 } 1980 1981 matched = false; // Combinators 1982 1983 if (match = rcombinators.exec(soFar)) { 1984 matched = match.shift(); 1985 tokens.push({ 1986 value: matched, 1987 // Cast descendant combinators to space 1988 type: match[0].replace(rtrim, " ") 1989 }); 1990 soFar = soFar.slice(matched.length); 1991 } // Filters 1992 1993 1994 for (type in Expr.filter) { 1995 if ((match = matchExpr[type].exec(soFar)) && (!preFilters[type] || (match = preFilters[type](match)))) { 1996 matched = match.shift(); 1997 tokens.push({ 1998 value: matched, 1999 type: type, 2000 matches: match 2001 }); 2002 soFar = soFar.slice(matched.length); 2003 } 2004 } 2005 2006 if (!matched) { 2007 break; 2008 } 2009 } // Return the length of the invalid excess 2010 // if we're just parsing 2011 // Otherwise, throw an error or return tokens 2012 2013 2014 return parseOnly ? soFar.length : soFar ? Sizzle.error(selector) : // Cache the tokens 2015 tokenCache(selector, groups).slice(0); 2016 }; 2017 2018 function toSelector(tokens) { 2019 var i = 0, 2020 len = tokens.length, 2021 selector = ""; 2022 2023 for (; i < len; i++) { 2024 selector += tokens[i].value; 2025 } 2026 2027 return selector; 2028 } 2029 2030 function addCombinator(matcher, combinator, base) { 2031 var dir = combinator.dir, 2032 skip = combinator.next, 2033 key = skip || dir, 2034 checkNonElements = base && key === "parentNode", 2035 doneName = done++; 2036 return combinator.first ? // Check against closest ancestor/preceding element 2037 function (elem, context, xml) { 2038 while (elem = elem[dir]) { 2039 if (elem.nodeType === 1 || checkNonElements) { 2040 return matcher(elem, context, xml); 2041 } 2042 } 2043 2044 return false; 2045 } : // Check against all ancestor/preceding elements 2046 function (elem, context, xml) { 2047 var oldCache, 2048 uniqueCache, 2049 outerCache, 2050 newCache = [dirruns, doneName]; // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching 2051 2052 if (xml) { 2053 while (elem = elem[dir]) { 2054 if (elem.nodeType === 1 || checkNonElements) { 2055 if (matcher(elem, context, xml)) { 2056 return true; 2057 } 2058 } 2059 } 2060 } else { 2061 while (elem = elem[dir]) { 2062 if (elem.nodeType === 1 || checkNonElements) { 2063 outerCache = elem[expando] || (elem[expando] = {}); // Support: IE <9 only 2064 // Defend against cloned attroperties (jQuery gh-1709) 2065 2066 uniqueCache = outerCache[elem.uniqueID] || (outerCache[elem.uniqueID] = {}); 2067 2068 if (skip && skip === elem.nodeName.toLowerCase()) { 2069 elem = elem[dir] || elem; 2070 } else if ((oldCache = uniqueCache[key]) && oldCache[0] === dirruns && oldCache[1] === doneName) { 2071 // Assign to newCache so results back-propagate to previous elements 2072 return newCache[2] = oldCache[2]; 2073 } else { 2074 // Reuse newcache so results back-propagate to previous elements 2075 uniqueCache[key] = newCache; // A match means we're done; a fail means we have to keep checking 2076 2077 if (newCache[2] = matcher(elem, context, xml)) { 2078 return true; 2079 } 2080 } 2081 } 2082 } 2083 } 2084 2085 return false;
vendor: 4,526 bytes, lines 2086-2224
2086 }; 2087 } 2088 2089 function elementMatcher(matchers) { 2090 return matchers.length > 1 ? function (elem, context, xml) { 2091 var i = matchers.length; 2092 2093 while (i--) { 2094 if (!matchers[i](elem, context, xml)) { 2095 return false; 2096 } 2097 } 2098 2099 return true; 2100 } : matchers[0]; 2101 } 2102 2103 function multipleContexts(selector, contexts, results) { 2104 var i = 0, 2105 len = contexts.length; 2106 2107 for (; i < len; i++) { 2108 Sizzle(selector, contexts[i], results); 2109 } 2110 2111 return results; 2112 } 2113 2114 function condense(unmatched, map, filter, context, xml) { 2115 var elem, 2116 newUnmatched = [], 2117 i = 0, 2118 len = unmatched.length, 2119 mapped = map != null; 2120 2121 for (; i < len; i++) { 2122 if (elem = unmatched[i]) { 2123 if (!filter || filter(elem, context, xml)) { 2124 newUnmatched.push(elem); 2125 2126 if (mapped) { 2127 map.push(i); 2128 } 2129 } 2130 } 2131 } 2132 2133 return newUnmatched; 2134 } 2135 2136 function setMatcher(preFilter, selector, matcher, postFilter, postFinder, postSelector) { 2137 if (postFilter && !postFilter[expando]) { 2138 postFilter = setMatcher(postFilter); 2139 } 2140 2141 if (postFinder && !postFinder[expando]) { 2142 postFinder = setMatcher(postFinder, postSelector); 2143 } 2144 2145 return markFunction(function (seed, results, context, xml) { 2146 var temp, 2147 i, 2148 elem, 2149 preMap = [], 2150 postMap = [], 2151 preexisting = results.length, 2152 // Get initial elements from seed or context 2153 elems = seed || multipleContexts(selector || "*", context.nodeType ? [context] : context, []), 2154 // Prefilter to get matcher input, preserving a map for seed-results synchronization 2155 matcherIn = preFilter && (seed || !selector) ? condense(elems, preMap, preFilter, context, xml) : elems, 2156 matcherOut = matcher ? // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, 2157 postFinder || (seed ? preFilter : preexisting || postFilter) ? // ...intermediate processing is necessary 2158 [] : // ...otherwise use results directly 2159 results : matcherIn; // Find primary matches 2160 2161 if (matcher) { 2162 matcher(matcherIn, matcherOut, context, xml); 2163 } // Apply postFilter 2164 2165 2166 if (postFilter) { 2167 temp = condense(matcherOut, postMap); 2168 postFilter(temp, [], context, xml); // Un-match failing elements by moving them back to matcherIn 2169 2170 i = temp.length; 2171 2172 while (i--) { 2173 if (elem = temp[i]) { 2174 matcherOut[postMap[i]] = !(matcherIn[postMap[i]] = elem); 2175 } 2176 } 2177 } 2178 2179 if (seed) { 2180 if (postFinder || preFilter) { 2181 if (postFinder) { 2182 // Get the final matcherOut by condensing this intermediate into postFinder contexts 2183 temp = []; 2184 i = matcherOut.length; 2185 2186 while (i--) { 2187 if (elem = matcherOut[i]) { 2188 // Restore matcherIn since elem is not yet a final match 2189 temp.push(matcherIn[i] = elem); 2190 } 2191 } 2192 2193 postFinder(null, matcherOut = [], temp, xml); 2194 } // Move matched elements from seed to results to keep them synchronized 2195 2196 2197 i = matcherOut.length; 2198 2199 while (i--) { 2200 if ((elem = matcherOut[i]) && (temp = postFinder ? indexOf(seed, elem) : preMap[i]) > -1) { 2201 seed[temp] = !(results[temp] = elem); 2202 } 2203 } 2204 } // Add elements to results, through postFinder if defined 2205 2206 } else { 2207 matcherOut = condense(matcherOut === results ? matcherOut.splice(preexisting, matcherOut.length) : matcherOut); 2208 2209 if (postFinder) { 2210 postFinder(null, results, matcherOut, xml); 2211 } else { 2212 push.apply(results, matcherOut); 2213 } 2214 } 2215 }); 2216 } 2217 2218 function matcherFromTokens(tokens) { 2219 var checkContext, 2220 matcher, 2221 j, 2222 len = tokens.length, 2223 leadingRelative = Expr.relative[tokens[0].type], 2224 implicitRelative = leadingRelative || Expr.relative[" "],
2225 i = leadingRelative ? 1 : 0, 2226 // The foundational matcher ensures that elements are reachable from top-level context(s) 2227 matchContext = addCombinator(function (elem) { 2228 return elem === checkContext; 2229 }, implicitRelative, true), 2230 matchAnyContext = addCombinator(function (elem) { 2231 return indexOf(checkContext, elem) > -1; 2232 }, implicitRelative, true), 2233 matchers = [function (elem, context, xml) { 2234 var ret = !leadingRelative && (xml || context !== outermostContext) || ((checkContext = context).nodeType ? matchContext(elem, context, xml) : matchAnyContext(elem, context, xml)); // Avoid hanging onto element (issue #299) 2235 2236 checkContext = null; 2237 return ret; 2238 }]; 2239 2240 for (; i < len; i++) { 2241 if (matcher = Expr.relative[tokens[i].type]) { 2242 matchers = [addCombinator(elementMatcher(matchers), matcher)]; 2243 } else { 2244 matcher = Expr.filter[tokens[i].type].apply(null, tokens[i].matches); // Return special upon seeing a positional matcher 2245 2246 if (matcher[expando]) { 2247 // Find the next relative operator (if any) for proper handling 2248 j = ++i; 2249 2250 for (; j < len; j++) { 2251 if (Expr.relative[tokens[j].type]) { 2252 break; 2253 } 2254 } 2255 2256 return setMatcher(i > 1 && elementMatcher(matchers), i > 1 && toSelector( // If the preceding token was a descendant combinator, insert an implicit any-element `*` 2257 tokens.slice(0, i - 1).concat({ 2258 value: tokens[i - 2].type === " " ? "*" : "" 2259 })).replace(rtrim, "$1"), matcher, i < j && matcherFromTokens(tokens.slice(i, j)), j < len && matcherFromTokens(tokens = tokens.slice(j)), j < len && toSelector(tokens)); 2260 } 2261 2262 matchers.push(matcher); 2263 } 2264 } 2265 2266 return elementMatcher(matchers); 2267 } 2268 2269 function matcherFromGroupMatchers(elementMatchers, setMatchers) { 2270 var bySet = setMatchers.length > 0, 2271 byElement = elementMatchers.length > 0, 2272 superMatcher = function (seed, context, xml, results, outermost) { 2273 var elem, 2274 j, 2275 matcher, 2276 matchedCount = 0, 2277 i = "0", 2278 unmatched = seed && [], 2279 setMatched = [], 2280 contextBackup = outermostContext, 2281 // We must always have either seed elements or outermost context 2282 elems = seed || byElement && Expr.find["TAG"]("*", outermost), 2283 // Use integer dirruns iff this is the outermost matcher 2284 dirrunsUnique = dirruns += contextBackup == null ? 1 : Math.random() || 0.1, 2285 len = elems.length; 2286 2287 if (outermost) { 2288 outermostContext = context === document || context || outermost; 2289 } // Add elements passing elementMatchers directly to results 2290 // Support: IE<9, Safari 2291 // Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id 2292 2293 2294 for (; i !== len && (elem = elems[i]) != null; i++) { 2295 if (byElement && elem) { 2296 j = 0; 2297 2298 if (!context && elem.ownerDocument !== document) { 2299 setDocument(elem); 2300 xml = !documentIsHTML; 2301 } 2302 2303 while (matcher = elementMatchers[j++]) { 2304 if (matcher(elem, context || document, xml)) { 2305 results.push(elem); 2306 break; 2307 } 2308 } 2309 2310 if (outermost) { 2311 dirruns = dirrunsUnique; 2312 } 2313 } // Track unmatched elements for set filters 2314 2315 2316 if (bySet) { 2317 // They will have gone through all possible matchers 2318 if (elem = !matcher && elem) { 2319 matchedCount--; 2320 } // Lengthen the array for every element, matched or not 2321 2322 2323 if (seed) { 2324 unmatched.push(elem); 2325 } 2326 } 2327 } // `i` is now the count of elements visited above, and adding it to `matchedCount` 2328 // makes the latter nonnegative. 2329 2330 2331 matchedCount += i; // Apply set filters to unmatched elements 2332 // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount` 2333 // equals `i`), unless we didn't visit _any_ elements in the above loop because we have 2334 // no element matchers and no seed. 2335 // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that 2336 // case, which will result in a "00" `matchedCount` that differs from `i` but is also 2337 // numerically zero. 2338 2339 if (bySet && i !== matchedCount) { 2340 j = 0; 2341 2342 while (matcher = setMatchers[j++]) { 2343 matcher(unmatched, setMatched, context, xml); 2344 } 2345 2346 if (seed) { 2347 // Reintegrate element matches to eliminate the need for sorting 2348 if (matchedCount > 0) { 2349 while (i--) { 2350 if (!(unmatched[i] || setMatched[i])) { 2351 setMatched[i] = pop.call(results); 2352 } 2353 } 2354 } // Discard index placeholder values to get only actual matches 2355 2356 2357 setMatched = condense(setMatched); 2358 } // Add matches to results 2359 2360 2361 push.apply(results, setMatched); // Seedless set matches succeeding multiple successful matchers stipulate sorting 2362 2363 if (outermost && !seed && setMatched.length > 0 && matchedCount + setMatchers.length > 1) { 2364 Sizzle.uniqueSort(results); 2365 } 2366 } // Override manipulation of globals by nested matchers 2367 2368 2369 if (outermost) { 2370 dirruns = dirrunsUnique; 2371 outermostContext = contextBackup; 2372 } 2373 2374 return unmatched; 2375 }; 2376 2377 return bySet ? markFunction(superMatcher) : superMatcher; 2378 } 2379 2380 compile = Sizzle.compile = function (selector, match 2381 /* Internal Use Only */ 2382 ) { 2383 var i, 2384 setMatchers = [], 2385 elementMatchers = [], 2386 cached = compilerCache[selector + " "]; 2387 2388 if (!cached) { 2389 // Generate a function of recursive functions that can be used to check each element 2390 if (!match) { 2391 match = tokenize(selector); 2392 } 2393 2394 i = match.length; 2395 2396 while (i--) { 2397 cached = matcherFromTokens(match[i]); 2398 2399 if (cached[expando]) { 2400 setMatchers.push(cached); 2401 } else { 2402 elementMatchers.push(cached); 2403 } 2404 } // Cache the compiled function 2405 2406 2407 cached = compilerCache(selector, matcherFromGroupMatchers(elementMatchers, setMatchers)); // Save selector and tokenization 2408 2409 cached.selector = selector; 2410 } 2411 2412 return cached; 2413 }; 2414 /** 2415 * A low-level selection function that works with Sizzle's compiled 2416 * selector functions 2417 * @param {String|Function} selector A selector or a pre-compiled 2418 * selector function built with Sizzle.compile 2419 * @param {Element} context 2420 * @param {Array} [results] 2421 * @param {Array} [seed] A set of elements to match against 2422 */ 2423 2424 2425 select = Sizzle.select = function (selector, context, results, seed) { 2426 var i, 2427 tokens, 2428 token, 2429 type, 2430 find, 2431 compiled = typeof selector === "function" && selector, 2432 match = !seed && tokenize(selector = compiled.selector || selector); 2433 results = results || []; // Try to minimize operations if there is only one selector in the list and no seed 2434 // (the latter of which guarantees us context) 2435 2436 if (match.length === 1) { 2437 // Reduce context if the leading compound selector is an ID 2438 tokens = match[0] = match[0].slice(0); 2439 2440 if (tokens.length > 2 && (token = tokens[0]).type === "ID" && context.nodeType === 9 && documentIsHTML && Expr.relative[tokens[1].type]) { 2441 context = (Expr.find["ID"](token.matches[0].replace(runescape, funescape), context) || [])[0]; 2442 2443 if (!context) { 2444 return results; // Precompiled matchers will still verify ancestry, so step up a level 2445 } else if (compiled) { 2446 context = context.parentNode; 2447 } 2448 2449 selector = selector.slice(tokens.shift().value.length); 2450 } // Fetch a seed set for right-to-left matching 2451 2452 2453 i = matchExpr["needsContext"].test(selector) ? 0 : tokens.length; 2454 2455 while (i--) { 2456 token = tokens[i]; // Abort if we hit a combinator 2457 2458 if (Expr.relative[type = token.type]) { 2459 break; 2460 } 2461 2462 if (find = Expr.find[type]) { 2463 // Search, expanding context for leading sibling combinators 2464 if (seed = find(token.matches[0].replace(runescape, funescape), rsibling.test(tokens[0].type) && testC
2464ontext(context.parentNode) || context)) { 2465 // If seed is empty or no tokens remain, we can return early 2466 tokens.splice(i, 1); 2467 selector = seed.length && toSelector(tokens); 2468 2469 if (!selector) { 2470 push.apply(results, seed); 2471 return results; 2472 } 2473 2474 break; 2475 } 2476 } 2477 } 2478 } // Compile and execute a filtering function if one is not provided 2479 // Provide `match` to avoid retokenization if we modified the selector above 2480 2481 2482 (compiled || compile(selector, match))(seed, context, !documentIsHTML, results, !context || rsibling.test(selector) && testContext(context.parentNode) || context); 2483 return results; 2484 }; // One-time assignments 2485 // Sort stability 2486 2487 2488 support.sortStable = expando.split("").sort(sortOrder).join("") === expando; // Support: Chrome 14-35+ 2489 // Always assume duplicates if they aren't passed to the comparison function 2490 2491 support.detectDuplicates = !!hasDuplicate; // Initialize against the default document 2492 2493 setDocument(); 2494 return Sizzle; 2495 }(window); 2496 2497 jQuery.find = Sizzle; 2498 jQuery.expr = Sizzle.selectors; // Deprecated 2499 2500 jQuery.expr[":"] = jQuery.expr.pseudos; 2501 jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort; 2502 jQuery.text = Sizzle.getText; 2503 jQuery.isXMLDoc = Sizzle.isXML; 2504 jQuery.contains = Sizzle.contains; 2505 jQuery.escapeSelector = Sizzle.escape; 2506 2507 var dir = function (elem, dir, until) { 2508 var matched = [], 2509 truncate = until !== undefined; 2510 2511 while ((elem = elem[dir]) && elem.nodeType !== 9) { 2512 if (elem.nodeType === 1) { 2513 if (truncate && jQuery(elem).is(until)) { 2514 break; 2515 } 2516 2517 matched.push(elem); 2518 } 2519 } 2520 2521 return matched; 2522 }; 2523 2524 var siblings = function (n, elem) { 2525 var matched = []; 2526 2527 for (; n; n = n.nextSibling) { 2528 if (n.nodeType === 1 && n !== elem) { 2529 matched.push(n); 2530 } 2531 } 2532 2533 return matched; 2534 }; 2535 2536 var rneedsContext = jQuery.expr.match.needsContext; 2537 2538 function nodeName(elem, name) { 2539 return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); 2540 } 2541 2542 var rsingleTag = /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i; // Implement the identical functionality for filter and not 2543 2544 function winnow(elements, qualifier, not) { 2545 if (isFunction(qualifier)) { 2546 return jQuery.grep(elements, function (elem, i) { 2547 return !!qualifier.call(elem, i, elem) !== not; 2548 }); 2549 } // Single element 2550 2551 2552 if (qualifier.nodeType) { 2553 return jQuery.grep(elements, function (elem) { 2554 return elem === qualifier !== not; 2555 }); 2556 } // Arraylike of elements (jQuery, arguments, Array) 2557 2558 2559 if (typeof qualifier !== "string") { 2560 return jQuery.grep(elements, function (elem) { 2561 return indexOf$1.call(qualifier, elem) > -1 !== not; 2562 }); 2563 } // Filtered directly for both simple and complex selectors 2564 2565 2566 return jQuery.filter(qualifier, elements, not); 2567 } 2568 2569 jQuery.filter = function (expr, elems, not) { 2570 var elem = elems[0]; 2571 2572 if (not) { 2573 expr = ":not(" + expr + ")"; 2574 } 2575 2576 if (elems.length === 1 && elem.nodeType === 1) { 2577 return jQuery.find.matchesSelector(elem, expr) ? [elem] : []; 2578 } 2579 2580 return jQuery.find.matches(expr, jQuery.grep(elems, function (elem) { 2581 return elem.nodeType === 1; 2582 })); 2583 }; 2584 2585 jQuery.fn.extend({ 2586 find: function (selector) { 2587 var i, 2588 ret, 2589 len = this.length, 2590 self = this; 2591 2592 if (typeof selector !== "string") { 2593 return this.pushStack(jQuery(selector).filter(function () { 2594 for (i = 0; i < len; i++) { 2595 if (jQuery.contains(self[i], this)) { 2596 return true; 2597 } 2598 } 2599 })); 2600 } 2601 2602 ret = this.pushStack([]); 2603 2604 for (i = 0; i < len; i++) { 2605 jQuery.find(selector, self[i], ret); 2606 } 2607 2608 return len > 1 ? jQuery.uniqueSort(ret) : ret; 2609 }, 2610 filter: function (selector) { 2611 return this.pushStack(winnow(this, selector || [], false)); 2612 }, 2613 not: function (selector) { 2614 return this.pushStack(winnow(this, selector || [], true)); 2615 }, 2616 is: function (selector) { 2617 return !!winnow(this, // If this is a positional/relative selector, check membership in the returned set 2618 // so $("p:first").is("p:last") won't return true for a doc with two "p". 2619 typeof selector === "string" && rneedsContext.test(selector) ? jQuery(selector) : selector || [], false).length; 2620 } 2621 }); // Initialize a jQuery object 2622 // A central reference to the root jQuery(document) 2623 2624 var rootjQuery, 2625 // A simple way to check for HTML strings 2626 // Prioritize #id over <tag> to avoid XSS via location.hash (#9521) 2627 // Strict HTML recognition (#11290: must start with <) 2628 // Shortcut simple #id case for speed 2629 rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/, 2630 init$2 = jQuery.fn.init = function (selector, context, root) { 2631 var match, elem; // HANDLE: $(""), $(null), $(undefined), $(false) 2632 2633 if (!selector) { 2634 return this; 2635 } // Method init() accepts an alternate rootjQuery
vendor: 4,597 bytes, lines 2636-2760
2636 // so migrate can support jQuery.sub (gh-2101) 2637 2638 2639 root = root || rootjQuery; // Handle HTML strings 2640 2641 if (typeof selector === "string") { 2642 if (selector[0] === "<" && selector[selector.length - 1] === ">" && selector.length >= 3) { 2643 // Assume that strings that start and end with <> are HTML and skip the regex check 2644 match = [null, selector, null]; 2645 } else { 2646 match = rquickExpr.exec(selector); 2647 } // Match html or make sure no context is specified for #id 2648 2649 2650 if (match && (match[1] || !context)) { 2651 // HANDLE: $(html) -> $(array) 2652 if (match[1]) { 2653 context = context instanceof jQuery ? context[0] : context; // Option to run scripts is true for back-compat 2654 // Intentionally let the error be thrown if parseHTML is not present 2655 2656 jQuery.merge(this, jQuery.parseHTML(match[1], context && context.nodeType ? context.ownerDocument || context : document$2, true)); // HANDLE: $(html, props) 2657 2658 if (rsingleTag.test(match[1]) && jQuery.isPlainObject(context)) { 2659 for (match in context) { 2660 // Properties of context are called as methods if possible 2661 if (isFunction(this[match])) { 2662 this[match](context[match]); // ...and otherwise set as attributes 2663 } else { 2664 this.attr(match, context[match]); 2665 } 2666 } 2667 } 2668 2669 return this; // HANDLE: $(#id) 2670 } else { 2671 elem = document$2.getElementById(match[2]); 2672 2673 if (elem) { 2674 // Inject the element directly into the jQuery object 2675 this[0] = elem; 2676 this.length = 1; 2677 } 2678 2679 return this; 2680 } // HANDLE: $(expr, $(...)) 2681 2682 } else if (!context || context.jquery) { 2683 return (context || root).find(selector); // HANDLE: $(expr, context) 2684 // (which is just equivalent to: $(context).find(expr) 2685 } else { 2686 return this.constructor(context).find(selector); 2687 } // HANDLE: $(DOMElement) 2688 2689 } else if (selector.nodeType) { 2690 this[0] = selector; 2691 this.length = 1; 2692 return this; // HANDLE: $(function) 2693 // Shortcut for document ready 2694 } else if (isFunction(selector)) { 2695 return root.ready !== undefined ? root.ready(selector) : // Execute immediately if ready is not present 2696 selector(jQuery); 2697 } 2698 2699 return jQuery.makeArray(selector, this); 2700 }; // Give the init function the jQuery prototype for later instantiation 2701 2702 2703 init$2.prototype = jQuery.fn; // Initialize central reference 2704 2705 rootjQuery = jQuery(document$2); 2706 var rparentsprev = /^(?:parents|prev(?:Until|All))/, 2707 // Methods guaranteed to produce a unique set when starting from a unique set 2708 guaranteedUnique = { 2709 children: true, 2710 contents: true, 2711 next: true, 2712 prev: true 2713 }; 2714 jQuery.fn.extend({ 2715 has: function (target) { 2716 var targets = jQuery(target, this), 2717 l = targets.length; 2718 return this.filter(function () { 2719 var i = 0; 2720 2721 for (; i < l; i++) { 2722 if (jQuery.contains(this, targets[i])) { 2723 return true; 2724 } 2725 } 2726 }); 2727 }, 2728 closest: function (selectors, context) { 2729 var cur, 2730 i = 0, 2731 l = this.length, 2732 matched = [], 2733 targets = typeof selectors !== "string" && jQuery(selectors); // Positional selectors never match, since there's no _selection_ context 2734 2735 if (!rneedsContext.test(selectors)) { 2736 for (; i < l; i++) { 2737 for (cur = this[i]; cur && cur !== context; cur = cur.parentNode) { 2738 // Always skip document fragments 2739 if (cur.nodeType < 11 && (targets ? targets.index(cur) > -1 : // Don't pass non-elements to Sizzle 2740 cur.nodeType === 1 && jQuery.find.matchesSelector(cur, selectors))) { 2741 matched.push(cur); 2742 break; 2743 } 2744 } 2745 } 2746 } 2747 2748 return this.pushStack(matched.length > 1 ? jQuery.uniqueSort(matched) : matched); 2749 }, 2750 // Determine the position of an element within the set 2751 index: function (elem) { 2752 // No argument, return index in parent 2753 if (!elem) { 2754 return this[0] && this[0].parentNode ? this.first().prevAll().length : -1; 2755 } // Index in selector 2756 2757 2758 if (typeof elem === "string") { 2759 return indexOf$1.call(jQuery(elem), this[0]); 2760 }
vendor: 5,478 bytes, lines 2760-2924
2760 // Locate the position of the desired element 2761 2762 2763 return indexOf$1.call(this, // If it receives a jQuery object, the first element is used 2764 elem.jquery ? elem[0] : elem); 2765 }, 2766 add: function (selector, context) { 2767 return this.pushStack(jQuery.uniqueSort(jQuery.merge(this.get(), jQuery(selector, context)))); 2768 }, 2769 addBack: function (selector) { 2770 return this.add(selector == null ? this.prevObject : this.prevObject.filter(selector)); 2771 } 2772 }); 2773 2774 function sibling(cur, dir) { 2775 while ((cur = cur[dir]) && cur.nodeType !== 1) {} 2776 2777 return cur; 2778 } 2779 2780 jQuery.each({ 2781 parent: function (elem) { 2782 var parent = elem.parentNode; 2783 return parent && parent.nodeType !== 11 ? parent : null; 2784 }, 2785 parents: function (elem) { 2786 return dir(elem, "parentNode"); 2787 }, 2788 parentsUntil: function (elem, i, until) { 2789 return dir(elem, "parentNode", until); 2790 }, 2791 next: function (elem) { 2792 return sibling(elem, "nextSibling"); 2793 }, 2794 prev: function (elem) { 2795 return sibling(elem, "previousSibling"); 2796 }, 2797 nextAll: function (elem) { 2798 return dir(elem, "nextSibling"); 2799 }, 2800 prevAll: function (elem) { 2801 return dir(elem, "previousSibling"); 2802 }, 2803 nextUntil: function (elem, i, until) { 2804 return dir(elem, "nextSibling", until); 2805 }, 2806 prevUntil: function (elem, i, until) { 2807 return dir(elem, "previousSibling", until); 2808 }, 2809 siblings: function (elem) { 2810 return siblings((elem.parentNode || {}).firstChild, elem); 2811 }, 2812 children: function (elem) { 2813 return siblings(elem.firstChild); 2814 }, 2815 contents: function (elem) { 2816 if (nodeName(elem, "iframe")) { 2817 return elem.contentDocument; 2818 } // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only 2819 // Treat the template element as a regular one in browsers that 2820 // don't support it. 2821 2822 2823 if (nodeName(elem, "template")) { 2824 elem = elem.content || elem; 2825 } 2826 2827 return jQuery.merge([], elem.childNodes); 2828 } 2829 }, function (name, fn) { 2830 jQuery.fn[name] = function (until, selector) { 2831 var matched = jQuery.map(this, fn, until); 2832 2833 if (name.slice(-5) !== "Until") { 2834 selector = until; 2835 } 2836 2837 if (selector && typeof selector === "string") { 2838 matched = jQuery.filter(selector, matched); 2839 } 2840 2841 if (this.length > 1) { 2842 // Remove duplicates 2843 if (!guaranteedUnique[name]) { 2844 jQuery.uniqueSort(matched); 2845 } // Reverse order for parents* and prev-derivatives 2846 2847 2848 if (rparentsprev.test(name)) { 2849 matched.reverse(); 2850 } 2851 } 2852 2853 return this.pushStack(matched); 2854 }; 2855 }); 2856 var rnothtmlwhite = /[^\x20\t\r\n\f]+/g; // Convert String-formatted options into Object-formatted ones 2857 2858 function createOptions(options) { 2859 var object = {}; 2860 jQuery.each(options.match(rnothtmlwhite) || [], function (_, flag) { 2861 object[flag] = true; 2862 }); 2863 return object; 2864 } 2865 /* 2866 * Create a callback list using the following parameters: 2867 * 2868 * options: an optional list of space-separated options that will change how 2869 * the callback list behaves or a more traditional option object 2870 * 2871 * By default a callback list will act like an event callback list and can be 2872 * "fired" multiple times. 2873 * 2874 * Possible options: 2875 * 2876 * once: will ensure the callback list can only be fired once (like a Deferred) 2877 * 2878 * memory: will keep track of previous values and will call any callback added 2879 * after the list has been fired right away with the latest "memorized" 2880 * values (like a Deferred) 2881 * 2882 * unique: will ensure a callback can only be added once (no duplicate in the list) 2883 * 2884 * stopOnFalse: interrupt callings when a callback returns false 2885 * 2886 */ 2887 2888 2889 jQuery.Callbacks = function (options) { 2890 // Convert options from String-formatted to Object-formatted if needed 2891 // (we check in cache first) 2892 options = typeof options === "string" ? createOptions(options) : jQuery.extend({}, options); 2893 2894 var // Flag to know if list is currently firing 2895 firing, 2896 // Last fire value for non-forgettable lists 2897 memory, 2898 // Flag to know if list was already fired 2899 fired, 2900 // Flag to prevent firing 2901 locked, 2902 // Actual callback list 2903 list = [], 2904 // Queue of execution data for repeatable lists 2905 queue = [], 2906 // Index of currently firing callback (modified by add/remove as needed) 2907 firingIndex = -1, 2908 // Fire callbacks 2909 fire = function () { 2910 // Enforce single-firing 2911 locked = locked || options.once; // Execute callbacks for all pending executions, 2912 // respecting firingIndex overrides and runtime changes 2913 2914 fired = firing = true; 2915 2916 for (; queue.length; firingIndex = -1) { 2917 memory = queue.shift(); 2918 2919 while (++firingIndex < list.length) { 2920 // Run callback and check for early termination 2921 if (list[firingIndex].apply(memory[0], memory[1]) === false && options.stopOnFalse) { 2922 // Jump to end and forget the data so .add doesn't re-fire 2923 firingIndex = list.length; 2924 memory = false;
vendor: 19,859 bytes, lines 2925-3474
2925 } 2926 } 2927 } // Forget the data if we're done with it 2928 2929 2930 if (!options.memory) { 2931 memory = false; 2932 } 2933 2934 firing = false; // Clean up if we're done firing for good 2935 2936 if (locked) { 2937 // Keep an empty list if we have data for future add calls 2938 if (memory) { 2939 list = []; // Otherwise, this object is spent 2940 } else { 2941 list = ""; 2942 } 2943 } 2944 }, 2945 // Actual Callbacks object 2946 self = { 2947 // Add a callback or a collection of callbacks to the list 2948 add: function () { 2949 if (list) { 2950 // If we have memory from a past run, we should fire after adding 2951 if (memory && !firing) { 2952 firingIndex = list.length - 1; 2953 queue.push(memory); 2954 } 2955 2956 (function add(args) { 2957 jQuery.each(args, function (_, arg) { 2958 if (isFunction(arg)) { 2959 if (!options.unique || !self.has(arg)) { 2960 list.push(arg); 2961 } 2962 } else if (arg && arg.length && toType(arg) !== "string") { 2963 // Inspect recursively 2964 add(arg); 2965 } 2966 }); 2967 })(arguments); 2968 2969 if (memory && !firing) { 2970 fire(); 2971 } 2972 } 2973 2974 return this; 2975 }, 2976 // Remove a callback from the list 2977 remove: function () { 2978 jQuery.each(arguments, function (_, arg) { 2979 var index; 2980 2981 while ((index = jQuery.inArray(arg, list, index)) > -1) { 2982 list.splice(index, 1); // Handle firing indexes 2983 2984 if (index <= firingIndex) { 2985 firingIndex--; 2986 } 2987 } 2988 }); 2989 return this; 2990 }, 2991 // Check if a given callback is in the list. 2992 // If no argument is given, return whether or not list has callbacks attached. 2993 has: function (fn) { 2994 return fn ? jQuery.inArray(fn, list) > -1 : list.length > 0; 2995 }, 2996 // Remove all callbacks from the list 2997 empty: function () { 2998 if (list) { 2999 list = []; 3000 } 3001 3002 return this; 3003 }, 3004 // Disable .fire and .add 3005 // Abort any current/pending executions 3006 // Clear all callbacks and values 3007 disable: function () { 3008 locked = queue = []; 3009 list = memory = ""; 3010 return this; 3011 }, 3012 disabled: function () { 3013 return !list; 3014 }, 3015 // Disable .fire 3016 // Also disable .add unless we have memory (since it would have no effect) 3017 // Abort any pending executions 3018 lock: function () { 3019 locked = queue = []; 3020 3021 if (!memory && !firing) { 3022 list = memory = ""; 3023 } 3024 3025 return this; 3026 }, 3027 locked: function () { 3028 return !!locked; 3029 }, 3030 // Call all callbacks with the given context and arguments 3031 fireWith: function (context, args) { 3032 if (!locked) { 3033 args = args || []; 3034 args = [context, args.slice ? args.slice() : args]; 3035 queue.push(args); 3036 3037 if (!firing) { 3038 fire(); 3039 } 3040 } 3041 3042 return this; 3043 }, 3044 // Call all the callbacks with the given arguments 3045 fire: function () { 3046 self.fireWith(this, arguments); 3047 return this; 3048 }, 3049 // To know if the callbacks have already been called at least once 3050 fired: function () { 3051 return !!fired; 3052 } 3053 }; 3054 3055 return self; 3056 }; 3057 3058 function Identity(v) { 3059 return v; 3060 } 3061 3062 function Thrower(ex) { 3063 throw ex; 3064 } 3065 3066 function adoptValue(value, resolve, reject, noValue) { 3067 var method; 3068 3069 try { 3070 // Check for promise aspect first to privilege synchronous behavior 3071 if (value && isFunction(method = value.promise)) { 3072 method.call(value).done(resolve).fail(reject); // Other thenables 3073 } else if (value && isFunction(method = value.then)) { 3074 method.call(value, resolve, reject); // Other non-thenables 3075 } else { 3076 // Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer: 3077 // * false: [ value ].slice( 0 ) => resolve( value ) 3078 // * true: [ value ].slice( 1 ) => resolve() 3079 resolve.apply(undefined, [value].slice(noValue)); 3080 } // For Promises/A+, convert exceptions into rejections 3081 // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in 3082 // Deferred#then to conditionally suppress rejection. 3083 3084 } catch (value) { 3085 // Support: Android 4.0 only 3086 // Strict mode functions invoked without .call/.apply get global-object context 3087 reject.apply(undefined, [value]); 3088 } 3089 } 3090 3091 jQuery.extend({ 3092 Deferred: function (func) { 3093 var tuples = [// action, add listener, callbacks, 3094 // ... .then handlers, argument index, [final state] 3095 ["notify", "progress", jQuery.Callbacks("memory"), jQuery.Callbacks("memory"), 2], ["resolve", "done", jQuery.Callbacks("once memory"), jQuery.Callbacks("once memory"), 0, "resolved"], ["reject", "fail", jQuery.Callbacks("once memory"), jQuery.Callbacks("once memory"), 1, "rejected"]], 3096 state = "pending", 3097 promise = { 3098 state: function () { 3099 return state; 3100 }, 3101 always: function () { 3102 deferred.done(arguments).fail(arguments); 3103 return this; 3104 }, 3105 "catch": function (fn) { 3106 return promise.then(null, fn); 3107 }, 3108 // Keep pipe for back-compat 3109 pipe: function 3110 /* fnDone, fnFail, fnProgress */ 3111 () { 3112 var fns = arguments; 3113 return jQuery.Deferred(function (newDefer) { 3114 jQuery.each(tuples, function (i, tuple) { 3115 // Map tuples (progress, done, fail) to arguments (done, fail, progress) 3116 var fn = isFunction(fns[tuple[4]]) && fns[tuple[4]]; // deferred.progress(function() { bind to newDefer or newDefer.notify }) 3117 // deferred.done(function() { bind to newDefer or newDefer.resolve }) 3118 // deferred.fail(function() { bind to newDefer or newDefer.reject }) 3119 3120 deferred[tuple[1]](function () { 3121 var returned = fn && fn.apply(this, arguments); 3122 3123 if (returned && isFunction(returned.promise)) { 3124 returned.promise().progress(newDefer.notify).done(newDefer.resolve).fail(newDefer.reject); 3125 } else { 3126 newDefer[tuple[0] + "With"](this, fn ? [returned] : arguments); 3127 } 3128 }); 3129 }); 3130 fns = null; 3131 }).promise(); 3132 }, 3133 then: function (onFulfilled, onRejected, onProgress) { 3134 var maxDepth = 0; 3135 3136 function resolve(depth, deferred, handler, special) { 3137 return function () { 3138 var that = this, 3139 args = arguments, 3140 mightThrow = function () { 3141 var returned, then; // Support: Promises/A+ section 2.3.3.3.3 3142 // https://promisesaplus.com/#point-59 3143 // Ignore double-resolution attempts 3144 3145 if (depth < maxDepth) { 3146 return; 3147 } 3148 3149 returned = handler.apply(that, args); // Support: Promises/A+ section 2.3.1 3150 // https://promisesaplus.com/#point-48 3151 3152 if (returned === deferred.promise()) { 3153 throw new TypeError("Thenable self-resolution"); 3154 } // Support: Promises/A+ sections 2.3.3.1, 3.5 3155 // https://promisesaplus.com/#point-54 3156 // https://promisesaplus.com/#point-75 3157 // Retrieve `then` only once 3158 3159 3160 then = returned && ( // Support: Promises/A+ section 2.3.4 3161 // https://promisesaplus.com/#point-64 3162 // Only check objects and functions for thenability 3163 typeof returned === "object" || typeof returned === "function") && returned.then; // Handle a returned thenable 3164 3165 if (isFunction(then)) { 3166 // Special processors (notify) just wait for resolution 3167 if (special) { 3168 then.call(returned, resolve(maxDepth, deferred, Identity, special), resolve(maxDepth, deferred, Thrower, special)); // Normal processors (resolve) also hook into progress 3169 } else { 3170 // ...and disregard older resolution values 3171 maxDepth++; 3172 then.call(returned, resolve(maxDepth, deferred, Identity, special), resolve(maxDepth, deferred, Thrower, special), resolve(maxDepth, deferred, Identity, deferred.notifyWith)); 3173 } // Handle all other returned values 3174 3175 } else { 3176 // Only substitute handlers pass on context 3177 // and multiple values (non-spec behavior) 3178 if (handler !== Identity) { 3179 that = undefined; 3180 args = [returned]; 3181 } // Process the value(s) 3182 // Default process is resolve 3183 3184 3185 (special || deferred.resolveWith)(that, args); 3186 } 3187 }, 3188 // Only normal processors (resolve) catch and reject exceptions 3189 process = special ? mightThrow : function () { 3190 try { 3191 mightThrow(); 3192 } catch (e) { 3193 if (jQuery.Deferred.exceptionHook) { 3194 jQuery.Deferred.exceptionHook(e, process.stackTrace); 3195 } // Support: Promises/A+ section 2.3.3.3.4.1 3196 // https://promisesaplus.com/#point-61 3197 // Ignore post-resolution exceptions 3198 3199 3200 if (depth + 1 >= maxDepth) { 3201 // Only substitute handlers pass on context 3202 // and multiple values (non-spec behavior) 3203 if (handler !== Thrower) { 3204 that = undefined; 3205 args = [e]; 3206 } 3207 3208 deferred.rejectWith(that, args); 3209 } 3210 } 3211 }; // Support: Promises/A+ section 2.3.3.3.1 3212 // https://promisesaplus.com/#point-57 3213 // Re-resolve promises immediately to dodge false rejection from 3214 // subsequent errors 3215 3216 3217 if (depth) { 3218 process(); 3219 } else { 3220 // Call an optional hook to record the stack, in case of exception 3221 // since it's otherwise lost when execution goes async 3222 if (jQuery.Deferred.getStackHook) { 3223 process.stackTrace = jQuery.Deferred.getStackHook(); 3224 } 3225 3226 window.setTimeout(process); 3227 } 3228 }; 3229 } 3230 3231 return jQuery.Deferred(function (newDefer) { 3232 // progress_handlers.add( ... ) 3233 tuples[0][3].add(resolve(0, newDefer, isFunction(onProgress) ? onProgress : Identity, newDefer.notifyWith)); // fulfilled_handlers.add( ... ) 3234 3235 tuples[1][3].add(resolve(0, newDefer, isFunction(onFulfilled) ? onFulfilled : Identity)); // rejected_handlers.add( ... ) 3236 3237 tuples[2][3].add(resolve(0, newDefer, isFunction(onRejected) ? onRejected : Thrower)); 3238 }).promise(); 3239 }, 3240 // Get a promise for this deferred 3241 // If obj is provided, the promise aspect is added to the object 3242 promise: function (obj) { 3243 return obj != null ? jQuery.extend(obj, promise) : promise; 3244 } 3245 }, 3246 deferred = {}; // Add list-specific methods 3247 3248 jQuery.each(tuples, function (i, tuple) { 3249 var list = tuple[2], 3250 stateString = tuple[5]; // promise.progress = list.add 3251 // promise.done = list.add 3252 // promise.fail = list.add 3253 3254 promise[tuple[1]] = list.add; // Handle state 3255 3256 if (stateString) { 3257 list.add(function () { 3258 // state = "resolved" (i.e., fulfilled) 3259 // state = "rejected" 3260 state = stateString; 3261 }, // rejected_callbacks.disable 3262 // fulfilled_callbacks.disable 3263 tuples[3 - i][2].disable, // rejected_handlers.disable 3264 // fulfilled_handlers.disable 3265 tuples[3 - i][3].disable, // progress_callbacks.lock 3266 tuples[0][2].lock, // progress_handlers.lock 3267 tuples[0][3].lock); 3268 } // progress_handlers.fire 3269 // fulfilled_handlers.fire 3270 // rejected_handlers.fire 3271 3272 3273 list.add(tuple[3].fire); // deferred.notify = function() { deferred.notifyWith(...) } 3274 // deferred.resolve = function() { deferred.resolveWith(...) } 3275 // deferred.reject = function() { deferred.rejectWith(...) } 3276 3277 deferred[tuple[0]] = function () { 3278 deferred[tuple[0] + "With"](this === deferred ? undefined : this, arguments); 3279 return this; 3280 }; // deferred.notifyWith = list.fireWith 3281 // deferred.resolveWith = list.fireWith 3282 // deferred.rejectWith = list.fireWith 3283 3284 3285 deferred[tuple[0] + "With"] = list.fireWith; 3286 }); // Make the deferred a promise 3287 3288 promise.promise(deferred); // Call given func if any 3289 3290 if (func) { 3291 func.call(deferred, deferred); 3292 } // All done! 3293 3294 3295 return deferred; 3296 }, 3297 // Deferred helper 3298 when: function (singleValue) { 3299 var // count of uncompleted subordinates 3300 remaining = arguments.length, 3301 // count of unprocessed arguments 3302 i = remaining, 3303 // subordinate fulfillment data 3304 resolveContexts = Array(i), 3305 resolveValues = slice.call(arguments), 3306 // the master Deferred 3307 master = jQuery.Deferred(), 3308 // subordinate callback factory 3309 updateFunc = function (i) { 3310 return function (value) { 3311 resolveContexts[i] = this; 3312 resolveValues[i] = arguments.length > 1 ? slice.call(arguments) : value; 3313 3314 if (! --remaining) { 3315 master.resolveWith(resolveContexts, resolveValues); 3316 } 3317 }; 3318 }; // Single- and empty arguments are adopted like Promise.resolve 3319 3320 3321 if (remaining <= 1) { 3322 adoptValue(singleValue, master.done(updateFunc(i)).resolve, master.reject, !remaining); // Use .then() to unwrap secondary thenables (cf. gh-3000) 3323 3324 if (master.state() === "pending" || isFunction(resolveValues[i] && resolveValues[i].then)) { 3325 return master.then(); 3326 } 3327 } // Multiple arguments are aggregated like Promise.all array elements 3328 3329 3330 while (i--) { 3331 adoptValue(resolveValues[i], updateFunc(i), master.reject); 3332 } 3333 3334 return master.promise(); 3335 } 3336 }); // These usually indicate a programmer mistake during development, 3337 // warn about them ASAP rather than swallowing them by default. 3338 3339 var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/; 3340 3341 jQuery.Deferred.exceptionHook = function (error, stack) { 3342 // Support: IE 8 - 9 only 3343 // Console exists when dev tools are open, which can happen at any time 3344 if (window.console && window.console.warn && error && rerrorNames.test(error.name)) { 3345 window.console.warn("jQuery.Deferred exception: " + error.message, error.stack, stack); 3346 } 3347 }; 3348 3349 jQuery.readyException = function (error) { 3350 window.setTimeout(function () { 3351 throw error; 3352 }); 3353 }; // The deferred used on DOM ready 3354 3355 3356 var readyList = jQuery.Deferred(); 3357 3358 jQuery.fn.ready = function (fn) { 3359 readyList.then(fn) // Wrap jQuery.readyException in a function so that the lookup 3360 // happens at the time of error handling instead of callback 3361 // registration. 3362 .catch(function (error) { 3363 jQuery.readyException(error); 3364 }); 3365 return this; 3366 }; 3367 3368 jQuery.extend({ 3369 // Is the DOM ready to be used? Set to true once it occurs. 3370 isReady: false, 3371 // A counter to track how many items to wait for before 3372 // the ready event fires. See #6781 3373 readyWait: 1, 3374 // Handle when the DOM is ready 3375 ready: function (wait) { 3376 // Abort if there are pending holds or we're already ready 3377 if (wait === true ? --jQuery.readyWait : jQuery.isReady) { 3378 return; 3379 } // Remember that the DOM is ready 3380 3381 3382 jQuery.isReady = true; // If a normal DOM Ready event fired, decrement, and wait if need be 3383 3384 if (wait !== true && --jQuery.readyWait > 0) { 3385 return; 3386 } // If there are functions bound, to execute 3387 3388 3389 readyList.resolveWith(document$2, [jQuery]); 3390 } 3391 }); 3392 jQuery.ready.then = readyList.then; // The ready event handler and self cleanup method 3393 3394 function completed() { 3395 document$2.removeEventListener("DOMContentLoaded", completed); 3396 window.removeEventListener("load", completed); 3397 jQuery.ready(); 3398 } // Catch cases where $(document).ready() is called 3399 // after the browser event has already occurred. 3400 // Support: IE <=9 - 10 only 3401 // Older IE sometimes signals "interactive" too soon 3402 3403 3404 if (document$2.readyState === "complete" || document$2.readyState !== "loading" && !document$2.documentElement.doScroll) { 3405 // Handle it asynchronously to allow scripts the opportunity to delay ready 3406 window.setTimeout(jQuery.ready); 3407 } else { 3408 // Use the handy event callback 3409 document$2.addEventListener("DOMContentLoaded", completed); // A fallback to window.onload, that will always work 3410 3411 window.addEventListener("load", completed); 3412 } // Multifunctional method to get and set values of a collection 3413 // The value/s can optionally be executed if it's a function 3414 3415 3416 var access = function (elems, fn, key, value, chainable, emptyGet, raw) { 3417 var i = 0, 3418 len = elems.length, 3419 bulk = key == null; // Sets many values 3420 3421 if (toType(key) === "object") { 3422 chainable = true; 3423 3424 for (i in key) { 3425 access(elems, fn, i, key[i], true, emptyGet, raw); 3426 } // Sets one value 3427 3428 } else if (value !== undefined) { 3429 chainable = true; 3430 3431 if (!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; // ...except when executing function values 3440 } else { 3441 bulk = fn; 3442 3443 fn = function (elem, key, value) { 3444 return bulk.call(jQuery(elem), value); 3445 }; 3446 } 3447 } 3448 3449 if (fn) { 3450 for (; i < len; i++) { 3451 fn(elems[i], key, raw ? value : value.call(elems[i], i, fn(elems[i], key))); 3452 } 3453 } 3454 } 3455 3456 if (chainable) { 3457 return elems; 3458 } // Gets 3459 3460 3461 if (bulk) { 3462 return fn.call(elems); 3463 } 3464 3465 return len ? fn(elems[0], key) : emptyGet; 3466 }; // Matches dashed string for camelizing 3467 3468 3469 var rmsPrefix = /^-ms-/, 3470 rdashAlpha = /-([a-z])/g; // Used by camelCase as callback to replace() 3471 3472 function fcamelCase(all, letter) { 3473 return letter.toUpperCase(); 3474 } // Convert dashed to camelCase; used by the css and data modules
3475 // Support: IE <=9 - 11, Edge 12 - 15 3476 // Microsoft forgot to hump their vendor prefix (#9572) 3477 3478 3479 function camelCase(string) { 3480 return string.replace(rmsPrefix, "ms-").replace(rdashAlpha, fcamelCase); 3481 } 3482 3483 var acceptData = function (owner) { 3484 // Accepts only: 3485 // - Node 3486 // - Node.ELEMENT_NODE 3487 // - Node.DOCUMENT_NODE 3488 // - Object 3489 // - Any 3490 return owner.nodeType === 1 || owner.nodeType === 9 || !+owner.nodeType; 3491 }; 3492 3493 function Data() { 3494 this.expando = jQuery.expando + Data.uid++; 3495 } 3496 3497 Data.uid = 1; 3498 Data.prototype = { 3499 cache: function (owner) { 3500 // Check if the owner object already has a cache 3501 var value = owner[this.expando]; // If not, create one 3502 3503 if (!value) { 3504 value = {}; // We can accept data for non-element nodes in modern browsers, 3505 // but we should not, see #8335. 3506 // Always return an empty object. 3507 3508 if (acceptData(owner)) { 3509 // If it is a node unlikely to be stringify-ed or looped over 3510 // use plain assignment 3511 if (owner.nodeType) { 3512 owner[this.expando] = value; // Otherwise secure it in a non-enumerable property 3513 // configurable must be true to allow the property to be 3514 // deleted when data is removed 3515 } else { 3516 Object.defineProperty(owner, this.expando, { 3517 value: value, 3518 configurable: true 3519 }); 3520 } 3521 } 3522 } 3523 3524 return value; 3525 }, 3526 set: function (owner, data, value) { 3527 var prop, 3528 cache = this.cache(owner); // Handle: [ owner, key, value ] args 3529 // Always use camelCase key (gh-2257) 3530 3531 if (typeof data === "string") { 3532 cache[camelCase(data)] = value; // Handle: [ owner, { properties } ] args 3533 } else { 3534 // Copy the properties one-by-one to the cache object 3535 for (prop in data) { 3536 cache[camelCase(prop)] = data[prop]; 3537 } 3538 } 3539 3540 return cache; 3541 }, 3542 get: function (owner, key) { 3543 return key === undefined ? this.cache(owner) : // Always use camelCase key (gh-2257) 3544 owner[this.expando] && owner[this.expando][camelCase(key)]; 3545 }, 3546 access: function (owner, key, value) { 3547 // In cases where either: 3548 // 3549 // 1. No key was specified 3550 // 2. A string key was specified, but no value provided 3551 // 3552 // Take the "read" path and allow the get method to determine 3553 // which value to return, respectively either: 3554 // 3555 // 1. The entire cache object 3556 // 2. The data stored at the key 3557 // 3558 if (key === undefined || key && typeof key === "string" && value === undefined) { 3559 return this.get(owner, key); 3560 } // When the key is not a string, or both a key and value 3561 // are specified, set or extend (existing objects) with either: 3562 // 3563 // 1. An object of properties 3564 // 2. A key and value 3565 // 3566 3567 3568 this.set(owner, key, value); // Since the "set" path can have two possible entry points 3569 // return the expected data based on which path was taken[*] 3570 3571 return value !== undefined ? value : key; 3572 }, 3573 remove: function (owner, key) { 3574 var i, 3575 cache = owner[this.expando]; 3576 3577 if (cache === undefined) { 3578 return; 3579 } 3580 3581 if (key !== undefined) { 3582 // Support array or space separated string of keys 3583 if (Array.isArray(key)) { 3584 // If key is an array of keys... 3585 // We always set camelCase keys, so remove that. 3586 key = key.map(camelCase); 3587 } else { 3588 key = camelCase(key); // If a key with the spaces exists, use it. 3589 // Otherwise, create an array by matching non-whitespace 3590 3591 key = key in cache ? [key] : key.match(rnothtmlwhite) || []; 3592 } 3593 3594 i = key.length; 3595 3596 while (i--) { 3597 delete cache[key[i]]; 3598 } 3599 } // Remove the expando if there's no more data 3600 3601 3602 if (key === undefined || jQuery.isEmptyObject(cache)) {
vendor: 9,050 bytes, lines 3603-3911
3603 // Support: Chrome <=35 - 45 3604 // Webkit & Blink performance suffers when deleting properties 3605 // from DOM nodes, so set to undefined instead 3606 // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted) 3607 if (owner.nodeType) { 3608 owner[this.expando] = undefined; 3609 } else { 3610 delete owner[this.expando]; 3611 } 3612 } 3613 }, 3614 hasData: function (owner) { 3615 var cache = owner[this.expando]; 3616 return cache !== undefined && !jQuery.isEmptyObject(cache); 3617 } 3618 }; 3619 var dataPriv = new Data(); 3620 var dataUser = new Data(); // Implementation Summary 3621 // 3622 // 1. Enforce API surface and semantic compatibility with 1.9.x branch 3623 // 2. Improve the module's maintainability by reducing the storage 3624 // paths to a single mechanism. 3625 // 3. Use the same single mechanism to support "private" and "user" data. 3626 // 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData) 3627 // 5. Avoid exposing implementation details on user objects (eg. expando properties) 3628 // 6. Provide a clear path for implementation upgrade to WeakMap in 2014 3629 3630 var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, 3631 rmultiDash = /[A-Z]/g; 3632 3633 function getData(data) { 3634 if (data === "true") { 3635 return true; 3636 } 3637 3638 if (data === "false") { 3639 return false; 3640 } 3641 3642 if (data === "null") { 3643 return null; 3644 } // Only convert to a number if it doesn't change the string 3645 3646 3647 if (data === +data + "") { 3648 return +data; 3649 } 3650 3651 if (rbrace.test(data)) { 3652 return JSON.parse(data); 3653 } 3654 3655 return data; 3656 } 3657 3658 function dataAttr(elem, key, data) { 3659 var name; // If nothing was found internally, try to fetch any 3660 // data from the HTML5 data-* attribute 3661 3662 if (data === undefined && elem.nodeType === 1) { 3663 name = "data-" + key.replace(rmultiDash, "-$&").toLowerCase(); 3664 data = elem.getAttribute(name); 3665 3666 if (typeof data === "string") { 3667 try { 3668 data = getData(data); 3669 } catch (e) {} // Make sure we set the data so it isn't changed later 3670 3671 3672 dataUser.set(elem, key, data); 3673 } else { 3674 data = undefined; 3675 } 3676 } 3677 3678 return data; 3679 } 3680 3681 jQuery.extend({ 3682 hasData: function (elem) { 3683 return dataUser.hasData(elem) || dataPriv.hasData(elem); 3684 }, 3685 data: function (elem, name, data) { 3686 return dataUser.access(elem, name, data); 3687 }, 3688 removeData: function (elem, name) { 3689 dataUser.remove(elem, name); 3690 }, 3691 // TODO: Now that all calls to _data and _removeData have been replaced 3692 // with direct calls to dataPriv methods, these can be deprecated. 3693 _data: function (elem, name, data) { 3694 return dataPriv.access(elem, name, data); 3695 }, 3696 _removeData: function (elem, name) { 3697 dataPriv.remove(elem, name); 3698 } 3699 }); 3700 jQuery.fn.extend({ 3701 data: function (key, value) { 3702 var i, 3703 name, 3704 data, 3705 elem = this[0], 3706 attrs = elem && elem.attributes; // Gets all values 3707 3708 if (key === undefined) { 3709 if (this.length) { 3710 data = dataUser.get(elem); 3711 3712 if (elem.nodeType === 1 && !dataPriv.get(elem, "hasDataAttrs")) { 3713 i = attrs.length; 3714 3715 while (i--) { 3716 // Support: IE 11 only 3717 // The attrs elements can be null (#14894) 3718 if (attrs[i]) { 3719 name = attrs[i].name; 3720 3721 if (name.indexOf("data-") === 0) { 3722 name = camelCase(name.slice(5)); 3723 dataAttr(elem, name, data[name]); 3724 } 3725 } 3726 } 3727 3728 dataPriv.set(elem, "hasDataAttrs", true); 3729 } 3730 } 3731 3732 return data; 3733 } // Sets multiple values 3734 3735 3736 if (typeof key === "object") { 3737 return this.each(function () { 3738 dataUser.set(this, key); 3739 }); 3740 } 3741 3742 return access(this, function (value) { 3743 var data; // The calling jQuery object (element matches) is not empty 3744 // (and therefore has an element appears at this[ 0 ]) and the 3745 // `value` parameter was not undefined. An empty jQuery object 3746 // will result in `undefined` for elem = this[ 0 ] which will 3747 // throw an exception if an attempt to read a data cache is made. 3748 3749 if (elem && value === undefined) { 3750 // Attempt to get data from the cache 3751 // The key will always be camelCased in Data 3752 data = dataUser.get(elem, key); 3753 3754 if (data !== undefined) { 3755 return data; 3756 } // Attempt to "discover" the data in 3757 // HTML5 custom data-* attrs 3758 3759 3760 data = dataAttr(elem, key); 3761 3762 if (data !== undefined) { 3763 return data; 3764 } // We tried really hard, but the data doesn't exist. 3765 3766 3767 return; 3768 } // Set the data... 3769 3770 3771 this.each(function () { 3772 // We always store the camelCased key 3773 dataUser.set(this, key, value); 3774 }); 3775 }, null, value, arguments.length > 1, null, true); 3776 }, 3777 removeData: function (key) { 3778 return this.each(function () { 3779 dataUser.remove(this, key); 3780 }); 3781 } 3782 }); 3783 jQuery.extend({ 3784 queue: function (elem, type, data) { 3785 var queue; 3786 3787 if (elem) { 3788 type = (type || "fx") + "queue"; 3789 queue = dataPriv.get(elem, type); // Speed up dequeue by getting out quickly if this is just a lookup 3790 3791 if (data) { 3792 if (!queue || Array.isArray(data)) { 3793 queue = dataPriv.access(elem, type, jQuery.makeArray(data)); 3794 } else { 3795 queue.push(data); 3796 } 3797 } 3798 3799 return queue || []; 3800 } 3801 }, 3802 dequeue: function (elem, type) { 3803 type = type || "fx"; 3804 3805 var queue = jQuery.queue(elem, type), 3806 startLength = queue.length, 3807 fn = queue.shift(), 3808 hooks = jQuery._queueHooks(elem, type), 3809 next = function () { 3810 jQuery.dequeue(elem, type); 3811 }; // If the fx queue is dequeued, always remove the progress sentinel 3812 3813 3814 if (fn === "inprogress") { 3815 fn = queue.shift(); 3816 startLength--; 3817 } 3818 3819 if (fn) { 3820 // Add a progress sentinel to prevent the fx queue from being 3821 // automatically dequeued 3822 if (type === "fx") { 3823 queue.unshift("inprogress"); 3824 } // Clear up the last queue stop function 3825 3826 3827 delete hooks.stop; 3828 fn.call(elem, next, hooks); 3829 } 3830 3831 if (!startLength && hooks) { 3832 hooks.empty.fire(); 3833 } 3834 }, 3835 // Not public - generate a queueHooks object, or return the current one 3836 _queueHooks: function (elem, type) { 3837 var key = type + "queueHooks"; 3838 return dataPriv.get(elem, key) || dataPriv.access(elem, key, { 3839 empty: jQuery.Callbacks("once memory").add(function () { 3840 dataPriv.remove(elem, [type + "queue", key]); 3841 }) 3842 }); 3843 } 3844 }); 3845 jQuery.fn.extend({ 3846 queue: function (type, data) { 3847 var setter = 2; 3848 3849 if (typeof type !== "string") { 3850 data = type; 3851 type = "fx"; 3852 setter--; 3853 } 3854 3855 if (arguments.length < setter) { 3856 return jQuery.queue(this[0], type); 3857 } 3858 3859 return data === undefined ? this : this.each(function () { 3860 var queue = jQuery.queue(this, type, data); // Ensure a hooks for this queue 3861 3862 jQuery._queueHooks(this, type); 3863 3864 if (type === "fx" && queue[0] !== "inprogress") { 3865 jQuery.dequeue(this, type); 3866 } 3867 }); 3868 }, 3869 dequeue: function (type) { 3870 return this.each(function () { 3871 jQuery.dequeue(this, type); 3872 }); 3873 }, 3874 clearQueue: function (type) { 3875 return this.queue(type || "fx", []); 3876 }, 3877 // Get a promise resolved when queues of a certain type 3878 // are emptied (fx is the type by default) 3879 promise: function (type, obj) { 3880 var tmp, 3881 count = 1, 3882 defer = jQuery.Deferred(), 3883 elements = this, 3884 i = this.length, 3885 resolve = function () { 3886 if (! --count) { 3887 defer.resolveWith(elements, [elements]); 3888 } 3889 }; 3890 3891 if (typeof type !== "string") { 3892 obj = type; 3893 type = undefined; 3894 } 3895 3896 type = type || "fx"; 3897 3898 while (i--) { 3899 tmp = dataPriv.get(elements[i], type + "queueHooks"); 3900 3901 if (tmp && tmp.empty) { 3902 count++; 3903 tmp.empty.add(resolve); 3904 } 3905 } 3906 3907 resolve(); 3908 return defer.promise(obj); 3909 } 3910 }); 3911 var pnum = /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source;
3912 var rcssNum = new RegExp("^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i"); 3913 var cssExpand = ["Top", "Right", "Bottom", "Left"]; 3914 3915 var isHiddenWithinTree = function (elem, el) { 3916 // isHiddenWithinTree might be called from jQuery#filter function; 3917 // in that case, element will be second argument 3918 elem = el || elem; // Inline style trumps all 3919 3920 return elem.style.display === "none" || elem.style.display === "" && // Otherwise, check computed style 3921 // Support: Firefox <=43 - 45 3922 // Disconnected elements can have computed display: none, so first confirm that elem is 3923 // in the document. 3924 jQuery.contains(elem.ownerDocument, elem) && jQuery.css(elem, "display") === "none"; 3925 }; 3926 3927 var swap = function (elem, options, callback, args) { 3928 var ret, 3929 name, 3930 old = {}; // Remember the old values, and insert the new ones 3931 3932 for (name in options) { 3933 old[name] = elem.style[name]; 3934 elem.style[name] = options[name]; 3935 } 3936 3937 ret = callback.apply(elem, args || []); // Revert the old values 3938 3939 for (name in options) { 3940 elem.style[name] = old[name]; 3941 } 3942 3943 return ret; 3944 }; 3945 3946 function adjustCSS(elem, prop, valueParts, tween) { 3947 var adjusted, 3948 scale, 3949 maxIterations = 20, 3950 currentValue = tween ? function () { 3951 return tween.cur(); 3952 } : function () { 3953 return jQuery.css(elem, prop, ""); 3954 }, 3955 initial = currentValue(), 3956 unit = valueParts && valueParts[3] || (jQuery.cssNumber[prop] ? "" : "px"), 3957 // Starting value computation is required for potential unit mismatches 3958 initialInUnit = (jQuery.cssNumber[prop] || unit !== "px" && +initial) && rcssNum.exec(jQuery.css(elem, prop)); 3959 3960 if (initialInUnit && initialInUnit[3] !== unit) { 3961 // Support: Firefox <=54 3962 // Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144) 3963 initial = initial / 2; // Trust units reported by jQuery.css 3964 3965 unit = unit || initialInUnit[3]; // Iteratively approximate from a nonzero starting point 3966 3967 initialInUnit = +initial || 1; 3968 3969 while (maxIterations--) { 3970 // Evaluate and update our best guess (doubling guesses that zero out). 3971 // Finish if the scale equals or crosses 1 (making the old*new product non-positive). 3972 jQuery.style(elem, prop, initialInUnit + unit); 3973 3974 if ((1 - scale) * (1 - (scale = currentValue() / initial || 0.5)) <= 0) { 3975 maxIterations = 0; 3976 } 3977 3978 initialInUnit = initialInUnit / scale; 3979 } 3980 3981 initialInUnit = initialInUnit * 2; 3982 jQuery.style(elem, prop, initialInUnit + unit); // Make sure we update the tween properties later on 3983 3984 valueParts = valueParts || []; 3985 } 3986 3987 if (valueParts) { 3988 initialInUnit = +initialInUnit || +initial || 0; // Apply relative offset (+=/-=) if specified 3989 3990 adjusted = valueParts[1] ? initialInUnit + (valueParts[1] + 1) * valueParts[2] : +valueParts[2]; 3991 3992 if (tween) { 3993 tween.unit = unit; 3994 tween.start = initialInUnit; 3995 tween.end = adjusted; 3996 } 3997 } 3998 3999 return adjusted; 4000 } 4001 4002 var defaultDisplayMap = {}; 4003 4004 function getDefaultDisplay(elem) { 4005 var temp, 4006 doc = elem.ownerDocument, 4007 nodeName = elem.nodeName, 4008 display = defaultDisplayMap[nodeName]; 4009 4010 if (display) { 4011 return display; 4012 } 4013 4014 temp = doc.body.appendChild(doc.createElement(nodeName)); 4015 display = jQuery.css(temp, "display"); 4016 temp.parentNode.removeChild(temp); 4017 4018 if (display === "none") { 4019 display = "block"; 4020 } 4021 4022 defaultDisplayMap[nodeName] = display; 4023 return display; 4024 } 4025 4026 function showHide(elements, show) { 4027 var display, 4028 elem, 4029 values = [], 4030 index = 0, 4031 length = elements.length; // Determine new display value for elements that need to change 4032 4033 for (; index < length; index++) { 4034 elem = elements[index]; 4035 4036 if (!elem.style) { 4037 continue; 4038 } 4039 4040 display = elem.style.display; 4041 4042 if (show) {
vendor: 6,155 bytes, lines 4043-4237
4043 // Since we force visibility upon cascade-hidden elements, an immediate (and slow) 4044 // check is required in this first loop unless we have a nonempty display value (either 4045 // inline or about-to-be-restored) 4046 if (display === "none") { 4047 values[index] = dataPriv.get(elem, "display") || null; 4048 4049 if (!values[index]) { 4050 elem.style.display = ""; 4051 } 4052 } 4053 4054 if (elem.style.display === "" && isHiddenWithinTree(elem)) { 4055 values[index] = getDefaultDisplay(elem); 4056 } 4057 } else { 4058 if (display !== "none") { 4059 values[index] = "none"; // Remember what we're overwriting 4060 4061 dataPriv.set(elem, "display", display); 4062 } 4063 } 4064 } // Set the display of the elements in a second loop to avoid constant reflow 4065 4066 4067 for (index = 0; index < length; index++) { 4068 if (values[index] != null) { 4069 elements[index].style.display = values[index]; 4070 } 4071 } 4072 4073 return elements; 4074 } 4075 4076 jQuery.fn.extend({ 4077 show: function () { 4078 return showHide(this, true); 4079 }, 4080 hide: function () { 4081 return showHide(this); 4082 }, 4083 toggle: function (state) { 4084 if (typeof state === "boolean") { 4085 return state ? this.show() : this.hide(); 4086 } 4087 4088 return this.each(function () { 4089 if (isHiddenWithinTree(this)) { 4090 jQuery(this).show(); 4091 } else { 4092 jQuery(this).hide(); 4093 } 4094 }); 4095 } 4096 }); 4097 var rcheckableType = /^(?:checkbox|radio)$/i; 4098 var rtagName = /<([a-z][^\/\0>\x20\t\r\n\f]+)/i; 4099 var rscriptType = /^$|^module$|\/(?:java|ecma)script/i; // We have to close these tags to support XHTML (#13200) 4100 4101 var wrapMap = { 4102 // Support: IE <=9 only 4103 option: [1, "<select multiple='multiple'>", "</select>"], 4104 // XHTML parsers do not magically insert elements in the 4105 // same way that tag soup parsers do. So we cannot shorten 4106 // this by omitting <tbody> or other required elements. 4107 thead: [1, "<table>", "</table>"], 4108 col: [2, "<table><colgroup>", "</colgroup></table>"], 4109 tr: [2, "<table><tbody>", "</tbody></table>"], 4110 td: [3, "<table><tbody><tr>", "</tr></tbody></table>"], 4111 _default: [0, "", ""] 4112 }; // Support: IE <=9 only 4113 4114 wrapMap.optgroup = wrapMap.option; 4115 wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; 4116 wrapMap.th = wrapMap.td; 4117 4118 function getAll(context, tag) { 4119 // Support: IE <=9 - 11 only 4120 // Use typeof to avoid zero-argument method invocation on host objects (#15151) 4121 var ret; 4122 4123 if (typeof context.getElementsByTagName !== "undefined") { 4124 ret = context.getElementsByTagName(tag || "*"); 4125 } else if (typeof context.querySelectorAll !== "undefined") { 4126 ret = context.querySelectorAll(tag || "*"); 4127 } else { 4128 ret = []; 4129 } 4130 4131 if (tag === undefined || tag && nodeName(context, tag)) { 4132 return jQuery.merge([context], ret); 4133 } 4134 4135 return ret; 4136 } // Mark scripts as having already been evaluated 4137 4138 4139 function setGlobalEval(elems, refElements) { 4140 var i = 0, 4141 l = elems.length; 4142 4143 for (; i < l; i++) { 4144 dataPriv.set(elems[i], "globalEval", !refElements || dataPriv.get(refElements[i], "globalEval")); 4145 } 4146 } 4147 4148 var rhtml = /<|&#?\w+;/; 4149 4150 function buildFragment(elems, context, scripts, selection, ignored) { 4151 var elem, 4152 tmp, 4153 tag, 4154 wrap, 4155 contains, 4156 j, 4157 fragment = context.createDocumentFragment(), 4158 nodes = [], 4159 i = 0, 4160 l = elems.length; 4161 4162 for (; i < l; i++) { 4163 elem = elems[i]; 4164 4165 if (elem || elem === 0) { 4166 // Add nodes directly 4167 if (toType(elem) === "object") { 4168 // Support: Android <=4.0 only, PhantomJS 1 only 4169 // push.apply(_, arraylike) throws on ancient WebKit 4170 jQuery.merge(nodes, elem.nodeType ? [elem] : elem); // Convert non-html into a text node 4171 } else if (!rhtml.test(elem)) { 4172 nodes.push(context.createTextNode(elem)); // Convert html into DOM nodes 4173 } else { 4174 tmp = tmp || fragment.appendChild(context.createElement("div")); // Deserialize a standard representation 4175 4176 tag = (rtagName.exec(elem) || ["", ""])[1].toLowerCase(); 4177 wrap = wrapMap[tag] || wrapMap._default; 4178 tmp.innerHTML = wrap[1] + jQuery.htmlPrefilter(elem) + wrap[2]; // Descend through wrappers to the right content 4179 4180 j = wrap[0]; 4181 4182 while (j--) { 4183 tmp = tmp.lastChild; 4184 } // Support: Android <=4.0 only, PhantomJS 1 only 4185 // push.apply(_, arraylike) throws on ancient WebKit 4186 4187 4188 jQuery.merge(nodes, tmp.childNodes); // Remember the top-level container 4189 4190 tmp = fragment.firstChild; // Ensure the created nodes are orphaned (#12392) 4191 4192 tmp.textContent = ""; 4193 } 4194 } 4195 } // Remove wrapper from fragment 4196 4197 4198 fragment.textContent = ""; 4199 i = 0; 4200 4201 while (elem = nodes[i++]) { 4202 // Skip elements already in the context collection (trac-4087) 4203 if (selection && jQuery.inArray(elem, selection) > -1) { 4204 if (ignored) { 4205 ignored.push(elem); 4206 } 4207 4208 continue; 4209 } 4210 4211 contains = jQuery.contains(elem.ownerDocument, elem); // Append to fragment 4212 4213 tmp = getAll(fragment.appendChild(elem), "script"); // Preserve script evaluation history 4214 4215 if (contains) { 4216 setGlobalEval(tmp); 4217 } // Capture executables 4218 4219 4220 if (scripts) { 4221 j = 0; 4222 4223 while (elem = tmp[j++]) { 4224 if (rscriptType.test(elem.type || "")) { 4225 scripts.push(elem); 4226 } 4227 } 4228 } 4229 } 4230 4231 return fragment; 4232 } 4233 4234 (function () { 4235 var fragment = document$2.createDocumentFragment(), 4236 div = fragment.appendChild(document$2.createElement("div")), 4237 input = document$2.createElement("input");
vendor: 12,157 bytes, lines 4237-4595
4237 // Support: Android 4.0 - 4.3 only 4238 // Check state lost if the name is set (#11217) 4239 // Support: Windows Web Apps (WWA) 4240 // `name` and `type` must use .setAttribute for WWA (#14901) 4241 4242 input.setAttribute("type", "radio"); 4243 input.setAttribute("checked", "checked"); 4244 input.setAttribute("name", "t"); 4245 div.appendChild(input); // Support: Android <=4.1 only 4246 // Older WebKit doesn't clone checked state correctly in fragments 4247 4248 support.checkClone = div.cloneNode(true).cloneNode(true).lastChild.checked; // Support: IE <=11 only 4249 // Make sure textarea (and checkbox) defaultValue is properly cloned 4250 4251 div.innerHTML = "<textarea>x</textarea>"; 4252 support.noCloneChecked = !!div.cloneNode(true).lastChild.defaultValue; 4253 })(); 4254 4255 var documentElement = document$2.documentElement; 4256 var rkeyEvent = /^key/, 4257 rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/, 4258 rtypenamespace = /^([^.]*)(?:\.(.+)|)/; 4259 4260 function returnTrue() { 4261 return true; 4262 } 4263 4264 function returnFalse() { 4265 return false; 4266 } // Support: IE <=9 only 4267 // See #13393 for more info 4268 4269 4270 function safeActiveElement() { 4271 try { 4272 return document$2.activeElement; 4273 } catch (err) {} 4274 } 4275 4276 function on(elem, types, selector, data, fn, one) { 4277 var origFn, type; // Types can be a map of types/handlers 4278 4279 if (typeof types === "object") { 4280 // ( types-Object, selector, data ) 4281 if (typeof selector !== "string") { 4282 // ( types-Object, data ) 4283 data = data || selector; 4284 selector = undefined; 4285 } 4286 4287 for (type in types) { 4288 on(elem, type, selector, data, types[type], one); 4289 } 4290 4291 return elem; 4292 } 4293 4294 if (data == null && fn == null) { 4295 // ( types, fn ) 4296 fn = selector; 4297 data = selector = undefined; 4298 } else if (fn == null) { 4299 if (typeof selector === "string") { 4300 // ( types, selector, fn ) 4301 fn = data; 4302 data = undefined; 4303 } else { 4304 // ( types, data, fn ) 4305 fn = data; 4306 data = selector; 4307 selector = undefined; 4308 } 4309 } 4310 4311 if (fn === false) { 4312 fn = returnFalse; 4313 } else if (!fn) { 4314 return elem; 4315 } 4316 4317 if (one === 1) { 4318 origFn = fn; 4319 4320 fn = function (event) { 4321 // Can use an empty set, since event contains the info 4322 jQuery().off(event); 4323 return origFn.apply(this, arguments); 4324 }; // Use same guid so caller can remove using origFn 4325 4326 4327 fn.guid = origFn.guid || (origFn.guid = jQuery.guid++); 4328 } 4329 4330 return elem.each(function () { 4331 jQuery.event.add(this, types, fn, data, selector); 4332 }); 4333 } 4334 /* 4335 * Helper functions for managing events -- not part of the public interface. 4336 * Props to Dean Edwards' addEvent library for many of the ideas. 4337 */ 4338 4339 4340 jQuery.event = { 4341 global: {}, 4342 add: function (elem, types, handler, data, selector) { 4343 var handleObjIn, 4344 eventHandle, 4345 tmp, 4346 events, 4347 t, 4348 handleObj, 4349 special, 4350 handlers, 4351 type, 4352 namespaces, 4353 origType, 4354 elemData = dataPriv.get(elem); // Don't attach events to noData or text/comment nodes (but allow plain objects) 4355 4356 if (!elemData) { 4357 return; 4358 } // Caller can pass in an object of custom data in lieu of the handler 4359 4360 4361 if (handler.handler) { 4362 handleObjIn = handler; 4363 handler = handleObjIn.handler; 4364 selector = handleObjIn.selector; 4365 } // Ensure that invalid selectors throw exceptions at attach time 4366 // Evaluate against documentElement in case elem is a non-element node (e.g., document) 4367 4368 4369 if (selector) { 4370 jQuery.find.matchesSelector(documentElement, selector); 4371 } // Make sure that the handler has a unique ID, used to find/remove it later 4372 4373 4374 if (!handler.guid) { 4375 handler.guid = jQuery.guid++; 4376 } // Init the element's event structure and main handler, if this is the first 4377 4378 4379 if (!(events = elemData.events)) { 4380 events = elemData.events = {}; 4381 } 4382 4383 if (!(eventHandle = elemData.handle)) { 4384 eventHandle = elemData.handle = function (e) { 4385 // Discard the second event of a jQuery.event.trigger() and 4386 // when an event is called after a page has unloaded 4387 return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ? jQuery.event.dispatch.apply(elem, arguments) : undefined; 4388 }; 4389 } // Handle multiple events separated by a space 4390 4391 4392 types = (types || "").match(rnothtmlwhite) || [""]; 4393 t = types.length; 4394 4395 while (t--) { 4396 tmp = rtypenamespace.exec(types[t]) || []; 4397 type = origType = tmp[1]; 4398 namespaces = (tmp[2] || "").split(".").sort(); // There *must* be a type, no attaching namespace-only handlers 4399 4400 if (!type) { 4401 continue; 4402 } // If event changes its type, use the special event handlers for the changed type 4403 4404 4405 special = jQuery.event.special[type] || {}; // If selector defined, determine special event api type, otherwise given type 4406 4407 type = (selector ? special.delegateType : special.bindType) || type; // Update special based on newly reset type 4408 4409 special = jQuery.event.special[type] || {}; // handleObj is passed to all event handlers 4410 4411 handleObj = jQuery.extend({ 4412 type: type, 4413 origType: origType, 4414 data: data, 4415 handler: handler, 4416 guid: handler.guid, 4417 selector: selector, 4418 needsContext: selector && jQuery.expr.match.needsContext.test(selector), 4419 namespace: namespaces.join(".") 4420 }, handleObjIn); // Init the event handler queue if we're the first 4421 4422 if (!(handlers = events[type])) { 4423 handlers = events[type] = []; 4424 handlers.delegateCount = 0; // Only use addEventListener if the special events handler returns false 4425 4426 if (!special.setup || special.setup.call(elem, data, namespaces, eventHandle) === false) { 4427 if (elem.addEventListener) { 4428 elem.addEventListener(type, eventHandle); 4429 } 4430 } 4431 } 4432 4433 if (special.add) { 4434 special.add.call(elem, handleObj); 4435 4436 if (!handleObj.handler.guid) { 4437 handleObj.handler.guid = handler.guid; 4438 } 4439 } // Add to the element's handler list, delegates in front 4440 4441 4442 if (selector) { 4443 handlers.splice(handlers.delegateCount++, 0, handleObj); 4444 } else { 4445 handlers.push(handleObj); 4446 } // Keep track of which events have ever been used, for event optimization 4447 4448 4449 jQuery.event.global[type] = true; 4450 } 4451 }, 4452 // Detach an event or set of events from an element 4453 remove: function (elem, types, handler, selector, mappedTypes) { 4454 var j, 4455 origCount, 4456 tmp, 4457 events, 4458 t, 4459 handleObj, 4460 special, 4461 handlers, 4462 type, 4463 namespaces, 4464 origType, 4465 elemData = dataPriv.hasData(elem) && dataPriv.get(elem); 4466 4467 if (!elemData || !(events = elemData.events)) { 4468 return; 4469 } // Once for each type.namespace in types; type may be omitted 4470 4471 4472 types = (types || "").match(rnothtmlwhite) || [""]; 4473 t = types.length; 4474 4475 while (t--) { 4476 tmp = rtypenamespace.exec(types[t]) || []; 4477 type = origType = tmp[1]; 4478 namespaces = (tmp[2] || "").split(".").sort(); // Unbind all events (on this namespace, if provided) for the element 4479 4480 if (!type) { 4481 for (type in events) { 4482 jQuery.event.remove(elem, type + types[t], handler, selector, true); 4483 } 4484 4485 continue; 4486 } 4487 4488 special = jQuery.event.special[type] || {}; 4489 type = (selector ? special.delegateType : special.bindType) || type; 4490 handlers = events[type] || []; 4491 tmp = tmp[2] && new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)"); // Remove matching events 4492 4493 origCount = j = handlers.length; 4494 4495 while (j--) { 4496 handleObj = handlers[j]; 4497 4498 if ((mappedTypes || origType === handleObj.origType) && (!handler || handler.guid === handleObj.guid) && (!tmp || tmp.test(handleObj.namespace)) && (!selector || selector === handleObj.selector || selector === "**" && handleObj.selector)) { 4499 handlers.splice(j, 1); 4500 4501 if (handleObj.selector) { 4502 handlers.delegateCount--; 4503 } 4504 4505 if (special.remove) { 4506 special.remove.call(elem, handleObj); 4507 } 4508 } 4509 } // Remove generic event handler if we removed something and no more handlers exist 4510 // (avoids potential for endless recursion during removal of special event handlers) 4511 4512 4513 if (origCount && !handlers.length) { 4514 if (!special.teardown || special.teardown.call(elem, namespaces, elemData.handle) === false) { 4515 jQuery.removeEvent(elem, type, elemData.handle); 4516 } 4517 4518 delete events[type]; 4519 } 4520 } // Remove data and the expando if it's no longer used 4521 4522 4523 if (jQuery.isEmptyObject(events)) { 4524 dataPriv.remove(elem, "handle events"); 4525 } 4526 }, 4527 dispatch: function (nativeEvent) { 4528 // Make a writable jQuery.Event from the native event object 4529 var event = jQuery.event.fix(nativeEvent); 4530 var i, 4531 j, 4532 ret, 4533 matched, 4534 handleObj, 4535 handlerQueue, 4536 args = new Array(arguments.length), 4537 handlers = (dataPriv.get(this, "events") || {})[event.type] || [], 4538 special = jQuery.event.special[event.type] || {}; // Use the fix-ed jQuery.Event rather than the (read-only) native event 4539 4540 args[0] = event; 4541 4542 for (i = 1; i < arguments.length; i++) { 4543 args[i] = arguments[i]; 4544 } 4545 4546 event.delegateTarget = this; // Call the preDispatch hook for the mapped type, and let it bail if desired 4547 4548 if (special.preDispatch && special.preDispatch.call(this, event) === false) { 4549 return; 4550 } // Determine handlers 4551 4552 4553 handlerQueue = jQuery.event.handlers.call(this, event, handlers); // Run delegates first; they may want to stop propagation beneath us 4554 4555 i = 0; 4556 4557 while ((matched = handlerQueue[i++]) && !event.isPropagationStopped()) { 4558 event.currentTarget = matched.elem; 4559 j = 0; 4560 4561 while ((handleObj = matched.handlers[j++]) && !event.isImmediatePropagationStopped()) { 4562 // Triggered event must either 1) have no namespace, or 2) have namespace(s) 4563 // a subset or equal to those in the bound event (both can have no namespace). 4564 if (!event.rnamespace || event.rnamespace.test(handleObj.namespace)) { 4565 event.handleObj = handleObj; 4566 event.data = handleObj.data; 4567 ret = ((jQuery.event.special[handleObj.origType] || {}).handle || handleObj.handler).apply(matched.elem, args); 4568 4569 if (ret !== undefined) { 4570 if ((event.result = ret) === false) { 4571 event.preventDefault(); 4572 event.stopPropagation(); 4573 } 4574 } 4575 } 4576 } 4577 } // Call the postDispatch hook for the mapped type 4578 4579 4580 if (special.postDispatch) { 4581 special.postDispatch.call(this, event); 4582 } 4583 4584 return event.result; 4585 }, 4586 handlers: function (event, handlers) { 4587 var i, 4588 handleObj, 4589 sel, 4590 matchedHandlers, 4591 matchedSelectors, 4592 handlerQueue = [], 4593 delegateCount = handlers.delegateCount, 4594 cur = event.target; // Find delegate handlers 4595
4596 if (delegateCount && // Support: IE <=9 4597 // Black-hole SVG <use> instance trees (trac-13180) 4598 cur.nodeType && // Support: Firefox <=42 4599 // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861) 4600 // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click 4601 // Support: IE 11 only 4602 // ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343) 4603 !(event.type === "click" && event.button >= 1)) { 4604 for (; cur !== this; cur = cur.parentNode || this) { 4605 // Don't check non-elements (#13208) 4606 // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) 4607 if (cur.nodeType === 1 && !(event.type === "click" && cur.disabled === true)) { 4608 matchedHandlers = []; 4609 matchedSelectors = {}; 4610 4611 for (i = 0; i < delegateCount; i++) { 4612 handleObj = handlers[i]; // Don't conflict with Object.prototype properties (#13203) 4613 4614 sel = handleObj.selector + " "; 4615 4616 if (matchedSelectors[sel] === undefined) { 4617 matchedSelectors[sel] = handleObj.needsContext ? jQuery(sel, this).index(cur) > -1 : jQuery.find(sel, this, null, [cur]).length; 4618 } 4619 4620 if (matchedSelectors[sel]) { 4621 matchedHandlers.push(handleObj); 4622 } 4623 } 4624 4625 if (matchedHandlers.length) { 4626 handlerQueue.push({ 4627 elem: cur, 4628 handlers: matchedHandlers 4629 }); 4630 } 4631 } 4632 } 4633 } // Add the remaining (directly-bound) handlers 4634 4635 4636 cur = this; 4637 4638 if (delegateCount < handlers.length) { 4639 handlerQueue.push({ 4640 elem: cur, 4641 handlers: handlers.slice(delegateCount) 4642 }); 4643 } 4644 4645 return handlerQueue; 4646 }, 4647 addProp: function (name, hook) { 4648 Object.defineProperty(jQuery.Event.prototype, name, { 4649 enumerable: true, 4650 configurable: true, 4651 get: isFunction(hook) ? function () { 4652 if (this.originalEvent) { 4653 return hook(this.originalEvent); 4654 } 4655 } : function () { 4656 if (this.originalEvent) { 4657 return this.originalEvent[name]; 4658 } 4659 }, 4660 set: function (value) { 4661 Object.defineProperty(this, name, { 4662 enumerable: true, 4663 configurable: true, 4664 writable: true, 4665 value: value 4666 }); 4667 } 4668 }); 4669 }, 4670 fix: function (originalEvent) { 4671 return originalEvent[jQuery.expando] ? originalEvent : new jQuery.Event(originalEvent); 4672 }, 4673 special: { 4674 load: { 4675 // Prevent triggered image.load events from bubbling to window.load 4676 noBubble: true 4677 }, 4678 focus: { 4679 // Fire native event if possible so blur/focus sequence is correct 4680 trigger: function () { 4681 if (this !== safeActiveElement() && this.focus) { 4682 this.focus(); 4683 return false; 4684 } 4685 }, 4686 delegateType: "focusin" 4687 }, 4688 blur: { 4689 trigger: function () { 4690 if (this === safeActiveElement() && this.blur) { 4691 this.blur(); 4692 return false; 4693 } 4694 }, 4695 delegateType: "focusout" 4696 }, 4697 click: { 4698 // For checkbox, fire native event so checked state will be right 4699 trigger: function () { 4700 if (this.type === "checkbox" && this.click && nodeName(this, "input")) { 4701 this.click(); 4702 return false; 4703 } 4704 }, 4705 // For cross-browser consistency, don't fire native .click() on links 4706 _default: function (event) { 4707 return nodeName(event.target, "a"); 4708 } 4709 }, 4710 beforeunload: { 4711 postDispatch: function (event) { 4712 // Support: Firefox 20+ 4713 // Firefox doesn't alert if the returnValue field is not set. 4714 if (event.result !== undefined && event.originalEvent) { 4715 event.originalEvent.returnValue = event.result; 4716 } 4717 } 4718 } 4719 } 4720 }; 4721 4722 jQuery.removeEvent = function (elem, type, handle) { 4723 // This "if" is needed for plain objects 4724 if (elem.removeEventListener) { 4725 elem.removeEventListener(type, handle); 4726 } 4727 }; 4728 4729 jQuery.Event = function (src, props) { 4730 // Allow instantiation without the 'new' keyword 4731 if (!(this instanceof jQuery.Event)) { 4732 return new jQuery.Event(src, props); 4733 } // Event object 4734 4735 4736 if (src && src.type) { 4737 this.originalEvent = src; 4738 this.type = src.type; // Events bubbling up the document may have been marked as prevented 4739 // by a handler lower down the tree; reflect the correct value. 4740 4741 this.isDefaultPrevented = src.defaultPrevented || src.defaultPrevented === undefined && // Supp
4741ort: Android <=2.3 only 4742 src.returnValue === false ? returnTrue : returnFalse; // Create target properties 4743 // Support: Safari <=6 - 7 only 4744 // Target should not be a text node (#504, #13143) 4745 4746 this.target = src.target && src.target.nodeType === 3 ? src.target.parentNode : src.target; 4747 this.currentTarget = src.currentTarget; 4748 this.relatedTarget = src.relatedTarget; // Event type 4749 } else { 4750 this.type = src; 4751 } // Put explicitly provided properties onto the event object 4752 4753 4754 if (props) { 4755 jQuery.extend(this, props); 4756 } // Create a timestamp if incoming event doesn't have one 4757 4758 4759 this.timeStamp = src && src.timeStamp || Date.now(); // Mark it as fixed 4760 4761 this[jQuery.expando] = true; 4762 }; // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding 4763 // https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html 4764 4765 4766 jQuery.Event.prototype = { 4767 constructor: jQuery.Event, 4768 isDefaultPrevented: returnFalse, 4769 isPropagationStopped: returnFalse, 4770 isImmediatePropagationStopped: returnFalse, 4771 isSimulated: false, 4772 preventDefault: function () { 4773 var e = this.originalEvent; 4774 this.isDefaultPrevented = returnTrue; 4775 4776 if (e && !this.isSimulated) { 4777 e.preventDefault(); 4778 } 4779 }, 4780 stopPropagation: function () { 4781 var e = this.originalEvent; 4782 this.isPropagationStopped = returnTrue; 4783 4784 if (e && !this.isSimulated) { 4785 e.stopPropagation(); 4786 } 4787 }, 4788 stopImmediatePropagation: function () { 4789 var e = this.originalEvent; 4790 this.isImmediatePropagationStopped = returnTrue; 4791 4792 if (e && !this.isSimulated) { 4793 e.stopImmediatePropagation(); 4794 } 4795 4796 this.stopPropagation(); 4797 } 4798 }; // Includes all common event props including KeyEvent and MouseEvent specific props 4799 4800 jQuery.each({ 4801 altKey: true, 4802 bubbles: true, 4803 cancelable: true, 4804 changedTouches: true, 4805 ctrlKey: true, 4806 detail: true, 4807 eventPhase: true, 4808 metaKey: true, 4809 pageX: true, 4810 pageY: true, 4811 shiftKey: true, 4812 view: true, 4813 "char": true, 4814 charCode: true, 4815 key: true, 4816 keyCode: true, 4817 button: true, 4818 buttons: true, 4819 clientX: true, 4820 clientY: true, 4821 offsetX: true, 4822 offsetY: true, 4823 pointerId: true, 4824 pointerType: true, 4825 screenX: true, 4826 screenY: true, 4827 targetTouches: true, 4828 toElement: true, 4829 touches: true, 4830 which: function (event) { 4831 var button = event.button; // Add which for key events 4832 4833 if (event.which == null && rkeyEvent.test(event.type)) { 4834 return event.charCode != null ? event.charCode : event.keyCode; 4835 } // Add which for click: 1 === left; 2 === middle; 3 === right 4836 4837 4838 if (!event.which && button !== undefined && rmouseEvent.test(event.type)) { 4839 if (button & 1) { 4840 return 1; 4841 } 4842 4843 if (button & 2) { 4844 return 3; 4845 } 4846 4847 if (button & 4) { 4848 return 2; 4849 } 4850 4851 return 0; 4852 } 4853 4854 return event.which; 4855 } 4856 }, jQuery.event.addProp); // Create mouseenter/leave events using mouseover/out and event-time checks 4857 // so that event delegation works in jQuery. 4858 // Do the same for pointerenter/pointerleave and pointerover/pointerout 4859 // 4860 // Support: Safari 7 only 4861 // Safari sends mouseenter too often; see: 4862 // https://bugs.chromium.org/p/chromium/issues/detail?id=470258 4863 // for the description of the bug (it existed in older Chrome versions as well). 4864 4865 jQuery.each({ 4866 mouseenter: "mouseover", 4867 mouseleave: "mouseout", 4868 pointerenter: "pointerover", 4869 pointerleave: "pointerout" 4870 }, function (orig, fix) { 4871 jQuery.event.special[orig] = { 4872 delegateType: fix, 4873 bindType: fix, 4874 handle: function (event) { 4875 var ret, 4876 target = this, 4877 related = event.relatedTarget, 4878 handleObj = event.handleObj; // For mouseenter/leave call the handler if related is outside the target. 4879 // NB: No relatedTarget if the mouse left/entered the browser window 4880 4881 if (!related || related !== target && !jQuery.contains(target, related)) { 4882 event.type = handleObj.origType; 4883 ret = handleObj.handler.apply(this, arguments); 4884 event.type = fix; 4885 } 4886 4887 return ret; 4888 } 4889 }; 4890 }); 4891 jQuery.fn.extend({ 4892 on: function (types, selector, data, fn) { 4893 return on(this, types, selector, data, fn); 4894 }, 4895 one: function (types, selector, data, fn) { 4896 return on(this, types, selector, data, fn, 1); 4897 }, 4898 off: function (types, selector, fn) { 4899 var handleObj, type; 4900 4901 if (types && types.preventDefault && types.handleObj) { 4902 // ( event ) dispatched jQuery.Event 4903 handleObj = types.handleObj; 4904 jQuery(types.delegateTarget).off(handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType, handleObj.selector, handleObj.handler); 4905 return this; 4906 } 4907 4908 if (typeof types === "object") { 4909 // ( types-object [, selector] ) 4910 for (type in types) { 4911 this.off(type, selector, types[type]); 4912 } 4913 4914 return this; 4915 } 4916 4917 if (selector === false || typeof selector === "function") { 4918 // ( types [, fn] ) 4919 fn = selector; 4920 selector = undefined; 4921 } 4922 4923 if (fn === false) { 4924 fn = returnFalse; 4925 } 4926 4927 return this.each(function () { 4928 jQuery.event.remove(this, types, fn, selector); 4929 }); 4930 } 4931 }); 4932 var 4933 /* eslint-disable max-len */ 4934 // See https://github.com/eslint/eslint/issues/3229 4935 rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi, 4936 4937 /* eslint-enable */
4938 // Support: IE <=10 - 11, Edge 12 - 13 only 4939 // In IE/Edge using regex groups here causes severe slowdowns. 4940 // See https://connect.microsoft.com/IE/feedback/details/1736512/ 4941 rnoInnerhtml = /
vendor: 4,855 bytes, lines 4941-5081
4941<script|<style|<link/i, 4942 // checked="checked" or checked 4943 rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i, 4944 rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g; // Prefer a tbody over its parent table for containing new rows 4945 4946 function manipulationTarget(elem, content) { 4947 if (nodeName(elem, "table") && nodeName(content.nodeType !== 11 ? content : content.firstChild, "tr")) { 4948 return jQuery(elem).children("tbody")[0] || elem; 4949 } 4950 4951 return elem; 4952 } // Replace/restore the type attribute of script elements for safe DOM manipulation 4953 4954 4955 function disableScript(elem) { 4956 elem.type = (elem.getAttribute("type") !== null) + "/" + elem.type; 4957 return elem; 4958 } 4959 4960 function restoreScript(elem) { 4961 if ((elem.type || "").slice(0, 5) === "true/") { 4962 elem.type = elem.type.slice(5); 4963 } else { 4964 elem.removeAttribute("type"); 4965 } 4966 4967 return elem; 4968 } 4969 4970 function cloneCopyEvent(src, dest) { 4971 var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events; 4972 4973 if (dest.nodeType !== 1) { 4974 return; 4975 } // 1. Copy private data: events, handlers, etc. 4976 4977 4978 if (dataPriv.hasData(src)) { 4979 pdataOld = dataPriv.access(src); 4980 pdataCur = dataPriv.set(dest, pdataOld); 4981 events = pdataOld.events; 4982 4983 if (events) { 4984 delete pdataCur.handle; 4985 pdataCur.events = {}; 4986 4987 for (type in events) { 4988 for (i = 0, l = events[type].length; i < l; i++) { 4989 jQuery.event.add(dest, type, events[type][i]); 4990 } 4991 } 4992 } 4993 } // 2. Copy user data 4994 4995 4996 if (dataUser.hasData(src)) { 4997 udataOld = dataUser.access(src); 4998 udataCur = jQuery.extend({}, udataOld); 4999 dataUser.set(dest, udataCur); 5000 } 5001 } // Fix IE bugs, see support tests 5002 5003 5004 function fixInput(src, dest) { 5005 var nodeName = dest.nodeName.toLowerCase(); // Fails to persist the checked state of a cloned checkbox or radio button. 5006 5007 if (nodeName === "input" && rcheckableType.test(src.type)) { 5008 dest.checked = src.checked; // Fails to return the selected option to the default selected state when cloning options 5009 } else if (nodeName === "input" || nodeName === "textarea") { 5010 dest.defaultValue = src.defaultValue; 5011 } 5012 } 5013 5014 function domManip(collection, args, callback, ignored) { 5015 // Flatten any nested arrays 5016 args = concat$1.apply([], args); 5017 var fragment, 5018 first, 5019 scripts, 5020 hasScripts, 5021 node, 5022 doc, 5023 i = 0, 5024 l = collection.length, 5025 iNoClone = l - 1, 5026 value = args[0], 5027 valueIsFunction = isFunction(value); // We can't cloneNode fragments that contain checked, in WebKit 5028 5029 if (valueIsFunction || l > 1 && typeof value === "string" && !support.checkClone && rchecked.test(value)) { 5030 return collection.each(function (index) { 5031 var self = collection.eq(index); 5032 5033 if (valueIsFunction) { 5034 args[0] = value.call(this, index, self.html()); 5035 } 5036 5037 domManip(self, args, callback, ignored); 5038 }); 5039 } 5040 5041 if (l) { 5042 fragment = buildFragment(args, collection[0].ownerDocument, false, collection, ignored); 5043 first = fragment.firstChild; 5044 5045 if (fragment.childNodes.length === 1) { 5046 fragment = first; 5047 } // Require either new content or an interest in ignored elements to invoke the callback 5048 5049 5050 if (first || ignored) { 5051 scripts = jQuery.map(getAll(fragment, "script"), disableScript); 5052 hasScripts = scripts.length; // Use the original fragment for the last item 5053 // instead of the first because it can end up 5054 // being emptied incorrectly in certain situations (#8070). 5055 5056 for (; i < l; i++) { 5057 node = fragment; 5058 5059 if (i !== iNoClone) { 5060 node = jQuery.clone(node, true, true); // Keep references to cloned scripts for later restoration 5061 5062 if (hasScripts) { 5063 // Support: Android <=4.0 only, PhantomJS 1 only 5064 // push.apply(_, arraylike) throws on ancient WebKit 5065 jQuery.merge(scripts, getAll(node, "script")); 5066 } 5067 } 5068 5069 callback.call(collection[i], node, i); 5070 } 5071 5072 if (hasScripts) { 5073 doc = scripts[scripts.length - 1].ownerDocument; // Reenable scripts 5074 5075 jQuery.map(scripts, restoreScript); // Evaluate executable scripts on first document insertion 5076 5077 for (i = 0; i < hasScripts; i++) { 5078 node = scripts[i]; 5079 5080 if (rscriptType.test(node.type || "") && !dataPriv.access(node, "globalEval") && jQuery.contains(doc, node)) { 5081 if (node.src && (node.type || "").toLowerCase() !== "module") {
vendor: 6,351 bytes, lines 5082-5279
5082 // Optional AJAX dependency, but won't run scripts if not present 5083 if (jQuery._evalUrl) { 5084 jQuery._evalUrl(node.src); 5085 } 5086 } else { 5087 DOMEval(node.textContent.replace(rcleanScript, ""), doc, node); 5088 } 5089 } 5090 } 5091 } 5092 } 5093 } 5094 5095 return collection; 5096 } 5097 5098 function remove(elem, selector, keepData) { 5099 var node, 5100 nodes = selector ? jQuery.filter(selector, elem) : elem, 5101 i = 0; 5102 5103 for (; (node = nodes[i]) != null; i++) { 5104 if (!keepData && node.nodeType === 1) { 5105 jQuery.cleanData(getAll(node)); 5106 } 5107 5108 if (node.parentNode) { 5109 if (keepData && jQuery.contains(node.ownerDocument, node)) { 5110 setGlobalEval(getAll(node, "script")); 5111 } 5112 5113 node.parentNode.removeChild(node); 5114 } 5115 } 5116 5117 return elem; 5118 } 5119 5120 jQuery.extend({ 5121 htmlPrefilter: function (html) { 5122 return html.replace(rxhtmlTag, "<$1></$2>"); 5123 }, 5124 clone: function (elem, dataAndEvents, deepDataAndEvents) { 5125 var i, 5126 l, 5127 srcElements, 5128 destElements, 5129 clone = elem.cloneNode(true), 5130 inPage = jQuery.contains(elem.ownerDocument, elem); // Fix IE cloning issues 5131 5132 if (!support.noCloneChecked && (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem)) { 5133 // We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2 5134 destElements = getAll(clone); 5135 srcElements = getAll(elem); 5136 5137 for (i = 0, l = srcElements.length; i < l; i++) { 5138 fixInput(srcElements[i], destElements[i]); 5139 } 5140 } // Copy the events from the original to the clone 5141 5142 5143 if (dataAndEvents) { 5144 if (deepDataAndEvents) { 5145 srcElements = srcElements || getAll(elem); 5146 destElements = destElements || getAll(clone); 5147 5148 for (i = 0, l = srcElements.length; i < l; i++) { 5149 cloneCopyEvent(srcElements[i], destElements[i]); 5150 } 5151 } else { 5152 cloneCopyEvent(elem, clone); 5153 } 5154 } // Preserve script evaluation history 5155 5156 5157 destElements = getAll(clone, "script"); 5158 5159 if (destElements.length > 0) { 5160 setGlobalEval(destElements, !inPage && getAll(elem, "script")); 5161 } // Return the cloned set 5162 5163 5164 return clone; 5165 }, 5166 cleanData: function (elems) { 5167 var data, 5168 elem, 5169 type, 5170 special = jQuery.event.special, 5171 i = 0; 5172 5173 for (; (elem = elems[i]) !== undefined; i++) { 5174 if (acceptData(elem)) { 5175 if (data = elem[dataPriv.expando]) { 5176 if (data.events) { 5177 for (type in data.events) { 5178 if (special[type]) { 5179 jQuery.event.remove(elem, type); // This is a shortcut to avoid jQuery.event.remove's overhead 5180 } else { 5181 jQuery.removeEvent(elem, type, data.handle); 5182 } 5183 } 5184 } // Support: Chrome <=35 - 45+ 5185 // Assign undefined instead of using delete, see Data#remove 5186 5187 5188 elem[dataPriv.expando] = undefined; 5189 } 5190 5191 if (elem[dataUser.expando]) { 5192 // Support: Chrome <=35 - 45+ 5193 // Assign undefined instead of using delete, see Data#remove 5194 elem[dataUser.expando] = undefined; 5195 } 5196 } 5197 } 5198 } 5199 }); 5200 jQuery.fn.extend({ 5201 detach: function (selector) { 5202 return remove(this, selector, true); 5203 }, 5204 remove: function (selector) { 5205 return remove(this, selector); 5206 }, 5207 text: function (value) { 5208 return access(this, function (value) { 5209 return value === undefined ? jQuery.text(this) : this.empty().each(function () { 5210 if (this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9) { 5211 this.textContent = value; 5212 } 5213 }); 5214 }, null, value, arguments.length); 5215 }, 5216 append: function () { 5217 return domManip(this, arguments, function (elem) { 5218 if (this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9) { 5219 var target = manipulationTarget(this, elem); 5220 target.appendChild(elem); 5221 } 5222 }); 5223 }, 5224 prepend: function () { 5225 return domManip(this, arguments, function (elem) { 5226 if (this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9) { 5227 var target = manipulationTarget(this, elem); 5228 target.insertBefore(elem, target.firstChild); 5229 } 5230 }); 5231 }, 5232 before: function () { 5233 return domManip(this, arguments, function (elem) { 5234 if (this.parentNode) { 5235 this.parentNode.insertBefore(elem, this); 5236 } 5237 }); 5238 }, 5239 after: function () { 5240 return domManip(this, arguments, function (elem) { 5241 if (this.parentNode) { 5242 this.parentNode.insertBefore(elem, this.nextSibling); 5243 } 5244 }); 5245 }, 5246 empty: function () { 5247 var elem, 5248 i = 0; 5249 5250 for (; (elem = this[i]) != null; i++) { 5251 if (elem.nodeType === 1) { 5252 // Prevent memory leaks 5253 jQuery.cleanData(getAll(elem, false)); // Remove any remaining nodes 5254 5255 elem.textContent = ""; 5256 } 5257 } 5258 5259 return this; 5260 }, 5261 clone: function (dataAndEvents, deepDataAndEvents) { 5262 dataAndEvents = dataAndEvents == null ? false : dataAndEvents; 5263 deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; 5264 return this.map(function () { 5265 return jQuery.clone(this, dataAndEvents, deepDataAndEvents); 5266 }); 5267 }, 5268 html: function (value) { 5269 return access(this, function (value) { 5270 var elem = this[0] || {}, 5271 i = 0, 5272 l = this.length; 5273 5274 if (value === undefined && elem.nodeType === 1) { 5275 return elem.innerHTML; 5276 } // See if we can take a shortcut and just use innerHTML 5277 5278 5279 if (typeof value === "string" && !rnoInnerhtml.test(value) && !wrapMap[
vendor: 4,584 bytes, lines 5279-5403
5279(rtagName.exec(value) || ["", ""])[1].toLowerCase()]) { 5280 value = jQuery.htmlPrefilter(value); 5281 5282 try { 5283 for (; i < l; i++) { 5284 elem = this[i] || {}; // Remove element nodes and prevent memory leaks 5285 5286 if (elem.nodeType === 1) { 5287 jQuery.cleanData(getAll(elem, false)); 5288 elem.innerHTML = value; 5289 } 5290 } 5291 5292 elem = 0; // If using innerHTML throws an exception, use the fallback method 5293 } catch (e) {} 5294 } 5295 5296 if (elem) { 5297 this.empty().append(value); 5298 } 5299 }, null, value, arguments.length); 5300 }, 5301 replaceWith: function () { 5302 var ignored = []; // Make the changes, replacing each non-ignored context element with the new content 5303 5304 return domManip(this, arguments, function (elem) { 5305 var parent = this.parentNode; 5306 5307 if (jQuery.inArray(this, ignored) < 0) { 5308 jQuery.cleanData(getAll(this)); 5309 5310 if (parent) { 5311 parent.replaceChild(elem, this); 5312 } 5313 } // Force callback invocation 5314 5315 }, ignored); 5316 } 5317 }); 5318 jQuery.each({ 5319 appendTo: "append", 5320 prependTo: "prepend", 5321 insertBefore: "before", 5322 insertAfter: "after", 5323 replaceAll: "replaceWith" 5324 }, function (name, original) { 5325 jQuery.fn[name] = function (selector) { 5326 var elems, 5327 ret = [], 5328 insert = jQuery(selector), 5329 last = insert.length - 1, 5330 i = 0; 5331 5332 for (; i <= last; i++) { 5333 elems = i === last ? this : this.clone(true); 5334 jQuery(insert[i])[original](elems); // Support: Android <=4.0 only, PhantomJS 1 only 5335 // .get() because push.apply(_, arraylike) throws on ancient WebKit 5336 5337 push$1.apply(ret, elems.get()); 5338 } 5339 5340 return this.pushStack(ret); 5341 }; 5342 }); 5343 var rnumnonpx = new RegExp("^(" + pnum + ")(?!px)[a-z%]+$", "i"); 5344 5345 var getStyles = function (elem) { 5346 // Support: IE <=11 only, Firefox <=30 (#15098, #14150) 5347 // IE throws on elements created in popups 5348 // FF meanwhile throws on frame elements through "defaultView.getComputedStyle" 5349 var view = elem.ownerDocument.defaultView; 5350 5351 if (!view || !view.opener) { 5352 view = window; 5353 } 5354 5355 return view.getComputedStyle(elem); 5356 }; 5357 5358 var rboxStyle = new RegExp(cssExpand.join("|"), "i"); 5359 5360 (function () { 5361 // Executing both pixelPosition & boxSizingReliable tests require only one layout 5362 // so they're executed at the same time to save the second computation. 5363 function computeStyleTests() { 5364 // This is a singleton, we need to execute it only once 5365 if (!div) { 5366 return; 5367 } 5368 5369 container.style.cssText = "position:absolute;left:-11111px;width:60px;" + "margin-top:1px;padding:0;border:0"; 5370 div.style.cssText = "position:relative;display:block;box-sizing:border-box;overflow:scroll;" + "margin:auto;border:1px;padding:1px;" + "width:60%;top:1%"; 5371 documentElement.appendChild(container).appendChild(div); 5372 var divStyle = window.getComputedStyle(div); 5373 pixelPositionVal = divStyle.top !== "1%"; // Support: Android 4.0 - 4.3 only, Firefox <=3 - 44 5374 5375 reliableMarginLeftVal = roundPixelMeasures(divStyle.marginLeft) === 12; // Support: Android 4.0 - 4.3 only, Safari <=9.1 - 10.1, iOS <=7.0 - 9.3 5376 // Some styles come back with percentage values, even though they shouldn't 5377 5378 div.style.right = "60%"; 5379 pixelBoxStylesVal = roundPixelMeasures(divStyle.right) === 36; // Support: IE 9 - 11 only 5380 // Detect misreporting of content dimensions for box-sizing:border-box elements 5381 5382 boxSizingReliableVal = roundPixelMeasures(divStyle.width) === 36; // Support: IE 9 only 5383 // Detect overflow:scroll screwiness (gh-3699) 5384 5385 div.style.position = "absolute"; 5386 scrollboxSizeVal = div.offsetWidth === 36 || "absolute"; 5387 documentElement.removeChild(container); // Nullify the div so it wouldn't be stored in the memory and 5388 // it will also be a sign that checks already performed 5389 5390 div = null; 5391 } 5392 5393 function roundPixelMeasures(measure) { 5394 return Math.round(parseFloat(measure)); 5395 } 5396 5397 var pixelPositionVal, 5398 boxSizingReliableVal, 5399 scrollboxSizeVal, 5400 pixelBoxStylesVal, 5401 reliableMarginLeftVal, 5402 container = document$2.createElement("div"), 5403 div = document$2.createElement("div");
5403 // Finish early in limited (non-browser) environments 5404 5405 if (!div.style) { 5406 return; 5407 } // Support: IE <=9 - 11 only 5408 // Style of cloned element affects source element cloned (#8908) 5409 5410 5411 div.style.backgroundClip = "content-box"; 5412 div.cloneNode(true).style.backgroundClip = ""; 5413 support.clearCloneStyle = div.style.backgroundClip === "content-box"; 5414 jQuery.extend(support, { 5415 boxSizingReliable: function () { 5416 computeStyleTests(); 5417 return boxSizingReliableVal; 5418 }, 5419 pixelBoxStyles: function () { 5420 computeStyleTests(); 5421 return pixelBoxStylesVal; 5422 }, 5423 pixelPosition: function () { 5424 computeStyleTests(); 5425 return pixelPositionVal; 5426 }, 5427 reliableMarginLeft: function () { 5428 computeStyleTests(); 5429 return reliableMarginLeftVal; 5430 }, 5431 scrollboxSize: function () { 5432 computeStyleTests(); 5433 return scrollboxSizeVal; 5434 } 5435 }); 5436 })(); 5437 5438 function curCSS(elem, name, computed) { 5439 var width, 5440 minWidth, 5441 maxWidth, 5442 ret, 5443 // Support: Firefox 51+ 5444 // Retrieving style before computed somehow 5445 // fixes an issue with getting wrong values 5446 // on detached elements 5447 style = elem.style; 5448 computed = computed || getStyles(elem); // getPropertyValue is needed for: 5449 // .css('filter') (IE 9 only, #12537) 5450 // .css('--customProperty) (#3144) 5451 5452 if (computed) { 5453 ret = computed.getPropertyValue(name) || computed[name]; 5454 5455 if (ret === "" && !jQuery.contains(elem.ownerDocument, elem)) { 5456 ret = jQuery.style(elem, name); 5457 } // A tribute to the "awesome hack by Dean Edwards" 5458 // Android Browser returns percentage for some values, 5459 // but width seems to be reliably pixels. 5460 // This is against the CSSOM draft spec: 5461 // https://drafts.csswg.org/cssom/#resolved-values 5462 5463 5464 if (!support.pixelBoxStyles() && rnumnonpx.test(ret) && rboxStyle.test(name)) { 5465 // Remember the original values 5466 width = style.width; 5467 minWidth = style.minWidth; 5468 maxWidth = style.maxWidth; // Put in the new values to get a computed value out 5469 5470 style.minWidth = style.maxWidth = style.width = ret; 5471 ret = computed.width; // Revert the changed values 5472 5473 style.width = width; 5474 style.minWidth = minWidth; 5475 style.maxWidth = maxWidth; 5476 } 5477 } 5478 5479 return ret !== undefined ? // Support: IE <=9 - 11 only 5480 // IE returns zIndex value as an integer. 5481 ret + "" : ret; 5482 } 5483 5484 function addGetHookIf(conditionFn, hookFn) { 5485 // Define the hook, we'll check on the first run if it's really needed. 5486 return { 5487 get: function () { 5488 if (conditionFn()) { 5489 // Hook not needed (or it's not possible to use it due 5490 // to missing dependency), remove it. 5491 delete this.get; 5492 return; 5493 } // Hook needed; redefine it so that the support test is not executed again. 5494 5495 5496 return (this.get = hookFn).apply(this, arguments); 5497 } 5498 }; 5499 } 5500 5501 var // Swappable if display is none or starts with table 5502 // except "table", "table-cell", or "table-caption" 5503 // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display 5504 rdisplayswap = /^(none|table(?!-c[ea]).+)/, 5505 rcustomProp = /^--/, 5506 cssShow = { 5507 position: "absolute", 5508 visibility: "hidden", 5509 display: "block" 5510 }, 5511 cssNormalTransform = { 5512 letterSpacing: "0", 5513 fontWeight: "400" 5514 }, 5515 cssPrefixes = ["Webkit", "Moz", "ms"], 5516 emptyStyle = document$2.createElement("div").style; // Return a css property mapped to a potentially vendor prefixed property 5517 5518 function vendorPropName(name) { 5519 // Shortcut for names that are not vendor prefixed 5520 if (name in emptyStyle) { 5521 return name; 5522 } // Check for vendor prefixed names 5523 5524 5525 var capName = name[0].toUpperCase() + name.slice(1), 5526 i = cssPrefixes.length; 5527 5528 while (i--) { 5529 name = cssPrefixes[i] + capName; 5530 5531 if (name in emptyStyle) { 5532 return name; 5533 } 5534 } 5535 } // Return a property mapped along what jQuery.cssProps suggests or to 5536 // a vendor prefixed property. 5537 5538 5539 function finalPropName(name) { 5540 var ret = jQuery.cssProps[name]; 5541 5542 if (!ret) { 5543 ret = jQuery.cssProps[name] = vendorPropName(name) || name; 5544 } 5545 5546 return ret; 5547 } 5548 5549 function setPositiveNumber(elem, value, subtract) { 5550 // Any relative (+/-) values have already been 5551 // normalized at this point 5552 var matches = rcssNum.exec(value); 5553 return matches ? // Guard against undefined "subtract", e.g., when used as in cssHooks 5554 Math.max(0, matches[2] - (subtract || 0)) + (matches[3] || "px") : value; 5555 } 5556 5557 function boxModelAdjustment(elem, dimension, box, isBorderBox, styles, computedVal) { 5558 var i = dimension === "width" ? 1 : 0, 5559 extra = 0, 5560 delta = 0; // Adjustment may not be necessary 5561 5562 if (box === (isBorderBox ? "border" : "content")) { 5563 return 0; 5564 } 5565 5566 for (; i < 4; i += 2) { 5567 // Both box models exclude margin 5568 if (box === "margin") { 5569 delta += jQuery.css(elem, box + cssExpand[i], true, styles); 5570 } // If we get here with a content-box, we're seeking "padding" or "border" or "margin" 5571 5572 5573 if (!isBorderBox) { 5574 // Add padding 5575 delta += jQuery.css(elem, "padding" + cssExpand[i], true, styles); // For "border" or "margin", add border 5576 5577 if (box !== "padding") { 5578 delta += jQuery.css(elem, "border" + cssExpand[i] + "Width", true, styles); // But still keep track of it otherwise 5579 } else { 5580 extra += jQuery.css(elem, "border" + cssExpand[i] + "Width", true, styles); 5581 } // If we get here with a border-box (content + padding + border), we're seeking "content" or 5582 // "padding" or "margin" 5583 5584 } else { 5585 // For "content", subtract padding 5586 if (box === "content") { 5587 delta -= jQuery.css(elem, "padding" + cssExpand[i], true, styles); 5588 } // For "content" or "padding", subtract border 5589 5590 5591 if (box !== "margin") { 5592 delta -= jQuery.css(elem, "border" + cssExpand[i] + "Width", true, styles); 5593 } 5594 } 5595 } // Account for positive content-box scroll gutter when requested by providing computedVal 5596 5597 5598 if (!isBorderBox && computedVal >= 0) { 5599 // offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border 5600 // Assuming integer scroll gutter, subtract the rest and round down 5601 delta += Math.max(0, Math.ceil(elem["offset" + dimension[0].toUpperCase() + dimension.slice(1)] - computedVal - delta - extra - 0.5)); 5602 } 5603 5604 return delta; 5605 } 5606 5607 function getWidthOrHeight(elem, dimension, extra) { 5608 // Start with computed style 5609 var styles = getStyles(elem), 5610 val = curCSS(elem, dimension, styles), 5611 isBorderBox = jQuery.css(elem, "boxSizing", false, styles) === "border-box", 5612 valueIsBorderBox = isBorderBox;
5612 // Support: Firefox <=54 5613 // Return a confounding non-pixel value or feign ignorance, as appropriate. 5614 5615 if (rnumnonpx.test(val)) { 5616 if (!extra) { 5617 return val; 5618 } 5619 5620 val = "auto"; 5621 } // Check for style in case a browser which returns unreliable values 5622 // for getComputedStyle silently falls back to the reliable elem.style 5623 5624 5625 valueIsBorderBox = valueIsBorderBox && (support.boxSizingReliable() || val === elem.style[dimension]); // Fall back to offsetWidth/offsetHeight when value is "auto" 5626 // This happens for inline elements with no explicit setting (gh-3571) 5627 // Support: Android <=4.1 - 4.3 only 5628 // Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602) 5629 5630 if (val === "auto" || !parseFloat(val) && jQuery.css(elem, "display", false, styles) === "inline") { 5631 val = elem["offset" + dimension[0].toUpperCase() + dimension.slice(1)]; // offsetWidth/offsetHeight provide border-box values 5632 5633 valueIsBorderBox = true; 5634 } // Normalize "" and auto 5635 5636 5637 val = parseFloat(val) || 0; // Adjust for the element's box model 5638 5639 return val + boxModelAdjustment(elem, dimension, extra || (isBorderBox ? "border" : "content"), valueIsBorderBox, styles, // Provide the current computed size to request scroll gutter calculation (gh-3589) 5640 val) + "px"; 5641 } 5642 5643 jQuery.extend({ 5644 // Add in style property hooks for overriding the default 5645 // behavior of getting and setting a style property 5646 cssHooks: { 5647 opacity: { 5648 get: function (elem, computed) { 5649 if (computed) { 5650 // We should always get a number back from opacity 5651 var ret = curCSS(elem, "opacity"); 5652 return ret === "" ? "1" : ret; 5653 } 5654 } 5655 } 5656 }, 5657 // Don't automatically add "px" to these possibly-unitless properties 5658 cssNumber: { 5659 "animationIterationCount": true, 5660 "columnCount": true, 5661 "fillOpacity": true, 5662 "flexGrow": true, 5663 "flexShrink": true, 5664 "fontWeight": true, 5665 "lineHeight": true, 5666 "opacity": true, 5667 "order": true, 5668 "orphans": true, 5669 "widows": true, 5670 "zIndex": true, 5671 "zoom": true 5672 }, 5673 // Add in properties whose names you wish to fix before 5674 // setting or getting the value 5675 cssProps: {}, 5676 // Get and set the style property on a DOM Node 5677 style: function (elem, name, value, extra) { 5678 // Don't set styles on text and comment nodes 5679 if (!elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style) { 5680 return; 5681 } // Make sure that we're working with the right name 5682 5683 5684 var ret, 5685 type, 5686 hooks, 5687 origName = camelCase(name), 5688 isCustomProp = rcustomProp.test(name), 5689 style = elem.style; // Make sure that we're working with the right name. We don't 5690 // want to query the value if it is a CSS custom property 5691 // since they are user-defined. 5692 5693 if (!isCustomProp) { 5694 name = finalPropName(origName); 5695 } // Gets hook for the prefixed version, then unprefixed version 5696 5697 5698 hooks = jQuery.cssHooks[name] || jQuery.cssHooks[origName]; // Check if we're setting a value 5699 5700 if (value !== undefined) { 5701 type = typeof value; // Convert "+=" or "-=" to relative numbers (#7345) 5702 5703 if (type === "string" && (ret = rcssNum.exec(value)) && ret[1]) { 5704 value = adjustCSS(elem, name, ret); // Fixes bug #9237 5705 5706 type = "number"; 5707 } // Make sure that null and NaN values aren't set (#7116) 5708 5709 5710 if (value == null || value !== value) { 5711 return; 5712 } // If a number was passed in, add the unit (except for certain CSS properties) 5713 5714 5715 if (type === "number") { 5716 value += ret && ret[3] || (jQuery.cssNumber[origName] ? "" : "px"); 5717 } // background-* props affect original clone's values 5718 5719 5720 if (!support.clearCloneStyle && value === "" && name.indexOf("background") === 0) { 5721 style[name] = "inherit"; 5722 } // If a hook was provided, use that value, otherwise just set the specified value 5723 5724 5725 if (!hooks || !("set" in hooks) || (value = hooks.set(elem, value, extra)) !== undefined) { 5726 if (isCustomProp) { 5727 style.setProperty(name, value); 5728 } else { 5729 style[name] = value; 5730 } 5731 } 5732 } else { 5733 // If a hook was provided get the non-computed value from there 5734 if (hooks && "get" in hooks && (ret = hooks.get(elem, false, extra)) !== undefined) { 5735 return ret; 5736 } // Otherwise just get the value from the style object 5737 5738 5739 return style[name]; 5740 } 5741 }, 5742 css: function (elem, name, extra, styles) { 5743 var val, 5744 num, 5745 hooks, 5746 origName = camelCase(name), 5747 isCustomProp = rcustomProp.test(name); // Make sure that we're working with the right name. We don't 5748 // want to modify the value if it is a CSS custom property 5749 // since they are user-defined. 5750 5751 if (!isCustomProp) { 5752 name = finalPropName(origName); 5753 } // Try prefixed name followed by the unprefixed name 5754 5755 5756 hooks = jQuery.cssHooks[name] || jQuery.cssHooks[origName]; // If a hook was provided get the computed value from there 5757 5758 if (hooks && "get" in hooks) { 5759 val = hooks.get(elem, true, extra); 5760 } // Otherwise, if a way to get the computed value exists, use that 5761 5762 5763 if (val === undefined) { 5764 val = curCSS(elem, name, styles); 5765 } // Convert "normal" to computed value 5766 5767 5768 if (val === "normal" && name in cssNormalTransform) { 5769 val = cssNormalTransform[name]; 5770 } // Make numeric if forced or a qualifier was provided and val looks numeric 5771 5772 5773 if (extra === "" || extra) { 5774 num = parseFloat(val); 5775 return extra === true || isFinite(num) ? num || 0 : val; 5776 } 5777 5778 return val; 5779 } 5780 }); 5781 jQuery.each(["height", "width"], function (i, dimension) { 5782 jQuery.cssHooks[dimension] = { 5783 get: function (elem, computed, extra) { 5784 if (computed) { 5785 // Certain elements can have dimension info if we invisibly show them 5786 // but it must have a current display style that would benefit
vendor: 9,588 bytes, lines 5787-6070
5787 return rdisplayswap.test(jQuery.css(elem, "display")) && ( // Support: Safari 8+ 5788 // Table columns in Safari have non-zero offsetWidth & zero 5789 // getBoundingClientRect().width unless display is changed. 5790 // Support: IE <=11 only 5791 // Running getBoundingClientRect on a disconnected node 5792 // in IE throws an error. 5793 !elem.getClientRects().length || !elem.getBoundingClientRect().width) ? swap(elem, cssShow, function () { 5794 return getWidthOrHeight(elem, dimension, extra); 5795 }) : getWidthOrHeight(elem, dimension, extra); 5796 } 5797 }, 5798 set: function (elem, value, extra) { 5799 var matches, 5800 styles = getStyles(elem), 5801 isBorderBox = jQuery.css(elem, "boxSizing", false, styles) === "border-box", 5802 subtract = extra && boxModelAdjustment(elem, dimension, extra, isBorderBox, styles); // Account for unreliable border-box dimensions by comparing offset* to computed and 5803 // faking a content-box to get border and padding (gh-3699) 5804 5805 if (isBorderBox && support.scrollboxSize() === styles.position) { 5806 subtract -= Math.ceil(elem["offset" + dimension[0].toUpperCase() + dimension.slice(1)] - parseFloat(styles[dimension]) - boxModelAdjustment(elem, dimension, "border", false, styles) - 0.5); 5807 } // Convert to pixels if value adjustment is needed 5808 5809 5810 if (subtract && (matches = rcssNum.exec(value)) && (matches[3] || "px") !== "px") { 5811 elem.style[dimension] = value; 5812 value = jQuery.css(elem, dimension); 5813 } 5814 5815 return setPositiveNumber(elem, value, subtract); 5816 } 5817 }; 5818 }); 5819 jQuery.cssHooks.marginLeft = addGetHookIf(support.reliableMarginLeft, function (elem, computed) { 5820 if (computed) { 5821 return (parseFloat(curCSS(elem, "marginLeft")) || elem.getBoundingClientRect().left - swap(elem, { 5822 marginLeft: 0 5823 }, function () { 5824 return elem.getBoundingClientRect().left; 5825 })) + "px"; 5826 } 5827 }); // These hooks are used by animate to expand properties 5828 5829 jQuery.each({ 5830 margin: "", 5831 padding: "", 5832 border: "Width" 5833 }, function (prefix, suffix) { 5834 jQuery.cssHooks[prefix + suffix] = { 5835 expand: function (value) { 5836 var i = 0, 5837 expanded = {}, 5838 // Assumes a single number if not a string 5839 parts = typeof value === "string" ? value.split(" ") : [value]; 5840 5841 for (; i < 4; i++) { 5842 expanded[prefix + cssExpand[i] + suffix] = parts[i] || parts[i - 2] || parts[0]; 5843 } 5844 5845 return expanded; 5846 } 5847 }; 5848 5849 if (prefix !== "margin") { 5850 jQuery.cssHooks[prefix + suffix].set = setPositiveNumber; 5851 } 5852 }); 5853 jQuery.fn.extend({ 5854 css: function (name, value) { 5855 return access(this, function (elem, name, value) { 5856 var styles, 5857 len, 5858 map = {}, 5859 i = 0; 5860 5861 if (Array.isArray(name)) { 5862 styles = getStyles(elem); 5863 len = name.length; 5864 5865 for (; i < len; i++) { 5866 map[name[i]] = jQuery.css(elem, name[i], false, styles); 5867 } 5868 5869 return map; 5870 } 5871 5872 return value !== undefined ? jQuery.style(elem, name, value) : jQuery.css(elem, name); 5873 }, name, value, arguments.length > 1); 5874 } 5875 }); // Based off of the plugin by Clint Helfers, with permission. 5876 // https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/ 5877 5878 jQuery.fn.delay = function (time, type) { 5879 time = jQuery.fx ? jQuery.fx.speeds[time] || time : time; 5880 type = type || "fx"; 5881 return this.queue(type, function (next, hooks) { 5882 var timeout = window.setTimeout(next, time); 5883 5884 hooks.stop = function () { 5885 window.clearTimeout(timeout); 5886 }; 5887 }); 5888 }; 5889 5890 (function () { 5891 var input = document$2.createElement("input"), 5892 select = document$2.createElement("select"), 5893 opt = select.appendChild(document$2.createElement("option")); 5894 input.type = "checkbox"; // Support: Android <=4.3 only 5895 // Default value for a checkbox should be "on" 5896 5897 support.checkOn = input.value !== ""; // Support: IE <=11 only 5898 // Must access selectedIndex to make default options select 5899 5900 support.optSelected = opt.selected; // Support: IE <=11 only 5901 // An input loses its value after becoming a radio 5902 5903 input = document$2.createElement("input"); 5904 input.value = "t"; 5905 input.type = "radio"; 5906 support.radioValue = input.value === "t"; 5907 })(); 5908 5909 var boolHook, 5910 attrHandle = jQuery.expr.attrHandle; 5911 jQuery.fn.extend({ 5912 attr: function (name, value) { 5913 return access(this, jQuery.attr, name, value, arguments.length > 1); 5914 }, 5915 removeAttr: function (name) { 5916 return this.each(function () { 5917 jQuery.removeAttr(this, name); 5918 }); 5919 } 5920 }); 5921 jQuery.extend({ 5922 attr: function (elem, name, value) { 5923 var ret, 5924 hooks, 5925 nType = elem.nodeType; // Don't get/set attributes on text, comment and attribute nodes 5926 5927 if (nType === 3 || nType === 8 || nType === 2) { 5928 return; 5929 } // Fallback to prop when attributes are not supported 5930 5931 5932 if (typeof elem.getAttribute === "undefined") { 5933 return jQuery.prop(elem, name, value); 5934 } // Attribute hooks are determined by the lowercase version 5935 // Grab necessary hook if one is defined 5936 5937 5938 if (nType !== 1 || !jQuery.isXMLDoc(elem)) { 5939 hooks = jQuery.attrHooks[name.toLowerCase()] || (jQuery.expr.match.bool.test(name) ? boolHook : undefined); 5940 } 5941 5942 if (value !== undefined) { 5943 if (value === null) { 5944 jQuery.removeAttr(elem, name); 5945 return; 5946 } 5947 5948 if (hooks && "set" in hooks && (ret = hooks.set(elem, value, name)) !== undefined) { 5949 return ret; 5950 } 5951 5952 elem.setAttribute(name, value + ""); 5953 return value; 5954 } 5955 5956 if (hooks && "get" in hooks && (ret = hooks.get(elem, name)) !== null) { 5957 return ret; 5958 } 5959 5960 ret = jQuery.find.attr(elem, name); // Non-existent attributes return null, we normalize to undefined 5961 5962 return ret == null ? undefined : ret; 5963 }, 5964 attrHooks: { 5965 type: { 5966 set: function (elem, value) { 5967 if (!support.radioValue && value === "radio" && nodeName(elem, "input")) { 5968 var val = elem.value; 5969 elem.setAttribute("type", value); 5970 5971 if (val) { 5972 elem.value = val; 5973 } 5974 5975 return value; 5976 } 5977 } 5978 } 5979 }, 5980 removeAttr: function (elem, value) { 5981 var name, 5982 i = 0, 5983 // Attribute names can contain non-HTML whitespace characters 5984 // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 5985 attrNames = value && value.match(rnothtmlwhite); 5986 5987 if (attrNames && elem.nodeType === 1) { 5988 while (name = attrNames[i++]) { 5989 elem.removeAttribute(name); 5990 } 5991 } 5992 } 5993 }); // Hooks for boolean attributes 5994 5995 boolHook = { 5996 set: function (elem, value, name) { 5997 if (value === false) { 5998 // Remove boolean attributes when set to false 5999 jQuery.removeAttr(elem, name); 6000 } else { 6001 elem.setAttribute(name, name); 6002 } 6003 6004 return name; 6005 } 6006 }; 6007 jQuery.each(jQuery.expr.match.bool.source.match(/\w+/g), function (i, name) { 6008 var getter = attrHandle[name] || jQuery.find.attr; 6009 6010 attrHandle[name] = function (elem, name, isXML) { 6011 var ret, 6012 handle, 6013 lowercaseName = name.toLowerCase(); 6014 6015 if (!isXML) { 6016 // Avoid an infinite loop by temporarily removing this function from the getter 6017 handle = attrHandle[lowercaseName]; 6018 attrHandle[lowercaseName] = ret; 6019 ret = getter(elem, name, isXML) != null ? lowercaseName : null; 6020 attrHandle[lowercaseName] = handle; 6021 } 6022 6023 return ret; 6024 }; 6025 }); 6026 var rfocusable = /^(?:input|select|textarea|button)$/i, 6027 rclickable = /^(?:a|area)$/i; 6028 jQuery.fn.extend({ 6029 prop: function (name, value) { 6030 return access(this, jQuery.prop, name, value, arguments.length > 1); 6031 }, 6032 removeProp: function (name) { 6033 return this.each(function () { 6034 delete this[jQuery.propFix[name] || name]; 6035 }); 6036 } 6037 }); 6038 jQuery.extend({ 6039 prop: function (elem, name, value) { 6040 var ret, 6041 hooks, 6042 nType = elem.nodeType; // Don't get/set properties on text, comment and attribute nodes 6043 6044 if (nType === 3 || nType === 8 || nType === 2) { 6045 return; 6046 } 6047 6048 if (nType !== 1 || !jQuery.isXMLDoc(elem)) { 6049 // Fix name and attach hooks 6050 name = jQuery.propFix[name] || name; 6051 hooks = jQuery.propHooks[name]; 6052 } 6053 6054 if (value !== undefined) { 6055 if (hooks && "set" in hooks && (ret = hooks.set(elem, value, name)) !== undefined) { 6056 return ret; 6057 } 6058 6059 return elem[name] = value; 6060 } 6061 6062 if (hooks && "get" in hooks && (ret = hooks.get(elem, name)) !== null) { 6063 return ret; 6064 } 6065 6066 return elem[name]; 6067 }, 6068 propHooks: { 6069 tabIndex: { 6070 get: function (elem) {
6071 // Support: IE <=9 - 11 only 6072 // elem.tabIndex doesn't always return the 6073 // correct value when it hasn't been explicitly set 6074 // https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ 6075 // Use proper attribute retrieval(#12072) 6076 var tabindex = jQuery.find.attr(elem, "tabindex"); 6077 6078 if (tabindex) { 6079 return parseInt(tabindex, 10); 6080 } 6081 6082 if (rfocusable.test(elem.nodeName) || rclickable.test(elem.nodeName) && elem.href) { 6083 return 0; 6084 } 6085 6086 return -1; 6087 } 6088 } 6089 }, 6090 propFix: { 6091 "for": "htmlFor", 6092 "class": "className" 6093 } 6094 }); // Support: IE <=11 only 6095 // Accessing the selectedIndex property 6096 // forces the browser to respect setting selected 6097 // on the option 6098 // The getter ensures a default option is selected 6099 // when in an optgroup 6100 // eslint rule "no-unused-expressions" is disabled for this code 6101 // since it considers such accessions noop 6102 6103 if (!support.optSelected) { 6104 jQuery.propHooks.selected = { 6105 get: function (elem) { 6106 /* eslint no-unused-expressions: "off" */ 6107 var parent = elem.parentNode; 6108 6109 if (parent && parent.parentNode) { 6110 parent.parentNode.selectedIndex; 6111 } 6112 6113 return null; 6114 }, 6115 set: function (elem) { 6116 /* eslint no-unused-expressions: "off" */ 6117 var parent = elem.parentNode; 6118 6119 if (parent) { 6120 parent.selectedIndex; 6121 6122 if (parent.parentNode) { 6123 parent.parentNode.selectedIndex; 6124 } 6125 } 6126 } 6127 }; 6128 } 6129 6130 jQuery.each(["tabIndex", "readOnly", "maxLength", "cellSpacing", "cellPadding", "rowSpan", "colSpan", "useMap", "frameBorder", "contentEditable"], function () { 6131 jQuery.propFix[this.toLowerCase()] = this; 6132 }); // Strip and collapse whitespace according to HTML spec 6133 // https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace 6134 6135 function stripAndCollapse(value) { 6136 var tokens = value.match(rnothtmlwhite) || []; 6137 return tokens.join(" "); 6138 } 6139 6140 function getClass(elem) { 6141 return elem.getAttribute && elem.getAttribute("class") || ""; 6142 } 6143 6144 function classesToArray(value) { 6145 if (Array.isArray(value)) { 6146 return value; 6147 } 6148 6149 if (typeof value === "string") { 6150 return value.match(rnothtmlwhite) || []; 6151 } 6152 6153 return []; 6154 } 6155 6156 jQuery.fn.extend({ 6157 addClass: function (value) { 6158 var classes, 6159 elem, 6160 cur, 6161 curValue, 6162 clazz, 6163 j, 6164 finalValue, 6165 i = 0; 6166 6167 if (isFunction(value)) { 6168 return this.each(function (j) { 6169 jQuery(this).addClass(value.call(this, j, getClass(this))); 6170 }); 6171 } 6172 6173 classes = classesToArray(value); 6174 6175 if (classes.length) { 6176 while (elem = this[i++]) { 6177 curValue = getClass(elem); 6178 cur = elem.nodeType === 1 && " " + stripAndCollapse(curValue) + " "; 6179 6180 if (cur) { 6181 j = 0; 6182 6183 while (clazz = classes[j++]) { 6184 if (cur.indexOf(" " + clazz + " ") < 0) { 6185 cur += clazz + " "; 6186 } 6187 } // Only assign if different to avoid unneeded rendering. 6188 6189 6190 finalValue = stripAndCollapse(cur); 6191 6192 if (curValue !== finalValue) { 6193 elem.setAttribute("class", finalValue); 6194 } 6195 } 6196 } 6197 } 6198 6199 return this; 6200 }, 6201 removeClass: function (value) { 6202 var classes, 6203 elem, 6204 cur, 6205 curValue, 6206 clazz, 6207 j, 6208 finalValue, 6209 i = 0; 6210 6211 if (isFunction(value)) { 6212 return this.each(function (j) { 6213 jQuery(this).removeClass(value.call(this, j, getClass(this))); 6214 }); 6215 } 6216 6217 if (!arguments.length) { 6218 return this.attr("class", ""); 6219 } 6220 6221 classes = classesToArray(value); 6222 6223 if (classes.length) { 6224 while (elem = this[i++]) { 6225 curValue = getClass(elem); // This expression is here for better compressibility (see addClass) 6226 6227 cur = elem.nodeType === 1 && " " + stripAndCollapse(curValue) + " "; 6228 6229 if (cur) { 6230 j = 0; 6231 6232 while (clazz = classes[j++]) {
6233 // Remove *all* instances 6234 while (cur.indexOf(" " + clazz + " ") > -1) { 6235 cur = cur.replace(" " + clazz + " ", " "); 6236 } 6237 } // Only assign if different to avoid unneeded rendering. 6238 6239 6240 finalValue = stripAndCollapse(cur); 6241 6242 if (curValue !== finalValue) { 6243 elem.setAttribute("class", finalValue); 6244 } 6245 } 6246 } 6247 } 6248 6249 return this; 6250 }, 6251 toggleClass: function (value, stateVal) { 6252 var type = typeof value, 6253 isValidValue = type === "string" || Array.isArray(value); 6254 6255 if (typeof stateVal === "boolean" && isValidValue) { 6256 return stateVal ? this.addClass(value) : this.removeClass(value); 6257 } 6258 6259 if (isFunction(value)) { 6260 return this.each(function (i) { 6261 jQuery(this).toggleClass(value.call(this, i, getClass(this), stateVal), stateVal); 6262 }); 6263 } 6264 6265 return this.each(function () { 6266 var className, i, self, classNames; 6267 6268 if (isValidValue) { 6269 // Toggle individual class names 6270 i = 0; 6271 self = jQuery(this); 6272 classNames = classesToArray(value); 6273 6274 while (className = classNames[i++]) { 6275 // Check each className given, space separated list 6276 if (self.hasClass(className)) { 6277 self.removeClass(className); 6278 } else { 6279 self.addClass(className); 6280 } 6281 } // Toggle whole class name 6282 6283 } else if (value === undefined || type === "boolean") { 6284 className = getClass(this); 6285 6286 if (className) { 6287 // Store className if set 6288 dataPriv.set(this, "__className__", className); 6289 } // If the element has a class name or if we're passed `false`, 6290 // then remove the whole classname (if there was one, the above saved it). 6291 // Otherwise bring back whatever was previously saved (if anything), 6292 // falling back to the empty string if nothing was stored. 6293 6294 6295 if (this.setAttribute) { 6296 this.setAttribute("class", className || value === false ? "" : dataPriv.get(this, "__className__") || ""); 6297 } 6298 } 6299 }); 6300 }, 6301 hasClass: function (selector) { 6302 var className, 6303 elem, 6304 i = 0; 6305 className = " " + selector + " "; 6306 6307 while (elem = this[i++]) { 6308 if (elem.nodeType === 1 && (" " + stripAndCollapse(getClass(elem)) + " ").indexOf(className) > -1) { 6309 return true; 6310 } 6311 } 6312 6313 return false; 6314 } 6315 }); 6316 var rreturn = /\r/g; 6317 jQuery.fn.extend({ 6318 val: function (value) { 6319 var hooks, 6320 ret, 6321 valueIsFunction, 6322 elem = this[0]; 6323 6324 if (!arguments.length) { 6325 if (elem) { 6326 hooks = jQuery.valHooks[elem.type] || jQuery.valHooks[elem.nodeName.toLowerCase()]; 6327 6328 if (hooks && "get" in hooks && (ret = hooks.get(elem, "value")) !== undefined) { 6329 return ret; 6330 } 6331 6332 ret = elem.value; // Handle most common string cases 6333 6334 if (typeof ret === "string") { 6335 return ret.replace(rreturn, ""); 6336 } // Handle cases where value is null/undef or number 6337 6338 6339 return ret == null ? "" : ret; 6340 } 6341 6342 return; 6343 } 6344 6345 valueIsFunction = isFunction(value); 6346 return this.each(function (i) { 6347 var val; 6348 6349 if (this.nodeType !== 1) { 6350 return; 6351 } 6352 6353 if (valueIsFunction) { 6354 val = value.call(this, i, jQuery(this).val()); 6355 } else { 6356 val = value; 6357 } // Treat null/undefined as ""; convert numbers to string 6358 6359 6360 if (val == null) { 6361 val = ""; 6362 } else if (typeof val === "number") { 6363 val += ""; 6364 } else if (Array.isArray(val)) { 6365 val = jQuery.map(val, function (value) { 6366 return value == null ? "" : value + ""; 6367 }); 6368 } 6369 6370 hooks = jQuery.valHooks[this.type] || jQuery.valHooks[this.nodeName.toLowerCase()]; // If set returns undefined, fall back to normal setting 6371 6372 if (!hooks || !("set" in hooks) || hooks.set(this, val, "value") === undefined) { 6373 this.value = val; 6374 } 6375 }); 6376 } 6377 }); 6378 jQuery.extend({ 6379 valHooks: { 6380 option: { 6381 get: function (elem) { 6382 var val = jQuery.find.attr(elem, "value"); 6383 return val != null ? val : // Support: IE <=10 - 11 only 6384 // option.text throws exceptions (#14686, #14858) 6385 // Strip and collapse whitespace 6386 // https://html.spec.whatwg.org/#strip-and-collapse-whitespace
vendor: 8,494 bytes, lines 6387-6640
6387 stripAndCollapse(jQuery.text(elem)); 6388 } 6389 }, 6390 select: { 6391 get: function (elem) { 6392 var value, 6393 option, 6394 i, 6395 options = elem.options, 6396 index = elem.selectedIndex, 6397 one = elem.type === "select-one", 6398 values = one ? null : [], 6399 max = one ? index + 1 : options.length; 6400 6401 if (index < 0) { 6402 i = max; 6403 } else { 6404 i = one ? index : 0; 6405 } // Loop through all the selected options 6406 6407 6408 for (; i < max; i++) { 6409 option = options[i]; // Support: IE <=9 only 6410 // IE8-9 doesn't update selected after form reset (#2551) 6411 6412 if ((option.selected || i === index) && // Don't return options that are disabled or in a disabled optgroup 6413 !option.disabled && (!option.parentNode.disabled || !nodeName(option.parentNode, "optgroup"))) { 6414 // Get the specific value for the option 6415 value = jQuery(option).val(); // We don't need an array for one selects 6416 6417 if (one) { 6418 return value; 6419 } // Multi-Selects return an array 6420 6421 6422 values.push(value); 6423 } 6424 } 6425 6426 return values; 6427 }, 6428 set: function (elem, value) { 6429 var optionSet, 6430 option, 6431 options = elem.options, 6432 values = jQuery.makeArray(value), 6433 i = options.length; 6434 6435 while (i--) { 6436 option = options[i]; 6437 /* eslint-disable no-cond-assign */ 6438 6439 if (option.selected = jQuery.inArray(jQuery.valHooks.option.get(option), values) > -1) { 6440 optionSet = true; 6441 } 6442 /* eslint-enable no-cond-assign */ 6443 6444 } // Force browsers to behave consistently when non-matching value is set 6445 6446 6447 if (!optionSet) { 6448 elem.selectedIndex = -1; 6449 } 6450 6451 return values; 6452 } 6453 } 6454 } 6455 }); // Radios and checkboxes getter/setter 6456 6457 jQuery.each(["radio", "checkbox"], function () { 6458 jQuery.valHooks[this] = { 6459 set: function (elem, value) { 6460 if (Array.isArray(value)) { 6461 return elem.checked = jQuery.inArray(jQuery(elem).val(), value) > -1; 6462 } 6463 } 6464 }; 6465 6466 if (!support.checkOn) { 6467 jQuery.valHooks[this].get = function (elem) { 6468 return elem.getAttribute("value") === null ? "on" : elem.value; 6469 }; 6470 } 6471 }); // Return jQuery for attributes-only inclusion 6472 6473 support.focusin = "onfocusin" in window; 6474 6475 var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, 6476 stopPropagationCallback = function (e) { 6477 e.stopPropagation(); 6478 }; 6479 6480 jQuery.extend(jQuery.event, { 6481 trigger: function (event, data, elem, onlyHandlers) { 6482 var i, 6483 cur, 6484 tmp, 6485 bubbleType, 6486 ontype, 6487 handle, 6488 special, 6489 lastElement, 6490 eventPath = [elem || document$2], 6491 type = hasOwn.call(event, "type") ? event.type : event, 6492 namespaces = hasOwn.call(event, "namespace") ? event.namespace.split(".") : []; 6493 cur = lastElement = tmp = elem = elem || document$2; // Don't do events on text and comment nodes 6494 6495 if (elem.nodeType === 3 || elem.nodeType === 8) { 6496 return; 6497 } // focus/blur morphs to focusin/out; ensure we're not firing them right now 6498 6499 6500 if (rfocusMorph.test(type + jQuery.event.triggered)) { 6501 return; 6502 } 6503 6504 if (type.indexOf(".") > -1) { 6505 // Namespaced trigger; create a regexp to match event type in handle() 6506 namespaces = type.split("."); 6507 type = namespaces.shift(); 6508 namespaces.sort(); 6509 } 6510 6511 ontype = type.indexOf(":") < 0 && "on" + type; // Caller can pass in a jQuery.Event object, Object, or just an event type string 6512 6513 event = event[jQuery.expando] ? event : new jQuery.Event(type, typeof event === "object" && event); // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) 6514 6515 event.isTrigger = onlyHandlers ? 2 : 3; 6516 event.namespace = namespaces.join("."); 6517 event.rnamespace = event.namespace ? new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)") : null; // Clean up the event in case it is being reused 6518 6519 event.result = undefined; 6520 6521 if (!event.target) { 6522 event.target = elem; 6523 } // Clone any incoming data and prepend the event, creating the handler arg list 6524 6525 6526 data = data == null ? [event] : jQuery.makeArray(data, [event]); // Allow special events to draw outside the lines 6527 6528 special = jQuery.event.special[type] || {}; 6529 6530 if (!onlyHandlers && special.trigger && special.trigger.apply(elem, data) === false) { 6531 return; 6532 } // Determine event propagation path in advance, per W3C events spec (#9951) 6533 // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) 6534 6535 6536 if (!onlyHandlers && !special.noBubble && !isWindow(elem)) { 6537 bubbleType = special.delegateType || type; 6538 6539 if (!rfocusMorph.test(bubbleType + type)) { 6540 cur = cur.parentNode; 6541 } 6542 6543 for (; cur; cur = cur.parentNode) { 6544 eventPath.push(cur); 6545 tmp = cur; 6546 } // Only add window if we got to document (e.g., not plain obj or detached DOM) 6547 6548 6549 if (tmp === (elem.ownerDocument || document$2)) { 6550 eventPath.push(tmp.defaultView || tmp.parentWindow || window); 6551 } 6552 } // Fire handlers on the event path 6553 6554 6555 i = 0; 6556 6557 while ((cur = eventPath[i++]) && !event.isPropagationStopped()) { 6558 lastElement = cur; 6559 event.type = i > 1 ? bubbleType : special.bindType || type; // jQuery handler 6560 6561 handle = (dataPriv.get(cur, "events") || {})[event.type] && dataPriv.get(cur, "handle"); 6562 6563 if (handle) { 6564 handle.apply(cur, data); 6565 } // Native handler 6566 6567 6568 handle = ontype && cur[ontype]; 6569 6570 if (handle && handle.apply && acceptData(cur)) { 6571 event.result = handle.apply(cur, data); 6572 6573 if (event.result === false) { 6574 event.preventDefault(); 6575 } 6576 } 6577 } 6578 6579 event.type = type; // If nobody prevented the default action, do it now 6580 6581 if (!onlyHandlers && !event.isDefaultPrevented()) { 6582 if ((!special._default || special._default.apply(eventPath.pop(), data) === false) && acceptData(elem)) { 6583 // Call a native DOM method on the target with the same name as the event. 6584 // Don't do default actions on window, that's where global variables be (#6170) 6585 if (ontype && isFunction(elem[type]) && !isWindow(elem)) { 6586 // Don't re-trigger an onFOO event when we call its FOO() method 6587 tmp = elem[ontype]; 6588 6589 if (tmp) { 6590 elem[ontype] = null; 6591 } // Prevent re-triggering of the same event, since we already bubbled it above 6592 6593 6594 jQuery.event.triggered = type; 6595 6596 if (event.isPropagationStopped()) { 6597 lastElement.addEventListener(type, stopPropagationCallback); 6598 } 6599 6600 elem[type](); 6601 6602 if (event.isPropagationStopped()) { 6603 lastElement.removeEventListener(type, stopPropagationCallback); 6604 } 6605 6606 jQuery.event.triggered = undefined; 6607 6608 if (tmp) { 6609 elem[ontype] = tmp; 6610 } 6611 } 6612 } 6613 } 6614 6615 return event.result; 6616 }, 6617 // Piggyback on a donor event to simulate a different one 6618 // Used only for `focus(in | out)` events 6619 simulate: function (type, elem, event) { 6620 var e = jQuery.extend(new jQuery.Event(), event, { 6621 type: type, 6622 isSimulated: true 6623 }); 6624 jQuery.event.trigger(e, null, elem); 6625 } 6626 }); 6627 jQuery.fn.extend({ 6628 trigger: function (type, data) { 6629 return this.each(function () { 6630 jQuery.event.trigger(type, data, this); 6631 }); 6632 }, 6633 triggerHandler: function (type, data) { 6634 var elem = this[0]; 6635 6636 if (elem) { 6637 return jQuery.event.trigger(type, data, elem, true); 6638 } 6639 } 6640 });
vendor: 1,466 bytes, lines 6640-6677
6640 // Support: Firefox <=44 6641 // Firefox doesn't have focus(in | out) events 6642 // Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787 6643 // 6644 // Support: Chrome <=48 - 49, Safari <=9.0 - 9.1 6645 // focus(in | out) events fire after focus & blur events, 6646 // which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order 6647 // Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857 6648 6649 if (!support.focusin) { 6650 jQuery.each({ 6651 focus: "focusin", 6652 blur: "focusout" 6653 }, function (orig, fix) { 6654 // Attach a single capturing handler on the document while someone wants focusin/focusout 6655 var handler = function (event) { 6656 jQuery.event.simulate(fix, event.target, jQuery.event.fix(event)); 6657 }; 6658 6659 jQuery.event.special[fix] = { 6660 setup: function () { 6661 var doc = this.ownerDocument || this, 6662 attaches = dataPriv.access(doc, fix); 6663 6664 if (!attaches) { 6665 doc.addEventListener(orig, handler, true); 6666 } 6667 6668 dataPriv.access(doc, fix, (attaches || 0) + 1); 6669 }, 6670 teardown: function () { 6671 var doc = this.ownerDocument || this, 6672 attaches = dataPriv.access(doc, fix) - 1; 6673 6674 if (!attaches) { 6675 doc.removeEventListener(orig, handler, true); 6676 dataPriv.remove(doc, fix); 6677 } else {
vendor: 13,806 bytes, lines 6678-7092
6678 dataPriv.access(doc, fix, attaches); 6679 } 6680 } 6681 }; 6682 }); 6683 } 6684 6685 var rbracket = /\[\]$/, 6686 rCRLF = /\r?\n/g, 6687 rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i, 6688 rsubmittable = /^(?:input|select|textarea|keygen)/i; 6689 6690 function buildParams(prefix, obj, traditional, add) { 6691 var name; 6692 6693 if (Array.isArray(obj)) { 6694 // Serialize array item. 6695 jQuery.each(obj, function (i, v) { 6696 if (traditional || rbracket.test(prefix)) { 6697 // Treat each array item as a scalar. 6698 add(prefix, v); 6699 } else { 6700 // Item is non-scalar (array or object), encode its numeric index. 6701 buildParams(prefix + "[" + (typeof v === "object" && v != null ? i : "") + "]", v, traditional, add); 6702 } 6703 }); 6704 } else if (!traditional && toType(obj) === "object") { 6705 // Serialize object item. 6706 for (name in obj) { 6707 buildParams(prefix + "[" + name + "]", obj[name], traditional, add); 6708 } 6709 } else { 6710 // Serialize scalar item. 6711 add(prefix, obj); 6712 } 6713 } // Serialize an array of form elements or a set of 6714 // key/values into a query string 6715 6716 6717 jQuery.param = function (a, traditional) { 6718 var prefix, 6719 s = [], 6720 add = function (key, valueOrFunction) { 6721 // If value is a function, invoke it and use its return value 6722 var value = isFunction(valueOrFunction) ? valueOrFunction() : valueOrFunction; 6723 s[s.length] = encodeURIComponent(key) + "=" + encodeURIComponent(value == null ? "" : value); 6724 }; // If an array was passed in, assume that it is an array of form elements. 6725 6726 6727 if (Array.isArray(a) || a.jquery && !jQuery.isPlainObject(a)) { 6728 // Serialize the form elements 6729 jQuery.each(a, function () { 6730 add(this.name, this.value); 6731 }); 6732 } else { 6733 // If traditional, encode the "old" way (the way 1.3.2 or older 6734 // did it), otherwise encode params recursively. 6735 for (prefix in a) { 6736 buildParams(prefix, a[prefix], traditional, add); 6737 } 6738 } // Return the resulting serialization 6739 6740 6741 return s.join("&"); 6742 }; 6743 6744 jQuery.fn.extend({ 6745 serialize: function () { 6746 return jQuery.param(this.serializeArray()); 6747 }, 6748 serializeArray: function () { 6749 return this.map(function () { 6750 // Can add propHook for "elements" to filter or add form elements 6751 var elements = jQuery.prop(this, "elements"); 6752 return elements ? jQuery.makeArray(elements) : this; 6753 }).filter(function () { 6754 var type = this.type; // Use .is( ":disabled" ) so that fieldset[disabled] works 6755 6756 return this.name && !jQuery(this).is(":disabled") && rsubmittable.test(this.nodeName) && !rsubmitterTypes.test(type) && (this.checked || !rcheckableType.test(type)); 6757 }).map(function (i, elem) { 6758 var val = jQuery(this).val(); 6759 6760 if (val == null) { 6761 return null; 6762 } 6763 6764 if (Array.isArray(val)) { 6765 return jQuery.map(val, function (val) { 6766 return { 6767 name: elem.name, 6768 value: val.replace(rCRLF, "\r\n") 6769 }; 6770 }); 6771 } 6772 6773 return { 6774 name: elem.name, 6775 value: val.replace(rCRLF, "\r\n") 6776 }; 6777 }).get(); 6778 } 6779 }); 6780 jQuery.fn.extend({ 6781 wrapAll: function (html) { 6782 var wrap; 6783 6784 if (this[0]) { 6785 if (isFunction(html)) { 6786 html = html.call(this[0]); 6787 } // The elements to wrap the target around 6788 6789 6790 wrap = jQuery(html, this[0].ownerDocument).eq(0).clone(true); 6791 6792 if (this[0].parentNode) { 6793 wrap.insertBefore(this[0]); 6794 } 6795 6796 wrap.map(function () { 6797 var elem = this; 6798 6799 while (elem.firstElementChild) { 6800 elem = elem.firstElementChild; 6801 } 6802 6803 return elem; 6804 }).append(this); 6805 } 6806 6807 return this; 6808 }, 6809 wrapInner: function (html) { 6810 if (isFunction(html)) { 6811 return this.each(function (i) { 6812 jQuery(this).wrapInner(html.call(this, i)); 6813 }); 6814 } 6815 6816 return this.each(function () { 6817 var self = jQuery(this), 6818 contents = self.contents(); 6819 6820 if (contents.length) { 6821 contents.wrapAll(html); 6822 } else { 6823 self.append(html); 6824 } 6825 }); 6826 }, 6827 wrap: function (html) { 6828 var htmlIsFunction = isFunction(html); 6829 return this.each(function (i) { 6830 jQuery(this).wrapAll(htmlIsFunction ? html.call(this, i) : html); 6831 }); 6832 }, 6833 unwrap: function (selector) { 6834 this.parent(selector).not("body").each(function () { 6835 jQuery(this).replaceWith(this.childNodes); 6836 }); 6837 return this; 6838 } 6839 }); 6840 6841 jQuery.expr.pseudos.hidden = function (elem) { 6842 return !jQuery.expr.pseudos.visible(elem); 6843 }; 6844 6845 jQuery.expr.pseudos.visible = function (elem) { 6846 return !!(elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length); 6847 }; // Support: Safari 8 only 6848 // In Safari 8 documents created via document.implementation.createHTMLDocument 6849 // collapse sibling forms: the second one becomes a child of the first one. 6850 // Because of that, this security measure has to be disabled in Safari 8. 6851 // https://bugs.webkit.org/show_bug.cgi?id=137337 6852 6853 6854 support.createHTMLDocument = function () { 6855 var body = document$2.implementation.createHTMLDocument("").body; 6856 body.innerHTML = "<form></form><form></form>"; 6857 return body.childNodes.length === 2; 6858 }(); // Argument "data" should be string of html 6859 // context (optional): If specified, the fragment will be created in this context, 6860 // defaults to document 6861 // keepScripts (optional): If true, will include scripts passed in the html string 6862 6863 6864 jQuery.parseHTML = function (data, context, keepScripts) { 6865 if (typeof data !== "string") { 6866 return []; 6867 } 6868 6869 if (typeof context === "boolean") { 6870 keepScripts = context; 6871 context = false; 6872 } 6873 6874 var base, parsed, scripts; 6875 6876 if (!context) { 6877 // Stop scripts or inline event handlers from being executed immediately 6878 // by using document.implementation 6879 if (support.createHTMLDocument) { 6880 context = document$2.implementation.createHTMLDocument(""); // Set the base href for the created document 6881 // so any parsed elements with URLs 6882 // are based on the document's URL (gh-2965) 6883 6884 base = context.createElement("base"); 6885 base.href = document$2.location.href; 6886 context.head.appendChild(base); 6887 } else { 6888 context = document$2; 6889 } 6890 } 6891 6892 parsed = rsingleTag.exec(data); 6893 scripts = !keepScripts && []; // Single tag 6894 6895 if (parsed) { 6896 return [context.createElement(parsed[1])]; 6897 } 6898 6899 parsed = buildFragment([data], context, scripts); 6900 6901 if (scripts && scripts.length) { 6902 jQuery(scripts).remove(); 6903 } 6904 6905 return jQuery.merge([], parsed.childNodes); 6906 }; 6907 6908 jQuery.offset = { 6909 setOffset: function (elem, options, i) { 6910 var curPosition, 6911 curLeft, 6912 curCSSTop, 6913 curTop, 6914 curOffset, 6915 curCSSLeft, 6916 calculatePosition, 6917 position = jQuery.css(elem, "position"), 6918 curElem = jQuery(elem), 6919 props = {}; // Set position first, in-case top/left are set even on static elem 6920 6921 if (position === "static") { 6922 elem.style.position = "relative"; 6923 } 6924 6925 curOffset = curElem.offset(); 6926 curCSSTop = jQuery.css(elem, "top"); 6927 curCSSLeft = jQuery.css(elem, "left"); 6928 calculatePosition = (position === "absolute" || position === "fixed") && (curCSSTop + curCSSLeft).indexOf("auto") > -1; // Need to be able to calculate position if either 6929 // top or left is auto and position is either absolute or fixed 6930 6931 if (calculatePosition) { 6932 curPosition = curElem.position(); 6933 curTop = curPosition.top; 6934 curLeft = curPosition.left; 6935 } else { 6936 curTop = parseFloat(curCSSTop) || 0; 6937 curLeft = parseFloat(curCSSLeft) || 0; 6938 } 6939 6940 if (isFunction(options)) { 6941 // Use jQuery.extend here to allow modification of coordinates argument (gh-1848) 6942 options = options.call(elem, i, jQuery.extend({}, curOffset)); 6943 } 6944 6945 if (options.top != null) { 6946 props.top = options.top - curOffset.top + curTop; 6947 } 6948 6949 if (options.left != null) { 6950 props.left = options.left - curOffset.left + curLeft; 6951 } 6952 6953 if ("using" in options) { 6954 options.using.call(elem, props); 6955 } else { 6956 curElem.css(props); 6957 } 6958 } 6959 }; 6960 jQuery.fn.extend({ 6961 // offset() relates an element's border box to the document origin 6962 offset: function (options) { 6963 // Preserve chaining for setter 6964 if (arguments.length) { 6965 return options === undefined ? this : this.each(function (i) { 6966 jQuery.offset.setOffset(this, options, i); 6967 }); 6968 } 6969 6970 var rect, 6971 win, 6972 elem = this[0]; 6973 6974 if (!elem) { 6975 return; 6976 } // Return zeros for disconnected and hidden (display: none) elements (gh-2310) 6977 // Support: IE <=11 only 6978 // Running getBoundingClientRect on a 6979 // disconnected node in IE throws an error 6980 6981 6982 if (!elem.getClientRects().length) { 6983 return { 6984 top: 0, 6985 left: 0 6986 }; 6987 } // Get document-relative position by adding viewport scroll to viewport-relative gBCR 6988 6989 6990 rect = elem.getBoundingClientRect(); 6991 win = elem.ownerDocument.defaultView; 6992 return { 6993 top: rect.top + win.pageYOffset, 6994 left: rect.left + win.pageXOffset 6995 }; 6996 }, 6997 // position() relates an element's margin box to its offset parent's padding box 6998 // This corresponds to the behavior of CSS absolute positioning 6999 position: function () { 7000 if (!this[0]) { 7001 return; 7002 } 7003 7004 var offsetParent, 7005 offset, 7006 doc, 7007 elem = this[0], 7008 parentOffset = { 7009 top: 0, 7010 left: 0 7011 }; // position:fixed elements are offset from the viewport, which itself always has zero offset 7012 7013 if (jQuery.css(elem, "position") === "fixed") { 7014 // Assume position:fixed implies availability of getBoundingClientRect 7015 offset = elem.getBoundingClientRect(); 7016 } else { 7017 offset = this.offset(); // Account for the *real* offset parent, which can be the document or its root element 7018 // when a statically positioned element is identified 7019 7020 doc = elem.ownerDocument; 7021 offsetParent = elem.offsetParent || doc.documentElement; 7022 7023 while (offsetParent && (offsetParent === doc.body || offsetParent === doc.documentElement) && jQuery.css(offsetParent, "position") === "static") { 7024 offsetParent = offsetParent.parentNode; 7025 } 7026 7027 if (offsetParent && offsetParent !== elem && offsetParent.nodeType === 1) { 7028 // Incorporate borders into its offset, since they are outside its content origin 7029 parentOffset = jQuery(offsetParent).offset(); 7030 parentOffset.top += jQuery.css(offsetParent, "borderTopWidth", true); 7031 parentOffset.left += jQuery.css(offsetParent, "borderLeftWidth", true); 7032 } 7033 } // Subtract parent offsets and element margins 7034 7035 7036 return { 7037 top: offset.top - parentOffset.top - jQuery.css(elem, "marginTop", true), 7038 left: offset.left - parentOffset.left - jQuery.css(elem, "marginLeft", true) 7039 }; 7040 }, 7041 // This method will return documentElement in the following cases: 7042 // 1) For the element inside the iframe without offsetParent, this method will return 7043 // documentElement of the parent window 7044 // 2) For the hidden or detached element 7045 // 3) For body or html element, i.e. in case of the html node - it will return itself 7046 // 7047 // but those exceptions were never presented as a real life use-cases 7048 // and might be considered as more preferable results. 7049 // 7050 // This logic, however, is not guaranteed and can change at any point in the future 7051 offsetParent: function () { 7052 return this.map(function () { 7053 var offsetParent = this.offsetParent; 7054 7055 while (offsetParent && jQuery.css(offsetParent, "position") === "static") { 7056 offsetParent = offsetParent.offsetParent; 7057 } 7058 7059 return offsetParent || documentElement; 7060 }); 7061 } 7062 }); // Create scrollLeft and scrollTop methods 7063 7064 jQuery.each({ 7065 scrollLeft: "pageXOffset", 7066 scrollTop: "pageYOffset" 7067 }, function (method, prop) { 7068 var top = "pageYOffset" === prop; 7069 7070 jQuery.fn[method] = function (val) { 7071 return access(this, function (elem, method, val) { 7072 // Coalesce documents and windows 7073 var win; 7074 7075 if (isWindow(elem)) { 7076 win = elem; 7077 } else if (elem.nodeType === 9) { 7078 win = elem.defaultView; 7079 } 7080 7081 if (val === undefined) { 7082 return win ? win[prop] : elem[method]; 7083 } 7084 7085 if (win) { 7086 win.scrollTo(!top ? val : win.pageXOffset, top ? val : win.pageYOffset); 7087 } else { 7088 elem[method] = val; 7089 } 7090 }, method, val, arguments.length); 7091 }; 7092 });
7092 // Support: Safari <=7 - 9.1, Chrome <=37 - 49 7093 // Add the top/left cssHooks using jQuery.fn.position 7094 // Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084 7095 // Blink bug: https://bugs.chromium.org/p/chromium/issues/detail?id=589347 7096 // getComputedStyle returns percent when specified for top/left/bottom/right; 7097 // rather than make the css module depend on the offset module, just check for it here 7098 7099 jQuery.each(["top", "left"], function (i, prop) { 7100 jQuery.cssHooks[prop] = addGetHookIf(support.pixelPosition, function (elem, computed) { 7101 if (computed) { 7102 computed = curCSS(elem, prop); // If curCSS returns percentage, fallback to offset 7103 7104 return rnumnonpx.test(computed) ? jQuery(elem).position()[prop] + "px" : computed; 7105 } 7106 }); 7107 }); // Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods 7108 7109 jQuery.each({ 7110 Height: "height", 7111 Width: "width" 7112 }, function (name, type) { 7113 jQuery.each({ 7114 padding: "inner" + name, 7115 content: type, 7116 "": "outer" + name 7117 }, function (defaultExtra, funcName) { 7118 // Margin is only for outerHeight, outerWidth 7119 jQuery.fn[funcName] = function (margin, value) { 7120 var chainable = arguments.length && (defaultExtra || typeof margin !== "boolean"), 7121 extra = defaultExtra || (margin === true || value === true ? "margin" : "border"); 7122 return access(this, function (elem, type, value) { 7123 var doc; 7124 7125 if (isWindow(elem)) { 7126 // $( window ).outerWidth/Height return w/h including scrollbars (gh-1729) 7127 return funcName.indexOf("outer") === 0 ? elem["inner" + name] : elem.document.documentElement["client" + name]; 7128 } // Get document width or height 7129 7130 7131 if (elem.nodeType === 9) { 7132 doc = elem.documentElement; // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height], 7133 // whichever is greatest 7134 7135 return Math.max(elem.body["scroll" + name], doc["scroll" + name], elem.body["offset" + name], doc["offset" + name], doc["client" + name]); 7136 } 7137 7138 return value === undefined ? // Get width or height on the element, requesting but not forcing parseFloat 7139 jQuery.css(elem, type, extra) : // Set width or height on the element 7140 jQuery.style(elem, type, value, extra); 7141 }, type, chainable ? margin : undefined, chainable); 7142 }; 7143 }); 7144 }); 7145 jQuery.each(("blur focus focusin focusout resize scroll click dblclick " + "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + "change select submit keydown keypress keyup contextmenu").split(" "), function (i, name) { 7146 // Handle event binding 7147 jQuery.fn[name] = function (data, fn) { 7148 return arguments.length > 0 ? this.on(name, null, data, fn) : this.trigger(name); 7149 }; 7150 }); 7151 jQuery.fn.extend({ 7152 hover: function (fnOver, fnOut) { 7153 return this.mouseenter(fnOver).mouseleave(fnOut || fnOver); 7154 } 7155 }); 7156 jQuery.fn.extend({ 7157 bind: function (types, data, fn) { 7158 return this.on(types, null, data, fn); 7159 }, 7160 unbind: function (types, fn) { 7161 return this.off(types, null, fn); 7162 }, 7163 delegate: function (selector, types, data, fn) { 7164 return this.on(types, selector, data, fn); 7165 }, 7166 undelegate: function (selector, types, fn) { 7167 // ( namespace ) or ( selector, types [, fn] ) 7168 return arguments.length === 1 ? this.off(selector, "**") : this.off(types, selector || "**", fn); 7169 } 7170 }); // Bind a function to a context, optionally partially applying any 7171 // arguments. 7172 // jQuery.proxy is deprecated to promote standards (specifically Function#bind) 7173 // However, it is not slated for removal any time soon 7174 7175 jQuery.proxy = function (fn, context) { 7176 var tmp, args, proxy; 7177 7178 if (typeof context === "string") { 7179 tmp = fn[context]; 7180 context = fn; 7181 fn = tmp; 7182 } // Quick check to determine if target is callable, in the spec 7183 // this throws a TypeError, but we will just return undefined. 7184 7185 7186 if (!isFunction(fn)) { 7187 return undefined; 7188 } // Simulated bind 7189 7190 7191 args = slice.call(arguments, 2); 7192 7193 proxy = function () { 7194 return fn.apply(context || this, args.concat(slice.call(arguments))); 7195 }; // Set the guid of unique handler to the same of original handler, so it can be removed 7196 7197 7198 proxy.guid = fn.guid = fn.guid || jQuery.guid++; 7199 return proxy; 7200 }; 7201 7202 jQuery.holdReady = function (hold) { 7203 if (hold) { 7204 jQuery.readyWait++; 7205 } else { 7206 jQuery.ready(true); 7207 } 7208 }; 7209 7210 jQuery.isArray = Array.isArray; 7211 jQuery.parseJSON = JSON.parse; 7212 jQuery.nodeName = nodeName; 7213 jQuery.isFunction = isFunction; 7214 jQuery.isWindow = isWindow; 7215 jQuery.camelCase = camelCase; 7216 jQuery.type = toType; 7217 jQuery.now = Date.now; 7218 7219 jQuery.isNumeric = function (obj) { 7220 // As of jQuery 3.0, isNumeric is limited to 7221 // strings and numbers (primitives or objects) 7222 // that can be coerced to finite numbers (gh-2662) 7223 var type = jQuery.type(obj); 7224 return (type === "number" || type === "string") && // parseFloat NaNs numeric-cast false positives ("") 7225 // ...but misinterprets leading-number strings, particularly hex literals ("0x...") 7226 // subtraction forces infinities to NaN 7227 !isNaN(obj - parseFloat(obj)); 7228 }; 7229 7230 const $$1 = jQuery; 7231 7232 function div$1(options) { 7233 return create$1("div", options); 7234 } 7235 7236 function create$1(tag, options) { 7237 const elem = document.createElement(tag); 7238 7239 if (options) { 7240 if (options.class) { 7241 elem.classList.add(options.class); 7242 } 7243 7244 if (options.id) { 7245 elem.id = options.id; 7246 } 7247 7248 if (options.style) { 7249 applyStyle$1(elem, options.style); 7250 } 7251 } 7252 7253 return elem; 7254 } 7255 7256 function hide$1(elem) { 7257 const cssStyle = getComputedStyle(elem); 7258 7259 if (cssStyle.display !== "none") { 7260 elem._initialDisplay = cssStyle.display; 7261 } 7262 7263 elem.style.display = "none"; 7264 } 7265 7266 function offset$1(elem) { 7267 // Return zeros for disconnected and hidden (display: none) elements (gh-2310)
7268 // Support: IE <=11 only 7269 // Running getBoundingClientRect on a 7270 // disconnected node in IE throws an error 7271 if (!elem.getClientRects().length) { 7272 return { 7273 top: 0, 7274 left: 0 7275 }; 7276 } // Get document-relative position by adding viewport scroll to viewport-relative gBCR 7277 7278 7279 const rect = elem.getBoundingClientRect(); 7280 const win = elem.ownerDocument.defaultView; 7281 return { 7282 top: rect.top + win.pageYOffset, 7283 left: rect.left + win.pageXOffset 7284 }; 7285 } 7286 7287 function pageCoordinates$1(e) { 7288 if (e.type.startsWith("touch")) { 7289 const touch = e.touches[0]; 7290 return { 7291 x: touch.pageX, 7292 y: touch.pageY 7293 }; 7294 } else { 7295 return { 7296 x: e.pageX, 7297 y: e.pageY 7298 }; 7299 } 7300 } 7301 7302 const relativeDOMBBox = (parentElement, childElement) => { 7303 const { 7304 x: x_p, 7305 y: y_p, 7306 width: width_p, 7307 height: height_p 7308 } = parentElement.getBoundingClientRect(); 7309 const { 7310 x: x_c, 7311 y: y_c, 7312 width: width_c, 7313 height: height_c 7314 } = childElement.getBoundingClientRect(); 7315 return { 7316 x: x_c - x_p, 7317 y: y_c - y_p, 7318 width: width_c, 7319 height: height_c 7320 }; 7321 }; 7322 7323 function applyStyle$1(elem, style) { 7324 for (let key of Object.keys(style)) { 7325 elem.style[key] = style[key]; 7326 } 7327 } 7328 7329 function guid$1() { 7330 return ("0000" + (Math.random() * Math.pow(36, 4) << 0).toString(36)).slice(-4); 7331 } 7332 7333 let getMouseXY$1 = (domElement, { 7334 clientX, 7335 clientY 7336 }) => { 7337 // DOMRect object with eight properties: left, top, right, bottom, x, y, width, height 7338 const { 7339 left, 7340 top, 7341 width, 7342 height 7343 } = domElement.getBoundingClientRect(); 7344 const x = clientX - left; 7345 const y = clientY - top; 7346 return { 7347 x, 7348 y, 7349 xNormalized: x / width, 7350 yNormalized: y / height, 7351 width, 7352 height 7353 }; 7354 }; 7355 /** 7356 * Translate the mouse coordinates for the event to the coordinates for the given target element 7357 * @param event 7358 * @param domElement 7359 * @returns {{x: number, y: number}} 7360 */ 7361 7362 7363 function translateMouseCoordinates$1(event, domElement) { 7364 const { 7365 clientX, 7366 clientY 7367 } = event; 7368 return getMouseXY$1(domElement, { 7369 clientX, 7370 clientY 7371 }); 7372 } 7373 7374 function createIcon$1(name, color) { 7375 return iconMarkup$1(name, color); 7376 } 7377 7378 function iconMarkup$1(name, color) { 7379 color = color || "currentColor"; 7380 let icon = icons$1[name]; 7381 7382 if (!icon) { 7383 console.error(`No icon named: ${name}`); 7384 icon = icons$1["question"]; 7385 } 7386 7387 const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg"); 7388 svg.setAttributeNS(null, 'viewBox', '0 0 ' + icon[0] + ' ' + icon[1]); 7389 const path = document.createElementNS("http://www.w3.org/2000/svg", "path"); 7390 path.setAttributeNS(null, 'fill', color); 7391 path.setAttributeNS(null, 'd', icon[4]); 7392 svg.appendChild(path); 7393 return svg; 7394 } 7395 7396 const icons$1 = { 7397 "check": [512, 512, [], "f00c", "M173.898 439.404l-166.4-166.4c-9.997-9.997-9.997-26.206 0-36.204l36.203-36.204c9.997-9.998 26.207-9.998 36.204 0L192 312.69 432.095 72.596c9.997-9.997 26.207-9.997 36.204 0l36.203 36.204c9.997 9.997 9.997 26.206 0 36.204l-294.4 294.401c-9.998 9.997-26.207 9.997-36.204-.001z"], 7398 "cog": [512, 512, [], "f013", "M444.788 291.1l42.616 24.599c4.867 2.809 7.126 8.618 5.459 13.985-11.07 35.642-29.97 67.842-54.689 94.586a12.016 12.016 0 0 1-14.832 2.254l-42.584-24.595a191.577 191.577 0 0 1-60.759 35.13v49.182a12.01 12.01 0 0 1-9.377 11.718c-34.956 7.85-72.499 8.256-109.219.007-5.49-1.233-9.403-6.096-9.403-11.723v-49.184a191.555 191.555 0 0 1-60.759-35.13l-42.584 24.595a12.016 12.016 0 0 1-14.832-2.254c-24.718-26.744-43.619-58.944-54.689-94.586-1.667-5.366.592-11.175 5.459-13.985L67.212 291.1a193.48 193.48 0 0 1 0-70.199l-42.616-24.599c-4.867-2.809-7.126-8.618-5.459-13.985 11.07-35.642 29.97-67.842 54.689-94.586a12.016 12.016 0 0 1 14.832-2.254l42.584 24.595a191.577 191.577 0 0 1 60.759-35.13V25.759a12.01 12.01 0 0 1 9.377-11.718c34.956-7.85 72.499-8.256 109.219-.007 5.49 1.233 9.403 6.096 9.403 11.723v49.184a191.555 191.555 0 0 1 60.759 35.13l42.584-24.595a12.016 12.016 0 0 1 14.832 2.254c24.718 26.744 43.619 58.944 54.689 94.586 1.667 5.366-.592 11.175-5.459 13.985L444.788 220.9a193.485 193.485 0 0 1 0 70.2zM336 256c0-44.112-35.888-80-80-80s-80 35.888-80 80 35.888 80 80 80 80-35.888 80-80z"], 7399 "exclamation": [192, 512, [], "f12a", "M176 432c0 44.112-35.888 80-80 80s-80-35.888-80-80 35.888-80 80-80 80 35.888 80 80zM25.26 25.199l13.6 272C39.499 309.972 50.041 320 62.83 320h66.34c12.789 0 23.331-10.028 23.97-22.801l13.6-272C167.425 11.49 156.496 0 142.77 0H49.23C35.504 0 24.575 11.49 25.26 25.199z"], 7400 "exclamation-circle": [512, 512, [], "f06a", "M504 256c0 136.997-111.043 248-248 248S8 392.997 8 256C8 119.083 119.043 8 256 8s248 111.083 248 248zm-248 50c-25.405 0-46 20.595-46 46s20.595 46 46 46 46-20.595 46-46-20.595-46-46-46zm-43.673-165.346l7.418 136c.347 6.364 5.609 11.346 11.982 11.346h48.546c6.373 0 11.635-4.982 11.982-11.346l7.418
7400-136c.375-6.874-5.098-12.654-11.982-12.654h-63.383c-6.884 0-12.356 5.78-11.981 12.654z"], 7401 "exclamation-triangle": [576, 512, [], "f071", "M569.517 440.013C587.975 472.007 564.806 512 527.94 512H48.054c-36.937 0-59.999-40.055-41.577-71.987L246.423 23.985c18.467-32.009 64.72-31.951 83.154 0l239.94 416.028zM288 354c-25.405 0-46 20.595-46 46s20.595 46 46 46 46-20.595 46-46-20.595-46-46-46zm-43.673-165.346l7.418 136c.347 6.364 5.609 11.346 11.982 11.346h48.546c6.373 0 11.635-4.982 11.982-11.346l7.418-136c.375-6.874-5.098-12.654-11.982-12.654h-63.383c-6.884 0-12.356 5.78-11.981 12.654z"], 7402 "minus": [448, 512, [], "f068", "M424 318.2c13.3 0 24-10.7 24-24v-76.4c0-13.3-10.7-24-24-24H24c-13.3 0-24 10.7-24 24v76.4c0 13.3 10.7 24 24 24h400z"], 7403 "minus-circle": [512, 512, [], "f056", "M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zM124 296c-6.6 0-12-5.4-12-12v-56c0-6.6 5.4-12 12-12h264c6.6 0 12 5.4 12 12v56c0 6.6-5.4 12-12 12H124z"], 7404 "minus-square": [448, 512, [], "f146", "M400 32H48C21.5 32 0 53.5 0 80v352c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V80c0-26.5-21.5-48-48-48zM92 296c-6.6 0-12-5.4-12-12v-56c0-6.6 5.4-12 12-12h264c6.6 0 12 5.4 12 12v56c0 6.6-5.4 12-12 12H92z"], 7405 "plus": [448, 512, [], "f067", "M448 294.2v-76.4c0-13.3-10.7-24-24-24H286.2V56c0-13.3-10.7-24-24-24h-76.4c-13.3 0-24 10.7-24 24v137.8H24c-13.3 0-24 10.7-24 24v76.4c0 13.3 10.7 24 24 24h137.8V456c0 13.3 10.7 24 24 24h76.4c13.3 0 24-10.7 24-24V318.2H424c13.3 0 24-10.7 24-24z"], 7406 "plus-circle": [512, 512, [], "f055", "M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm144 276c0 6.6-5.4 12-12 12h-92v92c0 6.6-5.4 12-12 12h-56c-6.6 0-12-5.4-12-12v-92h-92c-6.6 0-12-5.4-12-12v-56c0-6.6 5.4-12 12-12h92v-92c0-6.6 5.4-12 12-12h56c6.6 0 12 5.4 12 12v92h92c6.6 0 12 5.4 12 12v56z"], 7407 "plus-square": [448, 512, [], "f0fe", "M400 32H48C21.5 32 0 53.5 0 80v352c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V80c0-26.5-21.5-48-48-48zm-32 252c0 6.6-5.4 12-12 12h-92v92c0 6.6-5.4 12-12 12h-56c-6.6 0-12-5.4-12-12v-92H92c-6.6 0-12-5.4-12-12v-56c0-6.6 5.4-12 12-12h92v-92c0-6.6 5.4-12 12-12h56c6.6 0 12 5.4 12 12v92h92c6.6 0 12 5.4 12 12v56z"], 7408 "question": [384, 512, [], "f128", "M202.021 0C122.202 0 70.503 32.703 29.914 91.026c-7.363 10.58-5.093 25.086 5.178 32.874l43.138 32.709c10.373 7.865 25.132 6.026 33.253-4.148 25.049-31.381 43.63-49.449 82.757-49.449 30.764 0 68.816 19.799 68.816 49.631 0 22.552-18.617 34.134-48.993 51.164-35.423 19.86-82.299 44.576-82.299 106.405V320c0 13.255 10.745 24 24 24h72.471c13.255 0 24-10.745 24-24v-5.773c0-42.86 125.268-44.645 125.268-160.627C377.504 66.256 286.902 0 202.021 0zM192 373.459c-38.196 0-69.271 31.075-69.271 69.271 0 38.195 31.075 69.27 69.271 69.27s69.271-31.075 69.271-69.271-31.075-69.27-69.271-69.27z"], 7409 "save": [448, 512, [], "f0c7", "M433.941 129.941l-83.882-83.882A48 48 0 0 0 316.118 32H48C21.49 32 0 53.49 0 80v352c0 26.51 21.49 48 48 48h352c26.51 0 48-21.49 48-48V163.882a48 48 0 0 0-14.059-33.941zM224 416c-35.346 0-64-28.654-64-64 0-35.346 28.654-64 64-64s64 28.654 64 64c0 35.346-28.654 64-64 64zm96-304.52V212c0 6.627-5.373 12-12 12H76c-6.627 0-12-5.373-12-12V108c0-6.627 5.373-12 12-12h228.52c3.183 0 6.235 1.264 8.485 3.515l3.48 3.48A11.996 11.996 0 0 1 320 111.48z"], 7410 "search": [512, 512, [], "f002", "M505 442.7L405.3 343c-4.5-4.5-10.6-7-17-7H372c27.6-35.3 44-79.7 44-128C416 93.1 322.9 0 208 0S0 93.1 0 208s93.1 208 208 208c48.3 0 92.7-16.4 128-44v16.3c0 6.4 2.5 12.5 7 17l99.7 99.7c9.4 9.4 24.6 9.4 33.9 0l28.3-28.3c9.4-9.4 9.4-24.6.1-34zM208 336c-70.7 0-128-57.2-128-128 0-70.7 57.2-128 128-128 70.7 0 128 57.2 128 128 0 70.7-57.2 128-128 128z"], 7411 "share": [512, 512, [], "f064", "M503.691 189.836L327.687 37.851C312.281 24.546 288 35.347 288 56.015v80.053C127.371 137.907 0 170.1 0 322.326c0 61.441 39.581 122.309 83.333 154.132 13.653 9.931 33.111-2.533 28.077-18.631C66.066 312.814 132.917 274.316 288 272.085V360c0 20.7 24.3 31.453 39.687 18.164l176.004-152c11.071-9.562 11.086-26.753 0-36.328z"], 7412 "spinner": [512, 512, [], "f110", "M304 48c0 26.51-21.49 48-48 48s-48-21.49-48-48 21.49-48 48-48 48 21.49 48 48zm-48 368c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48-21.49-48-48-48zm208-208c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48-21.49-48-48-48zM96 256c0-26.51-21.49-48-48-48S0 229.49 0 256s21.49 48 48 48 48-21.49 48-48zm12.922 99.078c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48c0-26.509-21.491-48-48-48zm294.156 0c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48c0-26.509-21.49-48-48-48zM108.922 60.922c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48-21.491-48-48-48z"], 7413 "square": [448, 512, [], "f0c8", "M400 32H48C21.5 32 0 53.5 0 80v352c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V80c0-26.5-21.5-48-48-48z"], 7414 "square-full": [512, 512, [], "f45c", "M512 512H0V0h512v512z"], 7415 "times": [384, 512, [], "f00d", "M323.1 441l53.9-53.9c9.4-9.4 9.4-24.5 0-33.9L279.8 256l97.2-97.2c9.4-9.4 9.4-24.5 0-33.9L323.1 71c-9.4-9.4-24.5-9.4-33.9 0L192 168.2 94.8 71c-9.4-9.4-24.5-9.4-33.9 0L7 124.9c-9.4 9.4-9.4 24.5 0 33.9l97.2 97.2L7 353.2c-9.4 9.4-9.4 24.5 0 33.9L60.9 441c9.4 9.4 24.5 9.4 33.9 0l97.2-97.2 97.2 97.2c9.3 9.3 24.5 9.3 33.9 0z"], 7416 "times-circle": [512, 512, [], "f057", "M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm121.6 313.1c4.7 4.7 4.7 12.3 0 17L338 377.6c-4.7 4.7-12.3 4.7-17 0L256 312l-65.1 65.6c-4.7 4.7-12.3 4.7-17 0L134.4 338c-4.7-4.7-4.7-12.3 0-17l65.6-65-65.6-65.1c-4.7-4.7-4.7-12.3 0-17l39.6-39.6c4.7-4.7 12.3-4.7 17 0l65 65.7 65.1-65.6c4.7-4.7 12.3-4.7 17 0l39.6 39.6c4.7 4.7 4.7 12.3 0 17L312 256l65.6 65.1z"],
7417 "wrench": [512, 512, [], "f0ad", "M481.156 200c9.3 0 15.12 10.155 10.325 18.124C466.295 259.992 420.419 288 368 288c-79.222 0-143.501-63.974-143.997-143.079C223.505 65.469 288.548-.001 368.002 0c52.362.001 98.196 27.949 123.4 69.743C496.24 77.766 490.523 88 481.154 88H376l-40 56 40 56h105.156zm-171.649 93.003L109.255 493.255c-24.994 24.993-65.515 24.994-90.51 0-24.993-24.994-24.993-65.516 0-90.51L218.991 202.5c16.16 41.197 49.303 74.335 90.516 90.503zM104 432c0-13.255-10.745-24-24-24s-24 10.745-24 24 10.745 24 24 24 24-10.745 24-24z"] 7418 }; 7419 7420 function attachDialogCloseHandlerWithParent$1(parent, closeHandler) { 7421 var container = document.createElement("div"); 7422 parent.appendChild(container); 7423 container.appendChild(createIcon$1("times")); 7424 container.addEventListener('click', function (e) { 7425 e.preventDefault(); 7426 e.stopPropagation(); 7427 closeHandler(); 7428 }); 7429 } 7430 7431 /** 7432 * Covers string literals and String objects 7433 * @param x 7434 * @returns {boolean} 7435 */ 7436 function isString$3(x) { 7437 return typeof x === "string" || x instanceof String; 7438 } // StackOverflow: http://stackoverflow.com/a/10810674/116169 7439 7440 7441 function numberFormatter$1(rawNumber) { 7442 var dec = String(rawNumber).split(/[.,]/), 7443 sep = ',', 7444 decsep = '.'; 7445 return dec[0].split('').reverse().reduce(function (prev, now, i) { 7446 return i % 3 === 0 ? prev + sep + now : prev + now; 7447 }).split('').reverse().join('') + (dec[1] ? decsep + dec[1] : ''); 7448 } 7449 7450 const splitLines$5 = function (string) { 7451 return string.split(/\n|\r\n|\r/g); 7452 }; 7453 7454 function splitStringRespectingQuotes(string, delim) { 7455 var tokens = [], 7456 len = string.length, 7457 i, 7458 n = 0, 7459 quote = false, 7460 c; 7461 7462 if (len > 0) { 7463 tokens[n] = string.charAt(0); 7464 7465 for (i = 1; i < len; i++) { 7466 c = string.charAt(i); 7467 7468 if (c === '"') { 7469 quote = !quote; 7470 } else if (!quote && c === delim) { 7471 n++; 7472 tokens[n] = ""; 7473 } else { 7474 tokens[n] += c; 7475 } 7476 } 7477 } 7478 7479 return tokens; 7480 } 7481 7482 function stripQuotes$1(str) { 7483 if (str === undefined) { 7484 return str; 7485 } 7486 7487 if (str.startsWith("'") || str.startsWith('"')) { 7488 str = str.substring(1); 7489 } 7490 7491 if (str.endsWith("'") || str.endsWith('"')) { 7492 str = str.substring(0, str.length - 1); 7493 } 7494 7495 return str; 7496 } 7497 7498 function hashCode$1(s) { 7499 return s.split("").reduce(function (a, b) { 7500 a = (a << 5) - a + b.charCodeAt(0); 7501 return a & a; 7502 }, 0); 7503 } 7504 7505 function capitalize(str) { 7506 return str.length > 0 ? str.charAt(0).toUpperCase() + str.slice(1) : str; 7507 } 7508 /** 7509 * Parse a locus string and return a range object. Locus string is of the form chr:start-end. End is optional 7510 * 7511 */ 7512 7513 7514 function parseLocusString$1(string) { 7515 const t1 = string.split(":"); 7516 const t2 = t1[1].split("-"); 7517 const range = { 7518 chr: t1[0], 7519 start: Number.parseInt(t2[0].replace(/,/g, '')) - 1 7520 }; 7521 7522 if (t2.length > 1) { 7523 range.end = Number.parseInt(t2[1].replace(/,/g, '')); 7524 } else { 7525 range.end = range.start + 1; 7526 } 7527 7528 return range; 7529 } 7530 7531 function isGoogleURL(url) { 7532 return url.includes("googleapis") && !url.includes("urlshortener") || isGoogleStorageURL(url) || isGoogleDriveURL(url); 7533 } 7534 7535 function isGoogleStorageURL(url) { 7536 return url.startsWith("gs://") || url.startsWith("https://www.googleapis.com/storage") || url.startsWith("https://storage.cloud.google.com") || url.startsWith("https://storage.googleapis.com"); 7537 } 7538 7539 function isGoogleDriveURL(url) { 7540 return url.indexOf("drive.google.com") >= 0 || url.indexOf("www.googleapis.com/drive") > 0; 7541 } 7542 /** 7543 * Translate gs:// urls to https 7544 * See https://cloud.google.com/storage/docs/json_api/v1 7545 * @param gsUrl 7546 * @returns {string|*} 7547 */ 7548 7549 7550 function translateGoogleCloudURL(gsUrl) { 7551 let { 7552 bucket, 7553 object 7554 } = parseBucketName(gsUrl); 7555 object = encode(object); 7556 const qIdx = gsUrl.indexOf('?'); 7557 const paramString = qIdx > 0 ? gsUrl.substring(qIdx) + "&alt=media" : "?alt=media"; 7558 return `https://storage.googleapis.com/storage/v1/b/${bucket}/o/${object}${paramString}`; 7559 } 7560 /** 7561 * Parse a google bucket and object name from a google storage URL. Known forms include 7562 * 7563 * gs://BUCKET_NAME/OBJECT_NAME 7564 * https://storage.googleapis.com/BUCKET_NAME/OBJECT_NAME 7565 * https://storage.googleapis.com/storage/v1/b/BUCKET_NAME/o/OBJECT_NAME 7566 * https://www.googleapis.com/storage/v1/b/BUCKET_NAME/o/OBJECT_NAME" 7567 * https://storage.googleapis.com/download/storage/v1/b/BUCKET_NAME/o/OBJECT_NAME 7568 * 7569 * @param url 7570 */ 7571 7572 7573 function parseBucketName(url) { 7574 let bucket; 7575 let object; 7576 7577 if (url.startsWith("gs://")) { 7578 const i = url.indexOf('/', 5); 7579 7580 if (i >= 0) { 7581 bucket = url.substring(5, i); 7582 const qIdx = url.indexOf('?'); 7583 object = qIdx < 0 ? url.substring(i + 1) : url.substring(i + 1, qIdx); 7584 } 7585 } else if (url.startsWith("https://storage.googleapis.com") || url.startsWith("https://storage.cloud.google.com")) { 7586 const bucketIdx = url.indexOf("/v1/b/", 8); 7587 7588 if (bucketIdx > 0) { 7589 const objIdx = url.indexOf("/o/", bucketIdx); 7590 7591 if (objIdx > 0) { 7592 const queryIdx = url.indexOf("?", objIdx); 7593 bucket = url.substring(bucketIdx + 6, objIdx); 7594 object = queryIdx > 0 ? url.substring(objIdx + 3, queryIdx) : url.substring(objIdx + 3); 7595 } 7596 } else { 7597 const idx1 = url.indexOf("/", 8); 7598 const idx2 = url.indexOf("/", idx1 + 1); 7599 const idx3 = url.indexOf("?", idx2); 7600 7601 if (idx2 > 0) { 7602 bucket = url.substring(idx1 + 1, idx2); 7603 object = idx3 < 0 ? url.substring(idx2 + 1) : url.substring(idx2 + 1, idx3); 7604 } 7605 } 7606 } else if (url.startsWith("https://www.googleapis.com/storage/v1/b")) { 7607 const bucketIdx = url.indexOf("/v1/b/", 8); 7608 const objIdx = url.indexOf("/o/", bucketIdx); 7609 7610 if (objIdx > 0) { 7611 const queryIdx = url.indexOf("?", objIdx); 7612 bucket = url.substring(bucketIdx + 6, objIdx); 7613 object = queryIdx > 0 ? url.substring(objIdx + 3, queryIdx) : url.substring(objIdx + 3); 7614 } 7615 } 7616 7617 if (bucket && object) { 7618 return { 7619 bucket, 7620 object 7621 }; 7622 } else { 7623 throw Error(`Unrecognized Google Storage URI: ${url}`); 7624 } 7625 } 7626 7627 function driveDownloadURL(link) { 7628 // Return a google drive download url for the sharable link 7629 //https://drive.google.com/open?id=0B-lleX9c2pZFbDJ4VVRxakJzVGM 7630 //https://drive.google.com/file/d/1_FC4kCeO8E3V4dJ1yIW7A0sn1yURKIX-/view?usp=sharing 7631 var id = getGoogleDriveFileID(link); 7632 return id ? "https://www.googleapis.com/drive/v3/files/" + id + "?alt=media&supportsTeamDrives=true" : link; 7633 } 7634 7635 function getGoogleDriveFileID(link) { 7636 //https://drive.google.com/file/d/1_FC4kCeO8E3V4dJ1yIW7A0sn1yURKIX-/view?usp=sharing 7637 //https://www.googleapis.com/drive/v3/files/1w-tvo6p1SH4p1OaQSVxpkV_EJgGIstWF?alt=media&supportsTeamDrives=true" 7638 if (link.includes("/open?id=")) { 7639 const i1 = link.indexOf("/open?id=") + 9; 7640 const i2 = link.indexOf("&"); 7641 7642 if (i1 > 0 && i2 > i1) { 7643 return link.substring(i1, i2); 7644 } else if (i1 > 0) { 7645 return link.substring(i1); 7646 } 7647 } else if (link.includes("/file/d/")) { 7648 const i1 = link.indexOf("/file/d/") + 8; 7649 const i2 = link.lastIndexOf("/"); 7650 return link.substring(i1, i2); 7651 } else if (link.startsWith("https://www.googleapis.com/drive")) { 7652 let i1 = link.indexOf("/files/"); 7653 const i2 = link.indexOf("?"); 7654 7655 if (i1 > 0) { 7656 i1 += 7; 7657 return i2 > 0 ? link.substring(i1, i2) : link.substring(i1); 7658 } 7659 } 7660 7661 throw Error("Unknown Google Drive url format: " + link); 7662 } 7663 /** 7664 * Percent a GCS object name. See https://cloud.google.com/storage/docs/request-endpoints 7665 * Specific characters to encode: 7666 * !, #, $, &, ', (, ), *, +, ,, /, :, ;, =, ?, @, [, ], and space characters. 7667 * @param obj 7668 */ 7669 7670 7671 function encode(objectName) { 7672 let result = ''; 7673 objectName.split('').forEach(function (letter) { 7674 if (encodings.has(letter)) { 7675 result += encodings.get(letter); 7676 } else { 7677 result += letter; 7678 } 7679 }); 7680 return result; 7681 } // %23 %24 %25 %26 %27 %28 %29 %2A %2B %2C %2F %3A %3B %3D %3F %40 %5B %5D 7682 7683 7684 const encodings = new Map(); 7685 encodings.set("!", "%21"); 7686 encodings.set("#", "%23"); 7687 encodings.set("$", "%24"); 7688 encodings.set("%", "%25"); 7689 encodings.set("&", "%26"); 7690 encodings.set("'", "%27"); 7691 encodings.set("(", "%28"); 7692 encodings.set(")", "%29"); 7693 encodings.set("*", "%2A"); 7694 encodings.set("+", "%2B"); 7695 encodings.set(",", "%2C"); 7696 encodings.set("/", "%2F"); 7697 encodings.set(":", "%3A"); 7698 encodings.set(";", "%3B"); 7699 encodings.set("=", "%3D"); 7700 encodings.set("?", "%3F"); 7701 encodings.set("@", "%40"); 7702 encodings.set("[", "%5B"); 7703 encodings.set("]", "%5D"); 7704 encodings.set(" ", "%20"); // For testing 7705 7706 // Convenience functions for the gapi oAuth library. 7707 const FIVE_MINUTES = 5 * 60 * 1000; 7708 7709 async function load$1(library) { 7710 return new Promise(function (resolve, reject) { 7711 gapi.load(library, { 7712 callback: resolve, 7713 onerror: reject 7714 }); 7715 }); 7716 } 7717 7718 async function init$1(config) { 7719 if (isInitialized()) { 7720 console.warn("oAuth has already been initialized"); 7721 return; 7722 } 7723 7724 gapi.apiKey = config.apiKey; // copy config, gapi will modify it 7725 7726 const configCopy = Object.assign({}, config); 7727 7728 if (!configCopy.scope) { 7729 configCopy.scope = 'profile'; 7730 } 7731 7732 if (!config.client_id) { 7733 config.client_id = config.clientId; 7734 } 7735 7736 await load$1("auth2"); 7737 return new Promise(function (resolve, reject) { 7738 gapi.auth2.init(configCopy).then(resolve, reject); 7739 }); 7740 } 7741 7742 function isInitialized() { 7743 return typeof gapi !== "undefined" && gapi.auth2 && gapi.auth2.getAuthInstance(); 7744 } 7745 7746 let inProgress = false;
7747 7748 async function getAccessToken(scope) { 7749 if (typeof gapi === "undefined") { 7750 throw Error("Google authentication requires the 'gapi' library"); 7751 } 7752 7753 if (!gapi.auth2) { 7754 throw Error("Google 'auth2' has not been initialized"); 7755 } 7756 7757 if (inProgress) { 7758 return new Promise(function (resolve, reject) { 7759 let intervalID; 7760 7761 const checkForToken = () => { 7762 // Wait for inProgress to equal "false" 7763 try { 7764 if (inProgress === false) { 7765 //console.log("Delayed resolution for " + scope); 7766 resolve(getAccessToken(scope)); 7767 clearInterval(intervalID); 7768 } 7769 } catch (e) { 7770 clearInterval(intervalID); 7771 reject(e); 7772 } 7773 }; 7774 7775 intervalID = setInterval(checkForToken, 100); 7776 }); 7777 } else { 7778 inProgress = true; 7779 7780 try { 7781 let currentUser = gapi.auth2.getAuthInstance().currentUser.get(); 7782 let token; 7783 7784 if (currentUser.isSignedIn()) { 7785 if (!currentUser.hasGrantedScopes(scope)) { 7786 await currentUser.grant({ 7787 scope 7788 }); 7789 } 7790 7791 const { 7792 access_token, 7793 expires_at 7794 } = currentUser.getAuthResponse(); 7795 7796 if (Date.now() < expires_at - FIVE_MINUTES) { 7797 token = { 7798 access_token, 7799 expires_at 7800 }; 7801 } else { 7802 const { 7803 access_token, 7804 expires_at 7805 } = currentUser.reloadAuthResponse(); 7806 token = { 7807 access_token, 7808 expires_at 7809 }; 7810 } 7811 } else { 7812 currentUser = await signIn(scope); 7813 const { 7814 access_token, 7815 expires_at 7816 } = currentUser.getAuthResponse(); 7817 token = { 7818 access_token, 7819 expires_at 7820 }; 7821 } 7822 7823 return token; 7824 } finally { 7825 inProgress = false; 7826 } 7827 } 7828 } 7829 /** 7830 * Return the current access token if the user is signed in, or undefined otherwise. This function does not 7831 * attempt a signIn or request any specfic scopes. 7832 * 7833 * @returns access_token || undefined 7834 */ 7835 7836 7837 function getCurrentAccessToken() { 7838 let currentUser = gapi.auth2.getAuthInstance().currentUser.get(); 7839 7840 if (currentUser && currentUser.isSignedIn()) { 7841 const { 7842 access_token, 7843 expires_at 7844 } = currentUser.getAuthResponse(); 7845 return { 7846 access_token, 7847 expires_at 7848 }; 7849 } else { 7850 return undefined; 7851 } 7852 } 7853 7854 async function signIn(scope) { 7855 const options = new gapi.auth2.SigninOptionsBuilder(); 7856 options.setPrompt('select_account'); 7857 options.setScope(scope);
7858 return gapi.auth2.getAuthInstance().signIn(options); 7859 } 7860 7861 function getScopeForURL(url) { 7862 if (isGoogleDriveURL(url)) { 7863 return "https://www.googleapis.com/auth/drive.file"; 7864 } else if (isGoogleStorageURL(url)) { 7865 return "https://www.googleapis.com/auth/devstorage.read_only"; 7866 } else { 7867 return 'https://www.googleapis.com/auth/userinfo.profile'; 7868 } 7869 } 7870 7871 function getApiKey() { 7872 return gapi.apiKey; 7873 } 7874 7875 async function getDriveFileInfo(googleDriveURL) { 7876 const id = getGoogleDriveFileID(googleDriveURL); 7877 let endPoint = "https://www.googleapis.com/drive/v3/files/" + id + "?supportsTeamDrives=true"; 7878 const apiKey = getApiKey(); 7879 7880 if (apiKey) { 7881 endPoint += "&key=" + apiKey; 7882 } 7883 7884 const response = await fetch(endPoint); 7885 let json = await response.json(); 7886 7887 if (json.error && json.error.code === 404) { 7888 const { 7889 access_token 7890 } = await getAccessToken("https://www.googleapis.com/auth/drive.readonly"); 7891 7892 if (access_token) { 7893 const response = await fetch(endPoint, { 7894 headers: { 7895 'Authorization': `Bearer ${access_token}` 7896 } 7897 }); 7898 json = await response.json(); 7899 7900 if (json.error) { 7901 throw Error(json.error); 7902 } 7903 } else { 7904 throw Error(json.error); 7905 } 7906 } 7907 7908 return json; 7909 } 7910 7911 if (typeof process === 'object' && typeof window === 'undefined') { 7912 global.atob = function (str) { 7913 return Buffer.from(str, 'base64').toString('binary'); 7914 }; 7915 } 7916 7917 function parseUri(str) { 7918 var o = options, 7919 m = o.parser["loose"].exec(str), 7920 uri = {}, 7921 i = 14; 7922 7923 while (i--) uri[o.key[i]] = m[i] || ""; 7924 7925 uri[o.q.name] = {}; 7926 uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) { 7927 if ($1) uri[o.q.name][$1] = $2; 7928 }); 7929 return uri; 7930 } 7931 7932 const options = { 7933 strictMode: false, 7934 key: ["source", "protocol", "authority", "userInfo", "user", "password", "host", "port", "relative", "path", "directory", "file", "query", "anchor"], 7935 q: { 7936 name: "queryKey", 7937 parser: /(?:^|&)([^&=]*)=?([^&]*)/g 7938 }, 7939 parser: { 7940 strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/, 7941 loose: /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/ 7942 } 7943 }; 7944 /** 7945 * Resolve a url, which might be a string, function (that returns a string or Promse), or Promise (that resolves to a string) 7946 * 7947 * @param url 7948 * @returns {Promise<*>} 7949 */ 7950 7951 7952 async function resolveURL(url) { 7953 return typeof url === 'function' ? url() : url; 7954 } 7955 7956 /** 7957 * Return the filename from the path. Example 7958 * https://foo.com/bar.bed?param=2 => bar.bed 7959 * @param urlOrFile 7960 */ 7961 7962 7963 function getFilename$1(urlOrFile) { 7964 if (isFile(urlOrFile)) { 7965 return urlOrFile.name; 7966 } else if (isString$3(urlOrFile)) { 7967 let index = urlOrFile.lastIndexOf("/"); 7968 let filename = index < 0 ? urlOrFile : urlOrFile.substr(index + 1); //Strip parameters -- handle local files later 7969 7970 index = filename.indexOf("?"); 7971 7972 if (index > 0) { 7973 filename = filename.substr(0, index); 7974 } 7975 7976 return filename; 7977 } else { 7978 throw Error(`Expected File or string, got ${typeof urlOrFile}`); 7979 } 7980 } 7981 /** 7982 * Test if object is a File or File-like object by testing for the "name" property. This is not a robust test, 7983 * but the purpose is to distinguish the object from url strings 7984 * 7985 * @param object 7986 */ 7987 7988 7989 function isFile(object) { 7990 return object !== undefined && (object instanceof File || typeof object !== "function" && object.hasOwnProperty("name") && object.hasOwnProperty("size") && object.hasOwnProperty("type")); 7991 } 7992 7993 const isFilePath = isFile; // deprecated 7994 7995 function download(filename, data) { 7996 const element = document.createElement('a'); 7997 element.setAttribute('href', data); 7998 element.setAttribute('download', filename); 7999 element.style.display = 'none'; 8000 document.body.appendChild(element); 8001 element.click(); 8002 document.body.removeChild(element); 8003 } 8004 8005 // Ths file is a modification of the pako distribution https://github.com/nodeca/pako. The modifications 8006 // consists of simple changes to create an ES6 module, specifically commenting out the function wrapper and 8007 // adding an ES6 export statement. 8008 // ************** COMMENTED OUT BY JTR ******************// 8009 8010 /*! pako 2.0.4 https://github.com/nodeca/pako @license (MIT AND Zlib) */ 8011 // (function (global, factory) { 8012 // typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : 8013 // typeof define === 'function' && define.amd ? define(['exports'], factory) : 8014 // (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.pako = {})); 8015 // }(this, (function (exports) { 'use strict'; 8016 // ************** COMMENTED OUT BY JTR ******************// 8017 // (C) 1995-2013 Jean-loup Gailly and Mark Adler 8018 // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin 8019 // 8020 // This software is provided 'as-is', without any express or implied 8021 // warranty. In no event will the authors be held liable for any damages 8022 // arising from the use of this software. 8023 // 8024 // Permission is granted to anyone to use this software for any purpose, 8025 // including commercial applications, and to alter it and redistribute it 8026 // freely, subject to the following restrictions: 8027 // 8028 // 1. The origin of this software must not be misrepresented; you must not 8029 // claim that you wrote the original software. If you use this software 8030 // in a product, an acknowledgment in the product documentation would be 8031 // appreciated but is not required. 8032 // 2. Altered source versions must be plainly marked as such, and must not be 8033 // misrepresented as being the original software. 8034 // 3. This notice may not be removed or altered from any source distribution. 8035 8036 /* eslint-disable space-unary-ops */ 8037 8038 /* Public constants ==========================================================*/ 8039 8040 /* ===========================================================================*/ 8041 //const Z_FILTERED = 1; 8042 //const Z_HUFFMAN_ONLY = 2; 8043 //const Z_RLE = 3; 8044 const Z_FIXED$1 = 4; //const Z_DEFAULT_STRATEGY = 0; 8045 8046 /* Possible values of the data_type field (though see inflate()) */ 8047 8048 const Z_BINARY = 0; 8049 const Z_TEXT = 1; //const Z_ASCII = 1; // = Z_TEXT 8050 8051 const Z_UNKNOWN$1 = 2; 8052 /*============================================================================*/ 8053 8054 function zero$1(buf) { 8055 let len = buf.length; 8056 8057 while (--len >= 0) { 8058 buf[len] = 0; 8059 } 8060 } // From zutil.h 8061 8062 8063 const STORED_BLOCK = 0; 8064 const STATIC_TREES = 1; 8065 const DYN_TREES = 2; 8066 /* The three kinds of block type */ 8067 8068 const MIN_MATCH$1 = 3; 8069 const MAX_MATCH$1 = 258; 8070 /* The minimum and maximum match lengths */ 8071 // From deflate.h 8072 8073 /* ===========================================================================
vendor: 10,135 bytes, lines 8074-8416
8074 * Internal compression state. 8075 */ 8076 8077 const LENGTH_CODES$1 = 29; 8078 /* number of length codes, not counting the special END_BLOCK code */ 8079 8080 const LITERALS$1 = 256; 8081 /* number of literal bytes 0..255 */ 8082 8083 const L_CODES$1 = LITERALS$1 + 1 + LENGTH_CODES$1; 8084 /* number of Literal or Length codes, including the END_BLOCK code */ 8085 8086 const D_CODES$1 = 30; 8087 /* number of distance codes */ 8088 8089 const BL_CODES$1 = 19; 8090 /* number of codes used to transfer the bit lengths */ 8091 8092 const HEAP_SIZE$1 = 2 * L_CODES$1 + 1; 8093 /* maximum heap size */ 8094 8095 const MAX_BITS$1 = 15; 8096 /* All codes must not exceed MAX_BITS bits */ 8097 8098 const Buf_size = 16; 8099 /* size of bit buffer in bi_buf */ 8100 8101 /* =========================================================================== 8102 * Constants 8103 */ 8104 8105 const MAX_BL_BITS = 7; 8106 /* Bit length codes must not exceed MAX_BL_BITS bits */ 8107 8108 const END_BLOCK = 256; 8109 /* end of block literal code */ 8110 8111 const REP_3_6 = 16; 8112 /* repeat previous bit length 3-6 times (2 bits of repeat count) */ 8113 8114 const REPZ_3_10 = 17; 8115 /* repeat a zero length 3-10 times (3 bits of repeat count) */ 8116 8117 const REPZ_11_138 = 18; 8118 /* repeat a zero length 11-138 times (7 bits of repeat count) */ 8119 8120 /* eslint-disable comma-spacing,array-bracket-spacing */ 8121 8122 const extra_lbits = 8123 /* extra bits for each length code */ 8124 new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0]); 8125 const extra_dbits = 8126 /* extra bits for each distance code */ 8127 new Uint8Array([0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13]); 8128 const extra_blbits = 8129 /* extra bits for each bit length code */ 8130 new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 7]); 8131 const bl_order = new Uint8Array([16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]); 8132 /* eslint-enable comma-spacing,array-bracket-spacing */ 8133 8134 /* The lengths of the bit length codes are sent in order of decreasing 8135 * probability, to avoid transmitting the lengths for unused bit length codes. 8136 */ 8137 8138 /* =========================================================================== 8139 * Local data. These are initialized only once. 8140 */ 8141 // We pre-fill arrays with 0 to avoid uninitialized gaps 8142 8143 const DIST_CODE_LEN = 512; 8144 /* see definition of array dist_code below */ 8145 // !!!! Use flat array instead of structure, Freq = i*2, Len = i*2+1 8146 8147 const static_ltree = new Array((L_CODES$1 + 2) * 2); 8148 zero$1(static_ltree); 8149 /* The static literal tree. Since the bit lengths are imposed, there is no 8150 * need for the L_CODES extra codes used during heap construction. However 8151 * The codes 286 and 287 are needed to build a canonical tree (see _tr_init 8152 * below). 8153 */ 8154 8155 const static_dtree = new Array(D_CODES$1 * 2); 8156 zero$1(static_dtree); 8157 /* The static distance tree. (Actually a trivial tree since all codes use 8158 * 5 bits.) 8159 */ 8160 8161 const _dist_code = new Array(DIST_CODE_LEN); 8162 8163 zero$1(_dist_code); 8164 /* Distance codes. The first 256 values correspond to the distances 8165 * 3 .. 258, the last 256 values correspond to the top 8 bits of 8166 * the 15 bit distances. 8167 */ 8168 8169 const _length_code = new Array(MAX_MATCH$1 - MIN_MATCH$1 + 1); 8170 8171 zero$1(_length_code); 8172 /* length code for each normalized match length (0 == MIN_MATCH) */ 8173 8174 const base_length = new Array(LENGTH_CODES$1); 8175 zero$1(base_length); 8176 /* First normalized length for each code (0 = MIN_MATCH) */ 8177 8178 const base_dist = new Array(D_CODES$1); 8179 zero$1(base_dist); 8180 /* First normalized distance for each code (0 = distance of 1) */ 8181 8182 function StaticTreeDesc(static_tree, extra_bits, extra_base, elems, max_length) { 8183 this.static_tree = static_tree; 8184 /* static tree or NULL */ 8185 8186 this.extra_bits = extra_bits; 8187 /* extra bits for each code or NULL */ 8188 8189 this.extra_base = extra_base; 8190 /* base index for extra_bits */ 8191 8192 this.elems = elems; 8193 /* max number of elements in the tree */ 8194 8195 this.max_length = max_length; 8196 /* max bit length for the codes */ 8197 // show if `static_tree` has data or dummy - needed for monomorphic objects 8198 8199 this.has_stree = static_tree && static_tree.length; 8200 } 8201 8202 let static_l_desc; 8203 let static_d_desc; 8204 let static_bl_desc; 8205 8206 function TreeDesc(dyn_tree, stat_desc) { 8207 this.dyn_tree = dyn_tree; 8208 /* the dynamic tree */ 8209 8210 this.max_code = 0; 8211 /* largest code with non zero frequency */ 8212 8213 this.stat_desc = stat_desc; 8214 /* the corresponding static tree */ 8215 } 8216 8217 const d_code = dist => { 8218 return dist < 256 ? _dist_code[dist] : _dist_code[256 + (dist >>> 7)]; 8219 }; 8220 /* =========================================================================== 8221 * Output a short LSB first on the stream. 8222 * IN assertion: there is enough room in pendingBuf. 8223 */ 8224 8225 8226 const put_short = (s, w) => { 8227 // put_byte(s, (uch)((w) & 0xff)); 8228 // put_byte(s, (uch)((ush)(w) >> 8)); 8229 s.pending_buf[s.pending++] = w & 0xff; 8230 s.pending_buf[s.pending++] = w >>> 8 & 0xff; 8231 }; 8232 /* =========================================================================== 8233 * Send a value on a given number of bits. 8234 * IN assertion: length <= 16 and value fits in length bits. 8235 */ 8236 8237 8238 const send_bits = (s, value, length) => { 8239 if (s.bi_valid > Buf_size - length) { 8240 s.bi_buf |= value << s.bi_valid & 0xffff; 8241 put_short(s, s.bi_buf); 8242 s.bi_buf = value >> Buf_size - s.bi_valid; 8243 s.bi_valid += length - Buf_size; 8244 } else { 8245 s.bi_buf |= value << s.bi_valid & 0xffff; 8246 s.bi_valid += length; 8247 } 8248 }; 8249 8250 const send_code = (s, c, tree) => { 8251 send_bits(s, tree[c * 2] 8252 /*.Code*/ 8253 , tree[c * 2 + 1] 8254 /*.Len*/ 8255 ); 8256 }; 8257 /* =========================================================================== 8258 * Reverse the first len bits of a code, using straightforward code (a faster 8259 * method would use a table) 8260 * IN assertion: 1 <= len <= 15 8261 */ 8262 8263 8264 const bi_reverse = (code, len) => { 8265 let res = 0; 8266 8267 do { 8268 res |= code & 1; 8269 code >>>= 1; 8270 res <<= 1; 8271 } while (--len > 0); 8272 8273 return res >>> 1; 8274 }; 8275 /* =========================================================================== 8276 * Flush the bit buffer, keeping at most 7 bits in it. 8277 */ 8278 8279 8280 const bi_flush = s => { 8281 if (s.bi_valid === 16) { 8282 put_short(s, s.bi_buf); 8283 s.bi_buf = 0; 8284 s.bi_valid = 0; 8285 } else if (s.bi_valid >= 8) { 8286 s.pending_buf[s.pending++] = s.bi_buf & 0xff; 8287 s.bi_buf >>= 8; 8288 s.bi_valid -= 8; 8289 } 8290 }; 8291 /* =========================================================================== 8292 * Compute the optimal bit lengths for a tree and update the total bit length 8293 * for the current block. 8294 * IN assertion: the fields freq and dad are set, heap[heap_max] and 8295 * above are the tree nodes sorted by increasing frequency. 8296 * OUT assertions: the field len is set to the optimal bit length, the 8297 * array bl_count contains the frequencies for each bit length. 8298 * The length opt_len is updated; static_len is also updated if stree is 8299 * not null. 8300 */ 8301 8302 8303 const gen_bitlen = (s, desc) => // deflate_state *s; 8304 // tree_desc *desc; /* the tree descriptor */ 8305 { 8306 const tree = desc.dyn_tree; 8307 const max_code = desc.max_code; 8308 const stree = desc.stat_desc.static_tree; 8309 const has_stree = desc.stat_desc.has_stree; 8310 const extra = desc.stat_desc.extra_bits; 8311 const base = desc.stat_desc.extra_base; 8312 const max_length = desc.stat_desc.max_length; 8313 let h; 8314 /* heap index */ 8315 8316 let n, m; 8317 /* iterate over the tree elements */ 8318 8319 let bits; 8320 /* bit length */ 8321 8322 let xbits; 8323 /* extra bits */ 8324 8325 let f; 8326 /* frequency */ 8327 8328 let overflow = 0; 8329 /* number of elements with bit length too large */ 8330 8331 for (bits = 0; bits <= MAX_BITS$1; bits++) { 8332 s.bl_count[bits] = 0; 8333 } 8334 /* In a first pass, compute the optimal bit lengths (which may 8335 * overflow in the case of the bit length tree). 8336 */ 8337 8338 8339 tree[s.heap[s.heap_max] * 2 + 1] 8340 /*.Len*/ 8341 = 0; 8342 /* root of the heap */ 8343 8344 for (h = s.heap_max + 1; h < HEAP_SIZE$1; h++) { 8345 n = s.heap[h]; 8346 bits = tree[tree[n * 2 + 1] 8347 /*.Dad*/ 8348 * 2 + 1] 8349 /*.Len*/ 8350 + 1; 8351 8352 if (bits > max_length) { 8353 bits = max_length; 8354 overflow++; 8355 } 8356 8357 tree[n * 2 + 1] 8358 /*.Len*/ 8359 = bits; 8360 /* We overwrite tree[n].Dad which is no longer needed */ 8361 8362 if (n > max_code) { 8363 continue; 8364 } 8365 /* not a leaf node */ 8366 8367 8368 s.bl_count[bits]++; 8369 xbits = 0; 8370 8371 if (n >= base) { 8372 xbits = extra[n - base]; 8373 } 8374 8375 f = tree[n * 2] 8376 /*.Freq*/ 8377 ; 8378 s.opt_len += f * (bits + xbits); 8379 8380 if (has_stree) { 8381 s.static_len += f * (stree[n * 2 + 1] 8382 /*.Len*/ 8383 + xbits); 8384 } 8385 } 8386 8387 if (overflow === 0) { 8388 return; 8389 } // Trace((stderr,"\nbit length overflow\n")); 8390 8391 /* This happens for example on obj2 and pic of the Calgary corpus */ 8392 8393 /* Find the first bit length which could increase: */ 8394 8395 8396 do { 8397 bits = max_length - 1; 8398 8399 while (s.bl_count[bits] === 0) { 8400 bits--; 8401 } 8402 8403 s.bl_count[bits]--; 8404 /* move one leaf down the tree */ 8405 8406 s.bl_count[bits + 1] += 2; 8407 /* move one overflow item as its brother */ 8408 8409 s.bl_count[max_length]--; 8410 /* The brother of the overflow item also moves one step up, 8411 * but this does not affect bl_count[max_length] 8412 */ 8413 8414 overflow -= 2; 8415 } while (overflow > 0); 8416 /* Now recompute all bit lengths, scanning in increasing frequency.
8417 * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all 8418 * lengths instead of fixing only the wrong ones. This idea is taken 8419 * from 'ar' written by Haruhiko Okumura.) 8420 */ 8421 8422 8423 for (bits = max_length; bits !== 0; bits--) { 8424 n = s.bl_count[bits]; 8425 8426 while (n !== 0) { 8427 m = s.heap[--h]; 8428 8429 if (m > max_code) { 8430 continue; 8431 } 8432 8433 if (tree[m * 2 + 1] 8434 /*.Len*/ 8435 !== bits) { 8436 // Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); 8437 s.opt_len += (bits - tree[m * 2 + 1] 8438 /*.Len*/ 8439 ) * tree[m * 2] 8440 /*.Freq*/ 8441 ; 8442 tree[m * 2 + 1] 8443 /*.Len*/ 8444 = bits; 8445 } 8446 8447 n--; 8448 } 8449 } 8450 }; 8451 /* =========================================================================== 8452 * Generate the codes for a given tree and bit counts (which need not be 8453 * optimal). 8454 * IN assertion: the array bl_count contains the bit length statistics for 8455 * the given tree and the field len is set for all tree elements. 8456 * OUT assertion: the field code is set for all tree elements of non 8457 * zero code length. 8458 */ 8459 8460 8461 const gen_codes = (tree, max_code, bl_count) => // ct_data *tree; /* the tree to decorate */ 8462 // int max_code; /* largest code with non zero frequency */ 8463 // ushf *bl_count; /* number of codes at each bit length */ 8464 { 8465 const next_code = new Array(MAX_BITS$1 + 1); 8466 /* next code value for each bit length */ 8467 8468 let code = 0; 8469 /* running code value */ 8470 8471 let bits; 8472 /* bit index */ 8473 8474 let n; 8475 /* code index */ 8476 8477 /* The distribution counts are first used to generate the code values 8478 * without bit reversal. 8479 */ 8480 8481 for (bits = 1; bits <= MAX_BITS$1; bits++) { 8482 next_code[bits] = code = code + bl_count[bits - 1] << 1; 8483 } 8484 /* Check that the bit counts in bl_count are consistent. The last code 8485 * must be all ones. 8486 */ 8487 //Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1, 8488 // "inconsistent bit counts"); 8489 //Tracev((stderr,"\ngen_codes: max_code %d ", max_code)); 8490 8491 8492 for (n = 0; n <= max_code; n++) { 8493 let len = tree[n * 2 + 1] 8494 /*.Len*/ 8495 ; 8496 8497 if (len === 0) { 8498 continue; 8499 } 8500 /* Now reverse the bits */ 8501 8502 8503 tree[n * 2] 8504 /*.Code*/ 8505 = bi_reverse(next_code[len]++, len); //Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ", 8506 // n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1)); 8507 } 8508 }; 8509 /* =========================================================================== 8510 * Initialize the various 'constant' tables. 8511 */ 8512 8513 8514 const tr_static_init = () => { 8515 let n; 8516 /* iterates over tree elements */ 8517 8518 let bits; 8519 /* bit counter */ 8520 8521 let length; 8522 /* length value */ 8523 8524 let code; 8525 /* code value */ 8526 8527 let dist; 8528 /* distance index */ 8529 8530 const bl_count = new Array(MAX_BITS$1 + 1); 8531 /* number of codes at each bit length for an optimal tree */ 8532 // do check in _tr_init() 8533 //if (static_init_done) return; 8534 8535 /* For some embedded targets, global variables are not initialized: */ 8536 8537 /*#ifdef NO_INIT_GLOBAL_POINTERS 8538 static_l_desc.static_tree = static_ltree; 8539 static_l_desc.extra_bits = extra_lbits; 8540 static_d_desc.static_tree = static_dtree; 8541 static_d_desc.extra_bits = extra_dbits; 8542 static_bl_desc.extra_bits = extra_blbits; 8543 #endif*/ 8544 8545 /* Initialize the mapping length (0..255) -> length code (0..28) */ 8546 8547 length = 0; 8548 8549 for (code = 0; code < LENGTH_CODES$1 - 1; code++) { 8550 base_length[code] = length; 8551 8552 for (n = 0; n < 1 << extra_lbits[code]; n++) { 8553 _length_code[length++] = code; 8554 } 8555 } //Assert (length == 256, "tr_static_init: length != 256"); 8556 8557 /* Note that the length 255 (match length 258) can be represented 8558 * in two different ways: code 284 + 5 bits or code 285, so we 8559 * overwrite length_code[255] to use the best encoding: 8560 */ 8561 8562 8563 _length_code[length - 1] = code; 8564 /* Initialize the mapping dist (0..32K) -> dist code (0..29) */ 8565 8566 dist = 0; 8567 8568 for (code = 0;
vendor: 26,440 bytes, lines 8568-9469
8568 code < 16; code++) { 8569 base_dist[code] = dist; 8570 8571 for (n = 0; n < 1 << extra_dbits[code]; n++) { 8572 _dist_code[dist++] = code; 8573 } 8574 } //Assert (dist == 256, "tr_static_init: dist != 256"); 8575 8576 8577 dist >>= 7; 8578 /* from now on, all distances are divided by 128 */ 8579 8580 for (; code < D_CODES$1; code++) { 8581 base_dist[code] = dist << 7; 8582 8583 for (n = 0; n < 1 << extra_dbits[code] - 7; n++) { 8584 _dist_code[256 + dist++] = code; 8585 } 8586 } //Assert (dist == 256, "tr_static_init: 256+dist != 512"); 8587 8588 /* Construct the codes of the static literal tree */ 8589 8590 8591 for (bits = 0; bits <= MAX_BITS$1; bits++) { 8592 bl_count[bits] = 0; 8593 } 8594 8595 n = 0; 8596 8597 while (n <= 143) { 8598 static_ltree[n * 2 + 1] 8599 /*.Len*/ 8600 = 8; 8601 n++; 8602 bl_count[8]++; 8603 } 8604 8605 while (n <= 255) { 8606 static_ltree[n * 2 + 1] 8607 /*.Len*/ 8608 = 9; 8609 n++; 8610 bl_count[9]++; 8611 } 8612 8613 while (n <= 279) { 8614 static_ltree[n * 2 + 1] 8615 /*.Len*/ 8616 = 7; 8617 n++; 8618 bl_count[7]++; 8619 } 8620 8621 while (n <= 287) { 8622 static_ltree[n * 2 + 1] 8623 /*.Len*/ 8624 = 8; 8625 n++; 8626 bl_count[8]++; 8627 } 8628 /* Codes 286 and 287 do not exist, but we must include them in the 8629 * tree construction to get a canonical Huffman tree (longest code 8630 * all ones) 8631 */ 8632 8633 8634 gen_codes(static_ltree, L_CODES$1 + 1, bl_count); 8635 /* The static distance tree is trivial: */ 8636 8637 for (n = 0; n < D_CODES$1; n++) { 8638 static_dtree[n * 2 + 1] 8639 /*.Len*/ 8640 = 5; 8641 static_dtree[n * 2] 8642 /*.Code*/ 8643 = bi_reverse(n, 5); 8644 } // Now data ready and we can init static trees 8645 8646 8647 static_l_desc = new StaticTreeDesc(static_ltree, extra_lbits, LITERALS$1 + 1, L_CODES$1, MAX_BITS$1); 8648 static_d_desc = new StaticTreeDesc(static_dtree, extra_dbits, 0, D_CODES$1, MAX_BITS$1); 8649 static_bl_desc = new StaticTreeDesc(new Array(0), extra_blbits, 0, BL_CODES$1, MAX_BL_BITS); //static_init_done = true; 8650 }; 8651 /* =========================================================================== 8652 * Initialize a new block. 8653 */ 8654 8655 8656 const init_block = s => { 8657 let n; 8658 /* iterates over tree elements */ 8659 8660 /* Initialize the trees. */ 8661 8662 for (n = 0; n < L_CODES$1; n++) { 8663 s.dyn_ltree[n * 2] 8664 /*.Freq*/ 8665 = 0; 8666 } 8667 8668 for (n = 0; n < D_CODES$1; n++) { 8669 s.dyn_dtree[n * 2] 8670 /*.Freq*/ 8671 = 0; 8672 } 8673 8674 for (n = 0; n < BL_CODES$1; n++) { 8675 s.bl_tree[n * 2] 8676 /*.Freq*/ 8677 = 0; 8678 } 8679 8680 s.dyn_ltree[END_BLOCK * 2] 8681 /*.Freq*/ 8682 = 1; 8683 s.opt_len = s.static_len = 0; 8684 s.last_lit = s.matches = 0; 8685 }; 8686 /* =========================================================================== 8687 * Flush the bit buffer and align the output on a byte boundary 8688 */ 8689 8690 8691 const bi_windup = s => { 8692 if (s.bi_valid > 8) { 8693 put_short(s, s.bi_buf); 8694 } else if (s.bi_valid > 0) { 8695 //put_byte(s, (Byte)s->bi_buf); 8696 s.pending_buf[s.pending++] = s.bi_buf; 8697 } 8698 8699 s.bi_buf = 0; 8700 s.bi_valid = 0; 8701 }; 8702 /* =========================================================================== 8703 * Copy a stored block, storing first the length and its 8704 * one's complement if requested. 8705 */ 8706 8707 8708 const copy_block = (s, buf, len, header) => //DeflateState *s; 8709 //charf *buf; /* the input data */ 8710 //unsigned len; /* its length */ 8711 //int header; /* true if block header must be written */ 8712 { 8713 bi_windup(s); 8714 /* align on byte boundary */ 8715 8716 if (header) { 8717 put_short(s, len); 8718 put_short(s, ~len); 8719 } // while (len--) { 8720 // put_byte(s, *buf++); 8721 // } 8722 8723 8724 s.pending_buf.set(s.window.subarray(buf, buf + len), s.pending); 8725 s.pending += len; 8726 }; 8727 /* =========================================================================== 8728 * Compares to subtrees, using the tree depth as tie breaker when 8729 * the subtrees have equal frequency. This minimizes the worst case length. 8730 */ 8731 8732 8733 const smaller = (tree, n, m, depth) => { 8734 const _n2 = n * 2; 8735 8736 const _m2 = m * 2; 8737 8738 return tree[_n2] 8739 /*.Freq*/ 8740 < tree[_m2] 8741 /*.Freq*/ 8742 || tree[_n2] 8743 /*.Freq*/ 8744 === tree[_m2] 8745 /*.Freq*/ 8746 && depth[n] <= depth[m]; 8747 }; 8748 /* =========================================================================== 8749 * Restore the heap property by moving down the tree starting at node k, 8750 * exchanging a node with the smallest of its two sons if necessary, stopping 8751 * when the heap property is re-established (each father smaller than its 8752 * two sons). 8753 */ 8754 8755 8756 const pqdownheap = (s, tree, k) => // deflate_state *s; 8757 // ct_data *tree; /* the tree to restore */ 8758 // int k; /* node to move down */ 8759 { 8760 const v = s.heap[k]; 8761 let j = k << 1; 8762 /* left son of k */ 8763 8764 while (j <= s.heap_len) { 8765 /* Set j to the smallest of the two sons: */ 8766 if (j < s.heap_len && smaller(tree, s.heap[j + 1], s.heap[j], s.depth)) { 8767 j++; 8768 } 8769 /* Exit if v is smaller than both sons */ 8770 8771 8772 if (smaller(tree, v, s.heap[j], s.depth)) { 8773 break; 8774 } 8775 /* Exchange v with the smallest son */ 8776 8777 8778 s.heap[k] = s.heap[j]; 8779 k = j; 8780 /* And continue down the tree, setting j to the left son of k */ 8781 8782 j <<= 1; 8783 } 8784 8785 s.heap[k] = v; 8786 }; // inlined manually 8787 // const SMALLEST = 1; 8788 8789 /* =========================================================================== 8790 * Send the block data compressed using the given Huffman trees 8791 */ 8792 8793 8794 const compress_block = (s, ltree, dtree) => // deflate_state *s; 8795 // const ct_data *ltree; /* literal tree */ 8796 // const ct_data *dtree; /* distance tree */ 8797 { 8798 let dist; 8799 /* distance of matched string */ 8800 8801 let lc; 8802 /* match length or unmatched char (if dist == 0) */ 8803 8804 let lx = 0; 8805 /* running index in l_buf */ 8806 8807 let code; 8808 /* the code to send */ 8809 8810 let extra; 8811 /* number of extra bits to send */ 8812 8813 if (s.last_lit !== 0) { 8814 do { 8815 dist = s.pending_buf[s.d_buf + lx * 2] << 8 | s.pending_buf[s.d_buf + lx * 2 + 1]; 8816 lc = s.pending_buf[s.l_buf + lx]; 8817 lx++; 8818 8819 if (dist === 0) { 8820 send_code(s, lc, ltree); 8821 /* send a literal byte */ 8822 //Tracecv(isgraph(lc), (stderr," '%c' ", lc)); 8823 } else { 8824 /* Here, lc is the match length - MIN_MATCH */ 8825 code = _length_code[lc]; 8826 send_code(s, code + LITERALS$1 + 1, ltree); 8827 /* send the length code */ 8828 8829 extra = extra_lbits[code]; 8830 8831 if (extra !== 0) { 8832 lc -= base_length[code]; 8833 send_bits(s, lc, extra); 8834 /* send the extra length bits */ 8835 } 8836 8837 dist--; 8838 /* dist is now the match distance - 1 */ 8839 8840 code = d_code(dist); //Assert (code < D_CODES, "bad d_code"); 8841 8842 send_code(s, code, dtree); 8843 /* send the distance code */ 8844 8845 extra = extra_dbits[code]; 8846 8847 if (extra !== 0) { 8848 dist -= base_dist[code]; 8849 send_bits(s, dist, extra); 8850 /* send the extra distance bits */ 8851 } 8852 } 8853 /* literal or match pair ? */ 8854 8855 /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ 8856 //Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx, 8857 // "pendingBuf overflow"); 8858 8859 } while (lx < s.last_lit); 8860 } 8861 8862 send_code(s, END_BLOCK, ltree); 8863 }; 8864 /* =========================================================================== 8865 * Construct one Huffman tree and assigns the code bit strings and lengths. 8866 * Update the total bit length for the current block. 8867 * IN assertion: the field freq is set for all tree elements. 8868 * OUT assertions: the fields len and code are set to the optimal bit length 8869 * and corresponding code. The length opt_len is updated; static_len is 8870 * also updated if stree is not null. The field max_code is set. 8871 */ 8872 8873 8874 const build_tree = (s, desc) => // deflate_state *s; 8875 // tree_desc *desc; /* the tree descriptor */ 8876 { 8877 const tree = desc.dyn_tree; 8878 const stree = desc.stat_desc.static_tree; 8879 const has_stree = desc.stat_desc.has_stree; 8880 const elems = desc.stat_desc.elems; 8881 let n, m; 8882 /* iterate over heap elements */ 8883 8884 let max_code = -1; 8885 /* largest code with non zero frequency */ 8886 8887 let node; 8888 /* new node being created */ 8889 8890 /* Construct the initial heap, with least frequent element in 8891 * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. 8892 * heap[0] is not used. 8893 */ 8894 8895 s.heap_len = 0; 8896 s.heap_max = HEAP_SIZE$1; 8897 8898 for (n = 0; n < elems; n++) { 8899 if (tree[n * 2] 8900 /*.Freq*/ 8901 !== 0) { 8902 s.heap[++s.heap_len] = max_code = n; 8903 s.depth[n] = 0; 8904 } else { 8905 tree[n * 2 + 1] 8906 /*.Len*/ 8907 = 0; 8908 } 8909 } 8910 /* The pkzip format requires that at least one distance code exists, 8911 * and that at least one bit should be sent even if there is only one 8912 * possible code. So to avoid special checks later on we force at least 8913 * two codes of non zero frequency. 8914 */ 8915 8916 8917 while (s.heap_len < 2) { 8918 node = s.heap[++s.heap_len] = max_code < 2 ? ++max_code : 0; 8919 tree[node * 2] 8920 /*.Freq*/ 8921 = 1; 8922 s.depth[node] = 0; 8923 s.opt_len--; 8924 8925 if (has_stree) { 8926 s.static_len -= stree[node * 2 + 1] 8927 /*.Len*/ 8928 ; 8929 } 8930 /* node is 0 or 1 so it does not have extra bits */ 8931 8932 } 8933 8934 desc.max_code = max_code; 8935 /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, 8936 * establish sub-heaps of increasing lengths: 8937 */ 8938 8939 for (n = s.heap_len >> 1 8940 /*int /2*/ 8941 ; n >= 1; n--) { 8942 pqdownheap(s, tree, n); 8943 } 8944 /* Construct the Huffman tree by repeatedly combining the least two 8945 * frequent nodes. 8946 */ 8947 8948 8949 node = elems; 8950 /* next internal node of the tree */ 8951 8952 do { 8953 //pqremove(s, tree, n); /* n = node of least frequency */ 8954 8955 /*** pqremove ***/ 8956 n = s.heap[1 8957 /*SMALLEST*/ 8958 ]; 8959 s.heap[1 8960 /*SMALLEST*/ 8961 ] = s.heap[s.heap_len--]; 8962 pqdownheap(s, tree, 1 8963 /*SMALLEST*/ 8964 ); 8965 /***/ 8966 8967 m = s.heap[1 8968 /*SMALLEST*/ 8969 ]; 8970 /* m = node of next least frequency */ 8971 8972 s.heap[--s.heap_max] = n; 8973 /* keep the nodes sorted by frequency */ 8974 8975 s.heap[--s.heap_max] = m; 8976 /* Create a new node father of n and m */ 8977 8978 tree[node * 2] 8979 /*.Freq*/ 8980 = tree[n * 2] 8981 /*.Freq*/ 8982 + tree[m * 2] 8983 /*.Freq*/ 8984 ; 8985 s.depth[node] = (s.depth[n] >= s.depth[m] ? s.depth[n] : s.depth[m]) + 1; 8986 tree[n * 2 + 1] 8987 /*.Dad*/ 8988 = tree[m * 2 + 1] 8989 /*.Dad*/ 8990 = node; 8991 /* and insert the new node in the heap */ 8992 8993 s.heap[1 8994 /*SMALLEST*/ 8995 ] = node++; 8996 pqdownheap(s, tree, 1 8997 /*SMALLEST*/ 8998 ); 8999 } while (s.heap_len >= 2); 9000 9001 s.heap[--s.heap_max] = s.heap[1 9002 /*SMALLEST*/ 9003 ]; 9004 /* At this point, the fields freq and dad are set. We can now 9005 * generate the bit lengths. 9006 */ 9007 9008 gen_bitlen(s, desc); 9009 /* The field len is now set, we can generate the bit codes */ 9010 9011 gen_codes(tree, max_code, s.bl_count); 9012 }; 9013 /* =========================================================================== 9014 * Scan a literal or distance tree to determine the frequencies of the codes 9015 * in the bit length tree. 9016 */ 9017 9018 9019 const scan_tree = (s, tree, max_code) => // deflate_state *s; 9020 // ct_data *tree; /* the tree to be scanned */ 9021 // int max_code; /* and its largest code of non zero frequency */ 9022 { 9023 let n; 9024 /* iterates over all tree elements */ 9025 9026 let prevlen = -1; 9027 /* last emitted length */ 9028 9029 let curlen; 9030 /* length of current code */ 9031 9032 let nextlen = tree[0 * 2 + 1] 9033 /*.Len*/ 9034 ; 9035 /* length of next code */ 9036 9037 let count = 0; 9038 /* repeat count of the current code */ 9039 9040 let max_count = 7; 9041 /* max repeat count */ 9042 9043 let min_count = 4; 9044 /* min repeat count */ 9045 9046 if (nextlen === 0) { 9047 max_count = 138; 9048 min_count = 3; 9049 } 9050 9051 tree[(max_code + 1) * 2 + 1] 9052 /*.Len*/ 9053 = 0xffff; 9054 /* guard */ 9055 9056 for (n = 0; n <= max_code; n++) { 9057 curlen = nextlen; 9058 nextlen = tree[(n + 1) * 2 + 1] 9059 /*.Len*/ 9060 ; 9061 9062 if (++count < max_count && curlen === nextlen) { 9063 continue; 9064 } else if (count < min_count) { 9065 s.bl_tree[curlen * 2] 9066 /*.Freq*/ 9067 += count; 9068 } else if (curlen !== 0) { 9069 if (curlen !== prevlen) { 9070 s.bl_tree[curlen * 2] /*.Freq*/++; 9071 } 9072 9073 s.bl_tree[REP_3_6 * 2] /*.Freq*/++; 9074 } else if (count <= 10) { 9075 s.bl_tree[REPZ_3_10 * 2] /*.Freq*/++; 9076 } else { 9077 s.bl_tree[REPZ_11_138 * 2] /*.Freq*/++; 9078 } 9079 9080 count = 0; 9081 prevlen = curlen; 9082 9083 if (nextlen === 0) { 9084 max_count = 138; 9085 min_count = 3; 9086 } else if (curlen === nextlen) { 9087 max_count = 6; 9088 min_count = 3; 9089 } else { 9090 max_count = 7; 9091 min_count = 4; 9092 } 9093 } 9094 }; 9095 /* =========================================================================== 9096 * Send a literal or distance tree in compressed form, using the codes in 9097 * bl_tree. 9098 */ 9099 9100 9101 const send_tree = (s, tree, max_code) => // deflate_state *s; 9102 // ct_data *tree; /* the tree to be scanned */ 9103 // int max_code; /* and its largest code of non zero frequency */ 9104 { 9105 let n; 9106 /* iterates over all tree elements */ 9107 9108 let prevlen = -1; 9109 /* last emitted length */ 9110 9111 let curlen; 9112 /* length of current code */ 9113 9114 let nextlen = tree[0 * 2 + 1] 9115 /*.Len*/ 9116 ; 9117 /* length of next code */ 9118 9119 let count = 0; 9120 /* repeat count of the current code */ 9121 9122 let max_count = 7; 9123 /* max repeat count */ 9124 9125 let min_count = 4; 9126 /* min repeat count */ 9127 9128 /* tree[max_code+1].Len = -1; */ 9129 9130 /* guard already set */ 9131 9132 if (nextlen === 0) { 9133 max_count = 138; 9134 min_count = 3; 9135 } 9136 9137 for (n = 0; n <= max_code; n++) { 9138 curlen = nextlen; 9139 nextlen = tree[(n + 1) * 2 + 1] 9140 /*.Len*/ 9141 ; 9142 9143 if (++count < max_count && curlen === nextlen) { 9144 continue; 9145 } else if (count < min_count) { 9146 do { 9147 send_code(s, curlen, s.bl_tree); 9148 } while (--count !== 0); 9149 } else if (curlen !== 0) { 9150 if (curlen !== prevlen) { 9151 send_code(s, curlen, s.bl_tree); 9152 count--; 9153 } //Assert(count >= 3 && count <= 6, " 3_6?"); 9154 9155 9156 send_code(s, REP_3_6, s.bl_tree); 9157 send_bits(s, count - 3, 2); 9158 } else if (count <= 10) { 9159 send_code(s, REPZ_3_10, s.bl_tree); 9160 send_bits(s, count - 3, 3); 9161 } else { 9162 send_code(s, REPZ_11_138, s.bl_tree); 9163 send_bits(s, count - 11, 7); 9164 } 9165 9166 count = 0; 9167 prevlen = curlen; 9168 9169 if (nextlen === 0) { 9170 max_count = 138; 9171 min_count = 3; 9172 } else if (curlen === nextlen) { 9173 max_count = 6; 9174 min_count = 3; 9175 } else { 9176 max_count = 7; 9177 min_count = 4; 9178 } 9179 } 9180 }; 9181 /* =========================================================================== 9182 * Construct the Huffman tree for the bit lengths and return the index in 9183 * bl_order of the last bit length code to send. 9184 */ 9185 9186 9187 const build_bl_tree = s => { 9188 let max_blindex; 9189 /* index of last bit length code of non zero freq */ 9190 9191 /* Determine the bit length frequencies for literal and distance trees */ 9192 9193 scan_tree(s, s.dyn_ltree, s.l_desc.max_code); 9194 scan_tree(s, s.dyn_dtree, s.d_desc.max_code); 9195 /* Build the bit length tree: */ 9196 9197 build_tree(s, s.bl_desc); 9198 /* opt_len now includes the length of the tree representations, except 9199 * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. 9200 */ 9201 9202 /* Determine the number of bit length codes to send. The pkzip format 9203 * requires that at least 4 bit length codes be sent. (appnote.txt says 9204 * 3 but the actual value used is 4.) 9205 */ 9206 9207 for (max_blindex = BL_CODES$1 - 1; max_blindex >= 3; max_blindex--) { 9208 if (s.bl_tree[bl_order[max_blindex] * 2 + 1] 9209 /*.Len*/ 9210 !== 0) { 9211 break; 9212 } 9213 } 9214 /* Update opt_len to include the bit length tree and counts */ 9215 9216 9217 s.opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4; //Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", 9218 // s->opt_len, s->static_len)); 9219 9220 return max_blindex; 9221 }; 9222 /* =========================================================================== 9223 * Send the header for a block using dynamic Huffman trees: the counts, the 9224 * lengths of the bit length codes, the literal tree and the distance tree. 9225 * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. 9226 */ 9227 9228 9229 const send_all_trees = (s, lcodes, dcodes, blcodes) => // deflate_state *s; 9230 // int lcodes, dcodes, blcodes; /* number of codes for each tree */ 9231 { 9232 let rank; 9233 /* index in bl_order */ 9234 //Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); 9235 //Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, 9236 // "too many codes"); 9237 //Tracev((stderr, "\nbl counts: ")); 9238 9239 send_bits(s, lcodes - 257, 5); 9240 /* not +255 as stated in appnote.txt */ 9241 9242 send_bits(s, dcodes - 1, 5); 9243 send_bits(s, blcodes - 4, 4); 9244 /* not -3 as stated in appnote.txt */ 9245 9246 for (rank = 0; rank < blcodes; rank++) { 9247 //Tracev((stderr, "\nbl code %2d ", bl_order[rank])); 9248 send_bits(s, s.bl_tree[bl_order[rank] * 2 + 1] 9249 /*.Len*/ 9250 , 3); 9251 } //Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); 9252 9253 9254 send_tree(s, s.dyn_ltree, lcodes - 1); 9255 /* literal tree */ 9256 //Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); 9257 9258 send_tree(s, s.dyn_dtree, dcodes - 1); 9259 /* distance tree */ 9260 //Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); 9261 }; 9262 /* =========================================================================== 9263 * Check if the data type is TEXT or BINARY, using the following algorithm: 9264 * - TEXT if the two conditions below are satisfied: 9265 * a) There are no non-portable control characters belonging to the 9266 * "black list" (0..6, 14..25, 28..31). 9267 * b) There is at least one printable character belonging to the 9268 * "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255). 9269 * - BINARY otherwise. 9270 * - The following partially-portable control characters form a 9271 * "gray list" that is ignored in this detection algorithm: 9272 * (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}). 9273 * IN assertion: the fields Freq of dyn_ltree are set. 9274 */ 9275 9276 9277 const detect_data_type = s => { 9278 /* black_mask is the bit mask of black-listed bytes 9279 * set bits 0..6, 14..25, and 28..31 9280 * 0xf3ffc07f = binary 11110011111111111100000001111111 9281 */ 9282 let black_mask = 0xf3ffc07f; 9283 let n; 9284 /* Check for non-textual ("black-listed") bytes. */ 9285 9286 for (n = 0; n <= 31; n++, black_mask >>>= 1) { 9287 if (black_mask & 1 && s.dyn_ltree[n * 2] 9288 /*.Freq*/ 9289 !== 0) { 9290 return Z_BINARY; 9291 } 9292 } 9293 /* Check for textual ("white-listed") bytes. */ 9294 9295 9296 if (s.dyn_ltree[9 * 2] 9297 /*.Freq*/ 9298 !== 0 || s.dyn_ltree[10 * 2] 9299 /*.Freq*/ 9300 !== 0 || s.dyn_ltree[13 * 2] 9301 /*.Freq*/ 9302 !== 0) { 9303 return Z_TEXT; 9304 } 9305 9306 for (n = 32; n < LITERALS$1; n++) { 9307 if (s.dyn_ltree[n * 2] 9308 /*.Freq*/ 9309 !== 0) { 9310 return Z_TEXT; 9311 } 9312 } 9313 /* There are no "black-listed" or "white-listed" bytes: 9314 * this stream either is empty or has tolerated ("gray-listed") bytes only. 9315 */ 9316 9317 9318 return Z_BINARY; 9319 }; 9320 9321 let static_init_done = false; 9322 /* =========================================================================== 9323 * Initialize the tree data structures for a new zlib stream. 9324 */ 9325 9326 const _tr_init$1 = s => { 9327 if (!static_init_done) { 9328 tr_static_init(); 9329 static_init_done = true; 9330 } 9331 9332 s.l_desc = new TreeDesc(s.dyn_ltree, static_l_desc); 9333 s.d_desc = new TreeDesc(s.dyn_dtree, static_d_desc); 9334 s.bl_desc = new TreeDesc(s.bl_tree, static_bl_desc); 9335 s.bi_buf = 0; 9336 s.bi_valid = 0; 9337 /* Initialize the first block of the first file: */ 9338 9339 init_block(s); 9340 }; 9341 /* =========================================================================== 9342 * Send a stored block 9343 */ 9344 9345 9346 const _tr_stored_block$1 = (s, buf, stored_len, last) => //DeflateState *s; 9347 //charf *buf; /* input block */ 9348 //ulg stored_len; /* length of input block */ 9349 //int last; /* one if this is the last block for a file */ 9350 { 9351 send_bits(s, (STORED_BLOCK << 1) + (last ? 1 : 0), 3); 9352 /* send block type */ 9353 9354 copy_block(s, buf, stored_len, true); 9355 /* with header */ 9356 }; 9357 /* =========================================================================== 9358 * Send one empty static block to give enough lookahead for inflate. 9359 * This takes 10 bits, of which 7 may remain in the bit buffer. 9360 */ 9361 9362 9363 const _tr_align$1 = s => { 9364 send_bits(s, STATIC_TREES << 1, 3); 9365 send_code(s, END_BLOCK, static_ltree); 9366 bi_flush(s); 9367 }; 9368 /* =========================================================================== 9369 * Determine the best encoding for the current block: dynamic trees, static 9370 * trees or store, and output the encoded block to the zip file. 9371 */ 9372 9373 9374 const _tr_flush_block$1 = (s, buf, stored_len, last) => //DeflateState *s; 9375 //charf *buf; /* input block, or NULL if too old */ 9376 //ulg stored_len; /* length of input block */ 9377 //int last; /* one if this is the last block for a file */ 9378 { 9379 let opt_lenb, static_lenb; 9380 /* opt_len and static_len in bytes */ 9381 9382 let max_blindex = 0; 9383 /* index of last bit length code of non zero freq */ 9384 9385 /* Build the Huffman trees unless a stored block is forced */ 9386 9387 if (s.level > 0) { 9388 /* Check if the file is binary or text */ 9389 if (s.strm.data_type === Z_UNKNOWN$1) { 9390 s.strm.data_type = detect_data_type(s); 9391 } 9392 /* Construct the literal and distance trees */ 9393 9394 9395 build_tree(s, s.l_desc); // Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, 9396 // s->static_len)); 9397 9398 build_tree(s, s.d_desc); // Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, 9399 // s->static_len)); 9400 9401 /* At this point, opt_len and static_len are the total bit lengths of 9402 * the compressed block data, excluding the tree representations. 9403 */ 9404 9405 /* Build the bit length tree for the above two trees, and get the index 9406 * in bl_order of the last bit length code to send. 9407 */ 9408 9409 max_blindex = build_bl_tree(s); 9410 /* Determine the best encoding. Compute the block lengths in bytes. */ 9411 9412 opt_lenb = s.opt_len + 3 + 7 >>> 3; 9413 static_lenb = s.static_len + 3 + 7 >>> 3; // Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", 9414 // opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, 9415 // s->last_lit)); 9416 9417 if (static_lenb <= opt_lenb) { 9418 opt_lenb = static_lenb; 9419 } 9420 } else { 9421 // Assert(buf != (char*)0, "lost buf"); 9422 opt_lenb = static_lenb = stored_len + 5; 9423 /* force a stored block */ 9424 } 9425 9426 if (stored_len + 4 <= opt_lenb && buf !== -1) { 9427 /* 4: two words for the lengths */ 9428 9429 /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. 9430 * Otherwise we can't have processed more than WSIZE input bytes since 9431 * the last block flush, because compression would have been 9432 * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to 9433 * transform a block into a stored block. 9434 */ 9435 _tr_stored_block$1(s, buf, stored_len, last); 9436 } else if (s.strategy === Z_FIXED$1 || static_lenb === opt_lenb) { 9437 send_bits(s, (STATIC_TREES << 1) + (last ? 1 : 0), 3); 9438 compress_block(s, static_ltree, static_dtree); 9439 } else { 9440 send_bits(s, (DYN_TREES << 1) + (last ? 1 : 0), 3); 9441 send_all_trees(s, s.l_desc.max_code + 1, s.d_desc.max_code + 1, max_blindex + 1); 9442 compress_block(s, s.dyn_ltree, s.dyn_dtree); 9443 } // Assert (s->compressed_len == s->bits_sent, "bad compressed size"); 9444 9445 /* The above check is made mod 2^32, for files larger than 512 MB 9446 * and uLong implemented on 32 bits. 9447 */ 9448 9449 9450 init_block(s); 9451 9452 if (last) { 9453 bi_windup(s); 9454 } // Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, 9455 // s->compressed_len-7*last)); 9456 9457 }; 9458 /* =========================================================================== 9459 * Save the match info and tally the frequency counts. Return true if 9460 * the current block must be flushed. 9461 */ 9462 9463 9464 const _tr_tally$1 = (s, dist, lc) => // deflate_state *s; 9465 // unsigned dist; /* distance of matched string */ 9466 // unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ 9467 { 9468 //let out_length, in_length, dcode; 9469 s.pending_buf[s.d_buf + s.last_lit * 2] = dist >>
9469> 8 & 0xff; 9470 s.pending_buf[s.d_buf + s.last_lit * 2 + 1] = dist & 0xff; 9471 s.pending_buf[s.l_buf + s.last_lit] = lc & 0xff; 9472 s.last_lit++; 9473 9474 if (dist === 0) { 9475 /* lc is the unmatched char */ 9476 s.dyn_ltree[lc * 2] /*.Freq*/++; 9477 } else { 9478 s.matches++; 9479 /* Here, lc is the match length - MIN_MATCH */ 9480 9481 dist--; 9482 /* dist = match distance - 1 */ 9483 //Assert((ush)dist < (ush)MAX_DIST(s) && 9484 // (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && 9485 // (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); 9486 9487 s.dyn_ltree[(_length_code[lc] + LITERALS$1 + 1) * 2] /*.Freq*/++; 9488 s.dyn_dtree[d_code(dist) * 2] /*.Freq*/++; 9489 } // (!) This block is disabled in zlib defaults, 9490 // don't enable it for binary compatibility 9491 //#ifdef TRUNCATE_BLOCK 9492 // /* Try to guess if it is profitable to stop the current block here */ 9493 // if ((s.last_lit & 0x1fff) === 0 && s.level > 2) { 9494 // /* Compute an upper bound for the compressed length */ 9495 // out_length = s.last_lit*8; 9496 // in_length = s.strstart - s.block_start; 9497 // 9498 // for (dcode = 0; dcode < D_CODES; dcode++) { 9499 // out_length += s.dyn_dtree[dcode*2]/*.Freq*/ * (5 + extra_dbits[dcode]); 9500 // } 9501 // out_length >>>= 3; 9502 // //Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", 9503 // // s->last_lit, in_length, out_length, 9504 // // 100L - out_length*100L/in_length)); 9505 // if (s.matches < (s.last_lit>>1)/*int /2*/ && out_length < (in_length>>1)/*int /2*/) { 9506 // return true; 9507 // } 9508 // } 9509 //#endif 9510 9511 9512 return s.last_lit === s.lit_bufsize - 1; 9513 /* We avoid equality with lit_bufsize because of wraparound at 64K 9514 * on 16 bit machines and because stored blocks are restricted to 9515 * 64K-1 bytes. 9516 */ 9517 }; 9518 9519 var _tr_init_1 = _tr_init$1; 9520 var _tr_stored_block_1 = _tr_stored_block$1; 9521 var _tr_flush_block_1 = _tr_flush_block$1; 9522 var _tr_tally_1 = _tr_tally$1; 9523 var _tr_align_1 = _tr_align$1; 9524 var trees = { 9525 _tr_init: _tr_init_1, 9526 _tr_stored_block: _tr_stored_block_1, 9527 _tr_flush_block: _tr_flush_block_1, 9528 _tr_tally: _tr_tally_1, 9529 _tr_align: _tr_align_1 9530 }; // Note: adler32 takes 12% for level 0 and 2% for level 6. 9531 // It isn't worth it to make additional optimizations as in original. 9532 // Small size is preferable. 9533 // (C) 1995-2013 Jean-loup Gailly and Mark Adler 9534 // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin 9535 // 9536 // This software is provided 'as-is', without any express or implied 9537 // warranty. In no event will the authors be held liable for any damages 9538 // arising from the use of this software. 9539 // 9540 // Permission is granted to anyone to use this software for any purpose, 9541 // including commercial applications, and to alter it and redistribute it 9542 // freely, subject to the following restrictions: 9543 // 9544 // 1. The origin of this software must not be misrepresented; you must not 9545 // claim that you wrote the original software. If you use this software 9546 // in a product, an acknowledgment in the product documentation would be 9547 // appreciated but is not required. 9548 // 2. Altered source versions must be plainly marked as such, and must not be 9549 // misrepresented as being the original software. 9550 // 3. This notice may not be removed or altered from any source distribution. 9551 9552 const adler32 = (adler, buf, len, pos) => { 9553 let s1 = adler & 0xffff | 0, 9554 s2 = adler >>> 16 & 0xffff | 0, 9555 n = 0; 9556 9557 while (len !== 0) { 9558 // Set limit ~ twice less than 5552, to keep 9559 // s2 in 31-bits, because we force signed ints. 9560 // in other case %= will fail. 9561 n = len > 2000 ? 2000 : len; 9562 len -= n; 9563 9564 do { 9565 s1 = s1 + buf[pos++] | 0; 9566 s2 = s2 + s1 | 0; 9567 } while (--n); 9568 9569 s1 %= 65521; 9570 s2 %= 65521; 9571 } 9572 9573 return s1 | s2 << 16 | 0; 9574 }; 9575 9576 var adler32_1 = adler32; // Note: we can't get significant speed boost here. 9577 // So write code to minimize size - no pregenerated tables
vendor: 20,537 bytes, lines 9578-10171
9578 // and array tools dependencies. 9579 // (C) 1995-2013 Jean-loup Gailly and Mark Adler 9580 // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin 9581 // 9582 // This software is provided 'as-is', without any express or implied 9583 // warranty. In no event will the authors be held liable for any damages 9584 // arising from the use of this software. 9585 // 9586 // Permission is granted to anyone to use this software for any purpose, 9587 // including commercial applications, and to alter it and redistribute it 9588 // freely, subject to the following restrictions: 9589 // 9590 // 1. The origin of this software must not be misrepresented; you must not 9591 // claim that you wrote the original software. If you use this software 9592 // in a product, an acknowledgment in the product documentation would be 9593 // appreciated but is not required. 9594 // 2. Altered source versions must be plainly marked as such, and must not be 9595 // misrepresented as being the original software. 9596 // 3. This notice may not be removed or altered from any source distribution. 9597 // Use ordinary array, since untyped makes no boost here 9598 9599 const makeTable = () => { 9600 let c, 9601 table = []; 9602 9603 for (var n = 0; n < 256; n++) { 9604 c = n; 9605 9606 for (var k = 0; k < 8; k++) { 9607 c = c & 1 ? 0xEDB88320 ^ c >>> 1 : c >>> 1; 9608 } 9609 9610 table[n] = c; 9611 } 9612 9613 return table; 9614 }; // Create table on load. Just 255 signed longs. Not a problem. 9615 9616 9617 const crcTable = new Uint32Array(makeTable()); 9618 9619 const crc32 = (crc, buf, len, pos) => { 9620 const t = crcTable; 9621 const end = pos + len; 9622 crc ^= -1; 9623 9624 for (let i = pos; i < end; i++) { 9625 crc = crc >>> 8 ^ t[(crc ^ buf[i]) & 0xFF]; 9626 } 9627 9628 return crc ^ -1; // >>> 0; 9629 }; 9630 9631 var crc32_1 = crc32; // (C) 1995-2013 Jean-loup Gailly and Mark Adler 9632 // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin 9633 // 9634 // This software is provided 'as-is', without any express or implied 9635 // warranty. In no event will the authors be held liable for any damages 9636 // arising from the use of this software. 9637 // 9638 // Permission is granted to anyone to use this software for any purpose, 9639 // including commercial applications, and to alter it and redistribute it 9640 // freely, subject to the following restrictions: 9641 // 9642 // 1. The origin of this software must not be misrepresented; you must not 9643 // claim that you wrote the original software. If you use this software 9644 // in a product, an acknowledgment in the product documentation would be 9645 // appreciated but is not required. 9646 // 2. Altered source versions must be plainly marked as such, and must not be 9647 // misrepresented as being the original software. 9648 // 3. This notice may not be removed or altered from any source distribution. 9649 9650 var messages = { 9651 2: 'need dictionary', 9652 9653 /* Z_NEED_DICT 2 */ 9654 1: 'stream end', 9655 9656 /* Z_STREAM_END 1 */ 9657 0: '', 9658 9659 /* Z_OK 0 */ 9660 '-1': 'file error', 9661 9662 /* Z_ERRNO (-1) */ 9663 '-2': 'stream error', 9664 9665 /* Z_STREAM_ERROR (-2) */ 9666 '-3': 'data error', 9667 9668 /* Z_DATA_ERROR (-3) */ 9669 '-4': 'insufficient memory', 9670 9671 /* Z_MEM_ERROR (-4) */ 9672 '-5': 'buffer error', 9673 9674 /* Z_BUF_ERROR (-5) */ 9675 '-6': 'incompatible version' 9676 /* Z_VERSION_ERROR (-6) */ 9677 9678 }; // (C) 1995-2013 Jean-loup Gailly and Mark Adler 9679 // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin 9680 // 9681 // This software is provided 'as-is', without any express or implied 9682 // warranty. In no event will the authors be held liable for any damages 9683 // arising from the use of this software. 9684 // 9685 // Permission is granted to anyone to use this software for any purpose, 9686 // including commercial applications, and to alter it and redistribute it 9687 // freely, subject to the following restrictions: 9688 // 9689 // 1. The origin of this software must not be misrepresented; you must not 9690 // claim that you wrote the original software. If you use this software 9691 // in a product, an acknowledgment in the product documentation would be 9692 // appreciated but is not required. 9693 // 2. Altered source versions must be plainly marked as such, and must not be 9694 // misrepresented as being the original software. 9695 // 3. This notice may not be removed or altered from any source distribution. 9696 9697 var constants$2 = { 9698 /* Allowed flush values; see deflate() and inflate() below for details */ 9699 Z_NO_FLUSH: 0, 9700 Z_PARTIAL_FLUSH: 1, 9701 Z_SYNC_FLUSH: 2, 9702 Z_FULL_FLUSH: 3, 9703 Z_FINISH: 4, 9704 Z_BLOCK: 5, 9705 Z_TREES: 6, 9706 9707 /* Return codes for the compression/decompression functions. Negative values 9708 * are errors, positive values are used for special but normal events. 9709 */ 9710 Z_OK: 0, 9711 Z_STREAM_END: 1, 9712 Z_NEED_DICT: 2, 9713 Z_ERRNO: -1, 9714 Z_STREAM_ERROR: -2, 9715 Z_DATA_ERROR: -3, 9716 Z_MEM_ERROR: -4, 9717 Z_BUF_ERROR: -5, 9718 //Z_VERSION_ERROR: -6, 9719 9720 /* compression levels */ 9721 Z_NO_COMPRESSION: 0, 9722 Z_BEST_SPEED: 1, 9723 Z_BEST_COMPRESSION: 9, 9724 Z_DEFAULT_COMPRESSION: -1, 9725 Z_FILTERED: 1, 9726 Z_HUFFMAN_ONLY: 2, 9727 Z_RLE: 3, 9728 Z_FIXED: 4, 9729 Z_DEFAULT_STRATEGY: 0, 9730 9731 /* Possible values of the data_type field (though see inflate()) */ 9732 Z_BINARY: 0, 9733 Z_TEXT: 1, 9734 //Z_ASCII: 1, // = Z_TEXT (deprecated) 9735 Z_UNKNOWN: 2, 9736 9737 /* The deflate compression method */ 9738 Z_DEFLATED: 8 //Z_NULL: null // Use -1 or null inline, depending on var type 9739 9740 }; // (C) 1995-2013 Jean-loup Gailly and Mark Adler 9741 // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin 9742 // 9743 // This software is provided 'as-is', without any express or implied 9744 // warranty. In no event will the authors be held liable for any damages 9745 // arising from the use of this software. 9746 // 9747 // Permission is granted to anyone to use this software for any purpose, 9748 // including commercial applications, and to alter it and redistribute it 9749 // freely, subject to the following restrictions: 9750 // 9751 // 1. The origin of this software must not be misrepresented; you must not 9752 // claim that you wrote the original software. If you use this software 9753 // in a product, an acknowledgment in the product documentation would be 9754 // appreciated but is not required. 9755 // 2. Altered source versions must be plainly marked as such, and must not be 9756 // misrepresented as being the original software. 9757 // 3. This notice may not be removed or altered from any source distribution. 9758 9759 const { 9760 _tr_init, 9761 _tr_stored_block, 9762 _tr_flush_block, 9763 _tr_tally, 9764 _tr_align 9765 } = trees; 9766 /* Public constants ==========================================================*/ 9767 9768 /* ===========================================================================*/ 9769 9770 const { 9771 Z_NO_FLUSH: Z_NO_FLUSH$2, 9772 Z_PARTIAL_FLUSH, 9773 Z_FULL_FLUSH: Z_FULL_FLUSH$1, 9774 Z_FINISH: Z_FINISH$3, 9775 Z_BLOCK: Z_BLOCK$1, 9776 Z_OK: Z_OK$3, 9777 Z_STREAM_END: Z_STREAM_END$3, 9778 Z_STREAM_ERROR: Z_STREAM_ERROR$2, 9779 Z_DATA_ERROR: Z_DATA_ERROR$2, 9780 Z_BUF_ERROR: Z_BUF_ERROR$1, 9781 Z_DEFAULT_COMPRESSION: Z_DEFAULT_COMPRESSION$1, 9782 Z_FILTERED, 9783 Z_HUFFMAN_ONLY, 9784 Z_RLE, 9785 Z_FIXED, 9786 Z_DEFAULT_STRATEGY: Z_DEFAULT_STRATEGY$1, 9787 Z_UNKNOWN, 9788 Z_DEFLATED: Z_DEFLATED$2 9789 } = constants$2; 9790 /*============================================================================*/ 9791 9792 const MAX_MEM_LEVEL = 9; 9793 /* Maximum value for memLevel in deflateInit2 */ 9794 9795 const MAX_WBITS$1 = 15; 9796 /* 32K LZ77 window */ 9797 9798 const DEF_MEM_LEVEL = 8; 9799 const LENGTH_CODES = 29; 9800 /* number of length codes, not counting the special END_BLOCK code */ 9801 9802 const LITERALS = 256; 9803 /* number of literal bytes 0..255 */ 9804 9805 const L_CODES = LITERALS + 1 + LENGTH_CODES; 9806 /* number of Literal or Length codes, including the END_BLOCK code */ 9807 9808 const D_CODES = 30; 9809 /* number of distance codes */ 9810 9811 const BL_CODES = 19; 9812 /* number of codes used to transfer the bit lengths */ 9813 9814 const HEAP_SIZE = 2 * L_CODES + 1; 9815 /* maximum heap size */ 9816 9817 const MAX_BITS = 15; 9818 /* All codes must not exceed MAX_BITS bits */ 9819 9820 const MIN_MATCH = 3; 9821 const MAX_MATCH = 258; 9822 const MIN_LOOKAHEAD = MAX_MATCH + MIN_MATCH + 1; 9823 const PRESET_DICT = 0x20; 9824 const INIT_STATE = 42; 9825 const EXTRA_STATE = 69; 9826 const NAME_STATE = 73; 9827 const COMMENT_STATE = 91; 9828 const HCRC_STATE = 103; 9829 const BUSY_STATE = 113; 9830 const FINISH_STATE = 666; 9831 const BS_NEED_MORE = 1; 9832 /* block not completed, need more input or more output */ 9833 9834 const BS_BLOCK_DONE = 2; 9835 /* block flush performed */ 9836 9837 const BS_FINISH_STARTED = 3; 9838 /* finish started, need only more output at next deflate */ 9839 9840 const BS_FINISH_DONE = 4; 9841 /* finish done, accept no more input or output */ 9842 9843 const OS_CODE = 0x03; // Unix :) . Don't detect, use this default. 9844 9845 const err = (strm, errorCode) => { 9846 strm.msg = messages[errorCode]; 9847 return errorCode; 9848 }; 9849 9850 const rank = f => { 9851 return (f << 1) - (f > 4 ? 9 : 0); 9852 }; 9853 9854 const zero = buf => { 9855 let len = buf.length; 9856 9857 while (--len >= 0) { 9858 buf[len] = 0; 9859 } 9860 }; 9861 /* eslint-disable new-cap */ 9862 9863 9864 let HASH_ZLIB = (s, prev, data) => (prev << s.hash_shift ^ data) & s.hash_mask; // This hash causes less collisions, https://github.com/nodeca/pako/issues/135 9865 // But breaks binary compatibility 9866 //let HASH_FAST = (s, prev, data) => ((prev << 8) + (prev >> 8) + (data << 4)) & s.hash_mask; 9867 9868 9869 let HASH = HASH_ZLIB; 9870 /* ========================================================================= 9871 * Flush as much pending output as possible. All deflate() output goes 9872 * through this function so some applications may wish to modify it 9873 * to avoid allocating a large strm->output buffer and copying into it. 9874 * (See also read_buf()). 9875 */ 9876 9877 const flush_pending = strm => { 9878 const s = strm.state; //_tr_flush_bits(s); 9879 9880 let len = s.pending; 9881 9882 if (len > strm.avail_out) { 9883 len = strm.avail_out; 9884 } 9885 9886 if (len === 0) { 9887 return; 9888 } 9889 9890 strm.output.set(s.pending_buf.subarray(s.pending_out, s.pending_out + len), strm.next_out); 9891 strm.next_out += len; 9892 s.pending_out += len; 9893 strm.total_out += len; 9894 strm.avail_out -= len; 9895 s.pending -= len; 9896 9897 if (s.pending === 0) { 9898 s.pending_out = 0; 9899 } 9900 }; 9901 9902 const flush_block_only = (s, last) => { 9903 _tr_flush_block(s, s.block_start >= 0 ? s.block_start : -1, s.strstart - s.block_start, last); 9904 9905 s.block_start = s.strstart; 9906 flush_pending(s.strm); 9907 }; 9908 9909 const put_byte = (s, b) => { 9910 s.pending_buf[s.pending++] = b; 9911 }; 9912 /* ========================================================================= 9913 * Put a short in the pending buffer. The 16-bit value is put in MSB order. 9914 * IN assertion: the stream state is correct and there is enough room in 9915 * pending_buf. 9916 */ 9917 9918 9919 const putShortMSB = (s, b) => { 9920 // put_byte(s, (Byte)(b >> 8)); 9921 // put_byte(s, (Byte)(b & 0xff)); 9922 s.pending_buf[s.pending++] = b >>> 8 & 0xff; 9923 s.pending_buf[s.pending++] = b & 0xff; 9924 }; 9925 /* =========================================================================== 9926 * Read a new buffer from the current input stream, update the adler32 9927 * and total number of bytes read. All deflate() input goes through 9928 * this function so some applications may wish to modify it to avoid 9929 * allocating a large strm->input buffer and copying from it. 9930 * (See also flush_pending()). 9931 */ 9932 9933 9934 const read_buf = (strm, buf, start, size) => { 9935 let len = strm.avail_in; 9936 9937 if (len > size) { 9938 len = size; 9939 } 9940 9941 if (len === 0) { 9942 return 0; 9943 } 9944 9945 strm.avail_in -= len; // zmemcpy(buf, strm->next_in, len); 9946 9947 buf.set(strm.input.subarray(strm.next_in, strm.next_in + len), start); 9948 9949 if (strm.state.wrap === 1) { 9950 strm.adler = adler32_1(strm.adler, buf, len, start); 9951 } else if (strm.state.wrap === 2) { 9952 strm.adler = crc32_1(strm.adler, buf, len, start); 9953 } 9954 9955 strm.next_in += len; 9956 strm.total_in += len; 9957 return len; 9958 }; 9959 /* =========================================================================== 9960 * Set match_start to the longest match starting at the given string and 9961 * return its length. Matches shorter or equal to prev_length are discarded, 9962 * in which case the result is equal to prev_length and match_start is 9963 * garbage. 9964 * IN assertions: cur_match is the head of the hash chain for the current 9965 * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 9966 * OUT assertion: the match length is not greater than s->lookahead. 9967 */ 9968 9969 9970 const longest_match = (s, cur_match) => { 9971 let chain_length = s.max_chain_length; 9972 /* max hash chain length */ 9973 9974 let scan = s.strstart; 9975 /* current string */ 9976 9977 let match; 9978 /* matched string */ 9979 9980 let len; 9981 /* length of current match */ 9982 9983 let best_len = s.prev_length; 9984 /* best match length so far */ 9985 9986 let nice_match = s.nice_match; 9987 /* stop if match long enough */ 9988 9989 const limit = s.strstart > s.w_size - MIN_LOOKAHEAD ? s.strstart - (s.w_size - MIN_LOOKAHEAD) : 0 9990 /*NIL*/ 9991 ; 9992 const _win = s.window; // shortcut 9993 9994 const wmask = s.w_mask; 9995 const prev = s.prev; 9996 /* Stop when cur_match becomes <= limit. To simplify the code, 9997 * we prevent matches with the string of window index 0. 9998 */ 9999 10000 const strend = s.strstart + MAX_MATCH; 10001 let scan_end1 = _win[scan + best_len - 1]; 10002 let scan_end = _win[scan + best_len]; 10003 /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. 10004 * It is easy to get rid of this optimization if necessary. 10005 */ 10006 // Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); 10007 10008 /* Do not waste too much time if we already have a good match: */ 10009 10010 if (s.prev_length >= s.good_match) { 10011 chain_length >>= 2; 10012 } 10013 /* Do not look for matches beyond the end of the input. This is necessary 10014 * to make deflate deterministic. 10015 */ 10016 10017 10018 if (nice_match > s.lookahead) { 10019 nice_match = s.lookahead; 10020 } // Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); 10021 10022 10023 do { 10024 // Assert(cur_match < s->strstart, "no future"); 10025 match = cur_match; 10026 /* Skip to next match if the match length cannot increase 10027 * or if the match length is less than 2. Note that the checks below 10028 * for insufficient lookahead only occur occasionally for performance 10029 * reasons. Therefore uninitialized memory will be accessed, and 10030 * conditional jumps will be made that depend on those values. 10031 * However the length of the match is limited to the lookahead, so 10032 * the output of deflate is not affected by the uninitialized values. 10033 */ 10034 10035 if (_win[match + best_len] !== scan_end || _win[match + best_len - 1] !== scan_end1 || _win[match] !== _win[scan] || _win[++match] !== _win[scan + 1]) { 10036 continue; 10037 } 10038 /* The check at best_len-1 can be removed because it will be made 10039 * again later. (This heuristic is not always a win.) 10040 * It is not necessary to compare scan[2] and match[2] since they 10041 * are always equal when the other bytes match, given that 10042 * the hash keys are equal and that HASH_BITS >= 8. 10043 */ 10044 10045 10046 scan += 2; 10047 match++; // Assert(*scan == *match, "match[2]?"); 10048 10049 /* We check for insufficient lookahead only every 8th comparison; 10050 * the 256th check will be made at strstart+258. 10051 */ 10052 10053 do { 10054 /*jshint noempty:false*/ 10055 } while (_win[++scan] === _win[++match] && _win[++scan] === _win[++match] && _win[++scan] === _win[++match] && _win[++scan] === _win[++match] && _win[++scan] === _win[++match] && _win[++scan] === _win[++match] && _win[++scan] === _win[++match] && _win[++scan] === _win[++match] && scan < strend); // Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); 10056 10057 10058 len = MAX_MATCH - (strend - scan); 10059 scan = strend - MAX_MATCH; 10060 10061 if (len > best_len) { 10062 s.match_start = cur_match; 10063 best_len = len; 10064 10065 if (len >= nice_match) { 10066 break; 10067 } 10068 10069 scan_end1 = _win[scan + best_len - 1]; 10070 scan_end = _win[scan + best_len]; 10071 } 10072 } while ((cur_match = prev[cur_match & wmask]) > limit && --chain_length !== 0); 10073 10074 if (best_len <= s.lookahead) { 10075 return best_len; 10076 } 10077 10078 return s.lookahead; 10079 }; 10080 /* =========================================================================== 10081 * Fill the window when the lookahead becomes insufficient. 10082 * Updates strstart and lookahead. 10083 * 10084 * IN assertion: lookahead < MIN_LOOKAHEAD 10085 * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD 10086 * At least one byte has been read, or avail_in == 0; reads are 10087 * performed for at least two bytes (required for the zip translate_eol 10088 * option -- not supported here). 10089 */ 10090 10091 10092 const fill_window = s => { 10093 const _w_size = s.w_size; 10094 let p, n, m, more, str; //Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead"); 10095 10096 do { 10097 more = s.window_size - s.lookahead - s.strstart; // JS ints have 32 bit, block below not needed 10098 10099 /* Deal with !@#$% 64K limit: */ 10100 //if (sizeof(int) <= 2) { 10101 // if (more == 0 && s->strstart == 0 && s->lookahead == 0) { 10102 // more = wsize; 10103 // 10104 // } else if (more == (unsigned)(-1)) { 10105 // /* Very unlikely, but possible on 16 bit machine if 10106 // * strstart == 0 && lookahead == 1 (input done a byte at time) 10107 // */ 10108 // more--; 10109 // } 10110 //} 10111 10112 /* If the window is almost full and there is insufficient lookahead, 10113 * move the upper half to the lower one to make room in the upper half. 10114 */ 10115 10116 if (s.strstart >= _w_size + (_w_size - MIN_LOOKAHEAD)) { 10117 s.window.set(s.window.subarray(_w_size, _w_size + _w_size), 0); 10118 s.match_start -= _w_size; 10119 s.strstart -= _w_size; 10120 /* we now have strstart >= MAX_DIST */ 10121 10122 s.block_start -= _w_size; 10123 /* Slide the hash table (could be avoided with 32 bit values 10124 at the expense of memory usage). We slide even when level == 0 10125 to keep the hash table consistent if we switch back to level > 0 10126 later. (Using level 0 permanently is not an optimal usage of 10127 zlib, so we don't care about this pathological case.) 10128 */ 10129 10130 n = s.hash_size; 10131 p = n; 10132 10133 do { 10134 m = s.head[--p]; 10135 s.head[p] = m >= _w_size ? m - _w_size : 0; 10136 } while (--n); 10137 10138 n = _w_size; 10139 p = n; 10140 10141 do { 10142 m = s.prev[--p]; 10143 s.prev[p] = m >= _w_size ? m - _w_size : 0; 10144 /* If n is not on any hash chain, prev[n] is garbage but 10145 * its value will never be used. 10146 */ 10147 } while (--n); 10148 10149 more += _w_size; 10150 } 10151 10152 if (s.strm.avail_in === 0) { 10153 break; 10154 } 10155 /* If there was no sliding: 10156 * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && 10157 * more == window_size - lookahead - strstart 10158 * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) 10159 * => more >= window_size - 2*WSIZE + 2 10160 * In the BIG_MEM or MMAP case (not yet supported), 10161 * window_size == input_size + MIN_LOOKAHEAD && 10162 * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. 10163 * Otherwise, window_size == 2*WSIZE so more >= 2. 10164 * If there was sliding, more >= WSIZE. So in all cases, more >= 2. 10165 */ 10166 //Assert(more >= 2, "more < 2"); 10167 10168 10169 n = read_buf(s.strm, s.window, s.strstart + s.lookahead, more); 10170 s.lookahead += n; 10171 /* Initialize the hash value now that we have some input
10171: */ 10172 10173 if (s.lookahead + s.insert >= MIN_MATCH) { 10174 str = s.strstart - s.insert; 10175 s.ins_h = s.window[str]; 10176 /* UPDATE_HASH(s, s->ins_h, s->window[str + 1]); */ 10177 10178 s.ins_h = HASH(s, s.ins_h, s.window[str + 1]); //#if MIN_MATCH != 3 10179 // Call update_hash() MIN_MATCH-3 more times 10180 //#endif 10181 10182 while (s.insert) { 10183 /* UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); */ 10184 s.ins_h = HASH(s, s.ins_h, s.window[str + MIN_MATCH - 1]); 10185 s.prev[str & s.w_mask] = s.head[s.ins_h]; 10186 s.head[s.ins_h] = str; 10187 str++; 10188 s.insert--; 10189 10190 if (s.lookahead + s.insert < MIN_MATCH) { 10191 break; 10192 } 10193 } 10194 } 10195 /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, 10196 * but this is not important since only literal bytes will be emitted. 10197 */ 10198 10199 } while (s.lookahead < MIN_LOOKAHEAD && s.strm.avail_in !== 0); 10200 /* If the WIN_INIT bytes after the end of the current data have never been 10201 * written, then zero those bytes in order to avoid memory check reports of 10202 * the use of uninitialized (or uninitialised as Julian writes) bytes by 10203 * the longest match routines. Update the high water mark for the next 10204 * time through here. WIN_INIT is set to MAX_MATCH since the longest match 10205 * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead. 10206 */ 10207 // if (s.high_water < s.window_size) { 10208 // const curr = s.strstart + s.lookahead; 10209 // let init = 0; 10210 // 10211 // if (s.high_water < curr) { 10212 // /* Previous high water mark below current data -- zero WIN_INIT 10213 // * bytes or up to end of window, whichever is less. 10214 // */ 10215 // init = s.window_size - curr; 10216 // if (init > WIN_INIT) 10217 // init = WIN_INIT; 10218 // zmemzero(s->window + curr, (unsigned)init); 10219 // s->high_water = curr + init; 10220 // } 10221 // else if (s->high_water < (ulg)curr + WIN_INIT) { 10222 // /* High water mark at or above current data, but below current data 10223 // * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up 10224 // * to end of window, whichever is less. 10225 // */ 10226 // init = (ulg)curr + WIN_INIT - s->high_water; 10227 // if (init > s->window_size - s->high_water) 10228 // init = s->window_size - s->high_water; 10229 // zmemzero(s->window + s->high_water, (unsigned)init); 10230 // s->high_water += init; 10231 // } 10232 // } 10233 // 10234 // Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD, 10235 // "not enough room for search"); 10236 10237 }; 10238 /* =========================================================================== 10239 * Copy without compression as much as possible from the input stream, return 10240 * the current block state. 10241 * This function does not insert new strings in the dictionary since 10242 * uncompressible data is probably not useful. This function is used 10243 * only for the level=0 compression option. 10244 * NOTE: this function should be optimized to avoid extra copying from 10245 * window to pending_buf. 10246 */ 10247 10248 10249 const deflate_stored = (s, flush) => { 10250 /* Stored blocks are limited to 0xffff bytes, pending_buf is limited 10251 * to pending_buf_size, and each stored block has a 5 byte header: 10252 */ 10253 let max_block_size = 0xffff; 10254 10255 if (max_block_size > s.pending_buf_size - 5) { 10256 max_block_size = s.pending_buf_size - 5; 10257 } 10258 /* Copy as much as possible from input to output: */ 10259 10260 10261 for (;;) { 10262 /* Fill the window as much as possible: */ 10263 if (s.lookahead <= 1) { 10264 //Assert(s->strstart < s->w_size+MAX_DIST(s) || 10265 // s->block_start >= (long)s->w_size, "slide too late"); 10266 // if (!(s.strstart < s.w_size + (s.w_size - MIN_LOOKAHEAD) || 10267 // s.block_start >= s.w_size)) { 10268 // throw new Error("slide too late"); 10269 // } 10270 fill_window(s); 10271 10272 if (s.lookahead === 0 && flush === Z_NO_FLUSH$2) { 10273 return BS_NEED_MORE; 10274 } 10275 10276 if (s.lookahead === 0) { 10277 break; 10278 } 10279 /* flush the current block */ 10280 10281 } //Assert(s->block_start >= 0L, "block gone"); 10282 // if (s.block_start < 0) throw new Error("block gone"); 10283 10284 10285 s.strstart += s.lookahead; 10286 s.lookahead = 0; 10287 /* Emit a stored block if pending_buf will be full: */ 10288 10289 const max_start = s.block_start + max_block_size; 10290 10291 if (s.strstart === 0 || s.strstart >= max_start) { 10292 /* strstart == 0 is possible when wraparound on 16-bit machine */ 10293 s.lookahead = s.strstart - max_start; 10294 s.strstart = max_start; 10295 /*** FLUSH_BLOCK(s, 0); ***/ 10296 10297 flush_block_only(s, false); 10298 10299 if (s.strm.avail_out === 0) { 10300 return BS_NEED_MORE; 10301 } 10302 /***/ 10303 10304 } 10305 /* Flush if we may have to slide, otherwise block_start may become 10306 * negative and the data will be gone: 10307 */ 10308 10309 10310 if (s.strstart - s.block_start >= s.w_size - MIN_LOOKAHEAD) { 10311 /*** FLUSH_BLOCK(s, 0); ***/ 10312 flush_block_only(s, false); 10313 10314 if (s.strm.avail_out === 0) { 10315 return BS_NEED_MORE; 10316 } 10317 /***/ 10318 10319 } 10320 } 10321 10322 s.insert = 0; 10323 10324 if (flush === Z_FINISH$3) { 10325 /*** FLUSH_BLOCK(s, 1); ***/ 10326 flush_block_only(s, true); 10327 10328 if (s.strm.avail_out === 0) { 10329 return BS_FINISH_STARTED; 10330 } 10331 /***/ 10332 10333 10334 return BS_FINISH_DONE; 10335 } 10336 10337 if (s.strstart > s.block_start) { 10338 /*** FLUSH_BLOCK(s, 0); ***/ 10339 flush_block_only(s, false); 10340 10341 if (s.strm.avail_out === 0) { 10342 return BS_NEED_MORE; 10343 } 10344 /***/ 10345 10346 } 10347 10348 return BS_NEED_MORE; 10349 }; 10350 /* =========================================================================== 10351 * Compress as much as possible from the input stream, return the current 10352 * block state. 10353 * This function does not perform lazy evaluation of matches and inserts 10354 * new strings in the dictionary only for unmatched strings or for short
vendor: 16,384 bytes, lines 10355-10906
10355 * matches. It is used only for the fast compression options. 10356 */ 10357 10358 10359 const deflate_fast = (s, flush) => { 10360 let hash_head; 10361 /* head of the hash chain */ 10362 10363 let bflush; 10364 /* set if current block must be flushed */ 10365 10366 for (;;) { 10367 /* Make sure that we always have enough lookahead, except 10368 * at the end of the input file. We need MAX_MATCH bytes 10369 * for the next match, plus MIN_MATCH bytes to insert the 10370 * string following the next match. 10371 */ 10372 if (s.lookahead < MIN_LOOKAHEAD) { 10373 fill_window(s); 10374 10375 if (s.lookahead < MIN_LOOKAHEAD && flush === Z_NO_FLUSH$2) { 10376 return BS_NEED_MORE; 10377 } 10378 10379 if (s.lookahead === 0) { 10380 break; 10381 /* flush the current block */ 10382 } 10383 } 10384 /* Insert the string window[strstart .. strstart+2] in the 10385 * dictionary, and set hash_head to the head of the hash chain: 10386 */ 10387 10388 10389 hash_head = 0 10390 /*NIL*/ 10391 ; 10392 10393 if (s.lookahead >= MIN_MATCH) { 10394 /*** INSERT_STRING(s, s.strstart, hash_head); ***/ 10395 s.ins_h = HASH(s, s.ins_h, s.window[s.strstart + MIN_MATCH - 1]); 10396 hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; 10397 s.head[s.ins_h] = s.strstart; 10398 /***/ 10399 } 10400 /* Find the longest match, discarding those <= prev_length. 10401 * At this point we have always match_length < MIN_MATCH 10402 */ 10403 10404 10405 if (hash_head !== 0 10406 /*NIL*/ 10407 && s.strstart - hash_head <= s.w_size - MIN_LOOKAHEAD) { 10408 /* To simplify the code, we prevent matches with the string 10409 * of window index 0 (in particular we have to avoid a match 10410 * of the string with itself at the start of the input file). 10411 */ 10412 s.match_length = longest_match(s, hash_head); 10413 /* longest_match() sets match_start */ 10414 } 10415 10416 if (s.match_length >= MIN_MATCH) { 10417 // check_match(s, s.strstart, s.match_start, s.match_length); // for debug only 10418 10419 /*** _tr_tally_dist(s, s.strstart - s.match_start, 10420 s.match_length - MIN_MATCH, bflush); ***/ 10421 bflush = _tr_tally(s, s.strstart - s.match_start, s.match_length - MIN_MATCH); 10422 s.lookahead -= s.match_length; 10423 /* Insert new strings in the hash table only if the match length 10424 * is not too large. This saves time but degrades compression. 10425 */ 10426 10427 if (s.match_length <= s.max_lazy_match 10428 /*max_insert_length*/ 10429 && s.lookahead >= MIN_MATCH) { 10430 s.match_length--; 10431 /* string at strstart already in table */ 10432 10433 do { 10434 s.strstart++; 10435 /*** INSERT_STRING(s, s.strstart, hash_head); ***/ 10436 10437 s.ins_h = HASH(s, s.ins_h, s.window[s.strstart + MIN_MATCH - 1]); 10438 hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; 10439 s.head[s.ins_h] = s.strstart; 10440 /***/ 10441 10442 /* strstart never exceeds WSIZE-MAX_MATCH, so there are 10443 * always MIN_MATCH bytes ahead. 10444 */ 10445 } while (--s.match_length !== 0); 10446 10447 s.strstart++; 10448 } else { 10449 s.strstart += s.match_length; 10450 s.match_length = 0; 10451 s.ins_h = s.window[s.strstart]; 10452 /* UPDATE_HASH(s, s.ins_h, s.window[s.strstart+1]); */ 10453 10454 s.ins_h = HASH(s, s.ins_h, s.window[s.strstart + 1]); //#if MIN_MATCH != 3 10455 // Call UPDATE_HASH() MIN_MATCH-3 more times 10456 //#endif 10457 10458 /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not 10459 * matter since it will be recomputed at next deflate call. 10460 */ 10461 } 10462 } else { 10463 /* No match, output a literal byte */ 10464 //Tracevv((stderr,"%c", s.window[s.strstart])); 10465 10466 /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/ 10467 bflush = _tr_tally(s, 0, s.window[s.strstart]); 10468 s.lookahead--; 10469 s.strstart++; 10470 } 10471 10472 if (bflush) { 10473 /*** FLUSH_BLOCK(s, 0); ***/ 10474 flush_block_only(s, false); 10475 10476 if (s.strm.avail_out === 0) { 10477 return BS_NEED_MORE; 10478 } 10479 /***/ 10480 10481 } 10482 } 10483 10484 s.insert = s.strstart < MIN_MATCH - 1 ? s.strstart : MIN_MATCH - 1; 10485 10486 if (flush === Z_FINISH$3) { 10487 /*** FLUSH_BLOCK(s, 1); ***/ 10488 flush_block_only(s, true); 10489 10490 if (s.strm.avail_out === 0) { 10491 return BS_FINISH_STARTED; 10492 } 10493 /***/ 10494 10495 10496 return BS_FINISH_DONE; 10497 } 10498 10499 if (s.last_lit) { 10500 /*** FLUSH_BLOCK(s, 0); ***/ 10501 flush_block_only(s, false); 10502 10503 if (s.strm.avail_out === 0) { 10504 return BS_NEED_MORE; 10505 } 10506 /***/ 10507 10508 } 10509 10510 return BS_BLOCK_DONE; 10511 }; 10512 /* =========================================================================== 10513 * Same as above, but achieves better compression. We use a lazy 10514 * evaluation for matches: a match is finally adopted only if there is 10515 * no better match at the next window position. 10516 */ 10517 10518 10519 const deflate_slow = (s, flush) => { 10520 let hash_head; 10521 /* head of hash chain */ 10522 10523 let bflush; 10524 /* set if current block must be flushed */ 10525 10526 let max_insert; 10527 /* Process the input block. */ 10528 10529 for (;;) { 10530 /* Make sure that we always have enough lookahead, except 10531 * at the end of the input file. We need MAX_MATCH bytes 10532 * for the next match, plus MIN_MATCH bytes to insert the 10533 * string following the next match. 10534 */ 10535 if (s.lookahead < MIN_LOOKAHEAD) { 10536 fill_window(s); 10537 10538 if (s.lookahead < MIN_LOOKAHEAD && flush === Z_NO_FLUSH$2) { 10539 return BS_NEED_MORE; 10540 } 10541 10542 if (s.lookahead === 0) { 10543 break; 10544 } 10545 /* flush the current block */ 10546 10547 } 10548 /* Insert the string window[strstart .. strstart+2] in the 10549 * dictionary, and set hash_head to the head of the hash chain: 10550 */ 10551 10552 10553 hash_head = 0 10554 /*NIL*/ 10555 ; 10556 10557 if (s.lookahead >= MIN_MATCH) { 10558 /*** INSERT_STRING(s, s.strstart, hash_head); ***/ 10559 s.ins_h = HASH(s, s.ins_h, s.window[s.strstart + MIN_MATCH - 1]); 10560 hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; 10561 s.head[s.ins_h] = s.strstart; 10562 /***/ 10563 } 10564 /* Find the longest match, discarding those <= prev_length. 10565 */ 10566 10567 10568 s.prev_length = s.match_length; 10569 s.prev_match = s.match_start; 10570 s.match_length = MIN_MATCH - 1; 10571 10572 if (hash_head !== 0 10573 /*NIL*/ 10574 && s.prev_length < s.max_lazy_match && s.strstart - hash_head <= s.w_size - MIN_LOOKAHEAD 10575 /*MAX_DIST(s)*/ 10576 ) { 10577 /* To simplify the code, we prevent matches with the string 10578 * of window index 0 (in particular we have to avoid a match 10579 * of the string with itself at the start of the input file). 10580 */ 10581 s.match_length = longest_match(s, hash_head); 10582 /* longest_match() sets match_start */ 10583 10584 if (s.match_length <= 5 && (s.strategy === Z_FILTERED || s.match_length === MIN_MATCH && s.strstart - s.match_start > 4096 10585 /*TOO_FAR*/ 10586 )) { 10587 /* If prev_match is also MIN_MATCH, match_start is garbage 10588 * but we will ignore the current match anyway. 10589 */ 10590 s.match_length = MIN_MATCH - 1; 10591 } 10592 } 10593 /* If there was a match at the previous step and the current 10594 * match is not better, output the previous match: 10595 */ 10596 10597 10598 if (s.prev_length >= MIN_MATCH && s.match_length <= s.prev_length) { 10599 max_insert = s.strstart + s.lookahead - MIN_MATCH; 10600 /* Do not insert strings in hash table beyond this. */ 10601 //check_match(s, s.strstart-1, s.prev_match, s.prev_length); 10602 10603 /***_tr_tally_dist(s, s.strstart - 1 - s.prev_match, 10604 s.prev_length - MIN_MATCH, bflush);***/ 10605 10606 bflush = _tr_tally(s, s.strstart - 1 - s.prev_match, s.prev_length - MIN_MATCH); 10607 /* Insert in hash table all strings up to the end of the match. 10608 * strstart-1 and strstart are already inserted. If there is not 10609 * enough lookahead, the last two strings are not inserted in 10610 * the hash table. 10611 */ 10612 10613 s.lookahead -= s.prev_length - 1; 10614 s.prev_length -= 2; 10615 10616 do { 10617 if (++s.strstart <= max_insert) { 10618 /*** INSERT_STRING(s, s.strstart, hash_head); ***/ 10619 s.ins_h = HASH(s, s.ins_h, s.window[s.strstart + MIN_MATCH - 1]); 10620 hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; 10621 s.head[s.ins_h] = s.strstart; 10622 /***/ 10623 } 10624 } while (--s.prev_length !== 0); 10625 10626 s.match_available = 0; 10627 s.match_length = MIN_MATCH - 1; 10628 s.strstart++; 10629 10630 if (bflush) { 10631 /*** FLUSH_BLOCK(s, 0); ***/ 10632 flush_block_only(s, false); 10633 10634 if (s.strm.avail_out === 0) { 10635 return BS_NEED_MORE; 10636 } 10637 /***/ 10638 10639 } 10640 } else if (s.match_available) { 10641 /* If there was no match at the previous position, output a 10642 * single literal. If there was a match but the current match 10643 * is longer, truncate the previous match to a single literal. 10644 */ 10645 //Tracevv((stderr,"%c", s->window[s->strstart-1])); 10646 10647 /*** _tr_tally_lit(s, s.window[s.strstart-1], bflush); ***/ 10648 bflush = _tr_tally(s, 0, s.window[s.strstart - 1]); 10649 10650 if (bflush) { 10651 /*** FLUSH_BLOCK_ONLY(s, 0) ***/ 10652 flush_block_only(s, false); 10653 /***/ 10654 } 10655 10656 s.strstart++; 10657 s.lookahead--; 10658 10659 if (s.strm.avail_out === 0) { 10660 return BS_NEED_MORE; 10661 } 10662 } else { 10663 /* There is no previous match to compare with, wait for 10664 * the next step to decide. 10665 */ 10666 s.match_available = 1; 10667 s.strstart++; 10668 s.lookahead--; 10669 } 10670 } //Assert (flush != Z_NO_FLUSH, "no flush?"); 10671 10672 10673 if (s.match_available) { 10674 //Tracevv((stderr,"%c", s->window[s->strstart-1])); 10675 10676 /*** _tr_tally_lit(s, s.window[s.strstart-1], bflush); ***/ 10677 bflush = _tr_tally(s, 0, s.window[s.strstart - 1]); 10678 s.match_available = 0; 10679 } 10680 10681 s.insert = s.strstart < MIN_MATCH - 1 ? s.strstart : MIN_MATCH - 1; 10682 10683 if (flush === Z_FINISH$3) { 10684 /*** FLUSH_BLOCK(s, 1); ***/ 10685 flush_block_only(s, true); 10686 10687 if (s.strm.avail_out === 0) { 10688 return BS_FINISH_STARTED; 10689 } 10690 /***/ 10691 10692 10693 return BS_FINISH_DONE; 10694 } 10695 10696 if (s.last_lit) { 10697 /*** FLUSH_BLOCK(s, 0); ***/ 10698 flush_block_only(s, false); 10699 10700 if (s.strm.avail_out === 0) { 10701 return BS_NEED_MORE; 10702 } 10703 /***/ 10704 10705 } 10706 10707 return BS_BLOCK_DONE; 10708 }; 10709 /* =========================================================================== 10710 * For Z_RLE, simply look for runs of bytes, generate matches only of distance 10711 * one. Do not maintain a hash table. (It will be regenerated if this run of 10712 * deflate switches away from Z_RLE.) 10713 */ 10714 10715 10716 const deflate_rle = (s, flush) => { 10717 let bflush; 10718 /* set if current block must be flushed */ 10719 10720 let prev; 10721 /* byte at distance one to match */ 10722 10723 let scan, strend; 10724 /* scan goes up to strend for length of run */ 10725 10726 const _win = s.window; 10727 10728 for (;;) { 10729 /* Make sure that we always have enough lookahead, except 10730 * at the end of the input file. We need MAX_MATCH bytes 10731 * for the longest run, plus one for the unrolled loop. 10732 */ 10733 if (s.lookahead <= MAX_MATCH) { 10734 fill_window(s); 10735 10736 if (s.lookahead <= MAX_MATCH && flush === Z_NO_FLUSH$2) { 10737 return BS_NEED_MORE; 10738 } 10739 10740 if (s.lookahead === 0) { 10741 break; 10742 } 10743 /* flush the current block */ 10744 10745 } 10746 /* See how many times the previous byte repeats */ 10747 10748 10749 s.match_length = 0; 10750 10751 if (s.lookahead >= MIN_MATCH && s.strstart > 0) { 10752 scan = s.strstart - 1; 10753 prev = _win[scan]; 10754 10755 if (prev === _win[++scan] && prev === _win[++scan] && prev === _win[++scan]) { 10756 strend = s.strstart + MAX_MATCH; 10757 10758 do { 10759 /*jshint noempty:false*/ 10760 } while (prev === _win[++scan] && prev === _win[++scan] && prev === _win[++scan] && prev === _win[++scan] && prev === _win[++scan] && prev === _win[++scan] && prev === _win[++scan] && prev === _win[++scan] && scan < strend); 10761 10762 s.match_length = MAX_MATCH - (strend - scan); 10763 10764 if (s.match_length > s.lookahead) { 10765 s.match_length = s.lookahead; 10766 } 10767 } //Assert(scan <= s->window+(uInt)(s->window_size-1), "wild scan"); 10768 10769 } 10770 /* Emit match if have run of MIN_MATCH or longer, else emit literal */ 10771 10772 10773 if (s.match_length >= MIN_MATCH) { 10774 //check_match(s, s.strstart, s.strstart - 1, s.match_length); 10775 10776 /*** _tr_tally_dist(s, 1, s.match_length - MIN_MATCH, bflush); ***/ 10777 bflush = _tr_tally(s, 1, s.match_length - MIN_MATCH); 10778 s.lookahead -= s.match_length; 10779 s.strstart += s.match_length; 10780 s.match_length = 0; 10781 } else { 10782 /* No match, output a literal byte */ 10783 //Tracevv((stderr,"%c", s->window[s->strstart])); 10784 10785 /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/ 10786 bflush = _tr_tally(s, 0, s.window[s.strstart]); 10787 s.lookahead--; 10788 s.strstart++; 10789 } 10790 10791 if (bflush) { 10792 /*** FLUSH_BLOCK(s, 0); ***/ 10793 flush_block_only(s, false); 10794 10795 if (s.strm.avail_out === 0) { 10796 return BS_NEED_MORE; 10797 } 10798 /***/ 10799 10800 } 10801 } 10802 10803 s.insert = 0; 10804 10805 if (flush === Z_FINISH$3) { 10806 /*** FLUSH_BLOCK(s, 1); ***/ 10807 flush_block_only(s, true); 10808 10809 if (s.strm.avail_out === 0) { 10810 return BS_FINISH_STARTED; 10811 } 10812 /***/ 10813 10814 10815 return BS_FINISH_DONE; 10816 } 10817 10818 if (s.last_lit) { 10819 /*** FLUSH_BLOCK(s, 0); ***/ 10820 flush_block_only(s, false); 10821 10822 if (s.strm.avail_out === 0) { 10823 return BS_NEED_MORE; 10824 } 10825 /***/ 10826 10827 } 10828 10829 return BS_BLOCK_DONE; 10830 }; 10831 /* =========================================================================== 10832 * For Z_HUFFMAN_ONLY, do not look for matches. Do not maintain a hash table. 10833 * (It will be regenerated if this run of deflate switches away from Huffman.) 10834 */ 10835 10836 10837 const deflate_huff = (s, flush) => { 10838 let bflush; 10839 /* set if current block must be flushed */ 10840 10841 for (;;) { 10842 /* Make sure that we have a literal to write. */ 10843 if (s.lookahead === 0) { 10844 fill_window(s); 10845 10846 if (s.lookahead === 0) { 10847 if (flush === Z_NO_FLUSH$2) { 10848 return BS_NEED_MORE; 10849 } 10850 10851 break; 10852 /* flush the current block */ 10853 } 10854 } 10855 /* Output a literal byte */ 10856 10857 10858 s.match_length = 0; //Tracevv((stderr,"%c", s->window[s->strstart])); 10859 10860 /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/ 10861 10862 bflush = _tr_tally(s, 0, s.window[s.strstart]); 10863 s.lookahead--; 10864 s.strstart++; 10865 10866 if (bflush) { 10867 /*** FLUSH_BLOCK(s, 0); ***/ 10868 flush_block_only(s, false); 10869 10870 if (s.strm.avail_out === 0) { 10871 return BS_NEED_MORE; 10872 } 10873 /***/ 10874 10875 } 10876 } 10877 10878 s.insert = 0; 10879 10880 if (flush === Z_FINISH$3) { 10881 /*** FLUSH_BLOCK(s, 1); ***/ 10882 flush_block_only(s, true); 10883 10884 if (s.strm.avail_out === 0) { 10885 return BS_FINISH_STARTED; 10886 } 10887 /***/ 10888 10889 10890 return BS_FINISH_DONE; 10891 } 10892 10893 if (s.last_lit) { 10894 /*** FLUSH_BLOCK(s, 0); ***/ 10895 flush_block_only(s, false); 10896 10897 if (s.strm.avail_out === 0) { 10898 return BS_NEED_MORE; 10899 } 10900 /***/ 10901 10902 } 10903 10904 return BS_BLOCK_DONE; 10905 }; 10906 /* Values for max_lazy_match, good_match and max_c
10906hain_length, depending on 10907 * the desired pack level (0..9). The values given below have been tuned to 10908 * exclude worst case performance for pathological files. Better values may be 10909 * found for specific files. 10910 */ 10911 10912 10913 function Config(good_length, max_lazy, nice_length, max_chain, func) { 10914 this.good_length = good_length; 10915 this.max_lazy = max_lazy; 10916 this.nice_length = nice_length; 10917 this.max_chain = max_chain; 10918 this.func = func; 10919 } 10920 10921 const configuration_table = [ 10922 /* good lazy nice chain */ 10923 new Config(0, 0, 0, 0, deflate_stored), 10924 /* 0 store only */ 10925 new Config(4, 4, 8, 4, deflate_fast), 10926 /* 1 max speed, no lazy matches */ 10927 new Config(4, 5, 16, 8, deflate_fast), 10928 /* 2 */ 10929 new Config(4, 6, 32, 32, deflate_fast), 10930 /* 3 */ 10931 new Config(4, 4, 16, 16, deflate_slow), 10932 /* 4 lazy matches */ 10933 new Config(8, 16, 32, 32, deflate_slow), 10934 /* 5 */ 10935 new Config(8, 16, 128, 128, deflate_slow), 10936 /* 6 */ 10937 new Config(8, 32, 128, 256, deflate_slow), 10938 /* 7 */ 10939 new Config(32, 128, 258, 1024, deflate_slow), 10940 /* 8 */ 10941 new Config(32, 258, 258, 4096, deflate_slow) 10942 /* 9 max compression */ 10943 ]; 10944 /* =========================================================================== 10945 * Initialize the "longest match" routines for a new zlib stream 10946 */ 10947 10948 const lm_init = s => { 10949 s.window_size = 2 * s.w_size; 10950 /*** CLEAR_HASH(s); ***/ 10951 10952 zero(s.head); // Fill with NIL (= 0); 10953 10954 /* Set the default configuration parameters: 10955 */ 10956 10957 s.max_lazy_match = configuration_table[s.level].max_lazy; 10958 s.good_match = configuration_table[s.level].good_length; 10959 s.nice_match = configuration_table[s.level].nice_length; 10960 s.max_chain_length = configuration_table[s.level].max_chain; 10961 s.strstart = 0; 10962 s.block_start = 0; 10963 s.lookahead = 0; 10964 s.insert = 0; 10965 s.match_length = s.prev_length = MIN_MATCH - 1; 10966 s.match_available = 0; 10967 s.ins_h = 0; 10968 }; 10969 10970 function DeflateState() { 10971 this.strm = null; 10972 /* pointer back to this zlib stream */ 10973 10974 this.status = 0; 10975 /* as the name implies */ 10976 10977 this.pending_buf = null; 10978 /* output still pending */ 10979 10980 this.pending_buf_size = 0; 10981 /* size of pending_buf */ 10982 10983 this.pending_out = 0; 10984 /* next pending byte to output to the stream */ 10985 10986 this.pending = 0; 10987 /* nb of bytes in the pending buffer */ 10988 10989 this.wrap = 0; 10990 /* bit 0 true for zlib, bit 1 true for gzip */ 10991 10992 this.gzhead = null; 10993 /* gzip header information to write */ 10994 10995 this.gzindex = 0; 10996 /* where in extra, name, or comment */ 10997 10998 this.method = Z_DEFLATED$2; 10999 /* can only be DEFLATED */ 11000 11001 this.last_flush = -1; 11002 /* value of flush param for previous deflate call */ 11003 11004 this.w_size = 0; 11005 /* LZ77 window size (32K by default) */ 11006 11007 this.w_bits = 0; 11008 /* log2(w_size) (8..16) */ 11009 11010 this.w_mask = 0; 11011 /* w_size - 1 */ 11012 11013 this.window = null; 11014 /* Sliding window. Input bytes are read into the second half of the window, 11015 * and move to the first half later to keep a dictionary of at least wSize 11016 * bytes. With this organization, matches are limited to a distance of 11017 * wSize-MAX_MATCH bytes, but this ensures that IO is always 11018 * performed with a length multiple of the block size. 11019 */ 11020 11021 this.window_size = 0; 11022 /* Actual size of window: 2*wSize, except when the user input buffer 11023 * is directly used as sliding window. 11024 */ 11025 11026 this.prev = null; 11027 /* Link to older string with same hash index. To limit the size of this 11028 * array to 64K, this link is maintained only for the last 32K strings. 11029 * An index in this array is thus a window index modulo 32K. 11030 */ 11031 11032 this.head = null; 11033 /* Heads of the hash chains or NIL. */ 11034 11035 this.ins_h = 0; 11036 /* hash index of string to be inserted */ 11037 11038 this.hash_size = 0; 11039 /* number of elements in hash table */ 11040 11041 this.hash_bits = 0; 11042 /* log2(hash_size) */ 11043 11044 this.hash_mask = 0; 11045 /* hash_size-1 */ 11046 11047 this.hash_shift = 0; 11048 /* Number of bits by which ins_h must be shifted at each input 11049 * step. It must be such that after MIN_MATCH steps, the oldest 11050 * byte no longer takes part in the hash key, that is: 11051 * hash_shift * MIN_MATCH >= hash_bits 11052 */ 11053 11054 this.block_start = 0; 11055 /* Window position at the beginning of the current output block. Gets 11056 * negative when the window is moved backwards. 11057 */ 11058 11059 this.match_length = 0; 11060 /* length of best match */ 11061 11062 this.prev_match = 0; 11063 /* previous match */ 11064 11065 this.match_available = 0; 11066 /* set if previous match exists */ 11067 11068 this.strstart = 0; 11069 /* start of string to insert */ 11070 11071 this.match_start = 0; 11072 /* start of matching string */ 11073 11074 this.lookahead = 0; 11075 /* number of valid bytes ahead in window */ 11076 11077 this.prev_length = 0; 11078 /* Length of the best match at previous step. Matches not greater than this 11079 * are discarded. This is used in the lazy match evaluation. 11080 */ 11081 11082 this.max_chain_length = 0; 11083 /* To speed up deflation, hash chains are never searched beyond this 11084 * length. A higher limit improves compression ratio but degrades the 11085 * speed. 11086 */ 11087 11088 this.max_lazy_match = 0; 11089 /* Attempt to find a better match only when the current match is strictly 11090 * smaller than this value. This mechanism is used only for compression 11091 * levels >= 4. 11092 */ 11093 // That's alias to max_lazy_match, don't use directly 11094 //this.max_insert_length = 0; 11095 11096 /* Insert new strings in the hash table only if the match length is not 11097 * greater than this length. This saves time but degrades compression. 11098 * max_insert_length is used only for compression levels <= 3. 11099 */ 11100 11101 this.level = 0; 11102 /* compression level (1..9) */ 11103 11104 this.strategy = 0; 11105 /* favor or force Huffman coding*/ 11106 11107 this.good_match = 0; 11108 /* Use a faster search when the previous match is longer than this */ 11109 11110 this.nice_match = 0; 11111 /* Stop searching when current match exceeds this */ 11112 11113 /* used by trees.c: */ 11114 11115 /* Didn't use ct_data typedef below to suppress compiler warning */ 11116 // struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ 11117 // struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ 11118 // struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ 11119 // Use flat array of DOUBLE size, with interleaved fata, 11120 // because JS does not support effective 11121 11122 this.dyn_ltree = new Uint16Array(HEAP_SIZE * 2); 11123 this.dyn_dtree = new Uint16Array((2 * D_CODES + 1) * 2); 11124 this.bl_tree = new Uint16Array((2 * BL_CODES + 1) * 2); 11125 zero(this.dyn_ltree); 11126 zero(this.dyn_dtree); 11127 zero(this.bl_tree); 11128 this.l_desc = null; 11129 /* desc. for literal tree */ 11130
11131 this.d_desc = null; 11132 /* desc. for distance tree */ 11133 11134 this.bl_desc = null; 11135 /* desc. for bit length tree */ 11136 //ush bl_count[MAX_BITS+1]; 11137 11138 this.bl_count = new Uint16Array(MAX_BITS + 1); 11139 /* number of codes at each bit length for an optimal tree */ 11140 //int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ 11141 11142 this.heap = new Uint16Array(2 * L_CODES + 1); 11143 /* heap used to build the Huffman trees */ 11144 11145 zero(this.heap); 11146 this.heap_len = 0; 11147 /* number of elements in the heap */ 11148 11149 this.heap_max = 0; 11150 /* element of largest frequency */ 11151 11152 /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. 11153 * The same heap array is used to build all trees. 11154 */ 11155 11156 this.depth = new Uint16Array(2 * L_CODES + 1); //uch depth[2*L_CODES+1]; 11157 11158 zero(this.depth); 11159 /* Depth of each subtree used as tie breaker for trees of equal frequency 11160 */ 11161 11162 this.l_buf = 0; 11163 /* buffer index for literals or lengths */ 11164 11165 this.lit_bufsize = 0; 11166 /* Size of match buffer for literals/lengths. There are 4 reasons for 11167 * limiting lit_bufsize to 64K: 11168 * - frequencies can be kept in 16 bit counters 11169 * - if compression is not successful for the first block, all input 11170 * data is still in the window so we can still emit a stored block even 11171 * when input comes from standard input. (This can also be done for 11172 * all blocks if lit_bufsize is not greater than 32K.) 11173 * - if compression is not successful for a file smaller than 64K, we can 11174 * even emit a stored file instead of a stored block (saving 5 bytes). 11175 * This is applicable only for zip (not gzip or zlib). 11176 * - creating new Huffman trees less frequently may not provide fast 11177 * adaptation to changes in the input data statistics. (Take for 11178 * example a binary file with poorly compressible code followed by 11179 * a highly compressible string table.) Smaller buffer sizes give 11180 * fast adaptation but have of course the overhead of transmitting 11181 * trees more frequently. 11182 * - I can't count above 4 11183 */ 11184 11185 this.last_lit = 0; 11186 /* running index in l_buf */ 11187 11188 this.d_buf = 0; 11189 /* Buffer index for distances. To simplify the code, d_buf and l_buf have 11190 * the same number of elements. To use different lengths, an extra flag 11191 * array would be necessary. 11192 */ 11193 11194 this.opt_len = 0; 11195 /* bit length of current block with optimal trees */ 11196 11197 this.static_len = 0; 11198 /* bit length of current block with static trees */ 11199 11200 this.matches = 0; 11201 /* number of string matches in current block */ 11202 11203 this.insert = 0; 11204 /* bytes at end of window left to insert */ 11205 11206 this.bi_buf = 0; 11207 /* Output buffer. bits are inserted starting at the bottom (least 11208 * significant bits). 11209 */ 11210 11211 this.bi_valid = 0; 11212 /* Number of valid bits in bi_buf. All bits above the last valid bit 11213 * are always zero. 11214 */ 11215 // Used for window memory init. We safely ignore it for JS. That makes 11216 // sense only for pointers and memory check tools. 11217 //this.high_water = 0; 11218 11219 /* High water mark offset in window for initialized bytes -- bytes above 11220 * this are set to zero in order to avoid memory check warnings when 11221 * longest match routines access bytes past the input. This is then 11222 * updated to the new high water mark. 11223 */ 11224 } 11225 11226 const deflateResetKeep = strm => { 11227 if (!strm || !strm.state) { 11228 return err(strm, Z_STREAM_ERROR$2); 11229 } 11230 11231 strm.total_in = strm.total_out = 0; 11232 strm.data_type = Z_UNKNOWN; 11233 const s = strm.state; 11234 s.pending = 0; 11235 s.pending_out = 0; 11236 11237 if (s.wrap < 0) { 11238 s.wrap = -s.wrap; 11239 /* was made negative by deflate(..., Z_FINISH); */ 11240 } 11241 11242 s.status = s.wrap ? INIT_STATE : BUSY_STATE; 11243 strm.adler = s.wrap === 2 ? 0 // crc32(0, Z_NULL, 0) 11244 : 1; // adler32(0, Z_NULL, 0) 11245 11246 s.last_flush = Z_NO_FLUSH$2; 11247 11248 _tr_init(s); 11249 11250 return Z_OK$3; 11251 }; 11252 11253 const deflateReset = strm => { 11254 const ret = deflateResetKeep(strm); 11255 11256 if (ret === Z_OK$3) { 11257 lm_init(strm.state); 11258 } 11259 11260 return ret; 11261 }; 11262 11263 const deflateSetHeader = (strm, head) => { 11264 if (!strm || !strm.state) { 11265 return Z_STREAM_ERROR$2; 11266 } 11267 11268 if (strm.state.wrap !== 2) { 11269 return Z_STREAM_ERROR$2; 11270 } 11271 11272 strm.state.gzhead = head; 11273 return Z_OK$3; 11274 }; 11275 11276 const deflateInit2 = (strm, level, method, windowBits, memLevel, strategy) => { 11277 if (!strm) { 11278 // === Z_NULL 11279 return Z_STREAM_ERROR$2; 11280 } 11281 11282 let wrap = 1; 11283 11284 if (level === Z_DEFAULT_COMPRESSION$1) { 11285 level = 6; 11286 } 11287 11288 if (windowBits < 0) { 11289 /* suppress zlib wrapper */ 11290 wrap = 0; 11291 windowBits = -windowBits; 11292 } else if (windowBits > 15) { 11293 wrap = 2; 11294 /* write gzip wrapper instead */ 11295 11296 windowBits -= 16; 11297 } 11298 11299 if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method !== Z_DEFLATED$2 || windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) { 11300 return err(strm, Z_STREAM_ERROR$2); 11301 } 11302 11303 if (windowBits === 8) { 11304 windowBits = 9; 11305 } 11306 /* until 256-byte window bug fixed */ 11307 11308 11309 const s = new DeflateState(); 11310 strm.state = s; 11311 s.strm = strm; 11312 s.wrap = wrap; 11313 s.gzhead = null; 11314 s.w_bits = windowBits; 11315 s.w_size = 1 << s.w_bits; 11316 s.w_mask = s.w_size - 1; 11317 s.hash_bits = memLevel + 7; 11318 s.hash_size = 1 << s.hash_bits; 11319 s.hash_mask = s.hash_size - 1; 11320 s.hash_shift = ~~((s.hash_bits + MIN_MATCH - 1) / MIN_MATCH); 11321 s.window = new Uint8Array(s.w_size * 2); 11322 s.head = new Uint16Array(s.hash_size); 11323 s.prev = new Uint16Array(s.w_size); // Don't need mem init magic for JS. 11324 //s.high_water = 0;
11324 /* nothing written to s->window yet */ 11325 11326 s.lit_bufsize = 1 << memLevel + 6; 11327 /* 16K elements by default */ 11328 11329 s.pending_buf_size = s.lit_bufsize * 4; //overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); 11330 //s->pending_buf = (uchf *) overlay; 11331 11332 s.pending_buf = new Uint8Array(s.pending_buf_size); // It is offset from `s.pending_buf` (size is `s.lit_bufsize * 2`) 11333 //s->d_buf = overlay + s->lit_bufsize/sizeof(ush); 11334 11335 s.d_buf = 1 * s.lit_bufsize; //s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; 11336 11337 s.l_buf = (1 + 2) * s.lit_bufsize; 11338 s.level = level; 11339 s.strategy = strategy; 11340 s.method = method; 11341 return deflateReset(strm); 11342 }; 11343 11344 const deflateInit = (strm, level) => { 11345 return deflateInit2(strm, level, Z_DEFLATED$2, MAX_WBITS$1, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY$1); 11346 }; 11347 11348 const deflate$2 = (strm, flush) => { 11349 let beg, val; // for gzip header write only 11350 11351 if (!strm || !strm.state || flush > Z_BLOCK$1 || flush < 0) { 11352 return strm ? err(strm, Z_STREAM_ERROR$2) : Z_STREAM_ERROR$2; 11353 } 11354 11355 const s = strm.state; 11356 11357 if (!strm.output || !strm.input && strm.avail_in !== 0 || s.status === FINISH_STATE && flush !== Z_FINISH$3) { 11358 return err(strm, strm.avail_out === 0 ? Z_BUF_ERROR$1 : Z_STREAM_ERROR$2); 11359 } 11360 11361 s.strm = strm; 11362 /* just in case */ 11363 11364 const old_flush = s.last_flush; 11365 s.last_flush = flush; 11366 /* Write the header */ 11367 11368 if (s.status === INIT_STATE) { 11369 if (s.wrap === 2) { 11370 // GZIP header 11371 strm.adler = 0; //crc32(0L, Z_NULL, 0); 11372 11373 put_byte(s, 31); 11374 put_byte(s, 139); 11375 put_byte(s, 8); 11376 11377 if (!s.gzhead) { 11378 // s->gzhead == Z_NULL 11379 put_byte(s, 0); 11380 put_byte(s, 0); 11381 put_byte(s, 0); 11382 put_byte(s, 0); 11383 put_byte(s, 0); 11384 put_byte(s, s.level === 9 ? 2 : s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ? 4 : 0); 11385 put_byte(s, OS_CODE); 11386 s.status = BUSY_STATE; 11387 } else { 11388 put_byte(s, (s.gzhead.text ? 1 : 0) + (s.gzhead.hcrc ? 2 : 0) + (!s.gzhead.extra ? 0 : 4) + (!s.gzhead.name ? 0 : 8) + (!s.gzhead.comment ? 0 : 16)); 11389 put_byte(s, s.gzhead.time & 0xff); 11390 put_byte(s, s.gzhead.time >> 8 & 0xff); 11391 put_byte(s, s.gzhead.time >> 16 & 0xff); 11392 put_byte(s, s.gzhead.time >> 24 & 0xff); 11393 put_byte(s, s.level === 9 ? 2 : s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ? 4 : 0); 11394 put_byte(s, s.gzhead.os & 0xff); 11395 11396 if (s.gzhead.extra && s.gzhead.extra.length) { 11397 put_byte(s, s.gzhead.extra.length & 0xff); 11398 put_byte(s, s.gzhead.extra.length >> 8 & 0xff); 11399 } 11400 11401 if (s.gzhead.hcrc) { 11402 strm.adler = crc32_1(strm.adler, s.pending_buf, s.pending, 0); 11403 } 11404 11405 s.gzindex = 0; 11406 s.status = EXTRA_STATE; 11407 } 11408 } else // DEFLATE header 11409 { 11410 let header = Z_DEFLATED$2 + (s.w_bits - 8 << 4) << 8; 11411 let level_flags = -1; 11412 11413 if (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2) { 11414 level_flags = 0; 11415 } else if (s.level < 6) { 11416 level_flags = 1; 11417 } else if (s.level === 6) { 11418 level_flags = 2; 11419 } else { 11420 level_flags = 3; 11421 } 11422 11423 header |= level_flags << 6; 11424 11425 if (s.strstart !== 0) { 11426 header |= PRESET_DICT; 11427 } 11428 11429 header += 31 - header % 31; 11430 s.status = BUSY_STATE; 11431 putShortMSB(s, header); 11432 /* Save the adler32 of the preset dictionary: */ 11433 11434 if (s.strstart !== 0) { 11435 putShortMSB(s, strm.adler >>> 16); 11436 putShortMSB(s, strm.adler & 0xffff); 11437 } 11438 11439 strm.adler = 1; // adler32(0L, Z_NULL, 0); 11440 } 11441 } //#ifdef GZIP 11442 11443 11444 if (s.status === EXTRA_STATE) { 11445 if (s.gzhead.extra 11446 /* != Z_NULL*/ 11447 ) { 11448 beg = s.pending; 11449 /* start of bytes to update crc */ 11450 11451 while (s.gzindex < (s.gzhead.extra.length & 0xffff)) { 11452 if (s.pending === s.pending_buf_size) { 11453 if (s.gzhead.hcrc && s.pending > beg) { 11454 strm.adler = crc32_1(strm.adler, s.pending_buf, s.pending - beg, beg); 11455 } 11456 11457 flush_pending(strm); 11458 beg = s.pending; 11459 11460 if (s.pending === s.pending_buf_size) { 11461 break; 11462 } 11463 } 11464 11465 put_byte(s, s.gzhead.extra[s.gzindex] & 0xff);
vendor: 4,060 bytes, lines 11466-11608
11466 s.gzindex++; 11467 } 11468 11469 if (s.gzhead.hcrc && s.pending > beg) { 11470 strm.adler = crc32_1(strm.adler, s.pending_buf, s.pending - beg, beg); 11471 } 11472 11473 if (s.gzindex === s.gzhead.extra.length) { 11474 s.gzindex = 0; 11475 s.status = NAME_STATE; 11476 } 11477 } else { 11478 s.status = NAME_STATE; 11479 } 11480 } 11481 11482 if (s.status === NAME_STATE) { 11483 if (s.gzhead.name 11484 /* != Z_NULL*/ 11485 ) { 11486 beg = s.pending; 11487 /* start of bytes to update crc */ 11488 //int val; 11489 11490 do { 11491 if (s.pending === s.pending_buf_size) { 11492 if (s.gzhead.hcrc && s.pending > beg) { 11493 strm.adler = crc32_1(strm.adler, s.pending_buf, s.pending - beg, beg); 11494 } 11495 11496 flush_pending(strm); 11497 beg = s.pending; 11498 11499 if (s.pending === s.pending_buf_size) { 11500 val = 1; 11501 break; 11502 } 11503 } // JS specific: little magic to add zero terminator to end of string 11504 11505 11506 if (s.gzindex < s.gzhead.name.length) { 11507 val = s.gzhead.name.charCodeAt(s.gzindex++) & 0xff; 11508 } else { 11509 val = 0; 11510 } 11511 11512 put_byte(s, val); 11513 } while (val !== 0); 11514 11515 if (s.gzhead.hcrc && s.pending > beg) { 11516 strm.adler = crc32_1(strm.adler, s.pending_buf, s.pending - beg, beg); 11517 } 11518 11519 if (val === 0) { 11520 s.gzindex = 0; 11521 s.status = COMMENT_STATE; 11522 } 11523 } else { 11524 s.status = COMMENT_STATE; 11525 } 11526 } 11527 11528 if (s.status === COMMENT_STATE) { 11529 if (s.gzhead.comment 11530 /* != Z_NULL*/ 11531 ) { 11532 beg = s.pending; 11533 /* start of bytes to update crc */ 11534 //int val; 11535 11536 do { 11537 if (s.pending === s.pending_buf_size) { 11538 if (s.gzhead.hcrc && s.pending > beg) { 11539 strm.adler = crc32_1(strm.adler, s.pending_buf, s.pending - beg, beg); 11540 } 11541 11542 flush_pending(strm); 11543 beg = s.pending; 11544 11545 if (s.pending === s.pending_buf_size) { 11546 val = 1; 11547 break; 11548 } 11549 } // JS specific: little magic to add zero terminator to end of string 11550 11551 11552 if (s.gzindex < s.gzhead.comment.length) { 11553 val = s.gzhead.comment.charCodeAt(s.gzindex++) & 0xff; 11554 } else { 11555 val = 0; 11556 } 11557 11558 put_byte(s, val); 11559 } while (val !== 0); 11560 11561 if (s.gzhead.hcrc && s.pending > beg) { 11562 strm.adler = crc32_1(strm.adler, s.pending_buf, s.pending - beg, beg); 11563 } 11564 11565 if (val === 0) { 11566 s.status = HCRC_STATE; 11567 } 11568 } else { 11569 s.status = HCRC_STATE; 11570 } 11571 } 11572 11573 if (s.status === HCRC_STATE) { 11574 if (s.gzhead.hcrc) { 11575 if (s.pending + 2 > s.pending_buf_size) { 11576 flush_pending(strm); 11577 } 11578 11579 if (s.pending + 2 <= s.pending_buf_size) { 11580 put_byte(s, strm.adler & 0xff); 11581 put_byte(s, strm.adler >> 8 & 0xff); 11582 strm.adler = 0; //crc32(0L, Z_NULL, 0); 11583 11584 s.status = BUSY_STATE; 11585 } 11586 } else { 11587 s.status = BUSY_STATE; 11588 } 11589 } //#endif 11590 11591 /* Flush as much pending output as possible */ 11592 11593 11594 if (s.pending !== 0) { 11595 flush_pending(strm); 11596 11597 if (strm.avail_out === 0) { 11598 /* Since avail_out is 0, deflate will be called again with 11599 * more output space, but possibly with both pending and 11600 * avail_in equal to zero. There won't be anything to do, 11601 * but this is not an error situation so make sure we 11602 * return OK instead of BUF_ERROR at next call of deflate: 11603 */ 11604 s.last_flush = -1; 11605 return Z_OK$3; 11606 } 11607 /* Make sure there is something to do and avoid duplicate consecutive 11608 * flushes. For repeated and useless calls with Z_FINISH, we keep
vendor: 18,031 bytes, lines 11609-12234
11609 * returning Z_STREAM_END instead of Z_BUF_ERROR. 11610 */ 11611 11612 } else if (strm.avail_in === 0 && rank(flush) <= rank(old_flush) && flush !== Z_FINISH$3) { 11613 return err(strm, Z_BUF_ERROR$1); 11614 } 11615 /* User must not provide more input after the first FINISH: */ 11616 11617 11618 if (s.status === FINISH_STATE && strm.avail_in !== 0) { 11619 return err(strm, Z_BUF_ERROR$1); 11620 } 11621 /* Start a new block or continue the current one. 11622 */ 11623 11624 11625 if (strm.avail_in !== 0 || s.lookahead !== 0 || flush !== Z_NO_FLUSH$2 && s.status !== FINISH_STATE) { 11626 let bstate = s.strategy === Z_HUFFMAN_ONLY ? deflate_huff(s, flush) : s.strategy === Z_RLE ? deflate_rle(s, flush) : configuration_table[s.level].func(s, flush); 11627 11628 if (bstate === BS_FINISH_STARTED || bstate === BS_FINISH_DONE) { 11629 s.status = FINISH_STATE; 11630 } 11631 11632 if (bstate === BS_NEED_MORE || bstate === BS_FINISH_STARTED) { 11633 if (strm.avail_out === 0) { 11634 s.last_flush = -1; 11635 /* avoid BUF_ERROR next call, see above */ 11636 } 11637 11638 return Z_OK$3; 11639 /* If flush != Z_NO_FLUSH && avail_out == 0, the next call 11640 * of deflate should use the same flush parameter to make sure 11641 * that the flush is complete. So we don't have to output an 11642 * empty block here, this will be done at next call. This also 11643 * ensures that for a very small output buffer, we emit at most 11644 * one empty block. 11645 */ 11646 } 11647 11648 if (bstate === BS_BLOCK_DONE) { 11649 if (flush === Z_PARTIAL_FLUSH) { 11650 _tr_align(s); 11651 } else if (flush !== Z_BLOCK$1) { 11652 /* FULL_FLUSH or SYNC_FLUSH */ 11653 _tr_stored_block(s, 0, 0, false); 11654 /* For a full flush, this empty block will be recognized 11655 * as a special marker by inflate_sync(). 11656 */ 11657 11658 11659 if (flush === Z_FULL_FLUSH$1) { 11660 /*** CLEAR_HASH(s); ***/ 11661 11662 /* forget history */ 11663 zero(s.head); // Fill with NIL (= 0); 11664 11665 if (s.lookahead === 0) { 11666 s.strstart = 0; 11667 s.block_start = 0; 11668 s.insert = 0; 11669 } 11670 } 11671 } 11672 11673 flush_pending(strm); 11674 11675 if (strm.avail_out === 0) { 11676 s.last_flush = -1; 11677 /* avoid BUF_ERROR at next call, see above */ 11678 11679 return Z_OK$3; 11680 } 11681 } 11682 } //Assert(strm->avail_out > 0, "bug2"); 11683 //if (strm.avail_out <= 0) { throw new Error("bug2");} 11684 11685 11686 if (flush !== Z_FINISH$3) { 11687 return Z_OK$3; 11688 } 11689 11690 if (s.wrap <= 0) { 11691 return Z_STREAM_END$3; 11692 } 11693 /* Write the trailer */ 11694 11695 11696 if (s.wrap === 2) { 11697 put_byte(s, strm.adler & 0xff); 11698 put_byte(s, strm.adler >> 8 & 0xff); 11699 put_byte(s, strm.adler >> 16 & 0xff); 11700 put_byte(s, strm.adler >> 24 & 0xff); 11701 put_byte(s, strm.total_in & 0xff); 11702 put_byte(s, strm.total_in >> 8 & 0xff); 11703 put_byte(s, strm.total_in >> 16 & 0xff); 11704 put_byte(s, strm.total_in >> 24 & 0xff); 11705 } else { 11706 putShortMSB(s, strm.adler >>> 16); 11707 putShortMSB(s, strm.adler & 0xffff); 11708 } 11709 11710 flush_pending(strm); 11711 /* If avail_out is zero, the application will call deflate again 11712 * to flush the rest. 11713 */ 11714 11715 if (s.wrap > 0) { 11716 s.wrap = -s.wrap; 11717 } 11718 /* write the trailer only once! */ 11719 11720 11721 return s.pending !== 0 ? Z_OK$3 : Z_STREAM_END$3; 11722 }; 11723 11724 const deflateEnd = strm => { 11725 if (!strm 11726 /*== Z_NULL*/ 11727 || !strm.state 11728 /*== Z_NULL*/ 11729 ) { 11730 return Z_STREAM_ERROR$2; 11731 } 11732 11733 const status = strm.state.status; 11734 11735 if (status !== INIT_STATE && status !== EXTRA_STATE && status !== NAME_STATE && status !== COMMENT_STATE && status !== HCRC_STATE && status !== BUSY_STATE && status !== FINISH_STATE) { 11736 return err(strm, Z_STREAM_ERROR$2); 11737 } 11738 11739 strm.state = null; 11740 return status === BUSY_STATE ? err(strm, Z_DATA_ERROR$2) : Z_OK$3; 11741 }; 11742 /* ========================================================================= 11743 * Initializes the compression dictionary from the given byte 11744 * sequence without producing any compressed output. 11745 */ 11746 11747 11748 const deflateSetDictionary = (strm, dictionary) => { 11749 let dictLength = dictionary.length; 11750 11751 if (!strm 11752 /*== Z_NULL*/ 11753 || !strm.state 11754 /*== Z_NULL*/ 11755 ) { 11756 return Z_STREAM_ERROR$2; 11757 } 11758 11759 const s = strm.state; 11760 const wrap = s.wrap; 11761 11762 if (wrap === 2 || wrap === 1 && s.status !== INIT_STATE || s.lookahead) { 11763 return Z_STREAM_ERROR$2; 11764 } 11765 /* when using zlib wrappers, compute Adler-32 for provided dictionary */ 11766 11767 11768 if (wrap === 1) { 11769 /* adler32(strm->adler, dictionary, dictLength); */ 11770 strm.adler = adler32_1(strm.adler, dictionary, dictLength, 0); 11771 } 11772 11773 s.wrap = 0; 11774 /* avoid computing Adler-32 in read_buf */ 11775 11776 /* if dictionary would fill window, just replace the history */ 11777 11778 if (dictLength >= s.w_size) { 11779 if (wrap === 0) { 11780 /* already empty otherwise */ 11781 11782 /*** CLEAR_HASH(s); ***/ 11783 zero(s.head); // Fill with NIL (= 0); 11784 11785 s.strstart = 0; 11786 s.block_start = 0; 11787 s.insert = 0; 11788 } 11789 /* use the tail */ 11790 // dictionary = dictionary.slice(dictLength - s.w_size); 11791 11792 11793 let tmpDict = new Uint8Array(s.w_size); 11794 tmpDict.set(dictionary.subarray(dictLength - s.w_size, dictLength), 0); 11795 dictionary = tmpDict; 11796 dictLength = s.w_size; 11797 } 11798 /* insert dictionary into window and hash */ 11799 11800 11801 const avail = strm.avail_in; 11802 const next = strm.next_in; 11803 const input = strm.input; 11804 strm.avail_in = dictLength; 11805 strm.next_in = 0; 11806 strm.input = dictionary; 11807 fill_window(s); 11808 11809 while (s.lookahead >= MIN_MATCH) { 11810 let str = s.strstart; 11811 let n = s.lookahead - (MIN_MATCH - 1); 11812 11813 do { 11814 /* UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); */ 11815 s.ins_h = HASH(s, s.ins_h, s.window[str + MIN_MATCH - 1]); 11816 s.prev[str & s.w_mask] = s.head[s.ins_h]; 11817 s.head[s.ins_h] = str; 11818 str++; 11819 } while (--n); 11820 11821 s.strstart = str; 11822 s.lookahead = MIN_MATCH - 1; 11823 fill_window(s); 11824 } 11825 11826 s.strstart += s.lookahead; 11827 s.block_start = s.strstart; 11828 s.insert = s.lookahead; 11829 s.lookahead = 0; 11830 s.match_length = s.prev_length = MIN_MATCH - 1; 11831 s.match_available = 0; 11832 strm.next_in = next; 11833 strm.input = input; 11834 strm.avail_in = avail; 11835 s.wrap = wrap; 11836 return Z_OK$3; 11837 }; 11838 11839 var deflateInit_1 = deflateInit; 11840 var deflateInit2_1 = deflateInit2; 11841 var deflateReset_1 = deflateReset; 11842 var deflateResetKeep_1 = deflateResetKeep; 11843 var deflateSetHeader_1 = deflateSetHeader; 11844 var deflate_2$1 = deflate$2; 11845 var deflateEnd_1 = deflateEnd; 11846 var deflateSetDictionary_1 = deflateSetDictionary; 11847 var deflateInfo = 'pako deflate (from Nodeca project)'; 11848 /* Not implemented 11849 module.exports.deflateBound = deflateBound; 11850 module.exports.deflateCopy = deflateCopy; 11851 module.exports.deflateParams = deflateParams; 11852 module.exports.deflatePending = deflatePending; 11853 module.exports.deflatePrime = deflatePrime; 11854 module.exports.deflateTune = deflateTune; 11855 */ 11856 11857 var deflate_1$2 = { 11858 deflateInit: deflateInit_1, 11859 deflateInit2: deflateInit2_1, 11860 deflateReset: deflateReset_1, 11861 deflateResetKeep: deflateResetKeep_1, 11862 deflateSetHeader: deflateSetHeader_1, 11863 deflate: deflate_2$1, 11864 deflateEnd: deflateEnd_1, 11865 deflateSetDictionary: deflateSetDictionary_1, 11866 deflateInfo: deflateInfo 11867 }; 11868 11869 const _has = (obj, key) => { 11870 return Object.prototype.hasOwnProperty.call(obj, key); 11871 }; 11872 11873 var assign = function (obj 11874 /*from1, from2, from3, ...*/ 11875 ) { 11876 const sources = Array.prototype.slice.call(arguments, 1); 11877 11878 while (sources.length) { 11879 const source = sources.shift(); 11880 11881 if (!source) { 11882 continue; 11883 } 11884 11885 if (typeof source !== 'object') { 11886 throw new TypeError(source + 'must be non-object'); 11887 } 11888 11889 for (const p in source) { 11890 if (_has(source, p)) { 11891 obj[p] = source[p]; 11892 } 11893 } 11894 } 11895 11896 return obj; 11897 }; // Join array of chunks to single array. 11898 11899 11900 var flattenChunks = chunks => { 11901 // calculate data length 11902 let len = 0; 11903 11904 for (let i = 0, l = chunks.length; i < l; i++) { 11905 len += chunks[i].length; 11906 } // join chunks 11907 11908 11909 const result = new Uint8Array(len); 11910 11911 for (let i = 0, pos = 0, l = chunks.length; i < l; i++) { 11912 let chunk = chunks[i]; 11913 result.set(chunk, pos); 11914 pos += chunk.length; 11915 } 11916 11917 return result; 11918 }; 11919 11920 var common = { 11921 assign: assign, 11922 flattenChunks: flattenChunks 11923 }; // String encode/decode helpers 11924 // Quick check if we can use fast array to bin string conversion 11925 // 11926 // - apply(Array) can fail on Android 2.2 11927 // - apply(Uint8Array) can fail on iOS 5.1 Safari 11928 // 11929 11930 let STR_APPLY_UIA_OK = true; 11931 11932 try { 11933 String.fromCharCode.apply(null, new Uint8Array(1)); 11934 } catch (__) { 11935 STR_APPLY_UIA_OK = false; 11936 } // Table with utf8 lengths (calculated by first byte of sequence) 11937 // Note, that 5 & 6-byte values and some 4-byte values can not be represented in JS, 11938 // because max possible codepoint is 0x10ffff 11939 11940 11941 const _utf8len = new Uint8Array(256); 11942 11943 for (let q = 0; q < 256; q++) { 11944 _utf8len[q] = q >= 252 ? 6 : q >= 248 ? 5 : q >= 240 ? 4 : q >= 224 ? 3 : q >= 192 ? 2 : 1; 11945 } 11946 11947 _utf8len[254] = _utf8len[254] = 1; // Invalid sequence start 11948 // convert string to array (typed, when possible) 11949 11950 var string2buf = str => { 11951 if (typeof TextEncoder === 'function' && TextEncoder.prototype.encode) { 11952 return new TextEncoder().encode(str); 11953 } 11954 11955 let buf, 11956 c, 11957 c2, 11958 m_pos, 11959 i, 11960 str_len = str.length, 11961 buf_len = 0; // count binary size 11962 11963 for (m_pos = 0; m_pos < str_len; m_pos++) { 11964 c = str.charCodeAt(m_pos); 11965 11966 if ((c & 0xfc00) === 0xd800 && m_pos + 1 < str_len) { 11967 c2 = str.charCodeAt(m_pos + 1); 11968 11969 if ((c2 & 0xfc00) === 0xdc00) { 11970 c = 0x10000 + (c - 0xd800 << 10) + (c2 - 0xdc00); 11971 m_pos++; 11972 } 11973 } 11974 11975 buf_len += c < 0x80 ? 1 : c < 0x800 ? 2 : c < 0x10000 ? 3 : 4; 11976 } // allocate buffer 11977 11978 11979 buf = new Uint8Array(buf_len); // convert 11980 11981 for (i = 0, m_pos = 0; i < buf_len; m_pos++) { 11982 c = str.charCodeAt(m_pos); 11983 11984 if ((c & 0xfc00) === 0xd800 && m_pos + 1 < str_len) { 11985 c2 = str.charCodeAt(m_pos + 1); 11986 11987 if ((c2 & 0xfc00) === 0xdc00) { 11988 c = 0x10000 + (c - 0xd800 << 10) + (c2 - 0xdc00); 11989 m_pos++; 11990 } 11991 } 11992 11993 if (c < 0x80) { 11994 /* one byte */ 11995 buf[i++] = c; 11996 } else if (c < 0x800) { 11997 /* two bytes */ 11998 buf[i++] = 0xC0 | c >>> 6; 11999 buf[i++] = 0x80 | c & 0x3f; 12000 } else if (c < 0x10000) { 12001 /* three bytes */ 12002 buf[i++] = 0xE0 | c >>> 12; 12003 buf[i++] = 0x80 | c >>> 6 & 0x3f; 12004 buf[i++] = 0x80 | c & 0x3f; 12005 } else { 12006 /* four bytes */ 12007 buf[i++] = 0xf0 | c >>> 18; 12008 buf[i++] = 0x80 | c >>> 12 & 0x3f; 12009 buf[i++] = 0x80 | c >>> 6 & 0x3f; 12010 buf[i++] = 0x80 | c & 0x3f; 12011 } 12012 } 12013 12014 return buf; 12015 }; // Helper 12016 12017 12018 const buf2binstring = (buf, len) => { 12019 // On Chrome, the arguments in a function call that are allowed is `65534`. 12020 // If the length of the buffer is smaller than that, we can use this optimization, 12021 // otherwise we will take a slower path. 12022 if (len < 65534) { 12023 if (buf.subarray && STR_APPLY_UIA_OK) { 12024 return String.fromCharCode.apply(null, buf.length === len ? buf : buf.subarray(0, len)); 12025 } 12026 } 12027 12028 let result = ''; 12029 12030 for (let i = 0; i < len; i++) { 12031 result += String.fromCharCode(buf[i]); 12032 } 12033 12034 return result; 12035 }; // convert array to string 12036 12037 12038 var buf2string = (buf, max) => { 12039 const len = max || buf.length; 12040 12041 if (typeof TextDecoder === 'function' && TextDecoder.prototype.decode) { 12042 return new TextDecoder().decode(buf.subarray(0, max)); 12043 } 12044 12045 let i, out; // Reserve max possible length (2 words per char) 12046 // NB: by unknown reasons, Array is significantly faster for 12047 // String.fromCharCode.apply than Uint16Array. 12048 12049 const utf16buf = new Array(len * 2); 12050 12051 for (out = 0, i = 0; i < len;) { 12052 let c = buf[i++]; // quick process ascii 12053 12054 if (c < 0x80) { 12055 utf16buf[out++] = c; 12056 continue; 12057 } 12058 12059 let c_len = _utf8len[c]; // skip 5 & 6 byte codes 12060 12061 if (c_len > 4) { 12062 utf16buf[out++] = 0xfffd; 12063 i += c_len - 1; 12064 continue; 12065 } // apply mask on first byte 12066 12067 12068 c &= c_len === 2 ? 0x1f : c_len === 3 ? 0x0f : 0x07; // join the rest 12069 12070 while (c_len > 1 && i < len) { 12071 c = c << 6 | buf[i++] & 0x3f; 12072 c_len--; 12073 } // terminated by end of string? 12074 12075 12076 if (c_len > 1) { 12077 utf16buf[out++] = 0xfffd; 12078 continue; 12079 } 12080 12081 if (c < 0x10000) { 12082 utf16buf[out++] = c; 12083 } else { 12084 c -= 0x10000; 12085 utf16buf[out++] = 0xd800 | c >> 10 & 0x3ff; 12086 utf16buf[out++] = 0xdc00 | c & 0x3ff; 12087 } 12088 } 12089 12090 return buf2binstring(utf16buf, out); 12091 }; // Calculate max possible position in utf8 buffer, 12092 // that will not break sequence. If that's not possible 12093 // - (very small limits) return max size as is. 12094 // 12095 // buf[] - utf8 bytes array 12096 // max - length limit (mandatory); 12097 12098 12099 var utf8border = (buf, max) => { 12100 max = max || buf.length; 12101 12102 if (max > buf.length) { 12103 max = buf.length; 12104 } // go back from last position, until start of sequence found 12105 12106 12107 let pos = max - 1; 12108 12109 while (pos >= 0 && (buf[pos] & 0xC0) === 0x80) { 12110 pos--; 12111 } // Very small and broken sequence, 12112 // return max, because we should return something anyway. 12113 12114 12115 if (pos < 0) { 12116 return max; 12117 } // If we came to start of buffer - that means buffer is too small, 12118 // return max too. 12119 12120 12121 if (pos === 0) { 12122 return max; 12123 } 12124 12125 return pos + _utf8len[buf[pos]] > max ? pos : max; 12126 }; 12127 12128 var strings = { 12129 string2buf: string2buf, 12130 buf2string: buf2string, 12131 utf8border: utf8border 12132 }; // (C) 1995-2013 Jean-loup Gailly and Mark Adler 12133 // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin 12134 // 12135 // This software is provided 'as-is', without any express or implied 12136 // warranty. In no event will the authors be held liable for any damages 12137 // arising from the use of this software. 12138 // 12139 // Permission is granted to anyone to use this software for any purpose, 12140 // including commercial applications, and to alter it and redistribute it 12141 // freely, subject to the following restrictions: 12142 // 12143 // 1. The origin of this software must not be misrepresented; you must not 12144 // claim that you wrote the original software. If you use this software 12145 // in a product, an acknowledgment in the product documentation would be 12146 // appreciated but is not required. 12147 // 2. Altered source versions must be plainly marked as such, and must not be 12148 // misrepresented as being the original software. 12149 // 3. This notice may not be removed or altered from any source distribution. 12150 12151 function ZStream() { 12152 /* next input byte */ 12153 this.input = null; // JS specific, because we have no pointers 12154 12155 this.next_in = 0; 12156 /* number of bytes available at input */ 12157 12158 this.avail_in = 0; 12159 /* total number of input bytes read so far */ 12160 12161 this.total_in = 0; 12162 /* next output byte should be put there */ 12163 12164 this.output = null; // JS specific, because we have no pointers 12165 12166 this.next_out = 0; 12167 /* remaining free space at output */ 12168 12169 this.avail_out = 0; 12170 /* total number of bytes output so far */ 12171 12172 this.total_out = 0; 12173 /* last error message, NULL if no error */ 12174 12175 this.msg = '' 12176 /*Z_NULL*/ 12177 ; 12178 /* not visible by applications */ 12179 12180 this.state = null; 12181 /* best guess about the data type: binary or text */ 12182 12183 this.data_type = 2 12184 /*Z_UNKNOWN*/ 12185 ; 12186 /* adler32 value of the uncompressed data */ 12187 12188 this.adler = 0; 12189 } 12190 12191 var zstream = ZStream; 12192 const toString$1$1 = Object.prototype.toString; 12193 /* Public constants ==========================================================*/ 12194 12195 /* ===========================================================================*/ 12196 12197 const { 12198 Z_NO_FLUSH: Z_NO_FLUSH$1, 12199 Z_SYNC_FLUSH, 12200 Z_FULL_FLUSH, 12201 Z_FINISH: Z_FINISH$2, 12202 Z_OK: Z_OK$2, 12203 Z_STREAM_END: Z_STREAM_END$2, 12204 Z_DEFAULT_COMPRESSION, 12205 Z_DEFAULT_STRATEGY, 12206 Z_DEFLATED: Z_DEFLATED$1 12207 } = constants$2; 12208 /* ===========================================================================*/ 12209 12210 /** 12211 * class Deflate 12212 * 12213 * Generic JS-style wrapper for zlib calls. If you don't need 12214 * streaming behaviour - use more simple functions: [[deflate]], 12215 * [[deflateRaw]] and [[gzip]]. 12216 **/ 12217 12218 /* internal 12219 * Deflate.chunks -> Array 12220 * 12221 * Chunks of output data, if [[Deflate#onData]] not overridden. 12222 **/ 12223 12224 /** 12225 * Deflate.result -> Uint8Array 12226 * 12227 * Compressed result, generated by default [[Deflate#onData]] 12228 * and [[Deflate#onEnd]] handlers. Filled after you push last chunk 12229 * (call [[Deflate#push]] with `Z_FINISH` / `true` param). 12230 **/ 12231 12232 /** 12233 * Deflate.err -> Number 12234 *
12235 * Error code after deflate finished. 0 (Z_OK) on success. 12236 * You will not need it in real life, because deflate errors 12237 * are possible only on wrong options or bad `onData` / `onEnd` 12238 * custom handlers. 12239 **/ 12240 12241 /** 12242 * Deflate.msg -> String 12243 * 12244 * Error message, if [[Deflate.err]] != 0 12245 **/ 12246 12247 /** 12248 * new Deflate(options) 12249 * - options (Object): zlib deflate options. 12250 * 12251 * Creates new deflator instance with specified params. Throws exception 12252 * on bad params. Supported options: 12253 * 12254 * - `level` 12255 * - `windowBits` 12256 * - `memLevel` 12257 * - `strategy` 12258 * - `dictionary` 12259 * 12260 * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced) 12261 * for more information on these. 12262 * 12263 * Additional options, for internal needs: 12264 * 12265 * - `chunkSize` - size of generated data chunks (16K by default) 12266 * - `raw` (Boolean) - do raw deflate 12267 * - `gzip` (Boolean) - create gzip wrapper 12268 * - `header` (Object) - custom header for gzip 12269 * - `text` (Boolean) - true if compressed data believed to be text 12270 * - `time` (Number) - modification time, unix timestamp 12271 * - `os` (Number) - operation system code 12272 * - `extra` (Array) - array of bytes with extra data (max 65536) 12273 * - `name` (String) - file name (binary string) 12274 * - `comment` (String) - comment (binary string) 12275 * - `hcrc` (Boolean) - true if header crc should be added 12276 * 12277 * ##### Example: 12278 * 12279 * ```javascript 12280 * const pako = require('pako') 12281 * , chunk1 = new Uint8Array([1,2,3,4,5,6,7,8,9]) 12282 * , chunk2 = new Uint8Array([10,11,12,13,14,15,16,17,18,19]); 12283 * 12284 * const deflate = new pako.Deflate({ level: 3}); 12285 * 12286 * deflate.push(chunk1, false); 12287 * deflate.push(chunk2, true); // true -> last chunk 12288 * 12289 * if (deflate.err) { throw new Error(deflate.err); } 12290 * 12291 * console.log(deflate.result); 12292 * ``` 12293 **/ 12294 12295 function Deflate$1(options) { 12296 this.options = common.assign({ 12297 level: Z_DEFAULT_COMPRESSION, 12298 method: Z_DEFLATED$1, 12299 chunkSize: 16384, 12300 windowBits: 15, 12301 memLevel: 8, 12302 strategy: Z_DEFAULT_STRATEGY 12303 }, options || {}); 12304 let opt = this.options; 12305 12306 if (opt.raw && opt.windowBits > 0) { 12307 opt.windowBits = -opt.windowBits; 12308 } else if (opt.gzip && opt.windowBits > 0 && opt.windowBits < 16) { 12309 opt.windowBits += 16; 12310 } 12311 12312 this.err = 0; // error code, if happens (0 = Z_OK) 12313 12314 this.msg = ''; // error message 12315 12316 this.ended = false; // used to avoid multiple onEnd() calls 12317 12318 this.chunks = []; // chunks of compressed data 12319 12320 this.strm = new zstream(); 12321 this.strm.avail_out = 0; 12322 let status = deflate_1$2.deflateInit2(this.strm, opt.level, opt.method, opt.windowBits, opt.memLevel, opt.strategy); 12323 12324 if (status !== Z_OK$2) { 12325 throw new Error(messages[status]); 12326 } 12327 12328 if (opt.header) { 12329 deflate_1$2.deflateSetHeader(this.strm, opt.header); 12330 } 12331 12332 if (opt.dictionary) { 12333 let dict; // Convert data if needed 12334 12335 if (typeof opt.dictionary === 'string') { 12336 // If we need to compress text, change encoding to utf8. 12337 dict = strings.string2buf(opt.dictionary); 12338 } else if (toString$1$1.call(opt.dictionary) === '[object ArrayBuffer]') { 12339 dict = new Uint8Array(opt.dictionary); 12340 } else { 12341 dict = opt.dictionary; 12342 } 12343 12344 status = deflate_1$2.deflateSetDictionary(this.strm, dict); 12345 12346 if (status !== Z_OK$2) { 12347 throw new Error(messages[status]); 12348 } 12349 12350 this._dict_set = true; 12351 } 12352 } 12353 /** 12354 * Deflate#push(data[, flush_mode]) -> Boolean 12355 * - data (Uint8Array|ArrayBuffer|String): input data. Strings will be 12356 * converted to utf8 byte sequence. 12357 * - flush_mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE modes. 12358 * See constants. Skipped or `false` means Z_NO_FLUSH, `true` means Z_FINISH. 12359 * 12360 * Sends input data to deflate pipe, generating [[Deflate#onData]] calls with 12361 * new compressed chunks. Returns `true` on success. The last data block must 12362 * have `flush_mode` Z_FINISH (or `true`). That will flush internal pending 12363 * buffers and call [[Deflate#onEnd]]. 12364 * 12365 * On fail call [[Deflate#onEnd]] with error code and return false. 12366 * 12367 * ##### Example 12368 * 12369 * ```javascript 12370 * push(chunk, false); // push one of data chunks 12371 * ... 12372 * push(chunk, true); // push last chunk 12373 * ``` 12374 **/ 12375 12376 12377 Deflate$1.prototype.push = function (data, flush_mode) { 12378 const strm = this.strm; 12379 const chunkSize = this.options.chunkSize; 12380 12381 let status, _flush_mode; 12382 12383 if (this.ended) { 12384 return false;
vendor: 24,702 bytes, lines 12385-13139
12385 } 12386 12387 if (flush_mode === ~~flush_mode) _flush_mode = flush_mode;else _flush_mode = flush_mode === true ? Z_FINISH$2 : Z_NO_FLUSH$1; // Convert data if needed 12388 12389 if (typeof data === 'string') { 12390 // If we need to compress text, change encoding to utf8. 12391 strm.input = strings.string2buf(data); 12392 } else if (toString$1$1.call(data) === '[object ArrayBuffer]') { 12393 strm.input = new Uint8Array(data); 12394 } else { 12395 strm.input = data; 12396 } 12397 12398 strm.next_in = 0; 12399 strm.avail_in = strm.input.length; 12400 12401 for (;;) { 12402 if (strm.avail_out === 0) { 12403 strm.output = new Uint8Array(chunkSize); 12404 strm.next_out = 0; 12405 strm.avail_out = chunkSize; 12406 } // Make sure avail_out > 6 to avoid repeating markers 12407 12408 12409 if ((_flush_mode === Z_SYNC_FLUSH || _flush_mode === Z_FULL_FLUSH) && strm.avail_out <= 6) { 12410 this.onData(strm.output.subarray(0, strm.next_out)); 12411 strm.avail_out = 0; 12412 continue; 12413 } 12414 12415 status = deflate_1$2.deflate(strm, _flush_mode); // Ended => flush and finish 12416 12417 if (status === Z_STREAM_END$2) { 12418 if (strm.next_out > 0) { 12419 this.onData(strm.output.subarray(0, strm.next_out)); 12420 } 12421 12422 status = deflate_1$2.deflateEnd(this.strm); 12423 this.onEnd(status); 12424 this.ended = true; 12425 return status === Z_OK$2; 12426 } // Flush if out buffer full 12427 12428 12429 if (strm.avail_out === 0) { 12430 this.onData(strm.output); 12431 continue; 12432 } // Flush if requested and has data 12433 12434 12435 if (_flush_mode > 0 && strm.next_out > 0) { 12436 this.onData(strm.output.subarray(0, strm.next_out)); 12437 strm.avail_out = 0; 12438 continue; 12439 } 12440 12441 if (strm.avail_in === 0) break; 12442 } 12443 12444 return true; 12445 }; 12446 /** 12447 * Deflate#onData(chunk) -> Void 12448 * - chunk (Uint8Array): output data. 12449 * 12450 * By default, stores data blocks in `chunks[]` property and glue 12451 * those in `onEnd`. Override this handler, if you need another behaviour. 12452 **/ 12453 12454 12455 Deflate$1.prototype.onData = function (chunk) { 12456 this.chunks.push(chunk); 12457 }; 12458 /** 12459 * Deflate#onEnd(status) -> Void 12460 * - status (Number): deflate status. 0 (Z_OK) on success, 12461 * other if not. 12462 * 12463 * Called once after you tell deflate that the input stream is 12464 * complete (Z_FINISH). By default - join collected chunks, 12465 * free memory and fill `results` / `err` properties. 12466 **/ 12467 12468 12469 Deflate$1.prototype.onEnd = function (status) { 12470 // On success - join 12471 if (status === Z_OK$2) { 12472 this.result = common.flattenChunks(this.chunks); 12473 } 12474 12475 this.chunks = []; 12476 this.err = status; 12477 this.msg = this.strm.msg; 12478 }; 12479 /** 12480 * deflate(data[, options]) -> Uint8Array 12481 * - data (Uint8Array|String): input data to compress. 12482 * - options (Object): zlib deflate options. 12483 * 12484 * Compress `data` with deflate algorithm and `options`. 12485 * 12486 * Supported options are: 12487 * 12488 * - level 12489 * - windowBits 12490 * - memLevel 12491 * - strategy 12492 * - dictionary 12493 * 12494 * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced) 12495 * for more information on these. 12496 * 12497 * Sugar (options): 12498 * 12499 * - `raw` (Boolean) - say that we work with raw stream, if you don't wish to specify 12500 * negative windowBits implicitly. 12501 * 12502 * ##### Example: 12503 * 12504 * ```javascript 12505 * const pako = require('pako') 12506 * const data = new Uint8Array([1,2,3,4,5,6,7,8,9]); 12507 * 12508 * console.log(pako.deflate(data)); 12509 * ``` 12510 **/ 12511 12512 12513 function deflate$1(input, options) { 12514 const deflator = new Deflate$1(options); 12515 deflator.push(input, true); // That will never happens, if you don't cheat with options :) 12516 12517 if (deflator.err) { 12518 throw deflator.msg || messages[deflator.err]; 12519 } 12520 12521 return deflator.result; 12522 } 12523 /** 12524 * deflateRaw(data[, options]) -> Uint8Array 12525 * - data (Uint8Array|String): input data to compress. 12526 * - options (Object): zlib deflate options. 12527 * 12528 * The same as [[deflate]], but creates raw data, without wrapper 12529 * (header and adler32 crc). 12530 **/ 12531 12532 12533 function deflateRaw$1(input, options) { 12534 options = options || {}; 12535 options.raw = true; 12536 return deflate$1(input, options); 12537 } 12538 /** 12539 * gzip(data[, options]) -> Uint8Array 12540 * - data (Uint8Array|String): input data to compress. 12541 * - options (Object): zlib deflate options. 12542 * 12543 * The same as [[deflate]], but create gzip wrapper instead of 12544 * deflate one. 12545 **/ 12546 12547 12548 function gzip$1(input, options) { 12549 options = options || {}; 12550 options.gzip = true; 12551 return deflate$1(input, options); 12552 } 12553 12554 var Deflate_1$1 = Deflate$1; 12555 var deflate_2 = deflate$1; 12556 var deflateRaw_1$1 = deflateRaw$1; 12557 var gzip_1$1 = gzip$1; 12558 var constants$1 = constants$2; 12559 var deflate_1$1 = { 12560 Deflate: Deflate_1$1, 12561 deflate: deflate_2, 12562 deflateRaw: deflateRaw_1$1, 12563 gzip: gzip_1$1, 12564 constants: constants$1 12565 }; // (C) 1995-2013 Jean-loup Gailly and Mark Adler 12566 // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin 12567 // 12568 // This software is provided 'as-is', without any express or implied 12569 // warranty. In no event will the authors be held liable for any damages 12570 // arising from the use of this software. 12571 // 12572 // Permission is granted to anyone to use this software for any purpose, 12573 // including commercial applications, and to alter it and redistribute it 12574 // freely, subject to the following restrictions: 12575 // 12576 // 1. The origin of this software must not be misrepresented; you must not 12577 // claim that you wrote the original software. If you use this software 12578 // in a product, an acknowledgment in the product documentation would be 12579 // appreciated but is not required. 12580 // 2. Altered source versions must be plainly marked as such, and must not be 12581 // misrepresented as being the original software. 12582 // 3. This notice may not be removed or altered from any source distribution. 12583 // See state defs from inflate.js 12584 12585 const BAD$1 = 30; 12586 /* got a data error -- remain here until reset */ 12587 12588 const TYPE$1 = 12; 12589 /* i: waiting for type bits, including last-flag bit */ 12590 12591 /* 12592 Decode literal, length, and distance codes and write out the resulting 12593 literal and match bytes until either not enough input or output is 12594 available, an end-of-block is encountered, or a data error is encountered. 12595 When large enough input and output buffers are supplied to inflate(), for 12596 example, a 16K input buffer and a 64K output buffer, more than 95% of the 12597 inflate execution time is spent in this routine. 12598 Entry assumptions: 12599 state.mode === LEN 12600 strm.avail_in >= 6 12601 strm.avail_out >= 258 12602 start >= strm.avail_out 12603 state.bits < 8 12604 On return, state.mode is one of: 12605 LEN -- ran out of enough output space or enough available input 12606 TYPE -- reached end of block code, inflate() to interpret next block 12607 BAD -- error in block data 12608 Notes: 12609 - The maximum input bits used by a length/distance pair is 15 bits for the 12610 length code, 5 bits for the length extra, 15 bits for the distance code, 12611 and 13 bits for the distance extra. This totals 48 bits, or six bytes. 12612 Therefore if strm.avail_in >= 6, then there is enough input to avoid 12613 checking for available input while decoding. 12614 - The maximum bytes that a single length/distance pair can output is 258 12615 bytes, which is the maximum length that can be coded. inflate_fast() 12616 requires strm.avail_out >= 258 for each loop to avoid checking for 12617 output space. 12618 */ 12619 12620 var inffast = function inflate_fast(strm, start) { 12621 let _in; 12622 /* local strm.input */ 12623 12624 12625 let last; 12626 /* have enough input while in < last */ 12627 12628 let _out; 12629 /* local strm.output */ 12630 12631 12632 let beg; 12633 /* inflate()'s initial strm.output */ 12634 12635 let end; 12636 /* while out < end, enough space available */ 12637 //#ifdef INFLATE_STRICT 12638 12639 let dmax; 12640 /* maximum distance from zlib header */ 12641 //#endif 12642 12643 let wsize; 12644 /* window size or zero if not using window */ 12645 12646 let whave; 12647 /* valid bytes in the window */ 12648 12649 let wnext; 12650 /* window write index */ 12651 // Use `s_window` instead `window`, avoid conflict with instrumentation tools 12652 12653 let s_window; 12654 /* allocated sliding window, if wsize != 0 */ 12655 12656 let hold; 12657 /* local strm.hold */ 12658 12659 let bits; 12660 /* local strm.bits */ 12661 12662 let lcode; 12663 /* local strm.lencode */ 12664 12665 let dcode; 12666 /* local strm.distcode */ 12667 12668 let lmask; 12669 /* mask for first level of length codes */ 12670 12671 let dmask; 12672 /* mask for first level of distance codes */ 12673 12674 let here; 12675 /* retrieved table entry */ 12676 12677 let op; 12678 /* code bits, operation, extra bits, or */ 12679 12680 /* window position, window bytes to copy */ 12681 12682 let len; 12683 /* match length, unused bytes */ 12684 12685 let dist; 12686 /* match distance */ 12687 12688 let from; 12689 /* where to copy match from */ 12690 12691 let from_source; 12692 let input, output; // JS specific, because we have no pointers 12693 12694 /* copy state to local variables */ 12695 12696 const state = strm.state; //here = state.here; 12697 12698 _in = strm.next_in; 12699 input = strm.input; 12700 last = _in + (strm.avail_in - 5); 12701 _out = strm.next_out; 12702 output = strm.output; 12703 beg = _out - (start - strm.avail_out); 12704 end = _out + (strm.avail_out - 257); //#ifdef INFLATE_STRICT 12705 12706 dmax = state.dmax; //#endif 12707 12708 wsize = state.wsize; 12709 whave = state.whave; 12710 wnext = state.wnext; 12711 s_window = state.window; 12712 hold = state.hold; 12713 bits = state.bits; 12714 lcode = state.lencode; 12715 dcode = state.distcode; 12716 lmask = (1 << state.lenbits) - 1; 12717 dmask = (1 << state.distbits) - 1; 12718 /* decode literals and length/distances until end-of-block or not enough 12719 input data or output space */ 12720 12721 top: do { 12722 if (bits < 15) { 12723 hold += input[_in++] << bits; 12724 bits += 8; 12725 hold += input[_in++] << bits; 12726 bits += 8; 12727 } 12728 12729 here = lcode[hold & lmask]; 12730 12731 dolen: for (;;) { 12732 // Goto emulation 12733 op = here >>> 24 12734 /*here.bits*/ 12735 ; 12736 hold >>>= op; 12737 bits -= op; 12738 op = here >>> 16 & 0xff 12739 /*here.op*/ 12740 ; 12741 12742 if (op === 0) { 12743 /* literal */ 12744 //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? 12745 // "inflate: literal '%c'\n" : 12746 // "inflate: literal 0x%02x\n", here.val)); 12747 output[_out++] = here & 0xffff 12748 /*here.val*/ 12749 ; 12750 } else if (op & 16) { 12751 /* length base */ 12752 len = here & 0xffff 12753 /*here.val*/ 12754 ; 12755 op &= 15; 12756 /* number of extra bits */ 12757 12758 if (op) { 12759 if (bits < op) { 12760 hold += input[_in++] << bits; 12761 bits += 8; 12762 } 12763 12764 len += hold & (1 << op) - 1; 12765 hold >>>= op; 12766 bits -= op; 12767 } //Tracevv((stderr, "inflate: length %u\n", len)); 12768 12769 12770 if (bits < 15) { 12771 hold += input[_in++] << bits; 12772 bits += 8; 12773 hold += input[_in++] << bits; 12774 bits += 8; 12775 } 12776 12777 here = dcode[hold & dmask]; 12778 12779 dodist: for (;;) { 12780 // goto emulation 12781 op = here >>> 24 12782 /*here.bits*/ 12783 ; 12784 hold >>>= op; 12785 bits -= op; 12786 op = here >>> 16 & 0xff 12787 /*here.op*/ 12788 ; 12789 12790 if (op & 16) { 12791 /* distance base */ 12792 dist = here & 0xffff 12793 /*here.val*/ 12794 ; 12795 op &= 15; 12796 /* number of extra bits */ 12797 12798 if (bits < op) { 12799 hold += input[_in++] << bits; 12800 bits += 8; 12801 12802 if (bits < op) { 12803 hold += input[_in++] << bits; 12804 bits += 8; 12805 } 12806 } 12807 12808 dist += hold & (1 << op) - 1; //#ifdef INFLATE_STRICT 12809 12810 if (dist > dmax) { 12811 strm.msg = 'invalid distance too far back'; 12812 state.mode = BAD$1; 12813 break top; 12814 } //#endif 12815 12816 12817 hold >>>= op; 12818 bits -= op; //Tracevv((stderr, "inflate: distance %u\n", dist)); 12819 12820 op = _out - beg; 12821 /* max distance in output */ 12822 12823 if (dist > op) { 12824 /* see if copy from window */ 12825 op = dist - op; 12826 /* distance back in window */ 12827 12828 if (op > whave) { 12829 if (state.sane) { 12830 strm.msg = 'invalid distance too far back'; 12831 state.mode = BAD$1; 12832 break top; 12833 } // (!) This block is disabled in zlib defaults, 12834 // don't enable it for binary compatibility 12835 //#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR 12836 // if (len <= op - whave) { 12837 // do { 12838 // output[_out++] = 0; 12839 // } while (--len); 12840 // continue top; 12841 // } 12842 // len -= op - whave; 12843 // do { 12844 // output[_out++] = 0; 12845 // } while (--op > whave); 12846 // if (op === 0) { 12847 // from = _out - dist; 12848 // do { 12849 // output[_out++] = output[from++]; 12850 // } while (--len); 12851 // continue top; 12852 // } 12853 //#endif 12854 12855 } 12856 12857 from = 0; // window index 12858 12859 from_source = s_window; 12860 12861 if (wnext === 0) { 12862 /* very common case */ 12863 from += wsize - op; 12864 12865 if (op < len) { 12866 /* some from window */ 12867 len -= op; 12868 12869 do { 12870 output[_out++] = s_window[from++]; 12871 } while (--op); 12872 12873 from = _out - dist; 12874 /* rest from output */ 12875 12876 from_source = output; 12877 } 12878 } else if (wnext < op) { 12879 /* wrap around window */ 12880 from += wsize + wnext - op; 12881 op -= wnext; 12882 12883 if (op < len) { 12884 /* some from end of window */ 12885 len -= op; 12886 12887 do { 12888 output[_out++] = s_window[from++]; 12889 } while (--op); 12890 12891 from = 0; 12892 12893 if (wnext < len) { 12894 /* some from start of window */ 12895 op = wnext; 12896 len -= op; 12897 12898 do { 12899 output[_out++] = s_window[from++]; 12900 } while (--op); 12901 12902 from = _out - dist; 12903 /* rest from output */ 12904 12905 from_source = output; 12906 } 12907 } 12908 } else { 12909 /* contiguous in window */ 12910 from += wnext - op; 12911 12912 if (op < len) { 12913 /* some from window */ 12914 len -= op; 12915 12916 do { 12917 output[_out++] = s_window[from++]; 12918 } while (--op); 12919 12920 from = _out - dist; 12921 /* rest from output */ 12922 12923 from_source = output; 12924 } 12925 } 12926 12927 while (len > 2) { 12928 output[_out++] = from_source[from++]; 12929 output[_out++] = from_source[from++]; 12930 output[_out++] = from_source[from++]; 12931 len -= 3; 12932 } 12933 12934 if (len) { 12935 output[_out++] = from_source[from++]; 12936 12937 if (len > 1) { 12938 output[_out++] = from_source[from++]; 12939 } 12940 } 12941 } else { 12942 from = _out - dist; 12943 /* copy direct from output */ 12944 12945 do { 12946 /* minimum length is three */ 12947 output[_out++] = output[from++]; 12948 output[_out++] = output[from++]; 12949 output[_out++] = output[from++]; 12950 len -= 3; 12951 } while (len > 2); 12952 12953 if (len) { 12954 output[_out++] = output[from++]; 12955 12956 if (len > 1) { 12957 output[_out++] = output[from++]; 12958 } 12959 } 12960 } 12961 } else if ((op & 64) === 0) { 12962 /* 2nd level distance code */ 12963 here = dcode[(here & 0xffff 12964 /*here.val*/ 12965 ) + (hold & (1 << op) - 1)]; 12966 continue dodist; 12967 } else { 12968 strm.msg = 'invalid distance code'; 12969 state.mode = BAD$1; 12970 break top; 12971 } 12972 12973 break; // need to emulate goto via "continue" 12974 } 12975 } else if ((op & 64) === 0) { 12976 /* 2nd level length code */ 12977 here = lcode[(here & 0xffff 12978 /*here.val*/ 12979 ) + (hold & (1 << op) - 1)]; 12980 continue dolen; 12981 } else if (op & 32) { 12982 /* end-of-block */ 12983 //Tracevv((stderr, "inflate: end of block\n")); 12984 state.mode = TYPE$1; 12985 break top; 12986 } else { 12987 strm.msg = 'invalid literal/length code'; 12988 state.mode = BAD$1; 12989 break top; 12990 } 12991 12992 break; // need to emulate goto via "continue" 12993 } 12994 } while (_in < last && _out < end); 12995 /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ 12996 12997 12998 len = bits >> 3; 12999 _in -= len; 13000 bits -= len << 3; 13001 hold &= (1 << bits) - 1; 13002 /* update state and return */ 13003 13004 strm.next_in = _in; 13005 strm.next_out = _out; 13006 strm.avail_in = _in < last ? 5 + (last - _in) : 5 - (_in - last); 13007 strm.avail_out = _out < end ? 257 + (end - _out) : 257 - (_out - end); 13008 state.hold = hold; 13009 state.bits = bits; 13010 return; 13011 }; // (C) 1995-2013 Jean-loup Gailly and Mark Adler 13012 // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin 13013 // 13014 // This software is provided 'as-is', without any express or implied 13015 // warranty. In no event will the authors be held liable for any damages 13016 // arising from the use of this software. 13017 // 13018 // Permission is granted to anyone to use this software for any purpose, 13019 // including commercial applications, and to alter it and redistribute it 13020 // freely, subject to the following restrictions: 13021 // 13022 // 1. The origin of this software must not be misrepresented; you must not 13023 // claim that you wrote the original software. If you use this software 13024 // in a product, an acknowledgment in the product documentation would be 13025 // appreciated but is not required. 13026 // 2. Altered source versions must be plainly marked as such, and must not be 13027 // misrepresented as being the original software. 13028 // 3. This notice may not be removed or altered from any source distribution. 13029 13030 13031 const MAXBITS = 15; 13032 const ENOUGH_LENS$1 = 852; 13033 const ENOUGH_DISTS$1 = 592; //const ENOUGH = (ENOUGH_LENS+ENOUGH_DISTS); 13034 13035 const CODES$1 = 0; 13036 const LENS$1 = 1; 13037 const DISTS$1 = 2; 13038 const lbase = new Uint16Array([ 13039 /* Length codes 257..285 base */ 13040 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0]); 13041 const lext = new Uint8Array([ 13042 /* Length codes 257..285 extra */ 13043 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 78]); 13044 const dbase = new Uint16Array([ 13045 /* Distance codes 0..29 base */ 13046 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577, 0, 0]); 13047 const dext = new Uint8Array([ 13048 /* Distance codes 0..29 extra */ 13049 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 64, 64]); 13050 13051 const inflate_table = (type, lens, lens_index, codes, table, table_index, work, opts) => { 13052 const bits = opts.bits; //here = opts.here; /* table entry for duplication */ 13053 13054 let len = 0; 13055 /* a code's length in bits */ 13056 13057 let sym = 0; 13058 /* index of code symbols */ 13059 13060 let min = 0, 13061 max = 0; 13062 /* minimum and maximum code lengths */ 13063 13064 let root = 0; 13065 /* number of index bits for root table */ 13066 13067 let curr = 0; 13068 /* number of index bits for current table */ 13069 13070 let drop = 0; 13071 /* code bits to drop for sub-table */ 13072 13073 let left = 0; 13074 /* number of prefix codes available */ 13075 13076 let used = 0; 13077 /* code entries in table used */ 13078 13079 let huff = 0; 13080 /* Huffman code */ 13081 13082 let incr; 13083 /* for incrementing code, index */ 13084 13085 let fill; 13086 /* index for replicating entries */ 13087 13088 let low; 13089 /* low bits for current root entry */ 13090 13091 let mask; 13092 /* mask for low root bits */ 13093 13094 let next; 13095 /* next available space in table */ 13096 13097 let base = null; 13098 /* base value table to use */ 13099 13100 let base_index = 0; // let shoextra; /* extra bits table to use */ 13101 13102 let end; 13103 /* use base and extra for symbol > end */ 13104 13105 const count = new Uint16Array(MAXBITS + 1); //[MAXBITS+1]; /* number of codes of each length */ 13106 13107 const offs = new Uint16Array(MAXBITS + 1); //[MAXBITS+1]; /* offsets in table for each length */ 13108 13109 let extra = null; 13110 let extra_index = 0; 13111 let here_bits, here_op, here_val; 13112 /* 13113 Process a set of code lengths to create a canonical Huffman code. The 13114 code lengths are lens[0..codes-1]. Each length corresponds to the 13115 symbols 0..codes-1. The Huffman code is generated by first sorting the 13116 symbols by length from short to long, and retaining the symbol order 13117 for codes with equal lengths. Then the code starts with all zero bits 13118 for the first code of the shortest length, and the codes are integer 13119 increments for the same length, and zeros are appended as the length 13120 increases. For the deflate format, these bits are stored backwards 13121 from their more natural integer increment ordering, and so when the 13122 decoding tables are built in the large loop below, the integer codes 13123 are incremented backwards. 13124 This routine assumes, but does not check, that all of the entries in 13125 lens[] are in the range 0..MAXBITS. The caller must assure this. 13126 1..MAXBITS is interpreted as that code length. zero means that that 13127 symbol does not occur in this code. 13128 The codes are sorted by computing a count of codes for each length, 13129 creating from that a table of starting indices for each length in the 13130 sorted table, and then entering the symbols in order in the sorted 13131 table. The sorted table is work[], with that space being provided by 13132 the caller. 13133 The length counts are used for other purposes as well, i.e. finding 13134 the minimum and maximum length codes, determining if there are any 13135 codes at all, checking for a valid set of lengths, and looking ahead 13136 at length counts to determine sub-table sizes when building the 13137 decoding tables. 13138 */ 13139
vendor: 4,847 bytes, lines 13140-13297
13140 /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ 13141 13142 for (len = 0; len <= MAXBITS; len++) { 13143 count[len] = 0; 13144 } 13145 13146 for (sym = 0; sym < codes; sym++) { 13147 count[lens[lens_index + sym]]++; 13148 } 13149 /* bound code lengths, force root to be within code lengths */ 13150 13151 13152 root = bits; 13153 13154 for (max = MAXBITS; max >= 1; max--) { 13155 if (count[max] !== 0) { 13156 break; 13157 } 13158 } 13159 13160 if (root > max) { 13161 root = max; 13162 } 13163 13164 if (max === 0) { 13165 /* no symbols to code at all */ 13166 //table.op[opts.table_index] = 64; //here.op = (var char)64; /* invalid code marker */ 13167 //table.bits[opts.table_index] = 1; //here.bits = (var char)1; 13168 //table.val[opts.table_index++] = 0; //here.val = (var short)0; 13169 table[table_index++] = 1 << 24 | 64 << 16 | 0; //table.op[opts.table_index] = 64; 13170 //table.bits[opts.table_index] = 1; 13171 //table.val[opts.table_index++] = 0; 13172 13173 table[table_index++] = 1 << 24 | 64 << 16 | 0; 13174 opts.bits = 1; 13175 return 0; 13176 /* no symbols, but wait for decoding to report error */ 13177 } 13178 13179 for (min = 1; min < max; min++) { 13180 if (count[min] !== 0) { 13181 break; 13182 } 13183 } 13184 13185 if (root < min) { 13186 root = min; 13187 } 13188 /* check for an over-subscribed or incomplete set of lengths */ 13189 13190 13191 left = 1; 13192 13193 for (len = 1; len <= MAXBITS; len++) { 13194 left <<= 1; 13195 left -= count[len]; 13196 13197 if (left < 0) { 13198 return -1; 13199 } 13200 /* over-subscribed */ 13201 13202 } 13203 13204 if (left > 0 && (type === CODES$1 || max !== 1)) { 13205 return -1; 13206 /* incomplete set */ 13207 } 13208 /* generate offsets into symbol table for each length for sorting */ 13209 13210 13211 offs[1] = 0; 13212 13213 for (len = 1; len < MAXBITS; len++) { 13214 offs[len + 1] = offs[len] + count[len]; 13215 } 13216 /* sort symbols by length, by symbol order within each length */ 13217 13218 13219 for (sym = 0; sym < codes; sym++) { 13220 if (lens[lens_index + sym] !== 0) { 13221 work[offs[lens[lens_index + sym]]++] = sym; 13222 } 13223 } 13224 /* 13225 Create and fill in decoding tables. In this loop, the table being 13226 filled is at next and has curr index bits. The code being used is huff 13227 with length len. That code is converted to an index by dropping drop 13228 bits off of the bottom. For codes where len is less than drop + curr, 13229 those top drop + curr - len bits are incremented through all values to 13230 fill the table with replicated entries. 13231 root is the number of index bits for the root table. When len exceeds 13232 root, sub-tables are created pointed to by the root entry with an index 13233 of the low root bits of huff. This is saved in low to check for when a 13234 new sub-table should be started. drop is zero when the root table is 13235 being filled, and drop is root when sub-tables are being filled. 13236 When a new sub-table is needed, it is necessary to look ahead in the 13237 code lengths to determine what size sub-table is needed. The length 13238 counts are used for this, and so count[] is decremented as codes are 13239 entered in the tables. 13240 used keeps track of how many table entries have been allocated from the 13241 provided *table space. It is checked for LENS and DIST tables against 13242 the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in 13243 the initial root table size constants. See the comments in inftrees.h 13244 for more information. 13245 sym increments through all symbols, and the loop terminates when 13246 all codes of length max, i.e. all codes, have been processed. This 13247 routine permits incomplete codes, so another loop after this one fills 13248 in the rest of the decoding tables with invalid code markers. 13249 */ 13250 13251 /* set up for code type */ 13252 // poor man optimization - use if-else instead of switch, 13253 // to avoid deopts in old v8 13254 13255 13256 if (type === CODES$1) { 13257 base = extra = work; 13258 /* dummy value--not used */ 13259 13260 end = 19; 13261 } else if (type === LENS$1) { 13262 base = lbase; 13263 base_index -= 257; 13264 extra = lext; 13265 extra_index -= 257; 13266 end = 256; 13267 } else { 13268 /* DISTS */ 13269 base = dbase; 13270 extra = dext; 13271 end = -1; 13272 } 13273 /* initialize opts for loop */ 13274 13275 13276 huff = 0; 13277 /* starting code */ 13278 13279 sym = 0; 13280 /* starting code symbol */ 13281 13282 len = min; 13283 /* starting code length */ 13284 13285 next = table_index; 13286 /* current table to fill in */ 13287 13288 curr = root; 13289 /* current table index bits */ 13290 13291 drop = 0; 13292 /* current bits to drop from code for index */ 13293 13294 low = -1; 13295 /* trigger new sub-table when len > root */ 13296 13297 used = 1 << root;
13298 /* use root table entries */ 13299 13300 mask = used - 1; 13301 /* mask for comparing low */ 13302 13303 /* check available table space */ 13304 13305 if (type === LENS$1 && used > ENOUGH_LENS$1 || type === DISTS$1 && used > ENOUGH_DISTS$1) { 13306 return 1; 13307 } 13308 /* process all codes and make table entries */ 13309 13310 13311 for (;;) { 13312 /* create table entry */ 13313 here_bits = len - drop; 13314 13315 if (work[sym] < end) { 13316 here_op = 0; 13317 here_val = work[sym]; 13318 } else if (work[sym] > end) { 13319 here_op = extra[extra_index + work[sym]]; 13320 here_val = base[base_index + work[sym]]; 13321 } else { 13322 here_op = 32 + 64; 13323 /* end of block */ 13324 13325 here_val = 0; 13326 } 13327 /* replicate for those indices with low len bits equal to huff */ 13328 13329 13330 incr = 1 << len - drop; 13331 fill = 1 << curr; 13332 min = fill; 13333 /* save offset to next table */ 13334 13335 do { 13336 fill -= incr; 13337 table[next + (huff >> drop) + fill] = here_bits << 24 | here_op << 16 | here_val | 0; 13338 } while (fill !== 0); 13339 /* backwards increment the len-bit code huff */ 13340 13341 13342 incr = 1 << len - 1; 13343 13344 while (huff & incr) { 13345 incr >>= 1; 13346 } 13347 13348 if (incr !== 0) { 13349 huff &= incr - 1; 13350 huff += incr; 13351 } else { 13352 huff = 0; 13353 } 13354 /* go to next symbol, update count, len */ 13355 13356 13357 sym++; 13358 13359 if (--count[len] === 0) { 13360 if (len === max) { 13361 break; 13362 } 13363 13364 len = lens[lens_index + work[sym]]; 13365 } 13366 /* create new sub-table if needed */ 13367 13368 13369 if (len > root && (huff & mask) !== low) { 13370 /* if first time, transition to sub-tables */ 13371 if (drop === 0) { 13372 drop = root; 13373 } 13374 /* increment past last table */ 13375 13376 13377 next += min; 13378 /* here min is 1 << curr */ 13379 13380 /* determine length of next table */ 13381 13382 curr = len - drop; 13383 left = 1 << curr; 13384 13385 while (curr + drop < max) { 13386 left -= count[curr + drop]; 13387 13388 if (left <= 0) { 13389 break; 13390 } 13391 13392 curr++; 13393 left <<= 1; 13394 } 13395 /* check for enough space */ 13396 13397 13398 used += 1 << curr; 13399 13400 if (type === LENS$1 && used > ENOUGH_LENS$1 || type === DISTS$1 && used > ENOUGH_DISTS$1) { 13401 return 1; 13402 } 13403 /* point entry in root table to sub-table */ 13404 13405 13406 low = huff & mask; 13407 /*table.op[low] = curr; 13408 table.bits[low] = root; 13409 table.val[low] = next - opts.table_index;*/ 13410 13411 table[low] = root << 24 | curr << 16 | next - table_index | 0; 13412 } 13413 } 13414 /* fill in remaining table entry if code is incomplete (guaranteed to have 13415 at most one remaining entry, since if the code is incomplete, the 13416 maximum code length that was allowed to get this far is one bit) */ 13417 13418 13419 if (huff !== 0) { 13420 //table.op[next + huff] = 64; /* invalid code marker */ 13421 //table.bits[next + huff] = len - drop; 13422 //table.val[next + huff] = 0; 13423 table[next + huff] = len - drop << 24 | 64 << 16 | 0; 13424 } 13425 /* set return parameters */ 13426 //opts.table_index += used; 13427 13428 13429 opts.bits = root; 13430 return 0; 13431 }; 13432 13433 var inftrees = inflate_table; // (C) 1995-2013 Jean-loup Gailly and Mark Adler 13434 // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin 13435 // 13436 // This software is provided 'as-is', without any express or implied 13437 // warranty. In no event will the authors be held liable for any damages 13438 // arising from the use of this software. 13439 // 13440 // Permission is granted to anyone to use this software for any purpose, 13441 // including commercial applications, and to alter it and redistribute it 13442 // freely, subject to the following restrictions: 13443 // 13444 // 1. The origin of this software must not be misrepresented; you must not 13445 // claim that you wrote the original software. If you use this software 13446 // in a product, an acknowledgment in the product documentation would be 13447 // appreciated but is not required. 13448 // 2. Altered source versions must be plainly marked as such, and must not be 13449 // misrepresented as being the original software. 13450 // 3. This notice may not be removed or altered from any source distribution. 13451 13452 const CODES = 0; 13453 const LENS = 1; 13454 const DISTS = 2; 13455 /* Public constants ==========================================================*/ 13456 13457 /* ===========================================================================*/ 13458 13459 const { 13460 Z_FINISH: Z_FINISH$1, 13461 Z_BLOCK, 13462 Z_TREES, 13463 Z_OK: Z_OK$1, 13464 Z_STREAM_END: Z_STREAM_END$1, 13465 Z_NEED_DICT: Z_NEED_DICT$1, 13466 Z_STREAM_ERROR: Z_STREAM_ERROR$1, 13467 Z_DATA_ERROR: Z_DATA_ERROR$1, 13468 Z_MEM_ERROR: Z_MEM_ERROR$1,
vendor: 14,416 bytes, lines 13469-14029
13469 Z_BUF_ERROR, 13470 Z_DEFLATED 13471 } = constants$2; 13472 /* STATES ====================================================================*/ 13473 13474 /* ===========================================================================*/ 13475 13476 const HEAD = 1; 13477 /* i: waiting for magic header */ 13478 13479 const FLAGS = 2; 13480 /* i: waiting for method and flags (gzip) */ 13481 13482 const TIME = 3; 13483 /* i: waiting for modification time (gzip) */ 13484 13485 const OS = 4; 13486 /* i: waiting for extra flags and operating system (gzip) */ 13487 13488 const EXLEN = 5; 13489 /* i: waiting for extra length (gzip) */ 13490 13491 const EXTRA = 6; 13492 /* i: waiting for extra bytes (gzip) */ 13493 13494 const NAME$1 = 7; 13495 /* i: waiting for end of file name (gzip) */ 13496 13497 const COMMENT = 8; 13498 /* i: waiting for end of comment (gzip) */ 13499 13500 const HCRC = 9; 13501 /* i: waiting for header crc (gzip) */ 13502 13503 const DICTID = 10; 13504 /* i: waiting for dictionary check value */ 13505 13506 const DICT = 11; 13507 /* waiting for inflateSetDictionary() call */ 13508 13509 const TYPE = 12; 13510 /* i: waiting for type bits, including last-flag bit */ 13511 13512 const TYPEDO = 13; 13513 /* i: same, but skip check to exit inflate on new block */ 13514 13515 const STORED = 14; 13516 /* i: waiting for stored size (length and complement) */ 13517 13518 const COPY_ = 15; 13519 /* i/o: same as COPY below, but only first time in */ 13520 13521 const COPY = 16; 13522 /* i/o: waiting for input or output to copy stored block */ 13523 13524 const TABLE = 17; 13525 /* i: waiting for dynamic block table lengths */ 13526 13527 const LENLENS = 18; 13528 /* i: waiting for code length code lengths */ 13529 13530 const CODELENS = 19; 13531 /* i: waiting for length/lit and distance code lengths */ 13532 13533 const LEN_ = 20; 13534 /* i: same as LEN below, but only first time in */ 13535 13536 const LEN = 21; 13537 /* i: waiting for length/lit/eob code */ 13538 13539 const LENEXT = 22; 13540 /* i: waiting for length extra bits */ 13541 13542 const DIST = 23; 13543 /* i: waiting for distance code */ 13544 13545 const DISTEXT = 24; 13546 /* i: waiting for distance extra bits */ 13547 13548 const MATCH = 25; 13549 /* o: waiting for output space to copy string */ 13550 13551 const LIT = 26; 13552 /* o: waiting for output space to write literal */ 13553 13554 const CHECK = 27; 13555 /* i: waiting for 32-bit check value */ 13556 13557 const LENGTH = 28; 13558 /* i: waiting for 32-bit length (gzip) */ 13559 13560 const DONE = 29; 13561 /* finished check, done -- remain here until reset */ 13562 13563 const BAD = 30; 13564 /* got a data error -- remain here until reset */ 13565 13566 const MEM = 31; 13567 /* got an inflate() memory error -- remain here until reset */ 13568 13569 const SYNC = 32; 13570 /* looking for synchronization bytes to restart inflate() */ 13571 13572 /* ===========================================================================*/ 13573 13574 const ENOUGH_LENS = 852; 13575 const ENOUGH_DISTS = 592; //const ENOUGH = (ENOUGH_LENS+ENOUGH_DISTS); 13576 13577 const MAX_WBITS = 15; 13578 /* 32K LZ77 window */ 13579 13580 const DEF_WBITS = MAX_WBITS; 13581 13582 const zswap32 = q => { 13583 return (q >>> 24 & 0xff) + (q >>> 8 & 0xff00) + ((q & 0xff00) << 8) + ((q & 0xff) << 24); 13584 }; 13585 13586 function InflateState() { 13587 this.mode = 0; 13588 /* current inflate mode */ 13589 13590 this.last = false; 13591 /* true if processing last block */ 13592 13593 this.wrap = 0; 13594 /* bit 0 true for zlib, bit 1 true for gzip */ 13595 13596 this.havedict = false; 13597 /* true if dictionary provided */ 13598 13599 this.flags = 0; 13600 /* gzip header method and flags (0 if zlib) */ 13601 13602 this.dmax = 0; 13603 /* zlib header max distance (INFLATE_STRICT) */ 13604 13605 this.check = 0; 13606 /* protected copy of check value */ 13607 13608 this.total = 0; 13609 /* protected copy of output count */ 13610 // TODO: may be {} 13611 13612 this.head = null; 13613 /* where to save gzip header information */ 13614 13615 /* sliding window */ 13616 13617 this.wbits = 0; 13618 /* log base 2 of requested window size */ 13619 13620 this.wsize = 0; 13621 /* window size or zero if not using window */ 13622 13623 this.whave = 0; 13624 /* valid bytes in the window */ 13625 13626 this.wnext = 0; 13627 /* window write index */ 13628 13629 this.window = null; 13630 /* allocated sliding window, if needed */ 13631 13632 /* bit accumulator */ 13633 13634 this.hold = 0; 13635 /* input bit accumulator */ 13636 13637 this.bits = 0; 13638 /* number of bits in "in" */ 13639 13640 /* for string and stored block copying */ 13641 13642 this.length = 0; 13643 /* literal or length of data to copy */ 13644 13645 this.offset = 0; 13646 /* distance back to copy string from */ 13647 13648 /* for table and code decoding */ 13649 13650 this.extra = 0; 13651 /* extra bits needed */ 13652 13653 /* fixed and dynamic code tables */ 13654 13655 this.lencode = null; 13656 /* starting table for length/literal codes */ 13657 13658 this.distcode = null; 13659 /* starting table for distance codes */ 13660 13661 this.lenbits = 0; 13662 /* index bits for lencode */ 13663 13664 this.distbits = 0; 13665 /* index bits for distcode */ 13666 13667 /* dynamic table building */ 13668 13669 this.ncode = 0; 13670 /* number of code length code lengths */ 13671 13672 this.nlen = 0; 13673 /* number of length code lengths */ 13674 13675 this.ndist = 0; 13676 /* number of distance code lengths */ 13677 13678 this.have = 0; 13679 /* number of code lengths in lens[] */ 13680 13681 this.next = null; 13682 /* next available space in codes[] */ 13683 13684 this.lens = new Uint16Array(320); 13685 /* temporary storage for code lengths */ 13686 13687 this.work = new Uint16Array(288); 13688 /* work area for code table building */ 13689 13690 /* 13691 because we don't have pointers in js, we use lencode and distcode directly 13692 as buffers so we don't need codes 13693 */ 13694 //this.codes = new Int32Array(ENOUGH); /* space for code tables */ 13695 13696 this.lendyn = null; 13697 /* dynamic table for length/literal codes (JS specific) */ 13698 13699 this.distdyn = null; 13700 /* dynamic table for distance codes (JS specific) */ 13701 13702 this.sane = 0; 13703 /* if false, allow invalid distance too far */ 13704 13705 this.back = 0; 13706 /* bits back of last unprocessed length/lit */ 13707 13708 this.was = 0; 13709 /* initial length of match */ 13710 } 13711 13712 const inflateResetKeep = strm => { 13713 if (!strm || !strm.state) { 13714 return Z_STREAM_ERROR$1; 13715 } 13716 13717 const state = strm.state; 13718 strm.total_in = strm.total_out = state.total = 0; 13719 strm.msg = ''; 13720 /*Z_NULL*/ 13721 13722 if (state.wrap) { 13723 /* to support ill-conceived Java test suite */ 13724 strm.adler = state.wrap & 1; 13725 } 13726 13727 state.mode = HEAD; 13728 state.last = 0; 13729 state.havedict = 0; 13730 state.dmax = 32768; 13731 state.head = null 13732 /*Z_NULL*/ 13733 ; 13734 state.hold = 0; 13735 state.bits = 0; //state.lencode = state.distcode = state.next = state.codes; 13736 13737 state.lencode = state.lendyn = new Int32Array(ENOUGH_LENS); 13738 state.distcode = state.distdyn = new Int32Array(ENOUGH_DISTS); 13739 state.sane = 1; 13740 state.back = -1; //Tracev((stderr, "inflate: reset\n")); 13741 13742 return Z_OK$1; 13743 }; 13744 13745 const inflateReset = strm => { 13746 if (!strm || !strm.state) { 13747 return Z_STREAM_ERROR$1; 13748 } 13749 13750 const state = strm.state; 13751 state.wsize = 0; 13752 state.whave = 0; 13753 state.wnext = 0; 13754 return inflateResetKeep(strm); 13755 }; 13756 13757 const inflateReset2 = (strm, windowBits) => { 13758 let wrap; 13759 /* get the state */ 13760 13761 if (!strm || !strm.state) { 13762 return Z_STREAM_ERROR$1; 13763 } 13764 13765 const state = strm.state; 13766 /* extract wrap request from windowBits parameter */ 13767 13768 if (windowBits < 0) { 13769 wrap = 0; 13770 windowBits = -windowBits; 13771 } else { 13772 wrap = (windowBits >> 4) + 1; 13773 13774 if (windowBits < 48) { 13775 windowBits &= 15; 13776 } 13777 } 13778 /* set number of window bits, free window if different */ 13779 13780 13781 if (windowBits && (windowBits < 8 || windowBits > 15)) { 13782 return Z_STREAM_ERROR$1; 13783 } 13784 13785 if (state.window !== null && state.wbits !== windowBits) { 13786 state.window = null; 13787 } 13788 /* update state and reset the rest of it */ 13789 13790 13791 state.wrap = wrap; 13792 state.wbits = windowBits; 13793 return inflateReset(strm); 13794 }; 13795 13796 const inflateInit2 = (strm, windowBits) => { 13797 if (!strm) { 13798 return Z_STREAM_ERROR$1; 13799 } //strm.msg = Z_NULL; /* in case we return an error */ 13800 13801 13802 const state = new InflateState(); //if (state === Z_NULL) return Z_MEM_ERROR; 13803 //Tracev((stderr, "inflate: allocated\n")); 13804 13805 strm.state = state; 13806 state.window = null 13807 /*Z_NULL*/ 13808 ; 13809 const ret = inflateReset2(strm, windowBits); 13810 13811 if (ret !== Z_OK$1) { 13812 strm.state = null 13813 /*Z_NULL*/ 13814 ; 13815 } 13816 13817 return ret; 13818 }; 13819 13820 const inflateInit = strm => { 13821 return inflateInit2(strm, DEF_WBITS); 13822 }; 13823 /* 13824 Return state with length and distance decoding tables and index sizes set to 13825 fixed code decoding. Normally this returns fixed tables from inffixed.h. 13826 If BUILDFIXED is defined, then instead this routine builds the tables the 13827 first time it's called, and returns those tables the first time and 13828 thereafter. This reduces the size of the code by about 2K bytes, in 13829 exchange for a little execution time. However, BUILDFIXED should not be 13830 used for threaded applications, since the rewriting of the tables and virgin 13831 may not be thread-safe. 13832 */ 13833 13834 13835 let virgin = true; 13836 let lenfix, distfix; // We have no pointers in JS, so keep tables separate 13837 13838 const fixedtables = state => { 13839 /* build fixed huffman tables if first call (may not be thread safe) */ 13840 if (virgin) { 13841 lenfix = new Int32Array(512); 13842 distfix = new Int32Array(32); 13843 /* literal/length table */ 13844 13845 let sym = 0; 13846 13847 while (sym < 144) { 13848 state.lens[sym++] = 8; 13849 } 13850 13851 while (sym < 256) { 13852 state.lens[sym++] = 9; 13853 } 13854 13855 while (sym < 280) { 13856 state.lens[sym++] = 7; 13857 } 13858 13859 while (sym < 288) { 13860 state.lens[sym++] = 8; 13861 } 13862 13863 inftrees(LENS, state.lens, 0, 288, lenfix, 0, state.work, { 13864 bits: 9 13865 }); 13866 /* distance table */ 13867 13868 sym = 0; 13869 13870 while (sym < 32) { 13871 state.lens[sym++] = 5; 13872 } 13873 13874 inftrees(DISTS, state.lens, 0, 32, distfix, 0, state.work, { 13875 bits: 5 13876 }); 13877 /* do this just once */ 13878 13879 virgin = false; 13880 } 13881 13882 state.lencode = lenfix; 13883 state.lenbits = 9; 13884 state.distcode = distfix; 13885 state.distbits = 5; 13886 }; 13887 /* 13888 Update the window with the last wsize (normally 32K) bytes written before 13889 returning. If window does not exist yet, create it. This is only called 13890 when a window is already in use, or when output has been written during this 13891 inflate call, but the end of the deflate stream has not been reached yet. 13892 It is also called to create a window for dictionary data when a dictionary 13893 is loaded. 13894 Providing output buffers larger than 32K to inflate() should provide a speed 13895 advantage, since only the last 32K of output is copied to the sliding window 13896 upon return from inflate(), and since all distances after the first 32K of 13897 output will fall in the output data, making match copies simpler and faster. 13898 The advantage may be dependent on the size of the processor's data caches. 13899 */ 13900 13901 13902 const updatewindow = (strm, src, end, copy) => { 13903 let dist; 13904 const state = strm.state; 13905 /* if it hasn't been done already, allocate space for the window */ 13906 13907 if (state.window === null) { 13908 state.wsize = 1 << state.wbits; 13909 state.wnext = 0; 13910 state.whave = 0; 13911 state.window = new Uint8Array(state.wsize); 13912 } 13913 /* copy state->wsize or less output bytes into the circular window */ 13914 13915 13916 if (copy >= state.wsize) { 13917 state.window.set(src.subarray(end - state.wsize, end), 0); 13918 state.wnext = 0; 13919 state.whave = state.wsize; 13920 } else { 13921 dist = state.wsize - state.wnext; 13922 13923 if (dist > copy) { 13924 dist = copy; 13925 } //zmemcpy(state->window + state->wnext, end - copy, dist); 13926 13927 13928 state.window.set(src.subarray(end - copy, end - copy + dist), state.wnext); 13929 copy -= dist; 13930 13931 if (copy) { 13932 //zmemcpy(state->window, end - copy, copy); 13933 state.window.set(src.subarray(end - copy, end), 0); 13934 state.wnext = copy; 13935 state.whave = state.wsize; 13936 } else { 13937 state.wnext += dist; 13938 13939 if (state.wnext === state.wsize) { 13940 state.wnext = 0; 13941 } 13942 13943 if (state.whave < state.wsize) { 13944 state.whave += dist; 13945 } 13946 } 13947 } 13948 13949 return 0; 13950 }; 13951 13952 const inflate$2 = (strm, flush) => { 13953 let state; 13954 let input, output; // input/output buffers 13955 13956 let next; 13957 /* next input INDEX */ 13958 13959 let put; 13960 /* next output INDEX */ 13961 13962 let have, left; 13963 /* available input and output */ 13964 13965 let hold; 13966 /* bit buffer */ 13967 13968 let bits; 13969 /* bits in bit buffer */ 13970 13971 let _in, _out; 13972 /* save starting available input and output */ 13973 13974 13975 let copy; 13976 /* number of stored or match bytes to copy */ 13977 13978 let from; 13979 /* where to copy match bytes from */ 13980 13981 let from_source; 13982 let here = 0; 13983 /* current decoding table entry */ 13984 13985 let here_bits, here_op, here_val; // paked "here" denormalized (JS specific) 13986 //let last; /* parent table entry */ 13987 13988 let last_bits, last_op, last_val; // paked "last" denormalized (JS specific) 13989 13990 let len; 13991 /* length to copy for repeats, bits to drop */ 13992 13993 let ret; 13994 /* return code */ 13995 13996 const hbuf = new Uint8Array(4); 13997 /* buffer for gzip header crc calculation */ 13998 13999 let opts; 14000 let n; // temporary variable for NEED_BITS 14001 14002 const order = 14003 /* permutation of code lengths */ 14004 new Uint8Array([16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]); 14005 14006 if (!strm || !strm.state || !strm.output || !strm.input && strm.avail_in !== 0) { 14007 return Z_STREAM_ERROR$1; 14008 } 14009 14010 state = strm.state; 14011 14012 if (state.mode === TYPE) { 14013 state.mode = TYPEDO; 14014 } 14015 /* skip check */ 14016 //--- LOAD() --- 14017 14018 14019 put = strm.next_out; 14020 output = strm.output; 14021 left = strm.avail_out; 14022 next = strm.next_in; 14023 input = strm.input; 14024 have = strm.avail_in; 14025 hold = state.hold; 14026 bits = state.bits; //--- 14027 14028 _in = have; 14029 _out = left;
14030 ret = Z_OK$1; 14031 14032 inf_leave: // goto emulation 14033 for (;;) { 14034 switch (state.mode) { 14035 case HEAD: 14036 if (state.wrap === 0) { 14037 state.mode = TYPEDO; 14038 break; 14039 } //=== NEEDBITS(16); 14040 14041 14042 while (bits < 16) { 14043 if (have === 0) { 14044 break inf_leave; 14045 } 14046 14047 have--; 14048 hold += input[next++] << bits; 14049 bits += 8; 14050 } //===// 14051 14052 14053 if (state.wrap & 2 && hold === 0x8b1f) { 14054 /* gzip header */ 14055 state.check = 0 14056 /*crc32(0L, Z_NULL, 0)*/ 14057 ; //=== CRC2(state.check, hold); 14058 14059 hbuf[0] = hold & 0xff; 14060 hbuf[1] = hold >>> 8 & 0xff; 14061 state.check = crc32_1(state.check, hbuf, 2, 0); //===// 14062 //=== INITBITS(); 14063 14064 hold = 0; 14065 bits = 0; //===// 14066 14067 state.mode = FLAGS; 14068 break; 14069 } 14070 14071 state.flags = 0; 14072 /* expect zlib header */ 14073 14074 if (state.head) { 14075 state.head.done = false; 14076 } 14077 14078 if (!(state.wrap & 1) || 14079 /* check if zlib header allowed */ 14080 (((hold & 0xff 14081 /*BITS(8)*/ 14082 ) << 8) + (hold >> 8)) % 31) { 14083 strm.msg = 'incorrect header check'; 14084 state.mode = BAD; 14085 break; 14086 } 14087 14088 if ((hold & 0x0f 14089 /*BITS(4)*/ 14090 ) !== Z_DEFLATED) { 14091 strm.msg = 'unknown compression method'; 14092 state.mode = BAD; 14093 break; 14094 } //--- DROPBITS(4) ---// 14095 14096 14097 hold >>>= 4; 14098 bits -= 4; //---// 14099 14100 len = (hold & 0x0f 14101 /*BITS(4)*/ 14102 ) + 8; 14103 14104 if (state.wbits === 0) { 14105 state.wbits = len; 14106 } else if (len > state.wbits) { 14107 strm.msg = 'invalid window size'; 14108 state.mode = BAD; 14109 break; 14110 } // !!! pako patch. Force use `options.windowBits` if passed. 14111 // Required to always use max window size by default. 14112 14113 14114 state.dmax = 1 << state.wbits; //state.dmax = 1 << len; 14115 //Tracev((stderr, "inflate: zlib header ok\n")); 14116 14117 strm.adler = state.check = 1 14118 /*adler32(0L, Z_NULL, 0)*/ 14119 ; 14120 state.mode = hold & 0x200 ? DICTID : TYPE; //=== INITBITS(); 14121 14122 hold = 0; 14123 bits = 0; //===// 14124 14125 break; 14126 14127 case FLAGS: 14128 //=== NEEDBITS(16); */ 14129 while (bits < 16) { 14130 if (have === 0) { 14131 break inf_leave; 14132 } 14133 14134 have--; 14135 hold += input[next++] << bits; 14136 bits += 8; 14137 } //===// 14138 14139 14140 state.flags = hold; 14141 14142 if ((state.flags & 0xff) !== Z_DEFLATED) { 14143 strm.msg = 'unknown compression method'; 14144 state.mode = BAD; 14145 break; 14146 } 14147 14148 if (state.flags & 0xe000) { 14149 strm.msg = 'unknown header flags set'; 14150 state.mode = BAD; 14151 break; 14152 } 14153 14154 if (state.head) { 14155 state.head.text = hold >> 8 & 1; 14156 } 14157 14158 if (state.flags & 0x0200) { 14159 //=== CRC2(state.check, hold); 14160 hbuf[0] = hold & 0xff; 14161 hbuf[1] = hold >>> 8 & 0xff; 14162 state.check = crc32_1(state.check, hbuf, 2, 0); //===// 14163 } //=== INITBITS(); 14164 14165 14166 hold = 0; 14167 bits = 0; //===// 14168 14169 state.mode = TIME; 14170 14171 /* falls through */ 14172 14173 case TIME: 14174 //=== NEEDBITS(32); */ 14175 while (bits < 32) { 14176 if (have === 0) { 14177 break inf_leave; 14178 } 14179 14180 have--; 14181 hold += input[next++] << bits; 14182 bits += 8; 14183 } //===// 14184 14185 14186 if (state.head) { 14187 state.head.time = hold; 14188 } 14189 14190 if (state.flags & 0x0200) { 14191 //=== CRC4(state.check, hold) 14192 hbuf[0] = hold & 0xff;
vendor: 33,063 bytes, lines 14193-15392
14193 hbuf[1] = hold >>> 8 & 0xff; 14194 hbuf[2] = hold >>> 16 & 0xff; 14195 hbuf[3] = hold >>> 24 & 0xff; 14196 state.check = crc32_1(state.check, hbuf, 4, 0); //=== 14197 } //=== INITBITS(); 14198 14199 14200 hold = 0; 14201 bits = 0; //===// 14202 14203 state.mode = OS; 14204 14205 /* falls through */ 14206 14207 case OS: 14208 //=== NEEDBITS(16); */ 14209 while (bits < 16) { 14210 if (have === 0) { 14211 break inf_leave; 14212 } 14213 14214 have--; 14215 hold += input[next++] << bits; 14216 bits += 8; 14217 } //===// 14218 14219 14220 if (state.head) { 14221 state.head.xflags = hold & 0xff; 14222 state.head.os = hold >> 8; 14223 } 14224 14225 if (state.flags & 0x0200) { 14226 //=== CRC2(state.check, hold); 14227 hbuf[0] = hold & 0xff; 14228 hbuf[1] = hold >>> 8 & 0xff; 14229 state.check = crc32_1(state.check, hbuf, 2, 0); //===// 14230 } //=== INITBITS(); 14231 14232 14233 hold = 0; 14234 bits = 0; //===// 14235 14236 state.mode = EXLEN; 14237 14238 /* falls through */ 14239 14240 case EXLEN: 14241 if (state.flags & 0x0400) { 14242 //=== NEEDBITS(16); */ 14243 while (bits < 16) { 14244 if (have === 0) { 14245 break inf_leave; 14246 } 14247 14248 have--; 14249 hold += input[next++] << bits; 14250 bits += 8; 14251 } //===// 14252 14253 14254 state.length = hold; 14255 14256 if (state.head) { 14257 state.head.extra_len = hold; 14258 } 14259 14260 if (state.flags & 0x0200) { 14261 //=== CRC2(state.check, hold); 14262 hbuf[0] = hold & 0xff; 14263 hbuf[1] = hold >>> 8 & 0xff; 14264 state.check = crc32_1(state.check, hbuf, 2, 0); //===// 14265 } //=== INITBITS(); 14266 14267 14268 hold = 0; 14269 bits = 0; //===// 14270 } else if (state.head) { 14271 state.head.extra = null 14272 /*Z_NULL*/ 14273 ; 14274 } 14275 14276 state.mode = EXTRA; 14277 14278 /* falls through */ 14279 14280 case EXTRA: 14281 if (state.flags & 0x0400) { 14282 copy = state.length; 14283 14284 if (copy > have) { 14285 copy = have; 14286 } 14287 14288 if (copy) { 14289 if (state.head) { 14290 len = state.head.extra_len - state.length; 14291 14292 if (!state.head.extra) { 14293 // Use untyped array for more convenient processing later 14294 state.head.extra = new Uint8Array(state.head.extra_len); 14295 } 14296 14297 state.head.extra.set(input.subarray(next, // extra field is limited to 65536 bytes 14298 // - no need for additional size check 14299 next + copy), 14300 /*len + copy > state.head.extra_max - len ? state.head.extra_max : copy,*/ 14301 len); //zmemcpy(state.head.extra + len, next, 14302 // len + copy > state.head.extra_max ? 14303 // state.head.extra_max - len : copy); 14304 } 14305 14306 if (state.flags & 0x0200) { 14307 state.check = crc32_1(state.check, input, copy, next); 14308 } 14309 14310 have -= copy; 14311 next += copy; 14312 state.length -= copy; 14313 } 14314 14315 if (state.length) { 14316 break inf_leave; 14317 } 14318 } 14319 14320 state.length = 0; 14321 state.mode = NAME$1; 14322 14323 /* falls through */ 14324 14325 case NAME$1: 14326 if (state.flags & 0x0800) { 14327 if (have === 0) { 14328 break inf_leave; 14329 } 14330 14331 copy = 0; 14332 14333 do { 14334 // TODO: 2 or 1 bytes? 14335 len = input[next + copy++]; 14336 /* use constant limit because in js we should not preallocate memory */ 14337 14338 if (state.head && len && state.length < 65536 14339 /*state.head.name_max*/ 14340 ) { 14341 state.head.name += String.fromCharCode(len); 14342 } 14343 } while (len && copy < have); 14344 14345 if (state.flags & 0x0200) { 14346 state.check = crc32_1(state.check, input, copy, next); 14347 } 14348 14349 have -= copy; 14350 next += copy; 14351 14352 if (len) { 14353 break inf_leave; 14354 } 14355 } else if (state.head) { 14356 state.head.name = null; 14357 } 14358 14359 state.length = 0; 14360 state.mode = COMMENT; 14361 14362 /* falls through */ 14363 14364 case COMMENT: 14365 if (state.flags & 0x1000) { 14366 if (have === 0) { 14367 break inf_leave; 14368 } 14369 14370 copy = 0; 14371 14372 do { 14373 len = input[next + copy++]; 14374 /* use constant limit because in js we should not preallocate memory */ 14375 14376 if (state.head && len && state.length < 65536 14377 /*state.head.comm_max*/ 14378 ) { 14379 state.head.comment += String.fromCharCode(len); 14380 } 14381 } while (len && copy < have); 14382 14383 if (state.flags & 0x0200) { 14384 state.check = crc32_1(state.check, input, copy, next); 14385 } 14386 14387 have -= copy; 14388 next += copy; 14389 14390 if (len) { 14391 break inf_leave; 14392 } 14393 } else if (state.head) { 14394 state.head.comment = null; 14395 } 14396 14397 state.mode = HCRC; 14398 14399 /* falls through */ 14400 14401 case HCRC: 14402 if (state.flags & 0x0200) { 14403 //=== NEEDBITS(16); */ 14404 while (bits < 16) { 14405 if (have === 0) { 14406 break inf_leave; 14407 } 14408 14409 have--; 14410 hold += input[next++] << bits; 14411 bits += 8; 14412 } //===// 14413 14414 14415 if (hold !== (state.check & 0xffff)) { 14416 strm.msg = 'header crc mismatch'; 14417 state.mode = BAD; 14418 break; 14419 } //=== INITBITS(); 14420 14421 14422 hold = 0; 14423 bits = 0; //===// 14424 } 14425 14426 if (state.head) { 14427 state.head.hcrc = state.flags >> 9 & 1; 14428 state.head.done = true; 14429 } 14430 14431 strm.adler = state.check = 0; 14432 state.mode = TYPE; 14433 break; 14434 14435 case DICTID: 14436 //=== NEEDBITS(32); */ 14437 while (bits < 32) { 14438 if (have === 0) { 14439 break inf_leave; 14440 } 14441 14442 have--; 14443 hold += input[next++] << bits; 14444 bits += 8; 14445 } //===// 14446 14447 14448 strm.adler = state.check = zswap32(hold); //=== INITBITS(); 14449 14450 hold = 0; 14451 bits = 0; //===// 14452 14453 state.mode = DICT; 14454 14455 /* falls through */ 14456 14457 case DICT: 14458 if (state.havedict === 0) { 14459 //--- RESTORE() --- 14460 strm.next_out = put; 14461 strm.avail_out = left; 14462 strm.next_in = next; 14463 strm.avail_in = have; 14464 state.hold = hold; 14465 state.bits = bits; //--- 14466 14467 return Z_NEED_DICT$1; 14468 } 14469 14470 strm.adler = state.check = 1 14471 /*adler32(0L, Z_NULL, 0)*/ 14472 ; 14473 state.mode = TYPE; 14474 14475 /* falls through */ 14476 14477 case TYPE: 14478 if (flush === Z_BLOCK || flush === Z_TREES) { 14479 break inf_leave; 14480 } 14481 14482 /* falls through */ 14483 14484 case TYPEDO: 14485 if (state.last) { 14486 //--- BYTEBITS() ---// 14487 hold >>>= bits & 7; 14488 bits -= bits & 7; //---// 14489 14490 state.mode = CHECK; 14491 break; 14492 } //=== NEEDBITS(3); */ 14493 14494 14495 while (bits < 3) { 14496 if (have === 0) { 14497 break inf_leave; 14498 } 14499 14500 have--; 14501 hold += input[next++] << bits; 14502 bits += 8; 14503 } //===// 14504 14505 14506 state.last = hold & 0x01 14507 /*BITS(1)*/ 14508 ; //--- DROPBITS(1) ---// 14509 14510 hold >>>= 1; 14511 bits -= 1; //---// 14512 14513 switch (hold & 0x03 14514 /*BITS(2)*/ 14515 ) { 14516 case 0: 14517 /* stored block */ 14518 //Tracev((stderr, "inflate: stored block%s\n", 14519 // state.last ? " (last)" : "")); 14520 state.mode = STORED; 14521 break; 14522 14523 case 1: 14524 /* fixed block */ 14525 fixedtables(state); //Tracev((stderr, "inflate: fixed codes block%s\n", 14526 // state.last ? " (last)" : "")); 14527 14528 state.mode = LEN_; 14529 /* decode codes */ 14530 14531 if (flush === Z_TREES) { 14532 //--- DROPBITS(2) ---// 14533 hold >>>= 2; 14534 bits -= 2; //---// 14535 14536 break inf_leave; 14537 } 14538 14539 break; 14540 14541 case 2: 14542 /* dynamic block */ 14543 //Tracev((stderr, "inflate: dynamic codes block%s\n", 14544 // state.last ? " (last)" : "")); 14545 state.mode = TABLE; 14546 break; 14547 14548 case 3: 14549 strm.msg = 'invalid block type'; 14550 state.mode = BAD; 14551 } //--- DROPBITS(2) ---// 14552 14553 14554 hold >>>= 2; 14555 bits -= 2; //---// 14556 14557 break; 14558 14559 case STORED: 14560 //--- BYTEBITS() ---// /* go to byte boundary */ 14561 hold >>>= bits & 7; 14562 bits -= bits & 7; //---// 14563 //=== NEEDBITS(32); */ 14564 14565 while (bits < 32) { 14566 if (have === 0) { 14567 break inf_leave; 14568 } 14569 14570 have--; 14571 hold += input[next++] << bits; 14572 bits += 8; 14573 } //===// 14574 14575 14576 if ((hold & 0xffff) !== (hold >>> 16 ^ 0xffff)) { 14577 strm.msg = 'invalid stored block lengths'; 14578 state.mode = BAD; 14579 break; 14580 } 14581 14582 state.length = hold & 0xffff; //Tracev((stderr, "inflate: stored length %u\n", 14583 // state.length)); 14584 //=== INITBITS(); 14585 14586 hold = 0; 14587 bits = 0; //===// 14588 14589 state.mode = COPY_; 14590 14591 if (flush === Z_TREES) { 14592 break inf_leave; 14593 } 14594 14595 /* falls through */ 14596 14597 case COPY_: 14598 state.mode = COPY; 14599 14600 /* falls through */ 14601 14602 case COPY: 14603 copy = state.length; 14604 14605 if (copy) { 14606 if (copy > have) { 14607 copy = have; 14608 } 14609 14610 if (copy > left) { 14611 copy = left; 14612 } 14613 14614 if (copy === 0) { 14615 break inf_leave; 14616 } //--- zmemcpy(put, next, copy); --- 14617 14618 14619 output.set(input.subarray(next, next + copy), put); //---// 14620 14621 have -= copy; 14622 next += copy; 14623 left -= copy; 14624 put += copy; 14625 state.length -= copy; 14626 break; 14627 } //Tracev((stderr, "inflate: stored end\n")); 14628 14629 14630 state.mode = TYPE; 14631 break; 14632 14633 case TABLE: 14634 //=== NEEDBITS(14); */ 14635 while (bits < 14) { 14636 if (have === 0) { 14637 break inf_leave; 14638 } 14639 14640 have--; 14641 hold += input[next++] << bits; 14642 bits += 8; 14643 } //===// 14644 14645 14646 state.nlen = (hold & 0x1f 14647 /*BITS(5)*/ 14648 ) + 257; //--- DROPBITS(5) ---// 14649 14650 hold >>>= 5; 14651 bits -= 5; //---// 14652 14653 state.ndist = (hold & 0x1f 14654 /*BITS(5)*/ 14655 ) + 1; //--- DROPBITS(5) ---// 14656 14657 hold >>>= 5; 14658 bits -= 5; //---// 14659 14660 state.ncode = (hold & 0x0f 14661 /*BITS(4)*/ 14662 ) + 4; //--- DROPBITS(4) ---// 14663 14664 hold >>>= 4; 14665 bits -= 4; //---// 14666 //#ifndef PKZIP_BUG_WORKAROUND 14667 14668 if (state.nlen > 286 || state.ndist > 30) { 14669 strm.msg = 'too many length or distance symbols'; 14670 state.mode = BAD; 14671 break; 14672 } //#endif 14673 //Tracev((stderr, "inflate: table sizes ok\n")); 14674 14675 14676 state.have = 0; 14677 state.mode = LENLENS; 14678 14679 /* falls through */ 14680 14681 case LENLENS: 14682 while (state.have < state.ncode) { 14683 //=== NEEDBITS(3); 14684 while (bits < 3) { 14685 if (have === 0) { 14686 break inf_leave; 14687 } 14688 14689 have--; 14690 hold += input[next++] << bits; 14691 bits += 8; 14692 } //===// 14693 14694 14695 state.lens[order[state.have++]] = hold & 0x07; //BITS(3); 14696 //--- DROPBITS(3) ---// 14697 14698 hold >>>= 3; 14699 bits -= 3; //---// 14700 } 14701 14702 while (state.have < 19) { 14703 state.lens[order[state.have++]] = 0; 14704 } // We have separate tables & no pointers. 2 commented lines below not needed. 14705 //state.next = state.codes; 14706 //state.lencode = state.next; 14707 // Switch to use dynamic table 14708 14709 14710 state.lencode = state.lendyn; 14711 state.lenbits = 7; 14712 opts = { 14713 bits: state.lenbits 14714 }; 14715 ret = inftrees(CODES, state.lens, 0, 19, state.lencode, 0, state.work, opts); 14716 state.lenbits = opts.bits; 14717 14718 if (ret) { 14719 strm.msg = 'invalid code lengths set'; 14720 state.mode = BAD; 14721 break; 14722 } //Tracev((stderr, "inflate: code lengths ok\n")); 14723 14724 14725 state.have = 0; 14726 state.mode = CODELENS; 14727 14728 /* falls through */ 14729 14730 case CODELENS: 14731 while (state.have < state.nlen + state.ndist) { 14732 for (;;) { 14733 here = state.lencode[hold & (1 << state.lenbits) - 1]; 14734 /*BITS(state.lenbits)*/ 14735 14736 here_bits = here >>> 24; 14737 here_op = here >>> 16 & 0xff; 14738 here_val = here & 0xffff; 14739 14740 if (here_bits <= bits) { 14741 break; 14742 } //--- PULLBYTE() ---// 14743 14744 14745 if (have === 0) { 14746 break inf_leave; 14747 } 14748 14749 have--; 14750 hold += input[next++] << bits; 14751 bits += 8; //---// 14752 } 14753 14754 if (here_val < 16) { 14755 //--- DROPBITS(here.bits) ---// 14756 hold >>>= here_bits; 14757 bits -= here_bits; //---// 14758 14759 state.lens[state.have++] = here_val; 14760 } else { 14761 if (here_val === 16) { 14762 //=== NEEDBITS(here.bits + 2); 14763 n = here_bits + 2; 14764 14765 while (bits < n) { 14766 if (have === 0) { 14767 break inf_leave; 14768 } 14769 14770 have--; 14771 hold += input[next++] << bits; 14772 bits += 8; 14773 } //===// 14774 //--- DROPBITS(here.bits) ---// 14775 14776 14777 hold >>>= here_bits; 14778 bits -= here_bits; //---// 14779 14780 if (state.have === 0) { 14781 strm.msg = 'invalid bit length repeat'; 14782 state.mode = BAD; 14783 break; 14784 } 14785 14786 len = state.lens[state.have - 1]; 14787 copy = 3 + (hold & 0x03); //BITS(2); 14788 //--- DROPBITS(2) ---// 14789 14790 hold >>>= 2; 14791 bits -= 2; //---// 14792 } else if (here_val === 17) { 14793 //=== NEEDBITS(here.bits + 3); 14794 n = here_bits + 3; 14795 14796 while (bits < n) { 14797 if (have === 0) { 14798 break inf_leave; 14799 } 14800 14801 have--; 14802 hold += input[next++] << bits; 14803 bits += 8; 14804 } //===// 14805 //--- DROPBITS(here.bits) ---// 14806 14807 14808 hold >>>= here_bits; 14809 bits -= here_bits; //---// 14810 14811 len = 0; 14812 copy = 3 + (hold & 0x07); //BITS(3); 14813 //--- DROPBITS(3) ---// 14814 14815 hold >>>= 3; 14816 bits -= 3; //---// 14817 } else { 14818 //=== NEEDBITS(here.bits + 7); 14819 n = here_bits + 7; 14820 14821 while (bits < n) { 14822 if (have === 0) { 14823 break inf_leave; 14824 } 14825 14826 have--; 14827 hold += input[next++] << bits; 14828 bits += 8; 14829 } //===// 14830 //--- DROPBITS(here.bits) ---// 14831 14832 14833 hold >>>= here_bits; 14834 bits -= here_bits; //---// 14835 14836 len = 0; 14837 copy = 11 + (hold & 0x7f); //BITS(7); 14838 //--- DROPBITS(7) ---// 14839 14840 hold >>>= 7; 14841 bits -= 7; //---// 14842 } 14843 14844 if (state.have + copy > state.nlen + state.ndist) { 14845 strm.msg = 'invalid bit length repeat'; 14846 state.mode = BAD; 14847 break; 14848 } 14849 14850 while (copy--) { 14851 state.lens[state.have++] = len; 14852 } 14853 } 14854 } 14855 /* handle error breaks in while */ 14856 14857 14858 if (state.mode === BAD) { 14859 break; 14860 } 14861 /* check for end-of-block code (better have one) */ 14862 14863 14864 if (state.lens[256] === 0) { 14865 strm.msg = 'invalid code -- missing end-of-block'; 14866 state.mode = BAD; 14867 break; 14868 } 14869 /* build code tables -- note: do not change the lenbits or distbits 14870 values here (9 and 6) without reading the comments in inftrees.h 14871 concerning the ENOUGH constants, which depend on those values */ 14872 14873 14874 state.lenbits = 9; 14875 opts = { 14876 bits: state.lenbits 14877 }; 14878 ret = inftrees(LENS, state.lens, 0, state.nlen, state.lencode, 0, state.work, opts); // We have separate tables & no pointers. 2 commented lines below not needed. 14879 // state.next_index = opts.table_index; 14880 14881 state.lenbits = opts.bits; // state.lencode = state.next; 14882 14883 if (ret) { 14884 strm.msg = 'invalid literal/lengths set'; 14885 state.mode = BAD; 14886 break; 14887 } 14888 14889 state.distbits = 6; //state.distcode.copy(state.codes); 14890 // Switch to use dynamic table 14891 14892 state.distcode = state.distdyn; 14893 opts = { 14894 bits: state.distbits 14895 }; 14896 ret = inftrees(DISTS, state.lens, state.nlen, state.ndist, state.distcode, 0, state.work, opts); // We have separate tables & no pointers. 2 commented lines below not needed. 14897 // state.next_index = opts.table_index; 14898 14899 state.distbits = opts.bits; // state.distcode = state.next; 14900 14901 if (ret) { 14902 strm.msg = 'invalid distances set'; 14903 state.mode = BAD; 14904 break; 14905 } //Tracev((stderr, 'inflate: codes ok\n')); 14906 14907 14908 state.mode = LEN_; 14909 14910 if (flush === Z_TREES) { 14911 break inf_leave; 14912 } 14913 14914 /* falls through */ 14915 14916 case LEN_: 14917 state.mode = LEN; 14918 14919 /* falls through */ 14920 14921 case LEN: 14922 if (have >= 6 && left >= 258) { 14923 //--- RESTORE() --- 14924 strm.next_out = put; 14925 strm.avail_out = left; 14926 strm.next_in = next; 14927 strm.avail_in = have; 14928 state.hold = hold; 14929 state.bits = bits; //--- 14930 14931 inffast(strm, _out); //--- LOAD() --- 14932 14933 put = strm.next_out; 14934 output = strm.output; 14935 left = strm.avail_out; 14936 next = strm.next_in; 14937 input = strm.input; 14938 have = strm.avail_in; 14939 hold = state.hold; 14940 bits = state.bits; //--- 14941 14942 if (state.mode === TYPE) { 14943 state.back = -1; 14944 } 14945 14946 break; 14947 } 14948 14949 state.back = 0; 14950 14951 for (;;) { 14952 here = state.lencode[hold & (1 << state.lenbits) - 1]; 14953 /*BITS(state.lenbits)*/ 14954 14955 here_bits = here >>> 24; 14956 here_op = here >>> 16 & 0xff; 14957 here_val = here & 0xffff; 14958 14959 if (here_bits <= bits) { 14960 break; 14961 } //--- PULLBYTE() ---// 14962 14963 14964 if (have === 0) { 14965 break inf_leave; 14966 } 14967 14968 have--; 14969 hold += input[next++] << bits; 14970 bits += 8; //---// 14971 } 14972 14973 if (here_op && (here_op & 0xf0) === 0) { 14974 last_bits = here_bits; 14975 last_op = here_op; 14976 last_val = here_val; 14977 14978 for (;;) { 14979 here = state.lencode[last_val + ((hold & (1 << last_bits + last_op) - 1 14980 /*BITS(last.bits + last.op)*/ 14981 ) >> last_bits)]; 14982 here_bits = here >>> 24; 14983 here_op = here >>> 16 & 0xff; 14984 here_val = here & 0xffff; 14985 14986 if (last_bits + here_bits <= bits) { 14987 break; 14988 } //--- PULLBYTE() ---// 14989 14990 14991 if (have === 0) { 14992 break inf_leave; 14993 } 14994 14995 have--; 14996 hold += input[next++] << bits; 14997 bits += 8; //---// 14998 } //--- DROPBITS(last.bits) ---// 14999 15000 15001 hold >>>= last_bits; 15002 bits -= last_bits; //---// 15003 15004 state.back += last_bits; 15005 } //--- DROPBITS(here.bits) ---// 15006 15007 15008 hold >>>= here_bits; 15009 bits -= here_bits; //---// 15010 15011 state.back += here_bits; 15012 state.length = here_val; 15013 15014 if (here_op === 0) { 15015 //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? 15016 // "inflate: literal '%c'\n" : 15017 // "inflate: literal 0x%02x\n", here.val)); 15018 state.mode = LIT; 15019 break; 15020 } 15021 15022 if (here_op & 32) { 15023 //Tracevv((stderr, "inflate: end of block\n")); 15024 state.back = -1; 15025 state.mode = TYPE; 15026 break; 15027 } 15028 15029 if (here_op & 64) { 15030 strm.msg = 'invalid literal/length code'; 15031 state.mode = BAD; 15032 break; 15033 } 15034 15035 state.extra = here_op & 15; 15036 state.mode = LENEXT; 15037 15038 /* falls through */ 15039 15040 case LENEXT: 15041 if (state.extra) { 15042 //=== NEEDBITS(state.extra); 15043 n = state.extra; 15044 15045 while (bits < n) { 15046 if (have === 0) { 15047 break inf_leave; 15048 } 15049 15050 have--; 15051 hold += input[next++] << bits; 15052 bits += 8; 15053 } //===// 15054 15055 15056 state.length += hold & (1 << state.extra) - 1 15057 /*BITS(state.extra)*/ 15058 ; //--- DROPBITS(state.extra) ---// 15059 15060 hold >>>= state.extra; 15061 bits -= state.extra; //---// 15062 15063 state.back += state.extra; 15064 } //Tracevv((stderr, "inflate: length %u\n", state.length)); 15065 15066 15067 state.was = state.length; 15068 state.mode = DIST; 15069 15070 /* falls through */ 15071 15072 case DIST: 15073 for (;;) { 15074 here = state.distcode[hold & (1 << state.distbits) - 1]; 15075 /*BITS(state.distbits)*/ 15076 15077 here_bits = here >>> 24; 15078 here_op = here >>> 16 & 0xff; 15079 here_val = here & 0xffff; 15080 15081 if (here_bits <= bits) { 15082 break; 15083 } //--- PULLBYTE() ---// 15084 15085 15086 if (have === 0) { 15087 break inf_leave; 15088 } 15089 15090 have--; 15091 hold += input[next++] << bits; 15092 bits += 8; //---// 15093 } 15094 15095 if ((here_op & 0xf0) === 0) { 15096 last_bits = here_bits; 15097 last_op = here_op; 15098 last_val = here_val; 15099 15100 for (;;) { 15101 here = state.distcode[last_val + ((hold & (1 << last_bits + last_op) - 1 15102 /*BITS(last.bits + last.op)*/ 15103 ) >> last_bits)]; 15104 here_bits = here >>> 24; 15105 here_op = here >>> 16 & 0xff; 15106 here_val = here & 0xffff; 15107 15108 if (last_bits + here_bits <= bits) { 15109 break; 15110 } //--- PULLBYTE() ---// 15111 15112 15113 if (have === 0) { 15114 break inf_leave; 15115 } 15116 15117 have--; 15118 hold += input[next++] << bits; 15119 bits += 8; //---// 15120 } //--- DROPBITS(last.bits) ---// 15121 15122 15123 hold >>>= last_bits; 15124 bits -= last_bits; //---// 15125 15126 state.back += last_bits; 15127 } //--- DROPBITS(here.bits) ---// 15128 15129 15130 hold >>>= here_bits; 15131 bits -= here_bits; //---// 15132 15133 state.back += here_bits; 15134 15135 if (here_op & 64) { 15136 strm.msg = 'invalid distance code'; 15137 state.mode = BAD; 15138 break; 15139 } 15140 15141 state.offset = here_val; 15142 state.extra = here_op & 15; 15143 state.mode = DISTEXT; 15144 15145 /* falls through */ 15146 15147 case DISTEXT: 15148 if (state.extra) { 15149 //=== NEEDBITS(state.extra); 15150 n = state.extra; 15151 15152 while (bits < n) { 15153 if (have === 0) { 15154 break inf_leave; 15155 } 15156 15157 have--; 15158 hold += input[next++] << bits; 15159 bits += 8; 15160 } //===// 15161 15162 15163 state.offset += hold & (1 << state.extra) - 1 15164 /*BITS(state.extra)*/ 15165 ; //--- DROPBITS(state.extra) ---// 15166 15167 hold >>>= state.extra; 15168 bits -= state.extra; //---// 15169 15170 state.back += state.extra; 15171 } //#ifdef INFLATE_STRICT 15172 15173 15174 if (state.offset > state.dmax) { 15175 strm.msg = 'invalid distance too far back'; 15176 state.mode = BAD; 15177 break; 15178 } //#endif 15179 //Tracevv((stderr, "inflate: distance %u\n", state.offset)); 15180 15181 15182 state.mode = MATCH; 15183 15184 /* falls through */ 15185 15186 case MATCH: 15187 if (left === 0) { 15188 break inf_leave; 15189 } 15190 15191 copy = _out - left; 15192 15193 if (state.offset > copy) { 15194 /* copy from window */ 15195 copy = state.offset - copy; 15196 15197 if (copy > state.whave) { 15198 if (state.sane) { 15199 strm.msg = 'invalid distance too far back'; 15200 state.mode = BAD; 15201 break; 15202 } // (!) This block is disabled in zlib defaults, 15203 // don't enable it for binary compatibility 15204 //#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR 15205 // Trace((stderr, "inflate.c too far\n")); 15206 // copy -= state.whave; 15207 // if (copy > state.length) { copy = state.length; } 15208 // if (copy > left) { copy = left; } 15209 // left -= copy; 15210 // state.length -= copy; 15211 // do { 15212 // output[put++] = 0; 15213 // } while (--copy); 15214 // if (state.length === 0) { state.mode = LEN; } 15215 // break; 15216 //#endif 15217 15218 } 15219 15220 if (copy > state.wnext) { 15221 copy -= state.wnext; 15222 from = state.wsize - copy; 15223 } else { 15224 from = state.wnext - copy; 15225 } 15226 15227 if (copy > state.length) { 15228 copy = state.length; 15229 } 15230 15231 from_source = state.window; 15232 } else { 15233 /* copy from output */ 15234 from_source = output; 15235 from = put - state.offset; 15236 copy = state.length; 15237 } 15238 15239 if (copy > left) { 15240 copy = left; 15241 } 15242 15243 left -= copy; 15244 state.length -= copy; 15245 15246 do { 15247 output[put++] = from_source[from++]; 15248 } while (--copy); 15249 15250 if (state.length === 0) { 15251 state.mode = LEN; 15252 } 15253 15254 break; 15255 15256 case LIT: 15257 if (left === 0) { 15258 break inf_leave; 15259 } 15260 15261 output[put++] = state.length; 15262 left--; 15263 state.mode = LEN; 15264 break; 15265 15266 case CHECK: 15267 if (state.wrap) { 15268 //=== NEEDBITS(32); 15269 while (bits < 32) { 15270 if (have === 0) { 15271 break inf_leave; 15272 } 15273 15274 have--; // Use '|' instead of '+' to make sure that result is signed 15275 15276 hold |= input[next++] << bits; 15277 bits += 8; 15278 } //===// 15279 15280 15281 _out -= left; 15282 strm.total_out += _out; 15283 state.total += _out; 15284 15285 if (_out) { 15286 strm.adler = state.check = 15287 /*UPDATE(state.check, put - _out, _out);*/ 15288 state.flags ? crc32_1(state.check, output, _out, put - _out) : adler32_1(state.check, output, _out, put - _out); 15289 } 15290 15291 _out = left; // NB: crc32 stored as signed 32-bit int, zswap32 returns signed too 15292 15293 if ((state.flags ? hold : zswap32(hold)) !== state.check) { 15294 strm.msg = 'incorrect data check'; 15295 state.mode = BAD; 15296 break; 15297 } //=== INITBITS(); 15298 15299 15300 hold = 0; 15301 bits = 0; //===// 15302 //Tracev((stderr, "inflate: check matches trailer\n")); 15303 } 15304 15305 state.mode = LENGTH; 15306 15307 /* falls through */ 15308 15309 case LENGTH: 15310 if (state.wrap && state.flags) { 15311 //=== NEEDBITS(32); 15312 while (bits < 32) { 15313 if (have === 0) { 15314 break inf_leave; 15315 } 15316 15317 have--; 15318 hold += input[next++] << bits; 15319 bits += 8; 15320 } //===// 15321 15322 15323 if (hold !== (state.total & 0xffffffff)) { 15324 strm.msg = 'incorrect length check'; 15325 state.mode = BAD; 15326 break; 15327 } //=== INITBITS(); 15328 15329 15330 hold = 0; 15331 bits = 0; //===// 15332 //Tracev((stderr, "inflate: length matches trailer\n")); 15333 } 15334 15335 state.mode = DONE; 15336 15337 /* falls through */ 15338 15339 case DONE: 15340 ret = Z_STREAM_END$1; 15341 break inf_leave; 15342 15343 case BAD: 15344 ret = Z_DATA_ERROR$1; 15345 break inf_leave; 15346 15347 case MEM: 15348 return Z_MEM_ERROR$1; 15349 15350 case SYNC: 15351 /* falls through */ 15352 15353 default: 15354 return Z_STREAM_ERROR$1; 15355 } 15356 } // inf_leave <- here is real place for "goto inf_leave", emulated via "break inf_leave" 15357 15358 /* 15359 Return from inflate(), updating the total counts and the check value. 15360 If there was no progress during the inflate() call, return a buffer 15361 error. Call updatewindow() to create and/or update the window state. 15362 Note: a memory error from inflate() is non-recoverable. 15363 */ 15364 //--- RESTORE() --- 15365 15366 15367 strm.next_out = put; 15368 strm.avail_out = left; 15369 strm.next_in = next; 15370 strm.avail_in = have; 15371 state.hold = hold; 15372 state.bits = bits; //--- 15373 15374 if (state.wsize || _out !== strm.avail_out && state.mode < BAD && (state.mode < CHECK || flush !== Z_FINISH$1)) { 15375 if (updatewindow(strm, strm.output, strm.next_out, _out - strm.avail_out)) ; 15376 } 15377 15378 _in -= strm.avail_in; 15379 _out -= strm.avail_out; 15380 strm.total_in += _in; 15381 strm.total_out += _out; 15382 state.total += _out; 15383 15384 if (state.wrap && _out) { 15385 strm.adler = state.check = 15386 /*UPDATE(state.check, strm.next_out - _out, _out);*/ 15387 state.flags ? crc32_1(state.check, output, _out, strm.next_out - _out) : adler32_1(state.check, output, _out, strm.next_out - _out); 15388 } 15389 15390 strm.data_type = state.bits + (state.last ? 64 : 0) + (state.mode === TYPE ? 128 : 0) + (state.mode === LEN_ || state.mode === COPY_ ? 256 : 0); 15391 15392 if ((_in === 0 && _out === 0 || flush === Z_FINISH$1) && ret === Z_OK$1) {
15393 ret = Z_BUF_ERROR; 15394 } 15395 15396 return ret; 15397 }; 15398 15399 const inflateEnd = strm => { 15400 if (!strm || !strm.state 15401 /*|| strm->zfree == (free_func)0*/ 15402 ) { 15403 return Z_STREAM_ERROR$1; 15404 } 15405 15406 let state = strm.state; 15407 15408 if (state.window) { 15409 state.window = null; 15410 } 15411 15412 strm.state = null; 15413 return Z_OK$1; 15414 }; 15415 15416 const inflateGetHeader = (strm, head) => { 15417 /* check state */ 15418 if (!strm || !strm.state) { 15419 return Z_STREAM_ERROR$1; 15420 } 15421 15422 const state = strm.state; 15423 15424 if ((state.wrap & 2) === 0) { 15425 return Z_STREAM_ERROR$1; 15426 } 15427 /* save header structure */ 15428 15429 15430 state.head = head; 15431 head.done = false; 15432 return Z_OK$1; 15433 }; 15434 15435 const inflateSetDictionary = (strm, dictionary) => { 15436 const dictLength = dictionary.length; 15437 let state; 15438 let dictid; 15439 let ret; 15440 /* check state */ 15441 15442 if (!strm 15443 /* == Z_NULL */ 15444 || !strm.state 15445 /* == Z_NULL */ 15446 ) { 15447 return Z_STREAM_ERROR$1; 15448 } 15449 15450 state = strm.state; 15451 15452 if (state.wrap !== 0 && state.mode !== DICT) { 15453 return Z_STREAM_ERROR$1; 15454 }
15455 /* check for correct dictionary identifier */ 15456 15457 15458 if (state.mode === DICT) { 15459 dictid = 1; 15460 /* adler32(0, null, 0)*/ 15461 15462 /* dictid = adler32(dictid, dictionary, dictLength); */ 15463 15464 dictid = adler32_1(dictid, dictionary, dictLength, 0); 15465 15466 if (dictid !== state.check) { 15467 return Z_DATA_ERROR$1; 15468 } 15469 } 15470 /* copy dictionary to window using updatewindow(), which will amend the 15471 existing dictionary if appropriate */ 15472 15473 15474 ret = updatewindow(strm, dictionary, dictLength, dictLength); 15475 15476 if (ret) { 15477 state.mode = MEM; 15478 return Z_MEM_ERROR$1; 15479 } 15480 15481 state.havedict = 1; // Tracev((stderr, "inflate: dictionary set\n")); 15482 15483 return Z_OK$1; 15484 }; 15485 15486 var inflateReset_1 = inflateReset; 15487 var inflateReset2_1 = inflateReset2; 15488 var inflateResetKeep_1 = inflateResetKeep; 15489 var inflateInit_1 = inflateInit; 15490 var inflateInit2_1 = inflateInit2; 15491 var inflate_2$1 = inflate$2; 15492 var inflateEnd_1 = inflateEnd; 15493 var inflateGetHeader_1 = inflateGetHeader; 15494 var inflateSetDictionary_1 = inflateSetDictionary; 15495 var inflateInfo = 'pako inflate (from Nodeca project)'; 15496 /* Not implemented 15497 module.exports.inflateCopy = inflateCopy; 15498 module.exports.inflateGetDictionary = inflateGetDictionary; 15499 module.exports.inflateMark = inflateMark; 15500 module.exports.inflatePrime = inflatePrime; 15501 module.exports.inflateSync = inflateSync; 15502 module.exports.inflateSyncPoint = inflateSyncPoint; 15503 module.exports.inflateUndermine = inflateUndermine; 15504 */ 15505 15506 var inflate_1$2 = { 15507 inflateReset: inflateReset_1, 15508 inflateReset2: inflateReset2_1, 15509 inflateResetKeep: inflateResetKeep_1, 15510 inflateInit: inflateInit_1, 15511 inflateInit2: inflateInit2_1, 15512 inflate: inflate_2$1, 15513 inflateEnd: inflateEnd_1, 15514 inflateGetHeader: inflateGetHeader_1, 15515 inflateSetDictionary: inflateSetDictionary_1, 15516 inflateInfo: inflateInfo 15517 }; // (C) 1995-2013 Jean-loup Gailly and Mark Adler 15518 // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin 15519 // 15520 // This software is provided 'as-is', without any express or implied 15521 // warranty. In no event will the authors be held liable for any damages 15522 // arising from the use of this software. 15523 // 15524 // Permission is granted to anyone to use this software for any purpose, 15525 // including commercial applications, and to alter it and redistribute it 15526 // freely, subject to the following restrictions: 15527 // 15528 // 1. The origin of this software must not be misrepresented; you must not 15529 // claim that you wrote the original software. If you use this software 15530 // in a product, an acknowledgment in the product documentation would be 15531 // appreciated but is not required. 15532 // 2. Altered source versions must be plainly marked as such, and must not be 15533 // misrepresented as being the original software. 15534 // 3. This notice may not be removed or altered from any source distribution. 15535 15536 function GZheader() { 15537 /* true if compressed data believed to be text */ 15538 this.text = 0; 15539 /* modification time */ 15540 15541 this.time = 0; 15542 /* extra flags (not used when writing a gzip file) */ 15543 15544 this.xflags = 0; 15545 /* operating system */ 15546 15547 this.os = 0; 15548 /* pointer to extra field or Z_NULL if none */ 15549 15550 this.extra = null; 15551 /* extra field length (valid if extra != Z_NULL) */ 15552 15553 this.extra_len = 0; // Actually, we don't need it in JS, 15554 // but leave for few code modifications 15555 // 15556 // Setup limits is not necessary because in js we should not preallocate memory 15557 // for inflate use constant limit in 65536 bytes 15558 // 15559 15560 /* space at extra (only when reading header) */ 15561 // this.extra_max = 0; 15562 15563 /* pointer to zero-terminated file name or Z_NULL */ 15564 15565 this.name = ''; 15566 /* space at name (only when reading header) */ 15567 // this.name_max = 0; 15568 15569 /* pointer to zero-terminated comment or Z_NULL */ 15570 15571 this.comment = ''; 15572 /* space at comment (only when reading header) */ 15573 // this.comm_max = 0; 15574 15575 /* true if there was or will be a header crc */ 15576 15577 this.hcrc = 0; 15578 /* true when done reading gzip header (not used when writing a gzip f
vendor: 11,051 bytes, lines 15578-15921
15578ile) */ 15579 15580 this.done = false; 15581 } 15582 15583 var gzheader = GZheader; 15584 const toString$2 = Object.prototype.toString; 15585 /* Public constants ==========================================================*/ 15586 15587 /* ===========================================================================*/ 15588 15589 const { 15590 Z_NO_FLUSH, 15591 Z_FINISH, 15592 Z_OK, 15593 Z_STREAM_END, 15594 Z_NEED_DICT, 15595 Z_STREAM_ERROR, 15596 Z_DATA_ERROR, 15597 Z_MEM_ERROR 15598 } = constants$2; 15599 /* ===========================================================================*/ 15600 15601 /** 15602 * class Inflate 15603 * 15604 * Generic JS-style wrapper for zlib calls. If you don't need 15605 * streaming behaviour - use more simple functions: [[inflate]] 15606 * and [[inflateRaw]]. 15607 **/ 15608 15609 /* internal 15610 * inflate.chunks -> Array 15611 * 15612 * Chunks of output data, if [[Inflate#onData]] not overridden. 15613 **/ 15614 15615 /** 15616 * Inflate.result -> Uint8Array|String 15617 * 15618 * Uncompressed result, generated by default [[Inflate#onData]] 15619 * and [[Inflate#onEnd]] handlers. Filled after you push last chunk 15620 * (call [[Inflate#push]] with `Z_FINISH` / `true` param). 15621 **/ 15622 15623 /** 15624 * Inflate.err -> Number 15625 * 15626 * Error code after inflate finished. 0 (Z_OK) on success. 15627 * Should be checked if broken data possible. 15628 **/ 15629 15630 /** 15631 * Inflate.msg -> String 15632 * 15633 * Error message, if [[Inflate.err]] != 0 15634 **/ 15635 15636 /** 15637 * new Inflate(options) 15638 * - options (Object): zlib inflate options. 15639 * 15640 * Creates new inflator instance with specified params. Throws exception 15641 * on bad params. Supported options: 15642 * 15643 * - `windowBits` 15644 * - `dictionary` 15645 * 15646 * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced) 15647 * for more information on these. 15648 * 15649 * Additional options, for internal needs: 15650 * 15651 * - `chunkSize` - size of generated data chunks (16K by default) 15652 * - `raw` (Boolean) - do raw inflate 15653 * - `to` (String) - if equal to 'string', then result will be converted 15654 * from utf8 to utf16 (javascript) string. When string output requested, 15655 * chunk length can differ from `chunkSize`, depending on content. 15656 * 15657 * By default, when no options set, autodetect deflate/gzip data format via 15658 * wrapper header. 15659 * 15660 * ##### Example: 15661 * 15662 * ```javascript 15663 * const pako = require('pako') 15664 * const chunk1 = new Uint8Array([1,2,3,4,5,6,7,8,9]) 15665 * const chunk2 = new Uint8Array([10,11,12,13,14,15,16,17,18,19]); 15666 * 15667 * const inflate = new pako.Inflate({ level: 3}); 15668 * 15669 * inflate.push(chunk1, false); 15670 * inflate.push(chunk2, true); // true -> last chunk 15671 * 15672 * if (inflate.err) { throw new Error(inflate.err); } 15673 * 15674 * console.log(inflate.result); 15675 * ``` 15676 **/ 15677 15678 function Inflate$1(options) { 15679 this.options = common.assign({ 15680 chunkSize: 1024 * 64, 15681 windowBits: 15, 15682 to: '' 15683 }, options || {}); 15684 const opt = this.options; // Force window size for `raw` data, if not set directly, 15685 // because we have no header for autodetect. 15686 15687 if (opt.raw && opt.windowBits >= 0 && opt.windowBits < 16) { 15688 opt.windowBits = -opt.windowBits; 15689 15690 if (opt.windowBits === 0) { 15691 opt.windowBits = -15; 15692 } 15693 } // If `windowBits` not defined (and mode not raw) - set autodetect flag for gzip/deflate 15694 15695 15696 if (opt.windowBits >= 0 && opt.windowBits < 16 && !(options && options.windowBits)) { 15697 opt.windowBits += 32; 15698 } // Gzip header has no info about windows size, we can do autodetect only 15699 // for deflate. So, if window size not set, force it to max when gzip possible 15700 15701 15702 if (opt.windowBits > 15 && opt.windowBits < 48) { 15703 // bit 3 (16) -> gzipped data 15704 // bit 4 (32) -> autodetect gzip/deflate 15705 if ((opt.windowBits & 15) === 0) { 15706 opt.windowBits |= 15; 15707 } 15708 } 15709 15710 this.err = 0; // error code, if happens (0 = Z_OK) 15711 15712 this.msg = ''; // error message 15713 15714 this.ended = false; // used to avoid multiple onEnd() calls 15715 15716 this.chunks = []; // chunks of compressed data 15717 15718 this.strm = new zstream(); 15719 this.strm.avail_out = 0; 15720 let status = inflate_1$2.inflateInit2(this.strm, opt.windowBits); 15721 15722 if (status !== Z_OK) { 15723 throw new Error(messages[status]); 15724 } 15725 15726 this.header = new gzheader(); 15727 inflate_1$2.inflateGetHeader(this.strm, this.header); // Setup dictionary 15728 15729 if (opt.dictionary) { 15730 // Convert data if needed 15731 if (typeof opt.dictionary === 'string') { 15732 opt.dictionary = strings.string2buf(opt.dictionary); 15733 } else if (toString$2.call(opt.dictionary) === '[object ArrayBuffer]') { 15734 opt.dictionary = new Uint8Array(opt.dictionary); 15735 } 15736 15737 if (opt.raw) { 15738 //In raw mode we need to set the dictionary early 15739 status = inflate_1$2.inflateSetDictionary(this.strm, opt.dictionary); 15740 15741 if (status !== Z_OK) { 15742 throw new Error(messages[status]); 15743 } 15744 } 15745 } 15746 } 15747 /** 15748 * Inflate#push(data[, flush_mode]) -> Boolean 15749 * - data (Uint8Array|ArrayBuffer): input data 15750 * - flush_mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE 15751 * flush modes. See constants. Skipped or `false` means Z_NO_FLUSH, 15752 * `true` means Z_FINISH. 15753 * 15754 * Sends input data to inflate pipe, generating [[Inflate#onData]] calls with 15755 * new output chunks. Returns `true` on success. If end of stream detected, 15756 * [[Inflate#onEnd]] will be called. 15757 * 15758 * `flush_mode` is not needed for normal operation, because end of stream 15759 * detected automatically. You may try to use it for advanced things, but 15760 * this functionality was not tested. 15761 * 15762 * On fail call [[Inflate#onEnd]] with error code and return false. 15763 * 15764 * ##### Example 15765 * 15766 * ```javascript 15767 * push(chunk, false); // push one of data chunks 15768 * ... 15769 * push(chunk, true); // push last chunk 15770 * ``` 15771 **/ 15772 15773 15774 Inflate$1.prototype.push = function (data, flush_mode) { 15775 const strm = this.strm; 15776 const chunkSize = this.options.chunkSize; 15777 const dictionary = this.options.dictionary; 15778 15779 let status, _flush_mode, last_avail_out; 15780 15781 if (this.ended) return false; 15782 if (flush_mode === ~~flush_mode) _flush_mode = flush_mode;else _flush_mode = flush_mode === true ? Z_FINISH : Z_NO_FLUSH; // Convert data if needed 15783 15784 if (toString$2.call(data) === '[object ArrayBuffer]') { 15785 strm.input = new Uint8Array(data); 15786 } else { 15787 strm.input = data; 15788 } 15789 15790 strm.next_in = 0; 15791 strm.avail_in = strm.input.length; 15792 15793 for (;;) { 15794 if (strm.avail_out === 0) { 15795 strm.output = new Uint8Array(chunkSize); 15796 strm.next_out = 0; 15797 strm.avail_out = chunkSize; 15798 } 15799 15800 status = inflate_1$2.inflate(strm, _flush_mode); 15801 15802 if (status === Z_NEED_DICT && dictionary) { 15803 status = inflate_1$2.inflateSetDictionary(strm, dictionary); 15804 15805 if (status === Z_OK) { 15806 status = inflate_1$2.inflate(strm, _flush_mode); 15807 } else if (status === Z_DATA_ERROR) { 15808 // Replace code with more verbose 15809 status = Z_NEED_DICT; 15810 } 15811 } // Skip snyc markers if more data follows and not raw mode 15812 15813 15814 while (strm.avail_in > 0 && status === Z_STREAM_END && strm.state.wrap > 0 && data[strm.next_in] !== 0) { 15815 inflate_1$2.inflateReset(strm); 15816 status = inflate_1$2.inflate(strm, _flush_mode); 15817 } 15818 15819 switch (status) { 15820 case Z_STREAM_ERROR: 15821 case Z_DATA_ERROR: 15822 case Z_NEED_DICT: 15823 case Z_MEM_ERROR: 15824 this.onEnd(status); 15825 this.ended = true; 15826 return false; 15827 } // Remember real `avail_out` value, because we may patch out buffer content 15828 // to align utf8 strings boundaries. 15829 15830 15831 last_avail_out = strm.avail_out; 15832 15833 if (strm.next_out) { 15834 if (strm.avail_out === 0 || status === Z_STREAM_END) { 15835 if (this.options.to === 'string') { 15836 let next_out_utf8 = strings.utf8border(strm.output, strm.next_out); 15837 let tail = strm.next_out - next_out_utf8; 15838 let utf8str = strings.buf2string(strm.output, next_out_utf8); // move tail & realign counters 15839 15840 strm.next_out = tail; 15841 strm.avail_out = chunkSize - tail; 15842 if (tail) strm.output.set(strm.output.subarray(next_out_utf8, next_out_utf8 + tail), 0); 15843 this.onData(utf8str); 15844 } else { 15845 this.onData(strm.output.length === strm.next_out ? strm.output : strm.output.subarray(0, strm.next_out)); 15846 } 15847 } 15848 } // Must repeat iteration if out buffer is full 15849 15850 15851 if (status === Z_OK && last_avail_out === 0) continue; // Finalize if end of stream reached. 15852 15853 if (status === Z_STREAM_END) { 15854 status = inflate_1$2.inflateEnd(this.strm); 15855 this.onEnd(status); 15856 this.ended = true; 15857 return true; 15858 } 15859 15860 if (strm.avail_in === 0) break; 15861 } 15862 15863 return true; 15864 }; 15865 /** 15866 * Inflate#onData(chunk) -> Void 15867 * - chunk (Uint8Array|String): output data. When string output requested, 15868 * each chunk will be string. 15869 * 15870 * By default, stores data blocks in `chunks[]` property and glue 15871 * those in `onEnd`. Override this handler, if you need another behaviour. 15872 **/ 15873 15874 15875 Inflate$1.prototype.onData = function (chunk) { 15876 this.chunks.push(chunk); 15877 }; 15878 /** 15879 * Inflate#onEnd(status) -> Void 15880 * - status (Number): inflate status. 0 (Z_OK) on success, 15881 * other if not. 15882 * 15883 * Called either after you tell inflate that the input stream is 15884 * complete (Z_FINISH). By default - join collected chunks, 15885 * free memory and fill `results` / `err` properties. 15886 **/ 15887 15888 15889 Inflate$1.prototype.onEnd = function (status) { 15890 // On success - join 15891 if (status === Z_OK) { 15892 if (this.options.to === 'string') { 15893 this.result = this.chunks.join(''); 15894 } else { 15895 this.result = common.flattenChunks(this.chunks); 15896 } 15897 } 15898 15899 this.chunks = []; 15900 this.err = status; 15901 this.msg = this.strm.msg; 15902 }; 15903 /** 15904 * inflate(data[, options]) -> Uint8Array|String 15905 * - data (Uint8Array): input data to decompress. 15906 * - options (Object): zlib inflate options. 15907 * 15908 * Decompress `data` with inflate/ungzip and `options`. Autodetect 15909 * format via wrapper header by default. That's why we don't provide 15910 * separate `ungzip` method. 15911 * 15912 * Supported options are: 15913 * 15914 * - windowBits 15915 * 15916 * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced) 15917 * for more information. 15918 * 15919 * Sugar (options): 15920 * 15921 * - `raw` (Boolean) - say that we work with raw stream, if you don't wish to
15921specify 15922 * negative windowBits implicitly. 15923 * - `to` (String) - if equal to 'string', then result will be converted 15924 * from utf8 to utf16 (javascript) string. When string output requested, 15925 * chunk length can differ from `chunkSize`, depending on content. 15926 * 15927 * 15928 * ##### Example: 15929 * 15930 * ```javascript 15931 * const pako = require('pako'); 15932 * const input = pako.deflate(new Uint8Array([1,2,3,4,5,6,7,8,9])); 15933 * let output; 15934 * 15935 * try { 15936 * output = pako.inflate(input); 15937 * } catch (err) { 15938 * console.log(err); 15939 * } 15940 * ``` 15941 **/ 15942 15943 15944 function inflate$1(input, options) { 15945 const inflator = new Inflate$1(options); 15946 inflator.push(input); // That will never happens, if you don't cheat with options :) 15947 15948 if (inflator.err) throw inflator.msg || messages[inflator.err]; 15949 return inflator.result; 15950 } 15951 /** 15952 * inflateRaw(data[, options]) -> Uint8Array|String 15953 * - data (Uint8Array): input data to decompress. 15954 * - options (Object): zlib inflate options. 15955 * 15956 * The same as [[inflate]], but creates raw data, without wrapper 15957 * (header and adler32 crc). 15958 **/ 15959 15960 15961 function inflateRaw$1(input, options) { 15962 options = options || {}; 15963 options.raw = true; 15964 return inflate$1(input, options); 15965 } 15966 /** 15967 * ungzip(data[, options]) -> Uint8Array|String 15968 * - data (Uint8Array): input data to decompress. 15969 * - options (Object): zlib inflate options. 15970 * 15971 * Just shortcut to [[inflate]], because it autodetects format 15972 * by header.content. Done for convenience. 15973 **/ 15974 15975 15976 var Inflate_1$1 = Inflate$1; 15977 var inflate_2 = inflate$1; 15978 var inflateRaw_1$1 = inflateRaw$1; 15979 var ungzip$1 = inflate$1; 15980 var constants = constants$2; 15981 var inflate_1$1 = { 15982 Inflate: Inflate_1$1, 15983 inflate: inflate_2, 15984 inflateRaw: inflateRaw_1$1, 15985 ungzip: ungzip$1, 15986 constants: constants 15987 }; 15988 const { 15989 Deflate, 15990 deflate, 15991 deflateRaw, 15992 gzip 15993 } = deflate_1$1; 15994 const { 15995 Inflate, 15996 inflate: inflate$3, 15997 inflateRaw, 15998 ungzip: ungzip$2 15999 } = inflate_1$1; 16000 var Deflate_1 = Deflate; 16001 var deflate_1 = deflate; 16002 var deflateRaw_1 = deflateRaw; 16003 var gzip_1 = gzip; 16004 var Inflate_1 = Inflate; 16005 var inflate_1 = inflate$3; 16006 var inflateRaw_1 = inflateRaw; 16007 var ungzip_1 = ungzip$2; 16008 var constants_1 = constants$2; 16009 var pako = { 16010 Deflate: Deflate_1, 16011 deflate: deflate_1, 16012 deflateRaw: deflateRaw_1, 16013 gzip: gzip_1, 16014 Inflate: Inflate_1, 16015 inflate: inflate_1, 16016 inflateRaw: inflateRaw_1, 16017 ungzip: ungzip_1, 16018 constants: constants_1 16019 }; // Added by JTR 16020 // exports.Deflate = Deflate_1; 16021 // exports.Inflate = Inflate_1; 16022 // exports.constants = constants_1; 16023 // exports['default'] = pako; 16024 // exports.deflate = deflate_1; 16025 // exports.deflateRaw = deflateRaw_1; 16026 // exports.gzip = gzip_1; 16027 // exports.inflate = inflate_1; 16028 // exports.inflateRaw = inflateRaw_1; 16029 // exports.ungzip = ungzip_1; 16030 // Object.defineProperty(exports, '__esModule', { value: true }); 16031 // 16032 // }))); 16033 16034 pako.deflateRaw; 16035 pako.deflate; 16036 pako.inflateRaw; 16037 const inflate = pako.inflate; 16038 pako.gzip; 16039 const FEXTRA = 4; // gzip spec F.EXTRA flag 16040 16041 function isgzipped(data) { 16042 const b = ArrayBuffer.isView(data) ? data : new Uint8Array(data); 16043 return b[0] === 31 && b[1] === 139; 16044 } 16045 /** 16046 * Pako does not properly ungzip block compressed files if > 1 block is present. Test for bgzip and use wrapper. 16047 */ 16048 16049 16050 function ungzip(data) { 16051 const ba = ArrayBuffer.isView(data) ? data : new Uint8Array(data); 16052 const b = ba[3] & FEXTRA; 16053 16054 if (b !== 0 && ba[12] === 66 && ba[13] === 67) { 16055 return unbgzf(ba.buffer); 16056 } else { 16057 return pako.ungzip(ba); 16058 } 16059 } // Uncompress data, assumed to be series of bgzipped blocks 16060 16061 16062 function unbgzf(data, lim) { 16063 const oBlockList = []; 16064 let ptr = 0; 16065 let totalSize = 0; 16066 lim = lim || data.byteLength - 18; 16067 16068 while (ptr < lim) { 16069 try { 16070 const ba = ArrayBuffer.isView(data) ? data : new Uint8Array(data, ptr,
1607018); 16071 const xlen = ba[11] << 8 | ba[10]; 16072 const flg = ba[3]; 16073 const fextra = flg & FEXTRA; 16074 const si1 = ba[12]; 16075 const si2 = ba[13]; 16076 const slen = ba[15] << 8 | ba[14]; 16077 const bsize = (ba[17] << 8 | ba[16]) + 1; 16078 const start = 12 + xlen + ptr; // Start of CDATA 16079 16080 const bytesLeft = data.byteLength - start; 16081 const cDataSize = bsize - xlen - 19; 16082 if (bytesLeft < cDataSize || cDataSize <= 0) break; 16083 const a = new Uint8Array(data, start, cDataSize); 16084 const unc = pako.inflateRaw(a); // const inflate = new Zlib.RawInflate(a); 16085 // const unc = inflate.decompress(); 16086 16087 ptr += cDataSize - 1 + 26; //inflate.ip + 26 16088 16089 totalSize += unc.byteLength; 16090 oBlockList.push(unc); 16091 } catch (e) { 16092 console.error(e); 16093 break; 16094 } 16095 } // Concatenate decompressed blocks 16096 16097 16098 if (oBlockList.length === 1) { 16099 return oBlockList[0]; 16100 } else { 16101 const out = new Uint8Array(totalSize); 16102 let cursor = 0; 16103 16104 for (let i = 0; i < oBlockList.length; ++i) { 16105 var b = new Uint8Array(oBlockList[i]); 16106 arrayCopy(b, 0, out, cursor, b.length); 16107 cursor += b.length; 16108 } 16109 16110 return out; 16111 } 16112 } 16113 16114 function bgzBlockSize(data) { 16115 const ba = ArrayBuffer.isView(data) ? data : new Uint8Array(data); 16116 const bsize = (ba[17] << 8 | ba[16]) + 1; 16117 return bsize; 16118 } // From Thomas Down's zlib implementation 16119 16120 16121 const testArray = new Uint8Array(1); 16122 const hasSubarray = typeof testArray.subarray === 'function'; 16123 /* (typeof testArray.slice === 'function'); */ 16124 // Chrome slice performance is so dire that we're currently not using it... 16125 16126 function arrayCopy(src, srcOffset, dest, destOffset, count) { 16127 if (count === 0) { 16128 return; 16129 } 16130 16131 if (!src) { 16132 throw "Undef src"; 16133 } else if (!dest) { 16134 throw "Undef dest"; 16135 } 16136 16137 if (srcOffset === 0 && count === src.length) { 16138 arrayCopy_fast(src, dest, destOffset); 16139 } else if (hasSubarray) { 16140 arrayCopy_fast(src.subarray(srcOffset, srcOffset + count), dest, destOffset); 16141 } else if (src.BYTES_PER_ELEMENT === 1 && count > 100) { 16142 arrayCopy_fast(new Uint8Array(src.buffer, src.byteOffset + srcOffset, count), dest, destOffset); 16143 } else { 16144 arrayCopy_slow(src, srcOffset, dest, destOffset, count); 16145 } 16146 } 16147 16148 function arrayCopy_slow(src, srcOffset, dest, destOffset, count) { 16149 for (let i = 0; i < count; ++i) { 16150 dest[destOffset + i] = src[srcOffset + i]; 16151 } 16152 } 16153 16154 function arrayCopy_fast(src, dest, destOffset) {
16155 dest.set(src, destOffset); 16156 } 16157 /** 16158 * Compress string and encode in a url safe form 16159 * @param s 16160 */ 16161 16162 16163 function compressString(str) { 16164 const bytes = new Uint8Array(str.length); 16165 16166 for (var i = 0; i < str.length; i++) { 16167 bytes[i] = str.charCodeAt(i); 16168 } 16169 16170 const compressedBytes = new pako.deflateRaw(bytes); // UInt8Arry 16171 16172 const compressedString = String.fromCharCode.apply(null, compressedBytes); // Convert to string 16173 16174 let enc = btoa(compressedString); 16175 return enc.replace(/\+/g, '.').replace(/\//g, '_').replace(/=/g, '-'); // URL safe 16176 } 16177 /** 16178 * Uncompress the url-safe encoded compressed string, presumably created by compressString above 16179 * 16180 * @param enc 16181 * @returns {string} 16182 */ 16183 16184 16185 function uncompressString(enc) { 16186 enc = enc.replace(/\./g, '+').replace(/_/g, '/').replace(/-/g, '='); 16187 const compressedString = atob(enc); 16188 const compressedBytes = []; 16189 16190 for (let i = 0; i < compressedString.length; i++) { 16191 compressedBytes.push(compressedString.charCodeAt(i)); 16192 } //const bytes = new Zlib.RawInflate(compressedBytes).decompress(); 16193 16194 16195 const bytes = pako.inflateRaw(compressedBytes); 16196 let str = ''; 16197 16198 for (let b of bytes) { 16199 str += String.fromCharCode(b); 16200 } 16201 16202 return str; 16203 } 16204 /** 16205 * @param dataURI 16206 * @returns {Array<number>|Uint8Array} 16207 */ 16208 16209 16210 function decodeDataURI$1(dataURI, gzip) { 16211 const split = dataURI.split(','); 16212 const info = split[0].split(':')[1]; 16213 let dataString = split[1]; 16214 16215 if (info.indexOf('base64') >= 0) { 16216 dataString = atob(dataString); 16217 const bytes = new Uint8Array(dataString.length); 16218 16219 for (let i = 0; i < dataString.length; i++) { 16220 bytes[i] = dataString.charCodeAt(i); 16221 } 16222 16223 let plain; 16224 16225 if (gzip || info.indexOf('gzip') > 0) { 16226 plain = pako.ungzip(bytes); 16227 } else { 16228 plain = bytes; 16229 } 16230 16231 return plain; 16232 } else { 16233 return decodeURIComponent(dataString); // URL encoded string -- not currently used or tested 16234 } 16235 } 16236 16237 /* 16238 * The MIT License (MIT) 16239 * 16240 * Copyright (c) 2016-2017 The Regents of the University of California 16241 * Author: Jim Robinson 16242 * 16243 * Permission is hereby granted, free of charge, to any person obtaining a copy 16244 * of this software and associated documentation files (the "Software"), to deal 16245 * in the Software without restriction, including without limitation the rights 16246 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16247 * copies of the Software, and to permit persons to whom the Software is 16248 * furnished to do so, subject to the following conditions: 16249 * 16250 * The above copyright notice and this permission notice shall be included in 16251 * all copies or substantial portions of the Software. 16252 * 16253 * 16254 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16255 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16256 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16257 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16258 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 16259 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 16260 * THE SOFTWARE. 16261 */ 16262 const IGVMath = { 16263 lerp: (v0, v1, t) => { 16264 return (1 - t) * v0 + t * v1; 16265 }, 16266 mean: function (array) { 16267 var t = 0, 16268 n = 0, 16269 i; 16270 16271 for (i = 0; i < array.length; i++) { 16272 if (!isNaN(array[i])) { 16273 t += array[i]; 16274 n++; 16275 } 16276 } 16277 16278 return n > 0 ? t / n : 0; 16279 }, 16280 meanAndStdev: function (array) { 16281 var v, 16282 t = 0, 16283 t2 = 0, 16284 n = 0, 16285 i; 16286 16287 for (i = 0; i < array.length; i++) { 16288 v = array[i]; 16289 16290 if (!isNaN(v)) { 16291 t += v; 16292 t2 += v * v; 16293 n++; 16294 } 16295 } 16296 16297 return n > 0 ? { 16298 mean: t / n, 16299 stdev: Math.sqrt(t2 - t * t / n) 16300 } : { 16301 mean: 0, 16302 stdev: 0 16303 }; 16304 }, 16305 median: function (numbers) {
16306 // median of [3, 5, 4, 4, 1, 1, 2, 3] = 3 16307 var median = 0, 16308 numsLen = numbers.length; 16309 numbers.sort(); 16310 16311 if (numsLen % 2 === 0 // is even 16312 ) { 16313 // average of two middle numbers 16314 median = (numbers[numsLen / 2 - 1] + numbers[numsLen / 2]) / 2; 16315 } else { 16316 // is odd 16317 // middle number only 16318 median = numbers[(numsLen - 1) / 2]; 16319 } 16320 16321 return median; 16322 }, 16323 // Fast percentile function for "p" near edges. This needs profiled for p in middle (e.g. median) 16324 percentile: function (array, p) { 16325 if (array.length === 0) return undefined; 16326 var k = Math.floor(array.length * ((100 - p) / 100)); 16327 16328 if (k === 0) { 16329 array.sort(function (a, b) { 16330 return b - a; 16331 }); 16332 return array[k]; 16333 } else { 16334 return selectElement(array, k); 16335 } 16336 }, 16337 clamp: function (value, min, max) { 16338 return Math.min(Math.max(value, min), max); 16339 }, 16340 log2: function (x) { 16341 return Math.log(x) / Math.LN2; 16342 } 16343 }; 16344 16345 function selectElement(array, k) { 16346 // Credit Steve Hanov http://stevehanov.ca/blog/index.php?id=122 16347 var heap = new BinaryHeap(), 16348 i; 16349 16350 for (i = 0; i < array.length; i++) { 16351 var item = array[i]; // If we have not yet found k items, or the current item is larger than 16352 // the smallest item on the heap, add current item 16353 16354 if (heap.content.length < k || item > heap.content[0]) { 16355 // If the heap is full, remove the smallest element on the heap. 16356 if (heap.content.length === k) { 16357 heap.pop(); 16358 } 16359 16360 heap.push(item); 16361 } 16362 } 16363 16364 return heap.content[0]; 16365 } 16366 16367 function BinaryHeap() { 16368 this.content = []; 16369 } 16370 16371 BinaryHeap.prototype = { 16372 push: function (element) { 16373 // Add the new element to the end of the array. 16374 this.content.push(element); // Allow it to bubble up. 16375 16376 this.bubbleUp(this.content.length - 1); 16377 }, 16378 pop: function () { 16379 // Store the first element so we can return it later. 16380 var result = this.content[0]; // Get the element at the end of the array. 16381 16382 var end = this.content.pop(); // If there are any elements left, put the end element at the 16383 // start, and let it sink down. 16384 16385 if (this.content.length > 0) { 16386 this.content[0] = end; 16387 this.sinkDown(0); 16388 } 16389 16390 return result; 16391 }, 16392 remove: function (node) { 16393 var length = this.content.length; // To remove a value, we must search through the array to find 16394 // it. 16395 16396 for (var i = 0; i < length; i++) { 16397 if (this.content[i] !== node) continue; // When it is found, the process seen in 'pop' is repeated 16398 // to fill up the hole. 16399 16400 var end = this.content.pop(); // If the element we popped was the one we needed to remove, 16401 // we're done. 16402 16403 if (i === length - 1) break; // Otherwise, we replace the removed element with the popped 16404 // one, and allow it to float up or sink down as appropriate. 16405 16406 this.content[i] = end; 16407 this.bubbleUp(i); 16408 this.sinkDown(i); 16409 break; 16410 } 16411 }, 16412 size: function () { 16413 return this.content.length; 16414 }, 16415 bubbleUp: function (n) { 16416 // Fetch the element that has to be moved. 16417 var element = this.content[n], 16418 score = element; // When at 0, an element can not go up any further. 16419 16420 while (n > 0) { 16421 // Compute the parent element's index, and fetch it. 16422 var parentN = Math.floor((n + 1) / 2) - 1, 16423 parent = this.content[parentN]; // If the parent has a lesser score, things are in order and we 16424 // are done. 16425 16426 if (score >= parent) break; // Otherwise, swap the parent with the current element and 16427 // continue. 16428 16429 this.content[parentN] = element; 16430 this.content[n] = parent; 16431 n = parentN; 16432 } 16433 }, 16434 sinkDown: function (n) { 16435 // Look up the target element and its score. 16436 var length = this.content.length, 16437 element = this.content[n], 16438 elemScore = element; 16439 16440 while (true) { 16441 // Compute the indices of the child elements. 16442 var child2N = (n + 1) * 2, 16443 child1N = child2N - 1; // This is used to store the new position of the element, 16444 // if any. 16445 16446 var swap = null; // If the first child exists (is inside the array)... 16447 16448 if (child1N < length) { 16449 // Look it up and compute its score. 16450 var child1 = this.content[child1N], 16451 child1Score = child1; // If the score is less than our element's, we need to swap. 16452 16453 if (child1Score < elemScore) swap = child1N; 16454 } // Do the same checks for the other child. 16455 16456 16457 if (child2N < length) { 16458 var child2 = this.content[child2N], 16459 child2Score = child2; 16460 if (child2Score < (swap == null ? elemScore : child1Score)) swap = child2N; 16461 } // No need to swap further, we are done. 16462 16463 16464 if (swap == null) break; // Otherwise, swap and continue. 16465 16466 this.content[n] = this.content[swap]; 16467 this.content[swap] = element; 16468 n = swap; 16469 } 16470 } 16471 }; 16472 16473 /* 16474 * The MIT License (MIT) 16475 * 16476 * Copyright (c) 2014 Broad Institute 16477 * 16478 * Permission is hereby granted, free of charge, to any person obtaining a copy 16479 * of this software and associated documentation files (the "Software"), to deal 16480 * in the Software without restriction, including without limitation the rights 16481 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16482 * copies of the Software, and to permit persons to whom the Software is 16483 * furnished to do so, subject to the following conditions: 16484 * 16485 * The above copyright notice and this permission notice shall be included in 16486 * all copies or substantial portions of the Software. 16487 * 16488 * 16489 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16490 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16491 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16492 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16493 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 16494 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 16495 * THE SOFTWARE. 16496 */ 16497 16498 function _random(min, max) { 16499 return Math.random() * (max - min) + min; 16500 } 16501 16502 const IGVColor = { 16503 rgbListFromHSV: () => { 16504 let s = 1; 16505 let accumulation = []; 16506 16507 for (let v = 1; v >= 0.5; v -= .1) { 16508 for (let h = 0; h < 1; h += 1 / 28) { 16509 const r = "rgb(" + IGVColor.hsvToRgb(h, s, v).join(",") + ")"; 16510 accumulation.push(r); 16511 } 16512 } // add black 16513 16514 16515 accumulation.pop(); 16516 accumulation.push(IGVColor.rgbColor(16, 16, 16)); 16517 return accumulation; 16518 }, 16519 rgbToHex: function (rgb) { 16520 rgb = rgb.match(/^rgba?[\s+]?\([\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?/i); 16521 return rgb && rgb.length === 4 ? "#" + ("0" + parseInt(rgb[1], 10).toString(16)).slice(-2) + ("0" + parseInt(rgb[2], 10).toString(16)).slice(-2) + ("0" + parseInt(rgb[3], 10).toString(16)).slice(-2) : ''; 16522 }, 16523 hexToRgb: function (hex) { 16524 var cooked = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); 16525 16526 if (null === cooked) { 16527 return undefined; 16528 } 16529 16530 return "rgb(" + parseInt(cooked[1], 16) + "," + parseInt(cooked[2], 16) + "," + parseInt(cooked[3], 16) + ")"; 16531 }, 16532 16533 /** 16534 * Converts an HSV color value to RGB. Conversion formula 16535 * adapted from http://en.wikipedia.org/wiki/HSV_color_space. 16536 * Assumes h, s, and v are contained in the set [0, 1] and 16537 * returns r, g, and b in the set [0, 255]. 16538 * 16539 * Credit: https://gist.githubusercontent.com/mjackson/5311256 16540 * 16541 * @param h The hue 16542 * @param s The saturation 16543 * @param v The value 16544 * @return Array The RGB representation 16545 */ 16546 hsvToRgb: function (h, s, v) { 16547 var r, g, b; 16548 var i = Math.floor(h * 6); 16549 var f = h * 6 - i; 16550 var p = v * (1 - s); 16551 var q = v * (1 - f * s); 16552 var t = v * (1 - (1 - f) * s); 16553 16554 switch (i % 6) { 16555 case 0: 16556 r = v, g = t, b = p; 16557 break; 16558 16559 case 1: 16560 r = q, g = v, b = p; 16561 break; 16562 16563 case 2: 16564 r = p, g = v, b = t; 16565 break; 16566 16567 case 3: 16568 r = p, g = q, b = v; 16569 break; 16570 16571 case 4: 16572 r = t, g = p, b = v; 16573 break; 16574 16575 case 5: 16576 r = v, g = p, b = q; 16577 break; 16578 } 16579 16580 return [Math.floor(r * 255), Math.floor(g * 255), Math.floor(b * 255)]; 16581 }, 16582 16583 /** 16584 * Converts an HSL color value to RGB. Conversion formula 16585 * adapted from http://en.wikipedia.org/wiki/HSL_color_space. 16586 * Assumes h, s, and l are contained in the set [0, 1] and 16587 * returns r, g, and b in the set [0, 255]. 16588 * 16589 * Credit: https://gist.githubusercontent.com/mjackson/5311256 16590 * 16591 * @param h The hue 16592 * @param s The saturation 16593 * @param l The lightness 16594 * @return Array The RGB representation 16595 */ 16596 hslToRgb: function (h, s, l) { 16597 var r, g, b; 16598 16599 if (s === 0) { 16600 r = g = b = l; // achromatic 16601 } else { 16602 var q = l < 0.5 ? l * (1 + s) : l + s - l * s; 16603 var p = 2 * l - q; 16604 r = IGVColor.hue2rgb(p, q, h + 1 / 3); 16605 g = IGVColor.hue2rgb(p, q, h); 16606 b = IGVColor.hue2rgb(p, q, h - 1 / 3); 16607 } 16608 16609 return [r * 255, g * 255, b * 255]; 16610 }, 16611 hue2rgb: (p, q, t) => { 16612 if (t < 0) t += 1; 16613 if (t > 1) t -= 1; 16614 if (t < 1 / 6) return p + (q - p) * 6 * t; 16615 if (t < 1 / 2) return q; 16616 if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6; 16617 return p; 16618 }, 16619 rgbaColor: function (r, g, b, a) { 16620 r = IGVMath.clamp(r, 0, 255); 16621 g = IGVMath.clamp(g, 0, 255); 16622 b = IGVMath.clamp(b, 0, 255); 16623 a = IGVMath.clamp(a, 0.0, 1.0); 16624 return "rgba(" + r + "," + g + "," + b + "," + a + ")"; 16625 }, 16626 rgbColor: function (r, g, b) { 16627 r = IGVMath.clamp(r, 0, 255); 16628 g = IGVMath.clamp(g, 0, 255); 16629 b = IGVMath.clamp(b, 0, 255); 16630 return "rgb(" + r + "," + g + "," + b + ")"; 16631 }, 16632 greyScale: function (value) { 16633 var grey = IGVMath.clamp(value, 0, 255); 16634 return "rgb(" + grey + "," + grey + "," + grey + ")"; 16635 }, 16636 randomGrey: function (min, max) { 16637 min = IGVMath.clamp(min, 0, 255); 16638 max = IGVMath.clamp(max, 0, 255); 16639 var g = Math.round(_random(min, max)).toString(10); 16640 return "rgb(" + g + "," + g + "," + g + ")"; 16641 }, 16642 randomRGB: function (min, max) { 16643 min = IGVMath.clamp(min, 0, 255); 16644 max = IGVMath.clamp(max, 0, 255); 16645 var r = Math.round(_random(min, max)).toString(10); 16646 var g = Math.round(_random(min, max)).toString(10); 16647 var b = Math.round(_random(min, max)).toString(10); 16648 return "rgb(" + r + "," + g + "," + b + ")"; 16649 }, 16650 randomRGBConstantAlpha: function (min, max, alpha) { 16651 min = IGVMath.clamp(min, 0, 255); 16652 max = IGVMath.clamp(max, 0, 255); 16653 var r = Math.round(_random(min, max)).toString(10); 16654 var g = Math.round(_random(min, max)).toString(10); 16655 var b = Math.round(_random(min, max)).toString(10); 16656 return "rgba(" + r + "," + g + "," + b + "," + alpha + ")"; 16657 }, 16658 addAlpha: function (color, alpha) { 16659 if (color === "0" || color === ".") { 16660 color = "rgb(0,0,0)"; 16661 } else { 16662 const c = this.colorNameToHex(color); 16663 16664 if (c) { 16665 color = c; 16666 } 16667 } 16668 16669 var isHex = /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(color); 16670 16671 if (color.startsWith("rgba")) { 16672 const idx = color.lastIndexOf(","); 16673 return color.substring(0, idx + 1) + alpha.toString() + ")"; 16674 } 16675 16676 if (isHex) { 16677 color = IGVColor.hexToRgb(color); 16678 } 16679 16680 if (color.startsWith("rgb")) { 16681 return color.replace("rgb", "rgba").replace(")", ", " + alpha + ")"); 16682 } else { 16683 console.log(color + " is not an rgb style string"); 16684 return color; 16685 } 16686 }, 16687 rgbComponents: function (color) { 16688 if (color === "0" || color === ".") { 16689 return [0, 0, 0]; 16690 } 16691 16692 const isHex = /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(color); 16693 16694 if (isHex) { 16695 color = IGVColor.hexToRgb(color); 16696 } else { 16697 if (!color.startsWith("rgb")) { 16698 const hex = this.colorNameToHex(color); 16699 color = this.hexToRgb(hex); 16700 } 16701 } 16702 16703 if (color.startsWith("rgb(")) { 16704 return color.substring(4, color.length - 1).split(",").map(s => Number.parseInt(s.trim())); 16705 } else if (color.startsWith("rgba(")) { 16706 return color.substring(5, color.length - 1).split(",").map((s, i) => { 16707 s = s.trim(); 16708 return i === 3 ? Number.parseFloat(s) : Number.parseInt(s); 16709 }); 16710 } else { 16711 throw Error("Unrecognized color string: color"); 16712 } 16713 }, 16714 16715 /** 16716 * 16717 * @param dest RGB components as an array 16718 * @param src RGB components as an array 16719 * @param alpha alpha transparancy in the range 0-1 16720 * @returns {} 16721 */
16722 getCompositeColor: function (dest, src, alpha) { 16723 var r = Math.floor(alpha * src[0] + (1 - alpha) * dest[0]), 16724 g = Math.floor(alpha * src[1] + (1 - alpha) * dest[1]), 16725 b = Math.floor(alpha * src[2] + (1 - alpha) * dest[2]); 16726 return "rgb(" + r + "," + g + "," + b + ")"; 16727 }, 16728 createColorString: function (str) { 16729 // Excel will quote color strings, strip all quotes 16730 str = stripQuotes$1(str); 16731 16732 if (str.includes(",")) { 16733 return str.startsWith("rgb") ? str : "rgb(" + str + ")"; 16734 } else { 16735 return str; 16736 } 16737 }, 16738 darkenLighten: function (color, amt) { 16739 let src; 16740 let hexColor = this.colorNameToHex(color); 16741 16742 if (hexColor) { 16743 src = IGVColor.hexToRgb(hexColor); 16744 } else { 16745 src = color.startsWith('rgb(') ? color : IGVColor.hexToRgb(color); 16746 } 16747 16748 const components = src.replace(")", "").substring(4).split(","); 16749 const r = Math.max(0, Math.min(255, Number.parseInt(components[0].trim()) + amt)); 16750 const g = Math.max(0, Math.min(255, Number.parseInt(components[1].trim()) + amt)); 16751 const b = Math.max(0, Math.min(255, Number.parseInt(components[2].trim()) + amt)); 16752 return 'rgb(' + r.toString() + ',' + g.toString() + ',' + b.toString() + ')'; 16753 }, 16754 16755 /** 16756 * Convert html/css color name to hex value. Adapted from https://gist.github.com/mxfh/4719348 16757 * @param colorName 16758 * @returns {*} 16759 */ 16760 colorNameToHex: function (colorName) { 16761 // color list from http://stackoverflow.com/q/1573053/731179 with added gray/gray 16762 const definedColorNames = { 16763 "aliceblue": "#f0f8ff", 16764 "antiquewhite": "#faebd7", 16765 "aqua": "#00ffff", 16766 "aquamarine": "#7fffd4", 16767 "azure": "#f0ffff", 16768 "beige": "#f5f5dc", 16769 "bisque": "#ffe4c4", 16770 "black": "#000000", 16771 "blanchedalmond": "#ffebcd", 16772 "blue": "#0000ff", 16773 "blueviolet": "#8a2be2", 16774 "brown": "#a52a2a", 16775 "burlywood": "#deb887", 16776 "cadetblue": "#5f9ea0", 16777 "chartreuse": "#7fff00", 16778 "chocolate": "#d2691e", 16779 "coral": "#ff7f50", 16780 "cornflowerblue": "#6495ed", 16781 "cornsilk": "#fff8dc", 16782 "crimson": "#dc143c", 16783 "cyan": "#00ffff", 16784 "darkblue": "#00008b", 16785 "darkcyan": "#008b8b", 16786 "darkgoldenrod": "#b8860b", 16787 "darkgray": "#a9a9a9", 16788 "darkgreen": "#006400", 16789 "darkkhaki": "#bdb76b", 16790 "darkmagenta": "#8b008b", 16791 "darkolivegreen": "#556b2f", 16792 "darkorange": "#ff8c00", 16793 "darkorchid": "#9932cc", 16794 "darkred": "#8b0000", 16795 "darksalmon": "#e9967a", 16796 "darkseagreen": "#8fbc8f", 16797 "darkslateblue": "#483d8b", 16798 "darkslategray": "#2f4f4f", 16799 "darkturquoise": "#00ced1", 16800 "darkviolet": "#9400d3", 16801 "deeppink": "#ff1493", 16802 "deepskyblue": "#00bfff", 16803 "dimgray": "#696969", 16804 "dodgerblue": "#1e90ff", 16805 "firebrick": "#b22222", 16806 "floralwhite": "#fffaf0", 16807 "forestgreen": "#228b22", 16808 "fuchsia": "#ff00ff", 16809 "gainsboro": "#dcdcdc", 16810 "ghostwhite": "#f8f8ff", 16811 "gold": "#ffd700", 16812 "goldenrod": "#daa520", 16813 "gray": "#808080", 16814 "green": "#008000", 16815 "greenyellow": "#adff2f", 16816 "honeydew": "#f0fff0", 16817 "hotpink": "#ff69b4", 16818 "indianred ": "#cd5c5c", 16819 "indigo ": "#4b0082", 16820 "ivory": "#fffff0", 16821 "khaki": "#f0e68c", 16822 "lavender": "#e6e6fa", 16823 "lavenderblush": "#fff0f5", 16824 "lawngreen": "#7cfc00", 16825 "lemonchiffon": "#fffacd", 16826 "lightblue": "#add8e6", 16827 "lightcoral": "#f08080", 16828 "lightcyan": "#e0ffff", 16829 "lightgoldenrodyellow": "#fafad2", 16830 "lightgrey": "#d3d3d3", 16831 "lightgreen": "#90ee90", 16832 "lightpink": "#ffb6c1", 16833 "lightsalmon": "#ffa07a", 16834 "lightseagreen": "#20b2aa", 16835 "lightskyblue": "#87cefa", 16836 "lightslategray": "#778899", 16837 "lightsteelblue": "#b0c4de", 16838 "lightyellow": "#ffffe0", 16839 "lime": "#00ff00", 16840 "limegreen": "#32cd32", 16841 "linen": "#faf0e6", 16842 "magenta": "#ff00ff", 16843 "maroon": "#800000", 16844 "mediumaquamarine": "#66cdaa", 16845 "mediumblue": "#0000cd", 16846 "mediumorchid": "#ba55d3", 16847 "mediumpurple": "#9370d8", 16848 "mediumseagreen": "#3cb371", 16849 "mediumslateblue": "#7b68ee", 16850 "mediumspringgreen": "#00fa9a",
16851 "mediumturquoise": "#48d1cc", 16852 "mediumvioletred": "#c71585", 16853 "midnightblue": "#191970", 16854 "mintcream": "#f5fffa", 16855 "mistyrose": "#ffe4e1", 16856 "moccasin": "#ffe4b5", 16857 "navajowhite": "#ffdead", 16858 "navy": "#000080", 16859 "oldlace": "#fdf5e6", 16860 "olive": "#808000", 16861 "olivedrab": "#6b8e23", 16862 "orange": "#ffa500", 16863 "orangered": "#ff4500", 16864 "orchid": "#da70d6", 16865 "palegoldenrod": "#eee8aa", 16866 "palegreen": "#98fb98", 16867 "paleturquoise": "#afeeee", 16868 "palevioletred": "#d87093", 16869 "papayawhip": "#ffefd5", 16870 "peachpuff": "#ffdab9", 16871 "peru": "#cd853f", 16872 "pink": "#ffc0cb", 16873 "plum": "#dda0dd", 16874 "powderblue": "#b0e0e6", 16875 "purple": "#800080", 16876 "red": "#ff0000", 16877 "rosybrown": "#bc8f8f", 16878 "royalblue": "#4169e1", 16879 "saddlebrown": "#8b4513", 16880 "salmon": "#fa8072", 16881 "sandybrown": "#f4a460", 16882 "seagreen": "#2e8b57", 16883 "seashell": "#fff5ee", 16884 "sienna": "#a0522d", 16885 "silver": "#c0c0c0", 16886 "skyblue": "#87ceeb", 16887 "slateblue": "#6a5acd", 16888 "slategray": "#708090", 16889 "snow": "#fffafa", 16890 "springgreen": "#00ff7f", 16891 "steelblue": "#4682b4", 16892 "tan": "#d2b48c", 16893 "teal": "#008080", 16894 "thistle": "#d8bfd8", 16895 "tomato": "#ff6347", 16896 "turquoise": "#40e0d0", 16897 "violet": "#ee82ee", 16898 "wheat": "#f5deb3", 16899 "white": "#ffffff", 16900 "whitesmoke": "#f5f5f5", 16901 "yellow": "#ffff00", 16902 "yellowgreen": "#9acd32", 16903 "darkgrey": "#a9a9a9", 16904 "darkslategrey": "#2f4f4f", 16905 "dimgrey": "#696969", 16906 "grey": "#808080", 16907 "lightgray": "#d3d3d3", 16908 "lightslategrey": "#778899", 16909 "slategrey": "#708090" 16910 }; 16911 return definedColorNames[colorName]; 16912 } 16913 }; 16914 16915 /** 16916 * Make the target element movable by clicking and dragging on the handle. This is not a general purprose function, 16917 * it makes several options specific to igv dialogs, the primary one being that the 16918 * target is absolutely positioned in pixel coordinates 16919 16920 */ 16921 let dragData$1; // Its assumed we are only dragging one element at a time. 16922 16923 function makeDraggable$1(target, handle) { 16924 handle.addEventListener('mousedown', dragStart$1.bind(target)); 16925 } 16926 16927 function dragStart$1(event) { 16928 event.stopPropagation(); 16929 event.preventDefault(); 16930 offset$1(this); 16931 const dragFunction = drag$1.bind(this); 16932 const dragEndFunction = dragEnd$1.bind(this); 16933 const computedStyle = getComputedStyle(this); 16934 const top = parseInt(computedStyle.top.replace("px", "")); 16935 const left = parseInt(computedStyle.left.replace("px", "")); 16936 dragData$1 = { 16937 dragFunction: dragFunction, 16938 dragEndFunction: dragEndFunction, 16939 screenX: event.screenX, 16940 screenY: event.screenY, 16941 top: top, 16942 left: left 16943 }; 16944 document.addEventListener('mousemove', dragFunction); 16945 document.addEventListener('mouseup', dragEndFunction); 16946 document.addEventListener('mouseleave', dragEndFunction); 16947 document.addEventListener('mouseexit', dragEndFunction); 16948 } 16949 16950 function drag$1(event) { 16951 if (!dragData$1) { 16952 console.log("No drag data!"); 16953 return; 16954 } 16955 16956 event.stopPropagation(); 16957 event.preventDefault(); 16958 const dx = event.screenX - dragData$1.screenX; 16959 const dy = event.screenY - dragData$1.screenY; 16960 this.style.left = `${dragData$1.left + dx}px`; 16961 this.style.top = `${dragData$1.top + dy}px`; 16962 } 16963 16964 function dragEnd$1(event) { 16965 if (!dragData$1) { 16966 console.log("No drag data!"); 16967 return; 16968 } 16969 16970 event.stopPropagation(); 16971 event.preventDefault(); 16972 const dragFunction = dragData$1.dragFunction; 16973 const dragEndFunction = dragData$1.dragEndFunction; 16974 document.removeEventListener('mousemove', dragFunction); 16975 document.removeEventListener('mouseup', dragEndFunction); 16976 document.removeEventListener('mouseleave', dragEndFunction); 16977 document.removeEventListener('mouseexit', dragEndFunction); 16978 dragData$1 = undefined; 16979 } 16980 16981 const appleCrayonPalette$1 = { 16982 licorice: "#000000", 16983 lead: "#1e1e1e", 16984 tungsten: "#3a3a3a", 16985 iron: "#545453", 16986 steel: "#6e6e6e", 16987 tin: "#878687", 16988 nickel: "#888787", 16989 aluminum: "#a09fa0", 16990 magnesium: "#b8b8b8", 16991 silver: "#d0d0d0", 16992 mercury: "#e8e8e8", 16993 snow: "#ffffff", 16994 // 16995 cayenne: "#891100", 16996 mocha: "#894800", 16997 aspargus: "#888501", 16998 fern: "#458401", 16999 clover: "#028401", 17000 moss: "#018448", 17001 teal: "#008688", 17002 ocean: "#004a88", 17003 midnight: "#001888", 17004 eggplant: "#491a88", 17005 plum: "#891e88", 17006 maroon: "#891648", 17007 // 17008 maraschino: "#ff2101", 17009 tangerine: "#ff8802", 17010 lemon: "#fffa03", 17011 lime: "#83f902", 17012 spring: "#05f802", 17013 seam_foam: "#03f987", 17014 turquoise: "#00fdff", 17015 aqua: "#008cff", 17016 blueberry: "#002eff", 17017 grape: "#8931ff", 17018 magenta: "#ff39ff", 17019 strawberry: "#ff2987", 17020 // 17021 salmon: "#ff726e", 17022 cantaloupe: "#ffce6e", 17023 banana: "#fffb6d", 17024 honeydew: "#cefa6e", 17025 flora: "#68f96e", 17026 spindrift: "#68fbd0", 17027 ice: "#68fdff", 17028 sky: "#6acfff", 17029 orchid: "#6e76ff", 17030 lavender: "#d278ff", 17031 bubblegum: "#ff7aff", 17032 carnation: "#ff7fd3" 17033 }; 17034
17035 // Support for oauth token based authorization 17036 // This class supports explicit setting of an oauth token either globally or for specific hosts. 17037 // 17038 // The variable oauth.google.access_token, which becomes igv.oauth.google.access_token on ES5 conversion is 17039 // supported for backward compatibility 17040 const DEFAULT_HOST = "googleapis"; 17041 const oauth = { 17042 oauthTokens: {}, 17043 setToken: function (token, host) { 17044 host = host || DEFAULT_HOST; 17045 this.oauthTokens[host] = token; 17046 17047 if (host === DEFAULT_HOST) { 17048 this.google.access_token = token; // legacy support 17049 } 17050 }, 17051 getToken: function (host) { 17052 host = host || DEFAULT_HOST; 17053 let token; 17054 17055 for (let key of Object.keys(this.oauthTokens)) { 17056 const regex = wildcardToRegExp(key); 17057 17058 if (regex.test(host)) { 17059 token = this.oauthTokens[key]; 17060 break; 17061 } 17062 } 17063 17064 return token; 17065 }, 17066 removeToken: function (host) { 17067 host = host || DEFAULT_HOST; 17068 17069 for (let key of Object.keys(this.oauthTokens)) { 17070 const regex = wildcardToRegExp(key); 17071 17072 if (regex.test(host)) { 17073 this.oauthTokens[key] = undefined; 17074 } 17075 } 17076 17077 if (host === DEFAULT_HOST) { 17078 this.google.access_token = undefined; // legacy support 17079 } 17080 }, 17081 // Special object for google -- legacy support 17082 google: { 17083 setToken: function (token) { 17084 oauth.setToken(token); 17085 } 17086 } 17087 }; 17088 /** 17089 * Creates a RegExp from the given string, converting asterisks to .* expressions, 17090 * and escaping all other characters. 17091 * 17092 * credit https://gist.github.com/donmccurdy/6d073ce2c6f3951312dfa45da14a420f 17093 */ 17094 17095 function wildcardToRegExp(s) { 17096 return new RegExp('^' + s.split(/\*+/).map(regExpEscape).join('.*') + '$'); 17097 } 17098 /** 17099 * RegExp-escapes all characters in the given string. 17100 * 17101 * credit https://gist.github.com/donmccurdy/6d073ce2c6f3951312dfa45da14a420f 17102 */ 17103 17104 17105 function regExpEscape(s) { 17106 return s.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&'); 17107 } 17108 17109 // The MIT License (MIT) 17110 /** 17111 * @constructor 17112 * @param {Object} options A set op options to pass to the throttle function 17113 * @param {number} requestsPerSecond The amount of requests per second 17114 * the library will limit to 17115 */ 17116 17117 class Throttle { 17118 constructor(options) { 17119 this.requestsPerSecond = options.requestsPerSecond || 10; 17120 this.lastStartTime = 0; 17121 this.queued = []; 17122 } 17123 /** 17124 * Adds a promise 17125 * @param {Function} async function to be executed 17126 * @param {Object} options A set of options. 17127 * @return {Promise} A promise 17128 */ 17129 17130 17131 add(asyncFunction, options) { 17132 var self = this; 17133 return new Promise(function (resolve, reject) { 17134 self.queued.push({ 17135 resolve: resolve, 17136 reject: reject, 17137 asyncFunction: asyncFunction 17138 }); 17139 self.dequeue(); 17140 }); 17141 } 17142 /** 17143 * Adds all the promises passed as parameters 17144 * @param {Function} promises An array of functions that return a promise 17145 * @param {Object} options A set of options. 17146 * @param {number} options.signal An AbortSignal object that can be used to abort the returned promise 17147 * @param {number} options.weight A "weight" of each operation resolving by array of promises 17148 * @return {Promise} A promise that succeeds when all the promises passed as options do 17149 */ 17150 17151 17152 addAll(promises, options) { 17153 var addedPromises = promises.map(function (promise) { 17154 return this.add(promise, options); 17155 }.bind(this)); 17156 return Promise.all(addedPromises); 17157 } 17158 17159 /** 17160 * Dequeues a promise 17161 * @return {void} 17162 */ 17163 dequeue() { 17164 if (this.queued.length > 0) { 17165 var now = new Date(), 17166 inc = 1000 / this.requestsPerSecond + 1,
17167 elapsed = now - this.lastStartTime; 17168 17169 if (elapsed >= inc) { 17170 this._execute(); 17171 } else { 17172 // we have reached the limit, schedule a dequeue operation 17173 setTimeout(function () { 17174 this.dequeue(); 17175 }.bind(this), inc - elapsed); 17176 } 17177 } 17178 } 17179 /** 17180 * Executes the promise 17181 * @private 17182 * @return {void} 17183 */ 17184 17185 17186 async _execute() { 17187 this.lastStartTime = new Date(); 17188 var candidate = this.queued.shift(); 17189 const f = candidate.asyncFunction; 17190 17191 try { 17192 const r = await f(); 17193 candidate.resolve(r); 17194 } catch (e) { 17195 candidate.reject(e); 17196 } 17197 } 17198 17199 } 17200 17201 /* 17202 * The MIT License (MIT) 17203 * 17204 * Copyright (c) 2014 Broad Institute 17205 * 17206 * Permission is hereby granted, free of charge, to any person obtaining a copy 17207 * of this software and associated documentation files (the "Software"), to deal 17208 * in the Software without restriction, including without limitation the rights 17209 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17210 * copies of the Software, and to permit persons to whom the Software is 17211 * furnished to do so, subject to the following conditions: 17212 * 17213 * The above copyright notice and this permission notice shall be included in 17214 * all copies or substantial portions of the Software. 17215 * 17216 * 17217 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17218 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17219 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17220 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17221 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 17222 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 17223 * THE SOFTWARE. 17224 */ 17225 let RANGE_WARNING_GIVEN = false; 17226 const googleThrottle = new Throttle({ 17227 requestsPerSecond: 8 17228 }); 17229 const igvxhr = { 17230 apiKey: undefined, 17231 setApiKey: function (key) { 17232 this.apiKey = key; 17233 }, 17234 load: load, 17235 loadArrayBuffer: async function (url, options) { 17236 options = options || {}; 17237 17238 if (!options.responseType) { 17239 options.responseType = "arraybuffer"; 17240 } 17241 17242 if (isFile(url)) { 17243 return loadFileSlice(url, options); 17244 } else { 17245 return load(url, options); 17246 } 17247 }, 17248 loadJson: async function (url, options) { 17249 options = options || {}; 17250 const method = options.method || (options.sendData ? "POST" : "GET"); 17251 17252 if (method === "POST") { 17253 options.contentType = "application/json"; 17254 } 17255 17256 const result = await this.loadString(url, options); 17257 17258 if (result) { 17259 return JSON.parse(result); 17260 } else { 17261 return result; 17262 } 17263 }, 17264 loadString: async function (path, options) { 17265 options = options || {}; 17266 17267 if (path instanceof File) { 17268 return loadStringFromFile(path, options); 17269 } else { 17270 return loadStringFromUrl(path, options); 17271 } 17272 } 17273 }; 17274 17275 async function load(url, options) { 17276 options = options || {}; 17277 const urlType = typeof url; // Resolve functions, promises, and functions that return promises 17278 17279 url = await (typeof url === 'function' ? url() : url); 17280 17281 if (isFile(url)) { 17282 return loadFileSlice(url, options); 17283 } else if (typeof url.startsWith === 'function') { 17284 // Test for string 17285 if (url.startsWith("data:")) { 17286 const buffer = decodeDataURI$1(url).buffer; 17287 17288 if (options.range) { 17289 const rangeEnd = options.range.size ? options.range.start + options.range.size : buffer.byteLength; 17290 return buffer.slice(options.range.start, rangeEnd); 17291 } else { 17292 return buffer; 17293 } 17294 } else { 17295 if (url.startsWith("https://drive.google.com")) { 17296 url = driveDownloadURL(url); 17297 } 17298 17299 if (isGoogleDriveURL(url) || url.startsWith("https://www.dropbox.com")) { 17300 return googleThrottle.add(async function () { 17301 return loadURL(url, options); 17302 }); 17303 } else { 17304 return loadURL(url, options); 17305 } 17306 } 17307 } else { 17308 throw Error(`url must be either a 'File', 'string', 'function', or 'Promise'. Actual type: ${urlType}`); 17309 } 17310 } 17311 17312 async function loadURL(url, options) { 17313 //console.log(`${Date.now()} ${url}`) 17314 url = mapUrl(url); 17315 options = options || {}; 17316 let oauthToken = options.oauthToken || getOauthToken(url); 17317 17318 if (oauthToken) { 17319 oauthToken = await (typeof oauthToken === 'function' ? oauthToken() : oauthToken); 17320 } 17321 17322 return new Promise(function (resolve, reject) { 17323 // Various Google tansformations 17324 if (isGoogleURL(url)) { 17325 if (isGoogleStorageURL(url)) { 17326 url = translateGoogleCloudURL(url); 17327 } 17328 17329 url = addApiKey(url); 17330 17331 if (isGoogleDriveURL(url)) { 17332 addTeamDrive(url); 17333 } // If we have an access token try it, but don't force a signIn or request for scopes yet 17334 17335 17336 if (!oauthToken) { 17337 oauthToken = getCurrentGoogleAccessToken(); 17338 } 17339 } 17340 17341 const headers = options.headers || {}; 17342 17343 if (oauthToken) { 17344 addOauthHeaders(headers, oauthToken); 17345 } 17346 17347 const range = options.range; 17348 const isChrome = navigator.userAgent.indexOf('Chrome') > -1; 17349 navigator.vendor.indexOf("Apple") === 0 && /\sSafari\//.test(navigator.userAgent); 17350 17351 if (range && isChrome && !isAmazonV4Signed(url)) { 17352 // Hack to prevent caching for byte-ranges. Attempt to fix net:err-cache errors in Chrome 17353 url += url.includes("?") ? "&" : "?"; 17354 url += "someRandomSeed=" + Math.random().toString(36); 17355 } 17356 17357 const xhr = new XMLHttpRequest(); 17358 const sendData = options.sendData || options.body; 17359 const method = options.method || (sendData ? "POST" : "GET"); 17360 const responseType = options.responseType; 17361 const contentType = options.contentType; 17362 const mimeType = options.mimeType; 17363 xhr.open(method, url); 17364 17365 if (options.timeout) { 17366 xhr.timeout = options.timeout; 17367 } 17368 17369 if (range) { 17370 var rangeEnd = range.size ? range.start + range.size - 1 : ""; 17371 xhr.setRequestHeader("Range", "bytes=" + range.start + "-" + rangeEnd);
17371 // xhr.setRequestHeader("Cache-Control", "no-cache"); <= This can cause CORS issues, disabled for now 17372 } 17373 17374 if (contentType) { 17375 xhr.setRequestHeader("Content-Type", contentType); 17376 } 17377 17378 if (mimeType) { 17379 xhr.overrideMimeType(mimeType); 17380 } 17381 17382 if (responseType) { 17383 xhr.responseType = responseType; 17384 } 17385 17386 if (headers) { 17387 for (let key of Object.keys(headers)) { 17388 const value = headers[key]; 17389 xhr.setRequestHeader(key, value); 17390 } 17391 } // NOTE: using withCredentials with servers that return "*" for access-allowed-origin will fail 17392 17393 17394 if (options.withCredentials === true) { 17395 xhr.withCredentials = true; 17396 } 17397 17398 xhr.onload = async function (event) { 17399 // when the url points to a local file, the status is 0 but that is not an error 17400 if (xhr.status === 0 || xhr.status >= 200 && xhr.status <= 300) { 17401 if (range && xhr.status !== 206 && range.start !== 0) { 17402 // For small files a range starting at 0 can return the whole file => 200 17403 // Provide just the slice we asked for, throw out the rest quietly 17404 // If file is large warn user 17405 if (xhr.response.length > 100000 && !RANGE_WARNING_GIVEN) { 17406 alert(`Warning: Range header ignored for URL: ${url}. This can have performance impacts.`); 17407 } 17408 17409 resolve(xhr.response.slice(range.start, range.start + range.size)); 17410 } else { 17411 resolve(xhr.response); 17412 } 17413 } else if (typeof gapi !== "undefined" && (xhr.status === 404 || xhr.status === 401 || xhr.status === 403) && isGoogleURL(url) && !options.retries) { 17414 tryGoogleAuth(); 17415 } else { 17416 if (xhr.status === 403) { 17417 handleError("Access forbidden: " + url); 17418 } else if (xhr.status === 416) { 17419 // Tried to read off the end of the file. This shouldn't happen, but if it does return an 17420 handleError("Unsatisfiable range"); 17421 } else { 17422 handleError(xhr.status); 17423 } 17424 } 17425 }; 17426 17427 xhr.onerror = function (event) { 17428 if (isGoogleURL(url) && !options.retries) { 17429 tryGoogleAuth(); 17430 } 17431 17432 handleError("Error accessing resource: " + url + " Status: " + xhr.status); 17433 }; 17434 17435 xhr.ontimeout = function (event) { 17436 handleError("Timed out"); 17437 }; 17438 17439 xhr.onabort = function (event) { 17440 console.log("Aborted"); 17441 reject(event); 17442 }; 17443 17444 try { 17445 xhr.send(sendData); 17446 } catch (e) { 17447 reject(e); 17448 } 17449 17450 function handleError(error) { 17451 if (reject) { 17452 reject(error); 17453 } else { 17454 throw error; 17455 } 17456 } 17457 17458 async function tryGoogleAuth() { 17459 try { 17460 const accessToken = await fetchGoogleAccessToken(url); 17461 options.retries = 1; 17462 options.oauthToken = accessToken; 17463 const response = await load(url, options); 17464 resolve(response); 17465 } catch (e) { 17466 if (e.error) { 17467 const msg = e.error.startsWith("popup_blocked") ? "Google login popup blocked by browser." : e.error; 17468 alert(msg); 17469 } else { 17470 handleError(e); 17471 } 17472 } 17473 } 17474 }); 17475 } 17476 17477 async function loadFileSlice(localfile, options) { 17478 let blob = options && options.range ? localfile.slice(options.range.start, options.range.start + options.range.size) : localfile; 17479 17480 if ("arraybuffer" === options.responseType) { 17481 return blobToArrayBuffer(blob); 17482 } else { 17483 // binary string format, shouldn't be used anymore 17484 return new Promise(function (resolve, reject) { 17485 const fileReader = new FileReader(); 17486 17487 fileReader.onload = function (e) { 17488 resolve(fileReader.result); 17489 }; 17490 17491 fileReader.onerror = function (e) { 17492 console.error("reject uploading local file " + localfile.name); 17493 reject(null, fileReader); 17494 }; 17495 17496 fileReader.readAsBinaryString(blob); 17497 console.warn("Deprecated method used: readAsBinaryString"); 17498 }); 17499 } 17500 } 17501
17502 async function loadStringFromFile(localfile, options) { 17503 const blob = options.range ? localfile.slice(options.range.start, options.range.start + options.range.size) : localfile; 17504 const arrayBuffer = await blobToArrayBuffer(blob); 17505 return arrayBufferToString(arrayBuffer); 17506 } 17507 17508 async function blobToArrayBuffer(blob) { 17509 if (typeof blob.arrayBuffer === 'function') { 17510 return blob.arrayBuffer(); 17511 } 17512 17513 return new Promise(function (resolve, reject) { 17514 const fileReader = new FileReader(); 17515 17516 fileReader.onload = function (e) { 17517 resolve(fileReader.result); 17518 }; 17519 17520 fileReader.onerror = function (e) { 17521 console.error("reject uploading local file " + localfile.name); 17522 reject(null, fileReader); 17523 }; 17524 17525 fileReader.readAsArrayBuffer(blob); 17526 }); 17527 } 17528 17529 async function loadStringFromUrl(url, options) { 17530 options = options || {}; 17531 options.responseType = "arraybuffer"; 17532 const data = await igvxhr.load(url, options); 17533 return arrayBufferToString(data); 17534 } 17535 17536 function isAmazonV4Signed(url) { 17537 return url.indexOf("X-Amz-Signature") > -1; 17538 } 17539 17540 function getOauthToken(url) { 17541 // Google is the default provider, don't try to parse host for google URLs 17542 const host = isGoogleURL(url) ? undefined : parseUri(url).host; 17543 let token = oauth.getToken(host); 17544 17545 if (token) { 17546 return token; 17547 } else if (host === undefined) { 17548 const googleToken = getCurrentGoogleAccessToken(); 17549 17550 if (googleToken && googleToken.expires_at > Date.now()) { 17551 return googleToken.access_token; 17552 } 17553 } 17554 } 17555 /** 17556 * Return a Google oAuth token, triggering a sign in if required. This method should not be called until we know 17557 * a token is required, that is until we've tried the url and received a 401, 403, or 404. 17558 * 17559 * @param url 17560 * @returns the oauth token 17561 */ 17562 17563 17564 async function fetchGoogleAccessToken(url) { 17565 console.log("Fetch token for " + url); 17566 17567 if (isInitialized()) { 17568 const scope = getScopeForURL(url); 17569 const googleToken = await getAccessToken(scope); 17570 return googleToken ? googleToken.access_token : undefined; 17571 } else { 17572 throw Error(`Authorization is required, but Google oAuth has not been initalized. Contact your site administrator for assistance.`); 17573 } 17574 } 17575 /** 17576 * Return the current google access token, if one exists. Do not triger signOn or request additional scopes. 17577 * @returns {undefined|access_token} 17578 */ 17579 17580 17581 function getCurrentGoogleAccessToken() { 17582 if (isInitialized()) { 17583 const googleToken = getCurrentAccessToken(); 17584 return googleToken ? googleToken.access_token : undefined; 17585 } else { 17586 return undefined; 17587 } 17588 } 17589 17590 function addOauthHeaders(headers, acToken) { 17591 if (acToken) { 17592 headers["Cache-Control"] = "no-cache"; 17593 headers["Authorization"] = "Bearer " + acToken; 17594 } 17595 17596 return headers; 17597 } 17598 17599 function addApiKey(url) { 17600 let apiKey = igvxhr.apiKey; 17601 17602 if (!apiKey && typeof gapi !== "undefined") { 17603 apiKey = gapi.apiKey; 17604 } 17605 17606 if (apiKey !== undefined && !url.includes("key=")) { 17607 const paramSeparator = url.includes("?") ? "&" : "?"; 17608 url = url + paramSeparator + "key=" + apiKey; 17609 } 17610 17611 return url; 17612 } 17613 17614 function addTeamDrive(url) { 17615 if (url.includes("supportsTeamDrive")) { 17616 return url; 17617 } else { 17618 const paramSeparator = url.includes("?") ? "&" : "?"; 17619 url = url + paramSeparator + "supportsTeamDrive=true"; 17620 } 17621 } 17622 /** 17623 * Perform some well-known url mappings. 17624 * @param url 17625 */ 17626 17627 17628 function mapUrl(url) { 17629 if (url.includes("//www.dropbox.com")) { 17630 return url.replace("//www.dropbox.com", "//dl.dropboxusercontent.com"); 17631 } else if (url.includes("//drive.google.com")) { 17632 return driveDownloadURL(url); 17633 } else if (url.includes("//www.broadinstitute.org/igvdata")) { 17634 return url.replace("//www.broadinstitute.org/igvdata", "//data.broadinstitute.org/igvdata"); 17635 } else if (url.includes("//igvdata.broadinstitute.org")) { 17636 return url.replace("//igvdata.broadinstitute.org", "https://dn7ywbm9isq8j.cloudfront.net"); 17637 } else if (url.startsWith("ftp://ftp.ncbi.nlm.nih.gov/geo")) { 17638 return url.replace("ftp://", "https://"); 17639 } else { 17640 return url; 17641 } 17642 } 17643 17644 function arrayBufferToString(arraybuffer) { 17645 let plain; 17646 17647 if (isgzipped(arraybuffer)) { 17648 plain = ungzip(arraybuffer); 17649 } else { 17650 plain = new Uint8Array(arraybuffer); 17651 } 17652 17653 if ('TextDecoder' in getGlobalObject()) { 17654 return new TextDecoder().decode(plain); 17655 } else { 17656 return decodeUTF8(plain); 17657 } 17658 } 17659 /** 17660 * Use when TextDecoder is not available (primarily IE). 17661 * 17662 * From: https://gist.github.com/Yaffle/5458286 17663 * 17664 * @param octets 17665 * @returns {string} 17666 */ 17667 17668
17669 function decodeUTF8(octets) { 17670 var string = ""; 17671 var i = 0; 17672 17673 while (i < octets.length) { 17674 var octet = octets[i]; 17675 var bytesNeeded = 0; 17676 var codePoint = 0; 17677 17678 if (octet <= 0x7F) { 17679 bytesNeeded = 0; 17680 codePoint = octet & 0xFF; 17681 } else if (octet <= 0xDF) { 17682 bytesNeeded = 1; 17683 codePoint = octet & 0x1F; 17684 } else if (octet <= 0xEF) { 17685 bytesNeeded = 2; 17686 codePoint = octet & 0x0F; 17687 } else if (octet <= 0xF4) { 17688 bytesNeeded = 3; 17689 codePoint = octet & 0x07; 17690 } 17691 17692 if (octets.length - i - bytesNeeded > 0) { 17693 var k = 0; 17694 17695 while (k < bytesNeeded) { 17696 octet = octets[i + k + 1]; 17697 codePoint = codePoint << 6 | octet & 0x3F; 17698 k += 1; 17699 } 17700 } else { 17701 codePoint = 0xFFFD; 17702 bytesNeeded = octets.length - i; 17703 } 17704 17705 string += String.fromCodePoint(codePoint); 17706 i += bytesNeeded + 1; 17707 } 17708 17709 return string; 17710 } 17711 17712 function getGlobalObject() { 17713 if (typeof self !== 'undefined') { 17714 return self; 17715 } 17716 17717 if (typeof global !== 'undefined') { 17718 return global; 17719 } else { 17720 return window; 17721 } 17722 } 17723 17724 /* 17725 * The MIT License (MIT) 17726 * 17727 * Copyright (c) 2014 Broad Institute 17728 * 17729 * Permission is hereby granted, free of charge, to any person obtaining a copy 17730 * of this software and associated documentation files (the "Software"), to deal 17731 * in the Software without restriction, including without limitation the rights 17732 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17733 * copies of the Software, and to permit persons to whom the Software is 17734 * furnished to do so, subject to the following conditions: 17735 * 17736 * The above copyright notice and this permission notice shall be included in 17737 * all copies or substantial portions of the Software. 17738 * 17739 * 17740 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17741 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17742 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17743 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17744 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 17745 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 17746 * THE SOFTWARE. 17747 */ 17748 17749 /** An implementation of an interval tree, following the explanation. 17750 * from CLR. 17751 * 17752 * Public interface: 17753 * Constructor IntervalTree 17754 * Insertion insert 17755 * Search findOverlapping 17756 */ 17757 var BLACK = 1; 17758 var RED = 2; 17759 var NIL = {}; 17760 NIL.color = BLACK; 17761 NIL.parent = NIL; 17762 NIL.left = NIL; 17763 NIL.right = NIL; 17764 17765 class IntervalTree { 17766 constructor() { 17767 this.root = NIL; 17768 } 17769 17770 insert(start, end, value) { 17771 var interval = new Interval(start, end, value); 17772 var x = new Node(interval); 17773 this.treeInsert(x); 17774 x.color = RED; 17775 17776 while (x !== this.root && x.parent.color === RED) { 17777 if (x.parent === x.parent.parent.left) { 17778 let y = x.parent.parent.right; 17779 17780 if (y.color === RED) { 17781 x.parent.color = BLACK; 17782 y.color = BLACK; 17783 x.parent.parent.color = RED; 17784 x = x.parent.parent; 17785 } else { 17786 if (x === x.parent.right) { 17787 x = x.parent; 17788 leftRotate.call(this, x); 17789 } 17790 17791 x.parent.color = BLACK; 17792 x.parent.parent.color = RED; 17793 rightRotate.call(this, x.parent.parent); 17794 } 17795 } else { 17796 let y = x.parent.parent.left; 17797 17798 if (y.color === RED) { 17799 x.parent.color = BLACK; 17800 y.color = BLACK; 17801 x.parent.parent.color = RED; 17802 x = x.parent.parent; 17803 } else { 17804 if (x === x.parent.left) { 17805 x = x.parent; 17806 rightRotate.call(this, x); 17807 } 17808 17809 x.parent.color = BLACK; 17810 x.parent.parent.color = RED; 17811 leftRotate.call(this, x.parent.parent); 17812 } 17813 } 17814 } 17815 17816 this.root.color = BLACK; 17817 } 17818 /** 17819 * 17820 * @param start - query interval 17821 * @param end - query interval 17822 * @returns Array of all intervals overlapping the query region 17823 */ 17824 17825 17826 findOverlapping(start, end) { 17827 var searchInterval = new Interval(start, end, 0); 17828 if (this.root === NIL) return []; 17829 var intervals = searchAll.call(this, searchInterval, this.root, []); 17830 17831 if (intervals.length > 1) { 17832 intervals.sort(function (i1, i2) { 17833 return i1.low - i2.low; 17834 }); 17835 } 17836 17837 return intervals; 17838 } 17839 /** 17840 * Dump info on intervals to console. For debugging. 17841 */ 17842 17843 17844 logIntervals() { 17845 logNode(this.root, 0); 17846 17847 function logNode(node, indent) { 17848 var space = ""; 17849 17850 for (var i = 0; i < indent; i++) space += " ";
17851 17852 console.log(space + node.interval.low + " " + node.interval.high); // + " " + (node.interval.value ? node.interval.value : " null")); 17853 17854 indent += 5; 17855 if (node.left !== NIL) logNode(node.left, indent); 17856 if (node.right !== NIL) logNode(node.right, indent); 17857 } 17858 } 17859 17860 mapIntervals(func) { 17861 applyInterval(this.root); 17862 17863 function applyInterval(node) { 17864 func(node.interval); 17865 if (node.left !== NIL) applyInterval(node.left); 17866 if (node.right !== NIL) applyInterval(node.right); 17867 } 17868 } 17869 /** 17870 * Note: Does not maintain RB constraints, this is done post insert 17871 * 17872 * @param x a Node 17873 */ 17874 17875 17876 treeInsert(x) { 17877 var node = this.root; 17878 var y = NIL; 17879 17880 while (node !== NIL) { 17881 y = node; 17882 17883 if (x.interval.low <= node.interval.low) { 17884 node = node.left; 17885 } else { 17886 node = node.right; 17887 } 17888 } 17889 17890 x.parent = y; 17891 17892 if (y === NIL) { 17893 this.root = x; 17894 x.left = x.right = NIL; 17895 } else { 17896 if (x.interval.low <= y.interval.low) { 17897 y.left = x; 17898 } else { 17899 y.right = x; 17900 } 17901 } 17902 17903 applyUpdate.call(this, x); 17904 } 17905 17906 } 17907 17908 function searchAll(interval, node, results) { 17909 if (node.interval.overlaps(interval)) { 17910 results.push(node.interval); 17911 } 17912 17913 if (node.left !== NIL && node.left.max >= interval.low) { 17914 searchAll.call(this, interval, node.left, results); 17915 } 17916 17917 if (node.right !== NIL && node.right.min <= interval.high) { 17918 searchAll.call(this, interval, node.right, results); 17919 } 17920 17921 return results; 17922 } 17923 17924 function leftRotate(x) { 17925 var y = x.right; 17926 x.right = y.left; 17927 17928 if (y.left !== NIL) { 17929 y.left.parent = x; 17930 } 17931 17932 y.parent = x.parent; 17933 17934 if (x.parent === NIL) { 17935 this.root = y; 17936 } else { 17937 if (x.parent.left === x) { 17938 x.parent.left = y; 17939 } else { 17940 x.parent.right = y; 17941 } 17942 } 17943 17944 y.left = x; 17945 x.parent = y; 17946 applyUpdate.call(this, x); // no need to apply update on y, since it'll y is an ancestor 17947 // of x, and will be touched by applyUpdate(). 17948 } 17949 17950 function rightRotate(x) { 17951 var y = x.left; 17952 x.left = y.right; 17953 17954 if (y.right !== NIL) { 17955 y.right.parent = x; 17956 } 17957 17958 y.parent = x.parent; 17959 17960 if (x.parent === NIL) { 17961 this.root = y; 17962 } else { 17963 if (x.parent.right === x) { 17964 x.parent.right = y; 17965 } else { 17966 x.parent.left = y; 17967 } 17968 } 17969 17970 y.right = x; 17971 x.parent = y; 17972 applyUpdate.call(this, x); // no need to apply update on y, since it'll y is an ancestor 17973 // of x, and will be touched by applyUpdate(). 17974 } // Applies the statistic update on the node and its ancestors. 17975 17976 17977 function applyUpdate(node) { 17978 while (node !== NIL) { 17979 var nodeMax = node.left.max > node.right.max ? node.left.max : node.right.max; 17980 var intervalHigh = node.interval.high; 17981 node.max = nodeMax > intervalHigh ? nodeMax : intervalHigh; 17982 var nodeMin = node.left.min < node.right.min ? node.left.min : node.right.min; 17983 var intervalLow = node.interval.low; 17984 node.min = nodeMin < intervalLow ? nodeMin : intervalLow; 17985 node = node.parent; 17986 } 17987 } 17988 17989 class Interval { 17990 constructor(low, high, value) { 17991 this.low = low; 17992 this.high = high; 17993 this.value = value; 17994 } 17995 17996 equals(other) { 17997 if (!other) { 17998 return false; 17999 } 18000 18001 if (this === other) { 18002 return true; 18003 } 18004 18005 return this.low === other.low && this.high === other.high; 18006 } 18007 18008 compareTo(other) { 18009 if (this.low < other.low) return -1; 18010 if (this.low > other.low) return 1; 18011 if (this.high < other.high) return -1; 18012 if (this.high > other.high) return 1; 18013 return 0; 18014 } 18015 /** 18016 * Returns true if this interval overlaps the other. 18017 */ 18018 18019 18020 overlaps(other) { 18021 return this.low <= other.high && other.low <= this.high; 18022 } 18023 18024 } 18025 18026 function Node(interval) { 18027 this.parent = NIL; 18028 this.left = NIL; 18029 this.right = NIL; 18030 this.interval = interval; 18031 this.color = RED; 18032 } // 18033 18034 /* 18035 * The MIT License (MIT) 18036 * 18037 * Copyright (c) 2014 Broad Institute 18038 * 18039 * Permission is hereby granted, free of charge, to any person obtaining a copy 18040 * of this software and associated documentation files (the "Software"), to deal 18041 * in the Software without restriction, including without limitation the rights 18042 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18043 * copies of the Software, and to permit persons to whom the Software is 18044 * furnished to do so, subject to the following conditions: 18045 * 18046 * The above copyright notice and this permission notice shall be included in 18047 * all copies or substantial portions of the Software. 18048 * 18049 * 18050 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18051 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18052 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18053 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18054 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18055 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 18056 * THE SOFTWARE. 18057 */ 18058 /** 18059 * Object for caching lists of features. Supports effecient queries for sub-range (chr, start, end) 18060 * 18061 * @param featureList 18062 * @param The genomic range spanned by featureList (optional) 18063 * @constructor 18064 */ 18065 18066 class FeatureCache { 18067 constructor(featureList, genome, range) { 18068 featureList = featureList || []; 18069 this.treeMap = this.buildTreeMap(featureList, genome); 18070 this.range = range; 18071 this.count = featureList.length; 18072 } 18073 18074 containsRange(genomicRange) { 18075 // No range means cache contains all features 18076 return this.range === undefined || this.range.contains(genomicRange.chr, genomicRange.start, genomicRange.end); 18077 } 18078 18079 queryFeatures(chr, start, end) { 18080 const tree = this.treeMap[chr]; 18081 if (!tree) return []; 18082 const intervals = tree.findOverlapping(start, end); 18083 18084 if (intervals.length === 0) { 18085 return []; 18086 } else { 18087 // Trim the list of features in the intervals to those 18088 // overlapping the requested range. 18089 // Assumption: features are sorted by start position 18090 const featureList = []; 18091 const all = this.allFeatures[chr]; 18092 18093 if (all) { 18094 for (let interval of intervals) { 18095 const indexRange = interval.value; 18096 18097 for (let i = indexRange.start; i < indexRange.end; i++) { 18098 let feature = all[i]; 18099 if (feature.start > end) break;else if (feature.end >= start) { 18100 featureList.push(feature); 18101 } 18102 } 18103 } 18104 18105 featureList.sort(function (a, b) { 18106 return a.start - b.start; 18107 }); 18108 } 18109 18110 return featureList; 18111 } 18112 } 18113 18114 /** 18115 * Returns all features, unsorted. 18116 * 18117 * @returns {Array} 18118 */ 18119 getAllFeatures() { 18120 return this.allFeatures; 18121 } 18122 18123 buildTreeMap(featureList, genome) { 18124 const treeMap = {}; 18125 const chromosomes = []; 18126 this.allFeatures = {}; 18127 18128 if (featureList) { 18129 for (let feature of featureList) { 18130 let chr = feature.chr; // Translate to "official" name 18131 18132 if (genome) { 18133 chr = genome.getChromosomeName(chr); 18134 } 18135 18136 let geneList = this.allFeatures[chr]; 18137 18138 if (!geneList) { 18139 chromosomes.push(chr); 18140 geneList = []; 18141 this.allFeatures[chr] = geneList; 18142 } 18143 18144 geneList.push(feature); 18145 } // Now build interval tree for each chromosome 18146 18147 18148 for (let chr of chromosomes) { 18149 const chrFeatures = this.allFeatures[chr]; 18150 chrFeatures.sort(function (f1, f2) { 18151 return f1.start === f2.start ? 0 : f1.start > f2.start ? 1 : -1; 18152 }); 18153 treeMap[chr] = buildIntervalTree$1(chrFeatures); 18154 } 18155 } 18156 18157 return treeMap; 18158 } 18159 18160 } 18161 /** 18162 * Build an interval tree from the feature list for fast interval based queries. We lump features in groups 18163 * of 10, or total size / 100, to reduce size of the tree. 18164 * 18165 * @param featureList 18166 */ 18167 18168 18169 function buildIntervalTree$1(featureList) { 18170 const tree = new IntervalTree(); 18171 const len = featureList.length; 18172 const chunkSize = Math.max(10, Math.round(len / 10)); 18173 18174 for (let i = 0; i < len; i += chunkSize) { 18175 const e = Math.min(len, i + chunkSize); 18176 const subArray = new IndexRange(i, e); //featureList.slice(i, e); 18177 18178 const iStart = featureList[i].start; // 18179 18180 let iEnd = iStart; 18181 18182 for (let j = i; j < e; j++) { 18183 iEnd = Math.max(iEnd, featureList[j].end); 18184 } 18185 18186 tree.insert(iStart, iEnd, subArray); 18187 } 18188 18189 return tree; 18190 } 18191 18192 class IndexRange { 18193 constructor(start, end) { 18194 this.start = start; 18195 this.end = end; 18196 } 18197 18198 } 18199 18200 /* 18201 * The MIT License (MIT) 18202 * 18203 * Copyright (c) 2016-2017 The Regents of the University of California 18204 * Author: Jim Robinson 18205 * 18206 * Permission is hereby granted, free of charge, to any person obtaining a copy 18207 * of this software and associated documentation files (the "Software"), to deal 18208 * in the Software without restriction, including without limitation the rights 18209 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18210 * copies of the Software, and to permit persons to whom the Software is 18211 * furnished to do so, subject to the following conditions: 18212 * 18213 * The above copyright notice and this permission notice shall be included in 18214 * all copies or substantial portions of the Software. 18215 * 18216 * 18217 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18218 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18219 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18220 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18221 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18222 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 18223 * THE SOFTWARE. 18224 */ 18225 const FeatureUtils = { 18226 packFeatures: function (features, maxRows, sorted) { 18227 var start; 18228 var end; 18229 if (!features) return; 18230 maxRows = maxRows || 10000; 18231 18232 if (!sorted) { 18233 features.sort(function (a, b) { 18234 return a.start - b.start; 18235 }); 18236 } 18237 18238 if (features.length === 0) { 18239 return []; 18240 } else { 18241 var bucketList = [], 18242 allocatedCount = 0, 18243 lastAllocatedCount = 0, 18244 nextStart, 18245 row, 18246 index, 18247 bucket, 18248 feature, 18249 gap = 2, 18250 bucketStart; 18251 start = features[0].start; 18252 end = features[features.length - 1].start; 18253 bucketStart = Math.max(start, features[0].start); 18254 nextStart = bucketStart;
18255 features.forEach(function (alignment) { 18256 var buckListIndex = Math.max(0, alignment.start - bucketStart); 18257 18258 if (bucketList[buckListIndex] === undefined) { 18259 bucketList[buckListIndex] = []; 18260 } 18261 18262 bucketList[buckListIndex].push(alignment); 18263 }); 18264 row = 0; 18265 18266 while (allocatedCount < features.length && row <= maxRows) { 18267 while (nextStart <= end) { 18268 bucket = undefined; 18269 18270 while (!bucket && nextStart <= end) { 18271 index = nextStart - bucketStart; 18272 18273 if (bucketList[index] === undefined) { 18274 ++nextStart; // No buckets at this index 18275 } else { 18276 bucket = bucketList[index]; 18277 } 18278 } // while (bucket) 18279 18280 18281 if (!bucket) { 18282 break; 18283 } 18284 18285 feature = bucket.pop(); 18286 18287 if (0 === bucket.length) { 18288 bucketList[index] = undefined; 18289 } 18290 18291 feature.row = row; 18292 nextStart = feature.end + gap; 18293 ++allocatedCount; 18294 } // while (nextStart) 18295 18296 18297 row++; 18298 nextStart = bucketStart; 18299 if (allocatedCount === lastAllocatedCount) break; // Protect from infinite loops 18300 18301 lastAllocatedCount = allocatedCount; 18302 } // while (allocatedCount) 18303 18304 } 18305 }, 18306 18307 /** 18308 * Find features overlapping the given interval. It is assumed that all features share the same chromosome. 18309 * 18310 * TODO -- significant overlap with FeatureCache, refactor to combine 18311 * 18312 * @param featureList 18313 * @param start 18314 * @param end 18315 */ 18316 findOverlapping: function (featureList, start, end) { 18317 if (!featureList || featureList.length === 0) { 18318 return []; 18319 } else { 18320 const tree = buildIntervalTree(featureList); 18321 const intervals = tree.findOverlapping(start, end); 18322 18323 if (intervals.length === 0) { 18324 return []; 18325 } else { 18326 // Trim the list of features in the intervals to those 18327 // overlapping the requested range. 18328 // Assumption: features are sorted by start position 18329 featureList = []; 18330 intervals.forEach(function (interval) { 18331 const intervalFeatures = interval.value; 18332 const len = intervalFeatures.length; 18333 18334 for (let i = 0; i < len; i++) { 18335 const feature = intervalFeatures[i]; 18336 if (feature.start > end) break;else if (feature.end > start) { 18337 featureList.push(feature); 18338 } 18339 } 18340 }); 18341 featureList.sort(function (a, b) { 18342 return a.start - b.start; 18343 }); 18344 return featureList; 18345 } 18346 } 18347 } 18348 }; 18349 /** 18350 * Build an interval tree from the feature list for fast interval based queries. We lump features in groups 18351 * of 10, or total size / 100, to reduce size of the tree. 18352 * 18353 * @param featureList 18354 */ 18355 18356 function buildIntervalTree(featureList) { 18357 const tree = new IntervalTree(); 18358 const len = featureList.length; 18359 const chunkSize = Math.max(10, Math.round(len / 100)); 18360 featureList.sort(function (f1, f2) { 18361 return f1.start === f2.start ? 0 : f1.start > f2.start ? 1 : -1; 18362 }); 18363 18364 for (let i = 0; i < len; i += chunkSize) { 18365 const e = Math.min(len, i + chunkSize); 18366 const subArray = featureList.slice(i, e); 18367 const iStart = subArray[0].start; 18368 let iEnd = iStart; 18369 subArray.forEach(function (feature) { 18370 iEnd = Math.max(iEnd, feature.end); 18371 }); 18372 tree.insert(iStart, iEnd, subArray); 18373 } 18374 18375 return tree; 18376 } 18377 18378 function createCheckbox$1(name, initialState) { 18379 const container = div$1({ 18380 class: 'igv-menu-popup-check-container' 18381 }); 18382 const div = div$1(); 18383 container.appendChild(div); 18384 const svg = createIcon$1('check', true === initialState ? '#444' : 'transparent'); 18385 div.appendChild(svg); 18386 const label = div$1(); 18387 label.innerText = name; 18388 container.appendChild(label); 18389 return container; 18390 } 18391 18392 /** 18393 * Configure item list for track "gear" menu. 18394 * @param trackView 18395 */ 18396 18397 const MenuUtils = { 18398 trackMenuItemList: function (trackView) { 18399 const vizWindowTypes = new Set(['alignment', 'annotation', 'variant', 'eqtl', 'snp']); 18400 const hasVizWindow = trackView.track.config && trackView.track.config.visibilityWindow !== undefined; 18401 let menuItems = []; 18402 18403 if (trackView.track.config.type !== 'sequence') { 18404 menuItems.push(trackRenameMenuItem(trackView)); 18405 menuItems.push(trackHeightMenuItem(trackView)); 18406 } 18407 18408 if (this.showColorPicker(trackView.track)) { 18409 menuItems.push('<hr/>'); 18410 menuItems.push(colorPickerMenuItem({ 18411 trackView, 18412 label: "Set track color", 18413 option: "color" 18414 })); 18415 menuItems.push(unsetColorMenuItem({ 18416 trackView, 18417 label: "Unset track color" 18418 })); 18419 menuItems.push(colorPickerMenuItem({ 18420 trackView, 18421 label: "Set alt color", 18422 option: "altColor" 18423 })); 18424 } 18425 18426 if (trackView.track.menuItemList) { 18427 menuItems = menuItems.concat(trackView.track.menuItemList()); 18428 } 18429 18430 if (hasVizWindow || vizWindowTypes.has(trackView.track.type)) { 18431 menuItems.push('<hr/>'); 18432 menuItems.push(visibilityWindowMenuItem(trackView)); 18433 } 18434 18435 if (trackView.track.removable !== false) { 18436 menuItems.push('<hr/>'); 18437 menuItems.push(trackRemovalMenuItem(trackView)); 18438 } 18439 18440 return menuItems; 18441 }, 18442 numericDataMenuItems: function (trackView) { 18443 const menuItems = []; 18444 menuItems.push('<hr/>'); // Data range 18445 18446 const object = $$1('<div>'); 18447 object.text('Set data range'); 18448 18449 const click = () => { 18450 trackView.browser.dataRangeDialog.configure(trackView); 18451 trackView.browser.dataRangeDialog.present($$1(trackView.browser.columnContainer)); 18452 }; 18453 18454 menuItems.push({ 18455 object, 18456 click 18457 }); 18458 18459 if (trackView.track.logScale !== undefined) { 18460 menuItems.push({ 18461 object: $$1(createCheckbox$1("Log scale", trackView.track.logScale)), 18462 click: () => { 18463 trackView.track.logScale = !trackView.track.logScale; 18464 trackView.repaintViews(); 18465 } 18466 }); 18467 } 18468 18469 menuItems.push({ 18470 object: $$1(createCheckbox$1("Autoscale", trackView.track.autoscale)), 18471 click: () => { 18472 trackView.track.autoscale = !trackView.track.autoscale; 18473 trackView.updateViews(); 18474 } 18475 }); 18476 return menuItems; 18477 }, 18478 trackMenuItemListHelper: function (itemList, menuPopup) { 18479 var list = []; 18480 18481 if (itemList.length > 0) { 18482 list = itemList.map(function (item, i) { 18483 var $e; // name and object fields checked for backward compatibility 18484 18485 if (item.name) { 18486 $e = $$1('<div>'); 18487 $e.text(item.name); 18488 } else if (item.object) { 18489 $e = item.object; 18490 } else if (typeof item.label === 'string') { 18491 $e = $$1('<div>'); 18492 $e.html(item.label); 18493 } else if (typeof item === 'string') { 18494 if (item.startsWith("<")) { 18495 $e = $$1(item); 18496 } else { 18497 $e = $$1("<div>" + item + "</div>"); 18498 } 18499 } 18500 18501 if (0 === i) { 18502 $e.addClass('igv-track-menu-border-top'); 18503 } 18504 18505 if (item.click) { 18506 $e.on('click', handleClick); 18507 $e.on('touchend', function (e) { 18508 handleClick(e); 18509 }); 18510 $e.on('mouseup', function (e) { 18511 e.preventDefault(); 18512 e.stopPropagation(); 18513 }); // eslint-disable-next-line no-inner-declarations 18514 18515 function handleClick(e) { 18516 item.click(e); 18517 menuPopup.hide(); 18518 e.preventDefault(); 18519 e.stopPropagation(); 18520 } 18521 } 18522 18523 return { 18524 object: $e, 18525 init: item.init || undefined 18526 }; 18527 }); 18528 } 18529 18530 return list; 18531 }, 18532 18533 showColorPicker(track) { 18534 return undefined === track.type || "bedtype" === track.type || "alignment" === track.type || "annotation" === track.type || "variant" === track.type || "wig" === track.type || 'interact' === track.type; 18535 }, 18536 18537 createMenuItem(label, action) { 18538 const object = $$1('<div>'); 18539 object.text(label); 18540 return { 18541 object, 18542 click: action 18543 }; 18544 } 18545 18546 }; 18547 18548 function visibilityWindowMenuItem(trackView) { 18549 const click = e => { 18550 const callback = () => { 18551 let value = trackView.browser.inputDialog.input.value; 18552 value = '' === value || undefined === value ? -1 : value.trim(); 18553 trackView.track.visibilityWindow = Number.parseInt(value); 18554 trackView.track.config.visibilityWindow = Number.parseInt(value); 18555 trackView.updateViews(); 18556 }; 18557 18558 const config = { 18559 label: 'Visibility Window', 18560 value: trackView.track.visibilityWindow, 18561 callback 18562 }; 18563 trackView.browser.inputDialog.present(config, e); 18564 }; 18565 18566 const object = $$1('<div>'); 18567 object.text('Set visibility window'); 18568 return { 18569 object, 18570 click 18571 }; 18572 } 18573 18574 function trackRemovalMenuItem(trackView) { 18575 const object = $$1('<div>'); 18576 object.text('Remove track'); 18577 return { 18578 object, 18579 click: () => trackView.browser.removeTrack(trackView.track) 18580 }; 18581 } 18582 18583 function colorPickerMenuItem(_ref) { 18584 let { 18585 trackView, 18586 label, 18587 option 18588 } = _ref; 18589 const $e = $$1('<div>'); 18590 $e.text(label); 18591 return { 18592 object: $e, 18593 click: () => trackView.presentColorPicker(option) 18594 }; 18595 } 18596 18597 function unsetColorMenuItem(_ref2) { 18598 let { 18599 trackView, 18600 label 18601 } = _ref2; 18602 const $e = $$1('<div>'); 18603 $e.text(label); 18604 return { 18605 object: $e, 18606 click: () => { 18607 trackView.track.color = undefined; 18608 trackView.repaintViews(); 18609 } 18610 }; 18611 } 18612 18613 function trackRenameMenuItem(trackView) { 18614 const click = e => { 18615 const callback = function () { 18616 let value = trackView.browser.inputDialog.input.value; 18617 value = '' === value || undefined === value ? 'untitled' : value.trim(); 18618 trackView.track.name = value; 18619 }; 18620 18621 const config = { 18622 label: 'Track Name', 18623 value: getTrackLabelText(trackView.track) || 'unnamed', 18624 callback 18625 }; 18626 trackView.browser.inputDialog.present(config, e); 18627 }; 18628 18629 const object = $$1('<div>'); 18630 object.text('Set track name'); 18631 return { 18632 object, 18633 click 18634 }; 18635 } 18636 18637 function trackHeightMenuItem(trackView) { 18638 const click = e => { 18639 const callback = () => { 18640 const number = Number(trackView.browser.inputDialog.input.value, 10); 18641 18642 if (undefined !== number) { 18643 // If explicitly setting the height adust min or max, if neccessary. 18644 if (trackView.track.minHeight !== undefined && trackView.track.minHeight > number) { 18645 trackView.track.minHeight = number; 18646 } 18647 18648 if (trackView.track.maxHeight !== undefined && trackView.track.maxHeight < number) { 18649 trackView.track.minHeight = number; 18650 } 18651 18652 trackView.setTrackHeight(number, true); 18653 trackView.checkContentHeight(); 18654 trackView.repaintViews(); // Explicitly setting track height turns off autoHeight 18655 18656 trackView.track.autoHeight = false;
18657 } 18658 }; 18659 18660 const config = { 18661 label: 'Track Height', 18662 value: trackView.track.height, 18663 callback 18664 }; 18665 trackView.browser.inputDialog.present(config, e); 18666 }; 18667 18668 const object = $$1('<div>'); 18669 object.text('Set track height'); 18670 return { 18671 object, 18672 click 18673 }; 18674 } 18675 18676 function getTrackLabelText(track) { 18677 var vp, txt; 18678 vp = track.trackView.viewports[0]; 18679 txt = vp.$trackLabel.text(); 18680 return txt; 18681 } 18682 18683 function div(options) { 18684 return create("div", options); 18685 } 18686 18687 function create(tag, options) { 18688 const elem = document.createElement(tag); 18689 18690 if (options) { 18691 if (options.class) { 18692 elem.classList.add(options.class); 18693 } 18694 18695 if (options.id) { 18696 elem.id = options.id; 18697 } 18698 18699 if (options.style) { 18700 applyStyle(elem, options.style); 18701 } 18702 } 18703 18704 return elem; 18705 } 18706 18707 function hide(elem) { 18708 const cssStyle = getComputedStyle(elem); 18709 18710 if (cssStyle.display !== "none") { 18711 elem._initialDisplay = cssStyle.display; 18712 } 18713 18714 elem.style.display = "none"; 18715 } 18716 18717 function show(elem) { 18718 const currentDisplay = getComputedStyle(elem).display; 18719 18720 if (currentDisplay === "none") { 18721 const d = elem._initialDisplay || "block"; 18722 elem.style.display = d; 18723 } 18724 } 18725 18726 function offset(elem) { 18727 // Return zeros for disconnected and hidden (display: none) elements (gh-2310) 18728 // Support: IE <=11 only 18729 // Running getBoundingClientRect on a 18730 // disconnected node in IE throws an error 18731 if (!elem.getClientRects().length) { 18732 return { 18733 top: 0, 18734 left: 0 18735 }; 18736 } // Get document-relative position by adding viewport scroll to viewport-relative gBCR 18737 18738 18739 const rect = elem.getBoundingClientRect(); 18740 const win = elem.ownerDocument.defaultView; 18741 return { 18742 top: rect.top + win.pageYOffset, 18743 left: rect.left + win.pageXOffset 18744 }; 18745 } 18746 18747 function pageCoordinates(e) { 18748 if (e.type.startsWith("touch")) { 18749 const touch = e.touches[0]; 18750 return { 18751 x: touch.pageX, 18752 y: touch.pageY 18753 }; 18754 } else { 18755 return { 18756 x: e.pageX, 18757 y: e.pageY 18758 }; 18759 } 18760 } 18761 18762 function applyStyle(elem, style) { 18763 for (let key of Object.keys(style)) { 18764 elem.style[key] = style[key]; 18765 } 18766 } 18767 18768 let getMouseXY = (domElement, { 18769 clientX, 18770 clientY 18771 }) => { 18772 // DOMRect object with eight properties: left, top, right, bottom, x, y, width, height 18773 const { 18774 left, 18775 top, 18776 width, 18777 height 18778 } = domElement.getBoundingClientRect(); 18779 const x = clientX - left; 18780 const y = clientY - top; 18781 return { 18782 x, 18783 y, 18784 xNormalized: x / width, 18785 yNormalized: y / height, 18786 width, 18787 height 18788 }; 18789 }; 18790 /** 18791 * Translate the mouse coordinates for the event to the coordinates for the given target element 18792 * @param event 18793 * @param domElement 18794 * @returns {{x: number, y: number}} 18795 */ 18796 18797 18798 function translateMouseCoordinates(event, domElement) { 18799 const { 18800 clientX, 18801 clientY 18802 } = event; 18803 return getMouseXY(domElement, { 18804 clientX, 18805 clientY 18806 }); 18807 } 18808 18809 function createCheckbox(name, initialState) { 18810 const container = div({ 18811 class: 'igv-ui-trackgear-popover-check-container' 18812 }); 18813 const svg = iconMarkup('check', true === initialState ? '#444' : 'transparent'); 18814 svg.style.borderColor = 'gray'; 18815 svg.style.borderWidth = '1px'; 18816 svg.style.borderStyle = 'solid'; 18817 container.appendChild(svg); 18818 let label = div(); //{ class: 'igv-some-label-class' }); 18819 18820 label.textContent = name; 18821 container.appendChild(label); 18822 return container; 18823 } 18824 18825 function createIcon(name, color) { 18826 return iconMarkup(name, color); 18827 } 18828 18829 function iconMarkup(name, color) { 18830 color = color || "currentColor"; 18831 let icon = icons[name]; 18832 18833 if (!icon) { 18834 console.error(`No icon named: ${name}`); 18835 icon = icons["question"]; 18836 } 18837 18838 const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg"); 18839 svg.setAttributeNS(null, 'viewBox', '0 0 ' + icon[0] + ' ' + icon[1]); 18840 const path = document.createElementNS("http://www.w3.org/2000/svg", "path"); 18841 path.setAttributeNS(null, 'fill', color); 18842 path.setAttributeNS(null, 'd', icon[4]); 18843 svg.appendChild(path); 18844 return svg; 18845 } 18846 18847 const icons = { 18848 "check": [512, 512, [], "f00c", "M173.898 439.404l-166.4-166.4c-9.997-9.997-9.997-26.206 0-36.204l36.203-36.204c9.997-9.998 26.207-9.998 36.204 0L192 312.69 432.095 72.596c9.997-9.997 26.207-9.997 36.204 0l36.203 36.204c9.997 9.997 9.997 26.206 0 36.204l-294.4 294.401c-9.998 9.997-26.207 9.997-36.204-.001z"], 18849 "cog": [512, 512, [], "f013", "M444.788 291.1l42.616 24.599c4.867 2.809 7.126 8.618 5.459 13.985-11.07 35.642-29.97 67.842-54.689 94.586a12.016 12.016 0 0 1-14.832 2.254l-42.584-24.595a191.577 191.577 0 0 1-60.759 35.13v49.182a12.01 12.01 0 0 1-9.377 11.718c-34.956 7.85-72.499 8.256-109.219.007-5.49-1.233-9.403-6.096-9.403-11.723v-49.184a191.555 191.555 0 0 1-60.759-35.13l-42.584 24.595a12.016 12.016 0 0 1-14.832-2.254c-24.718-26.744-43.619-58.944-54.689-94.586-1.667-5.366.592-11.175 5.459-13.985L67.212 291.1a193.48 193.48 0 0 1 0-70.199l-42.616-24.599c-4.867-2.809-7.126-8.618-5.459-13.985 11.07-35.642 29.97-67.842 54.689-94.586a12.016 12.016 0 0 1 14.832-2.254l42.584 24.595a191.577 191.577 0 0 1 60.759-35.13V25.759a12.01 12.01 0 0 1 9.377-11.718c34.956-7.85 72.499-8.256 109.219-.007 5.49 1.233 9.403 6.096 9.403 11.723v49.184a191.555 191.555 0 0 1 60.759 35.13l42.584-24.595a12.016 12.016 0 0 1 14.832 2.254c24.718 26.744 43.619 58.944 54.689 94.586 1.667 5.366-.592 11.175-5.459 13.985L444.788 220.9a193.485 193.485 0 0 1 0 70.2zM336 256c0-44.112-35.888-80-80-80s-80 35.888-80 80 35.888 80 80 80 80-35.888 80-80z"], 18850 "exclamation": [192, 512, [], "f12a", "M176 432c0 44.112-35.888 80-80 80s-80-35.888-80-80 35.888-80 80-80 80 35.888 80 80zM25.26 25.199l13.6 272C39.499 309.972 50.041 320 62.83 320h66.34c12.789 0 23.331-10.028 23.97-22.801l13.6-272C167.425 11.49 156.496 0 142.77 0H49.23C35.504 0 24.575 11.49 25.26 25.199z"], 18851 "exclamation-circle": [512, 512, [], "f06a", "M504 256c0 136.997-111.043 248-248 248S8 392.997 8 256C8 119.083 119.043 8 256 8s248 111.083 248 248zm-248 50c-25.405 0-46 20.595-46 46s20.595 46 46 46 46-20.595 46-46-20.595-46-46-46zm-43.673-165.346l7.418 136c.347 6.364 5.609 11.346 11.982 11.346h48.546c6.373 0 11.635-4.982 11.982-11.346l7.418
18851-136c.375-6.874-5.098-12.654-11.982-12.654h-63.383c-6.884 0-12.356 5.78-11.981 12.654z"], 18852 "exclamation-triangle": [576, 512, [], "f071", "M569.517 440.013C587.975 472.007 564.806 512 527.94 512H48.054c-36.937 0-59.999-40.055-41.577-71.987L246.423 23.985c18.467-32.009 64.72-31.951 83.154 0l239.94 416.028zM288 354c-25.405 0-46 20.595-46 46s20.595 46 46 46 46-20.595 46-46-20.595-46-46-46zm-43.673-165.346l7.418 136c.347 6.364 5.609 11.346 11.982 11.346h48.546c6.373 0 11.635-4.982 11.982-11.346l7.418-136c.375-6.874-5.098-12.654-11.982-12.654h-63.383c-6.884 0-12.356 5.78-11.981 12.654z"], 18853 "minus": [448, 512, [], "f068", "M424 318.2c13.3 0 24-10.7 24-24v-76.4c0-13.3-10.7-24-24-24H24c-13.3 0-24 10.7-24 24v76.4c0 13.3 10.7 24 24 24h400z"], 18854 "minus-circle": [512, 512, [], "f056", "M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zM124 296c-6.6 0-12-5.4-12-12v-56c0-6.6 5.4-12 12-12h264c6.6 0 12 5.4 12 12v56c0 6.6-5.4 12-12 12H124z"], 18855 "minus-square": [448, 512, [], "f146", "M400 32H48C21.5 32 0 53.5 0 80v352c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V80c0-26.5-21.5-48-48-48zM92 296c-6.6 0-12-5.4-12-12v-56c0-6.6 5.4-12 12-12h264c6.6 0 12 5.4 12 12v56c0 6.6-5.4 12-12 12H92z"], 18856 "plus": [448, 512, [], "f067", "M448 294.2v-76.4c0-13.3-10.7-24-24-24H286.2V56c0-13.3-10.7-24-24-24h-76.4c-13.3 0-24 10.7-24 24v137.8H24c-13.3 0-24 10.7-24 24v76.4c0 13.3 10.7 24 24 24h137.8V456c0 13.3 10.7 24 24 24h76.4c13.3 0 24-10.7 24-24V318.2H424c13.3 0 24-10.7 24-24z"], 18857 "plus-circle": [512, 512, [], "f055", "M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm144 276c0 6.6-5.4 12-12 12h-92v92c0 6.6-5.4 12-12 12h-56c-6.6 0-12-5.4-12-12v-92h-92c-6.6 0-12-5.4-12-12v-56c0-6.6 5.4-12 12-12h92v-92c0-6.6 5.4-12 12-12h56c6.6 0 12 5.4 12 12v92h92c6.6 0 12 5.4 12 12v56z"], 18858 "plus-square": [448, 512, [], "f0fe", "M400 32H48C21.5 32 0 53.5 0 80v352c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V80c0-26.5-21.5-48-48-48zm-32 252c0 6.6-5.4 12-12 12h-92v92c0 6.6-5.4 12-12 12h-56c-6.6 0-12-5.4-12-12v-92H92c-6.6 0-12-5.4-12-12v-56c0-6.6 5.4-12 12-12h92v-92c0-6.6 5.4-12 12-12h56c6.6 0 12 5.4 12 12v92h92c6.6 0 12 5.4 12 12v56z"], 18859 "question": [384, 512, [], "f128", "M202.021 0C122.202 0 70.503 32.703 29.914 91.026c-7.363 10.58-5.093 25.086 5.178 32.874l43.138 32.709c10.373 7.865 25.132 6.026 33.253-4.148 25.049-31.381 43.63-49.449 82.757-49.449 30.764 0 68.816 19.799 68.816 49.631 0 22.552-18.617 34.134-48.993 51.164-35.423 19.86-82.299 44.576-82.299 106.405V320c0 13.255 10.745 24 24 24h72.471c13.255 0 24-10.745 24-24v-5.773c0-42.86 125.268-44.645 125.268-160.627C377.504 66.256 286.902 0 202.021 0zM192 373.459c-38.196 0-69.271 31.075-69.271 69.271 0 38.195 31.075 69.27 69.271 69.27s69.271-31.075 69.271-69.271-31.075-69.27-69.271-69.27z"], 18860 "save": [448, 512, [], "f0c7", "M433.941 129.941l-83.882-83.882A48 48 0 0 0 316.118 32H48C21.49 32 0 53.49 0 80v352c0 26.51 21.49 48 48 48h352c26.51 0 48-21.49 48-48V163.882a48 48 0 0 0-14.059-33.941zM224 416c-35.346 0-64-28.654-64-64 0-35.346 28.654-64 64-64s64 28.654 64 64c0 35.346-28.654 64-64 64zm96-304.52V212c0 6.627-5.373 12-12 12H76c-6.627 0-12-5.373-12-12V108c0-6.627 5.373-12 12-12h228.52c3.183 0 6.235 1.264 8.485 3.515l3.48 3.48A11.996 11.996 0 0 1 320 111.48z"], 18861 "search": [512, 512, [], "f002", "M505 442.7L405.3 343c-4.5-4.5-10.6-7-17-7H372c27.6-35.3 44-79.7 44-128C416 93.1 322.9 0 208 0S0 93.1 0 208s93.1 208 208 208c48.3 0 92.7-16.4 128-44v16.3c0 6.4 2.5 12.5 7 17l99.7 99.7c9.4 9.4 24.6 9.4 33.9 0l28.3-28.3c9.4-9.4 9.4-24.6.1-34zM208 336c-70.7 0-128-57.2-128-128 0-70.7 57.2-128 128-128 70.7 0 128 57.2 128 128 0 70.7-57.2 128-128 128z"], 18862 "share": [512, 512, [], "f064", "M503.691 189.836L327.687 37.851C312.281 24.546 288 35.347 288 56.015v80.053C127.371 137.907 0 170.1 0 322.326c0 61.441 39.581 122.309 83.333 154.132 13.653 9.931 33.111-2.533 28.077-18.631C66.066 312.814 132.917 274.316 288 272.085V360c0 20.7 24.3 31.453 39.687 18.164l176.004-152c11.071-9.562 11.086-26.753 0-36.328z"], 18863 "spinner": [512, 512, [], "f110", "M304 48c0 26.51-21.49 48-48 48s-48-21.49-48-48 21.49-48 48-48 48 21.49 48 48zm-48 368c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48-21.49-48-48-48zm208-208c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48-21.49-48-48-48zM96 256c0-26.51-21.49-48-48-48S0 229.49 0 256s21.49 48 48 48 48-21.49 48-48zm12.922 99.078c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48c0-26.509-21.491-48-48-48zm294.156 0c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48c0-26.509-21.49-48-48-48zM108.922 60.922c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48-21.491-48-48-48z"], 18864 "square": [448, 512, [], "f0c8", "M400 32H48C21.5 32 0 53.5 0 80v352c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V80c0-26.5-21.5-48-48-48z"], 18865 "square-full": [512, 512, [], "f45c", "M512 512H0V0h512v512z"], 18866 "times": [384, 512, [], "f00d", "M323.1 441l53.9-53.9c9.4-9.4 9.4-24.5 0-33.9L279.8 256l97.2-97.2c9.4-9.4 9.4-24.5 0-33.9L323.1 71c-9.4-9.4-24.5-9.4-33.9 0L192 168.2 94.8 71c-9.4-9.4-24.5-9.4-33.9 0L7 124.9c-9.4 9.4-9.4 24.5 0 33.9l97.2 97.2L7 353.2c-9.4 9.4-9.4 24.5 0 33.9L60.9 441c9.4 9.4 24.5 9.4 33.9 0l97.2-97.2 97.2 97.2c9.3 9.3 24.5 9.3 33.9 0z"], 18867 "times-circle": [512, 512, [], "f057", "M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm121.6 313.1c4.7 4.7 4.7 12.3 0 17L338 377.6c-4.7 4.7-12.3 4.7-17 0L256 312l-65.1 65.6c-4.7 4.7-12.3 4.7-17 0L134.4 338c-4.7-4.7-4.7-12.3 0-17l65.6-65-65.6-65.1c-4.7-4.7-4.7-12.3 0-17l39.6-39.6c4.7-4.7 12.3-4.7 17 0l65 65.7 65.1-65.6c4.7-4.7 12.3-4.7 17 0l39.6 39.6c4.7 4.7 4.7 12.3 0 17L312 256l65.6 65.1z"],
18868 "wrench": [512, 512, [], "f0ad", "M481.156 200c9.3 0 15.12 10.155 10.325 18.124C466.295 259.992 420.419 288 368 288c-79.222 0-143.501-63.974-143.997-143.079C223.505 65.469 288.548-.001 368.002 0c52.362.001 98.196 27.949 123.4 69.743C496.24 77.766 490.523 88 481.154 88H376l-40 56 40 56h105.156zm-171.649 93.003L109.255 493.255c-24.994 24.993-65.515 24.994-90.51 0-24.993-24.994-24.993-65.516 0-90.51L218.991 202.5c16.16 41.197 49.303 74.335 90.516 90.503zM104 432c0-13.255-10.745-24-24-24s-24 10.745-24 24 10.745 24 24 24 24-10.745 24-24z"] 18869 }; 18870 18871 function attachDialogCloseHandlerWithParent(parent, closeHandler) { 18872 var container = document.createElement("div"); 18873 parent.appendChild(container); 18874 container.appendChild(createIcon("times")); 18875 container.addEventListener('click', function (e) { 18876 e.preventDefault(); 18877 e.stopPropagation(); 18878 closeHandler(); 18879 }); 18880 } 18881 /** 18882 * Make the target element movable by clicking and dragging on the handle. This is not a general purprose function, 18883 * it makes several options specific to igv dialogs, the primary one being that the 18884 * target is absolutely positioned in pixel coordinates 18885 18886 */ 18887 18888 18889 let dragData; // Its assumed we are only dragging one element at a time. 18890 18891 function makeDraggable(target, handle) { 18892 handle.addEventListener('mousedown', dragStart.bind(target)); 18893 } 18894 18895 function dragStart(event) { 18896 event.stopPropagation(); 18897 event.preventDefault(); 18898 offset(this); 18899 const dragFunction = drag.bind(this); 18900 const dragEndFunction = dragEnd.bind(this); 18901 const computedStyle = getComputedStyle(this); 18902 const top = parseInt(computedStyle.top.replace("px", "")); 18903 const left = parseInt(computedStyle.left.replace("px", "")); 18904 dragData = { 18905 dragFunction: dragFunction, 18906 dragEndFunction: dragEndFunction, 18907 screenX: event.screenX, 18908 screenY: event.screenY, 18909 top: top, 18910 left: left 18911 }; 18912 document.addEventListener('mousemove', dragFunction); 18913 document.addEventListener('mouseup', dragEndFunction); 18914 document.addEventListener('mouseleave', dragEndFunction); 18915 document.addEventListener('mouseexit', dragEndFunction); 18916 } 18917 18918 function drag(event) { 18919 if (!dragData) { 18920 console.log("No drag data!"); 18921 return; 18922 } 18923 18924 event.stopPropagation(); 18925 event.preventDefault(); 18926 const dx = event.screenX - dragData.screenX; 18927 const dy = event.screenY - dragData.screenY; 18928 this.style.left = `${dragData.left + dx}px`; 18929 this.style.top = `${dragData.top + dy}px`; 18930 } 18931 18932 function dragEnd(event) { 18933 if (!dragData) { 18934 console.log("No drag data!"); 18935 return; 18936 } 18937 18938 event.stopPropagation(); 18939 event.preventDefault(); 18940 const dragFunction = dragData.dragFunction; 18941 const dragEndFunction = dragData.dragEndFunction; 18942 document.removeEventListener('mousemove', dragFunction); 18943 document.removeEventListener('mouseup', dragEndFunction); 18944 document.removeEventListener('mouseleave', dragEndFunction); 18945 document.removeEventListener('mouseexit', dragEndFunction); 18946 dragData = undefined; 18947 } 18948 18949 const httpMessages = { 18950 "401": "Access unauthorized", 18951 "403": "Access forbidden", 18952 "404": "Not found" 18953 }; 18954 18955 class AlertDialog { 18956 /** 18957 * Initialize a new alert dialog 18958 * @param parent 18959 * @param alertProps - Optional - properties such as scroll to error 18960 */ 18961 constructor(parent, alertProps) { 18962 this.alertProps = Object.assign({ 18963 /** When an alert is presented - focus occur */ 18964 shouldFocus: true, 18965 18966 /** When focus occur - scroll into that element in the view */ 18967 preventScroll: false 18968 }, alertProps); // container 18969 18970 this.container = div({ 18971 class: "igv-ui-alert-dialog-container" 18972 }); 18973 parent.appendChild(this.container); 18974 this.container.setAttribute('tabIndex', '-1'); // header 18975 18976 const header = div(); 18977 this.container.appendChild(header); 18978 this.errorHeadline = div(); 18979 header.appendChild(this.errorHeadline); 18980 this.errorHeadline.textContent = ''; // body container 18981 18982 let bodyContainer = div({ 18983 id: 'igv-ui-alert-dialog-body' 18984 }); 18985 this.container.appendChild(bodyContainer); // body copy 18986 18987 this.body = div({ 18988 id: 'igv-ui-alert-dialog-body-copy' 18989 }); 18990 bodyContainer.appendChild(this.body); // ok container 18991 18992 let ok_container = div(); 18993 this.container.appendChild(ok_container); // ok 18994 18995 this.ok = div(); 18996 ok_container.appendChild(this.ok); 18997 this.ok.textContent = 'OK'; 18998 18999 const okHandler = () => { 19000 if (typeof this.callback === 'function') { 19001 this.callback("OK"); 19002 this.callback = undefined; 19003 } 19004 19005 this.body.innerHTML = ''; 19006 hide(this.container); 19007 }; 19008 19009 this.ok.addEventListener('click', event => { 19010 event.stopPropagation(); 19011 okHandler(); 19012 }); 19013 this.container.addEventListener('keypress', event => { 19014 event.stopPropagation(); 19015 19016 if ('Enter' === event.key) { 19017 okHandler(); 19018 } 19019 }); 19020 makeDraggable(this.container, header); 19021 hide(this.container); 19022 } 19023 19024 present(alert, callback) { 19025 this.errorHeadline.textContent = alert.message ? 'ERROR' : ''; 19026 let string = alert.message || alert; 19027 19028 if (httpMessages.hasOwnProperty(string)) {
19029 string = httpMessages[string]; 19030 } 19031 19032 this.body.innerHTML = string; 19033 this.callback = callback; 19034 show(this.container); 19035 19036 if (this.alertProps.shouldFocus) { 19037 this.container.focus({ 19038 preventScroll: this.alertProps.preventScroll 19039 }); 19040 } 19041 } 19042 19043 } 19044 19045 let alertDialog; 19046 const Alert = { 19047 init(root, config = {}) { 19048 alertDialog = new AlertDialog(root, config); 19049 }, 19050 19051 presentAlert(alert, callback) { 19052 if (!alertDialog) { 19053 this.init(document.body); 19054 } 19055 19056 alertDialog.present(alert, callback); 19057 } 19058 19059 }; 19060 19061 class InputDialog { 19062 constructor(parent) { 19063 this.parent = parent; // dialog container 19064 19065 this.container = div({ 19066 class: 'igv-ui-generic-dialog-container' 19067 }); 19068 parent.appendChild(this.container); // const { x, y, width, height } = this.container.getBoundingClientRect(); 19069 // console.log(`InputDialog - x ${ x } y ${ y } width ${ width } height ${ height }`) 19070 // dialog header 19071 19072 const header = div({ 19073 class: 'igv-ui-generic-dialog-header' 19074 }); 19075 this.container.appendChild(header); // dialog label 19076 19077 this.label = div({ 19078 class: 'igv-ui-generic-dialog-one-liner' 19079 }); 19080 this.container.appendChild(this.label); 19081 this.label.text = 'Unlabeled'; // input container 19082 19083 this.input_container = div({ 19084 class: 'igv-ui-generic-dialog-input' 19085 }); 19086 this.container.appendChild(this.input_container); // 19087 19088 this.input = document.createElement("input"); 19089 this.input_container.appendChild(this.input); // ok | cancel 19090 19091 const buttons = div({ 19092 class: 'igv-ui-generic-dialog-ok-cancel' 19093 }); 19094 this.container.appendChild(buttons); // ok 19095 19096 this.ok = div(); 19097 buttons.appendChild(this.ok); 19098 this.ok.textContent = 'OK'; // cancel 19099 19100 this.cancel = div(); 19101 buttons.appendChild(this.cancel); 19102 this.cancel.textContent = 'Cancel'; 19103 hide(this.container); 19104 this.input.addEventListener('keyup', e => { 19105 if (13 === e.keyCode) { 19106 if (typeof this.callback === 'function') { 19107 this.callback(this.input.value); 19108 this.callback = undefined; 19109 } 19110 19111 this.input.value = undefined; 19112 hide(this.container); 19113 } 19114 }); 19115 this.ok.addEventListener('click', () => { 19116 if (typeof this.callback === 'function') { 19117 this.callback(this.input.value); 19118 this.callback = undefined; 19119 } 19120 19121 this.input.value = undefined; 19122 hide(this.container); 19123 }); 19124 19125 const cancel = () => { 19126 this.input.value = ''; 19127 hide(this.container); 19128 }; 19129 19130 this.cancel.addEventListener('click', cancel); 19131 attachDialogCloseHandlerWithParent(header, cancel); 19132 makeDraggable(this.container, header); 19133 } 19134 19135 present(options, e) { 19136 this.label.textContent = options.label; 19137 this.input.value = options.value; 19138 this.callback = options.callback || options.click; 19139 show(this.container); 19140 const { 19141 x, 19142 y 19143 } = pageCoordinates(e); 19144 this.clampLocation(x, y); 19145 } 19146 19147 clampLocation(pageX, pageY) { 19148 const { 19149 width: w, 19150 height: h 19151 } = this.container.getBoundingClientRect(); 19152 const { 19153 x: px, 19154 y: py, 19155 width: pw, 19156 height: ph 19157 } = this.parent.getBoundingClientRect(); 19158 const y = Math.min(Math.max(pageY, py), py + ph - h); 19159 const x = Math.min(Math.max(pageX, px), px + pw - w); 19160 this.container.style.left = `${x}px`; 19161 this.container.style.top = `${y}px`; 19162 } 19163 19164 } 19165 19166 const appleCrayonPalette = { 19167 licorice: "#000000", 19168 lead: "#1e1e1e", 19169 tungsten: "#3a3a3a", 19170 iron: "#545453", 19171 steel: "#6e6e6e", 19172 tin: "#878687", 19173 nickel: "#888787", 19174 aluminum: "#a09fa0", 19175 magnesium: "#b8b8b8", 19176 silver: "#d0d0d0", 19177 mercury: "#e8e8e8", 19178 snow: "#ffffff", 19179 // 19180 cayenne: "#891100", 19181 mocha: "#894800", 19182 aspargus: "#888501", 19183 fern: "#458401", 19184 clover: "#028401", 19185 moss: "#018448", 19186 teal: "#008688", 19187 ocean: "#004a88", 19188 midnight: "#001888", 19189 eggplant: "#491a88", 19190 plum: "#891e88", 19191 maroon: "#891648", 19192 // 19193 maraschino: "#ff2101", 19194 tangerine: "#ff8802", 19195 lemon: "#fffa03", 19196 lime: "#83f902", 19197 spring: "#05f802", 19198 seam_foam: "#03f987", 19199 turquoise: "#00fdff", 19200 aqua: "#008cff", 19201 blueberry: "#002eff", 19202 grape: "#8931ff", 19203 magenta: "#ff39ff", 19204 strawberry: "#ff2987", 19205 // 19206 salmon: "#ff726e", 19207 cantaloupe: "#ffce6e", 19208 banana: "#fffb6d", 19209 honeydew: "#cefa6e", 19210 flora: "#68f96e", 19211 spindrift: "#68fbd0", 19212 ice: "#68fdff", 19213 sky: "#6acfff", 19214 orchid: "#6e76ff", 19215 lavender: "#d278ff", 19216 bubblegum: "#ff7aff", 19217 carnation: "#ff7fd3" 19218 }; //import { DOMUtils, UIUtils, makeDraggable } from '../node_modules/igv-utils/src/index.js' 19219 19220 class GenericContainer { 19221 constructor({ 19222 parent, 19223 top, 19224 left, 19225 width, 19226 height, 19227 border, 19228 closeHandler 19229 }) { 19230 let container = div({ 19231 class: 'igv-ui-generic-container' 19232 }); 19233 parent.appendChild(container); 19234 hide(container); 19235 this.container = container; 19236 19237 if (top !== undefined) { 19238 this.container.style.top = `${top}px`; 19239 } 19240 19241 if (left !== undefined) { 19242 this.container.style.left = `${left}px`; 19243 } 19244 19245 if (width !== undefined) { 19246 this.container.style.width = `${width}px`; 19247 } 19248 19249 if (height !== undefined) { 19250 this.container.style.height = `${height}px`; 19251 } 19252 19253 if (border) { 19254 this.container.style.border = border; 19255 } // 19256 // let bbox = parent.getBoundingClientRect(); 19257 // this.origin = {x: bbox.x, y: bbox.y}; 19258 // this.container.offset({left: this.origin.x, top: this.origin.y}); 19259 // header 19260 19261 19262 const header = div(); 19263 this.container.appendChild(header); // close button 19264 19265 attachDialogCloseHandlerWithParent(header, e => { 19266 hide(this.container); 19267 19268 if (typeof closeHandler === "function") { 19269 closeHandler(e); 19270 } 19271 }); 19272 makeDraggable(this.container, header); 19273 } 19274 19275 show() { 19276 show(this.container); 19277 } 19278 19279 hide() { 19280 hide(this.container); 19281 } 19282 19283 dispose() { 19284 if (this.container.parent) { 19285 this.container.parent.removeChild(this.container); 19286 } 19287 } 19288 19289 } 19290 19291 class ColorPicker extends GenericContainer { 19292 constructor({ 19293 parent, 19294 top, 19295 left, 19296 width, 19297 height, 19298 defaultColors, 19299 colorHandler 19300 }) { 19301 super({ 19302 parent, 19303 top, 19304 left, 19305 width, 19306 height, 19307 border: '1px solid gray' 19308 }); 19309 createColorSwatchSelector(this.container, colorHandler, defaultColors); 19310 } 19311 19312 } 19313 19314 const createColorSwatchSelector = (container, colorHandler, defaultColors) => { 19315 const hexColorStrings = Object.values(appleCrayonPalette); 19316 19317 for (let hexColorString of hexColorStrings) { 19318 const swatch = div({ 19319 class: 'igv-ui-color-swatch' 19320 }); 19321 container.appendChild(swatch); 19322 decorateSwatch(swatch, hexColorString, colorHandler); 19323 } 19324 19325 if (defaultColors) { 19326 for (let hexColorString of defaultColors) { 19327 const swatch = div({ 19328 class: 'igv-ui-color-swatch' 19329 }); 19330 container.appendChild(swatch); 19331 decorateSwatch(swatch, hexColorString, colorHandler); 19332 } 19333 } 19334 }; 19335 19336 const decorateSwatch = (swatch, hexColorString, colorHandler) => { 19337 swatch.style.backgroundColor = hexColorString; 19338 swatch.addEventListener('mouseenter', e => swatch.style.borderColor = hexColorString); 19339 swatch.addEventListener('mouseleave', e => swatch.style.borderColor = 'white'); 19340 swatch.addEventListener('click', event => { 19341 event.stopPropagation(); 19342 colorHandler(hexColorString); 19343 }); 19344 swatch.addEventListener('touchend', event => { 19345 event.stopPropagation(); 19346 colorHandler(hexColorString); 19347 }); 19348 }; 19349 19350 class Popover { 19351 constructor(parent, title) { 19352 this.parent = parent; // popover 19353 19354 this.popover = div({ 19355 class: "igv-ui-popover" 19356 }); 19357 parent.appendChild(this.popover); // header 19358 19359 const popoverHeader = div();
19360 this.popover.appendChild(popoverHeader); 19361 const titleElement = div(); 19362 popoverHeader.appendChild(titleElement); 19363 19364 if (title) { 19365 titleElement.textContent = title; 19366 } 19367 19368 attachDialogCloseHandlerWithParent(popoverHeader, () => this.hide()); 19369 makeDraggable(this.popover, popoverHeader); // content 19370 19371 this.popoverContent = div(); 19372 this.popover.appendChild(this.popoverContent); 19373 this.popover.style.display = 'none'; 19374 } 19375 19376 presentContentWithEvent(e, content) { 19377 this.popover.style.display = 'block'; 19378 this.popoverContent.innerHTML = content; 19379 present$1(e, this.popover, this.popoverContent); 19380 } 19381 19382 presentMenu(e, menuItems) { 19383 if (0 === menuItems.length) { 19384 return; 19385 } 19386 19387 this.popover.style.display = 'block'; 19388 const menuElements = createMenuElements$1(menuItems, this.popover); 19389 19390 for (let item of menuElements) { 19391 this.popoverContent.appendChild(item.object); 19392 } 19393 19394 present$1(e, this.popover, this.popoverContent); 19395 } 19396 19397 hide() { 19398 this.popover.style.display = 'none'; 19399 this.dispose(); 19400 } 19401 19402 dispose() { 19403 if (this.popover) { 19404 this.popover.parentNode.removeChild(this.popover); 19405 } 19406 19407 const keys = Object.keys(this); 19408 19409 for (let key of keys) { 19410 this[key] = undefined; 19411 } 19412 } 19413 19414 } 19415 19416 function present$1(e, popover, popoverContent) { 19417 const { 19418 x, 19419 y, 19420 width 19421 } = translateMouseCoordinates(e, popover.parentNode); 19422 popover.style.top = `${y}px`; 19423 const { 19424 width: w 19425 } = popover.getBoundingClientRect(); 19426 const xmax = x + w; 19427 const delta = xmax - width; 19428 popover.style.left = `${xmax > width ? x - delta : x}px`; 19429 popoverContent.style.maxWidth = `${Math.min(w, width)}px`; 19430 } 19431 19432 function createMenuElements$1(itemList, popover) { 19433 const list = itemList.map(function (item, i) { 19434 let elem; 19435 19436 if (typeof item === 'string') { 19437 elem = div(); 19438 elem.innerHTML = item; 19439 } else if (typeof item === 'Node') { 19440 elem = item; 19441 } else { 19442 if (typeof item.init === 'function') { 19443 item.init(); 19444 } 19445 19446 if ("checkbox" === item.type) { 19447 elem = createCheckbox("Show all bases", item.value); 19448 } else if ("color" === item.type) { 19449 const colorPicker = new ColorPicker({ 19450 parent: popover.parentElement, 19451 width: 364, 19452 //defaultColor: 'aqua', 19453 colorHandler: color => item.click(color) 19454 }); 19455 elem = div(); 19456 19457 if (typeof item.label === 'string') { 19458 elem.innerHTML = item.label; 19459 } 19460 19461 const clickHandler = e => { 19462 colorPicker.show(); 19463 hide(popover); 19464 e.preventDefault(); 19465 e.stopPropagation(); 19466 }; 19467 19468 elem.addEventListener('click', clickHandler); 19469 elem.addEventListener('touchend', clickHandler); 19470 elem.addEventListener('mouseup', function (e) { 19471 e.preventDefault(); 19472 e.stopPropagation(); 19473 }); 19474 } else { 19475 elem = div(); 19476 19477 if (typeof item.label === 'string') { 19478 elem.innerHTML = item.label; 19479 } 19480 } 19481 19482 if (item.click && "color" !== item.type) { 19483 elem.addEventListener('click', handleClick); 19484 elem.addEventListener('touchend', handleClick); 19485 elem.addEventListener('mouseup', function (e) { 19486 e.preventDefault(); 19487 e.stopPropagation(); 19488 }); // eslint-disable-next-line no-inner-declarations 19489 19490 function handleClick(e) { 19491 item.click(); 19492 hide(popover); 19493 e.preventDefault(); 19494 e.stopPropagation(); 19495 } 19496 } 19497 } 19498 19499 return { 19500 object: elem, 19501 init: item.init 19502 }; 19503 }); 19504 return list; 19505 } 19506 19507 function embedCSS$2() {
19508 var css = '.igv-ui-popover {\n cursor: default;\n position: absolute;\n z-index: 2048;\n border-color: #7F7F7F;\n border-radius: 4px;\n border-style: solid;\n border-width: 1px;\n font-family: \"Open Sans\", sans-serif;\n font-size: small;\n background-color: white; }\n .igv-ui-popover > div:first-child {\n display: flex;\n flex-direction: row;\n flex-wrap: nowrap;\n justify-content: space-between;\n align-items: center;\n width: 100%;\n height: 24px;\n cursor: move;\n border-top-left-radius: 4px;\n border-top-right-radius: 4px;\n border-bottom-color: #7F7F7F;\n border-bottom-style: solid;\n border-bottom-width: thin;\n background-color: #eee; }\n .igv-ui-popover > div:first-child > div:first-child {\n margin-left: 4px; }\n .igv-ui-popover > div:first-child > div:last-child {\n margin-right: 4px;\n height: 12px;\n width: 12px;\n color: #7F7F7F; }\n .igv-ui-popover > div:first-child > div:last-child:hover {\n cursor: pointer;\n color: #444; }\n .igv-ui-popover > div:last-child {\n overflow-y: auto;\n overflow-x: hidden;\n max-height: 400px;\n max-width: 800px;\n background-color: white; }\n .igv-ui-popover > div:last-child > div {\n -webkit-user-select: all;\n /* Chrome/Safari */\n -moz-user-select: all;\n /* Firefox */\n margin-left: 4px;\n margin-right: 4px;\n min-width: 220px;\n overflow-x: hidden;\n text-overflow: ellipsis;\n white-space: nowrap; }\n .igv-ui-popover > div:last-child > div > span {\n font-weight: bolder; }\n .igv-ui-popover > div:last-child hr {\n width: 100%; }\n\n.igv-ui-alert-dialog-container {\n box-sizing: content-box;\n position: absolute;\n z-index: 2048;\n top: 50%;\n left: 50%;\n width: 400px;\n height: 200px;\n border-color: #7F7F7F;\n border-radius: 4px;\n border-style: solid;\n border-width: thin;\n outline: none;\n font-family: \"Open Sans\", sans-serif;\n font-size: 15px;\n font-weight: 400;\n background-color: white;\n display: flex;\n flex-flow: column;\n flex-wrap: nowrap;\n justify-content: space-between;\n align-items: center; }\n .igv-ui-alert-dialog-container > div:first-child {\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: center;\n width: 100%;\n height: 24px;\n cursor: move;\n border-top-left-radius: 4px;\n border-top-right-radius: 4px;\n border-bottom-color: #7F7F7F;\n border-bottom-style: solid;\n border-bottom-width: thin;\n background-color: #eee; }\n .igv-ui-alert-dialog-container > div:first-child div:first-child {\n padding-left: 8px; }\n .igv-ui-alert-dialog-container #igv-ui-alert-dialog-body {\n color: #373737;\n width: 100%;\n height: calc(100% - 24px - 64px);\n overflow-y: scroll; }\n .igv-ui-alert-dialog-container #igv-ui-alert-dialog-body #igv-ui-alert-dialog-body-copy {\n cursor: pointer;\n margin: 16px;\n width: auto;\n height: auto;\n overflow-wrap: break-word;\n word-break: break-word;\n background-color: white;\n border: unset; }\n .igv-ui-alert-dialog-container > div:last-child {\n width: 100%;\n margin-bottom: 10px;\n background-color: white;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: center;
19508\n align-items: center; }\n .igv-ui-alert-dialog-container > div:last-child div {\n margin: unset;\n width: 40px;\n height: 30px;\n line-height: 30px;\n text-align: center;\n color: white;\n font-family: \"Open Sans\", sans-serif;\n font-size: small;\n font-weight: 400;\n border-color: #2B81AF;\n border-style: solid;\n border-width: thin;\n border-radius: 4px;\n background-color: #2B81AF; }\n .igv-ui-alert-dialog-container > div:last-child div:hover {\n cursor: pointer;\n border-color: #25597f;\n background-color: #25597f; }\n\n.igv-ui-color-swatch {\n position: relative;\n box-sizing: content-box;\n display: flex;\n flex-flow: row;\n flex-wrap: wrap;\n justify-content: center;\n align-items: center;\n width: 32px;\n height: 32px;\n border-style: solid;\n border-width: 2px;\n border-color: white;\n border-radius: 4px; }\n\n.igv-ui-color-swatch:hover {\n border-color: dimgray; }\n\n.igv-ui-colorpicker-menu-close-button {\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: flex-end;\n align-items: center;\n width: 100%;\n height: 32px;\n margin-top: 4px;\n margin-bottom: 4px;\n padding-right: 8px; }\n .igv-ui-colorpicker-menu-close-button i.fa {\n display: block;\n margin-left: 4px;\n margin-right: 4px;\n color: #5f5f5f; }\n .igv-ui-colorpicker-menu-close-button i.fa:hover,\n .igv-ui-colorpicker-menu-close-button i.fa:focus,\n .igv-ui-colorpicker-menu-close-button i.fa:active {\n cursor: pointer;\n color: #0f0f0f; }\n\n.igv-ui-generic-dialog-container {\n box-sizing: content-box;\n position: fixed;\n top: 0;\n left: 0;\n width: 300px;\n height: 200px;\n border-color: #7F7F7F;\n border-radius: 4px;\n border-style: solid;\n border-width: thin;\n font-family: \"Open Sans\", sans-serif;\n font-size: medium;\n font-weight: 400;\n z-index: 2048;\n background-color: white;\n display: flex;\n flex-flow: column;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: center; }\n .igv-ui-generic-dialog-container .igv-ui-generic-dialog-header {\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: flex-end;\n align-items: center;\n width: 100%;\n height: 24px;\n cursor: move;\n border-top-left-radius: 4px;\n border-top-right-radius: 4px;\n border-bottom-color: #7F7F7F;\n border-bottom-style: solid;\n border-bottom-width: thin;\n background-color: #eee; }\n .igv-ui-generic-dialog-container .igv-ui-generic-dialog-header div {\n margin-right: 4px;\n margin-bottom: 2px;\n height: 12px;\n width: 12px;\n color: #7F7F7F; }\n .igv-ui-generic-dialog-container .igv-ui-generic-dialog-header div:hover {\n cursor: pointer;\n color: #444; }\n .igv-ui-generic-dialog-container .igv-ui-generic-dialog-one-liner {\n color: #373737;\n width: 95%;\n height: 24px;\n line-height: 24px;\n text-align: left;\n margin-top: 8px;\n padding-left: 8px;\n overflow-wrap: break-word;\n background-color: white; }\n .igv-ui-generic-dialog-container .igv-ui-generic-dialog-label-input {\n margin-top: 8px;\n width: 95%;\n height: 24px;\n color: #373737;\n line-height: 24px;\n padding-left: 8px;\n background-color: white;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: center; }\n .igv-ui-generic-dialog-container .igv-ui-generic-dialog-label-input div {\n width: 30%;\n height: 100%;\n font-size: 16px;\n text-align: right;\n padding-right: 8px;\n background-color: white; }\n .igv-ui-generic-dialog-container .igv-ui-generic-dialog-label-input input {\n display: block;\n height: 100%;\n width: 100%;\n padding-left: 4px;\n font-family: \"Open Sans\", sans-serif;\n font-weight: 400;\n color: #373737;\n text-align: left;\n outline: none;\n border-style: solid;\n border-width: thin;\n border-color: #7F7F7F;\n background-color: white; }\n .igv-ui-generic-dialog-container .igv-ui-generic-dialog-label-input input {\n width: 50%;\n font-size: 16px; }\n .igv-ui-generic-dialog-container .igv-ui-generic-dialog-input {\n margin-top: 8px;\n width: calc(100% - 16px);\n height: 24px;\n color: #373737;\n line-height: 24px;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: space-around;
19508\n align-items: center; }\n .igv-ui-generic-dialog-container .igv-ui-generic-dialog-input input {\n display: block;\n height: 100%;\n width: 100%;\n padding-left: 4px;\n font-family: \"Open Sans\", sans-serif;\n font-weight: 400;\n color: #373737;\n text-align: left;\n outline: none;\n border-style: solid;\n border-width: thin;\n border-color: #7F7F7F;\n background-color: white; }\n .igv-ui-generic-dialog-container .igv-ui-generic-dialog-input input {\n font-size: 16px; }\n .igv-ui-generic-dialog-container .igv-ui-generic-dialog-ok-cancel {\n width: 100%;\n height: 28px;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: space-around;\n align-items: center; }\n .igv-ui-generic-dialog-container .igv-ui-generic-dialog-ok-cancel div {\n margin-top: 32px;\n color: white;\n font-family: \"Open Sans\", sans-serif;\n font-size: 14px;\n font-weight: 400;\n width: 75px;\n height: 28px;\n line-height: 28px;\n text-align: center;\n border-color: transparent;\n border-style: solid;\n border-width: thin;\n border-radius: 2px; }\n .igv-ui-generic-dialog-container .igv-ui-generic-dialog-ok-cancel div:first-child {\n margin-left: 32px;\n margin-right: 0;\n background-color: #5ea4e0; }\n .igv-ui-generic-dialog-container .igv-ui-generic-dialog-ok-cancel div:last-child {\n margin-left: 0;\n margin-right: 32px;\n background-color: #c4c4c4; }\n .igv-ui-generic-dialog-container .igv-ui-generic-dialog-ok-cancel div:first-child:hover {\n cursor: pointer;\n background-color: #3b5c7f; }\n .igv-ui-generic-dialog-container .igv-ui-generic-dialog-ok-cancel div:last-child:hover {\n cursor: pointer;\n background-color: #7f7f7f; }\n .igv-ui-generic-dialog-container .igv-ui-generic-dialog-ok {\n width: 100%;\n height: 36px;\n margin-top: 32px;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: space-around;\n align-items: center; }\n .igv-ui-generic-dialog-container .igv-ui-generic-dialog-ok div {\n width: 98px;\n height: 36px;\n line-height: 36px;\n text-align: center;\n color: white;\n font-family: \"Open Sans\", sans-serif;\n font-size: medium;\n font-weight: 400;\n border-color: white;\n border-style: solid;\n border-width: thin;\n border-radius: 4px;\n background-color: #2B81AF; }\n .igv-ui-generic-dialog-container .igv-ui-generic-dialog-ok div:hover {\n cursor: pointer;\n background-color: #25597f; }\n\n.igv-ui-generic-container {\n box-sizing: content-box;\n position: absolute;\n z-index: 2048;\n background-color: white;\n cursor: pointer;\n display: flex;\n flex-direction: row;\n flex-wrap: wrap;\n justify-content: flex-start;\n align-items: center; }\n .igv-ui-generic-container div:first-child {\n cursor: move;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: flex-end;\n align-items: center;\n height: 24px;\n width: 100%;\n background-color: #dddddd; }\n .igv-ui-generic-container div:first-child div {\n display: block;\n color: #5f5f5f;\n cursor: pointer;\n width: 14px;\n height: 14px;\n margin-right: 8px;\n margin-bottom: 4px; }\n\n.igv-ui-dialog {\n z-index: 2048;\n position: fixed;\n width: fit-content;\n height: fit-content;\n display: flex;\n flex-flow: column;\n flex-wrap: nowrap;\n justify-content: flex-start;\n background-color: white;\n border-color: #7F7F7F;\n border-radius: 4px;\n border-style: solid;\n border-width: thin;\n font-family: \"Open Sans\", sans-serif;\n font-size: medium;\n font-weight: 400; }\n .igv-ui-dialog .igv-ui-dialog-header {\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: flex-end;\n align-items: center;\n width: 100%;\n height: 24px;\n cursor: move;\n border-top-left-radius: 4px;\n border-top-right-radius: 4px;\n border-bottom-color: #7F7F7F;\n border-bottom-style: solid;\n border-bottom-width: thin;\n background-color: #eee; }\n .igv-ui-dialog .igv-ui-dialog-header div {\n margin-right: 4px;\n margin-bottom: 2px;\n height: 12px;\n width: 12px;\n color: #7F7F7F; }\n .igv-ui-dialog .igv-ui-dialog-header div:hover {\n cursor: pointer;\n color: #444; }\n .igv-ui-dialog .igv-ui-dialog-one-liner {\n width: 95%;\n height: 24px;\n line-height: 24px;\n text-align: left;\n margin: 8px;\n overflow-wrap: break-word;\n background-color: white;\n font-weight: bold; }\n .igv-ui-dialog .igv-ui-dialog-ok-cancel {\n width: 100%;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: space-around;
19508\n align-items: center; }\n .igv-ui-dialog .igv-ui-dialog-ok-cancel div {\n margin: 16px;\n margin-top: 32px;\n color: white;\n font-family: \"Open Sans\", sans-serif;\n font-size: 14px;\n font-weight: 400;\n width: 75px;\n height: 28px;\n line-height: 28px;\n text-align: center;\n border-color: transparent;\n border-style: solid;\n border-width: thin;\n border-radius: 2px; }\n .igv-ui-dialog .igv-ui-dialog-ok-cancel div:first-child {\n background-color: #5ea4e0; }\n .igv-ui-dialog .igv-ui-dialog-ok-cancel div:last-child {\n background-color: #c4c4c4; }\n .igv-ui-dialog .igv-ui-dialog-ok-cancel div:first-child:hover {\n cursor: pointer;\n background-color: #3b5c7f; }\n .igv-ui-dialog .igv-ui-dialog-ok-cancel div:last-child:hover {\n cursor: pointer;\n background-color: #7f7f7f; }\n .igv-ui-dialog .igv-ui-dialog-ok {\n width: 100%;\n height: 36px;\n margin-top: 32px;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: space-around;\n align-items: center; }\n .igv-ui-dialog .igv-ui-dialog-ok div {\n width: 98px;\n height: 36px;\n line-height: 36px;\n text-align: center;\n color: white;\n font-family: \"Open Sans\", sans-serif;\n font-size: medium;\n font-weight: 400;\n border-color: white;\n border-style: solid;\n border-width: thin;\n border-radius: 4px;\n background-color: #2B81AF; }\n .igv-ui-dialog .igv-ui-dialog-ok div:hover {\n cursor: pointer;\n background-color: #25597f; }\n\n.igv-ui-panel, .igv-ui-panel-column, .igv-ui-panel-row {\n z-index: 2048;\n background-color: white;\n font-family: \"Open Sans\", sans-serif;\n font-size: medium;\n font-weight: 400;\n display: flex;\n justify-content: flex-start;\n align-items: flex-start; }\n\n.igv-ui-panel-column {\n display: flex;\n flex-direction: column; }\n\n.igv-ui-panel-row {\n display: flex;\n flex-direction: row; }\n\n.igv-ui-textbox {\n background-color: white;\n font-family: \"Open Sans\", sans-serif;\n font-size: medium;\n font-weight: 400;\n display: flex;\n justify-content: flex-start;\n align-items: flex-start; }\n\n/*# sourceMappingURL=igv-ui.css.map */\n'; 19509 var style = document.createElement('style'); 19510 style.setAttribute('type', 'text/css'); 19511 style.innerHTML = css; 19512 document.head.insertBefore(style, document.head.childNodes[document.head.childNodes.length - 1]); 19513 } 19514 19515 if (typeof document !== 'undefined') { 19516 if (!stylesheetExists("igv-ui.css")) { 19517 // console.log('igv-ui. will call embedCSS() ...'); 19518 embedCSS$2(); // console.log('... done.'); 19519 } 19520 19521 function stylesheetExists(stylesheetName) { 19522 for (let ss of document.styleSheets) { 19523 ss = ss.href ? ss.href.replace(/^.*[\\\/]/, '') : ''; 19524 19525 if (ss === stylesheetName) { 19526 return true; 19527 } 19528 } 19529 19530 return false; 19531 } 19532 } 19533 19534 /* 19535 * The MIT License (MIT) 19536 * 19537 * Copyright (c) 2016-2017 The Regents of the University of California 19538 * Author: Jim Robinson 19539 * 19540 * Permission is hereby granted, free of charge, to any person obtaining a copy 19541 * of this software and associated documentation files (the "Software"), to deal 19542 * in the Software without restriction, including without limitation the rights 19543 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 19544 * copies of the Software, and to permit persons to whom the Software is 19545 * furnished to do so, subject to the following conditions: 19546 * 19547 * The above copyright notice and this permission notice shall be included in 19548 * all copies or substantial portions of the Software. 19549 * 19550 * 19551 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19552 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19553 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19554 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19555 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19556 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19557 * THE SOFTWARE. 19558 */ 19559 19560 class DataRangeDialog { 19561 constructor($parent, alert) { 19562 // dialog container 19563 this.$container = $$1("<div>", { 19564 class: 'igv-generic-dialog-container' 19565 }); 19566 $parent.append(this.$container); 19567 this.$container.offset({ 19568 left: 0, 19569 top: 0 19570 }); // dialog header 19571 19572 const $header = $$1("<div>", { 19573 class: 'igv-generic-dialog-header' 19574 }); 19575 this.$container.append($header); 19576 attachDialogCloseHandlerWithParent$1($header[0], () => { 19577 this.$minimum_input.val(undefined); 19578 this.$maximum_input.val(undefined); 19579 this.$container.offset({ 19580 left: 0, 19581 top: 0 19582 }); 19583 this.$container.hide(); 19584 }); // minimun 19585 19586 this.$minimum = $$1("<div>", { 19587 class: 'igv-generic-dialog-label-input' 19588 }); 19589 this.$container.append(this.$minimum); 19590 const $mindiv = $$1('<div>'); 19591 $mindiv.text('Minimum'); 19592 this.$minimum.append($mindiv); 19593 this.$minimum_input = $$1("<input>"); 19594 this.$minimum.append(this.$minimum_input); // maximum 19595 19596 this.$maximum = $$1("<div>", { 19597 class: 'igv-generic-dialog-label-input' 19598 }); 19599 this.$container.append(this.$maximum); 19600 const $maxdiv = $$1('<div>'); 19601 $maxdiv.text('Maximum'); 19602 this.$maximum.append($maxdiv); 19603 this.$maximum_input = $$1("<input>"); 19604 this.$maximum.append(this.$maximum_input); // ok | cancel 19605 19606 const $buttons = $$1("<div>", { 19607 class: 'igv-generic-dialog-ok-cancel' 19608 }); 19609 this.$container.append($buttons); // ok 19610 19611 this.$ok = $$1("<div>"); 19612 $buttons.append(this.$ok); 19613 this.$ok.text('OK'); // cancel 19614 19615 this.$cancel = $$1("<div>"); 19616 $buttons.append(this.$cancel); 19617 this.$cancel.text('Cancel'); 19618 this.$cancel.on('click', () => { 19619 this.$minimum_input.val(undefined); 19620 this.$maximum_input.val(undefined); 19621 this.$container.offset({ 19622 left: 0, 19623 top: 0 19624 }); 19625 this.$container.hide(); 19626 }); //this.$container.draggable({ handle:$header.get(0) }); 19627 19628 makeDraggable$1(this.$container.get(0), $header.get(0)); 19629 this.$container.hide(); 19630 } 19631 19632 configure(trackView) { 19633 const dataRange = trackView.dataRange(); 19634 let min; 19635 let max; 19636 19637 if (dataRange) { 19638 min = dataRange.min; 19639 max = dataRange.max; 19640 } else { 19641 min = 0; 19642 max = 100; 19643 } 19644 19645 this.$minimum_input.val(min); 19646 this.$maximum_input.val(max); 19647 this.$minimum_input.unbind(); 19648 this.$minimum_input.on('keyup', e => { 19649 if (13 === e.keyCode) { 19650 this.processResults(trackView); 19651 } 19652 }); 19653 this.$maximum_input.unbind(); 19654 this.$maximum_input.on('keyup', e => { 19655 if (13 === e.keyCode) { 19656 this.processResults(trackView); 19657 } 19658 }); 19659 this.$ok.unbind(); 19660 this.$ok.on('click', e => { 19661 this.processResults(trackView); 19662 }); 19663 } 19664 19665 processResults(trackView) { 19666 const min = Number(this.$minimum_input.val()); 19667 const max = Number(this.$maximum_input.val()); 19668 19669 if (isNaN(min) || isNaN(max)) { 19670 Alert.presentAlert(new Error('Must input numeric values'), undefined); 19671 } else { 19672 trackView.setDataRange(min, max); 19673 } 19674 19675 this.$minimum_input.val(undefined); 19676 this.$maximum_input.val(undefined); 19677 this.$container.offset({ 19678 left: 0, 19679 top: 0 19680 }); 19681 this.$container.hide(); 19682 } 19683 19684 present($parent) { 19685 const offset_top = $parent.offset().top; 19686 const scroll_top = $$1('body').scrollTop(); 19687 this.$container.offset({ 19688 left: $parent.width() - this.$container.width(), 19689 top: offset_top + scroll_top 19690 }); 19691 this.$container.show(); 19692 } 19693 19694 } 19695 19696 /* 19697 * The MIT License (MIT) 19698 * 19699 * Copyright (c) 2014 Broad Institute 19700 * 19701 * Permission is hereby granted, free of charge, to any person obtaining a copy 19702 * of ctx software and associated documentation files (the "Software"), to deal 19703 * in the Software without restriction, including without limitation the rights 19704 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 19705 * copies of the Software, and to permit persons to whom the Software is 19706 * furnished to do so, subject to the following conditions: 19707 * 19708 * The above copyright notice and ctx permission notice shall be included in 19709 * all copies or substantial portions of the Software. 19710 * 19711 * 19712 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19713 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19714 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19715 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19716 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19717 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19718 * THE SOFTWARE. 19719 */ 19720 19721 const IGVGraphics = { 19722 configureHighDPICanvas: function (ctx, w, h) { 19723 const scaleFactor = window.devicePixelRatio; // const scaleFactor = 1 19724 19725 ctx.canvas.style.width = `${w}px`; 19726 ctx.canvas.width = Math.floor(scaleFactor * w); 19727 ctx.canvas.style.height = `${h}px`; 19728 ctx.canvas.height = Math.floor(scaleFactor * h); 19729 ctx.scale(scaleFactor, scaleFactor); 19730 }, 19731 setProperties: function (ctx, properties) { 19732 for (var key in properties) { 19733 if (properties.hasOwnProperty(key)) { 19734 var value = properties[key]; 19735 ctx[key] = value; 19736 } 19737 } 19738 }, 19739 strokeLine: function (ctx, x1, y1, x2, y2, properties) { 19740 x1 = Math.floor(x1) + 0.5; 19741 y1 = Math.floor(y1) + 0.5; 19742 x2 = Math.floor(x2) + 0.5; 19743 y2 = Math.floor(y2) + 0.5; 19744 19745 if (properties) { 19746 ctx.save(); 19747 IGVGraphics.setProperties(ctx, properties); 19748 } 19749 19750 ctx.beginPath(); 19751 ctx.moveTo(x1, y1); 19752 ctx.lineTo(x2, y2); 19753 ctx.stroke();
19754 if (properties) ctx.restore(); 19755 }, 19756 fillRect: function (ctx, x, y, w, h, properties) { 19757 x = Math.round(x); 19758 y = Math.round(y); 19759 19760 if (properties) { 19761 ctx.save(); 19762 IGVGraphics.setProperties(ctx, properties); 19763 } 19764 19765 ctx.fillRect(x, y, w, h); 19766 if (properties) ctx.restore(); 19767 }, 19768 fillPolygon: function (ctx, x, y, properties) { 19769 if (properties) { 19770 ctx.save(); 19771 IGVGraphics.setProperties(ctx, properties); 19772 } 19773 19774 doPath(ctx, x, y); 19775 ctx.fill(); 19776 if (properties) ctx.restore(); 19777 }, 19778 strokePolygon: function (ctx, x, y, properties) { 19779 if (properties) { 19780 ctx.save(); 19781 IGVGraphics.setProperties(ctx, properties); 19782 } 19783 19784 doPath(ctx, x, y); 19785 ctx.stroke(); 19786 if (properties) ctx.restore(); 19787 }, 19788 fillText: function (ctx, text, x, y, properties, transforms) { 19789 if (properties || transforms) { 19790 ctx.save(); 19791 } 19792 19793 if (properties) { 19794 IGVGraphics.setProperties(ctx, properties); 19795 } 19796 19797 if (transforms) { 19798 // Slow path with context saving and extra translate 19799 ctx.translate(x, y); 19800 19801 for (var transform in transforms) { 19802 var value = transforms[transform]; // TODO: Add error checking for robustness 19803 19804 if (transform === 'translate') { 19805 ctx.translate(value['x'], value['y']); 19806 } 19807 19808 if (transform === 'rotate') { 19809 ctx.rotate(value['angle'] * Math.PI / 180); 19810 } 19811 } 19812 19813 ctx.fillText(text, 0, 0); 19814 } else { 19815 ctx.fillText(text, x, y); 19816 } 19817 19818 if (properties || transforms) ctx.restore(); 19819 }, 19820 strokeText: function (ctx, text, x, y, properties, transforms) { 19821 if (properties || transforms) { 19822 ctx.save(); 19823 } 19824 19825 if (properties) { 19826 IGVGraphics.setProperties(ctx, properties); 19827 } 19828 19829 if (transforms) { 19830 ctx.translate(x, y); 19831 19832 for (var transform in transforms) { 19833 var value = transforms[transform]; // TODO: Add error checking for robustness 19834 19835 if (transform === 'translate') { 19836 ctx.translate(value['x'], value['y']); 19837 } 19838 19839 if (transform === 'rotate') { 19840 ctx.rotate(value['angle'] * Math.PI / 180); 19841 } 19842 } 19843 19844 ctx.strokeText(text, 0, 0); 19845 } else { 19846 ctx.strokeText(text, x, y); 19847 } 19848 19849 if (properties || transforms) ctx.restore(); 19850 }, 19851 strokeCircle: function (ctx, x, y, radius, properties) { 19852 if (properties) { 19853 ctx.save(); 19854 IGVGraphics.setProperties(ctx, properties); 19855 } 19856 19857 ctx.beginPath(); 19858 ctx.arc(x, y, radius, 0, 2 * Math.PI); 19859 ctx.stroke(); 19860 if (properties) ctx.restore(); 19861 }, 19862 fillCircle: function (ctx, x, y, radius, properties) { 19863 if (properties) { 19864 ctx.save(); 19865 IGVGraphics.setProperties(ctx, properties); 19866 } 19867 19868 ctx.beginPath(); 19869 ctx.arc(x, y, radius, 0, 2 * Math.PI); 19870 ctx.fill(); 19871 if (properties) ctx.restore(); 19872 }, 19873 drawArrowhead: function (ctx, x, y, size, lineWidth) { 19874 ctx.save(); 19875 19876 if (!size) { 19877 size = 5; 19878 } 19879 19880 if (lineWidth) { 19881 ctx.lineWidth = lineWidth; 19882 } 19883 19884 ctx.beginPath(); 19885 ctx.moveTo(x, y - size / 2); 19886 ctx.lineTo(x, y + size / 2); 19887 ctx.lineTo(x + size, y); 19888 ctx.lineTo(x, y - size / 2); 19889 ctx.closePath(); 19890 ctx.fill(); 19891 ctx.restore(); 19892 }, 19893 dashedLine: function (ctx, x1, y1, x2, y2, dashLen) { 19894 let properties = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : {}; 19895 if (dashLen === undefined) dashLen = 2; 19896 ctx.setLineDash([dashLen, dashLen]); 19897 IGVGraphics.strokeLine(ctx, x1, y1, x2, y2, properties); 19898 ctx.setLineDash([]); 19899 }, 19900 roundRect: function (ctx, x, y, width, height, radius, fill, stroke) { 19901 if (typeof stroke == "undefined") { 19902 stroke = true; 19903 } 19904 19905 if (typeof radius === "undefined") { 19906 radius = 5; 19907 } 19908 19909 ctx.beginPath(); 19910 ctx.moveTo(x + radius, y);
19911 ctx.lineTo(x + width - radius, y); 19912 ctx.quadraticCurveTo(x + width, y, x + width, y + radius); 19913 ctx.lineTo(x + width, y + height - radius); 19914 ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height); 19915 ctx.lineTo(x + radius, y + height); 19916 ctx.quadraticCurveTo(x, y + height, x, y + height - radius); 19917 ctx.lineTo(x, y + radius); 19918 ctx.quadraticCurveTo(x, y, x + radius, y); 19919 ctx.closePath(); 19920 19921 if (stroke) { 19922 ctx.stroke(); 19923 } 19924 19925 if (fill) { 19926 ctx.fill(); 19927 } 19928 }, 19929 polygon: function (ctx, x, y, fill, stroke) { 19930 if (typeof stroke == "undefined") { 19931 stroke = true; 19932 } 19933 19934 ctx.beginPath(); 19935 var len = x.length; 19936 ctx.moveTo(x[0], y[0]); 19937 19938 for (var i = 1; i < len; i++) { 19939 ctx.lineTo(x[i], y[i]); // this.moveTo(x[i], y[i]); 19940 } 19941 19942 ctx.closePath(); 19943 19944 if (stroke) { 19945 ctx.stroke(); 19946 } 19947 19948 if (fill) { 19949 ctx.fill(); 19950 } 19951 } 19952 }; 19953 19954 function doPath(ctx, x, y) { 19955 var i, 19956 len = x.length; 19957 19958 for (i = 0; i < len; i++) { 19959 x[i] = Math.round(x[i]); 19960 y[i] = Math.round(y[i]); 19961 } 19962 19963 ctx.beginPath(); 19964 ctx.moveTo(x[0], y[0]); 19965 19966 for (i = 1; i < len; i++) { 19967 ctx.lineTo(x[i], y[i]); 19968 } 19969 19970 ctx.closePath(); 19971 } 19972 19973 const FileFormats = { 19974 gwascatalog: { 19975 fields: ['bin', 'chr', 'start', 'end', 'name', 'pubMedID', 'author', 'pubDate', 'journal', 'title', 'trait', 'initSample', 'replSample', 'region', 'genes', 'riskAllele', 'riskAlFreq', 'pValue', 'pValueDesc', 'orOrBeta', 'ci95', 'platform', 'cnv'] 19976 }, 19977 wgrna: { 19978 fields: ['bin', 'chr', 'start', 'end', 'name', 'score', 'strand', 'thickStart', 'thickEnd', 'type'] 19979 }, 19980 cpgislandext: { 19981 fields: ['bin', 'chr', 'start', 'end', 'name', 'length', 'cpgNum', 'gcNum', 'perCpg', 'perGc', 'obsExp'] 19982 }, 19983 clinVarMain: { 19984 fields: ['chr1', 'start', 'end', 'name', 'score', 'strand', 'thickStart', 'thickEnd', 'reserved', 'blockCount', // Number of blocks 19985 'blockSizes', // Comma separated list of block sizes 19986 'chromStarts', // Start positions relative to chromStart 19987 'origName', // NM_198053.2(CD247):c.462C>T (p.Asp154=) ClinVar Variation Report 19988 'clinSign', // Likely benign Clinical significance 19989 'reviewStatus', // based on: criteria provided,single submitter Review Status 19990 'type', // single nucleotide variant Type of Variant 19991 'geneId', // CD247 Gene Symbol 19992 'snpId', // 181656780 dbSNP ID 19993 'nsvId', // dbVar ID 19994 'rcvAcc', // RCV000642347 ClinVar Allele Submission 19995 'testedInGtr', // N Genetic Testing Registry 19996 'phenotypeList', // Immunodeficiency due to defect in cd3-zeta Phenotypes 19997 'phenotype', // MedGen:C1857798, OMIM:610163 Phenotype identifiers 19998 'origin', // germline Data origin 19999 'assembly', // GRCh37 Genome assembly 20000 'cytogenetic', // 1q24.2 Cytogenetic status 20001 'hgvsCod', // NM_198053.2:c.462C>T Nucleotide HGVS 20002 'hgvsProt', // NP_932170.1:p.Asp154= Protein HGVS 20003 'numSubmit', // 1 Number of submitters 20004 'lastEval', // Dec 19,2017 Last evaluation 20005 'guidelines', // Guidelines 20006 'otherIds'] 20007 } 20008 }; 20009 20010 /* 20011 * The MIT License (MIT) 20012 * 20013 * Copyright (c) 2014 Broad Institute 20014 * 20015 * Permission is hereby granted, free of charge, to any person obtaining a copy 20016 * of this software and associated documentation files (the "Software"), to deal 20017 * in the Software without restriction, including without limitation the rights 20018 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 20019 * copies of the Software, and to permit persons to whom the Software is 20020 * furnished to do so, subject to the following conditions: 20021 * 20022 * The above copyright notice and this permission notice shall be included in 20023 * all copies or substantial portions of the Software. 20024 * 20025 * 20026 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20027 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20028 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20029 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20030 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20031 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20032 * THE SOFTWARE. 20033 */
20034 const knownFileExtensions = new Set(["narrowpeak", "broadpeak", "regionpeak", "peaks", "bedgraph", "wig", "gff3", "gff", "gtf", "fusionjuncspan", "refflat", "seg", "aed", "bed", "vcf", "bb", "bigbed", "bw", "bigwig", "bam", "tdf", "refgene", "genepred", "genepredext", "bedpe", "bp", "snp", "rmsk", "cram", "gwas", "maf", "mut"]); 20035 /** 20036 * Return a custom format object with the given name. 20037 * @param name 20038 * @returns {*} 20039 */ 20040 20041 function getFormat(name) { 20042 if (FileFormats && FileFormats[name]) { 20043 return expandFormat(FileFormats[name]); 20044 } else { 20045 return undefined; 20046 } 20047 20048 function expandFormat(format) { 20049 const fields = format.fields; 20050 const keys = ['chr', 'start', 'end']; 20051 20052 for (let i = 0; i < fields.length; i++) { 20053 for (let key of keys) { 20054 if (key === fields[i]) { 20055 format[key] = i; 20056 } 20057 } 20058 } 20059 20060 return format; 20061 } 20062 } 20063 20064 function inferFileFormat(fn) { 20065 var idx, ext; 20066 fn = fn.toLowerCase(); // Special case -- UCSC refgene files 20067 20068 if (fn.endsWith("refgene.txt.gz") || fn.endsWith("refgene.txt.bgz") || fn.endsWith("refgene.txt") || fn.endsWith("refgene.sorted.txt.gz") || fn.endsWith("refgene.sorted.txt.bgz")) { 20069 return "refgene"; 20070 } //Strip parameters -- handle local files later 20071 20072 20073 idx = fn.indexOf("?"); 20074 20075 if (idx > 0) { 20076 fn = fn.substr(0, idx); 20077 } //Strip aux extensions .gz, .tab, and .txt 20078 20079 20080 if (fn.endsWith(".gz")) { 20081 fn = fn.substr(0, fn.length - 3); 20082 } 20083 20084 if (fn.endsWith(".txt") || fn.endsWith(".tab") || fn.endsWith(".bgz")) { 20085 fn = fn.substr(0, fn.length - 4); 20086 } 20087 20088 idx = fn.lastIndexOf("."); 20089 ext = idx < 0 ? fn : fn.substr(idx + 1); 20090 20091 switch (ext) { 20092 case "bw": 20093 return "bigwig"; 20094 20095 case "bb": 20096 return "bigbed"; 20097 20098 default: 20099 if (knownFileExtensions.has(ext)) { 20100 return ext; 20101 } else { 20102 return undefined; 20103 } 20104 20105 } 20106 } 20107 20108 function inferIndexPath(url, extension) { 20109 if (isString$3(url)) { 20110 if (url.includes("?")) { 20111 const idx = url.indexOf("?"); 20112 return url.substring(0, idx) + "." + extension + url.substring(idx); 20113 } else { 20114 return url + "." + extension; 20115 } 20116 } else { 20117 return undefined; 20118 } 20119 } 20120 20121 function inferTrackType(config) { 20122 translateDeprecatedTypes(config); 20123 20124 if (config.type) { 20125 return config.type; 20126 } 20127 20128 if (config.format) { 20129 const format = config.format.toLowerCase(); 20130 20131 switch (format) { 20132 case "bw": 20133 case "bigwig": 20134 case "wig": 20135 case "bedgraph": 20136 case "tdf": 20137 return "wig"; 20138 20139 case "vcf": 20140 return "variant"; 20141 20142 case "seg": 20143 return "seg"; 20144 20145 case "mut": 20146 case "maf": 20147 return "mut"; 20148 20149 case "bam": 20150 case "cram": 20151 return "alignment"; 20152 20153 case "bedpe": 20154 case "bedpe-loop": 20155 return "interact"; 20156 20157 case "bp": 20158 return "arc"; 20159 20160 case "gwas": 20161 return "gwas"; 20162 20163 case "bed": 20164 case "bigbed": 20165 case "bb": 20166 return "bedtype"; 20167 20168 default: 20169 return "annotation"; 20170 } 20171 } 20172 } 20173 20174 function translateDeprecatedTypes(config) { 20175 if (config.featureType) { 20176 // Translate deprecated "feature" type 20177 config.type = config.type || config.featureType; 20178 config.featureType = undefined; 20179 } 20180 20181 if ("junctions" === config.type) { 20182 config.type = "junction"; 20183 } else if ("bed" === config.type) { 20184 config.type = "annotation"; 20185 config.format = config.format || "bed"; 20186 } else if ("annotations" === config.type) { 20187 config.type = "annotation"; 20188 } else if ("alignments" === config.type) { 20189 config.type = "alignment"; 20190 } else if ("bam" === config.type) { 20191 config.type = "alignment"; 20192 config.format = "bam"; 20193 } else if ("vcf" === config.type) { 20194 config.type = "variant"; 20195 config.format = "vcf"; 20196 } else if ("t2d" === config.type) { 20197 config.type = "gwas"; 20198 } else if ("FusionJuncSpan" === config.type && !config.format) { 20199 config.format = "fusionjuncspan"; 20200 } else if ("aed" === config.type) { 20201 config.type = "annotation"; 20202 config.format = config.format || "aed"; 20203 } 20204 } 20205 20206 /* 20207 * The MIT License (MIT) 20208 * 20209 * Copyright (c) 2014 Broad Institute 20210 * 20211 * Permission is hereby granted, free of charge, to any person obtaining a copy 20212 * of this software and associated documentation files (the "Software"), to deal 20213 * in the Software without restriction, including without limitation the rights 20214 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 20215 * copies of the Software, and to permit persons to whom the Software is 20216 * furnished to do so, subject to the following conditions: 20217 * 20218 * The above copyright notice and this permission notice shall be included in 20219 * all copies or substantial portions of the Software. 20220 * 20221 * 20222 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20223 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20224 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20225 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20226 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20227 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20228 * THE SOFTWARE. 20229 */ 20230 const defaultSequenceTrackOrder = Number.MIN_SAFE_INTEGER; 20231 const translationDict = { 20232 'TTT': 'F', 20233 'TTC': 'F', 20234 'TTA': 'L', 20235 'TTG': 'L',
20236 'CTT': 'L', 20237 'CTC': 'L', 20238 'CTA': 'L', 20239 'CTG': 'L', 20240 'ATT': 'I', 20241 'ATC': 'I', 20242 'ATA': 'I', 20243 'ATG': 'M', 20244 'GTT': 'V', 20245 'GTC': 'V', 20246 'GTA': 'V', 20247 'GTG': 'V', 20248 'TCT': 'S', 20249 'TCC': 'S', 20250 'TCA': 'S', 20251 'TCG': 'S', 20252 'CCT': 'P', 20253 'CCC': 'P', 20254 'CCA': 'P', 20255 'CCG': 'P', 20256 'ACT': 'T', 20257 'ACC': 'T', 20258 'ACA': 'T', 20259 'ACG': 'T', 20260 'GCT': 'A', 20261 'GCC': 'A', 20262 'GCA': 'A', 20263 'GCG': 'A', 20264 'TAT': 'Y', 20265 'TAC': 'Y', 20266 'TAA': 'STOP', 20267 'TAG': 'STOP', 20268 'CAT': 'H', 20269 'CAC': 'H', 20270 'CAA': 'Q', 20271 'CAG': 'Q', 20272 'AAT': 'N', 20273 'AAC': 'N', 20274 'AAA': 'K', 20275 'AAG': 'K', 20276 'GAT': 'D', 20277 'GAC': 'D', 20278 'GAA': 'E', 20279 'GAG': 'E', 20280 'TGT': 'C', 20281 'TGC': 'C', 20282 'TGA': 'STOP', 20283 'TGG': 'W', 20284 'CGT': 'R', 20285 'CGC': 'R', 20286 'CGA': 'R', 20287 'CGG': 'R', 20288 'AGT': 'S', 20289 'AGC': 'S', 20290 'AGA': 'R', 20291 'AGG': 'R', 20292 'GGT': 'G', 20293 'GGC': 'G', 20294 'GGA': 'G', 20295 'GGG': 'G' 20296 }; 20297 const complement = {}; 20298 const t1 = ['A', 'G', 'C', 'T', 'Y', 'R', 'W', 'S', 'K', 'M', 'D', 'V', 'H', 'B', 'N', 'X']; 20299 const t2 = ['T', 'C', 'G', 'A', 'R', 'Y', 'W', 'S', 'M', 'K', 'H', 'B', 'D', 'V', 'N', 'X']; 20300 20301 for (let i = 0; i < t1.length; i++) { 20302 complement[t1[i]] = t2[i]; 20303 complement[t1[i].toLowerCase()] = t2[i].toLowerCase(); 20304 } 20305 20306 class SequenceTrack { 20307 constructor(config, browser) { 20308 this.type = "sequence"; 20309 this.browser = browser; 20310 this.removable = false; 20311 this.config = config; 20312 this.name = "Sequence"; 20313 this.id = "sequence"; 20314 this.sequenceType = config.sequenceType || "dna"; // dna | rna | prot 20315 20316 this.height = 25; 20317 this.disableButtons = false; 20318 this.order = config.order || defaultSequenceTrackOrder; 20319 this.ignoreTrackMenu = false;
20320 this.reversed = false; 20321 this.frameTranslate = false; 20322 } 20323 20324 menuItemList() { 20325 return [{ 20326 name: this.reversed ? "Forward" : "Reverse", 20327 click: () => { 20328 this.reversed = !this.reversed; 20329 this.trackView.repaintViews(); 20330 } 20331 }, { 20332 name: this.frameTranslate ? "Close Translation" : "Three-frame Translate", 20333 click: () => { 20334 this.frameTranslate = !this.frameTranslate; 20335 20336 if (this.frameTranslate) { 20337 for (let vp of this.trackView.viewports) { 20338 vp.setContentHeight(115); 20339 } 20340 20341 this.trackView.setTrackHeight(115); 20342 } else { 20343 for (let vp of this.trackView.viewports) { 20344 vp.setContentHeight(25); 20345 } 20346 20347 this.trackView.setTrackHeight(25); 20348 } 20349 20350 this.trackView.repaintViews(); 20351 } 20352 }]; 20353 } 20354 20355 contextMenuItemList(clickState) { 20356 const viewport = clickState.viewport; 20357 20358 if (viewport.referenceFrame.bpPerPixel <= 1) { 20359 const items = [{ 20360 label: 'View visible sequence...', 20361 click: async () => { 20362 const pixelWidth = viewport.getWidth(); 20363 const bpWindow = pixelWidth * viewport.referenceFrame.bpPerPixel; 20364 const chr = viewport.referenceFrame.chr; 20365 const start = viewport.referenceFrame.start; 20366 const end = start + bpWindow; 20367 const sequence = await this.browser.genome.sequence.getSequence(chr, start, end); 20368 Alert.presentAlert(sequence); 20369 } 20370 }]; 20371 20372 if (isSecureContext()) { 20373 items.push({ 20374 label: 'Copy visible sequence', 20375 click: async () => { 20376 const pixelWidth = viewport.getWidth(); 20377 const bpWindow = pixelWidth * viewport.referenceFrame.bpPerPixel; 20378 const chr = viewport.referenceFrame.chr; 20379 const start = viewport.referenceFrame.start; 20380 const end = start + bpWindow; 20381 const sequence = await this.browser.genome.sequence.getSequence(chr, start, end); 20382 navigator.clipboard.writeText(sequence); 20383 } 20384 }); 20385 } 20386 20387 items.push('<hr/>'); 20388 return items; 20389 } else { 20390 return undefined; 20391 } 20392 } 20393 20394 translateSequence(seq) { 20395 const threeFrame = [[], [], []]; 20396 20397 for (let fNum of [0, 1, 2]) { 20398 let idx = fNum; 20399 20400 while (seq.length - idx >= 3) { 20401 let st = seq.slice(idx, idx + 3); 20402 20403 if (this.reversed) { 20404 st = st.split('').reverse().join(''); 20405 } 20406 20407 const aa = translationDict[st.toUpperCase()] || ""; 20408 threeFrame[fNum].push({ 20409 codons: st, 20410 aminoA: aa 20411 }); 20412 idx += 3; 20413 } 20414 } 20415 20416 return threeFrame; 20417 } 20418 20419 async getFeatures(chr, start, end, bpPerPixel) { 20420 if (bpPerPixel && bpPerPixel > 1) { 20421 return null; 20422 } else { 20423 const sequence = await this.browser.genome.sequence.getSequence(chr, start, end); 20424 return { 20425 bpStart: start, 20426 sequence: sequence 20427 }; 20428 } 20429 } 20430 20431 draw(options) { 20432 const ctx = options.context; 20433 20434 if (options.features) { 20435 const sequence = options.features.sequence; 20436 const sequenceBpStart = options.features.bpStart; 20437 const bpEnd = 1 + options.bpStart + options.pixelWidth * options.bpPerPixel; 20438 let height = 15; 20439 20440 for (let bp = sequenceBpStart; bp <= bpEnd; bp++) { 20441 let seqOffsetBp = Math.floor(bp - sequenceBpStart); 20442 20443 if (seqOffsetBp < sequence.length) { 20444 let letter = sequence[seqOffsetBp]; 20445 20446 if (this.reversed) { 20447 letter = complement[letter] || ""; 20448 } 20449 20450 let offsetBP = bp - options.bpStart; 20451 let aPixel = offsetBP / options.bpPerPixel; 20452 let bPixel = (offsetBP + 1) / options.bpPerPixel; 20453 let color = this.fillColor(letter); // IGVGraphics.fillRect(ctx, aPixel, 5, bPixel - aPixel, height - 5, { fillStyle: randomRGBConstantAlpha(150, 255, 0.75) }); 20454 20455 if (options.bpPerPixel > 1 / 10) { 20456 IGVGraphics.fillRect(ctx, aPixel, 5, bPixel - aPixel, height - 5, { 20457 fillStyle: color 20458 }); 20459 } else { 20460 let xPixel = 0.5 * (aPixel + bPixel - ctx.measureText(letter).width); 20461 IGVGraphics.strokeText(ctx, letter, xPixel, height, { 20462 strokeStyle: color 20463 }); 20464 } 20465 } 20466 } 20467 20468 if (this.frameTranslate) { 20469 let transSeq; 20470 20471 if (this.reversed) { 20472 transSeq = sequence.split('').map(function (cv) { 20473 return complement[cv]; 20474 }); 20475 transSeq = transSeq.join(''); 20476 } else { 20477 transSeq = sequence; 20478 } 20479 20480 let y = height; 20481 let translatedSequence = this.translateSequence(transSeq); 20482 20483 for (let arr of translatedSequence) { 20484 let i = translatedSequence.indexOf(arr); 20485 let fNum = i; 20486 let h = 25; 20487 y = i === 0 ? y + 10 : y + 30; //Little less room at first. 20488 20489 for (let cv of arr) { 20490 let aaS; 20491 let idx = arr.indexOf(cv); 20492 let xSeed = idx + fNum + 2 * idx; 20493 let color = 0 === idx % 2 ? 'rgb(160,160,160)' : 'rgb(224,224,224)'; 20494 let p0 = Math.floor(xSeed / options.bpPerPixel); 20495 let p1 = Math.floor((xSeed + 3) / options.bpPerPixel); 20496 let pc = Math.round((p0 + p1) / 2); 20497 20498 if (cv.aminoA.indexOf('STOP') > -1) { 20499 color = 'rgb(255, 0, 0)'; 20500 aaS = 'STOP'; //Color blind accessible 20501 } else { 20502 aaS = cv.aminoA; 20503 } 20504 20505 if (cv.aminoA === 'M') { 20506 color = 'rgb(0, 153, 0)'; 20507 aaS = 'START'; //Color blind accessible 20508 } 20509 20510 IGVGraphics.fillRect(ctx, p0, y, p1 - p0, h, { 20511 fillStyle: color 20512 }); 20513 20514 if (options.bpPerPixel <= 1 / 10) { 20515 IGVGraphics.strokeText(ctx, aaS, pc - ctx.measureText(aaS).width / 2, y + 15); 20516 } 20517 } 20518 } 20519 } 20520 } 20521 } 20522 20523 supportsWholeGenome() { 20524 return false;
20525 } 20526 20527 computePixelHeight(ignore) { 20528 return this.height; 20529 } 20530 20531 fillColor(index) { 20532 if (this.color) { 20533 return this.color; 20534 } else if ("dna" === this.sequenceType) { 20535 return this.browser.nucleotideColors[index] || 'gray'; 20536 } else { 20537 return 'rgb(0, 0, 150)'; 20538 } 20539 } 20540 20541 } 20542 20543 /* 20544 * The MIT License (MIT) 20545 * 20546 * Copyright (c) 2014 Broad Institute 20547 * 20548 * Permission is hereby granted, free of charge, to any person obtaining a copy 20549 * of this software and associated documentation files (the "Software"), to deal 20550 * in the Software without restriction, including without limitation the rights 20551 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 20552 * copies of the Software, and to permit persons to whom the Software is 20553 * furnished to do so, subject to the following conditions: 20554 * 20555 * The above copyright notice and this permission notice shall be included in 20556 * all copies or substantial portions of the Software. 20557 * 20558 * 20559 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20560 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20561 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20562 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20563 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20564 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20565 * THE SOFTWARE. 20566 */ 20567 20568 class Viewport { 20569 constructor(trackView, viewportColumn, referenceFrame, width) { 20570 this.guid = guid$1(); 20571 this.trackView = trackView; 20572 this.referenceFrame = referenceFrame; 20573 this.browser = trackView.browser; 20574 this.$viewport = $$1('<div class="igv-viewport">'); 20575 viewportColumn.appendChild(this.$viewport.get(0)); 20576 20577 if (trackView.track.height) { 20578 this.$viewport.get(0).style.height = `${trackView.track.height}px`; 20579 } // Create an alert dialog for the sequence track to copy ref sequence to. 20580 20581 20582 if (trackView.track instanceof SequenceTrack) { 20583 this.alert = new AlertDialog(this.$viewport.get(0)); 20584 } 20585 20586 this.$content = $$1("<div>", { 20587 class: 'igv-viewport-content' 20588 }); 20589 this.$viewport.append(this.$content); 20590 this.$content.height(this.$viewport.height()); 20591 this.contentDiv = this.$content.get(0); 20592 this.$canvas = $$1('<canvas>'); 20593 this.$content.append(this.$canvas); 20594 this.canvas = this.$canvas.get(0); 20595 this.ctx = this.canvas.getContext("2d"); 20596 this.setWidth(width); 20597 this.initializationHelper(); 20598 } 20599 20600 initializationHelper() {} 20601 20602 showMessage(message) { 20603 if (!this.messageDiv) { 20604 this.messageDiv = document.createElement('div'); 20605 this.messageDiv.className = 'igv-viewport-message'; 20606 this.contentDiv.append(this.messageDiv); 20607 } 20608 20609 this.messageDiv.textContent = message; 20610 this.messageDiv.style.display = 'inline-block'; 20611 } 20612 20613 hideMessage(message) { 20614 if (this.messageDiv) this.messageDiv.style.display = 'none'; 20615 } 20616 20617 setTrackLabel(label) {} 20618 20619 startSpinner() {} 20620 20621 stopSpinner() {} 20622 20623 checkZoomIn() { 20624 return true; 20625 } 20626 20627 shift() {} 20628 20629 setTop(contentTop) { 20630 const viewportHeight = this.$viewport.height(); 20631 const viewTop = -contentTop; 20632 const viewBottom = viewTop + viewportHeight; 20633 this.$content.css('top', `${contentTop}px`); 20634 20635 if (undefined === this.canvasVerticalRange || this.canvasVerticalRange.bottom < viewBottom || this.canvasVerticalRange.top > viewTop) { 20636 this.repaint(); 20637 } 20638 } 20639 20640 async loadFeatures() { 20641 return undefined; 20642 } 20643 20644 async repaint() { 20645 console.log('Viewport - repaint()'); 20646 } 20647 20648 draw(drawConfiguration, features, roiFeatures) { 20649 console.log('Viewport - draw(drawConfiguration, features, roiFeatures)'); 20650 } 20651 20652 checkContentHeight() { 20653 let track = this.trackView.track; 20654 20655 if ("FILL" === track.displayMode) { 20656 this.setContentHeight(this.$viewport.height()); 20657 } else if (typeof track.computePixelHeight === 'function') { 20658 let features = this.cachedFeatures; 20659 20660 if (features && features.length > 0) { 20661 let requiredContentHeight = track.computePixelHeight(features); 20662 let currentContentHeight = this.$content.height(); 20663 20664 if (requiredContentHeight !== currentContentHeight) { 20665 this.setContentHeight(requiredContentHeight); 20666 } 20667 } 20668 } 20669 } 20670 20671 getContentHeight() { 20672 return this.$content.height(); 20673 } 20674 20675 setContentHeight(contentHeight) { 20676 // Maximum height of a canvas is ~32,000 pixels on Chrome, possibly smaller on other platforms 20677 contentHeight = Math.min(contentHeight, 32000); 20678 this.$content.height(contentHeight);
20679 if (this.tile) this.tile.invalidate = true; 20680 } 20681 20682 isLoading() { 20683 return false; 20684 } 20685 20686 saveSVG() {} 20687 20688 isVisible() { 20689 return this.$viewport.width(); 20690 } 20691 20692 setWidth(width) { 20693 this.$viewport.width(width); 20694 this.canvas.style.width = `${width}px`; 20695 this.canvas.setAttribute('width', width); 20696 } 20697 20698 getWidth() { 20699 return this.$viewport.width(); 20700 } 20701 20702 getContentTop() { 20703 return this.contentDiv.offsetTop; 20704 } 20705 20706 containsPosition(chr, position) { 20707 console.log('Viewport - containsPosition(chr, position)'); 20708 } 20709 20710 addMouseHandlers() {} 20711 20712 removeMouseHandlers() {} 20713 /** 20714 * Called when the associated track is removed. Do any needed cleanup here. 20715 */ 20716 20717 20718 dispose() { 20719 if (this.popover) { 20720 this.popover.dispose(); 20721 } 20722 20723 this.removeMouseHandlers(); 20724 this.$viewport.get(0).remove(); // Null out all properties -- this should not be neccessary, but just in case there is a 20725 // reference to self somewhere we want to free memory. 20726 20727 for (let key of Object.keys(this)) { 20728 this[key] = undefined; 20729 } 20730 } 20731 20732 } 20733 20734 /*!! 20735 * Canvas 2 Svg v1.0.19 20736 * A low level canvas to SVG converter. Uses a mock canvas context to build an SVG document. 20737 * 20738 * Licensed under the MIT license: 20739 * http://www.opensource.org/licenses/mit-license.php 20740 * 20741 * Author: 20742 * Kerry Liu 20743 * 20744 * Copyright (c) 2014 Gliffy Inc. 20745 */ 20746 20747 function format(str, args) { 20748 var keys = Object.keys(args), 20749 i; 20750 20751 for (i = 0; i < keys.length; i++) { 20752 str = str.replace(new RegExp("\\{" + keys[i] + "\\}", "gi"), args[keys[i]]); 20753 } 20754 20755 return str; 20756 } //helper function that generates a random string 20757 20758 20759 function randomString(holder) { 20760 var chars, randomstring, i; 20761 20762 if (!holder) { 20763 throw new Error("cannot create a random attribute name for an undefined object"); 20764 } 20765 20766 chars = "ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz"; 20767 randomstring = ""; 20768 20769 do { 20770 randomstring = ""; 20771 20772 for (i = 0; i < 12; i++) { 20773 randomstring += chars[Math.floor(Math.random() * chars.length)]; 20774 } 20775 } while (holder[randomstring]); 20776 20777 return randomstring; 20778 } //helper function to map named to numbered entities 20779 20780 20781 function createNamedToNumberedLookup(items, radix) { 20782 var i, 20783 entity, 20784 lookup = {}, 20785 base10; 20786 items = items.split(','); 20787 radix = radix || 10; // Map from named to numbered entities. 20788 20789 for (i = 0; i < items.length; i += 2) { 20790 entity = '&' + items[i + 1] + ';'; 20791 base10 = parseInt(items[i], radix); 20792 lookup[entity] = '&#' + base10 + ';'; 20793 } //FF and IE need to create a regex from hex values ie == \xa0 20794 20795 20796 lookup["\\xa0"] = ' '; 20797 return lookup; 20798 } //helper function to map canvas-textAlign to svg-textAnchor 20799 20800 20801 function getTextAnchor(textAlign) { 20802 //TODO: support rtl languages 20803 var mapping = { 20804 "left": "start", 20805 "right": "end", 20806 "center": "middle", 20807 "start": "start", 20808 "end": "end" 20809 }; 20810 return mapping[textAlign] || mapping.start; 20811 } //helper function to map canvas-textBaseline to svg-dominantBaseline 20812 20813 20814 function getDominantBaseline(textBaseline) { 20815 //INFO: not supported in all browsers 20816 var mapping = { 20817 "alphabetic": "alphabetic", 20818 "hanging": "hanging", 20819 "top": "text-before-edge", 20820 "bottom": "text-after-edge", 20821 "middle": "central" 20822 }; 20823 return mapping[textBaseline] || mapping.alphabetic; 20824 } 20825 /** 20826 * Return a new normalized vector of given vector 20827 */ 20828 20829 20830 function normalize$1(vector) { 20831 var len = Math.sqrt(vector[0] * vector[0] + vector[1] * vector[1]); 20832 return [vector[0] / len, vector[1] / len]; 20833 } 20834 20835 function intersectRect(rect1, rect2) { 20836 return rect1.x < rect2.x + rect2.width && rect1.x + rect1.width > rect2.x && rect1.y < rect2.y + rect2.height && rect1.y + rect1.height > rect2.y; 20837 } // Unpack entities lookup where the numbers are in radix 32 to reduce the size 20838 // entity mapping courtesy of tinymce 20839 20840 20841 const namedEntities = createNamedToNumberedLookup('50,nbsp,51,iexcl,52,cent,53,pound,54,curren,55,yen,56,brvbar,57,sect,58,uml,59,copy,' + '5a,ordf,5b,laquo,5c,not,5d,shy,5e,reg,5f,macr,5g,deg,5h,plusmn,5i,sup2,5j,sup3,5k,acute,' + '5l,micro,5m,para,5n,middot,5o,cedil,5p,sup1,5q,ordm,5r,raquo,5s,frac14,5t,frac12,5u,frac34,' + '5v,iquest,60,Agrave,61,Aacute,62,Acirc,63,Atilde,64,Auml,65,Aring,66,AElig,67,Ccedil,' + '68,Egrave,69,Eacute,6a,Ecirc,6b,Euml,6c,Igrave,6d,Iacute,6e,Icirc,6f,Iuml,6g,ETH,6h,Ntilde,' + '6i,Ograve,6j,Oacute,6k,Ocirc,6l,Otilde,6m,Ouml,6n,times,6o,Oslash,6p,Ugrave,6q,Uacute,' + '6r,Ucirc,6s,Uuml,6t,Yacute,6u,THORN,6v,szlig,70,agrave,71,aacute,72,acirc,73,atilde,74,auml,' + '75,aring,76,aelig,77,ccedil,78,egrave,79,eacute,7a,ecirc,7b,euml,7c,igrave,7d,iacute,7e,icirc,' + '7f,iuml,7g,eth,7h,ntilde,7i,ograve,7j,oacute,7k,ocirc,7l,otilde,7m,ouml,7n,divide,7o,oslash,' + '7p,ugrave,7q,uacute,7r,ucirc,7s,uuml,7t,yacute,7u,thorn,7v,yuml,ci,fnof,sh,Alpha,si,Beta,' + 'sj,Gamma,sk,Delta,sl,Epsilon,sm,Zeta,sn,Eta,so,Theta,sp,Iota,sq,Kappa,sr,Lambda,ss,Mu,' + 'st,Nu,su,Xi,sv,Omicron,t0,Pi,t1,Rho,t3,Sigma,t4,Tau,t5,Upsilon,t6,Phi,t7,Chi,t8,Psi,' + 't9,Omega,th,alpha,ti,beta,tj,gamma,tk,delta,tl,epsilon,tm,zeta,tn,eta,to,theta,tp,iota,' + 'tq,kappa,tr,lambda,ts,mu,tt,nu,tu,xi,tv,omicron,u0,pi,u1,rho,u2,sigmaf,u3,sigma,u4,tau,' + 'u5,upsilon,u6,phi,u7,chi,u8,psi,u9,omega,uh,thetasym,ui,upsih,um,piv,812,bull,816,hellip,' + '81i,prime,81j,Prime,81u,oline,824,frasl,88o,weierp,88h,image,88s,real,892,trade,89l,alefsym,' + '8cg,larr,8ch,uarr,8ci,rarr,8cj,darr,8ck,harr,8dl,crarr,8eg,lArr,8eh,uArr,8ei,rArr,8ej,dArr,' + '8ek,hArr,8g0,forall,8g2,part,8g3,exist,8g5,empty,8g7,nabla,8g8,isin,8g9,notin,8gb,ni,8gf,prod,' + '8gh,sum,8gi,minus,8gn,lowast,8gq,radic,8gt,prop,8gu,infin,8h0,ang,8h7,and,8h8,or,8h9,cap,8ha,cup,' + '8hb,int,8hk,there4,8hs,sim,8i5,cong,8i8,asymp,8j0,ne,8j1,equiv,8j4,le,8j5,ge,8k2,sub,8k3,sup,8
20841k4,' + 'nsub,8k6,sube,8k7,supe,8kl,oplus,8kn,otimes,8l5,perp,8m5,sdot,8o8,lceil,8o9,rceil,8oa,lfloor,8ob,' + 'rfloor,8p9,lang,8pa,rang,9ea,loz,9j0,spades,9j3,clubs,9j5,hearts,9j6,diams,ai,OElig,aj,oelig,b0,' + 'Scaron,b1,scaron,bo,Yuml,m6,circ,ms,tilde,802,ensp,803,emsp,809,thinsp,80c,zwnj,80d,zwj,80e,lrm,' + '80f,rlm,80j,ndash,80k,mdash,80o,lsquo,80p,rsquo,80q,sbquo,80s,ldquo,80t,rdquo,80u,bdquo,810,dagger,' + '811,Dagger,81g,permil,81p,lsaquo,81q,rsaquo,85c,euro', 32); //Some basic mappings for attributes and default values. 20842 20843 const STYLES = { 20844 "strokeStyle": { 20845 svgAttr: "stroke", 20846 //corresponding svg attribute 20847 canvas: "#000000", 20848 //canvas default 20849 svg: "none", 20850 //svg default 20851 apply: "stroke" //apply on stroke() or fill() 20852 20853 }, 20854 "fillStyle": { 20855 svgAttr: "fill", 20856 canvas: "#000000", 20857 svg: null, 20858 //svg default is black, but we need to special case this to handle canvas stroke without fill 20859 apply: "fill" 20860 }, 20861 "lineCap": { 20862 svgAttr: "stroke-linecap", 20863 canvas: "butt", 20864 svg: "butt", 20865 apply: "stroke" 20866 }, 20867 "lineJoin": { 20868 svgAttr: "stroke-linejoin", 20869 canvas: "miter", 20870 svg: "miter", 20871 apply: "stroke" 20872 }, 20873 "miterLimit": { 20874 svgAttr: "stroke-miterlimit", 20875 canvas: 10, 20876 svg: 4, 20877 apply: "stroke" 20878 }, 20879 "lineWidth": { 20880 svgAttr: "stroke-width", 20881 canvas: 1, 20882 svg: 1, 20883 apply: "stroke" 20884 }, 20885 "globalAlpha": { 20886 svgAttr: "opacity", 20887 canvas: 1, 20888 svg: 1, 20889 apply: "fill stroke" 20890 }, 20891 "font": { 20892 //font converts to multiple svg attributes, there is custom logic for this 20893 canvas: "10px sans-serif" 20894 }, 20895 "shadowColor": { 20896 canvas: "#000000" 20897 }, 20898 "shadowOffsetX": { 20899 canvas: 0 20900 }, 20901 "shadowOffsetY": { 20902 canvas: 0 20903 }, 20904 "shadowBlur": { 20905 canvas: 0 20906 }, 20907 "textAlign": { 20908 canvas: "start" 20909 }, 20910 "textBaseline": { 20911 canvas: "alphabetic" 20912 }, 20913 "lineDash": { 20914 svgAttr: "stroke-dasharray", 20915 canvas: [], 20916 svg: null, 20917 apply: "stroke" 20918 } 20919 }; 20920 /** 20921 * 20922 * @param gradientNode - reference to the gradient 20923 * @constructor 20924 */ 20925 20926 class CanvasGradient { 20927 constructor(gradientNode, ctx) { 20928 this.__root = gradientNode; 20929 this.__ctx = ctx; 20930 } 20931 /** 20932 * Adds a color stop to the gradient root 20933 */ 20934 20935 20936 addColorStop(offset, color) { 20937 var stop = this.__ctx.__createElement("stop"), 20938 regex, 20939 matches; 20940 20941 stop.setAttribute("offset", offset); 20942 20943 if (color && color.indexOf("rgba") !== -1) { 20944 //separate alpha value, since webkit can't handle it 20945 regex = /rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d?\.?\d*)\s*\)/gi; 20946 matches = regex.exec(color); 20947 stop.setAttribute("stop-color", format("rgb({r},{g},{b})", { 20948 r: matches[1], 20949 g: matches[2], 20950 b: matches[3] 20951 })); 20952 stop.setAttribute("stop-opacity", matches[4]); 20953 } else { 20954 stop.setAttribute("stop-color", color); 20955 } 20956 20957 this.__root.appendChild(stop); 20958 } 20959 20960 } 20961 20962 class CanvasPattern { 20963 constructor(pattern, ctx) { 20964 this.__root = pattern; 20965 this.__ctx = ctx; 20966 } 20967 20968 } 20969 /** 20970 * The mock canvas context 20971 * @param config - options include: 20972 * ctx - existing Context2D to wrap around 20973 * width - width of your canvas (defaults to 500) 20974 * height - height of your canvas (defaults to 500) 20975 * enableMirroring - enables canvas mirroring (get image data) (defaults to false) 20976 * document - the document object (defaults to the current document) 20977 */ 20978 20979 20980 class ctx { 20981 constructor(config) { 20982 if (!(this instanceof ctx)) { 20983 //did someone call this without new? 20984 return new ctx(config); 20985 } // clone config 20986 20987 20988 this.config = config; //setup options 20989 20990 this.width = config.width; 20991 this.height = config.height; 20992 this.enableMirroring = config.enableMirroring || false; 20993 this.canvas = this; ///point back to this instance! 20994 20995 this.__document = document; // allow passing in an existing context to wrap around 20996 // if a context is passed in, we know a canvas already exist 20997 20998 if (config.ctx) { 20999 this.__ctx = config.ctx; 21000 } else { 21001 this.__canvas = this.__document.createElement("canvas"); 21002 this.__ctx = this.__canvas.getContext("2d"); 21003 } // give this canvas a type 21004 21005 21006 this.isSVG = true; 21007 21008 this.__setDefaultStyles(); 21009 21010 this.__stack = [this.__getStyleState()]; 21011 this.__groupStack = []; // root svg element 21012 21013 this.__root = this.__createElement("svg"); 21014 21015 this.__root.setAttribute("width", this.width); 21016 21017 this.__root.setAttribute("height", this.height); // allow contents to overflow svg bbox 21018 21019 21020 this.__root.setAttribute('overflow', 'visible'); // viewbox 21021 21022 21023 if (config.viewbox) { 21024 const str = config.viewbox.x + ' ' + config.viewbox.y + ' ' + config.viewbox.width + ' ' + config.viewbox.height; 21025 21026 this.__root.setAttribute("viewBox", str); 21027 21028 this.viewbox = config.viewbox; 21029 } // make sure we don't generate the same ids in defs 21030 21031 21032 this.__ids = {}; // defs 21033 21034 this.__defs = this.__createElement("defs"); 21035 21036 this.__root.appendChild(this.__defs); 21037 21038 this.multiLocusGap = config.multiLocusGap; // svg background color 21039 21040 let backdropConfig = { 21041 id: 'svg_output_backdrop', 21042 width: '100%', 21043 height: '100%', 21044 fill: config.backdropColor || 'white' 21045 }; 21046 21047 let backdropRect = this.__createElement('rect', backdropConfig); 21048 21049 this.__root.appendChild(backdropRect); // root group 21050 21051 21052 this.__rootGroup = this.__createElement('g', { 21053 id: 'root-group' 21054 }); 21055 21056 this.__root.appendChild(this.__rootGroup); // point current element to root group 21057 21058 21059 this.__currentElement = this.__rootGroup; 21060 } 21061 21062 setWidth(width) { 21063 this.width = width; 21064 21065 this.__root.setAttribute("width", this.width); 21066 21067 const str = this.config.viewbox.x + ' ' + this.config.viewbox.y + ' ' + width + ' ' + this.config.viewbox.height; 21068 21069 this.__root.setAttribute("viewBox", str); 21070 } 21071 21072 setHeight(height) { 21073 this.height = height; 21074 21075 this.__root.setAttribute("height", this.height); 21076 21077 const str = this.config.viewbox.x + ' ' + this.config.viewbox.y + ' ' + this.config.viewbox.width + ' ' + height; 21078 21079 this.__root.setAttribute("viewBox", str); 21080 } 21081 21082 /** 21083 * Creates the specified svg element 21084 * @private 21085 */ 21086 __createElement(elementName, properties, resetFill) { 21087 if (typeof properties === "undefined") { 21088 properties = {}; 21089 } 21090 21091 let element = this.__document.createElementNS("http://www.w3.org/2000/svg", elementName); 21092 21093 if (resetFill) { 21094 //if fill or stroke is not specified, the svg element should not display. By default SVG's fill is black. 21095 element.setAttribute("fill", "none"); 21096 element.setAttribute("stroke", "none"); 21097 } 21098 21099 for (let key of Object.keys(properties)) { 21100 element.setAttribute(key, properties[key]); 21101 } 21102 21103 return element; 21104 } 21105 21106 /** 21107 * Applies default canvas styles to the context 21108 * @private 21109 */ 21110 __setDefaultStyles() { 21111 //default 2d canvas context properties see:http://www.w3.org/TR/2dcontext/ 21112 var keys = Object.keys(STYLES), 21113 i, 21114 key; 21115 21116 for (i = 0; i < keys.length; i++) { 21117 key = keys[i]; 21118 this[key] = STYLES[key].canvas; 21119 } 21120 } 21121 21122 /** 21123 * Applies styles on restore 21124 * @param styleState 21125 * @private 21126 */ 21127 __applyStyleState(styleState) { 21128 var keys = Object.keys(styleState), 21129 i, 21130 key; 21131 21132 for (i = 0; i < keys.length; i++) { 21133 key = keys[i]; 21134 this[key] = styleState[key]; 21135 } 21136 } 21137 21138 /** 21139 * Gets the current style state 21140 * @return {Object} 21141 * @private 21142 */ 21143 __getStyleState() { 21144 var i, 21145 styleState = {}, 21146 keys = Object.keys(STYLES), 21147 key; 21148 21149 for (i = 0; i < keys.length; i++) { 21150 key = keys[i]; 21151 styleState[key] = this[key]; 21152 } 21153 21154 return styleState; 21155 } 21156 21157 /** 21158 * Apples the current styles to the current SVG element. On "ctx.fill" or "ctx.stroke" 21159 * @param type 21160 * @private 21161 */ 21162 __applyStyleToCurrentElement(type) { 21163 var currentElement = this.__currentElement; 21164 var currentStyleGroup = this.__currentElementsToStyle; 21165 21166 if (currentStyleGroup) { 21167 currentElement.setAttribute(type, ""); 21168 currentElement = currentStyleGroup.element;
21169 currentStyleGroup.children.forEach(function (node) { 21170 node.setAttribute(type, ""); 21171 }); 21172 } 21173 21174 var keys = Object.keys(STYLES), 21175 i, 21176 style, 21177 value, 21178 id, 21179 regex, 21180 matches; 21181 21182 for (i = 0; i < keys.length; i++) { 21183 style = STYLES[keys[i]]; 21184 value = this[keys[i]]; 21185 21186 if (style.apply) { 21187 //is this a gradient or pattern? 21188 if (value instanceof CanvasPattern) { 21189 //pattern 21190 if (value.__ctx) { 21191 //copy over defs 21192 while (value.__ctx.__defs.childNodes.length) { 21193 id = value.__ctx.__defs.childNodes[0].getAttribute("id"); 21194 this.__ids[id] = id; 21195 21196 this.__defs.appendChild(value.__ctx.__defs.childNodes[0]); 21197 } 21198 } 21199 21200 currentElement.setAttribute(style.apply, format("url(#{id})", { 21201 id: value.__root.getAttribute("id") 21202 })); 21203 } else if (value instanceof CanvasGradient) { 21204 //gradient 21205 currentElement.setAttribute(style.apply, format("url(#{id})", { 21206 id: value.__root.getAttribute("id") 21207 })); 21208 } else if (style && style.apply.indexOf(type) !== -1 && style.svg !== value) { 21209 if ((style.svgAttr === "stroke" || style.svgAttr === "fill") && value && value.indexOf("rgba") !== -1) { 21210 //separate alpha value, since illustrator can't handle it 21211 regex = /rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d?\.?\d*)\s*\)/gi; 21212 matches = regex.exec(value); 21213 currentElement.setAttribute(style.svgAttr, format("rgb({r},{g},{b})", { 21214 r: matches[1], 21215 g: matches[2], 21216 b: matches[3] 21217 })); //should take globalAlpha here 21218 21219 var opacity = matches[4]; 21220 var globalAlpha = this.globalAlpha; 21221 21222 if (globalAlpha != null) { 21223 opacity *= globalAlpha; 21224 } 21225 21226 currentElement.setAttribute(style.svgAttr + "-opacity", opacity); 21227 } else { 21228 var attr = style.svgAttr; 21229 21230 if (keys[i] === 'globalAlpha') { 21231 attr = type + '-' + style.svgAttr; 21232 21233 if (currentElement.getAttribute(attr)) { 21234 //fill-opacity or stroke-opacity has already been set by stroke or fill. 21235 continue; 21236 } 21237 } //otherwise only update attribute if right type, and not svg default 21238 21239 21240 currentElement.setAttribute(attr, value); 21241 } 21242 } 21243 } 21244 } 21245 } 21246 21247 /** 21248 * Will return the closest group or svg node. May return the current element. 21249 * @private 21250 */ 21251 __closestGroupOrSvg(node) { 21252 node = node || this.__currentElement; 21253 21254 if (node.nodeName === "g" || node.nodeName === "svg") { 21255 return node; 21256 } else { 21257 return this.__closestGroupOrSvg(node.parentNode); 21258 } 21259 } 21260 21261 /** 21262 * Returns the serialized value of the svg so far 21263 * @param fixNamedEntities - Standalone SVG doesn't support named entities, which document.createTextNode encodes. 21264 * If true, we attempt to find all named entities and encode it as a numeric entity. 21265 * @return serialized svg 21266 */ 21267 getSerializedSvg(fixNamedEntities) { 21268 var serialized = new XMLSerializer().serializeToString(this.__root), 21269 keys, 21270 i, 21271 key, 21272 value, 21273 regexp; 21274 //IE search for a duplicate xmnls because they didn't implement setAttributeNS correctly 21275 // xmlns = /xmlns="http:\/\/www\.w3\.org\/2000\/svg".+xmlns="http:\/\/www\.w3\.org\/2000\/svg/gi; 21276 // if (xmlns.test(serialized)) { 21277 // serialized = serialized.replace('xmlns="http://www.w3.org/2000/svg','xmlns:xlink="http://www.w3.org/1999/xlink'); 21278 // } 21279 21280 if (fixNamedEntities) { 21281 keys = Object.keys(namedEntities); //loop over each named entity and replace with the proper equivalent. 21282 21283 for (i = 0; i < keys.length; i++) { 21284 key = keys[i]; 21285 value = namedEntities[key]; 21286 regexp = new RegExp(key, "gi"); 21287 21288 if (regexp.test(serialized)) { 21289 serialized = serialized.replace(regexp, value); 21290 } 21291 } 21292 } 21293 21294 return serialized; 21295 } 21296 21297 /** 21298 * Returns the root svg 21299 * @return 21300 */ 21301 getSvg() { 21302 return this.__root; 21303 } 21304 21305 /** 21306 * Will generate a group tag. 21307 */ 21308 saveWithTranslationAndClipRect(id, tx, ty, width, height, clipYOffset) { 21309 // clip rect 21310 const clip_id = `${id}_clip_rect`; 21311 21312 let clipPath = this.__createElement('clipPath', { 21313 id: clip_id 21314 }); 21315 21316 this.__defs.appendChild(clipPath); 21317 21318 const config = { 21319 x: '0', 21320 y: clipYOffset.toString(), 21321 width: width.toString(), 21322 height: height.toString() 21323 }; 21324 clipPath.appendChild(this.__createElement('rect', config)); 21325 21326 const group = this.__createElement("g"); 21327 21328 group.setAttribute('transform', format('translate({x},{y})', { 21329 x: tx, 21330 y: ty 21331 })); 21332 group.setAttribute('clip-path', format('url(#{id})', { 21333 id: clip_id 21334 })); 21335 21336 const parent = this.__closestGroupOrSvg(); 21337 21338 parent.appendChild(group); 21339 21340 this.__groupStack.push(parent); 21341 21342 this.__currentElement = group; 21343 21344 this.__stack.push(this.__getStyleState()); 21345 } 21346 21347 save() { 21348 var group = this.__createElement("g"); 21349 21350 var parent = this.__closestGroupOrSvg(); 21351 21352 this.__groupStack.push(parent); 21353 21354 parent.appendChild(group); 21355 this.__currentElement = group; 21356 21357 this.__stack.push(this.__getStyleState()); 21358 } 21359 21360 /** 21361 * Sets current element to parent, or just root if already root 21362 */
21363 restore() { 21364 this.__currentElement = this.__groupStack.pop(); 21365 this.__currentElementsToStyle = null; //Clearing canvas will make the poped group invalid, currentElement is set to the root group node. 21366 21367 if (!this.__currentElement) { 21368 this.__currentElement = this.__root.childNodes[1]; 21369 } 21370 21371 var state = this.__stack.pop(); 21372 21373 this.__applyStyleState(state); 21374 } 21375 21376 /** 21377 * Helper method to add transform 21378 * @private 21379 */ 21380 __addTransform(t) { 21381 //if the current element has siblings, add another group 21382 var parent = this.__closestGroupOrSvg(); 21383 21384 if (parent.childNodes.length > 0) { 21385 if (this.__currentElement.nodeName === "path") { 21386 if (!this.__currentElementsToStyle) this.__currentElementsToStyle = { 21387 element: parent, 21388 children: [] 21389 }; 21390 21391 this.__currentElementsToStyle.children.push(this.__currentElement); 21392 21393 this.__applyCurrentDefaultPath(); 21394 } 21395 21396 var group = this.__createElement("g"); 21397 21398 parent.appendChild(group); 21399 this.__currentElement = group; 21400 } 21401 21402 var transform = this.__currentElement.getAttribute("transform"); 21403 21404 if (transform) { 21405 transform += " "; 21406 } else { 21407 transform = ""; 21408 } 21409 21410 transform += t; 21411 21412 this.__currentElement.setAttribute("transform", transform); 21413 } 21414 21415 addTrackGroupWithTranslationAndClipRect(id, tx, ty, width, height, clipYOffset) { 21416 // clip rect 21417 const clip_id = id + '_clip_rect'; 21418 21419 let clipPath = this.__createElement('clipPath', { 21420 id: clip_id 21421 }); 21422 21423 this.__defs.appendChild(clipPath); 21424 21425 clipPath.appendChild(this.__createElement('rect', { 21426 x: '0', 21427 y: clipYOffset.toString(), 21428 width: width.toString(), 21429 height: height.toString() 21430 })); 21431 21432 let group = this.__createElement('g'); 21433 21434 this.__rootGroup.appendChild(group); 21435 21436 group.setAttribute('transform', format('translate({x},{y})', { 21437 x: tx, 21438 y: ty 21439 })); 21440 group.setAttribute('id', id + '_group'); // add clip rect 21441 21442 group.setAttribute('clip-path', format('url(#{id})', { 21443 id: clip_id 21444 })); 21445 this.__currentElement = group; 21446 } 21447 21448 /** 21449 * scales the current element 21450 */ 21451 scale(x, y) { 21452 if (y === undefined) { 21453 y = x; 21454 } 21455 21456 this.__addTransform(format("scale({x},{y})", { 21457 x: x, 21458 y: y 21459 })); 21460 } 21461 21462 /** 21463 * rotates the current element 21464 */ 21465 rotate(angle) { 21466 var degrees = angle * 180 / Math.PI; 21467 21468 this.__addTransform(format("rotate({angle},{cx},{cy})", { 21469 angle: degrees, 21470 cx: 0, 21471 cy: 0 21472 })); 21473 } 21474 21475 /** 21476 * translates the current element 21477 */ 21478 translate(x, y) { 21479 this.__addTransform(format("translate({x},{y})", { 21480 x: x, 21481 y: y 21482 })); 21483 } 21484 21485 /** 21486 * applies a transform to the current element 21487 */ 21488 transform(a, b, c, d, e, f) { 21489 this.__addTransform(format("matrix({a},{b},{c},{d},{e},{f})", { 21490 a: a, 21491 b: b, 21492 c: c, 21493 d: d, 21494 e: e, 21495 f: f 21496 })); 21497 } 21498 21499 /** 21500 * Create a new Path Element 21501 */ 21502 beginPath() { 21503 var path, parent; // Note that there is only one current default path, it is not part of the drawing state. 21504 // See also: https://html.spec.whatwg.org/multipage/scripting.html#current-default-path 21505 21506 this.__currentDefaultPath = ""; 21507 this.__currentPosition = {}; 21508 path = this.__createElement("path", {}, true); 21509 parent = this.__closestGroupOrSvg(); 21510 parent.appendChild(path); 21511 this.__currentElement = path; 21512 } 21513 21514 /** 21515 * Helper function to apply currentDefaultPath to current path element 21516 * @private 21517 */ 21518 __applyCurrentDefaultPath() { 21519 var currentElement = this.__currentElement; 21520 21521 if (currentElement.nodeName === "path") { 21522 currentElement.setAttribute("d", this.__currentDefaultPath); 21523 } else { 21524 console.error("Attempted to apply path command to node", currentElement.nodeName); 21525 } 21526 } 21527 21528 /** 21529 * Helper function to add path command 21530 * @private 21531 */ 21532 __addPathCommand(command) { 21533 this.__currentDefaultPath += " "; 21534 this.__currentDefaultPath += command; 21535 } 21536 21537 /** 21538 * Adds the move command to the current path element, 21539 * if the currentPathElement is not empty create a new path element 21540 */ 21541 moveTo(x, y) { 21542 if (this.__currentElement.nodeName !== "path") { 21543 this.beginPath(); 21544 } // creates a new subpath with the given point 21545 21546 21547 this.__currentPosition = { 21548 x: x, 21549 y: y 21550 }; 21551 21552 this.__addPathCommand(format("M {x}
21552 {y}", { 21553 x: x, 21554 y: y 21555 })); 21556 } 21557 21558 /** 21559 * Closes the current path 21560 */ 21561 closePath() { 21562 if (this.__currentDefaultPath) { 21563 this.__addPathCommand("Z"); 21564 } 21565 } 21566 21567 /** 21568 * Adds a line to command 21569 */ 21570 lineTo(x, y) { 21571 this.__currentPosition = { 21572 x: x, 21573 y: y 21574 }; 21575 21576 if (this.__currentDefaultPath && this.__currentDefaultPath.indexOf('M') > -1) { 21577 this.__addPathCommand(format("L {x} {y}", { 21578 x: x, 21579 y: y 21580 })); 21581 } else { 21582 this.__addPathCommand(format("M {x} {y}", { 21583 x: x, 21584 y: y 21585 })); 21586 } 21587 } 21588 21589 /** 21590 * Add a bezier command 21591 */ 21592 bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y) { 21593 this.__currentPosition = { 21594 x: x, 21595 y: y 21596 }; 21597 21598 this.__addPathCommand(format("C {cp1x} {cp1y} {cp2x} {cp2y} {x} {y}", { 21599 cp1x: cp1x, 21600 cp1y: cp1y, 21601 cp2x: cp2x, 21602 cp2y: cp2y, 21603 x: x, 21604 y: y 21605 })); 21606 } 21607 21608 /** 21609 * Adds a quadratic curve to command 21610 */ 21611 quadraticCurveTo(cpx, cpy, x, y) { 21612 this.__currentPosition = { 21613 x: x, 21614 y: y 21615 }; 21616 21617 this.__addPathCommand(format("Q {cpx} {cpy} {x} {y}", { 21618 cpx: cpx, 21619 cpy: cpy, 21620 x: x, 21621 y: y 21622 })); 21623 } 21624 21625 /** 21626 * Adds the arcTo to the current path 21627 * 21628 * @see http://www.w3.org/TR/2015/WD-2dcontext-20150514/#dom-context-2d-arcto 21629 */ 21630 arcTo(x1, y1, x2, y2, radius) { 21631 // Let the point (x0, y0) be the last point in the subpath. 21632 var x0 = this.__currentPosition && this.__currentPosition.x; 21633 var y0 = this.__currentPosition && this.__currentPosition.y; // First ensure there is a subpath for (x1, y1). 21634 21635 if (typeof x0 == "undefined" || typeof y0 == "undefined") { 21636 return; 21637 } // Negative values for radius must cause the implementation to throw an IndexSizeError exception. 21638 21639 21640 if (radius < 0) { 21641 throw new Error("IndexSizeError: The radius provided (" + radius + ") is negative."); 21642 } // If the point (x0, y0) is equal to the point (x1, y1), 21643 // or if the point (x1, y1) is equal to the point (x2, y2), 21644 // or if the radius radius is zero, 21645 // then the method must add the point (x1, y1) to the subpath, 21646 // and connect that point to the previous point (x0, y0) by a straight line. 21647 21648 21649 if (x0 === x1 && y0 === y1 || x1 === x2 && y1 === y2 || radius === 0) { 21650 this.lineTo(x1, y1); 21651 return; 21652 } // Otherwise, if the points (x0, y0), (x1, y1), and (x2, y2) all lie on a single straight line, 21653 // then the method must add the point (x1, y1) to the subpath, 21654 // and connect that point to the previous point (x0, y0) by a straight line. 21655 21656 21657 var unit_vec_p1_p0 = normalize$1([x0 - x1, y0 - y1]); 21658 var unit_vec_p1_p2 = normalize$1([x2 - x1, y2 - y1]); 21659 21660 if (unit_vec_p1_p0[0] * unit_vec_p1_p2[1] === unit_vec_p1_p0[1] * unit_vec_p1_p2[0]) { 21661 this.lineTo(x1, y1); 21662 return; 21663 } // Otherwise, let The Arc be the shortest arc given by circumference of the circle that has radius radius, 21664 // and that has one point tangent to the half-infinite line that crosses the point (x0, y0) and ends at the point (x1, y1), 21665 // and that has a different point tangent to the half-infinite line that ends at the point (x1, y1), and crosses the point (x2, y2). 21666 // The points at which this circle touches these two lines are called the start and end tangent points respectively. 21667 // note that both vectors are unit vectors, so the length is 1 21668 21669 21670 var cos = unit_vec_p1_p0[0] * unit_vec_p1_p2[0] + unit_vec_p1_p0[1] * unit_vec_p1_p2[1]; 21671 var theta = Math.acos(Math.abs(cos)); // Calculate origin 21672 21673 var unit_vec_p1_origin = normalize$1([unit_vec_p1_p0[0] + unit_vec_p1_p2[0], unit_vec_p1_p0[1] + unit_vec_p1_p2[1]]);
21674 var len_p1_origin = radius / Math.sin(theta / 2); 21675 var x = x1 + len_p1_origin * unit_vec_p1_origin[0]; 21676 var y = y1 + len_p1_origin * unit_vec_p1_origin[1]; // Calculate start angle and end angle 21677 // rotate 90deg clockwise (note that y axis points to its down) 21678 21679 var unit_vec_origin_start_tangent = [-unit_vec_p1_p0[1], unit_vec_p1_p0[0]]; // rotate 90deg counter clockwise (note that y axis points to its down) 21680 21681 var unit_vec_origin_end_tangent = [unit_vec_p1_p2[1], -unit_vec_p1_p2[0]]; 21682 21683 var getAngle = function (vector) { 21684 // get angle (clockwise) between vector and (1, 0) 21685 var x = vector[0]; 21686 var y = vector[1]; 21687 21688 if (y >= 0) { 21689 // note that y axis points to its down 21690 return Math.acos(x); 21691 } else { 21692 return -Math.acos(x); 21693 } 21694 }; 21695 21696 var startAngle = getAngle(unit_vec_origin_start_tangent); 21697 var endAngle = getAngle(unit_vec_origin_end_tangent); // Connect the point (x0, y0) to the start tangent point by a straight line 21698 21699 this.lineTo(x + unit_vec_origin_start_tangent[0] * radius, y + unit_vec_origin_start_tangent[1] * radius); // Connect the start tangent point to the end tangent point by arc 21700 // and adding the end tangent point to the subpath. 21701 21702 this.arc(x, y, radius, startAngle, endAngle); 21703 } 21704 21705 /** 21706 * Sets the stroke property on the current element 21707 */ 21708 stroke() { 21709 if (this.__currentElement.nodeName === "path") { 21710 this.__currentElement.setAttribute("paint-order", "fill stroke markers"); 21711 } 21712 21713 this.__applyCurrentDefaultPath(); 21714 21715 this.__applyStyleToCurrentElement("stroke"); 21716 } 21717 21718 /** 21719 * Sets fill properties on the current element 21720 */ 21721 fill() { 21722 if (this.__currentElement.nodeName === "path") { 21723 this.__currentElement.setAttribute("paint-order", "stroke fill markers"); 21724 } 21725 21726 this.__applyCurrentDefaultPath(); 21727 21728 this.__applyStyleToCurrentElement("fill"); 21729 } 21730 21731 /** 21732 * Adds a rectangle to the path. 21733 */ 21734 rect(x, y, width, height) { 21735 if (this.__currentElement.nodeName !== "path") { 21736 this.beginPath(); 21737 } 21738 21739 this.moveTo(x, y); 21740 this.lineTo(x + width, y); 21741 this.lineTo(x + width, y + height); 21742 this.lineTo(x, y + height); 21743 this.lineTo(x, y); 21744 this.closePath(); 21745 } 21746 21747 /** 21748 * adds a rectangle element 21749 */ 21750 fillRect(x, y, width, height) { 21751 if (height < 0) { 21752 y += height; 21753 height = -height; 21754 } 21755 21756 if (width < 0) { 21757 x += width; 21758 width = -width; 21759 } // See if rect intersects current viewbox 21760 21761 21762 var r2 = { 21763 x: x, 21764 y: y, 21765 width: width, 21766 height: height 21767 }; 21768 21769 if (this.viewbox) { 21770 if (!intersectRect(this.viewbox, r2)) { 21771 return; 21772 } 21773 } 21774 21775 var rect, parent; 21776 rect = this.__createElement("rect", r2, true); 21777 parent = this.__closestGroupOrSvg(); 21778 parent.appendChild(rect); 21779 this.__currentElement = rect; 21780 21781 this.__applyStyleToCurrentElement("fill"); 21782 } 21783 21784 /** 21785 * Draws a rectangle with no fill 21786 * @param x 21787 * @param y 21788 * @param width 21789 * @param height 21790 */ 21791 strokeRect(x, y, width, height) { 21792 var rect, parent; 21793 rect = this.__createElement("rect", { 21794 x: x, 21795 y: y, 21796 width: width, 21797 height: height 21798 }, true); 21799 parent = this.__closestGroupOrSvg(); 21800 parent.appendChild(rect); 21801 this.__currentElement = rect; 21802 21803 this.__applyStyleToCurrentElement("stroke"); 21804 } 21805 21806 // stroke ellipse 21807 strokeEllipse(cx, cy, rx, ry, rotation, startAngle, endAngle, isCCW) { 21808 this.__ellipse(cx, cy, rx, ry, rotation, startAngle, endAngle, isCCW, 'stroke'); 21809 } // fill ellipse 21810 21811 21812 fillEllipse(cx, cy, rx, ry, rotation, startAngle, endAngle, isCCW) { 21813 this.__ellipse(cx, cy, rx, ry, rotation, startAngle, endAngle, isCCW, 'fill'); 21814 } // ellipse helper 21815 21816 21817 __ellipse(cx, cy, rx, ry, rotation, startAngle, endAngle, isCCW, style) { 21818 const config = { 21819 cx, 21820 cy, 21821 rx, 21822 ry 21823 }; 21824
21825 const element = this.__createElement('ellipse', config, true); 21826 21827 const parent = this.__closestGroupOrSvg(); 21828 21829 parent.appendChild(element); 21830 this.__currentElement = element; 21831 21832 this.__applyStyleToCurrentElement(style); 21833 } 21834 /** 21835 * Clear entire canvas: 21836 * 1. save current transforms 21837 * 2. remove all the childNodes of the root g element 21838 */ 21839 21840 21841 __clearCanvas() { 21842 var current = this.__closestGroupOrSvg(), 21843 transform = current.getAttribute("transform"); 21844 21845 var rootGroup = this.__root.childNodes[1]; 21846 var childNodes = rootGroup.childNodes; 21847 21848 for (var i = childNodes.length - 1; i >= 0; i--) { 21849 if (childNodes[i]) { 21850 rootGroup.removeChild(childNodes[i]); 21851 } 21852 } 21853 21854 this.__currentElement = rootGroup; //reset __groupStack as all the child group nodes are all removed. 21855 21856 this.__groupStack = []; 21857 21858 if (transform) { 21859 this.__addTransform(transform); 21860 } 21861 } 21862 21863 /** 21864 * "Clears" a canvas by just drawing a white rectangle in the current group. 21865 */ 21866 clearRect(x, y, width, height) { 21867 //clear entire canvas 21868 if (x === 0 && y === 0 && width === this.width && height === this.height) { 21869 this.__clearCanvas(); 21870 21871 return; 21872 } 21873 21874 var rect, 21875 parent = this.__closestGroupOrSvg(); 21876 21877 rect = this.__createElement("rect", { 21878 x: x, 21879 y: y, 21880 width: width, 21881 height: height, 21882 fill: "#FFFFFF" 21883 }, true); 21884 parent.appendChild(rect); 21885 } 21886 21887 /** 21888 * Adds a linear gradient to a defs tag. 21889 * Returns a canvas gradient object that has a reference to it's parent def 21890 */ 21891 createLinearGradient(x1, y1, x2, y2) { 21892 var grad = this.__createElement("linearGradient", { 21893 id: randomString(this.__ids), 21894 x1: x1 + "px", 21895 x2: x2 + "px", 21896 y1: y1 + "px", 21897 y2: y2 + "px", 21898 "gradientUnits": "userSpaceOnUse" 21899 }, false); 21900 21901 this.__defs.appendChild(grad); 21902 21903 return new CanvasGradient(grad, this); 21904 } 21905 21906 /** 21907 * Adds a radial gradient to a defs tag. 21908 * Returns a canvas gradient object that has a reference to it's parent def 21909 */ 21910 createRadialGradient(x0, y0, r0, x1, y1, r1) { 21911 var grad = this.__createElement("radialGradient", { 21912 id: randomString(this.__ids), 21913 cx: x1 + "px", 21914 cy: y1 + "px", 21915 r: r1 + "px", 21916 fx: x0 + "px", 21917 fy: y0 + "px", 21918 "gradientUnits": "userSpaceOnUse" 21919 }, false); 21920 21921 this.__defs.appendChild(grad); 21922 21923 return new CanvasGradient(grad, this); 21924 } 21925 21926 /** 21927 * Parses the font string and returns svg mapping 21928 * @private 21929 */ 21930 __parseFont() {
21931 var regex = /^\s*(?=(?:(?:[-a-z]+\s*){0,2}(italic|oblique))?)(?=(?:(?:[-a-z]+\s*){0,2}(small-caps))?)(?=(?:(?:[-a-z]+\s*){0,2}(bold(?:er)?|lighter|[1-9]00))?)(?:(?:normal|\1|\2|\3)\s*){0,3}((?:xx?-)?(?:small|large)|medium|smaller|larger|[.\d]+(?:\%|in|[cem]m|ex|p[ctx]))(?:\s*\/\s*(normal|[.\d]+(?:\%|in|[cem]m|ex|p[ctx])))?\s*([-,\'\"\sa-z0-9]+?)\s*$/i; 21932 var fontPart = regex.exec(this.font); 21933 var data = { 21934 style: fontPart[1] || 'normal', 21935 size: fontPart[4] || '10px', 21936 family: fontPart[6] || 'sans-serif', 21937 weight: fontPart[3] || 'normal', 21938 decoration: fontPart[2] || 'normal', 21939 href: null 21940 }; //canvas doesn't support underline natively, but we can pass this attribute 21941 21942 if (this.__fontUnderline === "underline") { 21943 data.decoration = "underline"; 21944 } //canvas also doesn't support linking, but we can pass this as well 21945 21946 21947 if (this.__fontHref) { 21948 data.href = this.__fontHref; 21949 } 21950 21951 return data; 21952 } 21953 21954 /** 21955 * Helper to link text fragments 21956 * @param font 21957 * @param element 21958 * @return {*} 21959 * @private 21960 */ 21961 __wrapTextLink(font, element) { 21962 if (font.href) { 21963 var a = this.__createElement("a"); 21964 21965 a.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href", font.href); 21966 a.appendChild(element); 21967 return a; 21968 } 21969 21970 return element; 21971 } 21972 21973 /** 21974 * Fills or strokes text 21975 * @param text 21976 * @param x 21977 * @param y 21978 * @param action - stroke or fill 21979 * @private 21980 */ 21981 __applyText(text, x, y, action) { 21982 var font = this.__parseFont(), 21983 parent = this.__closestGroupOrSvg(), 21984 textElement = this.__createElement("text", { 21985 "font-family": font.family, 21986 "font-size": font.size, 21987 "font-style": font.style, 21988 "font-weight": font.weight, 21989 "text-decoration": font.decoration, 21990 "x": x, 21991 "y": y, 21992 "text-anchor": getTextAnchor(this.textAlign), 21993 "dominant-baseline": getDominantBaseline(this.textBaseline) 21994 }, true); 21995 21996 textElement.appendChild(this.__document.createTextNode(text)); 21997 this.__currentElement = textElement; 21998 21999 this.__applyStyleToCurrentElement(action); 22000 22001 parent.appendChild(this.__wrapTextLink(font, textElement)); 22002 } 22003 22004 /** 22005 * Creates a text element 22006 * @param text 22007 * @param x 22008 * @param y 22009 */ 22010 fillText(text, x, y) { 22011 this.__applyText(text, x, y, "fill"); 22012 } 22013 22014 /** 22015 * Strokes text 22016 * @param text 22017 * @param x 22018 * @param y 22019 */ 22020 strokeText(text, x, y) { 22021 this.__applyText(text, x, y, "stroke"); 22022 } 22023 22024 /** 22025 * No need to implement this for svg. 22026 * @param text 22027 * @return {TextMetrics} 22028 */ 22029 measureText(text) { 22030 this.__ctx.font = this.font; 22031 return this.__ctx.measureText(text); 22032 } 22033 22034 /** 22035 * Arc command! 22036 */ 22037 arc(x, y, radius, startAngle, endAngle, counterClockwise) { 22038 // in canvas no circle is drawn if no angle is provided. 22039 if (startAngle === endAngle) { 22040 return; 22041 } 22042 22043 startAngle = startAngle % (2 * Math.PI); 22044 endAngle = endAngle % (2 * Math.PI); 22045 22046 if (startAngle === endAngle) { 22047 //circle time! subtract some of the angle so svg is happy (svg elliptical arc can't draw a full circle) 22048 endAngle = (endAngle + 2 * Math.PI - 0.001 * (counterClockwise ? -1 : 1)) % (2 * Math.PI); 22049 } 22050 22051 var endX = x + radius * Math.cos(endAngle), 22052 endY = y + radius * Math.sin(endAngle), 22053 startX = x + radius * Math.cos(startAngle), 22054 startY = y + radius * Math.sin(startAngle), 22055 sweepFlag = counterClockwise ? 0 : 1, 22056 largeArcFlag = 0, 22057 diff = endAngle - startAngle; // https://github.com/gliffy/canvas2svg/issues/4 22058 22059 if (diff < 0) { 22060 diff += 2 * Math.PI; 22061 } 22062 22063 if (counterClockwise) { 22064 largeArcFlag = diff > Math.PI ? 0 : 1; 22065 } else { 22066 largeArcFlag = diff > Math.PI ? 1 : 0; 22067 } 22068 22069 this.lineTo(startX, startY); 22070 22071 this.__addPathCommand(format("A {rx} {ry} {xAxisRotation} {largeArcFlag} {sweepFlag} {endX} {endY}", { 22072 rx: radius, 22073 ry: radius, 22074 xAxisRotation: 0, 22075 largeArcFlag: largeArcFlag, 22076 sweepFlag: sweepFlag, 22077 endX: endX, 22078 endY: endY 22079 })); 22080 22081 this.__currentPosition = { 22082 x: endX, 22083 y: endY 22084 }; 22085 } 22086 22087 /** 22088 * The ellipse() method creates an elliptical arc centered at (x, y) with the radii radiusX and radiusY. The path 22089 * starts at startAngle and ends at endAngle, and travels in the direction given by counterclockwise (defaulting to clockwise). 22090 */ 22091 // ellipse (x, y, radiusX, radiusY, rotation, startAngle, endAngle, counterclockwise) { 22092 // // TODO -- implement 22093 // } 22094 22095 /** 22096 * Generates a ClipPath from the clip command. 22097 */ 22098 clip() { 22099 var group = this.__closestGroupOrSvg(), 22100 clipPath = this.__createElement("clipPath"), 22101 id = randomString(this.__ids), 22102 newGroup = this.__createElement("g"); 22103 22104 this.__applyCurrentDefaultPath(); 22105 22106 group.removeChild(this.__currentElement); 22107 clipPath.setAttribute("id", id); 22108 clipPath.appendChild(this.__currentElement); 22109 22110 this.__defs.appendChild(clipPath); //set the clip path to this group 22111 22112 22113 group.setAttribute("clip-path", format("url(#{id})", { 22114 id: id 22115 })); //clip paths can be scaled and transformed, we need to add another wrapper group to avoid later transformations 22116 // to this path 22117 22118 group.appendChild(newGroup); 22119 this.__currentElement = newGroup; 22120 } 22121 22122 /** 22123 * Draws a canvas, image or mock context to this canvas. 22124 * Note that all svg dom manipulation uses node.childNodes rather than node.children for IE supp
22124ort. 22125 * http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-drawimage 22126 */ 22127 drawImage() { 22128 //convert arguments to a real array 22129 var args = Array.prototype.slice.call(arguments), 22130 image = args[0], 22131 dx, 22132 dy, 22133 dw, 22134 dh, 22135 sx = 0, 22136 sy = 0, 22137 sw, 22138 sh, 22139 parent, 22140 svg, 22141 defs, 22142 group, 22143 svgImage, 22144 canvas, 22145 context, 22146 id; 22147 22148 if (args.length === 3) { 22149 dx = args[1]; 22150 dy = args[2]; 22151 sw = image.width; 22152 sh = image.height; 22153 dw = sw; 22154 dh = sh; 22155 } else if (args.length === 5) { 22156 dx = args[1]; 22157 dy = args[2]; 22158 dw = args[3]; 22159 dh = args[4]; 22160 sw = image.width; 22161 sh = image.height; 22162 } else if (args.length === 9) { 22163 sx = args[1]; 22164 sy = args[2]; 22165 sw = args[3]; 22166 sh = args[4]; 22167 dx = args[5]; 22168 dy = args[6]; 22169 dw = args[7]; 22170 dh = args[8]; 22171 } else { 22172 throw new Error("Invalid number of arguments passed to drawImage: " + arguments.length); 22173 } 22174 22175 parent = this.__closestGroupOrSvg(); 22176 var translateDirective = "translate(" + dx + ", " + dy + ")"; 22177 22178 if (image instanceof ctx) { 22179 //canvas2svg mock canvas context. In the future we may want to clone nodes instead. 22180 //also I'm currently ignoring dw, dh, sw, sh, sx, sy for a mock context. 22181 svg = image.getSvg().cloneNode(true); 22182 22183 if (svg.childNodes && svg.childNodes.length > 1) { 22184 defs = svg.childNodes[0]; 22185 22186 while (defs.childNodes.length) { 22187 id = defs.childNodes[0].getAttribute("id"); 22188 this.__ids[id] = id; 22189 22190 this.__defs.appendChild(defs.childNodes[0]); 22191 } 22192 22193 group = svg.childNodes[1]; 22194 22195 if (group) { 22196 //save original transform 22197 var originTransform = group.getAttribute("transform"); 22198 var transformDirective; 22199 22200 if (originTransform) { 22201 transformDirective = originTransform + " " + translateDirective; 22202 } else { 22203 transformDirective = translateDirective; 22204 } 22205 22206 group.setAttribute("transform", transformDirective); 22207 parent.appendChild(group); 22208 } 22209 } 22210 } else if (image.nodeName === "CANVAS" || image.nodeName === "IMG") { 22211 //canvas or image 22212 svgImage = this.__createElement("image"); 22213 svgImage.setAttribute("width", dw); 22214 svgImage.setAttribute("height", dh); 22215 svgImage.setAttribute("preserveAspectRatio", "none"); 22216 22217 if (sx || sy || sw !== image.width || sh !== image.height) { 22218 //crop the image using a temporary canvas 22219 canvas = this.__document.createElement("canvas"); 22220 canvas.width = dw; 22221 canvas.height = dh; 22222 context = canvas.getContext("2d"); 22223 context.drawImage(image, sx, sy, sw, sh, 0, 0, dw, dh); 22224 image = canvas; 22225 } 22226 22227 svgImage.setAttribute("transform", translateDirective); 22228 svgImage.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href", image.nodeName === "CANVAS" ? image.toDataURL() : image.getAttribute("src")); 22229 parent.appendChild(svgImage); 22230 } 22231 } 22232 22233 /** 22234 * Generates a pattern tag 22235 */ 22236 createPattern(image, repetition) { 22237 let pattern = this.__document.__createElement("pattern"); 22238 22239 let id = randomString(this.__ids); 22240 let img; 22241 pattern.setAttribute("id", id); 22242 pattern.setAttribute("width", image.width); 22243 pattern.setAttribute("height", image.height); 22244 22245 if (image.nodeName === "CANVAS" || image.nodeName === "IMG") { 22246 img = this.__createElement("image"); 22247 img.setAttribute("width", image.width); 22248 img.setAttribute("height", image.height); 22249 img.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href", image.nodeName === "CANVAS" ? image.toDataURL() : image.getAttribute("src")); 22250 pattern.appendChild(img); 22251 22252 this.__defs.appendChild(pattern); 22253 } else if (image instanceof ctx) { 22254 pattern.appendChild(image.__root.childNodes[1]); 22255 22256 this.__defs.appendChild(pattern); 22257 } 22258 22259 return new CanvasPattern(pattern, this); 22260 } 22261 22262 setLineDash(dashArray) { 22263 if (dashArray && dashArray.length > 0) { 22264 this.lineDash = dashArray.join(","); 22265 } else { 22266 this.lineDash = null; 22267 } 22268 } 22269 22270 /** 22271 * Not yet implemented 22272 */ 22273 drawFocusRing() {} 22274 22275 createImageData() {} 22276 22277 getImageData() {} 22278 22279 putImageData() {} 22280 22281 globalCompositeOperation() {} 22282 22283 setTransform() {} 22284 22285 } 22286 22287 const Chromosome = function (name, order, bpStart, bpLength, rangeLocus) { 22288 this.name = name; 22289 this.order = order; 22290 this.bpStart = bpStart; 22291 this.bpLength = bpLength; 22292 this.rangeLocus = rangeLocus; 22293 }; 22294 22295 /* 22296 * The MIT License (MIT) 22297 * 22298 * Copyright (c) 2014 Broad Institute 22299 * 22300 * Permission is hereby granted, free of charge, to any person obtaining a copy 22301 * of this software and associated documentation files (the "Software"), to deal 22302 * in the Software without restriction, including without limitation the rights 22303 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 22304 * copies of the Software, and to permit persons to whom the Software is 22305 * furnished to do so, subject to the following conditions: 22306 * 22307 * The above copyright notice and this permission notice shall be included in 22308 * all copies or substantial portions of the Software. 22309 * 22310 * 22311 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22312 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22313 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22314 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22315 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22316 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22317 * THE SOFTWARE. 22318 */ 22319 const splitLines$4 = splitLines$5; 22320 const reservedProperties$1 = new Set(['fastaURL', 'indexURL', 'cytobandURL', 'indexed']); 22321 22322 class NonIndexedFasta { 22323 constructor(reference) { 22324 this.fastaURL = reference.fastaURL; 22325 this.withCredentials = reference.withCredentials; 22326 this.chromosomeNames = []; 22327 this.chromosomes = {}; 22328 this.sequences = new Map(); 22329 this.offsets = {}; // Build a track-like config object from the referenceObject 22330 22331 const config = {}; 22332 22333 for (let key in reference) { 22334 if (reference.hasOwnProperty(key) && !reservedProperties$1.has(key)) { 22335 config[key] = reference[key]; 22336 } 22337 } 22338 22339 this.config = config; 22340 } 22341
22342 async init() { 22343 return this.loadAll(); 22344 } 22345 22346 async getSequence(chr, start, end) { 22347 if (this.offsets[chr]) { 22348 start -= this.offsets[chr]; 22349 end -= this.offsets[chr]; 22350 } 22351 22352 let prefix = ""; 22353 22354 if (start < 0) { 22355 for (let i = start; i < Math.min(end, 0); i++) { 22356 prefix += "*"; 22357 } 22358 } 22359 22360 if (end <= 0) { 22361 return Promise.resolve(prefix); 22362 } 22363 22364 const seq = this.sequences.get(chr); 22365 const seqEnd = Math.min(end, seq.length); 22366 return prefix + seq.substring(start, seqEnd); 22367 } 22368 22369 async loadAll() { 22370 let data; 22371 22372 if (isDataURL(this.fastaURL)) { 22373 let bytes = decodeDataURI$1(this.fastaURL); 22374 data = ""; 22375 22376 for (let b of bytes) { 22377 data += String.fromCharCode(b); 22378 } 22379 } else { 22380 data = await igvxhr.load(this.fastaURL, buildOptions(this.config)); 22381 } 22382 22383 const lines = splitLines$4(data); 22384 const len = lines.length; 22385 let lineNo = 0; 22386 let currentSeq; 22387 let currentRangeLocus; 22388 let currentOffset = 0; 22389 let order = 0; 22390 let nextLine; 22391 let currentChr; 22392 22393 while (lineNo < len) { 22394 nextLine = lines[lineNo++].trim(); 22395 22396 if (nextLine.startsWith("#") || nextLine.length === 0) ; else if (nextLine.startsWith(">")) { 22397 // Start the next sequence 22398 if (currentSeq) { 22399 this.chromosomeNames.push(currentChr); 22400 this.sequences.set(currentChr, currentSeq); 22401 this.chromosomes[currentChr] = new Chromosome(currentChr, order++, currentOffset, currentOffset + currentSeq.length, currentRangeLocus); 22402 } 22403 22404 const parts = nextLine.substr(1).split(/\s+/); // Check for samtools style locus string. This is not perfect, and could fail on weird sequence names 22405 22406 const nameParts = parts[0].split(':'); 22407 currentChr = nameParts[0]; 22408 currentSeq = ""; 22409 currentOffset = 0; 22410 currentRangeLocus = undefined; 22411 22412 if (nameParts.length > 1 && nameParts[1].indexOf('-') > 0) { 22413 const locusParts = nameParts[1].split('-'); 22414 22415 if (locusParts.length === 2 && /^[0-9]+$/.test(locusParts[0]) && /^[0-9]+$/.test(locusParts[1])) ; 22416 22417 const from = Number.parseInt(locusParts[0]); 22418 const to = Number.parseInt(locusParts[1]); 22419 22420 if (to > from) { 22421 currentOffset = from - 1; 22422 this.offsets[currentChr] = currentOffset; 22423 currentRangeLocus = nameParts[1]; 22424 } 22425 } 22426 } else { 22427 currentSeq += nextLine; 22428 } 22429 } // add last seq 22430 22431 22432 if (currentSeq) { 22433 this.chromosomeNames.push(currentChr); 22434 this.sequences.set(currentChr, currentSeq); 22435 this.chromosomes[currentChr] = new Chromosome(currentChr, order++, currentOffset, currentOffset + currentSeq.length, currentRangeLocus); 22436 } 22437 } 22438 22439 } 22440 22441 const GenomicInterval = function (chr, start, end, features) { 22442 this.chr = chr; 22443 this.start = start; 22444 this.end = end; 22445 this.features = features; 22446 }; 22447 22448 GenomicInterval.prototype.contains = function (chr, start, end) { 22449 return this.chr === chr && this.start <= start && this.end >= end; 22450 }; 22451 22452 GenomicInterval.prototype.containsRange = function (range) { 22453 return this.chr === range.chr && this.start <= range.start && this.end >= range.end; 22454 }; 22455 22456 /* 22457 * The MIT License (MIT) 22458 * 22459 * Copyright (c) 2014 Broad Institute 22460 * 22461 * Permission is hereby granted, free of charge, to any person obtaining a copy 22462 * of this software and associated documentation files (the "Software"), to deal 22463 * in the Software without restriction, including without limitation the rights 22464 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 22465 * copies of the Software, and to permit persons to whom the Software is 22466 * furnished to do so, subject to the following conditions: 22467 * 22468 * The above copyright notice and this permission notice shall be included in 22469 * all copies or substantial portions of the Software. 22470 * 22471 * 22472 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22473 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22474 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22475 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22476 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22477 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22478 * THE SOFTWARE. 22479 */ 22480 const splitLines$3 = splitLines$5; 22481 const reservedProperties = new Set(['fastaURL', 'indexURL', 'cytobandURL', 'indexed']); 22482 22483 class FastaSequence { 22484 constructor(reference) { 22485 this.file = reference.fastaURL; 22486 this.indexFile = reference.indexURL || reference.indexFile || this.file + ".fai"; 22487 this.withCredentials = reference.withCredentials; 22488 this.chromosomeNames = []; 22489 this.chromosomes = {}; 22490 this.sequences = {}; 22491 this.offsets = {}; // Build a track-like config object from the referenceObject 22492 22493 const config = {}; 22494 22495 for (let key in reference) { 22496 if (reference.hasOwnProperty(key) && !reservedProperties.has(key)) { 22497 config[key] = reference[key]; 22498 } 22499 } 22500 22501 this.config = config; 22502 } 22503
22504 async init() { 22505 return this.getIndex(); 22506 } 22507 22508 async getSequence(chr, start, end) { 22509 if (!(this.interval && this.interval.contains(chr, start, end))) { 22510 // Expand query, to minimum of 50kb 22511 let qstart = start; 22512 let qend = end; 22513 22514 if (end - start < 50000) { 22515 const w = end - start; 22516 const center = Math.round(start + w / 2); 22517 qstart = Math.max(0, center - 25000); 22518 qend = center + 25000; 22519 } 22520 22521 const seqBytes = await this.readSequence(chr, qstart, qend); 22522 this.interval = new GenomicInterval(chr, qstart, qend, seqBytes); 22523 } 22524 22525 const offset = start - this.interval.start; 22526 const n = end - start; 22527 const seq = this.interval.features ? this.interval.features.substr(offset, n) : null; 22528 return seq; 22529 } 22530 22531 async getIndex() { 22532 if (this.index) { 22533 return this.index; 22534 } else { 22535 const data = await igvxhr.load(this.indexFile, buildOptions(this.config)); 22536 const lines = splitLines$3(data); 22537 const len = lines.length; 22538 let lineNo = 0; 22539 let order = 0; 22540 this.index = {}; 22541 22542 while (lineNo < len) { 22543 const tokens = lines[lineNo++].split("\t"); 22544 const nTokens = tokens.length; 22545 22546 if (nTokens === 5) { 22547 // Parse the index line. 22548 const chr = tokens[0]; 22549 const size = parseInt(tokens[1]); 22550 const position = parseInt(tokens[2]); 22551 const basesPerLine = parseInt(tokens[3]); 22552 const bytesPerLine = parseInt(tokens[4]); 22553 const indexEntry = { 22554 size: size, 22555 position: position, 22556 basesPerLine: basesPerLine, 22557 bytesPerLine: bytesPerLine 22558 }; 22559 this.chromosomeNames.push(chr); 22560 this.index[chr] = indexEntry; 22561 this.chromosomes[chr] = new Chromosome(chr, order++, 0, size); 22562 } 22563 } 22564 22565 return this.index; 22566 } 22567 } 22568 22569 async readSequence(chr, qstart, qend) { 22570 // let offset; 22571 // let start; 22572 // let end; 22573 // let basesPerLine; 22574 // let nEndBytes; 22575 await this.getIndex(); 22576 const idxEntry = this.index[chr]; 22577 22578 if (!idxEntry) { 22579 console.log("No index entry for chr: " + chr); // Tag interval with null so we don't try again 22580 22581 this.interval = new GenomicInterval(chr, qstart, qend, null); 22582 return null; 22583 } else { 22584 const start = Math.max(0, qstart); // qstart should never be < 0 22585 22586 const end = Math.min(idxEntry.size, qend); 22587 const bytesPerLine = idxEntry.bytesPerLine; 22588 const basesPerLine = idxEntry.basesPerLine; 22589 const position = idxEntry.position; 22590 const nEndBytes = bytesPerLine - basesPerLine; 22591 const startLine = Math.floor(start / basesPerLine); 22592 const endLine = Math.floor(end / basesPerLine); 22593 const base0 = startLine * basesPerLine; // Base at beginning of start line 22594 22595 const offset = start - base0; 22596 const startByte = position + startLine * bytesPerLine + offset; 22597 const base1 = endLine * basesPerLine; 22598 const offset1 = end - base1; 22599 const endByte = position + endLine * bytesPerLine + offset1 - 1; 22600 const byteCount = endByte - startByte + 1; 22601 let allBytes; 22602 22603 if (byteCount <= 0) { 22604 console.error("No sequence for " + chr + ":" + qstart + "-" + qend); 22605 } else { 22606 allBytes = await igvxhr.load(this.file, buildOptions(this.config, { 22607 range: { 22608 start: startByte, 22609 size: byteCount 22610 } 22611 })); 22612 } 22613 22614 if (!allBytes) { 22615 return null; 22616 } else { 22617 let nBases, 22618 seqBytes = "", 22619 srcPos = 0, 22620 allBytesLength = allBytes.length; 22621 22622 if (offset > 0) { 22623 nBases = Math.min(end - start, basesPerLine - offset); 22624 seqBytes += allBytes.substr(srcPos, nBases);
22625 srcPos += nBases + nEndBytes; 22626 } 22627 22628 while (srcPos < allBytesLength) { 22629 nBases = Math.min(basesPerLine, allBytesLength - srcPos); 22630 seqBytes += allBytes.substr(srcPos, nBases); 22631 srcPos += nBases + nEndBytes; 22632 } 22633 22634 return seqBytes; 22635 } 22636 } 22637 } 22638 22639 } 22640 22641 /* 22642 * The MIT License (MIT) 22643 * 22644 * Copyright (c) 2014 Broad Institute 22645 * 22646 * Permission is hereby granted, free of charge, to any person obtaining a copy 22647 * of this software and associated documentation files (the "Software"), to deal 22648 * in the Software without restriction, including without limitation the rights 22649 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 22650 * copies of the Software, and to permit persons to whom the Software is 22651 * furnished to do so, subject to the following conditions: 22652 * 22653 * The above copyright notice and this permission notice shall be included in 22654 * all copies or substantial portions of the Software. 22655 * 22656 * 22657 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22658 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22659 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22660 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22661 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22662 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22663 * THE SOFTWARE. 22664 */ 22665 const splitLines$2 = splitLines$5; 22666 22667 class ChromSizes { 22668 constructor(url) { 22669 this.url = url; 22670 this.chromosomeNames = []; 22671 this.chromosomes = {}; 22672 } 22673 22674 async init() { 22675 return this.loadAll(); 22676 } 22677 22678 async getSequence(chr, start, end) { 22679 return undefined; // TODO -- return array of "N"s? 22680 } 22681 22682 async loadAll() { 22683 let data; 22684 22685 if (isDataURL(this.url)) { 22686 let bytes = decodeDataURI$1(this.fastaURL); 22687 data = ""; 22688 22689 for (let b of bytes) { 22690 data += String.fromCharCode(b); 22691 } 22692 } else { 22693 data = await igvxhr.load(this.url, {}); 22694 } 22695 22696 this.chromosomeNames = []; 22697 this.chromosomes = {}; 22698 const lines = splitLines$2(data); 22699 let order = 0; 22700 22701 for (let nextLine of lines) { 22702 const tokens = nextLine.split('\t'); 22703 this.chromosomeNames.push(tokens[0]); 22704 const chrLength = Number.parseInt(tokens[1]); 22705 const chromosome = new Chromosome(tokens[0], order++, 0, chrLength); 22706 this.chromosomes[tokens[0]] = chromosome; 22707 } 22708 } 22709 22710 } 22711 22712 async function loadFasta(reference) { 22713 let fasta; 22714 22715 if ("chromsizes" === reference.format) { 22716 fasta = new ChromSizes(reference.fastaURL); 22717 } else if (isDataURL(reference.fastaURL) || reference.indexed === false) { 22718 fasta = new NonIndexedFasta(reference); 22719 } else { 22720 fasta = new FastaSequence(reference); 22721 } 22722 22723 await fasta.init(); 22724 return fasta; 22725 } 22726 22727 const Cytoband = function (start, end, name, typestain) { 22728 this.start = start; 22729 this.end = end; 22730 this.name = name; 22731 this.stain = 0; // Set the type, either p, n, or c 22732 22733 if (typestain === 'acen') { 22734 this.type = 'c'; 22735 } else { 22736 this.type = typestain.charAt(1); 22737 22738 if (this.type === 'p') { 22739 this.stain = parseInt(typestain.substring(4)); 22740 } 22741 } 22742 }; 22743 22744 const _version = "2.10.5"; 22745 22746 function version$1() { 22747 return _version; 22748 } 22749 22750 /* 22751 * The MIT License (MIT) 22752 * 22753 * Copyright (c) 2014 Broad Institute 22754 * 22755 * Permission is hereby granted, free of charge, to any person obtaining a copy 22756 * of this software and associated documentation files (the "Software"), to deal 22757 * in the Software without restriction, including without limitation the rights 22758 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 22759 * copies of the Software, and to permit persons to whom the Software is 22760 * furnished to do so, subject to the following conditions: 22761 * 22762 * The above copyright notice and this permission notice shall be included in 22763 * all copies or substantial portions of the Software. 22764 * 22765 * 22766 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22767 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22768 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22769 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22770 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22771 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22772 * THE SOFTWARE. 22773 */ 22774 const DEFAULT_GENOMES_URL = "https://igv.org/genomes/genomes.json"; 22775 const BACKUP_GENOMES_URL = "https://s3.amazonaws.com/igv.org.genomes/genomes.json"; 22776 const splitLines$1 = splitLines$5; 22777 const GenomeUtils = { 22778 loadGenome: async function (options) { 22779 const cytobandUrl = options.cytobandURL; 22780 const aliasURL = options.aliasURL; 22781 const sequence = await loadFasta(options); 22782 let cytobands; 22783 22784 if (cytobandUrl) { 22785 cytobands = await loadCytobands(cytobandUrl, sequence.config); 22786 } 22787 22788 let aliases; 22789 22790 if (aliasURL) { 22791 aliases = await loadAliases(aliasURL, sequence.config); 22792 } 22793 22794 return new Genome(options, sequence, cytobands, aliases); 22795 }, 22796 initializeGenomes: async function (config) { 22797 if (!GenomeUtils.KNOWN_GENOMES) { 22798 const table = {}; // Get default genomes 22799 22800 if (config.loadDefaultGenomes !== false) { 22801 try { 22802 const url = DEFAULT_GENOMES_URL + `?randomSeed=${Math.random().toString(36)}&version=${version$1()}`; // prevent caching 22803 22804 const jsonArray = await igvxhr.loadJson(url, { 22805 timeout: 5000 22806 }); 22807 processJson(jsonArray); 22808 } catch (e) { 22809 console.error(e); 22810 22811 try { 22812 const url = BACKUP_GENOMES_URL + `?randomSeed=${Math.random().toString(36)}&version=${version$1()}`; // prevent caching 22813 22814 const jsonArray = await igvxhr.loadJson(url, {}); 22815 processJson(jsonArray); 22816 } catch (e) { 22817 console.error(e); 22818 console.warn("Errors loading default genome definitions."); 22819 } 22820 } 22821 } // Add user-defined genomes 22822 22823 22824 const genomeList = config.genomeList || config.genomes; 22825 22826 if (genomeList) { 22827 if (typeof genomeList === 'string') { 22828 const jsonArray = await igvxhr.loadJson(genomeList, {}); 22829 processJson(jsonArray); 22830 } else { 22831 processJson(genomeList); 22832 } 22833 } 22834 22835 GenomeUtils.KNOWN_GENOMES = table; 22836 22837 function processJson(jsonArray) { 22838 jsonArray.forEach(function (json) { 22839 table[json.id] = json; 22840 }); 22841 return table; 22842 } 22843 } 22844 }, 22845 isWholeGenomeView: function (chr) { 22846 return 'all' === chr.toLowerCase(); 22847 }, 22848 // Expand a genome id to a reference object, if needed 22849 expandReference: function (idOrConfig) { 22850 // idOrConfig might be json 22851 if (isString$3(idOrConfig) && idOrConfig.startsWith("{")) { 22852 try { 22853 idOrConfig = JSON.parse(idOrConfig); 22854 } catch (e) {// Apparently its not json, could be an ID starting with "{". Unusual but legal. 22855 } 22856 } 22857 22858 let genomeID; 22859 22860 if (isString$3(idOrConfig)) { 22861 genomeID = idOrConfig; 22862 } else if (idOrConfig.genome) { 22863 genomeID = idOrConfig.genome; 22864 } else if (idOrConfig.id !== undefined && idOrConfig.fastaURL === undefined) { 22865 // Backward compatibility 22866 genomeID = idOrConfig.id; 22867 } 22868 22869 if (genomeID) {
22870 const knownGenomes = GenomeUtils.KNOWN_GENOMES; 22871 const reference = knownGenomes[genomeID]; 22872 22873 if (!reference) { 22874 Alert.presentAlert(new Error(`Unknown genome id: ${genomeID}`), undefined); 22875 } 22876 22877 return reference; 22878 } else { 22879 return idOrConfig; 22880 } 22881 } 22882 }; 22883 22884 class Genome { 22885 constructor(config, sequence, ideograms, aliases) { 22886 this.config = config; 22887 this.id = config.id; 22888 this.sequence = sequence; 22889 this.chromosomeNames = sequence.chromosomeNames; 22890 this.chromosomes = sequence.chromosomes; // An object (functions as a dictionary) 22891 22892 this.ideograms = ideograms; 22893 this.featureDB = {}; // Hash of name -> feature, used for search function. 22894 22895 this.wholeGenomeView = config.wholeGenomeView === undefined || config.wholeGenomeView; 22896 22897 if (this.wholeGenomeView && Object.keys(sequence.chromosomes).length > 1) { 22898 constructWG(this, config); 22899 } else { 22900 this.wgChromosomeNames = sequence.chromosomeNames; 22901 } 22902 /** 22903 * Return the official chromosome name for the (possibly) alias. Deals with 22904 * 1 <-> chr1, chrM <-> MT, IV <-> chr4, etc. 22905 * @param str 22906 */ 22907 22908 22909 var chrAliasTable = {}, 22910 self = this; // The standard mappings 22911 22912 chrAliasTable["all"] = "all"; 22913 this.chromosomeNames.forEach(function (name) { 22914 var alias = name.startsWith("chr") ? name.substring(3) : "chr" + name; 22915 chrAliasTable[alias.toLowerCase()] = name; 22916 if (name === "chrM") chrAliasTable["mt"] = "chrM"; 22917 if (name === "MT") chrAliasTable["chrm"] = "MT"; 22918 chrAliasTable[name.toLowerCase()] = name; 22919 }); // Custom mappings 22920 22921 if (aliases) { 22922 aliases.forEach(function (array) { 22923 // Find the official chr name 22924 var defName, i; 22925 22926 for (i = 0; i < array.length; i++) { 22927 if (self.chromosomes[array[i]]) { 22928 defName = array[i]; 22929 break; 22930 } 22931 } 22932 22933 if (defName) { 22934 array.forEach(function (alias) { 22935 if (alias !== defName) { 22936 chrAliasTable[alias.toLowerCase()] = defName; 22937 chrAliasTable[alias] = defName; // Should not be needed 22938 } 22939 }); 22940 } 22941 }); 22942 } 22943 22944 this.chrAliasTable = chrAliasTable; 22945 } 22946 22947 showWholeGenomeView() { 22948 return this.config.wholeGenomeView !== false; 22949 } 22950 22951 toJSON() { 22952 return Object.assign({}, this.config, { 22953 tracks: undefined 22954 }); 22955 } 22956 22957 getInitialLocus() {} 22958 22959 getHomeChromosomeName() { 22960 if (this.showWholeGenomeView() && this.chromosomes.hasOwnProperty("all")) { 22961 return "all"; 22962 } else { 22963 return this.chromosomeNames[0]; 22964 } 22965 } 22966 22967 getChromosomeName(str) { 22968 const chr = str ? this.chrAliasTable[str.toLowerCase()] : str; 22969 return chr ? chr : str; 22970 } 22971 22972 getChromosome(chr) { 22973 chr = this.getChromosomeName(chr); 22974 return this.chromosomes[chr]; 22975 } 22976 22977 getCytobands(chr) { 22978 return this.ideograms ? this.ideograms[chr] : null; 22979 } 22980 22981 getLongestChromosome() { 22982 var longestChr, 22983 chromosomes = this.chromosomes; 22984 22985 for (let key in chromosomes) { 22986 if (chromosomes.hasOwnProperty(key)) { 22987 var chr = chromosomes[key]; 22988 22989 if (longestChr === undefined || chr.bpLength > longestChr.bpLength) { 22990 longestChr = chr; 22991 } 22992 } 22993 22994 return longestChr; 22995 } 22996 } 22997 22998 getChromosomes() { 22999 return this.chromosomes; 23000 } 23001 /** 23002 * Return the genome coordinate in kb for the give chromosome and position. 23003 * NOTE: This might return undefined if the chr is filtered from whole genome view. 23004 */ 23005 23006 23007 getGenomeCoordinate(chr, bp) { 23008 var offset = this.getCumulativeOffset(chr); 23009 if (offset === undefined) return undefined; 23010 return offset + bp; 23011 } 23012 /** 23013 * Return the chromosome and coordinate in bp for the given genome coordinate 23014 */ 23015 23016 23017 getChromosomeCoordinate(genomeCoordinate) { 23018 if (this.cumulativeOffsets === undefined) { 23019 this.cumulativeOffsets = computeCumulativeOffsets.call(this); 23020 } 23021 23022 let lastChr = undefined; 23023 let lastCoord = 0; 23024 23025 for (let name of this.wgChromosomeNames) { 23026 const cumulativeOffset = this.cumulativeOffsets[name]; 23027 23028 if (cumulativeOffset > genomeCoordinate) { 23029 const position = genomeCoordinate - lastCoord; 23030 return {
23031 chr: lastChr, 23032 position: position 23033 }; 23034 } 23035 23036 lastChr = name; 23037 lastCoord = cumulativeOffset; 23038 } // If we get here off the end 23039 23040 23041 return { 23042 chr: this.wgChromosomeNames[this.wgChromosomeNames.length - 1], 23043 position: 0 23044 }; 23045 } 23046 23047 /** 23048 * Return the offset in genome coordinates (kb) of the start of the given chromosome 23049 * NOTE: This might return undefined if the chromosome is filtered from whole genome view. 23050 */ 23051 getCumulativeOffset(chr) { 23052 if (this.cumulativeOffsets === undefined) { 23053 this.cumulativeOffsets = computeCumulativeOffsets.call(this); 23054 } 23055 23056 const queryChr = this.getChromosomeName(chr); 23057 return this.cumulativeOffsets[queryChr]; 23058 23059 function computeCumulativeOffsets() { 23060 let self = this; 23061 let acc = {}; 23062 let offset = 0; 23063 23064 for (let name of self.wgChromosomeNames) { 23065 acc[name] = Math.floor(offset); 23066 const chromosome = self.getChromosome(name); 23067 offset += chromosome.bpLength; 23068 } 23069 23070 return acc; 23071 } 23072 } 23073 /** 23074 * Return the nominal genome length, this is the length of the main chromosomes (no scaffolds, etc). 23075 */ 23076 23077 23078 getGenomeLength() { 23079 let self = this; 23080 23081 if (!this.bpLength) { 23082 let bpLength = 0; 23083 self.wgChromosomeNames.forEach(function (cname) { 23084 let c = self.chromosomes[cname]; 23085 bpLength += c.bpLength; 23086 }); 23087 this.bpLength = bpLength; 23088 } 23089 23090 return this.bpLength; 23091 } 23092 23093 async getSequence(chr, start, end) { 23094 return this.sequence.getSequence(chr, start, end); 23095 } 23096 23097 } 23098 23099 async function loadCytobands(cytobandUrl, config) { 23100 let data; 23101 23102 if (isDataURL(cytobandUrl)) { 23103 const plain = decodeDataURI$1(cytobandUrl); 23104 data = ""; 23105 const len = plain.length; 23106 23107 for (let i = 0; i < len; i++) { 23108 data += String.fromCharCode(plain[i]); 23109 } 23110 } else { 23111 data = await igvxhr.loadString(cytobandUrl, buildOptions(config)); 23112 } // var bands = [], 23113 // lastChr, 23114 // n = 0, 23115 // c = 1, 23116 // 23117 // len = lines.length, 23118 23119 23120 const cytobands = {}; 23121 let lastChr; 23122 let bands = []; 23123 const lines = splitLines$1(data); 23124 23125 for (let line of lines) { 23126 var tokens = line.split("\t"); 23127 var chr = tokens[0]; 23128 if (!lastChr) lastChr = chr; 23129 23130 if (chr !== lastChr) { 23131 cytobands[lastChr] = bands; 23132 bands = []; 23133 lastChr = chr; 23134 } 23135 23136 if (tokens.length === 5) { 23137 //10 0 3000000 p15.3 gneg 23138 var start = parseInt(tokens[1]); 23139 var end = parseInt(tokens[2]); 23140 var name = tokens[3]; 23141 var stain = tokens[4]; 23142 bands.push(new Cytoband(start, end, name, stain)); 23143 } 23144 } 23145 23146 return cytobands; 23147 } 23148 23149 function loadAliases(aliasURL, config) { 23150 return igvxhr.loadString(aliasURL, buildOptions(config)).then(function (data) { 23151 var lines = splitLines$1(data), 23152 aliases = []; 23153 lines.forEach(function (line) { 23154 if (!line.startsWith("#") && line.length > 0) aliases.push(line.split("\t")); 23155 }); 23156 return aliases; 23157 }); 23158 } 23159 23160 function constructWG(genome, config) { 23161 let wgChromosomes; 23162 23163 if (config.chromosomeOrder) { 23164 if (Array.isArray(config.chromosomeOrder)) { 23165 genome.wgChromosomeNames = config.chromosomeOrder; 23166 } else { 23167 genome.wgChromosomeNames = config.chromosomeOrder.split(',').map(nm => nm.trim()); 23168 } 23169 23170 wgChromosomes = genome.wgChromosomeNames.map(nm => genome.chromosomes[nm]).filter(chr => chr !== undefined); 23171 } else { 23172 // Trim small chromosomes. 23173 const lengths = Object.keys(genome.chromosomes).map(key => genome.chromosomes[key].bpLength); 23174 const median = lengths.reduce((a, b) => Math.max(a, b)); 23175 const threshold = median / 50; 23176 wgChromosomes = Object.values(genome.chromosomes).filter(chr => chr.bpLength > threshold); // Sort chromosomes. First segregate numeric and alpha names, sort numeric, leave alpha as is 23177 23178 const numericChromosomes = wgChromosomes.filter(chr => isDigit(chr.name.replace('chr', '')));
23179 const alphaChromosomes = wgChromosomes.filter(chr => !isDigit(chr.name.replace('chr', ''))); 23180 numericChromosomes.sort((a, b) => Number.parseInt(a.name.replace('chr', '')) - Number.parseInt(b.name.replace('chr', ''))); 23181 const wgChromosomeNames = numericChromosomes.map(chr => chr.name); 23182 23183 for (let chr of alphaChromosomes) { 23184 wgChromosomeNames.push(chr.name); 23185 } 23186 23187 genome.wgChromosomeNames = wgChromosomeNames; 23188 } // Compute psuedo-chromosome "all" 23189 23190 23191 const l = wgChromosomes.reduce((accumulator, currentValue) => accumulator += currentValue.bpLength, 0); 23192 genome.chromosomes["all"] = { 23193 name: "all", 23194 bpLength: l 23195 }; 23196 23197 function isDigit(val) { 23198 return /^\d+$/.test(val); 23199 } 23200 } 23201 23202 /** 23203 * Created by dat on 9/16/16. 23204 */ 23205 const NOT_LOADED_MESSAGE = 'Error loading track data'; 23206 let lastClickTime = 0; 23207 let popupTimerID; 23208 23209 class TrackViewport extends Viewport { 23210 constructor(trackView, viewportColumn, referenceFrame, width) { 23211 super(trackView, viewportColumn, referenceFrame, width); 23212 } 23213 23214 initializationHelper() { 23215 this.$spinner = $$1('<div>', { 23216 class: 'igv-loading-spinner-container' 23217 }); 23218 this.$viewport.append(this.$spinner); 23219 this.$spinner.append($$1('<div>')); 23220 const { 23221 track 23222 } = this.trackView; 23223 23224 if ('sequence' !== track.type) { 23225 this.$zoomInNotice = this.createZoomInNotice(this.$content); 23226 } 23227 23228 if (track.name && "sequence" !== track.config.type) { 23229 this.$trackLabel = $$1('<div class="igv-track-label">'); 23230 this.$viewport.append(this.$trackLabel); 23231 this.setTrackLabel(track.name); 23232 23233 if (false === this.browser.trackLabelsVisible) { 23234 this.$trackLabel.hide(); 23235 } 23236 } 23237 23238 this.stopSpinner(); 23239 this.addMouseHandlers(); 23240 } 23241 23242 setTrackLabel(label) { 23243 this.$trackLabel.empty(); 23244 this.$trackLabel.html(label); 23245 const txt = this.$trackLabel.text(); 23246 this.$trackLabel.attr('title', txt); 23247 } 23248 23249 startSpinner() { 23250 this.$spinner.show(); 23251 } 23252 23253 stopSpinner() { 23254 this.$spinner.hide(); 23255 } 23256 23257 checkZoomIn() { 23258 const showZoomInNotice = () => { 23259 const referenceFrame = this.referenceFrame; 23260 23261 if (this.referenceFrame.chr.toLowerCase() === "all" && !this.trackView.track.supportsWholeGenome()) { 23262 return true; 23263 } else { 23264 const visibilityWindow = this.trackView.track.visibilityWindow; 23265 return visibilityWindow !== undefined && visibilityWindow > 0 && referenceFrame.bpPerPixel * this.$viewport.width() > visibilityWindow; 23266 } 23267 }; 23268 23269 if (!this.viewIsReady()) { 23270 return false; 23271 } 23272 23273 if (this.$zoomInNotice) { 23274 if (showZoomInNotice()) { 23275 // Out of visibility window 23276 if (this.canvas) { 23277 this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height); 23278 this.tile = undefined; 23279 } 23280 23281 this.$zoomInNotice.show(); 23282 23283 if (this.trackView.track.autoHeight) { 23284 const minHeight = this.trackView.minHeight || 0; 23285 this.setContentHeight(minHeight); 23286 } 23287 23288 return false; 23289 } else { 23290 this.$zoomInNotice.hide(); 23291 return true; 23292 } 23293 } 23294 23295 return true; 23296 } 23297 23298 shift() { 23299 const self = this; 23300 const referenceFrame = self.referenceFrame; 23301 23302 if (self.canvas && self.tile && self.tile.chr === self.referenceFrame.chr && self.tile.bpPerPixel === referenceFrame.bpPerPixel) { 23303 const pixelOffset = Math.round((self.tile.startBP - referenceFrame.start) / referenceFrame.bpPerPixel); 23304 self.canvas.style.left = pixelOffset + "px"; 23305 } 23306 } 23307 23308 async loadFeatures() { 23309 const referenceFrame = this.referenceFrame; 23310 const chr = referenceFrame.chr; // Expand the requested range so we can pan a bit without reloading. But not beyond chromosome bounds 23311 23312 const chrLength = this.browser.genome.getChromosome(chr).bpLength; 23313 const pixelWidth = this.$content.width(); // * 3; 23314 23315 const bpWidth = pixelWidth * referenceFrame.bpPerPixel; 23316 const bpStart = Math.floor(Math.max(0, referenceFrame.start - bpWidth)); 23317 const bpEnd = Math.ceil(Math.min(chrLength, referenceFrame.start + bpWidth + bpWidth)); // Add one screen width to end 23318 23319 if (this.loading && this.loading.start === bpStart && this.loading.end === bpEnd) { 23320 return undefined; 23321 } 23322 23323 this.loading = { 23324 start: bpStart, 23325 end: bpEnd 23326 }; 23327 this.startSpinner(); 23328 23329 try { 23330 const features = await this.getFeatures(this.trackView.track, chr, bpStart, bpEnd, referenceFrame.bpPerPixel); 23331 let roiFeatures = []; 23332 const roi = mergeArrays(this.browser.roi, this.trackView.track.roi); 23333 23334 if (roi) { 23335 for (let r of roi) { 23336 const f = await r.getFeatures(chr, bpStart, bpEnd, referenceFrame.bpPerPixel); 23337 roiFeatures.push({ 23338 track: r, 23339 features: f 23340 }); 23341 } 23342 } 23343 23344 this.tile = new Tile(chr, bpStart, bpEnd, referenceFrame.bpPerPixel, features, roiFeatures); 23345 this.loading = false;
23346 this.hideMessage(); 23347 this.stopSpinner(); 23348 return this.tile; 23349 } catch (error) { 23350 // Track might have been removed during load 23351 if (this.trackView && this.trackView.disposed !== true) { 23352 this.showMessage(NOT_LOADED_MESSAGE); 23353 Alert.presentAlert(error); 23354 console.error(error); 23355 } 23356 } finally { 23357 this.loading = false; 23358 this.stopSpinner(); 23359 } 23360 } 23361 23362 async repaint() { 23363 if (undefined === this.tile) { 23364 return; 23365 } 23366 23367 let { 23368 features, 23369 roiFeatures, 23370 bpPerPixel, 23371 startBP, 23372 endBP 23373 } = this.tile; // const isWGV = GenomeUtils.isWholeGenomeView(this.browser.referenceFrameList[0].chr) 23374 23375 const isWGV = GenomeUtils.isWholeGenomeView(this.referenceFrame.chr); 23376 let pixelWidth; 23377 23378 if (isWGV) { 23379 bpPerPixel = this.referenceFrame.end / this.$viewport.width(); 23380 startBP = 0; 23381 endBP = this.referenceFrame.end; 23382 pixelWidth = this.$viewport.width(); 23383 } else { 23384 pixelWidth = Math.ceil((endBP - startBP) / bpPerPixel); 23385 } // For deep tracks we paint a canvas == 3*viewportHeight centered on the current vertical scroll position 23386 23387 23388 const viewportHeight = this.$viewport.height(); 23389 const contentHeight = this.getContentHeight(); 23390 const minHeight = roiFeatures ? Math.max(contentHeight, viewportHeight) : contentHeight; // Need to fill viewport for ROIs. 23391 23392 let pixelHeight = Math.min(minHeight, 3 * viewportHeight); 23393 23394 if (0 === pixelWidth || 0 === pixelHeight) { 23395 if (this.canvas) { 23396 $$1(this.canvas).remove(); 23397 } 23398 23399 return; 23400 } 23401 23402 const canvasTop = Math.max(0, -this.$content.position().top - viewportHeight); // Always use high DPI if in compressed display mode, otherwise use preference setting; 23403 23404 let devicePixelRatio; 23405 23406 if ("FILL" === this.trackView.track.displayMode) { 23407 devicePixelRatio = window.devicePixelRatio; 23408 } else { 23409 devicePixelRatio = this.trackView.track.supportHiDPI === false ? 1 : window.devicePixelRatio; 23410 } 23411 23412 const pixelXOffset = Math.round((startBP - this.referenceFrame.start) / this.referenceFrame.bpPerPixel); 23413 const newCanvas = $$1('<canvas class="igv-canvas">').get(0); 23414 const ctx = newCanvas.getContext("2d"); 23415 newCanvas.style.width = pixelWidth + "px"; 23416 newCanvas.style.height = pixelHeight + "px"; 23417 newCanvas.width = devicePixelRatio * pixelWidth; 23418 newCanvas.height = devicePixelRatio * pixelHeight; 23419 ctx.scale(devicePixelRatio, devicePixelRatio); 23420 newCanvas.style.left = pixelXOffset + "px"; 23421 newCanvas.style.top = canvasTop + "px"; 23422 ctx.translate(0, -canvasTop); 23423 const drawConfiguration = { 23424 context: ctx, 23425 pixelXOffset, 23426 pixelWidth, 23427 pixelHeight, 23428 pixelTop: canvasTop, 23429 bpStart: startBP, 23430 bpEnd: endBP, 23431 bpPerPixel, 23432 referenceFrame: this.referenceFrame, 23433 selection: this.selection, 23434 viewport: this, 23435 viewportWidth: this.$viewport.width() 23436 }; 23437 this.draw(drawConfiguration, features, roiFeatures); 23438 this.canvasVerticalRange = { 23439 top: canvasTop, 23440 bottom: canvasTop + pixelHeight 23441 }; 23442 23443 if (this.$canvas) { 23444 this.$canvas.remove(); 23445 } 23446 23447 this.$canvas = $$1(newCanvas); 23448 this.$content.append(this.$canvas); 23449 this.canvas = newCanvas; 23450 this.ctx = ctx; 23451 } 23452 23453 draw(drawConfiguration, features, roiFeatures) { 23454 // console.log(`${ Date.now() } viewport draw(). track ${ this.trackView.track.type }. content-css-top ${ this.$content.css('top') }. canvas-top ${ drawConfiguration.pixelTop }.`) 23455 if (features) { 23456 drawConfiguration.features = features; 23457 this.trackView.track.draw(drawConfiguration); 23458 } 23459 23460 if (roiFeatures) { 23461 for (let r of roiFeatures) { 23462 drawConfiguration.features = r.features; 23463 r.track.draw(drawConfiguration); 23464 } 23465 } 23466 } // TODO: Nolonger used. Will discard 23467 23468 23469 async toSVG(tile) { 23470 // Nothing to do if zoomInNotice is active 23471 if (this.$zoomInNotice && this.$zoomInNotice.is(":visible")) { 23472 return; 23473 } 23474 23475 const referenceFrame = this.referenceFrame; 23476 const bpPerPixel = tile.bpPerPixel; 23477 const features = tile.features; 23478 const roiFeatures = tile.roiFeatures; 23479 const pixelWidth = this.$viewport.width(); 23480 const pixelHeight = this.$viewport.height(); 23481 const bpStart = referenceFrame.start; 23482 const bpEnd = referenceFrame.start + pixelWidth * referenceFrame.bpPerPixel; 23483 const ctx$1 = new ctx({ 23484 // svg 23485 width: pixelWidth, 23486 height: pixelHeight, 23487 viewbox: { 23488 x: 0, 23489 y: -this.$content.position().top, 23490 width: pixelWidth, 23491 height: pixelHeight 23492 } 23493 }); 23494 const drawConfiguration = { 23495 viewport: this, 23496 context: ctx$1, 23497 top: -this.$content.position().top, 23498 pixelTop: 0, 23499 // for compatibility with canvas draw 23500 pixelWidth, 23501 pixelHeight, 23502 bpStart, 23503 bpEnd, 23504 bpPerPixel, 23505 referenceFrame: this.referenceFrame, 23506 selection: this.selection, 23507 viewportWidth: pixelWidth 23508 }; 23509 this.draw(drawConfiguration, features, roiFeatures); 23510 return ctx$1.getSerializedSvg(true); 23511 } 23512 23513 containsPosition(chr, position) { 23514 if (this.referenceFrame.chr === chr && position >= this.referenceFrame.start) { 23515 return position <= this.referenceFrame.calculateEnd(this.getWidth()); 23516 } else { 23517 return false;
23518 } 23519 } 23520 23521 isLoading() { 23522 return this.loading; 23523 } 23524 23525 saveImage() { 23526 if (!this.ctx) return; 23527 const canvasTop = this.canvasVerticalRange ? this.canvasVerticalRange.top : 0; 23528 const devicePixelRatio = window.devicePixelRatio; 23529 const w = this.$viewport.width() * devicePixelRatio; 23530 const h = this.$viewport.height() * devicePixelRatio; 23531 const x = -$$1(this.canvas).position().left * devicePixelRatio; 23532 const y = (-this.$content.position().top - canvasTop) * devicePixelRatio; 23533 const imageData = this.ctx.getImageData(x, y, w, h); 23534 const exportCanvas = document.createElement('canvas'); 23535 const exportCtx = exportCanvas.getContext('2d'); 23536 exportCanvas.width = imageData.width; 23537 exportCanvas.height = imageData.height; 23538 exportCtx.putImageData(imageData, 0, 0); // filename = this.trackView.track.name + ".png"; 23539 23540 const filename = (this.$trackLabel.text() ? this.$trackLabel.text() : "image") + ".png"; 23541 const data = exportCanvas.toDataURL("image/png"); 23542 download(filename, data); 23543 } 23544 23545 saveSVG() { 23546 const { 23547 width, 23548 height 23549 } = this.$viewport.get(0).getBoundingClientRect(); 23550 const config = { 23551 width, 23552 height, 23553 viewbox: { 23554 x: 0, 23555 y: -this.$content.position().top, 23556 width, 23557 height 23558 } 23559 }; 23560 const context = new ctx(config); 23561 const str = (this.trackView.track.name || this.trackView.track.id).replace(/\W/g, ''); 23562 const index = this.browser.referenceFrameList.indexOf(this.referenceFrame); 23563 const id = `${str}_referenceFrame_${index}_guid_${guid$1()}`; 23564 this.drawSVGWithContext(context, width, height, id, 0, 0, 0); 23565 const svg = context.getSerializedSvg(true); 23566 const data = URL.createObjectURL(new Blob([svg], { 23567 type: "application/octet-stream" 23568 })); 23569 download(`${id}.svg`, data); 23570 } // called by trackView.renderSVGContext() when rendering 23571 // entire browser as SVG 23572 23573 23574 renderSVGContext(context, _ref) { 23575 let { 23576 deltaX, 23577 deltaY 23578 } = _ref; 23579 23580 // Nothing to do if zoomInNotice is active 23581 if (this.$zoomInNotice && this.$zoomInNotice.is(":visible")) { 23582 return; 23583 } 23584 23585 const str = (this.trackView.track.name || this.trackView.track.id).replace(/\W/g, ''); 23586 const index = this.browser.referenceFrameList.indexOf(this.referenceFrame); 23587 const id = `${str}_referenceFrame_${index}_guid_${guid$1()}`; 23588 const { 23589 top: yScrollDelta 23590 } = this.$content.position(); 23591 const { 23592 width, 23593 height 23594 } = this.$viewport.get(0).getBoundingClientRect(); 23595 this.drawSVGWithContext(context, width, height, id, deltaX, deltaY + yScrollDelta, -yScrollDelta); 23596 23597 if (this.$trackLabel && true === this.browser.trackLabelsVisible) { 23598 const { 23599 x, 23600 y, 23601 width, 23602 height 23603 } = relativeDOMBBox(this.$viewport.get(0), this.$trackLabel.get(0)); 23604 this.renderTrackLabelSVG(context, deltaX + x, deltaY + y, width, height); 23605 } 23606 } // render track label element called from renderSVGContext() 23607 23608 23609 renderTrackLabelSVG(context, tx, ty, width, height) { 23610 const str = (this.trackView.track.name || this.trackView.track.id).replace(/\W/g, ''); 23611 const id = `${str}_track_label_guid_${guid$1()}`; 23612 context.saveWithTranslationAndClipRect(id, tx, ty, width, height, 0); 23613 context.fillStyle = "white"; 23614 context.fillRect(0, 0, width, height); 23615 context.font = "12px Arial"; 23616 context.fillStyle = 'rgb(68, 68, 68)'; 23617 const { 23618 width: stringWidth 23619 } = context.measureText(this.$trackLabel.text()); 23620 const dx = 0.25 * (width - stringWidth); 23621 const dy = 0.7 * (height - 12); 23622 context.fillText(this.$trackLabel.text(), dx, height - dy); 23623 context.strokeStyle = 'rgb(68, 68, 68)'; 23624 context.strokeRect(0, 0, width, height);
23625 context.restore(); 23626 } // called by renderSVGContext() 23627 23628 23629 drawSVGWithContext(context, width, height, id, x, y, yClipOffset) { 23630 context.saveWithTranslationAndClipRect(id, x, y, width, height, yClipOffset); 23631 let { 23632 start, 23633 bpPerPixel 23634 } = this.referenceFrame; 23635 const config = { 23636 context, 23637 viewport: this, 23638 referenceFrame: this.referenceFrame, 23639 top: yClipOffset, 23640 pixelTop: yClipOffset, 23641 pixelWidth: width, 23642 pixelHeight: height, 23643 bpStart: start, 23644 bpEnd: start + width * bpPerPixel, 23645 bpPerPixel, 23646 viewportWidth: width, 23647 selection: this.selection 23648 }; 23649 const features = this.tile ? this.tile.features : []; 23650 const roiFeatures = this.tile ? this.tile.roiFeatures : undefined; 23651 this.draw(config, features, roiFeatures); 23652 context.restore(); 23653 } 23654 23655 getCachedFeatures() { 23656 return this.tile ? this.tile.features : []; 23657 } 23658 23659 async getFeatures(track, chr, start, end, bpPerPixel) { 23660 if (this.tile && this.tile.containsRange(chr, start, end, bpPerPixel)) { 23661 return this.tile.features; 23662 } else if (typeof track.getFeatures === "function") { 23663 const features = await track.getFeatures(chr, start, end, bpPerPixel, this); 23664 this.cachedFeatures = features; 23665 this.checkContentHeight(); 23666 return features; 23667 } else { 23668 return undefined; 23669 } 23670 } 23671 23672 createZoomInNotice($parent) { 23673 const $container = $$1('<div>', { 23674 class: 'igv-zoom-in-notice-container' 23675 }); 23676 $parent.append($container); 23677 const $e = $$1('<div>'); 23678 $container.append($e); 23679 $e.text('Zoom in to see features'); 23680 $container.hide(); 23681 return $container; 23682 } 23683 23684 viewIsReady() { 23685 return this.browser && this.browser.referenceFrameList && this.referenceFrame; 23686 } 23687 23688 addMouseHandlers() { 23689 this.addViewportContextMenuHandler(this.$viewport.get(0)); 23690 this.addViewportMouseDownHandler(this.$viewport.get(0)); 23691 this.addViewportTouchStartHandler(this.$viewport.get(0)); 23692 this.addViewportMouseUpHandler(this.$viewport.get(0)); 23693 this.addViewportTouchEndHandler(this.$viewport.get(0)); 23694 this.addViewportClickHandler(this.$viewport.get(0)); 23695 23696 if (this.trackView.track.name && "sequence" !== this.trackView.track.config.type) { 23697 this.addTrackLabelClickHandler(this.$trackLabel.get(0)); 23698 } 23699 } 23700 23701 removeMouseHandlers() { 23702 this.removeViewportContextMenuHandler(this.$viewport.get(0)); 23703 this.removeViewportMouseDownHandler(this.$viewport.get(0)); 23704 this.removeViewportTouchStartHandler(this.$viewport.get(0)); 23705 this.removeViewportMouseUpHandler(this.$viewport.get(0)); 23706 this.removeViewportTouchEndHandler(this.$viewport.get(0)); 23707 this.removeViewportClickHandler(this.$viewport.get(0)); 23708 23709 if (this.trackView.track.name && "sequence" !== this.trackView.track.config.type) { 23710 this.removeTrackLabelClickHandler(this.$trackLabel.get(0)); 23711 } 23712 } 23713 23714 addViewportContextMenuHandler(viewport) { 23715 this.boundContextMenuHandler = contextMenuHandler.bind(this); 23716 viewport.addEventListener('contextmenu', this.boundContextMenuHandler); 23717 23718 function contextMenuHandler(event) { 23719 // Ignore if we are doing a drag. This can happen with touch events. 23720 if (this.browser.dragObject) { 23721 return false; 23722 } 23723 23724 const clickState = createClickState(event, this); 23725 23726 if (undefined === clickState) { 23727 return false; 23728 } 23729 23730 event.preventDefault(); // Track specific items 23731 23732 let menuItems = []; 23733 23734 if (typeof this.trackView.track.contextMenuItemList === "function") { 23735 const trackMenuItems = this.trackView.track.contextMenuItemList(clickState); 23736 23737 if (trackMenuItems) { 23738 menuItems = trackMenuItems; 23739 } 23740 } // Add items common to all tracks 23741 23742 23743 if (menuItems.length > 0) { 23744 menuItems.push({ 23745 label: $$1('<HR>') 23746 }); 23747 } 23748 23749 menuItems.push({ 23750 label: 'Save Image (PNG)', 23751 click: () => this.saveImage() 23752 }); 23753 menuItems.push({ 23754 label: 'Save Image (SVG)', 23755 click: () => this.saveSVG() 23756 }); 23757 this.browser.menuPopup.presentTrackContextMenu(event, menuItems); 23758 } 23759 } 23760 23761 removeViewportContextMenuHandler(viewport) { 23762 viewport.removeEventListener('contextmenu', this.boundContextMenuHandler); 23763 } 23764 23765 addViewportMouseDownHandler(viewport) { 23766 this.boundMouseDownHandler = mouseDownHandler.bind(this); 23767 viewport.addEventListener('mousedown', this.boundMouseDownHandler); 23768 } 23769 23770 removeViewportMouseDownHandler(viewport) { 23771 viewport.removeEventListener('mousedown', this.boundMouseDownHandler); 23772 } 23773 23774 addViewportTouchStartHandler(viewport) { 23775 this.boundTouchStartHandler = mouseDownHandler.bind(this); 23776 viewport.addEventListener('touchstart', this.boundTouchStartHandler); 23777 } 23778 23779 removeViewportTouchStartHandler(viewport) { 23780 viewport.removeEventListener('touchstart', this.boundTouchStartHandler); 23781 } 23782 23783 addViewportMouseUpHandler(viewport) { 23784 this.boundMouseUpHandler = mouseUpHandler.bind(this); 23785 viewport.addEventListener('mouseup', this.boundMouseUpHandler); 23786 } 23787 23788 removeViewportMouseUpHandler(viewport) { 23789 viewport.removeEventListener('mouseup', this.boundMouseUpHandler); 23790 } 23791 23792 addViewportTouchEndHandler(viewport) { 23793 this.boundTouchEndHandler = mouseUpHandler.bind(this); 23794 viewport.addEventListener('touchend', this.boundTouchEndHandler); 23795 } 23796 23797 removeViewportTouchEndHandler(viewport) { 23798 viewport.removeEventListener('touchend', this.boundTouchEndHandler); 23799 } 23800 23801 addViewportClickHandler(viewport) { 23802 this.boundClickHandler = clickHandler.bind(this); 23803 viewport.addEventListener('click', this.boundClickHandler); 23804 23805 function clickHandler(event) { 23806 if (this.enableClick) { 23807 if (3 === event.which || event.ctrlKey) { 23808 return; 23809 } // Close any currently open popups 23810 23811 23812 $$1('.igv-popover').hide(); 23813 23814 if (this.browser.dragObject || this.browser.isScrolling) { 23815 return; 23816 } // Treat as a mouse click, its either a single or double click. 23817 // Handle here and stop propogation / default 23818 23819 23820 event.preventDefault(); 23821 const mouseX = translateMouseCoordinates$1(event, this.$viewport.get(0)).x; 23822 const mouseXCanvas = translateMouseCoordinates$1(event, this.canvas).x; 23823 const referenceFrame = this.referenceFrame; 23824 const xBP = Math.floor(referenceFrame.start + referenceFrame.toBP(mouseXCanvas)); 23825 const time = Date.now(); 23826 23827 if (time - lastClickTime < this.browser.constants.doubleClickDelay) { 23828 // double-click 23829 if (popupTimerID) { 23830 window.clearTimeout(popupTimerID); 23831 popupTimerID = undefined; 23832 } 23833 23834 const centerBP = Math.round(referenceFrame.start + referenceFrame.toBP(mouseX)); 23835 let string; 23836 23837 if ('all' === this.referenceFrame.chr.toLowerCase()) { 23838 const chr = this.browser.genome.getChromosomeCoordinate(centerBP).chr; 23839 23840 if (1 === this.browser.referenceFrameList.length) {
23841 string = chr; 23842 } else { 23843 const loci = this.browser.referenceFrameList.map(_ref2 => { 23844 let { 23845 locusSearchString 23846 } = _ref2; 23847 return locusSearchString; 23848 }); 23849 const index = this.browser.referenceFrameList.indexOf(this.referenceFrame); 23850 loci[index] = chr; 23851 string = loci.join(' '); 23852 } 23853 23854 this.browser.search(string); 23855 } else { 23856 this.browser.zoomWithScaleFactor(0.5, centerBP, this.referenceFrame); 23857 } 23858 } else { 23859 // single-click 23860 if (event.shiftKey && typeof this.trackView.track.shiftClick === "function") { 23861 this.trackView.track.shiftClick(xBP, event); 23862 } else if (typeof this.trackView.track.popupData === "function") { 23863 popupTimerID = setTimeout(() => { 23864 const content = getPopupContent(event, this); 23865 23866 if (content) { 23867 if (this.popover) this.popover.dispose(); 23868 this.popover = new Popover(this.browser.columnContainer); 23869 this.popover.presentContentWithEvent(event, content); 23870 } 23871 23872 window.clearTimeout(popupTimerID); 23873 popupTimerID = undefined; 23874 }, this.browser.constants.doubleClickDelay); 23875 } 23876 } 23877 23878 lastClickTime = time; 23879 } 23880 } 23881 } 23882 23883 removeViewportClickHandler(viewport) { 23884 viewport.removeEventListener('click', this.boundClickHandler); 23885 } 23886 23887 addTrackLabelClickHandler(trackLabel) { 23888 this.boundTrackLabelClickHandler = clickHandler.bind(this); 23889 trackLabel.addEventListener('click', this.boundTrackLabelClickHandler); 23890 23891 function clickHandler(event) { 23892 event.stopPropagation(); 23893 const { 23894 track 23895 } = this.trackView; 23896 let str; 23897 23898 if (typeof track.description === 'function') { 23899 str = track.description(); 23900 } else if (track.description) { 23901 str = `<div>${track.description}</div>`; 23902 } else { 23903 if (track.url) { 23904 if (isFile(track.url)) { 23905 str = `<div><b>Filename: </b>${track.url.name}`; 23906 } else { 23907 str = `<div><b>URL: </b>${track.url}`; 23908 } 23909 } else { 23910 str = track.name; 23911 } 23912 } 23913 23914 if (this.popover) { 23915 this.popover.dispose(); 23916 } 23917 23918 this.popover = new Popover(this.browser.columnContainer, track.name || 'unnamed'); 23919 this.popover.presentContentWithEvent(event, str); 23920 } 23921 } 23922 23923 removeTrackLabelClickHandler(trackLabel) { 23924 trackLabel.removeEventListener('click', this.boundTrackLabelClickHandler); 23925 } 23926 23927 } 23928 23929 function mouseDownHandler(event) { 23930 this.enableClick = true; 23931 this.browser.mouseDownOnViewport(event, this); 23932 pageCoordinates$1(event); 23933 } 23934 23935 function mouseUpHandler(event) { 23936 // Any mouse up cancels drag and scrolling 23937 if (this.browser.dragObject || this.browser.isScrolling) { 23938 this.browser.cancelTrackPan(); // event.preventDefault(); 23939 // event.stopPropagation(); 23940 23941 this.enableClick = false; // Until next mouse down 23942 } else { 23943 this.browser.cancelTrackPan(); 23944 this.browser.endTrackDrag(); 23945 } 23946 } 23947 23948 function createClickState(event, viewport) { 23949 const referenceFrame = viewport.referenceFrame; 23950 const viewportCoords = translateMouseCoordinates$1(event, viewport.contentDiv); 23951 const canvasCoords = translateMouseCoordinates$1(event, viewport.canvas); 23952 const genomicLocation = referenceFrame.start + referenceFrame.toBP(viewportCoords.x); 23953 23954 if (undefined === genomicLocation || null === viewport.tile) { 23955 return undefined; 23956 } 23957 23958 return { 23959 event, 23960 viewport, 23961 referenceFrame, 23962 genomicLocation, 23963 x: viewportCoords.x, 23964 y: viewportCoords.y, 23965 canvasX: canvasCoords.x, 23966 canvasY: canvasCoords.y 23967 }; 23968 } 23969 23970 function getPopupContent(event, viewport) { 23971 const clickState = createClickState(event, viewport); 23972 23973 if (undefined === clickState) { 23974 return; 23975 } 23976 23977 let track = viewport.trackView.track; 23978 const dataList = track.popupData(clickState); 23979 const popupClickHandlerResult = viewport.browser.fireEvent('trackclick', [track, dataList]); 23980 let content; 23981 23982 if (undefined === popupClickHandlerResult || true === popupClickHandlerResult) { 23983 // Indicates handler did not handle the result, or the handler wishes default behavior to occur 23984 if (dataList && dataList.length > 0) { 23985 content = formatPopoverText(dataList); 23986 } 23987 } else if (typeof popupClickHandlerResult === 'string') { 23988 content = popupClickHandlerResult; 23989 } 23990 23991 return content; 23992 } 23993 23994 function formatPopoverText(nameValues) { 23995 const rows = nameValues.map(nameValue => { 23996 if (nameValue.name) { 23997 const str = `<span>${nameValue.name}</span>   ${nameValue.value}`; 23998 return `<div title="${nameValue.value}">${str}</div>`; 23999 } else if ('<hr>' === nameValue) { 24000 // this can be retired if nameValue.html is allowed. 24001 return nameValue; 24002 } else if (nameValue.html) { 24003 return nameValue.html; 24004 } else { 24005 return `<div title="${nameValue}">${nameValue}</div>`; 24006 } 24007 }); 24008 return rows.join(''); 24009 } 24010 24011 var Tile = function (chr, tileStart, tileEnd, bpPerPixel, features, roiFeatures) { 24012 this.chr = chr; 24013 this.startBP = tileStart; 24014 this.endBP = tileEnd; 24015 this.bpPerPixel = bpPerPixel; 24016 this.features = features; 24017 this.roiFeatures = roiFeatures; 24018 }; 24019 24020 Tile.prototype.containsRange = function (chr, start, end, bpPerPixel) { 24021 return this.bpPerPixel === bpPerPixel && start >= this.startBP && end <= this.endBP && chr === this.chr; 24022 }; 24023 24024 Tile.prototype.overlapsRange = function (chr, start, end) { 24025 return this.chr === chr && end >= this.startBP && start <= this.endBP; 24026 }; 24027 /**
24028 * Merge 2 arrays. a and/or b can be undefined. If both are undefined, return undefined 24029 * @param a An array or undefined 24030 * @param b An array or undefined 24031 */ 24032 24033 24034 function mergeArrays(a, b) { 24035 if (a && b) return a.concat(b);else if (a) return a;else return b; 24036 } 24037 24038 /* 24039 * The MIT License (MIT) 24040 * 24041 * Copyright (c) 2016-2017 The Regents of the University of California 24042 * Author: Jim Robinson 24043 * 24044 * Permission is hereby granted, free of charge, to any person obtaining a copy 24045 * of this software and associated documentation files (the "Software"), to deal 24046 * in the Software without restriction, including without limitation the rights 24047 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 24048 * copies of the Software, and to permit persons to whom the Software is 24049 * furnished to do so, subject to the following conditions: 24050 * 24051 * The above copyright notice and this permission notice shall be included in 24052 * all copies or substantial portions of the Software. 24053 * 24054 * 24055 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24056 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24057 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24058 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24059 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24060 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24061 * THE SOFTWARE. 24062 */ 24063 24064 class RulerSweeper { 24065 constructor(rulerViewport) { 24066 this.rulerSweeper = div$1({ 24067 class: 'igv-ruler-sweeper' 24068 }); 24069 rulerViewport.contentDiv.appendChild(this.rulerSweeper); 24070 this.rulerViewport = rulerViewport; 24071 this.isMouseHandlers = undefined; 24072 this.addBrowserObserver(); 24073 } 24074 24075 addBrowserObserver() { 24076 // Viewport Content 24077 this.boundObserverHandler = observerHandler.bind(this); 24078 this.rulerViewport.browser.on('locuschange', this.boundObserverHandler); 24079 24080 function observerHandler() { 24081 if (this.rulerViewport.referenceFrame) { 24082 if (GenomeUtils.isWholeGenomeView(this.rulerViewport.referenceFrame.chr)) { 24083 this.removeMouseHandlers(); 24084 } else { 24085 this.addMouseHandlers(); 24086 } 24087 } 24088 } 24089 } 24090 24091 removeBrowserObserver() { 24092 this.rulerViewport.browser.off('locuschange', this.boundObserverHandler); 24093 } 24094 24095 addMouseHandlers() { 24096 if (true === this.isMouseHandlers) { 24097 return; 24098 } 24099 24100 let isMouseDown; 24101 let isMouseIn; 24102 let mouseDownX; 24103 let left; 24104 let width; 24105 let dx; 24106 let threshold = 1; // Viewport Content 24107 24108 this.boundContentMouseDownHandler = contentMouseDownHandler.bind(this); 24109 this.rulerViewport.contentDiv.addEventListener('mousedown', this.boundContentMouseDownHandler); 24110 24111 function contentMouseDownHandler(event) { 24112 isMouseDown = true; 24113 isMouseIn = true; 24114 const { 24115 x 24116 } = translateMouseCoordinates$1(event, this.rulerViewport.contentDiv); 24117 left = mouseDownX = x; 24118 width = threshold; 24119 this.rulerSweeper.style.display = 'block'; 24120 this.rulerSweeper.style.left = `${left}px`; 24121 this.rulerSweeper.style.width = `${width}px`; 24122 } // Document 24123 24124 24125 this.boundDocumentMouseMoveHandler = documentMouseMoveHandler.bind(this); 24126 document.addEventListener('mousemove', this.boundDocumentMouseMoveHandler); 24127 24128 function documentMouseMoveHandler(event) { 24129 // console.log(`${ Date.now() } RulerSweeper - documentMouseMoveHandler - target ${ event.target.nodeName }`) 24130 let mouseCurrentX; 24131 24132 if (isMouseDown && isMouseIn) { 24133 const { 24134 x 24135 } = translateMouseCoordinates$1(event, this.rulerViewport.contentDiv); 24136 mouseCurrentX = Math.max(Math.min(x, this.rulerViewport.contentDiv.clientWidth), 0); 24137 dx = mouseCurrentX - mouseDownX; 24138 width = Math.abs(dx); 24139 this.rulerSweeper.style.width = `${width}px`; 24140 24141 if (dx < 0) { 24142 left = mouseDownX + dx; 24143 this.rulerSweeper.style.left = `${left}px`; 24144 } 24145 } 24146 } 24147 24148 this.boundDocumentMouseUpHandler = documentMouseUpHandler.bind(this); 24149 document.addEventListener('mouseup', this.boundDocumentMouseUpHandler); 24150 24151 function documentMouseUpHandler(event) { 24152 // console.log(`${ Date.now() } RulerSweeper - documentMouseUpHandler - target ${ event.target.nodeName }`) 24153 let extent; 24154 24155 if (true === isMouseDown && true === isMouseIn) { 24156 isMouseDown = isMouseIn = undefined; 24157 this.rulerSweeper.style.display = 'none'; 24158 24159 if (width > threshold) { 24160 extent = { 24161 start: bp(this.rulerViewport.referenceFrame, left), 24162 end: bp(this.rulerViewport.referenceFrame, left + width) 24163 }; 24164 validateLocusExtent(this.rulerViewport.browser.genome.getChromosome(this.rulerViewport.referenceFrame.chr).bpLength, extent, this.rulerViewport.browser.minimumBases()); 24165 this.rulerViewport.referenceFrame.bpPerPixel = (Math.round(extent.end
24165) - Math.round(extent.start)) / this.rulerViewport.contentDiv.clientWidth; 24166 this.rulerViewport.referenceFrame.start = Math.round(extent.start); 24167 this.rulerViewport.referenceFrame.end = Math.round(extent.end); 24168 this.rulerViewport.browser.updateViews(this.rulerViewport.referenceFrame); 24169 } 24170 } 24171 } 24172 24173 this.isMouseHandlers = true; 24174 } 24175 24176 removeMouseHandlers() { 24177 this.rulerViewport.contentDiv.removeEventListener('mousedown', this.boundContentMouseDownHandler); 24178 document.removeEventListener('mousemove', this.boundDocumentMouseMoveHandler); 24179 document.removeEventListener('mouseup', this.boundDocumentMouseUpHandler); 24180 this.isMouseHandlers = false; 24181 } 24182 24183 dispose() { 24184 this.removeBrowserObserver(); 24185 this.removeMouseHandlers(); 24186 this.rulerSweeper.remove(); 24187 } 24188 24189 } 24190 24191 function bp(referenceFrame, pixel) { 24192 return referenceFrame.start + pixel * referenceFrame.bpPerPixel; 24193 } 24194 24195 var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; 24196 24197 function createCommonjsModule(fn) { 24198 var module = { exports: {} }; 24199 return fn(module, module.exports), module.exports; 24200 } 24201 24202 var check = function (it) { 24203 return it && it.Math == Math && it; 24204 }; // https://github.com/zloirock/core-js/issues/86#issuecomment-115759028 24205 24206 24207 var global$1 = // eslint-disable-next-line es/no-global-this -- safe 24208 check(typeof globalThis == 'object' && globalThis) || check(typeof window == 'object' && window) || // eslint-disable-next-line no-restricted-globals -- safe 24209 check(typeof self == 'object' && self) || check(typeof commonjsGlobal == 'object' && commonjsGlobal) || // eslint-disable-next-line no-new-func -- fallback 24210 function () { 24211 return this; 24212 }() || Function('return this')(); 24213 24214 var FunctionPrototype$2 = Function.prototype; 24215 var bind$2 = FunctionPrototype$2.bind; 24216 var call$2 = FunctionPrototype$2.call; 24217 var callBind = bind$2 && bind$2.bind(call$2); 24218 var functionUncurryThis = bind$2 ? function (fn) { 24219 return fn && callBind(call$2, fn); 24220 } : function (fn) { 24221 return fn && function () { 24222 return call$2.apply(fn, arguments); 24223 }; 24224 }; 24225 24226 var fails = function (exec) { 24227 try { 24228 return !!exec(); 24229 } catch (error) { 24230 return true; 24231 } 24232 }; 24233 24234 // `IsCallable` abstract operation 24235 // https://tc39.es/ecma262/#sec-iscallable 24236 var isCallable = function (argument) { 24237 return typeof argument == 'function'; 24238 }; 24239 24240 var String$4 = global$1.String; 24241 24242 var tryToString = function (argument) { 24243 try { 24244 return String$4(argument); 24245 } catch (error) { 24246 return 'Object'; 24247 } 24248 }; 24249 24250 var TypeError$9 = global$1.TypeError; // `Assert: IsCallable(argument) is true` 24251 24252 var aCallable = function (argument) { 24253 if (isCallable(argument)) return argument; 24254 throw TypeError$9(tryToString(argument) + ' is not a function'); 24255 }; 24256 24257 var ceil = Math.ceil; 24258 var floor$1 = Math.floor; // `ToIntegerOrInfinity` abstract operation 24259 // https://tc39.es/ecma262/#sec-tointegerorinfinity 24260 24261 var toIntegerOrInfinity = function (argument) { 24262 var number = +argument; // eslint-disable-next-line no-self-compare -- safe 24263 24264 return number !== number || number === 0 ? 0 : (number > 0 ? floor$1 : ceil)(number); 24265 }; 24266 24267 var max$1 = Math.max; 24268 var min$1 = Math.min; // Helper for a popular repeating case of the spec: 24269 // Let integer be ? ToInteger(index). 24270 // If integer < 0, let result be max((length + integer), 0); else let result be min(integer, length). 24271 24272 var toAbsoluteIndex = function (index, length) { 24273 var integer = toIntegerOrInfinity(index); 24274 return integer < 0 ? max$1(integer + length, 0) : min$1(integer, length); 24275 }; 24276 24277 var min = Math.min; // `ToLength` abstract operation 24278 // https://tc39.es/ecma262/#sec-tolength 24279 24280 var toLength = function (argument) { 24281 return argument > 0 ? min(toIntegerOrInfinity(argument), 0x1FFFFFFFFFFFFF) : 0; // 2 ** 53 - 1 == 9007199254740991 24282 }; 24283 24284 // https://tc39.es/ecma262/#sec-lengthofarraylike 24285 24286 var lengthOfArrayLike = function (obj) { 24287 return toLength(obj.length); 24288 }; 24289 24290 var call$1 = Function.prototype.call; 24291 var functionCall = call$1.bind ? call$1.bind(call$1) : function () { 24292 return call$1.apply(call$1, arguments); 24293 }; 24294 24295 var isObject = function (it) { 24296 return typeof it == 'object' ? it !== null : isCallable(it); 24297 }; 24298 24299 var aFunction = function (argument) { 24300 return isCallable(argument) ? argument : undefined; 24301 }; 24302 24303 var getBuiltIn = function (namespace, method) { 24304 return arguments.length < 2 ? aFunction(global$1[namespace]) : global$1[namespace] && global$1[namespace][method]; 24305 }; 24306 24307 var objectIsPrototypeOf = functionUncurryThis({}.isPrototypeOf); 24308 24309 var engineUserAgent = getBuiltIn('navigator', 'userAgent') || ''; 24310 24311 var process$2 = global$1.process; 24312 var Deno = global$1.Deno; 24313 var versions = process$2 && process$2.versions || Deno && Deno.version; 24314 var v8 = versions && versions.v8; 24315 var match, version; 24316 24317 if (v8) { 24318 match = v8.split('.'); // in old Chrome, versions of V8 isn't V8 = Chrome / 10 24319 // but their correct versions are not interesting for us 24320 24321 version = match[0] > 0 && match[0] < 4 ? 1 : +(match[0] + match[1]); 24322 } // BrowserFS NodeJS `process` polyfill incorrectly set `.v8` to `0.0` 24323 // so check `userAgent` even if `.v8` exists, but 0 24324 24325 24326 if (!version && engineUserAgent) { 24327 match = engineUserAgent.match(/Edge\/(\d+)/); 24328 24329 if (!match || match[1] >= 74) { 24330 match = engineUserAgent.match(/Chrome\/(\d+)/); 24331 if (match) version = +match[1]; 24332 } 24333 } 24334 24335 var engineV8Version = version; 24336 24337 /* eslint-disable es/no-symbol -- required for testing */ 24338 24339 var nativeSymbol = !!Object.getOwnPropertySymbols && !fails(function () { 24340 var symbol = Symbol(); // Chrome 38 Symbol has incorrect toString conversion
24341 // `get-own-property-symbols` polyfill symbols converted to object are not Symbol instances 24342 24343 return !String(symbol) || !(Object(symbol) instanceof Symbol) || // Chrome 38-40 symbols are not inherited from DOM collections prototypes to instances 24344 !Symbol.sham && engineV8Version && engineV8Version < 41; 24345 }); 24346 24347 /* eslint-disable es/no-symbol -- required for testing */ 24348 var useSymbolAsUid = nativeSymbol && !Symbol.sham && typeof Symbol.iterator == 'symbol'; 24349 24350 var Object$5 = global$1.Object; 24351 var isSymbol = useSymbolAsUid ? function (it) { 24352 return typeof it == 'symbol'; 24353 } : function (it) { 24354 var $Symbol = getBuiltIn('Symbol'); 24355 return isCallable($Symbol) && objectIsPrototypeOf($Symbol.prototype, Object$5(it)); 24356 }; 24357 24358 // https://tc39.es/ecma262/#sec-getmethod 24359 24360 var getMethod = function (V, P) { 24361 var func = V[P]; 24362 return func == null ? undefined : aCallable(func); 24363 }; 24364 24365 var TypeError$8 = global$1.TypeError; // `OrdinaryToPrimitive` abstract operation 24366 // https://tc39.es/ecma262/#sec-ordinarytoprimitive 24367 24368 var ordinaryToPrimitive = function (input, pref) { 24369 var fn, val; 24370 if (pref === 'string' && isCallable(fn = input.toString) && !isObject(val = functionCall(fn, input))) return val; 24371 if (isCallable(fn = input.valueOf) && !isObject(val = functionCall(fn, input))) return val; 24372 if (pref !== 'string' && isCallable(fn = input.toString) && !isObject(val = functionCall(fn, input))) return val; 24373 throw TypeError$8("Can't convert object to primitive value"); 24374 }; 24375 24376 var defineProperty$1 = Object.defineProperty; 24377 24378 var setGlobal = function (key, value) { 24379 try { 24380 defineProperty$1(global$1, key, { 24381 value: value, 24382 configurable: true, 24383 writable: true 24384 }); 24385 } catch (error) { 24386 global$1[key] = value; 24387 } 24388 24389 return value; 24390 }; 24391 24392 var SHARED = '__core-js_shared__'; 24393 var store$1 = global$1[SHARED] || setGlobal(SHARED, {}); 24394 var sharedStore = store$1; 24395 24396 var shared = createCommonjsModule(function (module) { 24397 (module.exports = function (key, value) { 24398 return sharedStore[key] || (sharedStore[key] = value !== undefined ? value : {}); 24399 })('versions', []).push({ 24400 version: '3.19.3', 24401 mode: 'global', 24402 copyright: '© 2021 Denis Pushkarev (zloirock.ru)' 24403 }); 24404 }); 24405 24406 var TypeError$7 = global$1.TypeError; // `RequireObjectCoercible` abstract operation 24407 // https://tc39.es/ecma262/#sec-requireobjectcoercible 24408 24409 var requireObjectCoercible = function (it) { 24410 if (it == undefined) throw TypeError$7("Can't call method on " + it); 24411 return it; 24412 }; 24413 24414 var Object$4 = global$1.Object; // `ToObject` abstract operation 24415 // https://tc39.es/ecma262/#sec-toobject 24416 24417 var toObject = function (argument) { 24418 return Object$4(requireObjectCoercible(argument)); 24419 }; 24420 24421 var hasOwnProperty = functionUncurryThis({}.hasOwnProperty); // `HasOwnProperty` abstract operation 24422 // https://tc39.es/ecma262/#sec-hasownproperty 24423 24424 var hasOwnProperty_1 = Object.hasOwn || function hasOwn(it, key) { 24425 return hasOwnProperty(toObject(it), key); 24426 }; 24427 24428 var id = 0; 24429 var postfix = Math.random(); 24430 var toString$1 = functionUncurryThis(1.0.toString); 24431 24432 var uid = function (key) { 24433 return 'Symbol(' + (key === undefined ? '' : key) + ')_' + toString$1(++id + postfix, 36); 24434 }; 24435 24436 var WellKnownSymbolsStore = shared('wks'); 24437 var Symbol$1 = global$1.Symbol; 24438 var symbolFor = Symbol$1 && Symbol$1['for']; 24439 var createWellKnownSymbol = useSymbolAsUid ? Symbol$1 : Symbol$1 && Symbol$1.withoutSetter || uid; 24440 24441 var wellKnownSymbol = function (name) { 24442 if (!hasOwnProperty_1(WellKnownSymbolsStore, name) || !(nativeSymbol || typeof WellKnownSymbolsStore[name] == 'string')) { 24443 var description = 'Symbol.' + name; 24444 24445 if (nativeSymbol && hasOwnProperty_1(Symbol$1, name)) { 24446 WellKnownSymbolsStore[name] = Symbol$1[name]; 24447 } else if (useSymbolAsUid && symbolFor) { 24448 WellKnownSymbolsStore[name] = symbolFor(description); 24449 } else {
24450 WellKnownSymbolsStore[name] = createWellKnownSymbol(description); 24451 } 24452 } 24453 24454 return WellKnownSymbolsStore[name]; 24455 }; 24456 24457 var TypeError$6 = global$1.TypeError; 24458 var TO_PRIMITIVE = wellKnownSymbol('toPrimitive'); // `ToPrimitive` abstract operation 24459 // https://tc39.es/ecma262/#sec-toprimitive 24460 24461 var toPrimitive = function (input, pref) { 24462 if (!isObject(input) || isSymbol(input)) return input; 24463 var exoticToPrim = getMethod(input, TO_PRIMITIVE); 24464 var result; 24465 24466 if (exoticToPrim) { 24467 if (pref === undefined) pref = 'default'; 24468 result = functionCall(exoticToPrim, input, pref); 24469 if (!isObject(result) || isSymbol(result)) return result; 24470 throw TypeError$6("Can't convert object to primitive value"); 24471 } 24472 24473 if (pref === undefined) pref = 'number'; 24474 return ordinaryToPrimitive(input, pref); 24475 }; 24476 24477 // https://tc39.es/ecma262/#sec-topropertykey 24478 24479 var toPropertyKey = function (argument) { 24480 var key = toPrimitive(argument, 'string'); 24481 return isSymbol(key) ? key : key + ''; 24482 }; 24483 24484 var descriptors = !fails(function () { 24485 // eslint-disable-next-line es/no-object-defineproperty -- required for testing 24486 return Object.defineProperty({}, 1, { 24487 get: function () { 24488 return 7; 24489 } 24490 })[1] != 7; 24491 }); 24492 24493 var document$1 = global$1.document; // typeof document.createElement is 'object' in old IE 24494 24495 var EXISTS$1 = isObject(document$1) && isObject(document$1.createElement); 24496 24497 var documentCreateElement = function (it) { 24498 return EXISTS$1 ? document$1.createElement(it) : {}; 24499 }; 24500 24501 var ie8DomDefine = !descriptors && !fails(function () { 24502 // eslint-disable-next-line es/no-object-defineproperty -- requied for testing 24503 return Object.defineProperty(documentCreateElement('div'), 'a', { 24504 get: function () { 24505 return 7; 24506 } 24507 }).a != 7; 24508 }); 24509 24510 var String$3 = global$1.String; 24511 var TypeError$5 = global$1.TypeError; // `Assert: Type(argument) is Object` 24512 24513 var anObject = function (argument) { 24514 if (isObject(argument)) return argument; 24515 throw TypeError$5(String$3(argument) + ' is not an object'); 24516 }; 24517 24518 var TypeError$4 = global$1.TypeError; // eslint-disable-next-line es/no-object-defineproperty -- safe 24519 24520 var $defineProperty = Object.defineProperty; // `Object.defineProperty` method 24521 // https://tc39.es/ecma262/#sec-object.defineproperty 24522 24523 var f$4 = descriptors ? $defineProperty : function defineProperty(O, P, Attributes) { 24524 anObject(O); 24525 P = toPropertyKey(P); 24526 anObject(Attributes); 24527 if (ie8DomDefine) try { 24528 return $defineProperty(O, P, Attributes); 24529 } catch (error) { 24530 /* empty */ 24531 } 24532 if ('get' in Attributes || 'set' in Attributes) throw TypeError$4('Accessors not supported'); 24533 if ('value' in Attributes) O[P] = Attributes.value; 24534 return O; 24535 }; 24536 var objectDefineProperty = { 24537 f: f$4 24538 }; 24539 24540 var createPropertyDescriptor = function (bitmap, value) { 24541 return { 24542 enumerable: !(bitmap & 1), 24543 configurable: !(bitmap & 2), 24544 writable: !(bitmap & 4), 24545 value: value 24546 }; 24547 }; 24548 24549 var createProperty = function (object, key, value) { 24550 var propertyKey = toPropertyKey(key); 24551 if (propertyKey in object) objectDefineProperty.f(object, propertyKey, createPropertyDescriptor(0, value));else object[propertyKey] = value; 24552 }; 24553 24554 var Array$2 = global$1.Array; 24555 var max = Math.max; 24556 24557 var arraySliceSimple = function (O, start, end) { 24558 var length = lengthOfArrayLike(O); 24559 var k = toAbsoluteIndex(start, length); 24560 var fin = toAbsoluteIndex(end === undefined ? length : end, length); 24561 var result = Array$2(max(fin - k, 0)); 24562 24563 for (var n = 0; k < fin; k++, n++) createProperty(result, n, O[k]); 24564 24565 result.length = n; 24566 return result; 24567 }; 24568 24569 var floor = Math.floor; 24570 24571 var mergeSort = function (array, comparefn) { 24572 var length = array.length; 24573 var middle = floor(length / 2); 24574 return length < 8 ? insertionSort(array, comparefn) : merge(array, mergeSort(arraySliceSimple(array, 0, middle), comparefn), mergeSort(arraySliceSimple(array, middle), comparefn), comparefn); 24575 }; 24576 24577 var insertionSort = function (array, comparefn) { 24578 var length = array.length; 24579 var i = 1; 24580 var element, j; 24581 24582 while (i < length) { 24583 j = i; 24584 element = array[i]; 24585 24586 while (j && comparefn(array[j - 1], element) > 0) { 24587 array[j] = array[--j]; 24588 } 24589 24590 if (j !== i++) array[j] = element; 24591 } 24592 24593 return array; 24594 }; 24595 24596 var merge = function (array, left, right, comparefn) { 24597 var llength = left.length; 24598 var rlength = right.length; 24599 var lindex = 0; 24600 var rindex = 0; 24601 24602 while (lindex < llength || rindex < rlength) { 24603 array[lindex + rindex] = lindex < llength && rindex < rlength ? comparefn(left[lindex], right[rindex]) <= 0 ? left[lindex++] : right[rindex++] : lindex < llength ? left[lindex++] : right[rindex++]; 24604 } 24605 24606 return array; 24607 }; 24608 24609 var arraySort = mergeSort; 24610 24611 // eslint-disable-next-line es/no-typed-arrays -- safe 24612 var arrayBufferNative = typeof ArrayBuffer != 'undefined' && typeof DataView != 'undefined'; 24613 24614 var TO_STRING_TAG$2 = wellKnownSymbol('toStringTag'); 24615 var test = {}; 24616 test[TO_STRING_TAG$2] = 'z'; 24617 var toStringTagSupport = String(test) === '[object z]'; 24618 24619 var toString = functionUncurryThis({}.toString); 24620 var stringSlice = functionUncurryThis(''.slice); 24621 24622 var classofRaw = function (it) { 24623 return stringSlice(toString(it), 8, -1); 24624 }; 24625 24626 var TO_STRING_TAG$1 = wellKnownSymbol('toStringTag'); 24627 var Object$3 = global$1.Object; // ES3 wrong here 24628 24629 var CORRECT_ARGUMENTS = classofRaw(function () { 24630 return arguments; 24631 }()) == 'Arguments'; // fallback for IE11 Script Access Denied error 24632 24633 var tryGet = function (it, key) {
24634 try { 24635 return it[key]; 24636 } catch (error) { 24637 /* empty */ 24638 } 24639 }; // getting tag from ES6+ `Object.prototype.toString` 24640 24641 24642 var classof = toStringTagSupport ? classofRaw : function (it) { 24643 var O, tag, result; 24644 return it === undefined ? 'Undefined' : it === null ? 'Null' // @@toStringTag case 24645 : typeof (tag = tryGet(O = Object$3(it), TO_STRING_TAG$1)) == 'string' ? tag // builtinTag case 24646 : CORRECT_ARGUMENTS ? classofRaw(O) // ES3 arguments fallback 24647 : (result = classofRaw(O)) == 'Object' && isCallable(O.callee) ? 'Arguments' : result; 24648 }; 24649 24650 var createNonEnumerableProperty = descriptors ? function (object, key, value) { 24651 return objectDefineProperty.f(object, key, createPropertyDescriptor(1, value)); 24652 } : function (object, key, value) { 24653 object[key] = value; 24654 return object; 24655 }; 24656 24657 var functionToString = functionUncurryThis(Function.toString); // this helper broken in `[email protected]`, so we can't use `shared` helper 24658 24659 if (!isCallable(sharedStore.inspectSource)) { 24660 sharedStore.inspectSource = function (it) { 24661 return functionToString(it); 24662 }; 24663 } 24664 24665 var inspectSource = sharedStore.inspectSource; 24666 24667 var WeakMap$1 = global$1.WeakMap; 24668 var nativeWeakMap = isCallable(WeakMap$1) && /native code/.test(inspectSource(WeakMap$1)); 24669 24670 var keys = shared('keys'); 24671 24672 var sharedKey = function (key) { 24673 return keys[key] || (keys[key] = uid(key)); 24674 }; 24675 24676 var hiddenKeys$1 = {}; 24677 24678 var OBJECT_ALREADY_INITIALIZED = 'Object already initialized'; 24679 var TypeError$3 = global$1.TypeError; 24680 var WeakMap = global$1.WeakMap; 24681 var set$1, get, has; 24682 24683 var enforce = function (it) { 24684 return has(it) ? get(it) : set$1(it, {}); 24685 }; 24686 24687 var getterFor = function (TYPE) { 24688 return function (it) { 24689 var state; 24690 24691 if (!isObject(it) || (state = get(it)).type !== TYPE) { 24692 throw TypeError$3('Incompatible receiver, ' + TYPE + ' required'); 24693 } 24694 24695 return state; 24696 }; 24697 }; 24698 24699 if (nativeWeakMap || sharedStore.state) { 24700 var store = sharedStore.state || (sharedStore.state = new WeakMap()); 24701 var wmget = functionUncurryThis(store.get); 24702 var wmhas = functionUncurryThis(store.has); 24703 var wmset = functionUncurryThis(store.set); 24704 24705 set$1 = function (it, metadata) { 24706 if (wmhas(store, it)) throw new TypeError$3(OBJECT_ALREADY_INITIALIZED); 24707 metadata.facade = it; 24708 wmset(store, it, metadata); 24709 return metadata; 24710 }; 24711 24712 get = function (it) { 24713 return wmget(store, it) || {}; 24714 }; 24715 24716 has = function (it) { 24717 return wmhas(store, it); 24718 }; 24719 } else { 24720 var STATE = sharedKey('state'); 24721 hiddenKeys$1[STATE] = true; 24722 24723 set$1 = function (it, metadata) { 24724 if (hasOwnProperty_1(it, STATE)) throw new TypeError$3(OBJECT_ALREADY_INITIALIZED); 24725 metadata.facade = it; 24726 createNonEnumerableProperty(it, STATE, metadata); 24727 return metadata; 24728 }; 24729 24730 get = function (it) { 24731 return hasOwnProperty_1(it, STATE) ? it[STATE] : {}; 24732 }; 24733 24734 has = function (it) { 24735 return hasOwnProperty_1(it, STATE); 24736 }; 24737 } 24738 24739 var internalState = { 24740 set: set$1, 24741 get: get, 24742 has: has, 24743 enforce: enforce, 24744 getterFor: getterFor 24745 }; 24746 24747 var FunctionPrototype$1 = Function.prototype; // eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe 24748 24749 var getDescriptor = descriptors && Object.getOwnPropertyDescriptor; 24750 var EXISTS = hasOwnProperty_1(FunctionPrototype$1, 'name'); // additional protection from minified / mangled / dropped function names 24751 24752 var PROPER = EXISTS && function something() { 24753 /* empty */ 24754 }.name === 'something'; 24755 24756 var CONFIGURABLE = EXISTS && (!descriptors || descriptors && getDescriptor(FunctionPrototype$1, 'name').configurable); 24757 var functionName = { 24758 EXISTS: EXISTS, 24759 PROPER: PROPER, 24760 CONFIGURABLE: CONFIGURABLE 24761 }; 24762 24763 var redefine = createCommonjsModule(function (module) { 24764 var CONFIGURABLE_FUNCTION_NAME = functionName.CONFIGURABLE; 24765 var getInternalState = internalState.get; 24766 var enforceInternalState = internalState.enforce;
24767 var TEMPLATE = String(String).split('String'); 24768 (module.exports = function (O, key, value, options) { 24769 var unsafe = options ? !!options.unsafe : false; 24770 var simple = options ? !!options.enumerable : false; 24771 var noTargetGet = options ? !!options.noTargetGet : false; 24772 var name = options && options.name !== undefined ? options.name : key; 24773 var state; 24774 24775 if (isCallable(value)) { 24776 if (String(name).slice(0, 7) === 'Symbol(') { 24777 name = '[' + String(name).replace(/^Symbol\(([^)]*)\)/, '$1') + ']'; 24778 } 24779 24780 if (!hasOwnProperty_1(value, 'name') || CONFIGURABLE_FUNCTION_NAME && value.name !== name) { 24781 createNonEnumerableProperty(value, 'name', name); 24782 } 24783 24784 state = enforceInternalState(value); 24785 24786 if (!state.source) { 24787 state.source = TEMPLATE.join(typeof name == 'string' ? name : ''); 24788 } 24789 } 24790 24791 if (O === global$1) { 24792 if (simple) O[key] = value;else setGlobal(key, value); 24793 return; 24794 } else if (!unsafe) { 24795 delete O[key]; 24796 } else if (!noTargetGet && O[key]) { 24797 simple = true; 24798 } 24799 24800 if (simple) O[key] = value;else createNonEnumerableProperty(O, key, value); // add fake Function#toString for correct work wrapped methods / constructors with methods like LoDash isNative 24801 })(Function.prototype, 'toString', function toString() { 24802 return isCallable(this) && getInternalState(this).source || inspectSource(this); 24803 }); 24804 }); 24805 24806 var correctPrototypeGetter = !fails(function () { 24807 function F() { 24808 /* empty */ 24809 } 24810 24811 F.prototype.constructor = null; // eslint-disable-next-line es/no-object-getprototypeof -- required for testing 24812 24813 return Object.getPrototypeOf(new F()) !== F.prototype; 24814 }); 24815 24816 var IE_PROTO = sharedKey('IE_PROTO'); 24817 var Object$2 = global$1.Object; 24818 var ObjectPrototype$1 = Object$2.prototype; // `Object.getPrototypeOf` method 24819 // https://tc39.es/ecma262/#sec-object.getprototypeof 24820 24821 var objectGetPrototypeOf = correctPrototypeGetter ? Object$2.getPrototypeOf : function (O) { 24822 var object = toObject(O); 24823 if (hasOwnProperty_1(object, IE_PROTO)) return object[IE_PROTO]; 24824 var constructor = object.constructor; 24825 24826 if (isCallable(constructor) && object instanceof constructor) { 24827 return constructor.prototype; 24828 } 24829 24830 return object instanceof Object$2 ? ObjectPrototype$1 : null; 24831 }; 24832 24833 var String$2 = global$1.String; 24834 var TypeError$2 = global$1.TypeError; 24835 24836 var aPossiblePrototype = function (argument) { 24837 if (typeof argument == 'object' || isCallable(argument)) return argument; 24838 throw TypeError$2("Can't set " + String$2(argument) + ' as a prototype'); 24839 }; 24840 24841 /* eslint-disable no-proto -- safe */ 24842 // https://tc39.es/ecma262/#sec-object.setprototypeof 24843 // Works with __proto__ only. Old v8 can't work with null proto objects. 24844 // eslint-disable-next-line es/no-object-setprototypeof -- safe 24845 24846 var objectSetPrototypeOf = Object.setPrototypeOf || ('__proto__' in {} ? function () { 24847 var CORRECT_SETTER = false; 24848 var test = {}; 24849 var setter; 24850 24851 try { 24852 // eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe 24853 setter = functionUncurryThis(Object.getOwnPropertyDescriptor(Object.prototype, '__proto__').set); 24854 setter(test, []); 24855 CORRECT_SETTER = test instanceof Array; 24856 } catch (error) { 24857 /* empty */ 24858 } 24859 24860 return function setPrototypeOf(O, proto) { 24861 anObject(O); 24862 aPossiblePrototype(proto); 24863 if (CORRECT_SETTER) setter(O, proto);else O.__proto__ = proto; 24864 return O; 24865 }; 24866 }() : undefined); 24867 24868 var defineProperty = objectDefineProperty.f; 24869 var Int8Array = global$1.Int8Array; 24870 var Int8ArrayPrototype = Int8Array && Int8Array.prototype; 24871 var Uint8ClampedArray = global$1.Uint8ClampedArray; 24872 var Uint8ClampedArrayPrototype = Uint8ClampedArray && Uint8ClampedArray.prototype; 24873 var TypedArray = Int8Array && objectGetPrototypeOf(Int8Array); 24874 var TypedArrayPrototype = Int8ArrayPrototype && objectGetPrototypeOf(Int8ArrayPrototype); 24875 var ObjectPrototype = Object.prototype; 24876 var TypeError$1 = global$1.TypeError; 24877 var TO_STRING_TAG = wellKnownSymbol('toStringTag'); 24878 var TYPED_ARRAY_TAG = uid('TYPED_ARRAY_TAG'); 24879 var TYPED_ARRAY_CONSTRUCTOR = uid('TYPED_ARRAY_CONSTRUCTOR'); // Fixing native typed arrays in Opera Presto crashes the browser, see #595 24880 24881 var NATIVE_ARRAY_BUFFER_VIEWS = arrayBufferNative && !!objectSetPrototypeOf && classof(global$1.opera) !== 'Opera'; 24882 var TYPED_ARRAY_TAG_REQIRED = false;
vendor: 5,883 bytes, lines 24883-25038
24883 var NAME, Constructor, Prototype; 24884 var TypedArrayConstructorsList = { 24885 Int8Array: 1, 24886 Uint8Array: 1, 24887 Uint8ClampedArray: 1, 24888 Int16Array: 2, 24889 Uint16Array: 2, 24890 Int32Array: 4, 24891 Uint32Array: 4, 24892 Float32Array: 4, 24893 Float64Array: 8 24894 }; 24895 var BigIntArrayConstructorsList = { 24896 BigInt64Array: 8, 24897 BigUint64Array: 8 24898 }; 24899 24900 var isView = function isView(it) { 24901 if (!isObject(it)) return false; 24902 var klass = classof(it); 24903 return klass === 'DataView' || hasOwnProperty_1(TypedArrayConstructorsList, klass) || hasOwnProperty_1(BigIntArrayConstructorsList, klass); 24904 }; 24905 24906 var isTypedArray = function (it) { 24907 if (!isObject(it)) return false; 24908 var klass = classof(it); 24909 return hasOwnProperty_1(TypedArrayConstructorsList, klass) || hasOwnProperty_1(BigIntArrayConstructorsList, klass); 24910 }; 24911 24912 var aTypedArray$1 = function (it) { 24913 if (isTypedArray(it)) return it; 24914 throw TypeError$1('Target is not a typed array'); 24915 }; 24916 24917 var aTypedArrayConstructor = function (C) { 24918 if (isCallable(C) && (!objectSetPrototypeOf || objectIsPrototypeOf(TypedArray, C))) return C; 24919 throw TypeError$1(tryToString(C) + ' is not a typed array constructor'); 24920 }; 24921 24922 var exportTypedArrayMethod$1 = function (KEY, property, forced) { 24923 if (!descriptors) return; 24924 if (forced) for (var ARRAY in TypedArrayConstructorsList) { 24925 var TypedArrayConstructor = global$1[ARRAY]; 24926 if (TypedArrayConstructor && hasOwnProperty_1(TypedArrayConstructor.prototype, KEY)) try { 24927 delete TypedArrayConstructor.prototype[KEY]; 24928 } catch (error) { 24929 /* empty */ 24930 } 24931 } 24932 24933 if (!TypedArrayPrototype[KEY] || forced) { 24934 redefine(TypedArrayPrototype, KEY, forced ? property : NATIVE_ARRAY_BUFFER_VIEWS && Int8ArrayPrototype[KEY] || property); 24935 } 24936 }; 24937 24938 var exportTypedArrayStaticMethod = function (KEY, property, forced) { 24939 var ARRAY, TypedArrayConstructor; 24940 if (!descriptors) return; 24941 24942 if (objectSetPrototypeOf) { 24943 if (forced) for (ARRAY in TypedArrayConstructorsList) { 24944 TypedArrayConstructor = global$1[ARRAY]; 24945 if (TypedArrayConstructor && hasOwnProperty_1(TypedArrayConstructor, KEY)) try { 24946 delete TypedArrayConstructor[KEY]; 24947 } catch (error) { 24948 /* empty */ 24949 } 24950 } 24951 24952 if (!TypedArray[KEY] || forced) { 24953 // V8 ~ Chrome 49-50 `%TypedArray%` methods are non-writable non-configurable 24954 try { 24955 return redefine(TypedArray, KEY, forced ? property : NATIVE_ARRAY_BUFFER_VIEWS && TypedArray[KEY] || property); 24956 } catch (error) { 24957 /* empty */ 24958 } 24959 } else return; 24960 } 24961 24962 for (ARRAY in TypedArrayConstructorsList) { 24963 TypedArrayConstructor = global$1[ARRAY]; 24964 24965 if (TypedArrayConstructor && (!TypedArrayConstructor[KEY] || forced)) { 24966 redefine(TypedArrayConstructor, KEY, property); 24967 } 24968 } 24969 }; 24970 24971 for (NAME in TypedArrayConstructorsList) { 24972 Constructor = global$1[NAME]; 24973 Prototype = Constructor && Constructor.prototype; 24974 if (Prototype) createNonEnumerableProperty(Prototype, TYPED_ARRAY_CONSTRUCTOR, Constructor);else NATIVE_ARRAY_BUFFER_VIEWS = false; 24975 } 24976 24977 for (NAME in BigIntArrayConstructorsList) { 24978 Constructor = global$1[NAME]; 24979 Prototype = Constructor && Constructor.prototype; 24980 if (Prototype) createNonEnumerableProperty(Prototype, TYPED_ARRAY_CONSTRUCTOR, Constructor); 24981 } // WebKit bug - typed arrays constructors prototype is Object.prototype 24982 24983 24984 if (!NATIVE_ARRAY_BUFFER_VIEWS || !isCallable(TypedArray) || TypedArray === Function.prototype) { 24985 // eslint-disable-next-line no-shadow -- safe 24986 TypedArray = function TypedArray() { 24987 throw TypeError$1('Incorrect invocation'); 24988 }; 24989 24990 if (NATIVE_ARRAY_BUFFER_VIEWS) for (NAME in TypedArrayConstructorsList) { 24991 if (global$1[NAME]) objectSetPrototypeOf(global$1[NAME], TypedArray); 24992 } 24993 } 24994 24995 if (!NATIVE_ARRAY_BUFFER_VIEWS || !TypedArrayPrototype || TypedArrayPrototype === ObjectPrototype) { 24996 TypedArrayPrototype = TypedArray.prototype; 24997 if (NATIVE_ARRAY_BUFFER_VIEWS) for (NAME in TypedArrayConstructorsList) { 24998 if (global$1[NAME]) objectSetPrototypeOf(global$1[NAME].prototype, TypedArrayPrototype); 24999 } 25000 } // WebKit bug - one more object in Uint8ClampedArray prototype chain 25001 25002 25003 if (NATIVE_ARRAY_BUFFER_VIEWS && objectGetPrototypeOf(Uint8ClampedArrayPrototype) !== TypedArrayPrototype) { 25004 objectSetPrototypeOf(Uint8ClampedArrayPrototype, TypedArrayPrototype); 25005 } 25006 25007 if (descriptors && !hasOwnProperty_1(TypedArrayPrototype, TO_STRING_TAG)) { 25008 TYPED_ARRAY_TAG_REQIRED = true; 25009 defineProperty(TypedArrayPrototype, TO_STRING_TAG, { 25010 get: function () { 25011 return isObject(this) ? this[TYPED_ARRAY_TAG] : undefined; 25012 } 25013 }); 25014 25015 for (NAME in TypedArrayConstructorsList) if (global$1[NAME]) { 25016 createNonEnumerableProperty(global$1[NAME], TYPED_ARRAY_TAG, NAME); 25017 } 25018 } 25019 25020 var arrayBufferViewCore = { 25021 NATIVE_ARRAY_BUFFER_VIEWS: NATIVE_ARRAY_BUFFER_VIEWS, 25022 TYPED_ARRAY_CONSTRUCTOR: TYPED_ARRAY_CONSTRUCTOR, 25023 TYPED_ARRAY_TAG: TYPED_ARRAY_TAG_REQIRED && TYPED_ARRAY_TAG, 25024 aTypedArray: aTypedArray$1, 25025 aTypedArrayConstructor: aTypedArrayConstructor, 25026 exportTypedArrayMethod: exportTypedArrayMethod$1, 25027 exportTypedArrayStaticMethod: exportTypedArrayStaticMethod, 25028 isView: isView, 25029 isTypedArray: isTypedArray, 25030 TypedArray: TypedArray, 25031 TypedArrayPrototype: TypedArrayPrototype 25032 }; 25033 25034 var firefox = engineUserAgent.match(/firefox\/(\d+)/i); 25035 var engineFfVersion = !!firefox && +firefox[1]; 25036 25037 var engineIsIeOrEdge = /MSIE|Trident/.test(engineUserAgent); 25038
25039 var webkit = engineUserAgent.match(/AppleWebKit\/(\d+)\./); 25040 var engineWebkitVersion = !!webkit && +webkit[1]; 25041 25042 var Array$1 = global$1.Array; 25043 var aTypedArray = arrayBufferViewCore.aTypedArray; 25044 var exportTypedArrayMethod = arrayBufferViewCore.exportTypedArrayMethod; 25045 var Uint16Array$1 = global$1.Uint16Array; 25046 var un$Sort = Uint16Array$1 && functionUncurryThis(Uint16Array$1.prototype.sort); // WebKit 25047 25048 var ACCEPT_INCORRECT_ARGUMENTS = !!un$Sort && !(fails(function () { 25049 un$Sort(new Uint16Array$1(2), null); 25050 }) && fails(function () { 25051 un$Sort(new Uint16Array$1(2), {}); 25052 })); 25053 var STABLE_SORT = !!un$Sort && !fails(function () { 25054 // feature detection can be too slow, so check engines versions 25055 if (engineV8Version) return engineV8Version < 74; 25056 if (engineFfVersion) return engineFfVersion < 67; 25057 if (engineIsIeOrEdge) return true; 25058 if (engineWebkitVersion) return engineWebkitVersion < 602; 25059 var array = new Uint16Array$1(516); 25060 var expected = Array$1(516); 25061 var index, mod; 25062 25063 for (index = 0; index < 516; index++) { 25064 mod = index % 4; 25065 array[index] = 515 - index; 25066 expected[index] = index - 2 * mod + 3; 25067 } 25068 25069 un$Sort(array, function (a, b) { 25070 return (a / 4 | 0) - (b / 4 | 0); 25071 }); 25072 25073 for (index = 0; index < 516; index++) { 25074 if (array[index] !== expected[index]) return true; 25075 } 25076 }); 25077 25078 var getSortCompare = function (comparefn) { 25079 return function (x, y) { 25080 if (comparefn !== undefined) return +comparefn(x, y) || 0; // eslint-disable-next-line no-self-compare -- NaN check 25081 25082 if (y !== y) return -1; // eslint-disable-next-line no-self-compare -- NaN check 25083 25084 if (x !== x) return 1; 25085 if (x === 0 && y === 0) return 1 / x > 0 && 1 / y < 0 ? 1 : -1; 25086 return x > y; 25087 }; 25088 }; // `%TypedArray%.prototype.sort` method 25089 // https://tc39.es/ecma262/#sec-%typedarray%.prototype.sort 25090 25091 25092 exportTypedArrayMethod('sort', function sort(comparefn) { 25093 if (comparefn !== undefined) aCallable(comparefn); 25094 if (STABLE_SORT) return un$Sort(this, comparefn); 25095 return arraySort(aTypedArray(this), getSortCompare(comparefn)); 25096 }, !STABLE_SORT || ACCEPT_INCORRECT_ARGUMENTS); 25097 25098 /* 25099 * The MIT License (MIT) 25100 * 25101 * Copyright (c) 2016 University of California San Diego 25102 * Author: Jim Robinson 25103 * 25104 * Permission is hereby granted, free of charge, to any person obtaining a copy 25105 * of this software and associated documentation files (the "Software"), to deal 25106 * in the Software without restriction, including without limitation the rights 25107 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 25108 * copies of the Software, and to permit persons to whom the Software is 25109 * furnished to do so, subject to the following conditions: 25110 * 25111 * The above copyright notice and this permission notice shall be included in 25112 * all copies or substantial portions of the Software. 25113 * 25114 * 25115 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25116 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25117 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25118 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25119 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25120 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25121 * THE SOFTWARE. 25122 */ 25123 class PairedAlignment { 25124 constructor(firstAlignment) { 25125 this.paired = true; 25126 this.firstAlignment = firstAlignment; 25127 this.chr = firstAlignment.chr; 25128 this.readName = firstAlignment.readName; 25129 25130 if (firstAlignment.start < firstAlignment.mate.position) { 25131 this.start = firstAlignment.start; 25132 this.scStart = firstAlignment.scStart; 25133 this.connectingStart = firstAlignment.start + firstAlignment.lengthOnRef; 25134 this.connectingEnd = firstAlignment.mate.position; 25135 } else { 25136 this.start = firstAlignment.mate.position; 25137 this.scStart = this.start; 25138 this.connectingStart = firstAlignment.mate.position;
25139 this.connectingEnd = firstAlignment.start; 25140 } 25141 25142 this.end = Math.max(firstAlignment.mate.position, firstAlignment.start + firstAlignment.lengthOnRef); // Approximate 25143 25144 this.lengthOnRef = this.end - this.start; 25145 let scEnd = Math.max(this.end, firstAlignment.scStart + firstAlignment.scLengthOnRef); 25146 this.scLengthOnRef = scEnd - this.scStart; 25147 } 25148 25149 setSecondAlignment(secondAlignment) { 25150 // TODO -- check the chrs are equal, error otherwise 25151 this.secondAlignment = secondAlignment; 25152 const firstAlignment = this.firstAlignment; 25153 25154 if (secondAlignment.start > firstAlignment.start) { 25155 this.connectingEnd = secondAlignment.start; 25156 } else { 25157 this.connectingStart = secondAlignment.start + secondAlignment.lengthOnRef; 25158 } 25159 25160 this.start = Math.min(firstAlignment.start, secondAlignment.start); 25161 this.end = Math.max(firstAlignment.start + firstAlignment.lengthOnRef, secondAlignment.start + secondAlignment.lengthOnRef); 25162 this.lengthOnRef = this.end - this.start; 25163 this.scStart = Math.min(firstAlignment.scStart, secondAlignment.scStart); 25164 const scEnd = Math.max(firstAlignment.scStart + firstAlignment.scLengthOnRef, secondAlignment.scStart + secondAlignment.scLengthOnRef); 25165 this.scLengthOnRef = scEnd - this.scStart; 25166 } 25167 25168 containsLocation(genomicLocation, showSoftClips) { 25169 const s = showSoftClips ? this.scStart : this.start; 25170 const l = showSoftClips ? this.scLengthOnRef : this.lengthOnRef; 25171 return genomicLocation >= s && genomicLocation <= s + l; 25172 } 25173 25174 alignmentContaining(genomicLocation, showSoftClips) { 25175 if (this.firstAlignment.containsLocation(genomicLocation, showSoftClips)) { 25176 return this.firstAlignment; 25177 } else if (this.secondAlignment && this.secondAlignment.containsLocation(genomicLocation, showSoftClips)) { 25178 return this.secondAlignment; 25179 } else { 25180 return undefined; 25181 } 25182 } 25183 25184 popupData(genomicLocation) { 25185 let nameValues = this.firstAlignment.popupData(genomicLocation); 25186 25187 if (this.secondAlignment) { 25188 nameValues.push("-------------------------------"); 25189 nameValues = nameValues.concat(this.secondAlignment.popupData(genomicLocation)); 25190 } 25191 25192 return nameValues; 25193 } 25194 25195 isPaired() { 25196 return true; // By definition 25197 } 25198 25199 firstOfPairStrand() { 25200 if (this.firstAlignment.isFirstOfPair()) { 25201 return this.firstAlignment.strand; 25202 } else if (this.secondAlignment && this.secondAlignment.isFirstOfPair()) { 25203 return this.secondAlignment.strand; 25204 } else { 25205 return this.firstAlignment.mate.strand; // Assumption is mate is first-of-pair 25206 } 25207 } 25208 25209 } 25210 25211 /* 25212 * The MIT License (MIT) 25213 * 25214 * Copyright (c) 2014 Broad Institute 25215 * 25216 * Permission is hereby granted, free of charge, to any person obtaining a copy 25217 * of this software and associated documentation files (the "Software"), to deal 25218 * in the Software without restriction, including without limitation the rights 25219 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 25220 * copies of the Software, and to permit persons to whom the Software is 25221 * furnished to do so, subject to the following conditions: 25222 * 25223 * The above copyright notice and this permission notice shall be included in 25224 * all copies or substantial portions of the Software. 25225 * 25226 * 25227 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25228 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25229 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25230 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25231 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25232 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25233 * THE SOFTWARE. 25234 */ 25235 const isString$2 = isString$3; 25236 const hashCode = hashCode$1; 25237 25238 class BamAlignmentRow { 25239 constructor() { 25240 this.alignments = []; 25241 this.score = undefined; 25242 } 25243 25244 findAlignment(genomicLocation) { 25245 const alignmentContains = (a, genomicLocation) => { 25246 return genomicLocation >= a.start && genomicLocation < a.start + a.lengthOnRef; 25247 }; // find single alignment that overlaps sort location 25248 25249 25250 let centerAlignment; 25251 25252 for (let i = 0; i < this.alignments.length; i++) { 25253 const a = this.alignments[i]; 25254 25255 if (genomicLocation >= a.start && genomicLocation < a.start + a.lengthOnRef) { 25256 if (a.paired) { 25257 if (a.firstAlignment && alignmentContains(a.firstAlignment, genomicLocation)) { 25258 centerAlignment = a.firstAlignment; 25259 } else if (a.secondAlignment && alignmentContains(a.secondAlignment, genomicLocation)) { 25260 centerAlignment = a.secondAlignment; 25261 } 25262 } else { 25263 centerAlignment = a; 25264 } 25265 25266 break; 25267 } 25268 } 25269 25270 return centerAlignment; 25271 } 25272 25273 updateScore(options, alignmentContainer) { 25274 this.score = this.calculateScore(options, alignmentContainer); 25275 } 25276 25277 calculateScore(_ref, alignmentContainer) { 25278 let { 25279 position, 25280 option, 25281 direction, 25282 tag 25283 } = _ref; 25284 if (!option) option = "BASE"; 25285 const alignment = this.findAlignment(position); 25286 25287 if (undefined === alignment) { 25288 return Number.MAX_VALUE * (direction ? 1 : -1); 25289 } 25290 25291 let mate; 25292 25293 switch (option) { 25294 case "NUCLEOTIDE": 25295 case "BASE": 25296 { 25297 return calculateBaseScore(alignment, alignmentContainer, position); 25298 } 25299 25300 case "STRAND":
25301 return alignment.strand ? 1 : -1; 25302 25303 case "START": 25304 return alignment.start; 25305 25306 case "TAG": 25307 { 25308 const tagValue = alignment.tags()[tag]; 25309 25310 if (tagValue !== undefined) { 25311 return isString$2(tagValue) ? hashCode(tagValue) : tagValue; 25312 } else { 25313 return Number.MAX_VALUE; 25314 } 25315 } 25316 25317 case "READ_NAME": 25318 return hashCode(alignment.readName); 25319 25320 case "INSERT_SIZE": 25321 return -Math.abs(alignment.fragmentLength); 25322 25323 case "GAP_SIZE": 25324 return -alignment.gapSizeAt(position); 25325 25326 case "MATE_CHR": 25327 mate = alignment.mate; 25328 25329 if (!mate) { 25330 return Number.MAX_VALUE; 25331 } else { 25332 if (mate.chr === alignment.chr) { 25333 return Number.MAX_VALUE - 1; 25334 } else { 25335 return hashCode(mate.chr); 25336 } 25337 } 25338 25339 case "MQ": 25340 return alignment.mq === undefined ? Number.MAX_VALUE : -alignment.mq; 25341 25342 default: 25343 return Number.MAX_VALUE; 25344 } 25345 25346 function calculateBaseScore(alignment, alignmentContainer, genomicLocation) { 25347 let reference; 25348 const idx = Math.floor(genomicLocation) - alignmentContainer.start; 25349 25350 if (idx < alignmentContainer.sequence.length) { 25351 reference = alignmentContainer.sequence.charAt(idx); 25352 } 25353 25354 if (!reference) { 25355 return 0; 25356 } 25357 25358 const base = alignment.readBaseAt(genomicLocation); 25359 const quality = alignment.readBaseQualityAt(genomicLocation); 25360 const coverageMap = alignmentContainer.coverageMap; 25361 const coverageMapIndex = Math.floor(genomicLocation - coverageMap.bpStart); 25362 const coverage = coverageMap.coverage[coverageMapIndex]; // Insertions. These are additive with base scores as they occur between bases, so you can have a 25363 // base mismatch AND an insertion 25364 25365 let baseScore = 0; 25366 25367 if (alignment.insertions) { 25368 for (let ins of alignment.insertions) { 25369 if (ins.start === genomicLocation) { 25370 baseScore = -coverage.ins; 25371 } 25372 } 25373 } 25374 25375 if (!base) { 25376 // Either deletion or skipped (splice junction) 25377 const delCount = coverage.del; 25378 25379 if (delCount > 0) { 25380 baseScore -= delCount; 25381 } else if (baseScore === 0) { 25382 // Don't modify insertion score, if any 25383 baseScore = 1; 25384 } 25385 } else { 25386 reference = reference.toUpperCase(); 25387 25388 if ('N' === base && baseScore === 0) { 25389 baseScore = 2; 25390 } else if ((reference === base || '=' === base) && baseScore === 0) { 25391 baseScore = 4 - quality / 1000; 25392 } else if ("X" === base || reference !== base) { 25393 const count = coverage["pos" + base] + coverage["neg" + base]; 25394 baseScore -= count + quality / 1000; 25395 } 25396 } 25397 25398 return baseScore; 25399 } 25400 } 25401 25402 } 25403 25404 function canBePaired(alignment) { 25405 return alignment.isPaired() && alignment.mate && alignment.isMateMapped() && alignment.chr === alignment.mate.chr && (alignment.isFirstOfPair() || alignment.isSecondOfPair()) && !(alignment.isSecondary() || alignment.isSupplementary()); 25406 } 25407 25408 function pairAlignments(rows) { 25409 const pairCache = {}; 25410 const result = []; 25411 25412 for (let row of rows) { 25413 for (let alignment of row.alignments) { 25414 if (canBePaired(alignment)) { 25415 let pairedAlignment = pairCache[alignment.readName]; 25416 25417 if (pairedAlignment) { 25418 pairedAlignment.setSecondAlignment(alignment); 25419 pairCache[alignment.readName] = undefined; // Don't need to track this anymore. 25420 } else { 25421 pairedAlignment = new PairedAlignment(alignment); 25422 pairCache[alignment.readName] = pairedAlignment; 25423 result.push(pairedAlignment); 25424 } 25425 } else { 25426 result.push(alignment); 25427 } 25428 } 25429 } 25430 25431 return result; 25432 } 25433 25434 function unpairAlignments(rows) { 25435 const result = []; 25436 25437 for (let row of rows) { 25438 for (let alignment of row.alignments) { 25439 if (alignment instanceof PairedAlignment) { 25440 if (alignment.firstAlignment) result.push(alignment.firstAlignment); // shouldn't need the null test 25441
25442 if (alignment.secondAlignment) result.push(alignment.secondAlignment); 25443 } else { 25444 result.push(alignment); 25445 } 25446 } 25447 } 25448 25449 return result; 25450 } 25451 25452 function packAlignmentRows(alignments, start, end, showSoftClips) { 25453 if (!alignments) { 25454 return undefined; 25455 } else if (alignments.length === 0) { 25456 return []; 25457 } else { 25458 alignments.sort(function (a, b) { 25459 return showSoftClips ? a.scStart - b.scStart : a.start - b.start; 25460 }); // bucketStart = Math.max(start, alignments[0].start); 25461 25462 const firstAlignment = alignments[0]; 25463 let bucketStart = Math.max(start, showSoftClips ? firstAlignment.scStart : firstAlignment.start); 25464 let nextStart = bucketStart; 25465 const bucketList = []; 25466 25467 for (let alignment of alignments) { 25468 //var buckListIndex = Math.max(0, alignment.start - bucketStart); 25469 const s = showSoftClips ? alignment.scStart : alignment.start; 25470 const buckListIndex = Math.max(0, s - bucketStart); 25471 25472 if (bucketList[buckListIndex] === undefined) { 25473 bucketList[buckListIndex] = []; 25474 } 25475 25476 bucketList[buckListIndex].push(alignment); 25477 } 25478 25479 let allocatedCount = 0; 25480 let lastAllocatedCount = 0; 25481 const packedAlignmentRows = []; 25482 const alignmentSpace = 2; 25483 25484 try { 25485 while (allocatedCount < alignments.length) { 25486 const alignmentRow = new BamAlignmentRow(); 25487 25488 while (nextStart <= end) { 25489 let bucket = undefined; 25490 let index; 25491 25492 while (!bucket && nextStart <= end) { 25493 index = nextStart - bucketStart; 25494 25495 if (bucketList[index] === undefined) { 25496 ++nextStart; // No alignments at this index 25497 } else { 25498 bucket = bucketList[index]; 25499 } 25500 } // while (bucket) 25501 25502 25503 if (!bucket) { 25504 break; 25505 } 25506 25507 const alignment = bucket.pop(); 25508 25509 if (0 === bucket.length) { 25510 bucketList[index] = undefined; 25511 } 25512 25513 alignmentRow.alignments.push(alignment); 25514 nextStart = showSoftClips ? alignment.scStart + alignment.scLengthOnRef + alignmentSpace : alignment.start + alignment.lengthOnRef + alignmentSpace; 25515 ++allocatedCount; 25516 } // while (nextStart) 25517 25518 25519 if (alignmentRow.alignments.length > 0) { 25520 packedAlignmentRows.push(alignmentRow); 25521 } 25522 25523 nextStart = bucketStart; 25524 if (allocatedCount === lastAllocatedCount) break; // Protect from infinite loops 25525 25526 lastAllocatedCount = allocatedCount; 25527 } // while (allocatedCount) 25528 25529 } catch (e) { 25530 console.error(e); 25531 throw e; 25532 } 25533 25534 return packedAlignmentRows; 25535 } 25536 } 25537 25538 /* 25539 * The MIT License (MIT) 25540 * 25541 * Copyright (c) 2016 University of California San Diego 25542 * Author: Jim Robinson 25543 * 25544 * Permission is hereby granted, free of charge, to any person obtaining a copy 25545 * of this software and associated documentation files (the "Software"), to deal 25546 * in the Software without restriction, including without limitation the rights 25547 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 25548 * copies of the Software, and to permit persons to whom the Software is 25549 * furnished to do so, subject to the following conditions: 25550 * 25551 * The above copyright notice and this permission notice shall be included in 25552 * all copies or substantial portions of the Software. 25553 * 25554 * 25555 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25556 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25557 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25558 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25559 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25560 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25561 * THE SOFTWARE. 25562 */ 25563 25564 class AlignmentContainer { 25565 constructor(chr, start, end, samplingWindowSize, samplingDepth, pairsSupported, alleleFreqThreshold) { 25566 this.chr = chr; 25567 this.start = Math.floor(start); 25568 this.end = Math.ceil(end); 25569 this.length = end - start; 25570 this.alleleFreqThreshold = alleleFreqThreshold === undefined ? 0.2 : alleleFreqThreshold; 25571 this.coverageMap = new CoverageMap(chr, start, end, this.alleleFreqThreshold); 25572 this.alignments = []; 25573 this.downsampledIntervals = []; 25574 this.samplingWindowSize = samplingWindowSize === undefined ? 100 : samplingWindowSize; 25575 this.samplingDepth = samplingDepth === undefined ? 1000 : samplingDepth; 25576 this.pairsSupported = pairsSupported === undefined ? true : pairsSupported; 25577 this.paired = false; // false until proven otherwise 25578 25579 this.pairsCache = {};
25579 // working cache of paired alignments by read name 25580 25581 this.downsampledReads = new Set(); 25582 this.currentBucket = new DownsampleBucket(this.start, this.start + this.samplingWindowSize, this); 25583 25584 this.filter = function filter(alignment) { 25585 // TODO -- pass this in 25586 return alignment.isMapped() && !alignment.isFailsVendorQualityCheck(); 25587 }; 25588 25589 this.pairedEndStats = new PairedEndStats(); 25590 } 25591 25592 push(alignment) { 25593 if (this.filter(alignment) === false) return; 25594 25595 if (alignment.isPaired()) { 25596 this.pairedEndStats.push(alignment); 25597 } 25598 25599 this.coverageMap.incCounts(alignment); // Count coverage before any downsampling 25600 25601 if (this.pairsSupported && this.downsampledReads.has(alignment.readName)) { 25602 return; // Mate already downsampled -- pairs are treated as a single alignment for downsampling 25603 } 25604 25605 if (alignment.start >= this.currentBucket.end) { 25606 this.finishBucket(); 25607 this.currentBucket = new DownsampleBucket(alignment.start, alignment.start + this.samplingWindowSize, this); 25608 } 25609 25610 this.currentBucket.addAlignment(alignment); 25611 } 25612 25613 forEach(callback) { 25614 this.alignments.forEach(callback); 25615 } 25616 25617 finish() { 25618 if (this.currentBucket !== undefined) { 25619 this.finishBucket(); 25620 } 25621 25622 this.alignments.sort(function (a, b) { 25623 return a.start - b.start; 25624 }); 25625 this.pairsCache = undefined; 25626 this.downsampledReads = undefined; 25627 this.pairedEndStats.compute(); 25628 } 25629 25630 contains(chr, start, end) { 25631 return this.chr === chr && this.start <= start && this.end >= end; 25632 } 25633 25634 hasDownsampledIntervals() { 25635 return this.downsampledIntervals && this.downsampledIntervals.length > 0; 25636 } 25637 25638 finishBucket() { 25639 this.alignments = this.alignments.concat(this.currentBucket.alignments); 25640 25641 if (this.currentBucket.downsampledCount > 0) { 25642 this.downsampledIntervals.push(new DownsampledInterval(this.currentBucket.start, this.currentBucket.end, this.currentBucket.downsampledCount)); 25643 } 25644 25645 this.paired = this.paired || this.currentBucket.paired; 25646 } 25647 25648 setViewAsPairs(bool) { 25649 let alignments; 25650 25651 if (bool) { 25652 alignments = pairAlignments(this.packedAlignmentRows); 25653 } else { 25654 alignments = unpairAlignments(this.packedAlignmentRows); 25655 } 25656 25657 this.packedAlignmentRows = packAlignmentRows(alignments, this.start, this.end); 25658 } 25659 25660 setShowSoftClips(bool) { 25661 const alignments = this.allAlignments(); 25662 this.packedAlignmentRows = packAlignmentRows(alignments, this.start, this.end, bool); 25663 } 25664 25665 repack(bpPerPixel, showSoftClips) { 25666 const alignments = this.allAlignments(); 25667 this.packedAlignmentRows = packAlignmentRows(alignments, this.start, this.end, showSoftClips); 25668 } 25669 25670 allAlignments() { 25671 const alignments = []; 25672 25673 for (let row of this.packedAlignmentRows) { 25674 for (let alignment of row.alignments) { 25675 alignments.push(alignment); 25676 } 25677 } 25678 25679 return alignments; 25680 } 25681 25682 getMax(start, end) { 25683 return this.coverageMap.getMax(start, end); 25684 } 25685 25686 } 25687 25688 class DownsampleBucket { 25689 constructor(start, end, alignmentContainer) { 25690 this.start = start; 25691 this.end = end; 25692 this.alignments = []; 25693 this.downsampledCount = 0; 25694 this.samplingDepth = alignmentContainer.samplingDepth; 25695 this.pairsSupported = alignmentContainer.pairsSupported; 25696 this.downsampledReads = alignmentContainer.downsampledReads; 25697 this.pairsCache = alignmentContainer.pairsCache; 25698 } 25699 25700 addAlignment(alignment) { 25701 var idx, replacedAlignment, pairedAlignment; 25702 25703 if (this.pairsSupported && canBePaired(alignment)) { 25704 pairedAlignment = this.pairsCache[alignment.readName]; 25705 25706 if (pairedAlignment) { 25707 // Not subject to downsampling, just update the existing alignment
25708 pairedAlignment.setSecondAlignment(alignment); 25709 this.pairsCache[alignment.readName] = undefined; // Don't need to track this anymore. NOTE: Don't "delete", causes runtime performance issues 25710 25711 return; 25712 } 25713 } 25714 25715 if (this.alignments.length < this.samplingDepth) { 25716 if (this.pairsSupported && canBePaired(alignment)) { 25717 // First alignment in a pair 25718 pairedAlignment = new PairedAlignment(alignment); 25719 this.paired = true; 25720 this.pairsCache[alignment.readName] = pairedAlignment; 25721 this.alignments.push(pairedAlignment); 25722 } else { 25723 this.alignments.push(alignment); 25724 } 25725 } else { 25726 idx = Math.floor(Math.random() * (this.samplingDepth + this.downsampledCount - 1)); 25727 25728 if (idx < this.samplingDepth) { 25729 // Keep the new item 25730 // idx = Math.floor(Math.random() * (this.alignments.length - 1)); 25731 replacedAlignment = this.alignments[idx]; // To be replaced 25732 25733 if (this.pairsSupported && canBePaired(alignment)) { 25734 if (this.pairsCache[replacedAlignment.readName] !== undefined) { 25735 this.pairsCache[replacedAlignment.readName] = undefined; 25736 } 25737 25738 pairedAlignment = new PairedAlignment(alignment); 25739 this.paired = true; 25740 this.pairsCache[alignment.readName] = pairedAlignment; 25741 this.alignments[idx] = pairedAlignment; 25742 } else { 25743 this.alignments[idx] = alignment; 25744 } 25745 25746 this.downsampledReads.add(replacedAlignment.readName); 25747 } else { 25748 this.downsampledReads.add(alignment.readName); 25749 } 25750 25751 this.downsampledCount++; 25752 } 25753 } 25754 25755 } 25756 25757 class CoverageMap { 25758 constructor(chr, start, end, alleleFreqThreshold) { 25759 this.chr = chr; 25760 this.bpStart = start; 25761 this.length = end - start; 25762 this.coverage = new Array(this.length); 25763 this.maximum = 0; 25764 this.threshold = alleleFreqThreshold; 25765 this.qualityWeight = true; 25766 } 25767 /** 25768 * Return the maximum coverage value between start and end. This is used for autoscaling. 25769 * @param start 25770 * @param end 25771 */ 25772 25773 25774 getMax(start, end) { 25775 let max = 0; 25776 const len = this.coverage.length; 25777 25778 for (let i = 0; i < len; i++) { 25779 const pos = this.bpStart + i; 25780 if (pos > end) break; 25781 const cov = this.coverage[i]; 25782 25783 if (pos >= start && cov) { 25784 max = Math.max(max, cov.total); 25785 } 25786 } 25787 25788 return max; 25789 } 25790 25791 incCounts(alignment) { 25792 var self = this; 25793 25794 if (alignment.blocks === undefined) { 25795 incBlockCount(alignment); 25796 } else { 25797 alignment.blocks.forEach(function (block) { 25798 incBlockCount(block); 25799 }); 25800 } 25801 25802 if (alignment.gaps) { 25803 for (let del of alignment.gaps) { 25804 if (del.type === 'D') { 25805 const offset = del.start - self.bpStart; 25806 25807 for (let i = offset; i < offset + del.len; i++) { 25808 if (i < 0) continue; 25809 25810 if (!this.coverage[i]) { 25811 this.coverage[i] = new Coverage(self.threshold); 25812 } 25813 25814 this.coverage[i].del++; 25815 } 25816 } 25817 } 25818 } 25819 25820 if (alignment.insertions) { 25821 for (let del of alignment.insertions) { 25822 const i = del.start - this.bpStart; 25823 if (i < 0) continue; 25824 25825 if (!this.coverage[i]) { 25826 this.coverage[i] = new Coverage(self.threshold); 25827 } 25828 25829 this.coverage[i].ins++; 25830 } 25831 } 25832 25833 function incBlockCount(block) { 25834 if ('S' === block.type) return; 25835 const seq = alignment.seq; 25836 const qual = alignment.qual; 25837 const seqOffset = block.seqOffset; 25838 25839 for (let i = block.start - self.bpStart, j = 0; j < block.len; i++, j++) { 25840 if (!self.coverage[i]) { 25841 self.coverage[i] = new Coverage(self.threshold); 25842 } 25843 25844 const base = seq == undefined ? "N" : seq.charAt(seqOffset + j);
25845 const key = alignment.strand ? "pos" + base : "neg" + base; 25846 const q = qual && seqOffset + j < qual.length ? qual[seqOffset + j] : 30; 25847 self.coverage[i][key] += 1; 25848 self.coverage[i]["qual" + base] += q; 25849 self.coverage[i].total += 1; 25850 self.coverage[i].qual += q; 25851 self.maximum = Math.max(self.coverage[i].total, self.maximum); 25852 } 25853 } 25854 } 25855 25856 } 25857 25858 class Coverage { 25859 constructor(alleleThreshold) { 25860 this.qualityWeight = true; 25861 this.posA = 0; 25862 this.negA = 0; 25863 this.posT = 0; 25864 this.negT = 0; 25865 this.posC = 0; 25866 this.negC = 0; 25867 this.posG = 0; 25868 this.negG = 0; 25869 this.posN = 0; 25870 this.negN = 0; 25871 this.pos = 0; 25872 this.neg = 0; 25873 this.qualA = 0; 25874 this.qualT = 0; 25875 this.qualC = 0; 25876 this.qualG = 0; 25877 this.qualN = 0; 25878 this.qual = 0; 25879 this.total = 0; 25880 this.del = 0; 25881 this.ins = 0; 25882 this.threshold = alleleThreshold; 25883 } 25884 25885 isMismatch(refBase) { 25886 const threshold = this.threshold * (this.qualityWeight && this.qual ? this.qual : this.total); 25887 let mismatchQualitySum = 0; 25888 25889 for (let base of ["A", "T", "C", "G"]) { 25890 if (base !== refBase) { 25891 mismatchQualitySum += this.qualityWeight && this.qual ? this["qual" + base] : this["pos" + base] + this["neg" + base]; 25892 } 25893 } 25894 25895 return mismatchQualitySum >= threshold; 25896 } 25897 25898 } 25899 25900 class DownsampledInterval { 25901 constructor(start, end, counts) { 25902 this.start = start; 25903 this.end = end; 25904 this.counts = counts; 25905 } 25906 25907 popupData(genomicLocation) { 25908 return [{ 25909 name: "start", 25910 value: this.start + 1 25911 }, { 25912 name: "end", 25913 value: this.end 25914 }, { 25915 name: "# downsampled:", 25916 value: this.counts 25917 }]; 25918 } 25919 25920 } 25921 25922 class PairedEndStats { 25923 constructor(lowerPercentile, upperPercentile) { 25924 this.totalCount = 0; 25925 this.frCount = 0; 25926 this.rfCount = 0; 25927 this.ffCount = 0; 25928 this.sumF = 0; 25929 this.sumF2 = 0; //this.lp = lowerPercentile === undefined ? 0.005 : lowerPercentile; 25930 //this.up = upperPercentile === undefined ? 0.995 : upperPercentile; 25931 //this.digest = new Digest(); 25932 } 25933 25934 push(alignment) { 25935 if (alignment.isProperPair()) { 25936 var fragmentLength = Math.abs(alignment.fragmentLength); //this.digest.push(fragmentLength); 25937 25938 this.sumF += fragmentLength; 25939 this.sumF2 += fragmentLength * fragmentLength; 25940 var po = alignment.pairOrientation; 25941 25942 if (typeof po === "string" && po.length === 4) { 25943 var tmp = '' + po.charAt(0) + po.charAt(2); 25944 25945 switch (tmp) { 25946 case 'FF': 25947 case 'RR': 25948 this.ffCount++; 25949 break; 25950 25951 case "FR": 25952 this.frCount++; 25953 break; 25954 25955 case "RF": 25956 this.rfCount++; 25957 } 25958 } 25959 25960 this.totalCount++; 25961 } 25962 } 25963 25964 compute() { 25965 if (this.totalCount > 100) { 25966 if (this.ffCount / this.totalCount > 0.9) this.orienation = "ff";else if (this.frCount / this.totalCount > 0.9) this.orienation = "fr";else if (this.rfCount / this.totalCount > 0.9) this.orienation = "rf"; 25967 var fMean = this.sumF / this.totalCount; 25968 var stdDev = Math.sqrt((this.totalCount * this.sumF2 - this.sumF * this.sumF) / (this.totalCount * this.totalCount)); 25969 this.lowerFragmentLength = fMean - 3 * stdDev; 25970 this.upperFragmentLength = fMean + 3 * stdDev; //this.lowerFragmentLength = this.digest.percentile(this.lp); 25971 //this.upperFragmentLength = this.digest.percentile(this.up); 25972 //this.digest = undefined; 25973 } 25974 } 25975 25976 } 25977 25978 class SupplementaryAlignment { 25979 constructor(rec) { 25980 const tokens = rec.split(','); 25981 this.chr = tokens[0]; 25982 this.start = parseInt(tokens[1]); 25983 this.strand = tokens[2].charAt(0); 25984 this.mapQ = parseInt(tokens[4]); 25985 this.numMismatches = parseInt(tokens[5]); 25986 this.lenOnRef = BamUtils.computeLengthOnReference(tokens[3]); 25987 } 25988 25989 printString() { 25990 return this.chr + ":" + numberFormatter$1(this.start) + "-" + numberFormatter$1(this.start + this.lenOnRef) + " (" + this.strand + ") = " + numberFormatter$1(this.lenOnRef) + "bp @MAPQ: " + this.mapQ + " NM: " + this.numMismatches; 25991 } 25992 25993 } 25994 25995 function createSupplementaryAlignments(str) { 25996 const tokens = str.split(';'); 25997 return tokens.filter(t => t.length > 0).map(str => new SupplementaryAlignment(str)); 25998 } 25999 26000 /* 26001 * The MIT License (MIT) 26002 * 26003 * Copyright (c) 2014 Broad Institute 26004 * 26005 * Permission is hereby granted, free of charge, to any person obtaining a copy 26006 * of this software and associated documentation files (the "Software"), to deal 26007 * in the Software without restriction, including without limitation the rights 26008 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 26009 * copies of the Software, and to permit persons to whom the Software is 26010 * furnished to do so, subject to the following conditions: 26011 * 26012 * The above copyright notice and this permission notice shall be included in 26013 * all copies or substantial portions of the Software. 26014 * 26015 * 26016 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26017 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26018 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26019 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26020 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26021 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26022 * THE SOFTWARE. 26023 */ 26024 const READ_PAIRED_FLAG = 0x1; 26025 const PROPER_PAIR_FLAG = 0x2; 26026 const READ_UNMAPPED_FLAG = 0x4; 26027 const MATE_UNMAPPED_FLAG = 0x8; 26028 const READ_STRAND_FLAG$2 = 0x10; 26029 const MATE_STRAND_FLAG$2 = 0x20; 26030 const FIRST_OF_PAIR_FLAG = 0x40; 26031 const SECOND_OF_PAIR_FLAG = 0x80; 26032 const SECONDARY_ALIGNMNET_FLAG = 0x100; 26033 const READ_FAILS_VENDOR_QUALITY_CHECK_FLAG = 0x200; 26034 const DUPLICATE_READ_FLAG = 0x400; 26035 const SUPPLEMENTARY_ALIGNMENT_FLAG = 0x800;
26036 const ELEMENT_SIZE = { 26037 c: 1, 26038 C: 1, 26039 s: 2, 26040 S: 2, 26041 i: 4, 26042 I: 4, 26043 f: 4 26044 }; 26045 const MAX_CIGAR = 50; 26046 /** 26047 * readName 26048 * chr 26049 * cigar 26050 * lengthOnRef 26051 * start 26052 * seq 26053 * qual 26054 * mq 26055 * strand 26056 * blocks 26057 */ 26058 26059 class BamAlignment { 26060 constructor() { 26061 this.hidden = false; 26062 } 26063 26064 isMapped() { 26065 return (this.flags & READ_UNMAPPED_FLAG) === 0; 26066 } 26067 26068 isPaired() { 26069 return (this.flags & READ_PAIRED_FLAG) !== 0; 26070 } 26071 26072 isProperPair() { 26073 return (this.flags & PROPER_PAIR_FLAG) !== 0; 26074 } 26075 26076 isFirstOfPair() { 26077 return (this.flags & FIRST_OF_PAIR_FLAG) !== 0; 26078 } 26079 26080 isSecondOfPair() { 26081 return (this.flags & SECOND_OF_PAIR_FLAG) !== 0; 26082 } 26083 26084 isSecondary() { 26085 return (this.flags & SECONDARY_ALIGNMNET_FLAG) !== 0; 26086 } 26087 26088 isSupplementary() { 26089 return (this.flags & SUPPLEMENTARY_ALIGNMENT_FLAG) !== 0; 26090 } 26091 26092 isFailsVendorQualityCheck() { 26093 return (this.flags & READ_FAILS_VENDOR_QUALITY_CHECK_FLAG) !== 0; 26094 } 26095 26096 isDuplicate() { 26097 return (this.flags & DUPLICATE_READ_FLAG) !== 0; 26098 } 26099 26100 isMateMapped() { 26101 return (this.flags & MATE_UNMAPPED_FLAG) === 0; 26102 } 26103 26104 isNegativeStrand() { 26105 return (this.flags & READ_STRAND_FLAG$2) !== 0; 26106 } 26107 26108 isMateNegativeStrand() { 26109 return (this.flags & MATE_STRAND_FLAG$2) !== 0; 26110 } 26111 26112 hasTag(tag) { 26113 const tmpTags = this.tagDict || decodeTags(this.tagBA); 26114 return tmpTags.hasOwnProperty(tag); 26115 } 26116 26117 tags() { 26118 if (!this.tagDict) { 26119 if (this.tagBA) { 26120 this.tagDict = decodeTags(this.tagBA); 26121 this.tagBA = undefined; 26122 } else { 26123 this.tagDict = {}; // Mark so we don't try again. The record has no tags 26124 } 26125 } 26126 26127 return this.tagDict; 26128 } 26129 /** 26130 * Does alignment (or alignment extended by soft clips) contain the genomic location? 26131 * 26132 * @param genomicLocation 26133 * @param showSoftClips 26134 * @returns {boolean|boolean} 26135 */ 26136 26137 26138 containsLocation(genomicLocation, showSoftClips) { 26139 const s = showSoftClips ? this.scStart : this.start; 26140 const l = showSoftClips ? this.scLengthOnRef : this.lengthOnRef; 26141 return genomicLocation >= s && genomicLocation <= s + l; 26142 } 26143 26144 popupData(genomicLocation) { 26145 // if the user clicks on a base next to an insertion, show just the 26146 // inserted bases in a popup (like in desktop IGV). 26147 const nameValues = []; // Consert genomic location to int 26148 26149 genomicLocation = Math.floor(genomicLocation); 26150 26151 if (this.insertions) { 26152 const seq = this.seq; 26153 26154 for (let insertion of this.insertions) { 26155 var ins_start = insertion.start; 26156 26157 if (genomicLocation === ins_start || genomicLocation === ins_start - 1) { 26158 nameValues.push({ 26159 name: 'Insertion', 26160 value: seq.substr(insertion.seqOffset, insertion.len) 26161 }); 26162 nameValues.push({ 26163 name: 'Location', 26164 value: ins_start 26165 }); 26166 return nameValues; 26167 } 26168 } 26169 } 26170 26171 nameValues.push({ 26172 name: 'Read Name', 26173 value: this.readName 26174 }); // Sample 26175 // Read group 26176 26177 nameValues.push('<hr/>'); // Add 1 to genomic location to map from 0-based computer units to user-based units 26178 26179 nameValues.push({ 26180 name: 'Alignment Start', 26181 value: numberFormatter$1(1 + this.start), 26182 borderTop: true 26183 }); 26184 nameValues.push({ 26185 name: 'Read Strand', 26186 value: true === this.strand ? '(+)' : '(-)', 26187 borderTop: true 26188 }); // Abbreviate long cigar strings, keeping the beginning and end to show cliping 26189 26190 let cigar = this.cigar; 26191 26192 if (cigar && cigar.length > MAX_CIGAR) { 26193 const half = MAX_CIGAR / 2; 26194 cigar = `${cigar.substring(0, half - 2)} ... ${cigar.substring(cigar.length - half + 2)}`; 26195 } 26196 26197 nameValues.push({ 26198 name: 'Cigar', 26199 value: cigar 26200 }); 26201 nameValues.push({ 26202 name: 'Mapping Quality', 26203 value: this.mq 26204 }); 26205 nameValues.push({ 26206 name: 'Secondary', 26207 value: yesNo(this.isSecondary()) 26208 }); 26209 nameValues.push({ 26210 name: 'Supplementary', 26211 value: yesNo(this.isSupplementary()) 26212 }); 26213 nameValues.push({ 26214 name: 'Duplicate', 26215 value: yesNo(this.isDuplicate()) 26216 }); 26217 nameValues.push({ 26218 name: 'Failed QC', 26219 value: yesNo(this.isFailsVendorQualityCheck()) 26220 }); 26221 26222 if (this.isPaired()) { 26223 nameValues.push('<hr/>'); 26224 nameValues.push({ 26225 name: 'First in Pair', 26226 value: !this.isSecondOfPair(), 26227 borderTop: true 26228 }); 26229 nameValues.push({ 26230 name: 'Mate is Mapped', 26231 value: yesNo(this.isMateMapped()) 26232 }); 26233 26234 if (this.pairOrientation) { 26235 nameValues.push({ 26236 name: 'Pair Orientation', 26237 value: this.pairOrientation 26238 }); 26239 } 26240 26241 if (this.isMateMapped()) { 26242 nameValues.push({ 26243 name: 'Mate Chromosome', 26244 value: this.mate.chr 26245 }); 26246 nameValues.push({ 26247 name: 'Mate Start', 26248 value: this.mate.position + 1 26249 }); 26250 nameValues.push({ 26251 name: 'Mate Strand', 26252 value: true === this.mate.strand ? '(+)' : '(-)' 26253 }); 26254 nameValues.push({ 26255 name: 'Insert Size', 26256 value: this.fragmentLength 26257 }); // Mate Start 26258 // Mate Strand 26259 // Insert Size 26260 } // First in Pair 26261 // Pair Orientation 26262 26263 } 26264 26265 const tagDict = this.tags(); 26266 26267 if (tagDict.hasOwnProperty('SA')) { 26268 nameValues.push('<hr/>'); 26269 nameValues.push({ 26270 name: 'Supplementary Alignments', 26271 value: '' 26272 }); 26273 const sa = createSupplementaryAlignments(tagDict['SA']); 26274 26275 if (sa) { 26276 nameValues.push('<ul>'); 26277 26278 for (let s of sa) { 26279 nameValues.push(`<li>${s.printString()}</li>`); 26280 } 26281 26282 nameValues.push('</ul>'); 26283 } 26284 } 26285 26286 const hiddenTags = new Set(['SA', 'MD']); 26287 nameValues.push('<hr/>'); 26288 26289 for (let key in tagDict) { 26290 if (!hiddenTags.has(key)) { 26291 nameValues.push({ 26292 name: key, 26293 value: tagDict[key] 26294 }); 26295 } 26296 } 26297 26298 nameValues.push({ 26299 name: 'Hidden Tags', 26300 value: 'SA, MD' 26301 }); 26302 nameValues.push('<hr/>'); 26303 nameValues.push({ 26304 name: 'Genomic Location: ', 26305 value: numberFormatter$1(1 + genomicLocation) 26306 }); 26307 nameValues.push({ 26308 name: 'Read Base:', 26309 value: this.readBaseAt(genomicLocation) 26310 }); 26311 nameValues.push({ 26312 name: 'Base Quality:', 26313 value: this.readBaseQualityAt(genomicLocation) 26314 }); 26315 return nameValues; 26316 26317 function yesNo(bool) { 26318 return bool ? 'Yes' : 'No'; 26319 } 26320 } 26321 26322 readBaseAt(genomicLocation) { 26323 const block = blockAtGenomicLocation(this.blocks, genomicLocation); 26324 26325 if (block) { 26326 if ("*" === this.seq) { 26327 return "*"; 26328 } else { 26329 const idx = block.seqIndexAt(genomicLocation); // if (idx >= 0 && idx < this.seq.length) { 26330 26331 return this.seq[idx]; // } 26332 } 26333 } else { 26334 return undefined; 26335 } 26336 } 26337 26338 readBaseQualityAt(genomicLocation) { 26339 const block = blockAtGenomicLocation(this.blocks, genomicLocation); 26340 26341 if (block) { 26342 if ("*" === this.qual) { 26343 return 30; 26344 } else { 26345 const idx = block.seqIndexAt(genomicLocation); 26346 26347 if (idx >= 0 && this.qual && idx < this.qual.length) { 26348 return this.qual[idx]; 26349 } else { 26350 return 30; 26351 } 26352 } 26353 } else { 26354 return undefined; 26355 } 26356 } 26357 26358 gapSizeAt(genomicLocation) { 26359 if (this.gaps) { 26360 for (let gap of this.gaps) { 26361 if (genomicLocation >= gap.start && genomicLocation < gap.start + gap.len) { 26362 return gap.len; 26363 } 26364 } 26365 } 26366 26367 return 0; 26368 } 26369 26370 } 26371 26372 function blockAtGenomicLocation(blocks, genomicLocation) { 26373 for (let i = 0; i < blocks.length; i++) { 26374 const block = blocks[i]; 26375 26376 if (genomicLocation >= block.start && genomicLocation < block.start + block.len) { 26377 return block; 26378 } 26379 } 26380 26381 return undefined; 26382 } 26383 26384 function decodeTags(ba) { 26385 let p = 0; 26386 const len = ba.length; 26387 const tags = {}; 26388 26389 while (p < len) { 26390 const tag = String.fromCharCode(ba[p]) + String.fromCharCode(ba[p + 1]); 26391 p += 2; 26392 const type = String.fromCharCode(ba[p++]); 26393 let value; 26394 26395 if (type === 'A') {
26396 value = String.fromCharCode(ba[p]); 26397 p++; 26398 } else if (type === 'i' || type === 'I') { 26399 value = readInt$1(ba, p); 26400 p += 4; 26401 } else if (type === 'c') { 26402 value = readInt8(ba, p); 26403 p++; 26404 } else if (type === 'C') { 26405 value = readUInt8(ba, p); 26406 p++; 26407 } else if (type === 's' || type === 'S') { 26408 value = readShort(ba, p); 26409 p += 2; 26410 } else if (type === 'f') { 26411 value = readFloat(ba, p); 26412 p += 4; 26413 } else if (type === 'Z') { 26414 value = ''; 26415 26416 for (;;) { 26417 var cc = ba[p++]; 26418 26419 if (cc === 0) { 26420 break; 26421 } else { 26422 value += String.fromCharCode(cc); 26423 } 26424 } 26425 } else if (type === 'B') { 26426 const elementType = String.fromCharCode(ba[p++]); 26427 let elementSize = ELEMENT_SIZE[elementType]; 26428 26429 if (elementSize === undefined) { 26430 tags[tag] = `Error: unknown element type '${elementType}'`; 26431 break; 26432 } 26433 26434 const numElements = readInt$1(ba, p); 26435 p += 4 + numElements * elementSize; 26436 value = '[not shown]'; 26437 } else { 26438 //'Unknown type ' + type; 26439 value = 'Error unknown type: ' + type; 26440 tags[tag] = value; 26441 break; 26442 } 26443 26444 tags[tag] = value; 26445 } 26446 26447 return tags; 26448 } 26449 26450 function readInt$1(ba, offset) { 26451 return ba[offset + 3] << 24 | ba[offset + 2] << 16 | ba[offset + 1] << 8 | ba[offset]; 26452 } 26453 26454 function readShort(ba, offset) { 26455 return ba[offset + 1] << 8 | ba[offset]; 26456 } 26457 26458 function readFloat(ba, offset) { 26459 const dataView = new DataView(ba.buffer); 26460 return dataView.getFloat32(offset); 26461 } 26462 26463 function readInt8(ba, offset) { 26464 const dataView = new DataView(ba.buffer); 26465 return dataView.getInt8(offset); 26466 } 26467 26468 function readUInt8(ba, offset) { 26469 const dataView = new DataView(ba.buffer); 26470 return dataView.getUint8(offset); 26471 } 26472 26473 /* 26474 * The MIT License (MIT) 26475 * 26476 * Copyright (c) 2016-2017 The Regents of the University of California 26477 * Author: Jim Robinson 26478 * 26479 * Permission is hereby granted, free of charge, to any person obtaining a copy 26480 * of this software and associated documentation files (the "Software"), to deal 26481 * in the Software without restriction, including without limitation the rights 26482 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 26483 * copies of the Software, and to permit persons to whom the Software is 26484 * furnished to do so, subject to the following conditions: 26485 * 26486 * The above copyright notice and this permission notice shall be included in 26487 * all copies or substantial portions of the Software. 26488 * 26489 * 26490 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26491 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26492 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26493 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26494 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26495 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26496 * THE SOFTWARE. 26497 */ 26498 26499 /** 26500 * Created by jrobinso on 4/5/18. 26501 */ 26502 class AlignmentBlock { 26503 constructor(b) { 26504 if (b) { 26505 Object.assign(this, b); 26506 } 26507 } 26508 26509 seqIndexAt(genomicLocation) { 26510 return Math.floor(genomicLocation) - this.start + this.seqOffset; 26511 } 26512 26513 } 26514 26515 class BamFilter { 26516 constructor(options) { 26517 if (!options) options = {}; 26518 this.vendorFailed = options.vendorFailed === undefined ? true : options.vendorFailed; 26519 this.duplicates = options.duplicates === undefined ? true : options.duplicates; 26520 this.secondary = options.secondary || false; 26521 this.supplementary = options.supplementary || false; 26522 this.mqThreshold = options.mqThreshold === undefined ? 0 : options.mqThreshold; 26523 26524 if (options.readgroups) { 26525 this.readgroups = new Set(options.readgroups); 26526 } 26527 } 26528 26529 pass(alignment) { 26530 if (this.vendorFailed && alignment.isFailsVendorQualityCheck()) return false;
26531 if (this.duplicates && alignment.isDuplicate()) return false; 26532 if (this.secondary && alignment.isSecondary()) return false; 26533 if (this.supplementary && alignment.isSupplementary()) return false; 26534 if (alignment.mq < this.mqThreshold) return false; 26535 26536 if (this.readgroups) { 26537 var rg = alignment.tags()['RG']; 26538 return this.readgroups.has(rg); 26539 } 26540 26541 return true; 26542 } 26543 26544 } 26545 26546 /** 26547 * This code is based on the Biodalliance BAM reader by Thomas Down, 2011 26548 * 26549 * https://github.com/dasmoth/dalliance/blob/master/js/bam.js 26550 */ 26551 26552 const SEQ_DECODER = ['=', 'A', 'C', 'x', 'G', 'x', 'x', 'x', 'T', 'x', 'x', 'x', 'x', 'x', 'x', 'N']; 26553 const CIGAR_DECODER = ['M', 'I', 'D', 'N', 'S', 'H', 'P', '=', 'X', '?', '?', '?', '?', '?', '?', '?']; 26554 const READ_STRAND_FLAG$1 = 0x10; 26555 const MATE_STRAND_FLAG$1 = 0x20; 26556 const BAM1_MAGIC_BYTES = new Uint8Array([0x42, 0x41, 0x4d, 0x01]); // BAM\1 26557 26558 const BAM1_MAGIC_NUMBER = readInt(BAM1_MAGIC_BYTES, 0); 26559 const DEFAULT_ALLELE_FREQ_THRESHOLD = 0.2; 26560 const DEFAULT_SAMPLING_WINDOW_SIZE = 100; 26561 const DEFAULT_SAMPLING_DEPTH = 500; 26562 const MAXIMUM_SAMPLING_DEPTH = 10000; 26563 const BamUtils = { 26564 readHeader: function (url, options, genome) { 26565 return igvxhr.loadArrayBuffer(url, options).then(function (compressedBuffer) { 26566 var header, unc, uncba; 26567 unc = unbgzf(compressedBuffer); 26568 uncba = unc; 26569 header = BamUtils.decodeBamHeader(uncba, genome); 26570 return header; 26571 }); 26572 }, 26573 26574 /** 26575 * 26576 * @param ba bytes to decode as a UInt8Array 26577 * @param genome optional igv genome object 26578 * @returns {{ magicNumer: number, size: number, chrNames: Array, chrToIndex: ({}|*), chrAliasTable: ({}|*) }} 26579 */ 26580 decodeBamHeader: function (ba, genome) { 26581 var magic, samHeaderLen, samHeader, chrToIndex, chrNames, chrAliasTable, alias; 26582 magic = readInt(ba, 0); 26583 26584 if (magic !== BAM1_MAGIC_NUMBER) { 26585 throw new Error('BAM header errror: bad magic number. This could be caused by either a corrupt or missing file.'); 26586 } 26587 26588 samHeaderLen = readInt(ba, 4); 26589 samHeader = ''; 26590 26591 for (var i = 0; i < samHeaderLen; ++i) { 26592 samHeader += String.fromCharCode(ba[i + 8]); 26593 } 26594 26595 var nRef = readInt(ba, samHeaderLen + 8); 26596 var p = samHeaderLen + 12; 26597 chrToIndex = {}; 26598 chrNames = []; 26599 chrAliasTable = {}; 26600 26601 for (i = 0; i < nRef; ++i) { 26602 var lName = readInt(ba, p); 26603 var name = ''; 26604 26605 for (var j = 0; j < lName - 1; ++j) { 26606 name += String.fromCharCode(ba[p + 4 + j]); 26607 } 26608 26609 readInt(ba, p + lName + 4); //dlog(name + ': ' + lRef); 26610 26611 chrToIndex[name] = i; 26612 chrNames[i] = name; 26613 26614 if (genome) { 26615 alias = genome.getChromosomeName(name); 26616 chrAliasTable[alias] = name; 26617 } 26618 26619 p = p + 8 + lName; 26620 } 26621 26622 return { 26623 magicNumber: magic, 26624 size: p, 26625 chrNames: chrNames, 26626 chrToIndex: chrToIndex, 26627 chrAliasTable: chrAliasTable 26628 }; 26629 }, 26630 bam_tag2cigar: function (ba, block_end, seq_offset, lseq, al, cigarArray) { 26631 function type2size(x) { 26632 if (x === 'C' || x === 'c' || x === 'A') return 1;else if (x === 'S' || x === 's') return 2;else if (x === 'I' || x === 'i' || x === 'f') return 4;else return 0; 26633 } // test if the real CIGAR is encoded in a CG:B,I tag 26634 26635 26636 if (cigarArray.length !== 1 || al.start < 0) return false; 26637 var p = seq_offset + (lseq + 1 >> 1) + lseq; 26638 26639 while (p + 4 < block_end) { 26640 var tag = String.fromCharCode(ba[p]) + String.fromCharCode(ba[p + 1]); 26641 if (tag === 'CG') break; 26642 var type = String.fromCharCode(ba[p + 2]); 26643 26644 if (type === 'B') { 26645 // the binary array type 26646 type = String.fromCharCode(ba[p + 3]); 26647 var size = type2size(type); 26648 var len = readInt(ba, p + 4); 26649 p += 8 + size * len; 26650 } else if (type === 'Z' || type === 'H') { 26651 // 0-terminated string 26652 p += 3; 26653 26654 while (ba[p++] !== 0) {} 26655 } else { 26656 // other atomic types 26657 p += 3 + type2size(type); 26658 } 26659 } 26660 26661 if (p >= block_end) return false; // no CG tag 26662 26663 if (String.fromCharCode(ba[p + 2]) !== 'B' || String.fromCharCode(ba[p + 3]) !== 'I') return false; // not of type B,I 26664 // now we know the real CIGAR length and its offset in the binary array 26665 26666 var cigar_len = readInt(ba, p + 4); 26667 var cigar_offset = p + 8; // 4 for "CGBI" and 4 for length 26668 26669 if (cigar_offset + cigar_len * 4 > block_end) return false; // out of bound 26670 // decode CIGAR 26671 26672 var cigar = ''; 26673 var lengthOnRef = 0; 26674 cigarArray.length = 0; // empty the old array 26675 26676 p = cigar_offset; 26677 26678 for (var k = 0; k < cigar_len; ++k, p += 4) { 26679 var cigop = readInt(ba, p); 26680 var opLen = cigop >> 4; 26681 var opLtr = CIGAR_DECODER[cigop & 0xf]; 26682 if (opLtr === 'M' || opLtr === 'EQ' || opLtr === 'X' || opLtr === 'D' || opLtr === 'N' || opLtr === '=') lengthOnRef += opLen; 26683 cigar = cigar + opLen + opLtr; 26684 cigarArray.push({
26685 len: opLen, 26686 ltr: opLtr 26687 }); 26688 } // update alignment record. We are not updating bin, as apparently it is not used. 26689 26690 26691 al.cigar = cigar; 26692 al.lengthOnRef = lengthOnRef; 26693 return true; 26694 }, 26695 26696 /** 26697 * 26698 * @param ba bytes to decode as an UInt8Array 26699 * @param offset offset position of ba array to start decoding 26700 * @param alignmentContainer container to receive the decoded alignments 26701 * @param min minimum genomic position 26702 * @param max maximum genomic position 26703 * @param chrIdx chromosome index 26704 * @param chrNames array of chromosome names 26705 * @param filter a BamFilter object 26706 * 26707 * @return true if we have moved beyond the right end of the genomic range. 26708 */ 26709 decodeBamRecords: function (ba, offset, alignmentContainer, chrNames, chrIdx, min, max, filter) { 26710 while (offset < ba.length) { 26711 const blockSize = readInt(ba, offset); 26712 const blockEnd = offset + blockSize + 4; 26713 const alignment = new BamAlignment(); 26714 const refID = readInt(ba, offset + 4); 26715 const pos = readInt(ba, offset + 8); 26716 26717 if (blockEnd > ba.length) { 26718 return; 26719 } 26720 26721 if (refID < 0) { 26722 offset = blockEnd; 26723 continue; // unmapped read 26724 } else if (chrIdx !== undefined && (refID > chrIdx || pos > max)) { 26725 return true; // off right edge, we're done 26726 } else if (chrIdx !== undefined && refID < chrIdx) { 26727 offset = blockEnd; 26728 continue; // ref ID to left of start, not sure this is possible 26729 } 26730 26731 const bin_mq_nl = readInt(ba, offset + 12); 26732 const mq = (bin_mq_nl & 0xff00) >> 8; 26733 const nl = bin_mq_nl & 0xff; 26734 const flag_nc = readInt(ba, offset + 16); 26735 const flag = (flag_nc & 0xffff0000) >> 16; 26736 const nc = flag_nc & 0xffff; 26737 const lseq = readInt(ba, offset + 20); 26738 const mateChrIdx = readInt(ba, offset + 24); 26739 const matePos = readInt(ba, offset + 28); 26740 const tlen = readInt(ba, offset + 32); 26741 let readName = []; 26742 26743 for (let j = 0; j < nl - 1; ++j) { 26744 readName.push(String.fromCharCode(ba[offset + 36 + j])); 26745 } 26746 26747 readName = readName.join(''); 26748 let lengthOnRef = 0; 26749 let cigar = ''; 26750 let p = offset + 36 + nl; 26751 const cigarArray = []; // concatenate M,=,EQ,and X 26752 26753 let lastCigRecord; 26754 26755 for (let c = 0; c < nc; ++c) { 26756 var cigop = readInt(ba, p); 26757 var opLen = cigop >> 4; 26758 var opLtr = CIGAR_DECODER[cigop & 0xf]; 26759 if (opLtr === 'M' || opLtr === 'EQ' || opLtr === 'X' || opLtr === 'D' || opLtr === 'N' || opLtr === '=') lengthOnRef += opLen; 26760 cigar = cigar + opLen + opLtr; 26761 p += 4; // if(mOperators.has(opLtr) && mOperators.has(lastCigRecord.ltr)) { 26762 // lastCigRecord.len += opLen; 26763 // lastCigRecord.ltr = 'M' 26764 // } 26765 // else { 26766 26767 lastCigRecord = { 26768 len: opLen, 26769 ltr: opLtr 26770 }; 26771 cigarArray.push(lastCigRecord); //} 26772 } 26773 26774 alignment.chr = chrNames[refID]; 26775 alignment.start = pos; 26776 alignment.flags = flag; 26777 alignment.strand = !(flag & READ_STRAND_FLAG$1); 26778 alignment.readName = readName; 26779 alignment.cigar = cigar; 26780 alignment.lengthOnRef = lengthOnRef; 26781 alignment.fragmentLength = tlen; 26782 alignment.mq = mq; 26783 BamUtils.bam_tag2cigar(ba, blockEnd, p, lseq, alignment, cigarArray); 26784 alignment.end = alignment.start + alignment.lengthOnRef; 26785 26786 if (alignment.end < min) { 26787 offset = blockEnd; 26788 continue; 26789 } // Record out-of-range "to the left", skip to next one 26790 26791 26792 let seq = []; 26793 const seqBytes = lseq + 1 >> 1; 26794 26795 for (let j = 0; j < seqBytes; ++j) { 26796 var sb = ba[p + j]; 26797 seq.push(SEQ_DECODER[(sb & 0xf0) >> 4]); 26798 seq.push(SEQ_DECODER[sb & 0x0f]); 26799 } 26800 26801 seq = seq.slice(0, lseq).join(''); // seq might have one extra character (if lseq is an odd number) 26802 26803 p += seqBytes; 26804 const qualArray = []; 26805 26806 for (let j = 0; j < lseq; ++j) { 26807 qualArray.push(ba[p + j]); 26808 } 26809 26810 p += lseq; 26811 26812 if (mateChrIdx >= 0) { 26813 alignment.mate = { 26814 chr: chrNames[mateChrIdx], 26815 position: matePos, 26816 strand: !(flag & MATE_STRAND_FLAG$1) 26817 }; 26818 } 26819
26820 alignment.seq = seq; 26821 alignment.qual = qualArray; 26822 alignment.tagBA = new Uint8Array(ba.buffer.slice(p, blockEnd)); // decode these on demand 26823 26824 this.setPairOrientation(alignment); 26825 26826 if (undefined === filter || filter.pass(alignment)) { 26827 makeBlocks(alignment, cigarArray); 26828 alignmentContainer.push(alignment); 26829 } 26830 26831 offset = blockEnd; 26832 } 26833 }, 26834 decodeSamRecords: function (sam, alignmentContainer, chr, min, max, filter) { 26835 var lines, i, j, len, tokens, qualString, rnext, lengthOnRef, alignment, cigarArray, started; 26836 lines = splitLines$5(sam); 26837 len = lines.length; 26838 started = false; 26839 26840 for (i = 0; i < len; i++) { 26841 tokens = lines[i].split('\t'); 26842 alignment = new BamAlignment(); 26843 alignment.chr = tokens[2]; 26844 alignment.start = Number.parseInt(tokens[3]) - 1; 26845 alignment.flags = Number.parseInt(tokens[1]); 26846 alignment.readName = tokens[0]; 26847 alignment.strand = !(alignment.flags & READ_STRAND_FLAG$1); 26848 alignment.mq = Number.parseInt(tokens[4]); 26849 alignment.cigar = tokens[5]; 26850 alignment.fragmentLength = Number.parseInt(tokens[8]); 26851 alignment.seq = tokens[9]; 26852 if (alignment.chr === '*' || !alignment.isMapped()) continue; // Unmapped 26853 26854 if (alignment.chr !== chr) { 26855 if (started) break; // Off the right edge, we're done 26856 else continue; // Possibly to the left, skip but keep looping 26857 } else if (alignment.start > max) { 26858 break; // off right edge, we're done 26859 } 26860 26861 lengthOnRef = 0; 26862 cigarArray = buildOperators(alignment.cigar); 26863 cigarArray.forEach(function (op) { 26864 var opLen = op.len; 26865 var opLtr = op.ltr; 26866 if (opLtr === 'M' || opLtr === 'EQ' || opLtr === 'X' || opLtr === 'D' || opLtr === 'N' || opLtr === '=') lengthOnRef += opLen; 26867 }); 26868 alignment.lengthOnRef = lengthOnRef; // TODO for lh3: parse the CG:B,I tag in SAM here 26869 26870 if (alignment.start + lengthOnRef < min) { 26871 continue; // To the left, skip and continue 26872 } 26873 26874 qualString = tokens[10]; 26875 alignment.qual = []; 26876 26877 for (j = 0; j < qualString.length; j++) { 26878 alignment.qual[j] = qualString.charCodeAt(j) - 33; 26879 } 26880 26881 alignment.tagDict = tokens.length < 11 ? {} : decodeSamTags(tokens.slice(11)); 26882 26883 if (alignment.isMateMapped()) { 26884 rnext = tokens[6]; 26885 alignment.mate = { 26886 chr: rnext === '=' ? alignment.chr : rnext, 26887 position: Number.parseInt(tokens[7]), 26888 strand: !(alignment.flags & MATE_STRAND_FLAG$1) 26889 }; 26890 } 26891 26892 this.setPairOrientation(alignment); 26893 26894 if (undefined === filter || filter.pass(alignment)) { 26895 makeBlocks(alignment, cigarArray); 26896 alignmentContainer.push(alignment); 26897 } 26898 } 26899 }, 26900 setReaderDefaults: function (reader, config) { 26901 reader.filter = new BamFilter(config.filter); 26902 26903 if (config.readgroup) { 26904 reader.filter.readgroups = new Set([config.readgroup]); 26905 } 26906 26907 reader.alleleFreqThreshold = config.alleleFreqThreshold === undefined ? DEFAULT_ALLELE_FREQ_THRESHOLD : config.alleleFreqThreshold; 26908 reader.samplingWindowSize = config.samplingWindowSize === undefined ? DEFAULT_SAMPLING_WINDOW_SIZE : config.samplingWindowSize; 26909 reader.samplingDepth = config.samplingDepth === undefined ? DEFAULT_SAMPLING_DEPTH : config.samplingDepth; 26910 26911 if (reader.samplingDepth > MAXIMUM_SAMPLING_DEPTH) { 26912 console.log("Warning: attempt to set sampling depth > maximum value of " + MAXIMUM_SAMPLING_DEPTH); 26913 reader.samplingDepth = MAXIMUM_SAMPLING_DEPTH; 26914 } 26915 26916 if (config.viewAsPairs) { 26917 reader.pairsSupported = true; 26918 } else { 26919 reader.pairsSupported = config.pairsSupported === undefined ? true : config.pairsSupported; 26920 } 26921 }, 26922 setPairOrientation: function (alignment) {
26923 if (alignment.isMapped() && alignment.mate && alignment.isMateMapped() && alignment.mate.chr === alignment.chr) { 26924 var s1 = alignment.strand ? 'F' : 'R'; 26925 var mate = alignment.mate; 26926 var s2 = mate.strand ? 'F' : 'R'; 26927 var o1 = ' '; 26928 var o2 = ' '; 26929 26930 if (alignment.isFirstOfPair()) { 26931 o1 = '1'; 26932 o2 = '2'; 26933 } else if (alignment.isSecondOfPair()) { 26934 o1 = '2'; 26935 o2 = '1'; 26936 } 26937 26938 var tmp = []; 26939 var isize = alignment.fragmentLength; 26940 var estReadLen = alignment.end - alignment.start; 26941 26942 if (isize === 0) { 26943 //isize not recorded. Need to estimate. This calculation was validated against an Illumina 26944 // -> <- library bam. 26945 var estMateEnd = alignment.start < mate.position ? mate.position + estReadLen : mate.position - estReadLen; 26946 isize = estMateEnd - alignment.start; 26947 } //if (isize > estReadLen) { 26948 26949 26950 if (isize > 0) { 26951 tmp[0] = s1; 26952 tmp[1] = o1; 26953 tmp[2] = s2; 26954 tmp[3] = o2; 26955 } else { 26956 tmp[2] = s1; 26957 tmp[3] = o1; 26958 tmp[0] = s2; 26959 tmp[1] = o2; 26960 } // } 26961 26962 26963 alignment.pairOrientation = tmp.join(''); 26964 } 26965 }, 26966 computeLengthOnReference: function (cigarString) { 26967 let len = 0; 26968 let buf = ''; 26969 26970 for (let i = 0; i < cigarString.length; i++) { 26971 const c = cigarString.charCodeAt(i); 26972 26973 if (c > 47 && c < 58) { 26974 buf += cigarString.charAt(i); 26975 } else { 26976 switch (c) { 26977 case 78: // N 26978 26979 case 68: // D 26980 26981 case 77: // M 26982 26983 case 61: // = 26984 26985 case 88: 26986 // X 26987 len += parseInt(buf.toString()); 26988 } 26989 26990 buf = ''; 26991 } 26992 } 26993 26994 return len; 26995 } 26996 }; 26997 /** 26998 * Split the alignment record into blocks as specified in the cigarArray. Each aligned block contains 26999 * its portion of the read sequence and base quality strings. A read sequence or base quality string 27000 * of "*" indicates the value is not recorded. In all other cases the length of the block sequence (block.seq) 27001 * and quality string (block.qual) must == the block length. 27002 * 27003 * @param alignment 27004 * @param cigarArray 27005 * @returns array of blocks 27006 */ 27007 27008 function makeBlocks(alignment, cigarArray) { 27009 const blocks = []; 27010 let insertions; 27011 let gaps; 27012 let seqOffset = 0; 27013 let pos = alignment.start; 27014 alignment.scStart = alignment.start; 27015 alignment.scLengthOnRef = alignment.lengthOnRef; 27016 27017 for (let c of cigarArray) { 27018 let scPos; 27019 27020 switch (c.ltr) { 27021 case 'H': 27022 break; 27023 // ignore hard clips 27024 27025 case 'P': 27026 break; 27027 // ignore pads 27028 27029 case 'S': 27030 scPos = pos; 27031 alignment.scLengthOnRef += c.len; 27032 27033 if (blocks.length === 0) { 27034 alignment.scStart -= c.len; 27035 scPos -= c.len; 27036 } 27037 27038 blocks.push(new AlignmentBlock({ 27039 start: scPos, 27040 seqOffset: seqOffset, 27041 len: c.len, 27042 type: 'S' 27043 })); 27044 seqOffset += c.len; 27045 break; 27046 // soft clip read bases 27047 27048 case 'N': 27049 case 'D': 27050 if (gaps === undefined) { 27051 gaps = []; 27052 } 27053 27054 gaps.push({ 27055 start: pos, 27056 len: c.len, 27057 type: c.ltr 27058 }); 27059 pos += c.len; 27060 break; 27061 27062 case 'I': 27063 if (insertions === undefined) { 27064 insertions = []; 27065 } 27066 27067 insertions.push(new AlignmentBlock({ 27068 start: pos, 27069 len: c.len, 27070 seqOffset: seqOffset, 27071 type: 'I' 27072 })); 27073 seqOffset += c.len; 27074 break; 27075 27076 case 'M': 27077 case 'EQ': 27078 case '=': 27079 case 'X': 27080 blocks.push(new AlignmentBlock({ 27081 start: pos, 27082 seqOffset: seqOffset, 27083 len: c.len, 27084 type: 'M' 27085 })); 27086 seqOffset += c.len; 27087 pos += c.len; 27088 break; 27089 27090 default: 27091 console.log('Error processing cigar element: ' + c.len + c.ltr); 27092 } 27093 } 27094 27095 alignment.blocks = blocks; 27096 alignment.insertions = insertions; 27097 alignment.gaps = gaps; 27098 } 27099 27100 function readInt(ba, offset) { 27101 return ba[offset + 3] << 24 | ba[offset + 2] << 16 | ba[offset + 1] << 8 | ba[offset]; 27102 } 27103 /** 27104 * Build a list of cigar operators from a cigarString. Removes padding operators and concatenates consecutive 27105 * operators of the same type 27106 * 27107 * @param cigarString 27108 * @return 27109 */ 27110 27111 27112 function buildOperators(cigarString) { 27113 var operators, buffer, i, len, prevOp, next, op, nBases; 27114 operators = []; 27115 buffer = []; // Create list of cigar operators 27116 27117 prevOp = null; 27118 len = cigarString.length; 27119 27120 for (i = 0; i < len; i++) { 27121 next = cigarString.charAt(i); 27122 27123 if (isDigit(next)) { 27124 buffer.push(next); 27125 } else { 27126 op = next; 27127 nBases = Number.parseInt(buffer.join('')); 27128 buffer = []; 27129 27130 if (prevOp !== null && prevOp.ltr === op) { 27131 prevOp.len += nBases; 27132 } else { 27133 prevOp = { 27134 len: nBases, 27135 ltr: op 27136 }; 27137 operators.push(prevOp); 27138 } 27139 } 27140 } 27141 27142 return operators; 27143 } 27144 27145 function isDigit(a) {
27146 var charCode = a.charCodeAt(0); 27147 return charCode >= 48 && charCode <= 57; // 0-9 27148 } 27149 27150 function decodeSamTags(tags) { 27151 var tagDict = {}; 27152 tags.forEach(function (tag) { 27153 var tokens = tag.split(':'); 27154 tagDict[tokens[0]] = tokens[2]; 27155 }); 27156 return tagDict; 27157 } 27158 27159 /** 27160 * Class for reading a bam file 27161 * 27162 * @param config 27163 * @constructor 27164 */ 27165 27166 class BamReaderNonIndexed { 27167 constructor(config, genome) { 27168 this.config = config; 27169 this.genome = genome; 27170 this.bamPath = config.url; 27171 this.isDataUri = isDataURL(config.url); 27172 BamUtils.setReaderDefaults(this, config); 27173 } // Return an alignment container 27174 27175 27176 async readAlignments(chr, bpStart, bpEnd) { 27177 if (this.alignmentCache) { 27178 const header = this.header; 27179 const queryChr = header.chrAliasTable.hasOwnProperty(chr) ? header.chrAliasTable[chr] : chr; 27180 const qAlignments = this.alignmentCache.queryFeatures(queryChr, bpStart, bpEnd); 27181 const alignmentContainer = new AlignmentContainer(chr, bpStart, bpEnd, this.samplingWindowSize, this.samplingDepth, this.pairsSupported, this.alleleFreqThreshold); 27182 27183 for (let a of qAlignments) { 27184 alignmentContainer.push(a); 27185 } 27186 27187 alignmentContainer.finish(); 27188 return alignmentContainer; 27189 } else { 27190 if (this.isDataUri) { 27191 const data = decodeDataURI(this.bamPath); 27192 const unc = unbgzf(data.buffer); 27193 this.parseAlignments(unc); 27194 return this.fetchAlignments(chr, bpStart, bpEnd); 27195 } else { 27196 const arrayBuffer = await igvxhr.loadArrayBuffer(this.bamPath, buildOptions(this.config)); 27197 const unc = unbgzf(arrayBuffer); 27198 this.parseAlignments(unc); 27199 return this.fetchAlignments(chr, bpStart, bpEnd); 27200 } 27201 } 27202 } 27203 27204 parseAlignments(data) { 27205 const alignments = []; 27206 this.header = BamUtils.decodeBamHeader(data); 27207 BamUtils.decodeBamRecords(data, this.header.size, alignments, this.header.chrNames); 27208 this.alignmentCache = new FeatureCache(alignments, this.genome); 27209 } 27210 27211 fetchAlignments(chr, bpStart, bpEnd) { 27212 const queryChr = this.header.chrAliasTable.hasOwnProperty(chr) ? this.header.chrAliasTable[chr] : chr; 27213 const features = this.alignmentCache.queryFeatures(queryChr, bpStart, bpEnd); 27214 const alignmentContainer = new AlignmentContainer(chr, bpStart, bpEnd, this.samplingWindowSize, this.samplingDepth, this.pairsSupported); 27215 27216 for (let feature of features) { 27217 alignmentContainer.push(feature); 27218 } 27219 27220 alignmentContainer.finish(); 27221 return alignmentContainer; 27222 } 27223 27224 } 27225 27226 function decodeDataURI(dataURI) { 27227 const split = dataURI.split(','); 27228 const info = split[0].split(':')[1]; 27229 let dataString = split[1]; 27230 27231 if (info.indexOf('base64') >= 0) { 27232 dataString = atob(dataString); 27233 } else { 27234 dataString = decodeURI(dataString); 27235 } 27236 27237 const bytes = new Uint8Array(dataString.length); 27238 27239 for (var i = 0; i < dataString.length; i++) { 27240 bytes[i] = dataString.charCodeAt(i); 27241 } 27242 27243 return bytes; 27244 } 27245 27246 /* 27247 * The MIT License (MIT) 27248 * 27249 * Copyright (c) 2014 Broad Institute 27250 * 27251 * Permission is hereby granted, free of charge, to any person obtaining a copy 27252 * of this software and associated documentation files (the "Software"), to deal 27253 * in the Software without restriction, including without limitation the rights 27254 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 27255 * copies of the Software, and to permit persons to whom the Software is 27256 * furnished to do so, subject to the following conditions: 27257 * 27258 * The above copyright notice and this permission notice shall be included in 27259 * all copies or substantial portions of the Software. 27260 * 27261 * 27262 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 27263 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27264 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27265 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27266 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27267 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27268 * THE SOFTWARE. 27269 */ 27270 // TODO -- big endian? 27271 class BinaryParser { 27272 constructor(dataView, littleEndian) { 27273 this.littleEndian = littleEndian !== undefined ? littleEndian : true; 27274 this.position = 0; 27275 this.view = dataView; 27276 this.length = dataView.byteLength; 27277 } 27278 27279 available() { 27280 return this.length - this.position; 27281 } 27282 27283 remLength() { 27284 return this.length - this.position; 27285 } 27286 27287 hasNext() { 27288 return this.position < this.length - 1; 27289 } 27290 27291 getByte() { 27292 var retValue = this.view.getUint8(this.position, this.littleEndian); 27293 this.position++; 27294 return retValue; 27295 } 27296 27297 getShort() { 27298 var retValue = this.view.getInt16(this.position, this.littleEndian); 27299 this.position += 2; 27300 return retValue; 27301 } 27302 27303 getUShort() { 27304 // var byte1 = this.getByte(), 27305 // byte2 = this.getByte(), 27306 // retValue = ((byte2 << 24 >>> 16) + (byte1 << 24 >>> 24)); 27307 // return retValue; 27308 // 27309 var retValue = this.view.getUint16(this.position, this.littleEndian); 27310 this.position += 2; 27311 return retValue; 27312 } 27313 27314 getInt() { 27315 var retValue = this.view.getInt32(this.position, this.littleEndian); 27316 this.position += 4; 27317 return retValue; 27318 } 27319 27320 getUInt() { 27321 var retValue = this.view.getUint32(this.position, this.littleEndian); 27322 this.position += 4; 27323 return retValue; 27324 } 27325 27326 getLong() { 27327 // DataView doesn't support long. So we'll try manually 27328 var b = []; 27329 b[0] = this.view.getUint8(this.position); 27330 b[1] = this.view.getUint8(this.position + 1); 27331 b[2] = this.view.getUint8(this.position + 2); 27332 b[3] = this.view.getUint8(this.position + 3); 27333 b[4] = this.view.getUint8(this.position + 4); 27334 b[5] = this.view.getUint8(this.position + 5); 27335 b[6] = this.view.getUint8(this.position + 6); 27336 b[7] = this.view.getUint8(this.position + 7); 27337 var value = 0; 27338 27339 if (this.littleEndian) { 27340 for (let i = b.length - 1; i >= 0; i--) { 27341 value = value * 256 + b[i]; 27342 } 27343 } else { 27344 for (let i = 0; i < b.length; i++) { 27345 value = value * 256 + b[i]; 27346 } 27347 } 27348 27349 this.position += 8; 27350 return value; 27351 } 27352 27353 getString(len) { 27354 var s = ""; 27355 var c; 27356 27357 while ((c = this.view.getUint8(this.position++)) !== 0) { 27358 s += String.fromCharCode(c); 27359 if (len && s.length === len) break; 27360 } 27361 27362 return s; 27363 } 27364
27365 getFixedLengthString(len) { 27366 var s = ""; 27367 var i; 27368 var c; 27369 27370 for (i = 0; i < len; i++) { 27371 c = this.view.getUint8(this.position++); 27372 27373 if (c > 0) { 27374 s += String.fromCharCode(c); 27375 } 27376 } 27377 27378 return s; 27379 } 27380 27381 getFixedLengthTrimmedString(len) { 27382 var s = ""; 27383 var i; 27384 var c; 27385 27386 for (i = 0; i < len; i++) { 27387 c = this.view.getUint8(this.position++); 27388 27389 if (c > 32) { 27390 s += String.fromCharCode(c); 27391 } 27392 } 27393 27394 return s; 27395 } 27396 27397 getFloat() { 27398 var retValue = this.view.getFloat32(this.position, this.littleEndian); 27399 this.position += 4; 27400 return retValue; 27401 } 27402 27403 getDouble() { 27404 var retValue = this.view.getFloat64(this.position, this.littleEndian); 27405 this.position += 8; 27406 return retValue; 27407 } 27408 27409 skip(n) { 27410 this.position += n; 27411 return this.position; 27412 } 27413 /** 27414 * Return a BGZip (bam and tabix) virtual pointer 27415 * TODO -- why isn't 8th byte used ? 27416 * @returns {*} 27417 */ 27418 27419 27420 getVPointer() { 27421 var position = this.position, 27422 offset = this.view.getUint8(position + 1) << 8 | this.view.getUint8(position), 27423 byte6 = (this.view.getUint8(position + 6) & 0xff) * 0x100000000, 27424 byte5 = (this.view.getUint8(position + 5) & 0xff) * 0x1000000, 27425 byte4 = (this.view.getUint8(position + 4) & 0xff) * 0x10000, 27426 byte3 = (this.view.getUint8(position + 3) & 0xff) * 0x100, 27427 byte2 = this.view.getUint8(position + 2) & 0xff, 27428 block = byte6 + byte5 + byte4 + byte3 + byte2; 27429 this.position += 8; // if (block == 0 && offset == 0) { 27430 // return null; 27431 // } else { 27432 27433 return new VPointer(block, offset); // } 27434 } 27435 27436 } 27437 27438 class VPointer { 27439 constructor(block, offset) { 27440 this.block = block; 27441 this.offset = offset; 27442 } 27443 27444 isLessThan(vp) { 27445 return this.block < vp.block || this.block === vp.block && this.offset < vp.offset; 27446 } 27447 27448 isGreaterThan(vp) { 27449 return this.block > vp.block || this.block === vp.block && this.offset > vp.offset; 27450 } 27451 27452 print() { 27453 return "" + this.block + ":" + this.offset; 27454 } 27455 27456 } 27457 27458 // Represents a BAM index. 27459 const CSI1_MAGIC$1 = 21582659; // CSI\1 27460 27461 const CSI2_MAGIC$1 = 38359875; // CSI\2 27462 27463 async function parseCsiIndex(arrayBuffer, genome) { 27464 const idx = new CSIIndex(); 27465 idx.parse(arrayBuffer, genome); 27466 return idx; 27467 } 27468 27469 class CSIIndex { 27470 constructor(tabix) { 27471 this.tabix = true; // Means whatever is indexed is BGZipped 27472 } 27473 27474 parse(arrayBuffer, genome) { 27475 const parser = new BinaryParser(new DataView(arrayBuffer)); 27476 const magic = parser.getInt(); 27477 27478 if (magic !== CSI1_MAGIC$1) { 27479 if (magic === CSI2_MAGIC$1) { 27480 throw Error("CSI version 2 is not supported. Please enter an issue at https://github.com/igvteam/igv.js"); 27481 } else { 27482 throw Error("Not a CSI index"); 27483 } 27484 } 27485 27486 this.indices = []; 27487 this.blockMin = Number.MAX_SAFE_INTEGER; 27488 this.lastBlockPosition = []; 27489 this.sequenceIndexMap = {}; 27490 this.minShift = parser.getInt(); 27491 this.depth = parser.getInt(); 27492 const lAux = parser.getInt(); 27493 const seqNames = []; 27494 let bmax = 0; 27495 27496 if (lAux >= 28) { 27497 // Tabix header parameters aren't used, but they must be read to advance the pointer 27498 parser.getInt(); 27499 parser.getInt(); 27500 parser.getInt(); 27501 parser.getInt(); 27502 parser.getInt(); 27503 parser.getInt(); 27504 const l_nm = parser.getInt(); 27505 const nameEndPos = parser.position + l_nm; 27506 let i = 0; 27507 27508 while (parser.position < nameEndPos) { 27509 let seq_name = parser.getString(); // Translate to "official" chr name. 27510 27511 if (genome) { 27512 seq_name = genome.getChromosomeName(seq_name); 27513 } 27514 27515 this.sequenceIndexMap[seq_name] = i; 27516 seqNames[i] = seq_name; 27517 i++; 27518 } 27519 } 27520 27521 const MAX_BIN = this.bin_limit() + 1; 27522 const nref = parser.getInt(); 27523 27524 for (let ref = 0; ref < nref; ref++) { 27525 const binIndex = []; 27526 const loffset = []; 27527 const nbin = parser.getInt(); 27528 27529 for (let b = 0; b < nbin; b++) { 27530 const binNumber = parser.getInt(); 27531 loffset[binNumber] = parser.getVPointer(); 27532 27533 if (binNumber > MAX_BIN) {
27534 // This is a psuedo bin, not used but we have to consume the bytes 27535 parser.getInt(); // # of chunks for this bin 27536 27537 parser.getVPointer(); // unmapped beg 27538 27539 parser.getVPointer(); // unmapped end 27540 27541 parser.getLong(); 27542 parser.getLong(); 27543 } else { 27544 binIndex[binNumber] = []; 27545 const nchnk = parser.getInt(); // # of chunks for this bin 27546 27547 for (let i = 0; i < nchnk; i++) { 27548 const cs = parser.getVPointer(); //chunk_beg 27549 27550 const ce = parser.getVPointer(); //chunk_end 27551 27552 if (cs && ce) { 27553 if (cs.block < this.blockMin) { 27554 this.blockMin = cs.block; // Block containing first alignment 27555 } 27556 27557 if (ce.block > bmax) { 27558 bmax = ce.block; 27559 } 27560 27561 binIndex[binNumber].push([cs, ce]); 27562 } 27563 } 27564 } 27565 } 27566 27567 if (nbin > 0) { 27568 this.indices[ref] = { 27569 binIndex: binIndex, 27570 loffset: loffset 27571 }; 27572 } 27573 } 27574 27575 this.lastBlockPosition = bmax; 27576 } 27577 27578 get chromosomeNames() { 27579 return Object.keys(this.sequenceIndexMap); 27580 } 27581 /** 27582 * Fetch blocks for a particular genomic range. This method is public so it can be unit-tested. 27583 * 27584 * @param refId the sequence dictionary index of the chromosome 27585 * @param min genomic start position 27586 * @param max genomic end position 27587 * @param return an array of {minv: {filePointer, offset}, {maxv: {filePointer, offset}} 27588 */ 27589 27590 27591 blocksForRange(refId, min, max) { 27592 const ba = this.indices[refId]; 27593 27594 if (!ba) { 27595 return []; 27596 } else { 27597 const overlappingBins = this.reg2bins(min, max); // List of bin #s that overlap min, max 27598 27599 if (overlappingBins.length == 0) return []; 27600 const chunks = []; // Find chunks in overlapping bins. Leaf bins (< 4681) are not pruned 27601 27602 for (let binRange of overlappingBins) { 27603 for (let bin = binRange[0]; bin <= binRange[1]; bin++) { 27604 if (ba.binIndex[bin]) { 27605 const binChunks = ba.binIndex[bin]; 27606 const nchnk = binChunks.length; 27607 27608 for (let c = 0; c < nchnk; ++c) { 27609 const cs = binChunks[c][0]; 27610 const ce = binChunks[c][1]; 27611 chunks.push({ 27612 minv: cs, 27613 maxv: ce, 27614 bin: bin 27615 }); 27616 } 27617 } 27618 } 27619 } 27620 27621 const lowestOffset = ba.loffset[overlappingBins[0]]; 27622 return optimizeChunks$1(chunks, lowestOffset); 27623 } 27624 } // reg2bins implementation adapted from GMOD/tabix-js https://github.com/GMOD/tabix-js/blob/master/src/csi.ts 27625 27626 27627 reg2bins(beg, end) { 27628 beg -= 1; // < convert to 1-based closed 27629 27630 if (beg < 1) beg = 1; 27631 if (end > 2 ** 50) end = 2 ** 34; // 17 GiB ought to be enough for anybody 27632 27633 end -= 1; 27634 let l = 0; 27635 let t = 0; 27636 let s = this.minShift + this.depth * 3; 27637 const bins = []; 27638 27639 for (; l <= this.depth; s -= 3, t += 1 << l * 3, l += 1) { 27640 const b = t + (beg >> s); 27641 const e = t + (end >> s); 27642 if (e - b + bins.length > this.maxBinNumber) throw new Error(`query ${beg}-${end} is too large for current binning scheme (shift ${this.minShift}, depth ${this.depth}), try a smaller query or a coarser index binning scheme`); //for (let i = b; i <= e; i += 1) bins.push(i) 27643 27644 bins.push([b, e]); 27645 } 27646 27647 return bins; 27648 } // function reg2bins(beg, end, min_shift, depth) { 27649 // let l, t, n, s = min_shift + depth * 3; 27650 // const bins = []; 27651 // for (--end, l = n = t = 0; l <= depth; s -= 3, t += 1 << l * 3, ++l) { 27652 // let b = t + (beg >> s), e = t + (end >> s), i; 27653 // for (i = b; i <= e; ++i) bins[n++] = i; 27654 // } 27655 // return bins; 27656 // } 27657 27658 27659 bin_limit() { 27660 return ((1 << (this.depth + 1) * 3) - 1) / 7; 27661 } 27662 27663 } 27664 27665 function optimizeChunks$1(chunks, lowest) { 27666 const mergedChunks = []; 27667 let lastChunk = null; 27668 if (chunks.length === 0) return chunks; 27669 chunks.sort(function (c0, c1) { 27670 const dif = c0.minv.block - c1.minv.block; 27671 27672 if (dif !== 0) { 27673 return dif; 27674 } else { 27675 return c0.minv.offset - c1.minv.offset; 27676 } 27677 }); 27678 chunks.forEach(function (chunk) { 27679 if (!lowest || chunk.maxv.isGreaterThan(lowest)) { 27680 if (lastChunk === null) { 27681 mergedChunks.push(chunk); 27682 lastChunk = chunk; 27683 } else { 27684 if (canMerge$1(lastChunk, chunk)) { 27685 if (chunk.maxv.isGreaterThan(lastChunk.maxv)) { 27686 lastChunk.maxv = chunk.maxv; 27687 } 27688 } else { 27689 mergedChunks.push(chunk); 27690 lastChunk = chunk; 27691 } 27692 } 27693 } 27694 }); 27695 return mergedChunks; 27696 } 27697 27698 function canMerge$1(chunk1, chunk2) { 27699 return chunk2.minv.block - chunk1.maxv.block < 65000 && chunk2.maxv.block - chunk1.minv.block < 5000000; // lastChunk.minv.block === lastChunk.maxv.block && 27700 // lastChunk.maxv.block === chunk.minv.block && 27701 // chunk.minv.block === chunk.maxv.block 27702 } 27703 27704 // Represents a BAM index. 27705 const BAI_MAGIC$1 = 21578050; 27706 const TABIX_MAGIC$1 = 21578324; 27707 const MB = 1000000; 27708 27709 async function parseBamIndex(arrayBuffer, genome) { 27710 const index = new BamIndex(); 27711 await index.parse(arrayBuffer, false, genome); 27712 return index; 27713 } 27714 27715 async function parseTabixIndex(arrayBuffer, genome) { 27716 const index = new BamIndex(); 27717 await index.parse(arrayBuffer, true, genome); 27718 return index; 27719 } 27720 27721 class BamIndex { 27722 constructor() {} 27723 27724 async parse(arrayBuffer, tabix, genome) { 27725 const indices = []; 27726 let blockMin = Number.MAX_SAFE_INTEGER; 27727 let blockMax = 0; 27728 const seqNames = []; 27729 const parser = new BinaryParser(new DataView(arrayBuffer)); 27730 const magic = parser.getInt(); 27731 const sequenceIndexMap = {}; 27732 27733 if (magic === BAI_MAGIC$1 || tabix && magic === TABIX_MAGIC$1) { 27734 const nref = parser.getInt(); 27735 27736 if (tabix) { 27737 // Tabix header parameters aren't used, but they must be read to advance the pointer 27738 parser.getInt(); 27739 parser.getInt(); 27740 parser.getInt(); 27741 parser.getInt(); 27742 parser.getInt(); 27743 parser.getInt(); 27744 parser.getInt(); 27745 27746 for (let i = 0; i < nref; i++) { 27747 let seq_name = parser.getString(); // Translate to "official" chr name. 27748 27749 if (genome) { 27750 seq_name = genome.getChromosomeName(seq_name); 27751 } 27752 27753 sequenceIndexMap[seq_name] = i; 27754 seqNames[i] = seq_name; 27755 } 27756 }
27756 // Loop through sequences 27757 27758 27759 for (let ref = 0; ref < nref; ref++) { 27760 const binIndex = {}; 27761 const linearIndex = []; 27762 const nbin = parser.getInt(); 27763 27764 for (let b = 0; b < nbin; b++) { 27765 const binNumber = parser.getInt(); 27766 27767 if (binNumber === 37450) { 27768 // This is a psuedo bin, not used but we have to consume the bytes 27769 parser.getInt(); // # of chunks for this bin 27770 27771 parser.getVPointer(); // unmapped beg 27772 27773 parser.getVPointer(); // unmapped end 27774 27775 parser.getLong(); 27776 parser.getLong(); 27777 } else { 27778 binIndex[binNumber] = []; 27779 const nchnk = parser.getInt(); // # of chunks for this bin 27780 27781 for (let i = 0; i < nchnk; i++) { 27782 const cs = parser.getVPointer(); //chunk_beg 27783 27784 const ce = parser.getVPointer(); //chunk_end 27785 27786 if (cs && ce) { 27787 if (cs.block < blockMin) { 27788 blockMin = cs.block; // Block containing first alignment 27789 } 27790 27791 if (ce.block > blockMax) { 27792 blockMax = ce.block; 27793 } 27794 27795 binIndex[binNumber].push([cs, ce]); 27796 } 27797 } 27798 } 27799 } 27800 27801 const nintv = parser.getInt(); 27802 27803 for (let i = 0; i < nintv; i++) { 27804 const cs = parser.getVPointer(); 27805 linearIndex.push(cs); // Might be null 27806 } 27807 27808 if (nbin > 0) { 27809 indices[ref] = { 27810 binIndex: binIndex, 27811 linearIndex: linearIndex 27812 }; 27813 } 27814 } 27815 27816 this.firstBlockPosition = blockMin; 27817 this.lastBlockPosition = blockMax; 27818 this.indices = indices; 27819 this.sequenceIndexMap = sequenceIndexMap; 27820 this.tabix = tabix; 27821 } else { 27822 throw new Error(indexURL + " is not a " + (tabix ? "tabix" : "bai") + " file"); 27823 } 27824 } 27825 27826 get chromosomeNames() { 27827 return Object.keys(this.sequenceIndexMap); 27828 } 27829 /** 27830 * Fetch blocks for a particular genomic range. This method is public so it can be unit-tested. 27831 * 27832 * @param refId the sequence dictionary index of the chromosome 27833 * @param min genomic start position 27834 * @param max genomic end position 27835 * @param return an array of {minv: {filePointer, offset}, {maxv: {filePointer, offset}} 27836 */ 27837 27838 27839 blocksForRange(refId, min, max) { 27840 const bam = this; 27841 const ba = bam.indices[refId]; 27842 27843 if (!ba) { 27844 return []; 27845 } else { 27846 const overlappingBins = reg2bins(min, max); // List of bin #s that overlap min, max 27847 27848 const chunks = []; // Find chunks in overlapping bins. Leaf bins (< 4681) are not pruned 27849 27850 for (let binRange of overlappingBins) { 27851 for (let bin = binRange[0]; bin <= binRange[1]; bin++) { 27852 if (ba.binIndex[bin]) { 27853 const binChunks = ba.binIndex[bin], 27854 nchnk = binChunks.length; 27855 27856 for (let c = 0; c < nchnk; ++c) { 27857 const cs = binChunks[c][0]; 27858 const ce = binChunks[c][1]; 27859 chunks.push({ 27860 minv: cs, 27861 maxv: ce, 27862 bin: bin 27863 }); 27864 } 27865 } 27866 } 27867 } // Use the linear index to find minimum file position of chunks that could contain alignments in the region 27868 27869 27870 const nintv = ba.linearIndex.length; 27871 let lowest = null; 27872 const minLin = Math.min(min >> 14, nintv - 1); 27873 const maxLin = Math.min(max >> 14, nintv - 1); 27874 27875 for (let i = minLin; i <= maxLin; ++i) { 27876 const vp = ba.linearIndex[i]; 27877 27878 if (vp) { 27879 // todo -- I think, but am not sure, that the values in the linear index have to be in increasing order. So the first non-null should be minimum 27880 if (!lowest || vp.isLessThan(lowest)) { 27881 lowest = vp; 27882 } 27883 } 27884 } 27885 27886 return optimizeChunks(chunks, lowest); 27887 } 27888 } 27889 27890 } 27891 27892 function optimizeChunks(chunks, lowest) { 27893 const mergedChunks = []; 27894 let lastChunk = null; 27895 if (chunks.length === 0) return chunks; 27896 chunks.sort(function (c0, c1) { 27897 const dif = c0.minv.block - c1.minv.block; 27898 27899 if (dif !== 0) { 27900 return dif; 27901 } else { 27902 return c0.minv.offset - c1.minv.offset; 27903 } 27904 }); 27905 chunks.forEach(function (chunk) { 27906 if (!lowest || chunk.maxv.isGreaterThan(lowest)) { 27907 if (lastChunk === null) { 27908 mergedChunks.push(chunk); 27909 lastChunk = chunk; 27910 } else { 27911 if (canMerge(lastChunk, chunk)) { 27912 if (chunk.maxv.isGreaterThan(lastChunk.maxv)) { 27913 lastChunk.maxv = chunk.maxv; 27914 } 27915 } else { 27916 mergedChunks.push(chunk); 27917 lastChunk = chunk; 27918 } 27919 } 27920 } 27921 }); 27922 return mergedChunks; 27923 } 27924 /** 27925 * Merge 2 blocks if the gap between them is < 1kb and the total resulting size < 100mb 27926 * @param chunk1 27927 * @param chunk2 27928 * @returns {boolean|boolean} 27929 */ 27930 27931 27932 function canMerge(chunk1, chunk2) { 27933 const gap = chunk2.minv.block - chunk1.maxv.block; 27934 const total = chunk2.maxv.block - chunk1.minv.block; 27935 return gap < 30000 && total < 10 * MB; 27936 } 27937 /** 27938 * Calculate the list of bins that overlap with region [beg, end] 27939 * 27940 */ 27941 27942 27943 function reg2bins(beg, end) { 27944 const list = []; 27945 if (end >= 1 << 29) end = 1 << 29; 27946 --end; 27947 list.push([0, 0]); 27948 list.push([1 + (beg >> 26), 1 + (end >> 26)]); 27949 list.push([9 + (beg >> 23), 9 + (end >> 23)]); 27950 list.push([73 + (beg >> 20), 73 + (end >> 20)]); 27951 list.push([585 + (beg >> 17), 585 + (end >> 17)]); 27952 list.push([4681 + (beg >> 14), 4681 + (end >> 14)]); // for (k = 1 + (beg >> 26); k <= 1 + (end >> 26); ++k) list.push(k); 27953 // for (k = 9 + (beg >> 23); k <= 9 + (end >> 23); ++k) list.push(k); 27954 // for (k = 73 + (beg >> 20); k <= 73 + (end >> 20); ++k) list.push(k); 27955 // for (k = 585 + (beg >> 17); k <= 585 + (end >> 17); ++k) list.push(k); 27956 // for (k = 4681 + (beg >> 14); k <= 4681 + (end >> 14); ++k) list.push(k); 27957 27958 return list; 27959 } 27960 27961 /* 27962 * The MIT License (MIT) 27963 * 27964 * Copyright (c) 2014 Broad Institute 27965 * 27966 * Permission is hereby granted, free of charge, to any person obtaining a copy 27967 * of this software and associated documentation files (the "Software"), to deal 27968 * in the Software without restriction, including without limitation the rights 27969 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 27970 * copies of the Software, and to permit persons to whom the Software is 27971 * furnished to do so, subject to the following conditions: 27972 * 27973 * The above copyright notice and this permission notice shall be included in 27974 * all copies or substantial portions of the Software. 27975 * 27976 * 27977 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 27978 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27979 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27980 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27981 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27982 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27983 * THE SOFTWARE. 27984 */ 27985 27986 async function parseTribbleIndex(arrayBuffer, genome) { 27987 const index = new TribbleIndex(); 27988 index.parse(arrayBuffer, genome); 27989 return index; 27990 } 27991 27992 class TribbleIndex { 27993 constructor() {} 27994 27995 async parse(arrayBuffer, genome) { 27996 let blockMax = 0; 27997 this.chrIndex = {}; 27998 this.lastBlockPosition = []; 27999 const parser = new BinaryParser(new DataView(arrayBuffer)); 28000 readHeader(parser); 28001 let nChrs = parser.getInt(); 28002 28003 while (nChrs-- > 0) { 28004 // todo -- support interval tree index, we're assuming its a linear index 28005 let chr = parser.getString(); 28006 if (genome) chr = genome.getChromosomeName(chr); // Translate to canonical name 28007 28008 const binWidth = parser.getInt(); 28009 const nBins = parser.getInt(); 28010 const longestFeature = parser.getInt(); 28011 parser.getInt() > 0; 28012 parser.getInt(); // note the code below accounts for > 60% of the total time to read an index 28013 28014 let pos = parser.getLong(); 28015 const blocks = []; 28016 28017 for (let binNumber = 0; binNumber < nBins; binNumber++) { 28018 const nextPos = parser.getLong(); 28019 blocks.push({ 28020 min: pos, 28021 max: nextPos 28022 }); // {position: pos, size: size}); 28023 28024 pos = nextPos; 28025 28026 if (nextPos > blockMax) { 28027 blockMax = nextPos; 28028 } 28029 } 28030 28031 this.chrIndex[chr] = { 28032 chr: chr, 28033 blocks: blocks, 28034 longestFeature: longestFeature, 28035 binWidth: binWidth 28036 }; 28037 } 28038 28039 this.lastBlockPosition = blockMax; 28040 /** 28041 * Read the header . Data here is not used in igv.js but we need to read it to advance the pointer. 28042 * @param parser 28043 */ 28044 28045 function readHeader(parser) { 28046 parser.getInt(); // view._getInt32(offset += 32, true); 28047 28048 parser.getInt(); 28049 const version = parser.getInt(); 28050 parser.getString(); 28051 parser.getLong(); 28052 parser.getLong(); 28053 parser.getString(); 28054 parser.getInt(); 28055 28056 if (version >= 3) { 28057 let nProperties = parser.getInt(); 28058 28059 while (nProperties-- > 0) { 28060 parser.getString(); 28061 parser.getString(); 28062 } 28063 } 28064 } 28065 } 28066 28067 get chromosomeNames() { 28068 return Object.keys(this.chrIndex); 28069 } 28070 /** 28071 * Fetch blocks for a particular genomic range. 28072 * 28073 * @param queryChr the sequence dictionary index of the chromosome 28074 * @param min genomic start position 28075 * @param max genomic end position 28076 */ 28077 28078 28079 blocksForRange(queryChr, min, max) { 28080 const chrIdx = this.chrIndex[queryChr]; 28081 28082 if (chrIdx) { 28083 const blocks = chrIdx.blocks; 28084 const longestFeature = chrIdx.longestFeature; 28085 const binWidth = chrIdx.binWidth; 28086 const adjustedPosition = Math.max(min - longestFeature, 0); 28087 const startBinNumber = Math.floor(adjustedPosition / binWidth); 28088 if (startBinNumber >= blocks.length) // are we off the end of the bin list, so return nothing 28089 return [];else { 28090 const endBinNumber = Math.min(Math.floor((max - 1) / binWidth), blocks.length - 1); // By definition blocks are adjacent in the file for the liner index. Combine them into one merged block 28091 28092 const startPos = blocks[startBinNumber].min; 28093 const endPos = blocks[endBinNumber].max; 28094 const size = endPos - startPos; 28095 28096 if (size === 0) { 28097 return []; 28098 } else { 28099 const mergedBlock = { 28100 minv: { 28101 block: startPos, 28102 offset: 0 28103 }, 28104 maxv: { 28105 block: endPos, 28106 offset: 0 28107 } 28108 }; 28109 return [mergedBlock]; 28110 } 28111 } 28112 } else { 28113 return undefined; 28114 } 28115 } 28116 28117 } 28118 28119 const CSI1_MAGIC = 21582659; // CSI\1 28120 28121 const CSI2_MAGIC = 38359875; // CSI\2 28122 28123 const BAI_MAGIC = 21578050; 28124 const TABIX_MAGIC = 21578324; 28125 const TRIBBLE_MAGIC = 1480870228; // byte[]{'T', 'I', 'D', 'X'}; 28126 28127 /** 28128 * @param indexURL 28129 * @param config 28130 * @param tabix 28131 * 28132 */ 28133 28134 async function loadIndex(indexURL, config, genome) { 28135 let arrayBuffer = await igvxhr.loadArrayBuffer(indexURL, buildOptions(config)); 28136 let dv = new DataView(arrayBuffer); // Some indexs are bgzipped, specifically tabix, and csi. Bam (bai) are not. Tribble is usually not. 28137 // Check first 2 bytes of file for gzip magic number, and inflate if neccessary 28138 28139 if (dv.getUint8(0) === 0x1f && dv.getUint8(1) === 0x8b) { 28140 // gzipped 28141 const inflate = unbgzf(arrayBuffer); 28142 arrayBuffer = inflate.buffer; 28143 dv = new DataView(arrayBuffer); 28144 } 28145 28146 const magic = dv.getInt32(0, true); 28147 28148 switch (magic) { 28149 case BAI_MAGIC: 28150 return parseBamIndex(arrayBuffer, genome); 28151 28152 case TABIX_MAGIC: 28153 return parseTabixIndex(arrayBuffer, genome); 28154 28155 case CSI1_MAGIC: 28156 return parseCsiIndex(arrayBuffer, genome); 28157 28158 case TRIBBLE_MAGIC: 28159 return parseTribbleIndex(arrayBuffer, genome); 28160 28161 case CSI2_MAGIC: 28162 throw Error("CSI version 2 is not supported."); 28163 28164 default: 28165 throw Error(`Unrecognized index type: ${indexURL}`); 28166 } 28167 } 28168 28169 /* 28170 * The MIT License (MIT) 28171 * 28172 * Copyright (c) 2016-2017 The Regents of the University of California 28173 * Author: Jim Robinson 28174 * 28175 * Permission is hereby granted, free of charge, to any person obtaining a copy 28176 * of this software and associated documentation files (the "Software"), to deal 28177 * in the Software without restriction, including without limitation the rights 28178 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 28179 * copies of the Software, and to permit persons to whom the Software is 28180 * furnished to do so, subject to the following conditions: 28181 * 28182 * The above copyright notice and this permission notice shall be included in 28183 * all copies or substantial portions of the Software. 28184 * 28185 * 28186 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 28187 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 28188 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 28189 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28190 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28191 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 28192 * THE SOFTWARE. 28193 */ 28194 /** 28195 * Class for reading a bam file 28196 * 28197 * @param config 28198 * @constructor 28199 */ 28200 28201 class BamReader { 28202 constructor(config, genome) { 28203 this.config = config; 28204 this.genome = genome; 28205 this.bamPath = config.url; 28206 this.baiPath = config.indexURL; 28207 BamUtils.setReaderDefaults(this, config); 28208 } 28209 28210 async readAlignments(chr, bpStart, bpEnd) { 28211 const chrToIndex = await this.getChrIndex(); 28212 const queryChr = this.chrAliasTable.hasOwnProperty(chr) ? this.chrAliasTable[chr] : chr; 28213 const chrId = chrToIndex[queryChr]; 28214 const alignmentContainer = new AlignmentContainer(chr, bpStart, bpEnd, this.config.samplingWindowSize, this.config.samplingDepth, this.config.pairsSupported, this.config.alleleFreqThreshold); 28215 28216 if (chrId === undefined) { 28217 return alignmentContainer; 28218 } else { 28219 const bamIndex = await this.getIndex(); 28220 const chunks = bamIndex.blocksForRange(chrId, bpStart, bpEnd); 28221 28222 if (!chunks || chunks.length === 0) { 28223 return alignmentContainer; 28224 } 28225 28226 for (let c of chunks) { 28227 let lastBlockSize; 28228 28229 if (c.maxv.offset === 0) { 28230 lastBlockSize = 0; // Don't need to read the last block. 28231 } else { 28232 const bsizeOptions = buildOptions(this.config, { 28233 range: { 28234 start: c.maxv.block, 28235 size: 26 28236 } 28237 }); 28238 const abuffer = await igvxhr.loadArrayBuffer(this.bamPath, bsizeOptions); 28239 lastBlockSize = bgzBlockSize(abuffer); 28240 } 28241 28242 const fetchMin = c.minv.block; 28243 const fet
28243chMax = c.maxv.block + lastBlockSize; 28244 const range = { 28245 start: fetchMin, 28246 size: fetchMax - fetchMin + 1 28247 }; 28248 const compressed = await igvxhr.loadArrayBuffer(this.bamPath, buildOptions(this.config, { 28249 range: range 28250 })); 28251 var ba = unbgzf(compressed); //new Uint8Array(BGZip.unbgzf(compressed)); //, c.maxv.block - c.minv.block + 1)); 28252 28253 const done = BamUtils.decodeBamRecords(ba, c.minv.offset, alignmentContainer, this.indexToChr, chrId, bpStart, bpEnd, this.filter); 28254 28255 if (done) { 28256 // console.log(`Loaded ${counter} chunks out of ${chunks.length}`); 28257 break; 28258 } 28259 } 28260 28261 alignmentContainer.finish(); 28262 return alignmentContainer; 28263 } 28264 } 28265 28266 async getHeader() { 28267 if (!this.header) { 28268 const genome = this.genome; 28269 const index = await this.getIndex(); 28270 let len; 28271 28272 if (index.firstBlockPosition) { 28273 const bsizeOptions = buildOptions(this.config, { 28274 range: { 28275 start: index.firstBlockPosition, 28276 size: 26 28277 } 28278 }); 28279 const abuffer = await igvxhr.loadArrayBuffer(this.bamPath, bsizeOptions); 28280 const bsize = bgzBlockSize(abuffer); 28281 len = index.firstBlockPosition + bsize; // Insure we get the complete compressed block containing the header 28282 } else { 28283 len = 64000; 28284 } 28285 28286 const options = buildOptions(this.config, { 28287 range: { 28288 start: 0, 28289 size: len 28290 } 28291 }); 28292 this.header = await BamUtils.readHeader(this.bamPath, options, genome); 28293 } 28294 28295 return this.header; 28296 } 28297 28298 async getIndex() { 28299 const genome = this.genome; 28300 28301 if (!this.index) { 28302 this.index = await loadIndex(this.baiPath, this.config, genome); 28303 } 28304 28305 return this.index; 28306 } 28307 28308 async getChrIndex() { 28309 if (this.chrToIndex) { 28310 return this.chrToIndex; 28311 } else { 28312 const header = await this.getHeader(); 28313 this.chrToIndex = header.chrToIndex; 28314 this.indexToChr = header.chrNames; 28315 this.chrAliasTable = header.chrAliasTable; 28316 return this.chrToIndex; 28317 } 28318 } 28319 28320 } 28321 28322 /* 28323 * The MIT License (MIT) 28324 * 28325 * Copyright (c) 2016-2017 The Regents of the University of California 28326 * Author: Jim Robinson 28327 * 28328 * Permission is hereby granted, free of charge, to any person obtaining a copy 28329 * of this software and associated documentation files (the "Software"), to deal 28330 * in the Software without restriction, including without limitation the rights 28331 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 28332 * copies of the Software, and to permit persons to whom the Software is 28333 * furnished to do so, subject to the following conditions: 28334 * 28335 * The above copyright notice and this permission notice shall be included in 28336 * all copies or substantial portions of the Software. 28337 * 28338 * 28339 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 28340 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 28341 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 28342 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28343 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28344 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 28345 * THE SOFTWARE. 28346 */ 28347 28348 class ShardedBamReader { 28349 constructor(config, genome) { 28350 this.config = config; 28351 this.genome = genome; 28352 const bamReaders = {}; 28353 config.sources.sequences.forEach(function (chr) { 28354 const queryChr = genome ? genome.getChromosomeName(chr) : chr; 28355 bamReaders[queryChr] = getReader(config, genome, chr); 28356 }); 28357 this.bamReaders = bamReaders; 28358 BamUtils.setReaderDefaults(this, config); 28359 } 28360 28361 async readAlignments(chr, start, end) { 28362 if (!this.bamReaders.hasOwnProperty(chr)) { 28363 return new AlignmentContainer(chr, start, end); 28364 } else { 28365 let reader = this.bamReaders[chr]; 28366 const a = await reader.readAlignments(chr, start, end); 28367 return a; 28368 } 28369 } 28370 28371 } 28372 28373 function getReader(config, genome, chr) { 28374 const tmp = { 28375 url: config.sources.url.replace("$CHR", chr) 28376 }; 28377 28378 if (config.sources.indexURL) { 28379 tmp.indexURL = config.sources.indexURL.replace("$CHR", chr); 28380 } 28381 28382 const bamConfig = Object.assign(config, tmp); // TODO -- support non-indexed, htsget, etc 28383 28384 return new BamReader(bamConfig, genome); 28385 } 28386 28387 /* 28388 * The MIT License (MIT) 28389 * 28390 * Copyright (c) 2016-2017 The Regents of the University of California 28391 * Author: Jim Robinson 28392 * 28393 * Permission is hereby granted, free of charge, to any person obtaining a copy 28394 * of this software and associated documentation files (the "Software"), to deal 28395 * in the Software without restriction, including without limitation the rights 28396 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 28397 * copies of the Software, and to permit persons to whom the Software is 28398 * furnished to do so, subject to the following conditions: 28399 * 28400 * The above copyright notice and this permission notice shall be included in 28401 * all copies or substantial portions of the Software. 28402 * 28403 * 28404 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 28405 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 28406 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 28407 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28408 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28409 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 28410 * THE SOFTWARE. 28411 */ 28412 /** 28413 * Class for reading bam records from an igv.js-flask server backed by pysam. Deprecated. 28414 * 28415 * @param config 28416 * @constructor 28417 */ 28418 28419 const BamWebserviceReader = function (config, genome) { 28420 this.config = config; 28421 this.genome = genome; 28422 BamUtils.setReaderDefaults(this, config); 28423 }; // Example http://localhost:5000/alignments/?reference=/Users/jrobinso/hg19mini.fa&file=/Users/jrobinso/cram_with_crai_index.cram®ion=1:100-2000 28424 28425 28426 BamWebserviceReader.prototype.readAlignments = function (chr, bpStart, bpEnd) { 28427 var self = this; 28428 return getHeader.call(self).then(function (header) { 28429 var queryChr, url; 28430 queryChr = header.chrAliasTable.hasOwnProperty(chr) ? header.chrAliasTable[chr] : chr; 28431 url = self.config.url + "?reference=" + self.config.referenceFile + "&file=" + self.config.alignmentFile + "" + "®ion=" + queryChr + ":" + bpStart + "-" + bpEnd; 28432 return igvxhr.loadString(url, buildOptions(self.config)).then(function (sam) { 28433 var alignmentContainer; 28434 header.chrToIndex[queryChr]; 28435 alignmentContainer = new AlignmentContainer(chr, bpStart, bpEnd, self.samplingWindowSize, self.samplingDepth, self.pairsSupported, self.alleleFreqThreshold); 28436 BamUtils.decodeSamRecords(sam, alignmentContainer, queryChr, bpStart, bpEnd, self.filter); 28437 return alignmentContainer; 28438 }); 28439 }); 28440 }; // Example http://localhost:5000/alignments/?reference=/Users/jrobinso/hg19mini.fa&file=/Users/jrobinso/cram_with_crai_index.cram&options=-b%20-H 28441 28442 28443 function getHeader() { 28444 const self = this; 28445 const genome = this.genome; 28446 28447 if (this.header) { 28448 return Promise.resolve(this.header); 28449 } else { 28450 const url = this.config.url + "?file=" + this.config.alignmentFile + "&options=-b,-H"; 28451 const options = buildOptions(this.config); 28452 return BamUtils.readHeader(url, options, genome).then(function (header) { 28453 self.header = header; 28454 return header; 28455 }); 28456 } 28457 } 28458 28459 class HtsgetReader { 28460 constructor(config, genome) { 28461 this.config = config; 28462 this.genome = genome; 28463 this.format = config.format ? config.format.toUpperCase() : "BAM"; // Backward compatibility 28464 28465 if (!(this.format === "BAM" || this.format === "VCF")) { 28466 throw Error(`htsget format ${config.format} is not supported`); 28467 } 28468 } 28469 28470 async readHeaderData() { 28471 const url = `${getUrl(this.config)}?class=header&format=${this.format}`; 28472 const ticket = await igvxhr.loadJson(url, buildOptions(this.config)); 28473 return await this.loadUrls(ticket.htsget.urls); 28474 } 28475 28476 async readData(chr, start, end) { 28477 const url = `${getUrl(this.config)}?format=${this.format}&referenceName=${chr}&start=${Math.floor(start)}&end=${Math.ceil(end)}`; 28478 const ticket = await igvxhr.loadJson(url, buildOptions(this.config)); 28479 return this.loadUrls(ticket.htsget.urls); 28480 } 28481 28482 async loadUrls(urls) { 28483 const promiseArray = []; 28484 28485 for (let urlData of urls) { 28486 if (urlData.url.startsWith('data:')) { 28487 // this is a data-uri
28488 promiseArray.push(Promise.resolve(dataUriToBytes(urlData.url))); 28489 } else { 28490 const options = buildOptions(this.config || {}); 28491 28492 if (urlData.headers) { 28493 options.headers = Object.assign(options.headers || {}, urlData.headers); 28494 } 28495 28496 promiseArray.push(igvxhr.loadArrayBuffer(urlData.url, options)); 28497 } 28498 } 28499 28500 const arrayBuffers = await Promise.all(promiseArray); 28501 return concatArrays(arrayBuffers); 28502 } 28503 28504 static async inferFormat(config) { 28505 try { 28506 const url = getUrl(config); 28507 const headerURL = `${url}${url.includes("?") ? "&" : "?"}class=header`; 28508 const ticket = await igvxhr.loadJson(headerURL, buildOptions(config)); 28509 28510 if (ticket.htsget) { 28511 const format = ticket.htsget.format; 28512 28513 if (!(format === "BAM" || format === "VCF")) { 28514 throw Error(`htsget format ${format} is not supported`); 28515 } 28516 28517 config.format = format.toLowerCase(); 28518 config.sourceType = "htsget"; 28519 28520 if (!config.name) { 28521 config.name = await getFilename(config.url); 28522 } 28523 } 28524 } catch (e) {// Errors => this is not an htsget source, not an application error. Ignore 28525 } 28526 } 28527 28528 } 28529 /** 28530 * Extract the full url from the config. Striving for backward compatibility, "endpoint" and "id" are deprecated. 28531 * 28532 * @param config 28533 */ 28534 28535 28536 function getUrl(config) { 28537 if (config.url && config.endpoint && config.id) { 28538 return config.url + config.endpoint + config.id; // Deprecated 28539 } else if (config.endpoint && config.id) { 28540 return config.endpoint + config.id; // Deprecated 28541 } else if (config.url) { 28542 if (config.url.startsWith("htsget://")) { 28543 return config.url.replace("htsget://", "https://"); // htsget -> http not supported 28544 } else { 28545 return config.url; 28546 } 28547 } else { 28548 throw Error("Must specify either 'url', or 'endpoint' and 'id"); 28549 } 28550 } 28551 /** 28552 * Concatenate a list of array buffers, returning an UInt8Array 28553 * @param arrayBuffers 28554 */ 28555 28556 28557 function concatArrays(arrayBuffers) { 28558 let len = 0; 28559 28560 for (let a of arrayBuffers) { 28561 len += a.byteLength; 28562 } 28563 28564 let offset = 0; 28565 const newArray = new Uint8Array(len); 28566 28567 for (let buf of arrayBuffers) { 28568 const a = new Uint8Array(buf); 28569 newArray.set(a, offset); 28570 offset += a.length; 28571 } 28572 28573 return newArray; 28574 } 28575 28576 function dataUriToBytes(dataUri) { 28577 const split = dataUri.split(','); 28578 const info = split[0].split(':')[1]; 28579 let dataString = split[1]; 28580 28581 if (info.indexOf('base64') >= 0) { 28582 dataString = atob(dataString); 28583 } else { 28584 dataString = decodeURI(dataString); 28585 } 28586 28587 const bytes = new Uint8Array(dataString.length); 28588 28589 for (var i = 0; i < dataString.length; i++) { 28590 bytes[i] = dataString.charCodeAt(i); 28591 } 28592 28593 return bytes; 28594 } 28595 28596 /* 28597 * The MIT License (MIT) 28598 * 28599 * Copyright (c) 2016-2017 The Regents of the University of California 28600 * Author: Jim Robinson 28601 * 28602 * Permission is hereby granted, free of charge, to any person obtaining a copy 28603 * of this software and associated documentation files (the "Software"), to deal 28604 * in the Software without restriction, including without limitation the rights 28605 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 28606 * copies of the Software, and to permit persons to whom the Software is 28607 * furnished to do so, subject to the following conditions: 28608 * 28609 * The above copyright notice and this permission notice shall be included in 28610 * all copies or substantial portions of the Software. 28611 * 28612 * 28613 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 28614 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 28615 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 28616 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28617 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28618 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 28619 * THE SOFTWARE. 28620 */ 28621 28622 class HtsgetBamReader extends HtsgetReader { 28623 constructor(config, genome) { 28624 super(config, genome); 28625 BamUtils.setReaderDefaults(this, config); 28626 } 28627 28628 async readAlignments(chr, start, end) { 28629 if (!this.header) { 28630 const compressedData = await this.readHeaderData(); 28631 const ba = unbgzf(compressedData.buffer); 28632 this.header = BamUtils.decodeBamHeader(ba, this.genome); 28633 this.chrAliasTable = new Map(); 28634 28635 for (let key of Object.keys(this.header.chrAliasTable)) { 28636 this.chrAliasTable.set(key, this.header.chrAliasTable[key]); 28637 } 28638 } 28639 28640 let queryChr = this.chrAliasTable.has(chr) ? this.chrAliasTable.get(chr) : chr; 28641 const compressedData = await this.readData(queryChr, start, end); // BAM decoding 28642 28643 const ba = unbgzf(compressedData.buffer); 28644 const chrIdx = this.header.chrToIndex[chr]; 28645 const alignmentContainer = new AlignmentContainer(chr, start, end, this.samplingWindowSize, this.samplingDepth, this.pairsSupported, this.alleleFreqThreshold); 28646 BamUtils.decodeBamRecords(ba, this.header.size, alignmentContainer, this.header.chrNames, chrIdx, start, end); 28647 alignmentContainer.finish(); 28648 return alignmentContainer; 28649 } 28650 28651 } 28652 28653 var $propertyIsEnumerable = {}.propertyIsEnumerable; // eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe 28654 28655 var getOwnPropertyDescriptor$1 = Object.getOwnPropertyDescriptor; // Nashorn ~ JDK8 bug 28656 28657 var NASHORN_BUG = getOwnPropertyDescriptor$1 && !$propertyIsEnumerable.call({ 28658 1: 2 28659 }, 1); // `Object.prototype.propertyIsEnumerable` method implementation 28660 // https://tc39.es/ecma262/#sec-object.prototype.propertyisenumerable 28661 28662 var f$3 = NASHORN_BUG ? function propertyIsEnumerable(V) { 28663 var descriptor = getOwnPropertyDescriptor$1(this, V); 28664 return !!descriptor && descriptor.enumerable; 28665 } : $propertyIsEnumerable; 28666 var objectPropertyIsEnumerable = { 28667 f: f$3 28668 }; 28669 28670 var Object$1 = global$1.Object; 28671 var split = functionUncurryThis(''.split); // fallback for non-array-like ES3 and non-enumerable old V8 strings 28672 28673 var indexedObject = fails(function () { 28674 // throws an error in rhino, see https://github.com/mozilla/rhino/issues/346 28675 // eslint-disable-next-line no-prototype-builtins -- safe 28676 return !Object$1('z').propertyIsEnumerable(0); 28677 }) ? function (it) { 28678 return classofRaw(it) == 'String' ? split(it, '') : Object$1(it); 28679 } : Object$1; 28680 28681 var toIndexedObject = function (it) { 28682 return indexedObject(requireObjectCoercible(it)); 28683 }; 28684 28685 var $getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; // `Object.getOwnPropertyDescriptor` method 28686 // https://tc39.es/ecma262/#sec-object.getownpropertydescriptor 28687 28688 var f$2 = descriptors ? $getOwnPropertyDescriptor : function getOwnPropertyDescriptor(O, P) { 28689 O = toIndexedObject(O); 28690 P = toPropertyKey(P); 28691 if (ie8DomDefine) try { 28692 return $getOwnPropertyDescriptor(O, P); 28693 } catch (error) { 28694 /* empty */ 28695 } 28696 if (hasOwnProperty_1(O, P)) return createPropertyDescriptor(!functionCall(objectPropertyIsEnumerable.f, O, P), O[P]); 28697 }; 28698 var objectGetOwnPropertyDescriptor = { 28699 f: f$2 28700 }; 28701 28702 var createMethod = function (IS_INCLUDES) { 28703 return function ($this, el, fromIndex) { 28704 var O = toIndexedObject($this); 28705 var length = lengthOfArrayLike(O); 28706 var index = toAbsoluteIndex(fromIndex, length); 28707 var value; // Array#includes uses SameValueZero equality algorithm 28708 // eslint-disable-next-line no-self-compare -- NaN check 28709
vendor: 4,301 bytes, lines 28710-28816
28710 if (IS_INCLUDES && el != el) while (length > index) { 28711 value = O[index++]; // eslint-disable-next-line no-self-compare -- NaN check 28712 28713 if (value != value) return true; // Array#indexOf ignores holes, Array#includes - not 28714 } else for (; length > index; index++) { 28715 if ((IS_INCLUDES || index in O) && O[index] === el) return IS_INCLUDES || index || 0; 28716 } 28717 return !IS_INCLUDES && -1; 28718 }; 28719 }; 28720 28721 var arrayIncludes = { 28722 // `Array.prototype.includes` method 28723 // https://tc39.es/ecma262/#sec-array.prototype.includes 28724 includes: createMethod(true), 28725 // `Array.prototype.indexOf` method 28726 // https://tc39.es/ecma262/#sec-array.prototype.indexof 28727 indexOf: createMethod(false) 28728 }; 28729 28730 var indexOf = arrayIncludes.indexOf; 28731 var push = functionUncurryThis([].push); 28732 28733 var objectKeysInternal = function (object, names) { 28734 var O = toIndexedObject(object); 28735 var i = 0; 28736 var result = []; 28737 var key; 28738 28739 for (key in O) !hasOwnProperty_1(hiddenKeys$1, key) && hasOwnProperty_1(O, key) && push(result, key); // Don't enum bug & hidden keys 28740 28741 28742 while (names.length > i) if (hasOwnProperty_1(O, key = names[i++])) { 28743 ~indexOf(result, key) || push(result, key); 28744 } 28745 28746 return result; 28747 }; 28748 28749 // IE8- don't enum bug keys 28750 var enumBugKeys = ['constructor', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', 'toLocaleString', 'toString', 'valueOf']; 28751 28752 var hiddenKeys = enumBugKeys.concat('length', 'prototype'); // `Object.getOwnPropertyNames` method 28753 // https://tc39.es/ecma262/#sec-object.getownpropertynames 28754 // eslint-disable-next-line es/no-object-getownpropertynames -- safe 28755 28756 var f$1 = Object.getOwnPropertyNames || function getOwnPropertyNames(O) { 28757 return objectKeysInternal(O, hiddenKeys); 28758 }; 28759 28760 var objectGetOwnPropertyNames = { 28761 f: f$1 28762 }; 28763 28764 // eslint-disable-next-line es/no-object-getownpropertysymbols -- safe 28765 var f = Object.getOwnPropertySymbols; 28766 var objectGetOwnPropertySymbols = { 28767 f: f 28768 }; 28769 28770 var concat = functionUncurryThis([].concat); // all object keys, includes non-enumerable and symbols 28771 28772 var ownKeys = getBuiltIn('Reflect', 'ownKeys') || function ownKeys(it) { 28773 var keys = objectGetOwnPropertyNames.f(anObject(it)); 28774 var getOwnPropertySymbols = objectGetOwnPropertySymbols.f; 28775 return getOwnPropertySymbols ? concat(keys, getOwnPropertySymbols(it)) : keys; 28776 }; 28777 28778 var copyConstructorProperties = function (target, source) { 28779 var keys = ownKeys(source); 28780 var defineProperty = objectDefineProperty.f; 28781 var getOwnPropertyDescriptor = objectGetOwnPropertyDescriptor.f; 28782 28783 for (var i = 0; i < keys.length; i++) { 28784 var key = keys[i]; 28785 if (!hasOwnProperty_1(target, key)) defineProperty(target, key, getOwnPropertyDescriptor(source, key)); 28786 } 28787 }; 28788 28789 var replacement = /#|\.prototype\./; 28790 28791 var isForced = function (feature, detection) { 28792 var value = data[normalize(feature)]; 28793 return value == POLYFILL ? true : value == NATIVE ? false : isCallable(detection) ? fails(detection) : !!detection; 28794 }; 28795 28796 var normalize = isForced.normalize = function (string) { 28797 return String(string).replace(replacement, '.').toLowerCase(); 28798 }; 28799 28800 var data = isForced.data = {}; 28801 var NATIVE = isForced.NATIVE = 'N'; 28802 var POLYFILL = isForced.POLYFILL = 'P'; 28803 var isForced_1 = isForced; 28804 28805 var getOwnPropertyDescriptor = objectGetOwnPropertyDescriptor.f; 28806 /* 28807 options.target - name of the target object 28808 options.global - target is the global object 28809 options.stat - export as static methods of target 28810 options.proto - export as prototype methods of target 28811 options.real - real prototype method for the `pure` version 28812 options.forced - export even if the native feature is available 28813 options.bind - bind methods to the target, required for the `pure` version 28814 options.wrap - wrap constructors to preventing global pollution, required for the `pure` version 28815 options.unsafe - use the simple assignment of property instead of delete + defineProperty 28816 options.sham - add a flag to not completely full pol
28816yfills 28817 options.enumerable - export as enumerable property 28818 options.noTargetGet - prevent calling a getter on target 28819 options.name - the .name of the function if it does not match the key 28820 */ 28821 28822 var _export = function (options, source) { 28823 var TARGET = options.target; 28824 var GLOBAL = options.global; 28825 var STATIC = options.stat; 28826 var FORCED, target, key, targetProperty, sourceProperty, descriptor; 28827 28828 if (GLOBAL) { 28829 target = global$1; 28830 } else if (STATIC) { 28831 target = global$1[TARGET] || setGlobal(TARGET, {}); 28832 } else { 28833 target = (global$1[TARGET] || {}).prototype; 28834 } 28835 28836 if (target) for (key in source) { 28837 sourceProperty = source[key]; 28838 28839 if (options.noTargetGet) { 28840 descriptor = getOwnPropertyDescriptor(target, key); 28841 targetProperty = descriptor && descriptor.value; 28842 } else targetProperty = target[key]; 28843 28844 FORCED = isForced_1(GLOBAL ? key : TARGET + (STATIC ? '.' : '#') + key, options.forced); // contained in target 28845 28846 if (!FORCED && targetProperty !== undefined) { 28847 if (typeof sourceProperty == typeof targetProperty) continue; 28848 copyConstructorProperties(sourceProperty, targetProperty); 28849 } // add a flag to not completely full polyfills 28850 28851 28852 if (options.sham || targetProperty && targetProperty.sham) { 28853 createNonEnumerableProperty(sourceProperty, 'sham', true); 28854 } // extend global 28855 28856 28857 redefine(target, key, sourceProperty, options); 28858 } 28859 }; 28860 28861 var FunctionPrototype = Function.prototype; 28862 var apply = FunctionPrototype.apply; 28863 var bind$1 = FunctionPrototype.bind; 28864 var call = FunctionPrototype.call; // eslint-disable-next-line es/no-reflect -- safe 28865 28866 var functionApply = typeof Reflect == 'object' && Reflect.apply || (bind$1 ? call.bind(apply) : function () { 28867 return call.apply(apply, arguments); 28868 }); 28869 28870 var bind = functionUncurryThis(functionUncurryThis.bind); // optional / simple context binding 28871 28872 var functionBindContext = function (fn, that) { 28873 aCallable(fn); 28874 return that === undefined ? fn : bind ? bind(fn, that) : function 28875 /* ...args */ 28876 () { 28877 return fn.apply(that, arguments); 28878 }; 28879 }; 28880 28881 var html = getBuiltIn('document', 'documentElement'); 28882 28883 var arraySlice = functionUncurryThis([].slice); 28884 28885 var engineIsIos = /(?:ipad|iphone|ipod).*applewebkit/i.test(engineUserAgent); 28886 28887 var engineIsNode = classofRaw(global$1.process) == 'process'; 28888 28889 var set = global$1.setImmediate; 28890 var clear = global$1.clearImmediate; 28891 var process$1 = global$1.process; 28892 var Dispatch = global$1.Dispatch; 28893 var Function$1 = global$1.Function; 28894 var MessageChannel$1 = global$1.MessageChannel; 28895 var String$1 = global$1.String; 28896 var counter = 0; 28897 var queue = {}; 28898 var ONREADYSTATECHANGE = 'onreadystatechange'; 28899 var location, defer, channel, port; 28900 28901 try { 28902 // Deno throws a ReferenceError on `location` access without `--location` flag 28903 location = global$1.location; 28904 } catch (error) { 28905 /* empty */ 28906 } 28907 28908 var run = function (id) { 28909 if (hasOwnProperty_1(queue, id)) { 28910 var fn = queue[id]; 28911 delete queue[id]; 28912 fn(); 28913 } 28914 }; 28915 28916 var runner = function (id) { 28917 return function () { 28918 run(id); 28919 }; 28920 }; 28921 28922 var listener = function (event) { 28923 run(event.data); 28924 }; 28925 28926 var post = function (id) { 28927 // old engines have not location.origin 28928 global$1.postMessage(String$1(id), location.protocol + '//' + location.host); 28929 }; // Node.js 0.9+ & IE10+ has setImmediate, otherwise: 28930 28931 28932 if (!set || !clear) { 28933 set = function setImmediate(fn) { 28934 var args = arraySlice(arguments, 1); 28935 28936 queue[++counter] = function () { 28937 functionApply(isCallable(fn) ? fn : Function$1(fn), undefined, args); 28938 }; 28939 28940 defer(counter); 28941 return counter; 28942 }; 28943 28944 clear = function clearImmediate(id) { 28945 delete queue[id]; 28946 }; // Node.js 0.8- 28947 28948 28949 if (engineIsNode) { 28950 defer = function (id) { 28951 process$1.nextTick(runner(id)); 28952 }; // Sphere (JS game engine) Dispatch API 28953 28954 } else if (Dispatch && Dispatch.now) { 28955 defer = function (id) { 28956 Dispatch.now(runner(id)); 28957 }; // Browsers with MessageChannel, includes WebWorkers 28958 // except iOS - https://github.com/zloirock/core-js/issues/624 28959 28960 } else if (MessageChannel$1 && !engineIsIos) { 28961 channel = new MessageChannel$1(); 28962 port = channel.port2; 28963 channel.port1.onmessage = listener; 28964 defer = functionBindContext(port.postMessage, port); // Browsers with postMessage, skip WebWorkers 28965 // IE8 has postMessage, but it's sync & typeof its postMessage is 'object' 28966 } else if (global$1.addEventListener && isCallable(global$1.postMessage) && !global$1.importScripts && location && location.protocol !== 'file:' && !fails(post)) { 28967 defer = post; 28968 global$1.addEventListener('message', listener, false); // IE8- 28969 } else if (ONREADYSTATECHANGE in documentCreateElement('script')) { 28970 defer = function (id) { 28971 html.appendChild(documentCreateElement('script'))[ONREADYSTATECHANGE] = function () { 28972 html.removeChild(this); 28973 run(id); 28974 }; 28975 }; // Rest old browsers 28976 28977 } else { 28978 defer = function (id) { 28979 setTimeout(runner(id), 0); 28980 }; 28981 } 28982 } 28983 28984 var task = { 28985 set: set, 28986 clear: clear 28987 }; 28988 28989 var FORCED = !global$1.setImmediate || !global$1.clearImmediate; // http://w3c.github.io/setImmediate/ 28990 28991 _export({ 28992 global: true, 28993 bind: true, 28994 enumerable: true, 28995 forced: FORCED 28996 }, {
28997 // `setImmediate` method 28998 // http://w3c.github.io/setImmediate/#si-setImmediate 28999 setImmediate: task.set, 29000 // `clearImmediate` method 29001 // http://w3c.github.io/setImmediate/#si-clearImmediate 29002 clearImmediate: task.clear 29003 }); 29004 29005 const eval2 = eval; 29006 29007 const gmodCRAM = function (t) { 29008 var e = {}; 29009 29010 function r(n) { 29011 if (e[n]) return e[n].exports; 29012 var i = e[n] = { 29013 i: n, 29014 l: !1, 29015 exports: {} 29016 }; 29017 return t[n].call(i.exports, i, i.exports, r), i.l = !0, i.exports; 29018 } 29019 29020 return r.m = t, r.c = e, r.d = function (t, e, n) { 29021 r.o(t, e) || Object.defineProperty(t, e, { 29022 enumerable: !0, 29023 get: n 29024 }); 29025 }, r.r = function (t) { 29026 "undefined" != typeof Symbol && Symbol.toStringTag && Object.defineProperty(t, Symbol.toStringTag, { 29027 value: "Module" 29028 }), Object.defineProperty(t, "__esModule", { 29029 value: !0 29030 }); 29031 }, r.t = function (t, e) { 29032 if (1 & e && (t = r(t)), 8 & e) return t; 29033 if (4 & e && "object" == typeof t && t && t.__esModule) return t; 29034 var n = Object.create(null); 29035 if (r.r(n), Object.defineProperty(n, "default", { 29036 enumerable: !0, 29037 value: t 29038 }), 2 & e && "string" != typeof t) for (var i in t) r.d(n, i, function (e) { 29039 return t[e]; 29040 }.bind(null, i)); 29041 return n; 29042 }, r.n = function (t) { 29043 var e = t && t.__esModule ? function () { 29044 return t.default; 29045 } : function () { 29046 return t; 29047 }; 29048 return r.d(e, "a", e), e; 29049 }, r.o = function (t, e) { 29050 return Object.prototype.hasOwnProperty.call(t, e); 29051 }, r.p = "", r(r.s = 163); 29052 }([function (t, e, r) { 29053 29054 var n = r(13), 29055 i = r(81).f, 29056 o = r(107), 29057 a = r(3), 29058 s = r(15), 29059 u = r(20), 29060 f = r(24), 29061 c = function (t) { 29062 var e = function (e, r, n) { 29063 if (this instanceof t) { 29064 switch (arguments.length) { 29065 case 0: 29066 return new t(); 29067 29068 case 1: 29069 return new t(e); 29070 29071 case 2: 29072 return new t(e, r); 29073 } 29074 29075 return new t(e, r, n); 29076 } 29077 29078 return t.apply(this, arguments); 29079 }; 29080 29081 return e.prototype = t.prototype, e; 29082 }; 29083 29084 t.exports = function (t, e) { 29085 var r, 29086 l, 29087 h, 29088 d, 29089 p, 29090 g, 29091 v, 29092 y, 29093 m = t.target, 29094 b = t.global, 29095 _ = t.stat, 29096 w = t.proto, 29097 x = b ? n : _ ? n[m] : (n[m] || {}).prototype, 29098 E = b ? a : a[m] || (a[m] = {}), 29099 S = E.prototype; 29100 29101 for (h in e) r = !o(b ? h : m + (_ ? "." : "#") + h, t.forced) && x && f(x, h), p = E[h], r && (g = t.noTargetGet ? (y = i(x, h)) && y.value : x[h]), d = r && g ? g : e[h], r && typeof p == typeof d || (v = t.bind && r ? s(d, n) : t.wrap && r ? c(d) : w && "function" == typeof d ? s(Function.call, d) : d, (t.sham || d && d.sham || p && p.sham) && u(v, "sham", !0), E[h] = v, w && (f(a, l = m + "Prototype") || u(a, l, {}), a[l][h] = d, t.real && S && !S[h] && u(S, h, d))); 29102 }; 29103 }, function (t, e) { 29104 t.exports = function (t) { 29105 return t && t.__esModule ? t : { 29106 default: t 29107 }; 29108 }; 29109 }, function (t, e, r) { 29110 var n = r(14); 29111 29112 t.exports = function (t) { 29113 if (!n(t)) throw TypeError(String(t) + " is not an object"); 29114 return t; 29115 }; 29116 }, function (t, e) { 29117 t.exports = {}; 29118 }, function (t, e) { 29119 t.exports = !0; 29120 }, function (t, e) { 29121 t.exports = function (t) { 29122 if ("function" != typeof t) throw TypeError(String(t) + " is not a function"); 29123 return t; 29124 }; 29125 }, function (t, e, r) { 29126 var n = r(13), 29127 i = r(61), 29128 o = r(64), 29129 a = r(110), 29130 s = n.Symbol, 29131 u = i("wks"); 29132 29133 t.exports = function (t) { 29134 return u[t] || (u[t] = a && s[t] || (a ? s : o)("Symbol." + t)); 29135 }; 29136 }, function (t, e) { 29137 t.exports = function (t, e) { 29138 if (!(t instanceof e)) throw new TypeError("Cannot call a class as a function"); 29139 }; 29140 }, function (t, e, r) { 29141 var n = r(2), 29142 i = r(119), 29143 o = r(29), 29144 a = r(15), 29145 s = r(90), 29146 u = r(120), 29147 f = function (t, e) { 29148 this.stopped = t, this.result = e; 29149 }; 29150 29151 (t.exports = function (t, e, r, c, l) { 29152 var h, 29153 d, 29154 p, 29155 g, 29156 v, 29157 y, 29158 m = a(e, r, c ? 2 : 1); 29159 if (l) h = t;else { 29160 if ("function" != typeof (d = s(t))) throw TypeError("Target is not iterable"); 29161 29162 if (i(d)) { 29163 for (p = 0, g = o(t.length); g > p; p++) if ((v = c ? m(n(y = t[p])[0], y[1]) : m(t[p])) && v instanceof f) return v; 29164 29165 return new f(!1); 29166 } 29167 29168 h = d.call(t); 29169 } 29170 29171 for (; !(y = h.next()).done;) if ((v = u(h, m, y.value, c)) && v instanceof f) return v; 29172 29173 return new f(!1); 29174 }).stop = function (t) { 29175 return new f(!0, t); 29176 }; 29177 }, function (t, e, r) { 29178 29179 var n = r(1), 29180 i = n(r(7)), 29181 o = n(r(32)), 29182 a = n(r(27)), 29183 s = n(r(33)), 29184 u = n(r(265)), 29185 f = function (t) { 29186 function e() { 29187 return (0, i.default)(this, e), (0, o.default)(this, (0, a.default)(e).apply(this, arguments)); 29188 } 29189 29190 return (0, s.default)(e, t), e; 29191 }((0, u.default)(Error)), 29192 c = function (t) { 29193 function e() { 29194 return (0, i.default)(this, e), (0, o.default)(this, (0, a.default)(e).apply(this, arguments)); 29195 } 29196 29197 return (0, s.default)(e, t), e; 29198 }((0, u.default)(Error)), 29199 l = function (t) { 29200 function e() { 29201 return (0, i.default)(this, e), (0, o.default)(this, (0, a.default)(e).apply(this, arguments)); 29202 } 29203 29204 return (0, s.default)(e, t), e; 29205 }(f), 29206 h = function (t) { 29207 function e() { 29208 return (0, i.default)(this, e), (0, o.default)(this, (0, a.default)(e).apply(this, arguments)); 29209 } 29210 29211 return (0, s.default)(e, t), e; 29212 }(l), 29213 d = function (t) { 29214 function e() { 29215 return (0, i.default)(this, e), (0, o.default)(this, (0, a.default)(e).apply(this, arguments)); 29216 } 29217 29218 return (0, s.default)(e, t), e; 29219 }(f), 29220 p = function (t) { 29221 function e() { 29222 return (0, i.default)(this, e), (0, o.default)(this, (0, a.default)(e).apply(this, arguments)); 29223 } 29224 29225 return (0, s.default)(e, t), e; 29226 }(f); 29227 29228 t.exports = { 29229 CramBufferOverrunError: h, 29230 CramMalformedError: l, 29231 CramUnimplementedError: c, 29232 CramSizeLimitError: d, 29233 CramArgumentError: p 29234 }; 29235 }, function (t, e, r) { 29236 var n = r(196); 29237 29238 function i(t, e) { 29239 for (var r = 0; r < e.length; r++) { 29240 var i = e[r]; 29241 i.enumerable = i.enumerable || !1, i.configurable = !0, "value" in i && (i.writable = !0), n(t, i.key, i); 29242 } 29243 } 29244 29245 t.exports = function (t, e, r) { 29246 return e && i(t.prototype, e), r && i(t, r), t; 29247 }; 29248 }, function (t, e, r) { 29249 var n = r(3), 29250 i = r(24), 29251 o = r(95), 29252 a = r(21).f; 29253 29254 t.exports = function (t) { 29255 var e = n.Symbol || (n.Symbol = {}); 29256 i(e, t) || a(e, t, { 29257 value: o.f(t) 29258 }); 29259 }; 29260 }, function (t, e) { 29261 t.exports = function (t) { 29262 try { 29263 return !!t(); 29264 } catch (t) { 29265 return !0; 29266 } 29267 }; 29268 }, function (t, e, r) { 29269 (function (e) { 29270 var r = "object", 29271 n = function (t) { 29272 return t && t.Math == Math && t; 29273 }; 29274 29275 t.exports = n(typeof globalThis == r && globalThis) || n(typeof window == r && window) || n(typeof self == r && self) || n(typeof e == r && e) || Function("return this")(); 29276 }).call(this, r(23)); 29277 }, function (t, e) { 29278 t.exports = function (t) { 29279 return "object" == typeof t ? null !== t : "function" == typeof t; 29280 }; 29281 }, function (t, e, r) { 29282 var n = r(5); 29283 29284 t.exports = function (t, e, r) { 29285 if (n(t), void 0 === e) return t; 29286 29287 switch (r) { 29288 case 0: 29289 return function () { 29290 return t.call(e); 29291 }; 29292 29293 case 1: 29294 return function (r) { 29295 return t.call(e, r); 29296 }; 29297 29298 case 2: 29299 return function (r, n) { 29300 return t.call(e, r, n); 29301 }; 29302 29303 case 3: 29304 return function (r, n, i) { 29305 return t.call(e, r, n, i); 29306 }; 29307 } 29308 29309 return function () { 29310 return t.apply(e, arguments); 29311 }; 29312 }; 29313 }, function (t, e, r) { 29314 t.exports = r(167); 29315 }, function (t, e, r) { 29316 var n = r(12); 29317 t.exports = !n(function () { 29318 return 7 != Object.defineProperty({}, "a", { 29319 get: function () { 29320 return 7; 29321 } 29322 }).a; 29323 }); 29324 }, function (t, e, r) { 29325 var n = r(3); 29326 29327 t.exports = function (t) { 29328 return n[t + "Prototype"]; 29329 }; 29330 }, function (t, e, r) { 29331 29332 (function (t) { 29333 /*! 29334 * The buffer module from node.js, for the browser. 29335 * 29336 * @author Feross Aboukhadijeh <[email protected]> <http://feross.org> 29337 * @license MIT 29338 */ 29339 var n = r(165), 29340 i = r(166),
29341 o = r(105); 29342 29343 function a() { 29344 return u.TYPED_ARRAY_SUPPORT ? 2147483647 : 1073741823; 29345 } 29346 29347 function s(t, e) { 29348 if (a() < e) throw new RangeError("Invalid typed array length"); 29349 return u.TYPED_ARRAY_SUPPORT ? (t = new Uint8Array(e)).__proto__ = u.prototype : (null === t && (t = new u(e)), t.length = e), t; 29350 } 29351 29352 function u(t, e, r) { 29353 if (!(u.TYPED_ARRAY_SUPPORT || this instanceof u)) return new u(t, e, r); 29354 29355 if ("number" == typeof t) { 29356 if ("string" == typeof e) throw new Error("If encoding is specified then the first argument must be a string"); 29357 return l(this, t); 29358 } 29359 29360 return f(this, t, e, r); 29361 } 29362 29363 function f(t, e, r, n) { 29364 if ("number" == typeof e) throw new TypeError('"value" argument must not be a number'); 29365 return "undefined" != typeof ArrayBuffer && e instanceof ArrayBuffer ? function (t, e, r, n) { 29366 if (e.byteLength, r < 0 || e.byteLength < r) throw new RangeError("'offset' is out of bounds"); 29367 if (e.byteLength < r + (n || 0)) throw new RangeError("'length' is out of bounds"); 29368 e = void 0 === r && void 0 === n ? new Uint8Array(e) : void 0 === n ? new Uint8Array(e, r) : new Uint8Array(e, r, n); 29369 u.TYPED_ARRAY_SUPPORT ? (t = e).__proto__ = u.prototype : t = h(t, e); 29370 return t; 29371 }(t, e, r, n) : "string" == typeof e ? function (t, e, r) { 29372 "string" == typeof r && "" !== r || (r = "utf8"); 29373 if (!u.isEncoding(r)) throw new TypeError('"encoding" must be a valid string encoding'); 29374 var n = 0 | p(e, r), 29375 i = (t = s(t, n)).write(e, r); 29376 i !== n && (t = t.slice(0, i)); 29377 return t; 29378 }(t, e, r) : function (t, e) { 29379 if (u.isBuffer(e)) { 29380 var r = 0 | d(e.length); 29381 return 0 === (t = s(t, r)).length ? t : (e.copy(t, 0, 0, r), t); 29382 } 29383 29384 if (e) { 29385 if ("undefined" != typeof ArrayBuffer && e.buffer instanceof ArrayBuffer || "length" in e) return "number" != typeof e.length || (n = e.length) != n ? s(t, 0) : h(t, e); 29386 if ("Buffer" === e.type && o(e.data)) return h(t, e.data); 29387 } 29388 29389 var n; 29390 throw new TypeError("First argument must be a string, Buffer, ArrayBuffer, Array, or array-like object."); 29391 }(t, e); 29392 } 29393 29394 function c(t) { 29395 if ("number" != typeof t) throw new TypeError('"size" argument must be a number'); 29396 if (t < 0) throw new RangeError('"size" argument must not be negative'); 29397 } 29398 29399 function l(t, e) { 29400 if (c(e), t = s(t, e < 0 ? 0 : 0 | d(e)), !u.TYPED_ARRAY_SUPPORT) for (var r = 0; r < e; ++r) t[r] = 0; 29401 return t; 29402 } 29403 29404 function h(t, e) { 29405 var r = e.length < 0 ? 0 : 0 | d(e.length); 29406 t = s(t, r); 29407 29408 for (var n = 0; n < r; n += 1) t[n] = 255 & e[n]; 29409 29410 return t; 29411 } 29412 29413 function d(t) { 29414 if (t >= a()) throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x" + a().toString(16) + " bytes"); 29415 return 0 | t; 29416 } 29417 29418 function p(t, e) { 29419 if (u.isBuffer(t)) return t.length; 29420 if ("undefined" != typeof ArrayBuffer && "function" == typeof ArrayBuffer.isView && (ArrayBuffer.isView(t) || t instanceof ArrayBuffer)) return t.byteLength; 29421 "string" != typeof t && (t = "" + t); 29422 var r = t.length; 29423 if (0 === r) return 0; 29424 29425 for (var n = !1;;) switch (e) { 29426 case "ascii": 29427 case "latin1": 29428 case "binary": 29429 return r; 29430 29431 case "utf8": 29432 case "utf-8": 29433 case void 0: 29434 return D(t).length; 29435 29436 case "ucs2": 29437 case "ucs-2": 29438 case "utf16le": 29439 case "utf-16le": 29440 return 2 * r; 29441 29442 case "hex": 29443 return r >>> 1; 29444 29445 case "base64": 29446 return q(t).length; 29447 29448 default: 29449 if (n) return D(t).length; 29450 e = ("" + e).toLowerCase(), n = !0; 29451 } 29452 } 29453 29454 function g(t, e, r) { 29455 var n = !1; 29456 if ((void 0 === e || e < 0) && (e = 0), e > this.length) return ""; 29457 if ((void 0 === r || r > this.length) && (r = this.length), r <= 0) return ""; 29458 if ((r >>>= 0) <= (e >>>= 0)) return ""; 29459 29460 for (t || (t = "utf8");;) switch (t) { 29461 case "hex": 29462 return O(this, e, r); 29463 29464 case "utf8": 29465 case "utf-8": 29466 return A(this, e, r); 29467 29468 case "ascii": 29469 return T(this, e, r); 29470 29471 case "latin1": 29472 case "binary": 29473 return R(this, e, r); 29474 29475 case "base64": 29476 return k(this, e, r); 29477 29478 case "ucs2": 29479 case "ucs-2": 29480 case "utf16le": 29481 case "utf-16le": 29482 return I(this, e, r); 29483 29484 default: 29485 if (n) throw new TypeError("Unknown encoding: " + t); 29486 t = (t + "").toLowerCase(), n = !0; 29487 } 29488 } 29489 29490 function v(t, e, r) { 29491 var n = t[e]; 29492 t[e] = t[r], t[r] = n; 29493 } 29494 29495 function y(t, e, r, n, i) { 29496 if (0 === t.length) return -1; 29497 29498 if ("string" == typeof r ? (n = r, r = 0) : r > 2147483647 ? r = 2147483647 : r < -2147483648 && (r = -2147483648), r = +r, isNaN(r) && (r = i ? 0 : t.length - 1), r < 0 && (r = t.length + r), r >= t.length) { 29499 if (i) return -1; 29500 r = t.length - 1; 29501 } else if (r < 0) { 29502 if (!i) return -1; 29503 r = 0; 29504 } 29505 29506 if ("string" == typeof e && (e = u.from(e, n)), u.isBuffer(e)) return 0 === e.length ? -1 : m(t, e, r, n, i); 29507 if ("number" == typeof e) return e &= 255, u.TYPED_ARRAY_SUPPORT && "function" == typeof Uint8Array.prototype.indexOf ? i ? Uint8Array.prototype.indexOf.call(t, e, r) : Uint8Array.prototype.lastIndexOf.call(t, e, r) : m(t, [e], r, n, i); 29508 throw new TypeError("val must be string, number or Buffer"); 29509 } 29510 29511 function m(t, e, r, n, i) { 29512 var o, 29513 a = 1, 29514 s = t.length, 29515 u = e.length; 29516 29517 if (void 0 !== n && ("ucs2" === (n = String(n).toLowerCase()) || "ucs-2" === n || "utf16le" === n || "utf-16le" === n)) { 29518 if (t.length < 2 || e.length < 2) return -1; 29519 a = 2, s /= 2, u /= 2, r /= 2; 29520 } 29521 29522 function f(t, e) { 29523 return 1 === a ? t[e] : t.readUInt16BE(e * a); 29524 } 29525 29526 if (i) { 29527 var c = -1; 29528 29529 for (o = r; o < s; o++) if (f(t, o) === f(e, -1 === c ? 0 : o - c)) { 29530 if (-1 === c && (c = o), o - c + 1 === u) return c * a; 29531 } else -1 !== c && (o -= o - c), c = -1; 29532 } else for (r + u >
29532 s && (r = s - u), o = r; o >= 0; o--) { 29533 for (var l = !0, h = 0; h < u; h++) if (f(t, o + h) !== f(e, h)) { 29534 l = !1; 29535 break; 29536 } 29537 29538 if (l) return o; 29539 } 29540 29541 return -1; 29542 } 29543 29544 function b(t, e, r, n) { 29545 r = Number(r) || 0; 29546 var i = t.length - r; 29547 n ? (n = Number(n)) > i && (n = i) : n = i; 29548 var o = e.length; 29549 if (o % 2 != 0) throw new TypeError("Invalid hex string"); 29550 n > o / 2 && (n = o / 2); 29551 29552 for (var a = 0; a < n; ++a) { 29553 var s = parseInt(e.substr(2 * a, 2), 16); 29554 if (isNaN(s)) return a; 29555 t[r + a] = s; 29556 } 29557 29558 return a; 29559 } 29560 29561 function _(t, e, r, n) { 29562 return Z(D(e, t.length - r), t, r, n); 29563 } 29564 29565 function w(t, e, r, n) { 29566 return Z(function (t) { 29567 for (var e = [], r = 0; r < t.length; ++r) e.push(255 & t.charCodeAt(r)); 29568 29569 return e; 29570 }(e), t, r, n); 29571 } 29572 29573 function x(t, e, r, n) { 29574 return w(t, e, r, n); 29575 } 29576 29577 function E(t, e, r, n) { 29578 return Z(q(e), t, r, n); 29579 } 29580 29581 function S(t, e, r, n) { 29582 return Z(function (t, e) { 29583 for (var r, n, i, o = [], a = 0; a < t.length && !((e -= 2) < 0); ++a) r = t.charCodeAt(a), n = r >> 8, i = r % 256, o.push(i), o.push(n); 29584 29585 return o; 29586 }(e, t.length - r), t, r, n); 29587 } 29588 29589 function k(t, e, r) { 29590 return 0 === e && r === t.length ? n.fromByteArray(t) : n.fromByteArray(t.slice(e, r)); 29591 } 29592 29593 function A(t, e, r) { 29594 r = Math.min(t.length, r); 29595 29596 for (var n = [], i = e; i < r;) { 29597 var o, 29598 a, 29599 s, 29600 u, 29601 f = t[i], 29602 c = null, 29603 l = f > 239 ? 4 : f > 223 ? 3 : f > 191 ? 2 : 1; 29604 if (i + l <= r) switch (l) { 29605 case 1: 29606 f < 128 && (c = f); 29607 break; 29608 29609 case 2: 29610 128 == (192 & (o = t[i + 1])) && (u = (31 & f) << 6 | 63 & o) > 127 && (c = u); 29611 break; 29612 29613 case 3: 29614 o = t[i + 1], a = t[i + 2], 128 == (192 & o) && 128 == (192 & a) && (u = (15 & f) << 12 | (63 & o) << 6 | 63 & a) > 2047 && (u < 55296 || u > 57343) && (c = u); 29615 break; 29616 29617 case 4: 29618 o = t[i + 1], a = t[i + 2], s = t[i + 3], 128 == (192 & o) && 128 == (192 & a) && 128 == (192 & s) && (u = (15 & f) << 18 | (63 & o) << 12 | (63 & a) << 6 | 63 & s) > 65535 && u < 1114112 && (c = u); 29619 } 29620 null === c ? (c = 65533, l = 1) : c > 65535 && (c -= 65536, n.push(c >>> 10 & 1023 | 55296), c = 56320 | 1023 & c), n.push(c), i += l; 29621 } 29622 29623 return function (t) { 29624 var e = t.length; 29625 if (e <= C) return String.fromCharCode.apply(String, t); 29626 var r = "", 29627 n = 0; 29628 29629 for (; n < e;) r += String.fromCharCode.apply(String, t.slice(n, n += C)); 29630 29631 return r; 29632 }(n); 29633 } 29634 29635 e.Buffer = u, e.SlowBuffer = function (t) { 29636 +t != t && (t = 0); 29637 return u.alloc(+t); 29638 }, e.INSPECT_MAX_BYTES = 50, u.TYPED_ARRAY_SUPPORT = void 0 !== t.TYPED_ARRAY_SUPPORT ? t.TYPED_ARRAY_SUPPORT : function () { 29639 try { 29640 var t = new Uint8Array(1); 29641 return t.__proto__ = { 29642 __proto__: Uint8Array.prototype, 29643 foo: function () { 29644 return 42; 29645 } 29646 }, 42 === t.foo() && "function" == typeof t.subarray && 0 === t.subarray(1, 1).byteLength; 29647 } catch (t) { 29648 return !1; 29649 } 29650 }(), e.kMaxLength = a(), u.poolSize = 8192, u._augment = function (t) { 29651 return t.__proto__ = u.prototype, t; 29652 }, u.from = function (t, e, r) { 29653 return f(null, t, e, r); 29654 }, u.TYPED_ARRAY_SUPPORT && (u.prototype.__proto__ = Uint8Array.prototype, u.__proto__ = Uint8Array, "undefined" != typeof Symbol && Symbol.species && u[Symbol.species] === u && Ob
vendor: 14,856 bytes, lines 29654-29995
29654ject.defineProperty(u, Symbol.species, { 29655 value: null, 29656 configurable: !0 29657 })), u.alloc = function (t, e, r) { 29658 return function (t, e, r, n) { 29659 return c(e), e <= 0 ? s(t, e) : void 0 !== r ? "string" == typeof n ? s(t, e).fill(r, n) : s(t, e).fill(r) : s(t, e); 29660 }(null, t, e, r); 29661 }, u.allocUnsafe = function (t) { 29662 return l(null, t); 29663 }, u.allocUnsafeSlow = function (t) { 29664 return l(null, t); 29665 }, u.isBuffer = function (t) { 29666 return !(null == t || !t._isBuffer); 29667 }, u.compare = function (t, e) { 29668 if (!u.isBuffer(t) || !u.isBuffer(e)) throw new TypeError("Arguments must be Buffers"); 29669 if (t === e) return 0; 29670 29671 for (var r = t.length, n = e.length, i = 0, o = Math.min(r, n); i < o; ++i) if (t[i] !== e[i]) { 29672 r = t[i], n = e[i]; 29673 break; 29674 } 29675 29676 return r < n ? -1 : n < r ? 1 : 0; 29677 }, u.isEncoding = function (t) { 29678 switch (String(t).toLowerCase()) { 29679 case "hex": 29680 case "utf8": 29681 case "utf-8": 29682 case "ascii": 29683 case "latin1": 29684 case "binary": 29685 case "base64": 29686 case "ucs2": 29687 case "ucs-2": 29688 case "utf16le": 29689 case "utf-16le": 29690 return !0; 29691 29692 default: 29693 return !1; 29694 } 29695 }, u.concat = function (t, e) { 29696 if (!o(t)) throw new TypeError('"list" argument must be an Array of Buffers'); 29697 if (0 === t.length) return u.alloc(0); 29698 var r; 29699 if (void 0 === e) for (e = 0, r = 0; r < t.length; ++r) e += t[r].length; 29700 var n = u.allocUnsafe(e), 29701 i = 0; 29702 29703 for (r = 0; r < t.length; ++r) { 29704 var a = t[r]; 29705 if (!u.isBuffer(a)) throw new TypeError('"list" argument must be an Array of Buffers'); 29706 a.copy(n, i), i += a.length; 29707 } 29708 29709 return n; 29710 }, u.byteLength = p, u.prototype._isBuffer = !0, u.prototype.swap16 = function () { 29711 var t = this.length; 29712 if (t % 2 != 0) throw new RangeError("Buffer size must be a multiple of 16-bits"); 29713 29714 for (var e = 0; e < t; e += 2) v(this, e, e + 1); 29715 29716 return this; 29717 }, u.prototype.swap32 = function () { 29718 var t = this.length; 29719 if (t % 4 != 0) throw new RangeError("Buffer size must be a multiple of 32-bits"); 29720 29721 for (var e = 0; e < t; e += 4) v(this, e, e + 3), v(this, e + 1, e + 2); 29722 29723 return this; 29724 }, u.prototype.swap64 = function () { 29725 var t = this.length; 29726 if (t % 8 != 0) throw new RangeError("Buffer size must be a multiple of 64-bits"); 29727 29728 for (var e = 0; e < t; e += 8) v(this, e, e + 7), v(this, e + 1, e + 6), v(this, e + 2, e + 5), v(this, e + 3, e + 4); 29729 29730 return this; 29731 }, u.prototype.toString = function () { 29732 var t = 0 | this.length; 29733 return 0 === t ? "" : 0 === arguments.length ? A(this, 0, t) : g.apply(this, arguments); 29734 }, u.prototype.equals = function (t) { 29735 if (!u.isBuffer(t)) throw new TypeError("Argument must be a Buffer"); 29736 return this === t || 0 === u.compare(this, t); 29737 }, u.prototype.inspect = function () { 29738 var t = "", 29739 r = e.INSPECT_MAX_BYTES; 29740 return this.length > 0 && (t = this.toString("hex", 0, r).match(/.{2}/g).join(" "), this.length > r && (t += " ... ")), "<Buffer " + t + ">"; 29741 }, u.prototype.compare = function (t, e, r, n, i) { 29742 if (!u.isBuffer(t)) throw new TypeError("Argument must be a Buffer"); 29743 if (void 0 === e && (e = 0), void 0 === r && (r = t ? t.length : 0), void 0 === n && (n = 0), void 0 === i && (i = this.length), e < 0 || r > t.length || n < 0 || i > this.length) throw new RangeError("out of range index"); 29744 if (n >= i && e >= r) return 0; 29745 if (n >= i) return -1; 29746 if (e >= r) return 1; 29747 if (this === t) return 0; 29748 29749 for (var o = (i >>>= 0) - (n >>>= 0), a = (r >>>= 0) - (e >>>= 0), s = Math.min(o, a), f = this.slice(n, i), c = t.slice(e, r), l = 0; l < s; ++l) if (f[l] !== c[l]) { 29750 o = f[l], a = c[l]; 29751 break; 29752 } 29753 29754 return o < a ? -1 : a < o ? 1 : 0; 29755 }, u.prototype.includes = function (t, e, r) { 29756 return -1 !== this.indexOf(t, e, r); 29757 }, u.prototype.indexOf = function (t, e, r) { 29758 return y(this, t, e, r, !0); 29759 }, u.prototype.lastIndexOf = function (t, e, r) { 29760 return y(this, t, e, r, !1); 29761 }, u.prototype.write = function (t, e, r, n) { 29762 if (void 0 === e) n = "utf8", r = this.length, e = 0;else if (void 0 === r && "string" == typeof e) n = e, r = this.length, e = 0;else { 29763 if (!isFinite(e)) throw new Error("Buffer.write(string, encoding, offset[, length]) is no longer supported"); 29764 e |= 0, isFinite(r) ? (r |= 0, void 0 === n && (n = "utf8")) : (n = r, r = void 0); 29765 } 29766 var i = this.length - e; 29767 if ((void 0 === r || r > i) && (r = i), t.length > 0 && (r < 0 || e < 0) || e > this.length) throw new RangeError("Attempt to write outside buffer bounds"); 29768 n || (n = "utf8"); 29769 29770 for (var o = !1;;) switch (n) { 29771 case "hex": 29772 return b(this, t, e, r); 29773 29774 case "utf8": 29775 case "utf-8": 29776 return _(this, t, e, r); 29777 29778 case "ascii": 29779 return w(this, t, e, r); 29780 29781 case "latin1": 29782 case "binary": 29783 return x(this, t, e, r); 29784 29785 case "base64": 29786 return E(this, t, e, r); 29787 29788 case "ucs2": 29789 case "ucs-2": 29790 case "utf16le": 29791 case "utf-16le": 29792 return S(this, t, e, r); 29793 29794 default: 29795 if (o) throw new TypeError("Unknown encoding: " + n); 29796 n = ("" + n).toLowerCase(), o = !0; 29797 } 29798 }, u.prototype.toJSON = function () { 29799 return { 29800 type: "Buffer", 29801 data: Array.prototype.slice.call(this._arr || this, 0) 29802 }; 29803 }; 29804 var C = 4096; 29805 29806 function T(t, e, r) { 29807 var n = ""; 29808 r = Math.min(t.length, r); 29809 29810 for (var i = e; i < r; ++i) n += String.fromCharCode(127 & t[i]); 29811 29812 return n; 29813 } 29814 29815 function R(t, e, r) { 29816 var n = ""; 29817 r = Math.min(t.length, r); 29818 29819 for (var i = e; i < r; ++i) n += String.fromCharCode(t[i]); 29820 29821 return n; 29822 } 29823 29824 function O(t, e, r) { 29825 var n = t.length; 29826 (!e || e < 0) && (e = 0), (!r || r < 0 || r > n) && (r = n); 29827 29828 for (var i = "", o = e; o < r; ++o) i += U(t[o]); 29829 29830 return i; 29831 } 29832 29833 function I(t, e, r) { 29834 for (var n = t.slice(e, r), i = "", o = 0; o < n.length; o += 2) i += String.fromCharCode(n[o] + 256 * n[o + 1]); 29835 29836 return i; 29837 } 29838 29839 function L(t, e, r) { 29840 if (t % 1 != 0 || t < 0) throw new RangeError("offset is not uint"); 29841 if (t + e > r) throw new RangeError("Trying to access beyond buffer length"); 29842 } 29843 29844 function B(t, e, r, n, i, o) { 29845 if (!u.isBuffer(t)) throw new TypeError('"buffer" argument must be a Buffer instance'); 29846 if (e > i || e < o) throw new RangeError('"value" argument is out of bounds'); 29847 if (r + n > t.length) throw new RangeError("Index out of range"); 29848 } 29849 29850 function P(t, e, r, n) { 29851 e < 0 && (e = 65535 + e + 1); 29852 29853 for (var i = 0, o = Math.min(t.length - r, 2); i < o; ++i) t[r + i] = (e & 255 << 8 * (n ? i : 1 - i)) >>> 8 * (n ? i : 1 - i); 29854 } 29855 29856 function F(t, e, r, n) { 29857 e < 0 && (e = 4294967295 + e + 1); 29858 29859 for (var i = 0, o = Math.min(t.length - r, 4); i < o; ++i) t[r + i] = e >>> 8 * (n ? i : 3 - i) & 255; 29860 } 29861 29862 function N(t, e, r, n, i, o) { 29863 if (r + n > t.length) throw new RangeError("Index out of range"); 29864 if (r < 0) throw new RangeError("Index out of range"); 29865 } 29866 29867 function M(t, e, r, n, o) { 29868 return o || N(t, 0, r, 4), i.write(t, e, r, n, 23, 4), r + 4; 29869 } 29870 29871 function j(t, e, r, n, o) { 29872 return o || N(t, 0, r, 8), i.write(t, e, r, n, 52, 8), r + 8; 29873 } 29874 29875 u.prototype.slice = function (t, e) { 29876 var r, 29877 n = this.length; 29878 if ((t = ~~t) < 0 ? (t += n) < 0 && (t = 0) : t > n && (t = n), (e = void 0 === e ? n : ~~e) < 0 ? (e += n) < 0 && (e = 0) : e > n && (e = n), e < t && (e = t), u.TYPED_ARRAY_SUPPORT) (r = this.subarray(t, e)).__proto__ = u.prototype;else { 29879 var i = e - t; 29880 r = new u(i, void 0); 29881 29882 for (var o = 0; o < i; ++o) r[o] = this[o + t]; 29883 } 29884 return r; 29885 }, u.prototype.readUIntLE = function (t, e, r) { 29886 t |= 0, e |= 0, r || L(t, e, this.length); 29887 29888 for (var n = this[t], i = 1, o = 0; ++o < e && (i *= 256);) n += this[t + o] * i; 29889 29890 return n; 29891 }, u.prototype.readUIntBE = function (t, e, r) { 29892 t |= 0, e |= 0, r || L(t, e, this.length); 29893 29894 for (var n = this[t + --e], i = 1; e > 0 && (i *= 256);) n += this[t + --e] * i; 29895 29896 return n; 29897 }, u.prototype.readUInt8 = function (t, e) { 29898 return e || L(t, 1, this.length), this[t]; 29899 }, u.prototype.readUInt16LE = function (t, e) { 29900 return e || L(t, 2, this.length), this[t] | this[t + 1] << 8; 29901 }, u.prototype.readUInt16BE = function (t, e) { 29902 return e || L(t, 2, this.length), this[t] << 8 | this[t + 1]; 29903 }, u.prototype.readUInt32LE = function (t, e) { 29904 return e || L(t, 4, this.length), (this[t] | this[t + 1] << 8 | this[t + 2] << 16) + 16777216 * this[t + 3]; 29905 }, u.prototype.readUInt32BE = function (t, e) { 29906 return e || L(t, 4, this.length), 16777216 * this[t] + (this[t + 1] << 16 | this[t + 2] << 8 | this[t + 3]); 29907 }, u.prototype.readIntLE = function (t, e, r) { 29908 t |= 0, e |= 0, r || L(t, e, this.length); 29909 29910 for (var n = this[t], i = 1, o = 0; ++o < e && (i *= 256);) n += this[t + o] * i; 29911 29912 return n >= (i *= 128) && (n -= Math.pow(2, 8 * e)), n; 29913 }, u.prototype.readIntBE = function (t, e, r) { 29914 t |= 0, e |= 0, r || L(t, e, this.length); 29915 29916 for (var n = e, i = 1, o = this[t + --n]; n > 0 && (i *= 256);) o += this[t + --n] * i; 29917 29918 return o >= (i *= 128) && (o -= Math.pow(2, 8 * e)), o; 29919 }, u.prototype.readInt8 = function (t, e) { 29920 return e || L(t, 1, this.length), 128 & this[t] ? -1 * (255 - this[t] + 1) : this[t]; 29921 }, u.prototype.readInt16LE = function (t, e) { 29922 e || L(t, 2, this.length); 29923 var r = this[t] | this[t + 1] << 8; 29924 return 32768 & r ? 4294901760 | r : r; 29925 }, u.prototype.readInt16BE = function (t, e) { 29926 e || L(t, 2, this.length); 29927 var r = this[t + 1] | this[t] << 8; 29928 return 32768 & r ? 4294901760 | r : r; 29929 }, u.prototype.readInt32LE = function (t, e) { 29930 return e || L(t, 4, this.length), this[t] | this[t + 1] << 8 | this[t + 2] << 16 | this[t + 3] << 24; 29931 }, u.prototype.readInt32BE = function (t, e) { 29932 return e || L(t, 4, this.length), this[t] << 24 | this[t + 1] << 16 | this[t + 2] << 8 | this[t + 3]; 29933 }, u.prototype.readFloatLE = function (t, e) { 29934 return e || L(t, 4, this.length), i.read(this, t, !0, 23, 4); 29935 }, u.prototype.readFloatBE = function (t, e) { 29936 return e || L(t, 4, this.length), i.read(this, t, !1, 23, 4); 29937 }, u.prototype.readDoubleLE = function (t, e) { 29938 return e || L(t, 8, this.length), i.read(this, t, !0, 52, 8); 29939 }, u.prototype.readDoubleBE = function (t, e) { 29940 return e || L(t, 8, this.length), i.read(this, t, !1, 52, 8); 29941 }, u.prototype.writeUIntLE = function (t, e, r, n) { 29942 (t = +t, e |= 0, r |= 0, n) || B(this, t, e, r, Math.pow(2, 8 * r) - 1, 0); 29943 var i = 1, 29944 o = 0; 29945 29946 for (this[e] = 255 & t; ++o < r && (i *= 256);) this[e + o] = t / i & 255; 29947 29948 return e + r; 29949 }, u.prototype.writeUIntBE = function (t, e, r, n) { 29950 (t = +t, e |= 0, r |= 0, n) || B(this, t, e, r, Math.pow(2, 8 * r) - 1, 0); 29951 var i = r - 1, 29952 o = 1; 29953 29954 for (this[e + i] = 255 & t; --i >= 0 && (o *= 256);) this[e + i] = t / o & 255; 29955 29956 return e + r; 29957 }, u.prototype.writeUInt8 = function (t, e, r) { 29958 return t = +t, e |= 0, r || B(this, t, e, 1, 255, 0), u.TYPED_ARRAY_SUPPORT || (t = Math.floor(t)), this[e] = 255 & t, e + 1; 29959 }, u.prototype.writeUInt16LE = function (t, e, r) { 29960 return t = +t, e |= 0, r || B(this, t, e, 2, 65535, 0), u.TYPED_ARRAY_SUPPORT ? (this[e] = 255 & t, this[e + 1] = t >>> 8) : P(this, t, e, !0), e + 2; 29961 }, u.prototype.writeUInt16BE = function (t, e, r) { 29962 return t = +t, e |= 0, r || B(this, t, e, 2, 65535, 0), u.TYPED_ARRAY_SUPPORT ? (this[e] = t >>> 8, this[e + 1] = 255 & t) : P(this, t, e, !1), e + 2; 29963 }, u.prototype.writeUInt32LE = function (t, e, r) { 29964 return t = +t, e |= 0, r || B(this, t, e, 4, 4294967295, 0), u.TYPED_ARRAY_SUPPORT ? (this[e + 3] = t >>> 24, this[e + 2] = t >>> 16, this[e + 1] = t >>> 8, this[e] = 255 & t) : F(this, t, e, !0), e + 4; 29965 }, u.prototype.writeUInt32BE = function (t, e, r) { 29966 return t = +t, e |= 0, r || B(this, t, e, 4, 4294967295, 0), u.TYPED_ARRAY_SUPPORT ? (this[e] = t >>> 24, this[e + 1] = t >>> 16, this[e + 2] = t >>> 8, this[e + 3] = 255 & t) : F(this, t, e, !1), e + 4; 29967 }, u.prototype.writeIntLE = function (t, e, r, n) { 29968 if (t = +t, e |= 0, !n) { 29969 var i = Math.pow(2, 8 * r - 1); 29970 B(this, t, e, r, i - 1, -i); 29971 } 29972 29973 var o = 0, 29974 a = 1, 29975 s = 0; 29976 29977 for (this[e] = 255 & t; ++o < r && (a *= 256);) t < 0 && 0 === s && 0 !== this[e + o - 1] && (s = 1), this[e + o] = (t / a >> 0) - s & 255; 29978 29979 return e + r; 29980 }, u.prototype.writeIntBE = function (t, e, r, n) { 29981 if (t = +t, e |= 0, !n) { 29982 var i = Math.pow(2, 8 * r - 1); 29983 B(this, t, e, r, i - 1, -i); 29984 } 29985 29986 var o = r - 1, 29987 a = 1, 29988 s = 0; 29989 29990 for (this[e + o] = 255 & t; --o >= 0 && (a *= 256);) t < 0 && 0 === s && 0 !== this[e + o + 1] && (s = 1), this[e + o] = (t / a >> 0) - s & 255; 29991 29992 return e + r; 29993 }, u.prototype.writeInt8 = function (t, e, r) { 29994 return t = +t, e |= 0, r || B(this, t, e, 1, 127, -128), u.TYPED_ARRAY_SUPPORT || (t = Math.floor(t)), t < 0 && (t = 255 + t + 1), this[e] = 255 & t, e + 1; 29995 }
29995, u.prototype.writeInt16LE = function (t, e, r) { 29996 return t = +t, e |= 0, r || B(this, t, e, 2, 32767, -32768), u.TYPED_ARRAY_SUPPORT ? (this[e] = 255 & t, this[e + 1] = t >>> 8) : P(this, t, e, !0), e + 2; 29997 }, u.prototype.writeInt16BE = function (t, e, r) { 29998 return t = +t, e |= 0, r || B(this, t, e, 2, 32767, -32768), u.TYPED_ARRAY_SUPPORT ? (this[e] = t >>> 8, this[e + 1] = 255 & t) : P(this, t, e, !1), e + 2; 29999 }, u.prototype.writeInt32LE = function (t, e, r) { 30000 return t = +t, e |= 0, r || B(this, t, e, 4, 2147483647, -2147483648), u.TYPED_ARRAY_SUPPORT ? (this[e] = 255 & t, this[e + 1] = t >>> 8, this[e + 2] = t >>> 16, this[e + 3] = t >>> 24) : F(this, t, e, !0), e + 4; 30001 }, u.prototype.writeInt32BE = function (t, e, r) { 30002 return t = +t, e |= 0, r || B(this, t, e, 4, 2147483647, -2147483648), t < 0 && (t = 4294967295 + t + 1), u.TYPED_ARRAY_SUPPORT ? (this[e] = t >>> 24, this[e + 1] = t >>> 16, this[e + 2] = t >>> 8, this[e + 3] = 255 & t) : F(this, t, e, !1), e + 4; 30003 }, u.prototype.writeFloatLE = function (t, e, r) { 30004 return M(this, t, e, !0, r); 30005 }, u.prototype.writeFloatBE = function (t, e, r) { 30006 return M(this, t, e, !1, r); 30007 }, u.prototype.writeDoubleLE = function (t, e, r) { 30008 return j(this, t, e, !0, r); 30009 }, u.prototype.writeDoubleBE = function (t, e, r) { 30010 return j(this, t, e, !1, r); 30011 }, u.prototype.copy = function (t, e, r, n) { 30012 if (r || (r = 0), n || 0 === n || (n = this.length), e >= t.length && (e = t.length), e || (e = 0), n > 0 && n < r && (n = r), n === r) return 0; 30013 if (0 === t.length || 0 === this.length) return 0; 30014 if (e < 0) throw new RangeError("targetStart out of bounds"); 30015 if (r < 0 || r >= this.length) throw new RangeError("sourceStart out of bounds"); 30016 if (n < 0) throw new RangeError("sourceEnd out of bounds"); 30017 n > this.length && (n = this.length), t.length - e < n - r && (n = t.length - e + r); 30018 var i, 30019 o = n - r; 30020 if (this === t && r < e && e < n) for (i = o - 1; i >= 0; --i) t[i + e] = this[i + r];else if (o < 1e3 || !u.TYPED_ARRAY_SUPPORT) for (i = 0; i < o; ++i) t[i + e] = this[i + r];else Uint8Array.prototype.set.call(t, this.subarray(r, r + o), e); 30021 return o; 30022 }, u.prototype.fill = function (t, e, r, n) { 30023 if ("string" == typeof t) { 30024 if ("string" == typeof e ? (n = e, e = 0, r = this.length) : "string" == typeof r && (n = r, r = this.length), 1 === t.length) { 30025 var i = t.charCodeAt(0); 30026 i < 256 && (t = i); 30027 } 30028 30029 if (void 0 !== n && "string" != typeof n) throw new TypeError("encoding must be a string"); 30030 if ("string" == typeof n && !u.isEncoding(n)) throw new TypeError("Unknown encoding: " + n); 30031 } else "number" == typeof t && (t &= 255); 30032 30033 if (e < 0 || this.length < e || this.length < r) throw new RangeError("Out of range index"); 30034 if (r <= e) return this; 30035 var o; 30036 if (e >>>= 0, r = void 0 === r ? this.length : r >>> 0, t || (t = 0), "number" == typeof t) for (o = e; o < r; ++o) this[o] = t;else { 30037 var a = u.isBuffer(t) ? t : D(new u(t, n).toString()), 30038 s = a.length; 30039 30040 for (o = 0; o < r - e; ++o) this[o + e] = a[o % s]; 30041 } 30042 return this; 30043 }; 30044 var z = /[^+\/0-9A-Za-z-_]/g; 30045 30046 function U(t) { 30047 return t < 16 ? "0" + t.toString(16) : t.toString(16); 30048 } 30049 30050 function D(t, e) { 30051 var r; 30052 e = e || 1 / 0; 30053 30054 for (var n = t.length, i = null, o = [], a = 0; a < n; ++a) { 30055 if ((r = t.charCodeAt(a)) > 55295 && r < 57344) { 30056 if (!i) { 30057 if (r > 56319) { 30058 (e -= 3) > -1 && o.push(239, 191, 189); 30059 continue; 30060 } 30061 30062 if (a + 1 === n) { 30063 (e -= 3) > -1 && o.push(239, 191, 189); 30064 continue; 30065 } 30066 30067 i = r; 30068 continue; 30069 } 30070 30071 if (r < 56320) { 30072 (e -= 3) > -1 && o.push(239, 191, 189), i = r; 30073 continue; 30074 } 30075 30076 r = 65536 + (i - 55296 << 10 | r - 56320); 30077 } else i && (e -= 3) > -1 && o.push(239, 191, 189); 30078 30079 if (i = null, r < 128) { 30080 if ((e -= 1) < 0) break; 30081 o.push(r); 30082 } else if (r < 2048) { 30083 if ((e -= 2) < 0) break; 30084 o.push(r >> 6 | 192, 63 & r | 128); 30085 } else if (r < 65536) { 30086 if ((e -= 3) < 0) break; 30087 o.push(r >> 12 | 224, r >> 6 & 63 | 128, 63 & r | 128); 30088 } else { 30089 if (!(r < 1114112)) throw new Error("Invalid code point"); 30090 if ((e -= 4) < 0) break; 30091 o.push(r >> 18 | 240, r >> 12 & 63 | 128, r >> 6 & 63 | 128, 63 & r | 128); 30092 } 30093 } 30094 30095 return o; 30096 } 30097 30098 function q(t) { 30099 return n.toByteArray(function (t) { 30100 if ((t = function (t) { 30101 return t.trim ? t.trim() : t.replace(/^\s+|\s+$/g, ""); 30102 }(t).replace(z, "")).length < 2) return ""; 30103 30104 for (; t.length % 4 != 0;) t += "="; 30105 30106 return t; 30107 }(t)); 30108 } 30109 30110 function Z(t, e, r, n) { 30111 for (var i = 0; i < n && !(i + r >= e.length || i >= t.length); ++i) e[i + r] = t[i]; 30112 30113 return i; 30114 } 30115 }).call(this, r(23)); 30116 }, function (t, e, r) { 30117 var n = r(17), 30118 i = r(21), 30119 o = r(43); 30120 t.exports = n ? function (t, e, r) { 30121 return i.f(t, e, o(1, r)); 30122 } : function (t, e, r) { 30123 return t[e] = r, t; 30124 }; 30125 }, function (t, e, r) { 30126 var n = r(17), 30127 i = r(106), 30128 o = r(2), 30129 a = r(62), 30130 s = Object.defineProperty; 30131 e.f = n ? s : function (t, e, r) { 30132 if (o(t), e = a(e, !0), o(r), i) try { 30133 return s(t, e, r); 30134 } catch (t) {} 30135 if ("get" in r || "set" in r) throw TypeError("Accessors not supported"); 30136 return "value" in r && (t[e] = r.value), t; 30137 }; 30138 }, function (t, e, r) { 30139 var n = r(49); 30140 30141 t.exports = function (t) { 30142 return Object(n(t)); 30143 }; 30144 }, function (t, e) { 30145 var r; 30146 30147 r = function () { 30148 return this; 30149 }(); 30150
30151 try { 30152 r = r || new Function("return this")(); 30153 } catch (t) { 30154 "object" == typeof window && (r = window); 30155 } 30156 30157 t.exports = r; 30158 }, function (t, e) { 30159 var r = {}.hasOwnProperty; 30160 30161 t.exports = function (t, e) { 30162 return r.call(t, e); 30163 }; 30164 }, function (t, e, r) { 30165 var n = r(4), 30166 i = r(142); 30167 t.exports = n ? i : function (t) { 30168 return Map.prototype.entries.call(t); 30169 }; 30170 }, function (t, e, r) { 30171 var n = r(3), 30172 i = r(13), 30173 o = function (t) { 30174 return "function" == typeof t ? t : void 0; 30175 }; 30176 30177 t.exports = function (t, e) { 30178 return arguments.length < 2 ? o(n[t]) || o(i[t]) : n[t] && n[t][e] || i[t] && i[t][e]; 30179 }; 30180 }, function (t, e, r) { 30181 var n = r(255), 30182 i = r(139); 30183 30184 function o(e) { 30185 return t.exports = o = i ? n : function (t) { 30186 return t.__proto__ || n(t); 30187 }, o(e); 30188 } 30189 30190 t.exports = o; 30191 }, function (t, e, r) { 30192 var n = r(60), 30193 i = r(49); 30194 30195 t.exports = function (t) { 30196 return n(i(t)); 30197 }; 30198 }, function (t, e, r) { 30199 var n = r(83), 30200 i = Math.min; 30201 30202 t.exports = function (t) { 30203 return t > 0 ? i(n(t), 9007199254740991) : 0; 30204 }; 30205 }, function (t, e, r) { 30206 t.exports = r(184); 30207 }, function (t, e, r) { 30208 var n = r(185); 30209 30210 function i(t, e, r, i, o, a, s) { 30211 try { 30212 var u = t[a](s), 30213 f = u.value; 30214 } catch (t) { 30215 return void r(t); 30216 } 30217 30218 u.done ? e(f) : n.resolve(f).then(i, o); 30219 } 30220 30221 t.exports = function (t) { 30222 return function () { 30223 var e = this, 30224 r = arguments; 30225 return new n(function (n, o) { 30226 var a = t.apply(e, r); 30227 30228 function s(t) { 30229 i(a, n, o, s, u, "next", t); 30230 } 30231 30232 function u(t) { 30233 i(a, n, o, s, u, "throw", t); 30234 } 30235 30236 s(void 0); 30237 }); 30238 }; 30239 }; 30240 }, function (t, e, r) { 30241 var n = r(225), 30242 i = r(254); 30243 30244 t.exports = function (t, e) { 30245 return !e || "object" !== n(e) && "function" != typeof e ? i(t) : e; 30246 }; 30247 }, function (t, e, r) { 30248 var n = r(140), 30249 i = r(96); 30250 30251 t.exports = function (t, e) { 30252 if ("function" != typeof e && null !== e) throw new TypeError("Super expression must either be null or a function"); 30253 t.prototype = n(e && e.prototype, { 30254 constructor: { 30255 value: t, 30256 writable: !0, 30257 configurable: !0 30258 } 30259 }), e && i(t, e); 30260 }; 30261 }, function (t, e) { 30262 var r = {}.toString; 30263 30264 t.exports = function (t) { 30265 return r.call(t).slice(8, -1); 30266 }; 30267 }, function (t, e) { 30268 t.exports = {}; 30269 }, function (t, e, r) { 30270 var n = r(21).f, 30271 i = r(20), 30272 o = r(24), 30273 a = r(174), 30274 s = r(6)("toStringTag"), 30275 u = a !== {}.toString; 30276 30277 t.exports = function (t, e, r, f) { 30278 if (t) { 30279 var c = r ? t : t.prototype; 30280 o(c, s) || n(c, s, { 30281 configurable: !0, 30282 value: e 30283 }), f && u && i(c, "toString", a); 30284 } 30285 }; 30286 }, function (t, e, r) { 30287 t.exports = r(181); 30288 }, function (t, e) { 30289 var r, 30290 n, 30291 i = t.exports = {}; 30292 30293 function o() { 30294 throw new Error("setTimeout has not been defined"); 30295 } 30296 30297 function a() { 30298 throw new Error("clearTimeout has not been defined"); 30299 } 30300 30301 function s(t) { 30302 if (r === setTimeout) return setTimeout(t, 0); 30303 if ((r === o || !r) && setTimeout) return r = setTimeout, setTimeout(t, 0); 30304 30305 try { 30306 return r(t, 0); 30307 } catch (e) { 30308 try { 30309 return r.call(null, t, 0); 30310 } catch (e) { 30311 return r.call(this, t, 0); 30312 } 30313 } 30314 } 30315 30316 !function () { 30317 try { 30318 r = "function" == typeof setTimeout ? setTimeout : o; 30319 } catch (t) { 30320 r = o; 30321 } 30322 30323 try { 30324 n = "function" == typeof clearTimeout ? clearTimeout : a; 30325 } catch (t) { 30326 n = a; 30327 } 30328 }(); 30329 var u, 30330 f = [], 30331 c = !1, 30332 l = -1; 30333 30334 function h() { 30335 c && u && (c = !1, u.length ? f = u.concat(f) : l = -1, f.length && d()); 30336 } 30337 30338 function d() { 30339 if (!c) { 30340 var t = s(h); 30341 c = !0; 30342 30343 for (var e = f.length; e;) { 30344 for (u = f, f = []; ++l < e;) u && u[l].run(); 30345 30346 l = -1, e = f.length; 30347 } 30348 30349 u = null, c = !1, function (t) { 30350 if (n === clearTimeout) return clearTimeout(t); 30351 if ((n === a || !n) && clearTimeout) return n = clearTimeout, clearTimeout(t); 30352 30353 try { 30354 n(t); 30355 } catch (e) { 30356 try { 30357 return n.call(null, t); 30358 } catch (e) { 30359 return n.call(this, t); 30360 } 30361 } 30362 }(t); 30363 } 30364 } 30365 30366 function p(t, e) { 30367 this.fun = t, this.array = e; 30368 } 30369 30370 function g() {} 30371 30372 i.nextTick = function (t) { 30373 var e = new Array(arguments.length - 1); 30374 if (arguments.length > 1) for (var r = 1; r < arguments.length; r++) e[r - 1] = arguments[r]; 30375 f.push(new p(t, e)), 1 !== f.length || c || s(d); 30376 }, p.prototype.run = function () { 30377 this.fun.apply(null, this.array); 30378 }, i.title = "browser", i.browser = !0, i.env = {}, i.argv = [], i.version = "", i.versions = {}, i.on = g, i.addListener = g, i.once = g, i.off = g, i.removeListener = g, i.removeAllListeners = g, i.emit = g, i.prependListener = g, i.prependOnceListener = g, i.listeners = function (t) { 30379 return []; 30380 }, i.binding = function (t) { 30381 throw new Error("process.binding is not supported"); 30382 }, i.cwd = function () { 30383 return "/"; 30384 }, i.chdir = function (t) { 30385 throw new Error("process.chdir is not supported"); 30386 }, i.umask = function () { 30387 return 0; 30388 }; 30389 }, function (t, e, r) { 30390 30391 var n = r(70), 30392 i = Object.keys || function (t) { 30393 var e = []; 30394 30395 for (var r in t) e.push(r); 30396 30397 return e; 30398 }; 30399 30400 t.exports = l; 30401 var o = r(57); 30402 o.inherits = r(47); 30403 var a = r(127), 30404 s = r(93); 30405 o.inherits(l, a); 30406 30407 for (var u = i(s.prototype), f = 0; f < u.length; f++) { 30408 var c = u[f]; 30409 l.prototype[c] || (l.prototype[c] = s.prototype[c]); 30410 } 30411 30412 function l(t) { 30413 if (!(this instanceof l)) return new l(t); 30414 a.call(this, t), s.call(this, t), t && !1 === t.readable && (this.readable = !1), t && !1 === t.writable && (this.writable = !1), this.allowHalfOpen = !0, t && !1 === t.allowHalfOpen && (this.allowHalfOpen = !1), this.once("end", h); 30415 } 30416 30417 function h() { 30418 this.allowHalfOpen || this._writableState.ended || n.nextTick(d, this); 30419 } 30420 30421 function d(t) { 30422 t.end(); 30423 } 30424 30425 Object.defineProperty(l.prototype, "writableHighWaterMark", { 30426 enumerable: !1, 30427 get: function () { 30428 return this._writableState.highWaterMark; 30429 } 30430 }), Object.defineProperty(l.prototype, "destroyed", { 30431 get: function () { 30432 return void 0 !== this._readableState && void 0 !== this._writableState && this._readableState.destroyed && this._writableState.destroyed; 30433 }, 30434 set: function (t) { 30435 void 0 !== this._readableState && void 0 !== this._writableState && (this._readableState.destroyed = t, this._writableState.destroyed = t); 30436 } 30437 }), l.prototype._destroy = function (t, e) { 30438 this.push(null), this.end(), n.nextTick(e, t); 30439 }; 30440 }, function (t, e, r) { 30441 30442 var n = r(1), 30443 i = n(r(7)), 30444 o = n(r(10)), 30445 a = r(9).CramBufferOverrunError, 30446 s = { 30447 int: !0, 30448 byte: !0, 30449 long: !0, 30450 byteArray: !0, 30451 byteArrayBlock: !0 30452 }, 30453 u = function () { 30454 function t() { 30455 var e = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {}, 30456 r = arguments.length > 1 ? arguments[1] : void 0; 30457 if ((0, i.default)(this, t), this.parameters = e, this.dataType = r, !r) throw new TypeError("must provide a data type to codec constructor"); 30458 if (!s[r]) throw new TypeError("invalid data type ".concat(r)); 30459 } 30460 30461 return (0, o.default)(t, [{ 30462 key: "_getBits", 30463 value: function (t, e, r) { 30464 var n = 0; 30465 if (e.bytePosition + (7 - e.bitPosition + r) / 8 > t.length) throw new a("read error during decoding. the file seems to be truncated."); 30466 30467 for (var i = r; i; i -= 1) n <<= 1, n |= t[e.bytePosition] >> e.bitPosition & 1, e.bitPosition -= 1, e.bitPosition < 0 && (e.bytePosition += 1), e.bitPosition &= 7; 30468 30469 return n; 30470 } 30471 }]), t; 30472 }(); 30473 30474 t.exports = u; 30475 }, function (t, e, r) { 30476 r(168); 30477 var n = r(176), 30478 i = r(13), 30479 o = r(20), 30480 a = r(35), 30481 s = r(6)("toStringTag"); 30482 30483 for (var u in n) { 30484 var f = i[u], 30485 c = f && f.prototype; 30486 c && !c[s] && o(c, s, u), a[u] = a.Array; 30487 } 30488 }, function (t, e, r) { 30489 var n, 30490 i, 30491 o, 30492 a = r(169), 30493 s = r(13), 30494 u = r(14), 30495 f = r(20), 30496 c = r(24), 30497 l = r(63), 30498 h = r(50), 30499 d = s.WeakMap; 30500 30501 if (a) { 30502 var p = new d(), 30503 g = p.get, 30504 v = p.has, 30505 y = p.set; 30506 n = function (t, e) {
30507 return y.call(p, t, e), e; 30508 }, i = function (t) { 30509 return g.call(p, t) || {}; 30510 }, o = function (t) { 30511 return v.call(p, t); 30512 }; 30513 } else { 30514 var m = l("state"); 30515 h[m] = !0, n = function (t, e) { 30516 return f(t, m, e), e; 30517 }, i = function (t) { 30518 return c(t, m) ? t[m] : {}; 30519 }, o = function (t) { 30520 return c(t, m); 30521 }; 30522 } 30523 30524 t.exports = { 30525 set: n, 30526 get: i, 30527 has: o, 30528 enforce: function (t) { 30529 return o(t) ? i(t) : n(t, {}); 30530 }, 30531 getterFor: function (t) { 30532 return function (e) { 30533 var r; 30534 if (!u(e) || (r = i(e)).type !== t) throw TypeError("Incompatible receiver, " + t + " required"); 30535 return r; 30536 }; 30537 } 30538 }; 30539 }, function (t, e) { 30540 t.exports = function (t, e) { 30541 return { 30542 enumerable: !(1 & t), 30543 configurable: !(2 & t), 30544 writable: !(4 & t), 30545 value: e 30546 }; 30547 }; 30548 }, function (t, e, r) { 30549 var n = r(2), 30550 i = r(173), 30551 o = r(85), 30552 a = r(50), 30553 s = r(112), 30554 u = r(79), 30555 f = r(63)("IE_PROTO"), 30556 c = function () {}, 30557 l = function () { 30558 var t, 30559 e = u("iframe"), 30560 r = o.length; 30561 30562 for (e.style.display = "none", s.appendChild(e), e.src = String("javascript:"), (t = e.contentWindow.document).open(), t.write("
30562<script>document.F=Object<\/script>"), t.close(), l = t.F; r--;) delete l.prototype[o[r]]; 30563 30564 return l(); 30565 }; 30566 30567 t.exports = Object.create || function (t, e) { 30568 var r; 30569 return null !== t ? (c.prototype = n(t), r = new c(), c.prototype = null, r[f] = t) : r = l(), void 0 === e ? r : i(r, e); 30570 }, a[f] = !0; 30571 }, function (t, e, r) { 30572 var n = r(15), 30573 i = r(60), 30574 o = r(22), 30575 a = r(29), 30576 s = r(113), 30577 u = [].push, 30578 f = function (t) { 30579 var e = 1 == t, 30580 r = 2 == t, 30581 f = 3 == t, 30582 c = 4 == t, 30583 l = 6 == t, 30584 h = 5 == t || l; 30585 return function (d, p, g, v) { 30586 for (var y, m, b = o(d), _ = i(b), w = n(p, g, 3), x = a(_.length), E = 0, S = v || s, k = e ? S(d, x) : r ? S(d, 0) : void 0; x > E; E++) if ((h || E in _) && (m = w(y = _[E], E, b), t)) if (e) k[E] = m;else if (m) switch (t) { 30587 case 3: 30588 return !0; 30589 30590 case 5: 30591 return y; 30592 30593 case 6: 30594 return E; 30595 30596 case 2: 30597 u.call(k, y); 30598 } else if (c) return !1; 30599 30600 return l ? -1 : f || c ? c : k; 30601 }; 30602 }; 30603 30604 t.exports = { 30605 forEach: f(0), 30606 map: f(1), 30607 filter: f(2), 30608 some: f(3), 30609 every: f(4), 30610 find: f(5), 30611 findIndex: f(6) 30612 }; 30613 }, function (t, e, r) { 30614 30615 var n = r(187).charAt, 30616 i = r(42), 30617 o = r(80), 30618 a = i.set, 30619 s = i.getterFor("String Iterator"); 30620 o(String, "String", function (t) { 30621 a(this, { 30622 type: "String Iterator", 30623 string: String(t), 30624 index: 0 30625 }); 30626 }, function () { 30627 var t, 30628 e = s(this), 30629 r = e.string, 30630 i = e.index; 30631 return i >= r.length ? { 30632 value: void 0, 30633 done: !0 30634 } : (t = n(r, i), e.index += t.length, { 30635 value: t, 30636 done: !1 30637 }); 30638 }); 30639 }, function (t, e) { 30640 "function" == typeof Object.create ? t.exports = function (t, e) { 30641 e && (t.super_ = e, t.prototype = Object.create(e.prototype, { 30642 constructor: { 30643 value: t, 30644 enumerable: !1, 30645 writable: !0, 30646 configurable: !0 30647 } 30648 })); 30649 } : t.exports = function (t, e) { 30650 if (e) { 30651 t.super_ = e; 30652 30653 var r = function () {}; 30654 30655 r.prototype = e.prototype, t.prototype = new r(), t.prototype.constructor = t; 30656 } 30657 }; 30658 }, function (t, e, r) { 30659 var n = r(157), 30660 i = r(384), 30661 o = r(158); 30662 30663 t.exports = function (t, e) { 30664 return n(t) || i(t, e) || o(); 30665 }; 30666 }, function (t, e) { 30667 t.exports = function (t) { 30668 if (null == t) throw TypeError("Can't call method on " + t); 30669 return t; 30670 }; 30671 }, function (t, e) { 30672 t.exports = {}; 30673 }, function (t, e, r) { 30674 var n = r(111), 30675 i = r(85); 30676 30677 t.exports = Object.keys || function (t) { 30678 return n(t, i); 30679 }; 30680 }, function (t, e, r) { 30681 var n = r(20); 30682 30683 t.exports = function (t, e, r, i) { 30684 i && i.enumerable ? t[e] = r : n(t, e, r); 30685 }; 30686 }, function (t, e, r) { 30687 var n = r(34); 30688 30689 t.exports = Array.isArray || function (t) { 30690 return "Array" == n(t); 30691 }; 30692 }, function (t, e, r) { 30693 30694 var n = r(12); 30695 30696 t.exports = function (t, e) { 30697 var r = [][t]; 30698 return !r || !n(function () { 30699 r.call(null, e || function () { 30700 throw 1; 30701 }, 1); 30702 }); 30703 }; 30704 }, function (t, e, r) { 30705 var n = r(2), 30706 i = r(5), 30707 o = r(6)("species"); 30708 30709 t.exports = function (t, e) { 30710 var r, 30711 a = n(t).constructor; 30712 return void 0 === a || null == (r = n(a)[o]) ? e : i(r); 30713 }; 30714 }, function (t, e, r) { 30715 30716 var n = r(5), 30717 i = function (t) { 30718 var e, r; 30719 this.promise = new t(function (t, n) { 30720 if (void 0 !== e || void 0 !== r) throw TypeError("Bad Promise constructor"); 30721 e = t, r = n; 30722 }), this.resolve = n(e), this.reject = n(r); 30723 }; 30724 30725 t.exports.f = function (t) { 30726 return new i(t); 30727 }; 30728 }, function (t, e, r) { 30729 (function (t) { 30730 function r(t) { 30731 return Object.prototype.toString.call(t); 30732 } 30733 30734 e.isArray = function (t) { 30735 return Array.isArray ? Array.isArray(t) : "[object Array]" === r(t); 30736 }, e.isBoolean = function (t) { 30737 return "boolean" == typeof t; 30738 }, e.isNull = function (t) { 30739 return null === t; 30740 }, e.isNullOrUndefined = function (t) { 30741 return null == t; 30742 }, e.isNumber = function (t) { 30743 return "number" == typeof t; 30744 }, e.isString = function (t) { 30745 return "string" == typeof t; 30746 }, e.isSymbol = function (t) { 30747 return "symbol" == typeof t; 30748 }, e.isUndefined = function (t) { 30749 return void 0 === t; 30750 }, e.isRegExp = function (t) { 30751 return "[object RegExp]" === r(t); 30752 }, e.isObject = function (t) { 30753 return "object" == typeof t && null !== t; 30754 }, e.isDate = function (t) { 30755 return "[object Date]" === r(t); 30756 }, e.isError = function (t) { 30757 return "[object Error]" === r(t) || t instanceof Error; 30758 }, e.isFunction = function (t) { 30759 return "function" == typeof t; 30760 }, e.isPrimitive = function (t) { 30761 return null === t || "boolean" == typeof t || "number" == typeof t || "string" == typeof t || "symbol" == typeof t || void 0 === t; 30762 }, e.isBuffer = t.isBuffer; 30763 }).call(this, r(19).Buffer); 30764 }, function (t, e, r) { 30765 30766 var n = r(1)(r(76)), 30767 i = r(331), 30768 o = r(9).CramBufferOverrunError; 30769 t.exports = { 30770 itf8Size: function (t) { 30771 return -128 & t ? -16384 & t ? -2097152 & t ? -268435456 & t ? 5 : 4 : 3 : 2 : 1; 30772 }, 30773 parseItf8: function (t, e) { 30774 var r, 30775 n = e, 30776 i = t[n]; 30777 if (i < 128 ? (r = i, n += 1) : i < 192 ? (r = 16383 & (i << 8 | t[n + 1]), n += 2) : i < 224 ? (r = 2097151 & (i << 16 | t[n + 1] << 8 | t[n + 2]), n += 3) : i < 240 ? (r = 268435455 & (i << 24 | t[n + 1] << 16 | t[n + 2] << 8 | t[n + 3]), n += 4) : (r = (15 & i) << 28 | t[n + 1] << 20 | t[n + 2] << 12 | t[n + 3] << 4 | 15 & t[n + 4], n += 5), n > t.length) throw new o("Attempted to read beyond end of buffer; this file seems truncated."); 30778 return [r, n - e]; 30779 }, 30780 parseItem: function (t, e) { 30781 var r = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : 0, 30782 n = arguments.length > 3 && void 0 !== arguments[3] ? arguments[3] : 0, 30783 i = e.parse(t), 30784 o = i.offset, 30785 a = i.result; 30786 return a._endPosition = o + n, a._size = o - r, a; 30787 }, 30788 tinyMemoize: function (t, e) { 30789 var r = t.prototype[e], 30790 i = "_memo_".concat(e); 30791 30792 t.prototype[e] = function () { 30793 var t = this; 30794 30795 if (!(i in this)) { 30796 var e = r.call(this); 30797 this[i] = e, n.default.resolve(e).catch(function () { 30798 delete t[i]; 30799 }); 30800 } 30801 30802 return this[i]; 30803 }; 30804 }, 30805 sequenceMD5: function (t) { 30806 return i(t.toUpperCase().replace(/[^\x21-\x7e]/g, "")); 30807 } 30808 }; 30809 }, function (t, e, r) { 30810 var n = r(351), 30811 i = r(152), 30812 o = r(362); 30813 30814 t.exports = function (t) { 30815 return n(t) || i(t) || o(); 30816 }; 30817 }, function (t, e, r) { 30818 var n = r(12), 30819 i = r(34), 30820 o = "".split; 30821 t.exports = n(function () { 30822 return !Object("z").propertyIsEnumerable(0); 30823 }) ? function (t) { 30824 return "String" == i(t) ? o.call(t, "") : Object(t); 30825 } : Object; 30826 }, function (t, e, r) { 30827 var n = r(13), 30828 i = r(171), 30829 o = r(4), 30830 a = n["__core-js_shared__"] || i("__core-js_shared__", {}); 30831 (t.exports = function (t, e) { 30832 return a[t] || (a[t] = void 0 !== e ? e : {}); 30833 })("versions", []).push({ 30834 version: "3.2.1", 30835 mode: o ? "pure" : "global", 30836 copyright: "© 2019 Denis Pushkarev (zloirock.ru)" 30837 }); 30838 }, function (t, e, r) { 30839 var n = r(14); 30840 30841 t.exports = function (t, e) { 30842 if (!n(t)) return t; 30843 var r, i; 30844 if (e && "function" == typeof (r = t.toString) && !n(i = r.call(t))) return i; 30845 if ("function" == typeof (r = t.valueOf) && !n(i = r.call(t))) return i; 30846 if (!e && "function" == typeof (r = t.toString) && !n(i = r.call(t))) return i; 30847 throw TypeError("Can't convert object to primitive value"); 30848 }; 30849 }, function (t, e, r) { 30850 var n = r(61), 30851 i = r(64), 30852 o = n("keys"); 30853 30854 t.exports = function (t) { 30855 return o[t] || (o[t] = i(t)); 30856 }; 30857 }, function (t, e) { 30858 var r = 0, 30859 n = Math.random(); 30860 30861 t.exports = function (t) { 30862 return "Symbol(" + String(void 0 === t ? "" : t) + ")_" + (++r + n).toString(36); 30863 }; 30864 }, function (t, e, r) { 30865 30866 var n = {}.propertyIsEnumerable, 30867 i = Object.getOwnPropertyDescriptor, 30868 o = i && !n.call({ 30869 1: 2 30870 }, 1); 30871 e.f = o ? function (t) { 30872 var e = i(this, t); 30873 return !!e && e.enumerable; 30874 } : n; 30875 }, function (t, e, r) { 30876 var n = r(24), 30877 i = r(22), 30878 o = r(63), 30879 a = r(109), 30880 s = o("IE_PROTO"), 30881 u = Object.prototype; 30882 t.exports = a ? Object.getPrototypeOf : function (t) { 30883 return t = i(t), n(t, s) ? t[s] : "function" == typeof t.constructor && t instanceof t.constructor ? t.constructor.prototype : t instanceof Object ? u : null; 30884 }; 30885 }, function (t, e, r) { 30886 var n = r(34), 30887 i = r(6)("toStringTag"), 30888 o = "Arguments" == n(function () { 30889 return arguments; 30890 }()); 30891 30892 t.exports = function (t) { 30893 var e, r, a; 30894 return void 0 === t ? "Undefined" : null === t ? "Null" : "string" == typeof (r = function (t, e) { 30895 try { 30896 return t[e]; 30897 } catch (t) {} 30898 }(e = Object(t), i)) ? r : o ? n(e) : "Object" == (a = n(e)) && "function" == typeof e.callee ? "Arguments" : a; 30899 }; 30900 }, function (t, e, r) { 30901 var n = r(12), 30902 i = r(6)("species"); 30903 30904 t.exports = function (t) { 30905 return !n(function () { 30906 var e = []; 30907 return (e.constructor = {})[i] = function () { 30908 return { 30909 foo: 1 30910 }; 30911 }, 1 !== e[t](Boolean).foo; 30912 }); 30913 }; 30914 }, function (t, e) { 30915 t.exports = function (t) { 30916 try { 30917 return { 30918 error: !1, 30919 value: t() 30920 }; 30921 } catch (t) { 30922 return { 30923 error: !0, 30924 value: t 30925 }; 30926 } 30927 }; 30928 }, function (t, e, r) { 30929 30930 (function (e) { 30931 void 0 === e || !e.version || 0 === e.version.indexOf("v0.") || 0 === e.version.indexOf("v1.") && 0 !== e.version.indexOf("v1.8.") ? t.exports = { 30932 nextTick: function (t, r, n, i) { 30933 if ("function" != typeof t) throw new TypeError('"callback" argument must be a function'); 30934 var o, 30935 a, 30936 s = arguments.length; 30937 30938 switch (s) { 30939 case 0: 30940 case 1: 30941 return e.nextTick(t); 30942 30943 case 2: 30944 return e.nextTick(function () { 30945 t.call(null, r); 30946 }); 30947 30948 case 3: 30949 return e.nextTick(function () { 30950 t.call(null, r, n); 30951 }); 30952 30953 case 4: 30954 return e.nextTick(function () { 30955 t.call(null, r, n, i); 30956 }); 30957 30958 default: 30959 for (o = new Array(s - 1), a = 0; a < o.length;) o[a++] = arguments[a]; 30960 30961 return e.nextTick(function () { 30962 t.apply(null, o); 30963 }); 30964 } 30965 } 30966 } : t.exports = e; 30967 }).call(this, r(38)); 30968 }, function (t, e, r) { 30969 var n = r(19), 30970 i = n.Buffer; 30971 30972 function o(t, e) { 30973 for (var r in t) e[r] = t[r]; 30974 } 30975 30976 function a(t, e, r) { 30977 return i(t, e, r); 30978 } 30979 30980 i.from && i.alloc && i.allocUnsafe && i.allocUnsafeSlow ? t.exports = n : (o(n, e), e.Buffer = a), o(i, a), a.from = function (t, e, r) { 30981 if ("number" == typeof t) throw new TypeError("Argument must not be a number"); 30982 return i(t, e, r); 30983 }, a.alloc = function (t, e, r) { 30984 if ("number" != typeof t) throw new TypeError("Argument must be a number"); 30985 var n = i(t); 30986 return void 0 !== e ? "string" == typeof r ? n.fill(e, r) : n.fill(e) : n.fill(0), n; 30987 }, a.allocUnsafe = function (t) { 30988 if ("number" != typeof t) throw new TypeError("Argument must be a number"); 30989 return i(t); 30990 }, a.allocUnsafeSlow = function (t) { 30991 if ("number" != typeof t) throw new TypeError("Argument must be a number"); 30992 return n.SlowBuffer(t); 30993 }; 30994 }, function (t, e, r) { 30995 30996 var n = "undefined" != typeof Uint8Array && "undefined" != typeof Uint16Array && "undefined" != typeof Int32Array; 30997 30998 function i(t, e) { 30999 return Object.prototype.hasOwnProperty.call(t, e); 31000 } 31001 31002 e.assign = function (t) { 31003 for (var e = Array.prototype.slice.call(arguments, 1); e.length;) { 31004 var r = e.shift(); 31005 31006 if (r) { 31007 if ("object" != typeof r) throw new TypeError(r + "must be non-object"); 31008 31009 for (var n in r) i(r, n) && (t[n] = r[n]); 31010 } 31011 } 31012 31013 return t; 31014 }, e.shrinkBuf = function (t, e) { 31015 return t.length === e ? t : t.subarray ? t.subarray(0, e) : (t.length = e, t); 31016 }; 31017 var o = { 31018 arraySet: function (t, e, r, n, i) { 31019 if (e.subarray && t.subarray) t.set(e.subarray(r, r + n), i);else for (var o = 0; o < n;
31019 o++) t[i + o] = e[r + o]; 31020 }, 31021 flattenChunks: function (t) { 31022 var e, r, n, i, o, a; 31023 31024 for (n = 0, e = 0, r = t.length; e < r; e++) n += t[e].length; 31025 31026 for (a = new Uint8Array(n), i = 0, e = 0, r = t.length; e < r; e++) o = t[e], a.set(o, i), i += o.length; 31027 31028 return a; 31029 } 31030 }, 31031 a = { 31032 arraySet: function (t, e, r, n, i) { 31033 for (var o = 0; o < n; o++) t[i + o] = e[r + o]; 31034 }, 31035 flattenChunks: function (t) { 31036 return [].concat.apply([], t); 31037 } 31038 }; 31039 e.setTyped = function (t) { 31040 t ? (e.Buf8 = Uint8Array, e.Buf16 = Uint16Array, e.Buf32 = Int32Array, e.assign(e, o)) : (e.Buf8 = Array, e.Buf16 = Array, e.Buf32 = Array, e.assign(e, a)); 31041 }, e.setTyped(n); 31042 }, function (t, e, r) { 31043 31044 var n = r(1)(r(7)), 31045 i = r(9).CramMalformedError, 31046 o = r(74), 31047 a = function t() { 31048 (0, n.default)(this, t), this.F = void 0, this.C = void 0; 31049 }; 31050 31051 function s(t, e, r, n) { 31052 return r * (t >> n) + (t & (1 << n) - 1) - e; 31053 } 31054 31055 var u = { 31056 FC: a, 31057 AriDecoder: function t() { 31058 (0, n.default)(this, t), this.fc = new Array(256); 31059 31060 for (var e = 0; e < this.fc.length; e += 1) this.fc[e] = new a(); 31061 31062 this.R = null; 31063 }, 31064 Symbol: function t() { 31065 (0, n.default)(this, t), this.start = void 0, this.freq = void 0; 31066 }, 31067 symbolInit: function (t, e, r) { 31068 if (!(e <= 65536)) throw new i("assertion failed: start <= 1<<16"); 31069 if (!(r <= 65536 - e)) throw new i("assertion failed: freq <= 1<<16"); 31070 t.start = e, t.freq = r; 31071 }, 31072 advanceStep: s, 31073 advanceSymbolStep: function (t, e, r) { 31074 return s(t, e.start, e.freq, r); 31075 }, 31076 get: function (t, e) { 31077 return t & (1 << e) - 1; 31078 }, 31079 advanceSymbol: function (t, e, r, n) { 31080 return function (t, e, r, n, i) { 31081 if ((t = n * (t >> i) + (t & (1 << i) - 1) - r) < o.RANS_BYTE_L) do { 31082 t = t << 8 | 255 & e.get(); 31083 } while (t < o.RANS_BYTE_L); 31084 return t; 31085 }(t, e, r.start, r.freq, n); 31086 }, 31087 renormalize: function (t, e) { 31088 if (t < o.RANS_BYTE_L) do { 31089 t = t << 8 | 255 & e.get(); 31090 } while (t < o.RANS_BYTE_L); 31091 return t; 31092 } 31093 }; 31094 t.exports = u; 31095 }, function (t, e, r) { 31096 31097 t.exports = { 31098 TF_SHIFT: 12, 31099 TOTFREQ: 4096, 31100 RANS_BYTE_L: 1 << 23 31101 }; 31102 }, function (t, e, r) { 31103 t.exports = r(322); 31104 }, function (t, e, r) { 31105 t.exports = r(330); 31106 }, function (t, e, r) { 31107 t.exports = r(347); 31108 }, function (t, e) { 31109 t.exports = function () {}; 31110 }, function (t, e, r) { 31111 var n = r(13), 31112 i = r(14), 31113 o = n.document, 31114 a = i(o) && i(o.createElement); 31115 31116 t.exports = function (t) { 31117 return a ? o.createElement(t) : {}; 31118 }; 31119 }, function (t, e, r) { 31120 31121 var n = r(0), 31122 i = r(172), 31123 o = r(66), 31124 a = r(86), 31125 s = r(36), 31126 u = r(20), 31127 f = r(52), 31128 c = r(6), 31129 l = r(4), 31130 h = r(35), 31131 d = r(108), 31132 p = d.IteratorPrototype, 31133 g = d.BUGGY_SAFARI_ITERATORS, 31134 v = c("iterator"), 31135 y = function () { 31136 return this; 31137 }; 31138 31139 t.exports = function (t, e, r, c, d, m, b) { 31140 i(r, e, c); 31141 31142 var _, 31143 w, 31144 x, 31145 E = function (t) { 31146 if (t === d && T) return T; 31147 if (!g && t in A) return A[t]; 31148 31149 switch (t) { 31150 case "keys": 31151 case "values": 31152 case "entries": 31153 return function () { 31154 return new r(this, t); 31155 }; 31156 } 31157 31158 return function () { 31159 return new r(this); 31160 }; 31161 }, 31162 S = e + " Iterator", 31163 k = !1, 31164 A = t.prototype, 31165 C = A[v] || A["@@iterator"] || d && A[d], 31166 T = !g && C || E(d), 31167 R = "Array" == e && A.entries || C; 31168 31169 if (R && (_ = o(R.call(new t())), p !== Object.prototype && _.next && (l || o(_) === p || (a ? a(_, p) : "function" != typeof _[v] && u(_, v, y)), s(_, S, !0, !0), l && (h[S] = y))), "values" == d && C && "values" !== C.name && (k = !0, T = function () { 31170 return C.call(this); 31171 }), l && !b || A[v] === T || u(A, v, T), h[e] = T, d) if (w = { 31172 values: E("values"), 31173 keys: m ? T : E("keys"),
31174 entries: E("entries") 31175 }, b) for (x in w) !g && !k && x in A || f(A, x, w[x]);else n({ 31176 target: e, 31177 proto: !0, 31178 forced: g || k 31179 }, w); 31180 return w; 31181 }; 31182 }, function (t, e, r) { 31183 var n = r(17), 31184 i = r(65), 31185 o = r(43), 31186 a = r(28), 31187 s = r(62), 31188 u = r(24), 31189 f = r(106), 31190 c = Object.getOwnPropertyDescriptor; 31191 e.f = n ? c : function (t, e) { 31192 if (t = a(t), e = s(e, !0), f) try { 31193 return c(t, e); 31194 } catch (t) {} 31195 if (u(t, e)) return o(!i.f.call(t, e), t[e]); 31196 }; 31197 }, function (t, e, r) { 31198 var n = r(28), 31199 i = r(29), 31200 o = r(84), 31201 a = function (t) { 31202 return function (e, r, a) { 31203 var s, 31204 u = n(e), 31205 f = i(u.length), 31206 c = o(a, f); 31207 31208 if (t && r != r) { 31209 for (; f > c;) if ((s = u[c++]) != s) return !0; 31210 } else for (; f > c; c++) if ((t || c in u) && u[c] === r) return t || c || 0; 31211 31212 return !t && -1; 31213 }; 31214 }; 31215 31216 t.exports = { 31217 includes: a(!0), 31218 indexOf: a(!1) 31219 }; 31220 }, function (t, e) {
31221 var r = Math.ceil, 31222 n = Math.floor; 31223 31224 t.exports = function (t) { 31225 return isNaN(t = +t) ? 0 : (t > 0 ? n : r)(t); 31226 }; 31227 }, function (t, e, r) { 31228 var n = r(83), 31229 i = Math.max, 31230 o = Math.min; 31231 31232 t.exports = function (t, e) { 31233 var r = n(t); 31234 return r < 0 ? i(r + e, 0) : o(r, e); 31235 }; 31236 }, function (t, e) { 31237 t.exports = ["constructor", "hasOwnProperty", "isPrototypeOf", "propertyIsEnumerable", "toLocaleString", "toString", "valueOf"]; 31238 }, function (t, e, r) { 31239 var n = r(2), 31240 i = r(175); 31241 t.exports = Object.setPrototypeOf || ("__proto__" in {} ? function () { 31242 var t, 31243 e = !1, 31244 r = {}; 31245 31246 try { 31247 (t = Object.getOwnPropertyDescriptor(Object.prototype, "__proto__").set).call(r, []), e = r instanceof Array; 31248 } catch (t) {} 31249 31250 return function (r, o) { 31251 return n(r), i(o), e ? t.call(r, o) : r.__proto__ = o, r; 31252 }; 31253 }() : void 0); 31254 }, function (t, e, r) { 31255 31256 var n = r(62), 31257 i = r(21), 31258 o = r(43); 31259 31260 t.exports = function (t, e, r) { 31261 var a = n(e); 31262 a in t ? i.f(t, a, o(0, r)) : t[a] = r; 31263 }; 31264 }, function (t, e) {}, function (t, e) { 31265 t.exports = function (t, e, r) { 31266 if (!(t instanceof e)) throw TypeError("Incorrect " + (r ? r + " " : "") + "invocation"); 31267 return t; 31268 }; 31269 }, function (t, e, r) { 31270 var n = r(67), 31271 i = r(35), 31272 o = r(6)("iterator"); 31273 31274 t.exports = function (t) { 31275 if (null != t) return t[o] || t["@@iterator"] || i[n(t)]; 31276 }; 31277 }, function (t, e, r) { 31278 31279 var n, 31280 i = "object" == typeof Reflect ? Reflect : null, 31281 o = i && "function" == typeof i.apply ? i.apply : function (t, e, r) { 31282 return Function.prototype.apply.call(t, e, r); 31283 }; 31284 n = i && "function" == typeof i.ownKeys ? i.ownKeys : Object.getOwnPropertySymbols ? function (t) { 31285 return Object.getOwnPropertyNames(t).concat(Object.getOwnPropertySymbols(t)); 31286 } : function (t) { 31287 return Object.getOwnPropertyNames(t); 31288 }; 31289 31290 var a = Number.isNaN || function (t) { 31291 return t != t; 31292 }; 31293 31294 function s() { 31295 s.init.call(this); 31296 } 31297 31298 t.exports = s, s.EventEmitter = s, s.prototype._events = void 0, s.prototype._eventsCount = 0, s.prototype._maxListeners = void 0; 31299 var u = 10; 31300 31301 function f(t) { 31302 return void 0 === t._maxListeners ? s.defaultMaxListeners : t._maxListeners; 31303 } 31304 31305 function c(t, e, r, n) { 31306 var i, o, a, s; 31307 if ("function" != typeof r) throw new TypeError('The "listener" argument must be of type Function. Received type ' + typeof r); 31308 if (void 0 === (o = t._events) ? (o = t._events = Object.create(null), t._eventsCount = 0) : (void 0 !== o.newListener && (t.emit("newListener", e, r.listener ? r.listener : r), o = t._events), a = o[e]), void 0 === a) a = o[e] = r, ++t._eventsCount;else if ("function" == typeof a ? a = o[e] = n ? [r, a] : [a, r] : n ? a.unshift(r) : a.push(r), (i = f(t)) > 0 && a.length > i && !a.warned) { 31309 a.warned = !0; 31310 var u = new Error("Possible EventEmitter memory leak detected. " + a.length + " " + String(e) + " listeners added. Use emitter.setMaxListeners() to increase limit"); 31311 u.name = "MaxListenersExceededWarning", u.emitter = t, u.type = e, u.count = a.length, s = u, console && console.warn && console.warn(s); 31312 } 31313 return t; 31314 } 31315 31316 function l() { 31317 for (var t = [], e = 0; e < arguments.length; e++) t.push(arguments[e]); 31318 31319 this.fired || (this.target.removeListener(this.type, this.wrapFn), this.fired = !0, o(this.listener, this.target, t)); 31320 } 31321 31322 function h(t, e, r) { 31323 var n = { 31324 fired: !1, 31325 wrapFn: void 0, 31326 target: t, 31327 type: e, 31328 listener: r 31329 }, 31330 i = l.bind(n); 31331 return i.listener = r, n.wrapFn = i, i; 31332 } 31333 31334 function d(t, e, r) { 31335 var n = t._events; 31336 if (void 0 === n) return []; 31337 var i = n[e]; 31338 return void 0 === i ? [] : "function" == typeof i ? r ? [i.listener || i] : [i] : r ? function (t) { 31339 for (var e = new Array(t.length), r = 0; r < e.length; ++r) e[r] = t[r].listener || t[r]; 31340 31341 return e; 31342 }(i) : g(i, i.length); 31343 } 31344 31345 function p(t) { 31346 var e = this._events; 31347 31348 if (void 0 !== e) { 31349 var r = e[t]; 31350 if ("function" == typeof r) return 1; 31351 if (void 0 !== r) return r.length; 31352 } 31353 31354 return 0; 31355 } 31356 31357 function g(t, e) { 31358 for (var r = new Array(e), n = 0; n < e; ++n) r[n] = t[n]; 31359 31360 return r; 31361 } 31362 31363 Object.defineProperty(s, "defaultMaxListeners", { 31364 enumerable: !0, 31365 get: function () { 31366 return u; 31367 }, 31368 set: function (t) { 31369 if ("number" != typeof t || t < 0 || a(t)) throw new RangeError('The value of "defaultMaxListeners" is out of range. It must be a non-negative number. Received ' + t + "."); 31370 u = t; 31371 } 31372 }), s.init = function () { 31373 void 0 !== this._events && this._events !== Object.getPrototypeOf(this)._events || (this._events = Object.create(null), this._eventsCount = 0), this._maxListeners = this._maxListeners || void 0; 31374 }, s.prototype.setMaxListeners = function (t) { 31375 if ("number" != typeof t || t < 0 || a(t)) throw new RangeError('The value of "n" is out of range. It must be a non-negative number. Received ' + t + "."); 31376 return this._maxListeners = t, this; 31377 }, s.prototype.getMaxListeners = function () { 31378 return f(this); 31379 }, s.prototype.emit = function (t) { 31380 for (var e = [], r = 1; r < arguments.length; r++) e.push(arguments[r]); 31381 31382 var n = "error" === t, 31383 i = this._events; 31384 if (void 0 !== i) n = n && void 0 === i.error;else if (!n) return !1; 31385 31386 if (n) { 31387 var a; 31388 if (e.length > 0 && (a = e[0]), a instanceof Error) throw a; 31389 var s = new Error("Unhandled error." + (a ? " (" + a.message + ")" : "")); 31390 throw s.context = a, s; 31391 } 31392 31393 var u = i[t]; 31394 if (void 0 === u) return !1; 31395 if ("function" == typeof u) o(u, this, e);else { 31396 var f = u.length, 31397 c = g(u, f); 31398 31399 for (r = 0; r < f; ++r) o(c[r], this, e); 31400 } 31401 return !0; 31402 }, s.prototype.addListener = function (t, e) { 31403 return c(this, t, e, !1); 31404 }, s.prototype.on = s.prototype.addListener, s.prototype.prependListener = function (t, e) { 31405 return c(this, t, e, !0); 31406 }, s.prototype.once = function (t, e) { 31407 if ("function" != typeof e) throw new TypeError('The "listener" argument must be of type Function. Received type ' + typeof e); 31408 return this.on(t, h(this, t, e)), this; 31409 }, s.prototype.prependOnceListener = function (t, e) { 31410 if ("function" != typeof e) throw new TypeError('The "listener" argument must be of type Function. Received type ' + typeof e); 31411 return this.prependListener(t, h(this, t, e)), this; 31412 }, s.prototype.removeListener = function (t, e) { 31413 var r, n, i, o, a; 31414 if ("function" != typeof e) throw new TypeError('The "listener" argument must be of type Function. Received type ' + typeof e); 31415 if (void 0 === (n = this._events)) return this; 31416 if (void 0 === (r = n[t])) return this; 31417 if (r === e || r.listener === e) 0 == --this._eventsCount ? this._events = Object.create(null) : (delete n[t], n.removeListener && this.emit
31417("removeListener", t, r.listener || e));else if ("function" != typeof r) { 31418 for (i = -1, o = r.length - 1; o >= 0; o--) if (r[o] === e || r[o].listener === e) { 31419 a = r[o].listener, i = o; 31420 break; 31421 } 31422 31423 if (i < 0) return this; 31424 0 === i ? r.shift() : function (t, e) { 31425 for (; e + 1 < t.length; e++) t[e] = t[e + 1]; 31426 31427 t.pop(); 31428 }(r, i), 1 === r.length && (n[t] = r[0]), void 0 !== n.removeListener && this.emit("removeListener", t, a || e); 31429 } 31430 return this; 31431 }, s.prototype.off = s.prototype.removeListener, s.prototype.removeAllListeners = function (t) { 31432 var e, r, n; 31433 if (void 0 === (r = this._events)) return this; 31434 if (void 0 === r.removeListener) return 0 === arguments.length ? (this._events = Object.create(null), this._eventsCount = 0) : void 0 !== r[t] && (0 == --this._eventsCount ? this._events = Object.create(null) : delete r[t]), this; 31435 31436 if (0 === arguments.length) { 31437 var i, 31438 o = Object.keys(r); 31439 31440 for (n = 0; n < o.length; ++n) "removeListener" !== (i = o[n]) && this.removeAllListeners(i); 31441 31442 return this.removeAllListeners("removeListener"), this._events = Object.create(null), this._eventsCount = 0, this; 31443 } 31444 31445 if ("function" == typeof (e = r[t])) this.removeListener(t, e);else if (void 0 !== e) for (n = e.length - 1; n >= 0; n--) this.removeListener(t, e[n]); 31446 return this; 31447 }, s.prototype.listeners = function (t) { 31448 return d(this, t, !0); 31449 }, s.prototype.rawListeners = function (t) { 31450 return d(this, t, !1); 31451 }, s.listenerCount = function (t, e) { 31452 return "function" == typeof t.listenerCount ? t.listenerCount(e) : p.call(t, e); 31453 }, s.prototype.listenerCount = p, s.prototype.eventNames = function () { 31454 return this._eventsCount > 0 ? n(this._events) : []; 31455 }; 31456 }, function (t, e, r) { 31457 (e = t.exports = r(127)).Stream = e, e.Readable = e, e.Writable = r(93), e.Duplex = r(39), e.Transform = r(131), e.PassThrough = r(207); 31458 }, function (t, e, r) { 31459 31460 (function (e, n, i) { 31461 var o = r(70); 31462 31463 function a(t) { 31464 var e = this; 31465 this.next = null, this.entry = null, this.finish = function () { 31466 !function (t, e, r) { 31467 var n = t.entry; 31468 t.entry = null; 31469 31470 for (; n;) { 31471 var i = n.callback; 31472 e.pendingcb--, i(r), n = n.next; 31473 } 31474 31475 e.corkedRequestsFree ? e.corkedRequestsFree.next = t : e.corkedRequestsFree = t; 31476 }(e, t); 31477 }; 31478 } 31479 31480 t.exports = m; 31481 var s, 31482 u = !e.browser && ["v0.10", "v0.9."].indexOf(e.version.slice(0, 5)) > -1 ? n : o.nextTick; 31483 m.WritableState = y; 31484 var f = r(57); 31485 f.inherits = r(47); 31486 31487 var c = { 31488 deprecate: r(206) 31489 }, 31490 l = r(128), 31491 h = r(71).Buffer, 31492 d = i.Uint8Array || function () {}; 31493 31494 var p, 31495 g = r(129); 31496 31497 function v() {} 31498 31499 function y(t, e) { 31500 s = s || r(39), t = t || {}; 31501 var n = e instanceof s; 31502 this.objectMode = !!t.objectMode, n && (this.objectMode = this.objectMode || !!t.writableObjectMode); 31503 var i = t.highWaterMark, 31504 f = t.writableHighWaterMark, 31505 c = this.objectMode ? 16 : 16384; 31506 this.highWaterMark = i || 0 === i ? i : n && (f || 0 === f) ? f : c, this.highWaterMark = Math.floor(this.highWaterMark), this.finalCalled = !1, this.needDrain = !1, this.ending = !1, this.ended = !1, this.finished = !1, this.destroyed = !1; 31507 var l = !1 === t.decodeStrings; 31508 this.decodeStrings = !l, this.defaultEncoding = t.defaultEncoding || "utf8", this.length = 0, this.writing = !1, this.corked = 0, this.sync = !0, this.bufferProcessing = !1, this.onwrite = function (t) { 31509 !function (t, e) { 31510 var r = t._writableState, 31511 n = r.sync, 31512 i = r.writecb; 31513 if (function (t) { 31514 t.writing = !1, t.writecb = null, t.length -= t.writelen, t.writelen = 0; 31515 }(r), e) !function (t, e, r, n, i) { 31516 --e.pendingcb, r ? (o.nextTick(i, n), o.nextTick(S, t, e), t._writableState.errorEmitted = !0, t.emit("error", n)) : (i(n), t._writableState.errorEmitted = !0, t.emit("error", n), S(t, e)); 31517 }(t, r, n, e, i);else { 31518 var a = x(r); 31519 a || r.corked || r.bufferProcessing || !r.bufferedRequest || w(t, r), n ? u(_, t, r, a, i) : _(t, r, a, i); 31520 } 31521 }(e, t); 31522 }, this.writecb = null, this.writelen = 0, this.bufferedRequest = null, this.lastBufferedRequest = null, this.pendingcb = 0, this.prefinished = !1, this.errorEmitted = !1, this.bufferedRequestCount = 0, this.corkedRequestsFree = new a(this); 31523 } 31524 31525 function m(t) { 31526 if (s = s || r(39), !(p.call(m, this) || this instanceof s)) return new m(t); 31527 this._writableState = new y(t, this), this.writable = !0, t && ("function" == typeof t.write && (this._write = t.write), "function" == typeof t.writev && (this._writev = t.writev), "function" == typeof t.destroy && (this._destroy = t.destroy), "function" == typeof t.final && (this._final = t.final)), l.call(this); 31528 } 31529 31530 function b(t, e, r, n, i, o, a) {
31531 e.writelen = n, e.writecb = a, e.writing = !0, e.sync = !0, r ? t._writev(i, e.onwrite) : t._write(i, o, e.onwrite), e.sync = !1; 31532 } 31533 31534 function _(t, e, r, n) { 31535 r || function (t, e) { 31536 0 === e.length && e.needDrain && (e.needDrain = !1, t.emit("drain")); 31537 }(t, e), e.pendingcb--, n(), S(t, e); 31538 } 31539 31540 function w(t, e) { 31541 e.bufferProcessing = !0; 31542 var r = e.bufferedRequest; 31543 31544 if (t._writev && r && r.next) { 31545 var n = e.bufferedRequestCount, 31546 i = new Array(n), 31547 o = e.corkedRequestsFree; 31548 o.entry = r; 31549 31550 for (var s = 0, u = !0; r;) i[s] = r, r.isBuf || (u = !1), r = r.next, s += 1; 31551 31552 i.allBuffers = u, b(t, e, !0, e.length, i, "", o.finish), e.pendingcb++, e.lastBufferedRequest = null, o.next ? (e.corkedRequestsFree = o.next, o.next = null) : e.corkedRequestsFree = new a(e), e.bufferedRequestCount = 0; 31553 } else { 31554 for (; r;) { 31555 var f = r.chunk, 31556 c = r.encoding, 31557 l = r.callback; 31558 if (b(t, e, !1, e.objectMode ? 1 : f.length, f, c, l), r = r.next, e.bufferedRequestCount--, e.writing) break; 31559 } 31560 31561 null === r && (e.lastBufferedRequest = null); 31562 } 31563 31564 e.bufferedRequest = r, e.bufferProcessing = !1; 31565 } 31566 31567 function x(t) { 31568 return t.ending && 0 === t.length && null === t.bufferedRequest && !t.finished && !t.writing; 31569 } 31570 31571 function E(t, e) { 31572 t._final(function (r) { 31573 e.pendingcb--, r && t.emit("error", r), e.prefinished = !0, t.emit("prefinish"), S(t, e); 31574 }); 31575 } 31576 31577 function S(t, e) { 31578 var r = x(e); 31579 return r && (!function (t, e) { 31580 e.prefinished || e.finalCalled || ("function" == typeof t._final ? (e.pendingcb++, e.finalCalled = !0, o.nextTick(E, t, e)) : (e.prefinished = !0, t.emit("prefinish"))); 31581 }(t, e), 0 === e.pendingcb && (e.finished = !0, t.emit("finish"))), r; 31582 } 31583 31584 f.inherits(m, l), y.prototype.getBuffer = function () { 31585 for (var t = this.bufferedRequest, e = []; t;) e.push(t), t = t.next; 31586 31587 return e; 31588 }, function () { 31589 try { 31590 Object.defineProperty(y.prototype, "buffer", { 31591 get: c.deprecate(function () { 31592 return this.getBuffer(); 31593 }, "_writableState.buffer is deprecated. Use _writableState.getBuffer instead.", "DEP0003") 31594 }); 31595 } catch (t) {} 31596 }(), "function" == typeof Symbol && Symbol.hasInstance && "function" == typeof Function.prototype[Symbol.hasInstance] ? (p = Function.prototype[Symbol.hasInstance], Object.defineProperty(m, Symbol.hasInstance, { 31597 value: function (t) { 31598 return !!p.call(this, t) || this === m && t && t._writableState instanceof y; 31599 } 31600 })) : p = function (t) { 31601 return t instanceof this; 31602 }, m.prototype.pipe = function () { 31603 this.emit("error", new Error("Cannot pipe, not readable")); 31604 }, m.prototype.write = function (t, e, r) { 31605 var n, 31606 i = this._writableState, 31607 a = !1, 31608 s = !i.objectMode && (n = t, h.isBuffer(n) || n instanceof d); 31609 return s && !h.isBuffer(t) && (t = function (t) { 31610 return h.from(t); 31611 }(t)), "function" == typeof e && (r = e, e = null), s ? e = "buffer" : e || (e = i.defaultEncoding), "function" != typeof r && (r = v), i.ended ? function (t, e) { 31612 var r = new Error("write after end"); 31613 t.emit("error", r), o.nextTick(e, r); 31614 }(this, r) : (s || function (t, e, r, n) { 31615 var i = !0, 31616 a = !1; 31617 return null === r ? a = new TypeError("May not write null values to stream") : "string" == typeof r || void 0 === r || e.objectMode || (a = new TypeError("Invalid non-string/buffer chunk")), a && (t.emit("error", a), o.nextTick(n, a), i = !1), i; 31618 }(this, i, t, r)) && (i.pendingcb++, a = function (t, e, r, n, i, o) { 31619 if (!r) { 31620 var a = function (t, e, r) { 31621 t.objectMode || !1 === t.decodeStrings || "string" != typeof e || (e = h.from(e, r)); 31622 return e; 31623 }(e, n, i); 31624 31625 n !== a && (r = !0, i = "buffer", n = a); 31626 } 31627 31628 var s = e.objectMode ? 1 : n.length; 31629 e.length += s; 31630 var u = e.length < e.highWaterMark; 31631 u || (e.needDrain = !0); 31632 31633 if (e.writing || e.corked) { 31634 var f = e.lastBufferedRequest; 31635 e.lastBufferedRequest = { 31636 chunk: n, 31637 encoding: i, 31638 isBuf: r, 31639 callback: o, 31640 next: null 31641 }, f ? f.next = e.lastBufferedRequest : e.bufferedRequest = e.lastBufferedRequest, e.bufferedRequestCount += 1; 31642 } else b(t, e, !1, s, n, i, o); 31643 31644 return u; 31645 }(this, i, s, t, e, r)), a; 31646 }, m.prototype.cork = function () { 31647 this._writableState.corked++; 31648 }, m.prototype.uncork = function () { 31649 var t = this._writableState; 31650 t.corked && (t.corked--, t.writing || t.corked || t.finished || t.bufferProcessing || !t.bufferedRequest || w(this, t)); 31651 }, m.prototype.setDefaultEncoding = function (t) { 31652 if ("string" == typeof t && (t = t.toLowerCase()), !(["hex", "utf8", "utf-8", "ascii", "binary", "base64", "ucs2", "ucs-2", "utf16le", "utf-16le", "raw"].indexOf((t + "").toLowerCase()) > -1)) throw new TypeError("Unknown encoding: " + t); 31653 return this._writableState.defaultEncoding = t, this; 31654 }, Object.defineProperty(m.prototype, "writableHighWaterMark", { 31655 enumerable: !1, 31656 get: function () { 31657 return this._writableState.highWaterMark; 31658 } 31659 }), m.prototype._write = function (t, e, r) { 31660 r(new Error("_write() is not implemented")); 31661 }, m.prototype._writev = null, m.prototype.end = function (t, e, r) { 31662 var n = this._writableState; 31663 "function" == typeof t ? (r = t, t = null, e = null) : "function" == typeof e && (r = e, e = null), null != t && this.write(t, e), n.corked && (n.corked = 1, this.uncork()), n.ending || n.finished || function (t, e, r) { 31664 e.ending = !0, S(t, e), r && (e.finished ? o.nextTick(r) : t.once("finish", r)); 31665 e.ended = !0, t.writable = !1; 31666 }(this, n, r); 31667 }, Object.defineProperty(m.prototype, "destroyed", { 31668 get: function () { 31669 return void 0 !== this._writableState && this._writableState.destroyed; 31670 }, 31671 set: function (t) { 31672 this._writableState && (this._writableState.destroyed = t); 31673 } 31674 }), m.prototype.destroy = g.destroy, m.prototype._undestroy = g.undestroy, m.prototype._destroy = function (t, e) { 31675 this.end(), e(t); 31676 }; 31677 }).call(this, r(38), r(204).setImmediate, r(23)); 31678 }, function (t, e, r) { 31679 31680 t.exports = class { 31681 constructor() { 31682 let t = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; 31683 if (!(t.maxSize && t.maxSize > 0)) throw new TypeError("`maxSize` must be a number greater than 0"); 31684 this.maxSize = t.maxSize, this.cache = new Map(), this.oldCache = new Map(), this._size = 0; 31685 } 31686 31687 _set(t, e) { 31688 this.cache.set(t, e), this._size++, this._size >= this.maxSize && (this._size = 0, this.oldCache = this.cache, this.cache = new Map()); 31689 } 31690 31691 get(t) { 31692 if (this.cache.has(t)) return this.cache.get(t); 31693 31694 if (this.oldCache.has(t)) { 31695 const e = this.oldCache.get(t); 31696 return this._set(t, e), e; 31697 } 31698 } 31699 31700 set(t, e) { 31701 return this.cache.has(t) ? this.cache.set(t, e) : this._set(t, e), this; 31702 } 31703 31704 has(t) { 31705 return this.cache.has(t) || this.oldCache.has(t); 31706 } 31707 31708 peek(t) { 31709 return this.cache.has(t) ? this.cache.get(t) : this.oldCache.has(t) ? this.oldCache.get(t) : void 0; 31710 } 31711 31712 delete(t) { 31713 const e = this.cache.delete(t); 31714 return e && this._size--, this.oldCache.delete(t) || e; 31715 } 31716 31717 clear() { 31718 this.cache.clear(), this.oldCache.clear(), this._size = 0; 31719 } 31720 31721 *keys() { 31722 for (const [t] of this) yield t; 31723 } 31724 31725 *values() { 31726 for (const [, t] of this) yield t; 31727 } 31728 31729 *[Symbol.iterator]() { 31730 for (const t of this.cache) yield t; 31731 31732 for (const t of this.oldCache) { 31733 const [e] = t; 31734 this.cache.has(e) || (yield t); 31735 } 31736 } 31737 31738 get size() { 31739 let t = 0; 31740 31741 for (const e of this.oldCache.keys()) this.cache.has(e) || t++; 31742 31743 return this._size + t; 31744 } 31745 31746 }; 31747 }, function (t, e, r) { 31748 e.f = r(6); 31749 }, function (t, e, r) { 31750 var n = r(139); 31751 31752 function i(e, r) { 31753 return t.exports = i = n || function (t, e) { 31754 return t.__proto__ = e, t; 31755 }, i(e, r); 31756 } 31757 31758 t.exports = i; 31759 }, function (t, e, r) { 31760 t.exports = r(310); 31761 }, function (t, e, r) { 31762 t.exports = r(319); 31763 }, function (t, e, r) { 31764 t.exports = r(342); 31765 }, function (t, e, r) { 31766 31767 t.exports = { 31768 CRAM_FLAG_PRESERVE_QUAL_SCORES: 1, 31769 CRAM_FLAG_DETACHED: 2, 31770 CRAM_FLAG_MATE_DOWNSTREAM: 4, 31771 CRAM_FLAG_NO_SEQ: 8, 31772 CRAM_FLAG_MASK: 15, 31773 CRAM_M_REVERSE: 1, 31774 CRAM_M_UNMAP: 2, 31775 BAM_FPAIRED: 1, 31776 BAM_FPROPER_PAIR: 2, 31777 BAM_FUNMAP: 4, 31778 BAM_FMUNMAP: 8, 31779 BAM_FREVERSE: 16, 31780 BAM_FMREVERSE: 32, 31781 BAM_FREAD1: 64, 31782 BAM_FREAD2: 128, 31783 BAM_FSECONDARY: 256, 31784 BAM_FQCFAIL: 512, 31785 BAM_FDUP: 1024, 31786 BAM_FSUPPLEMENTARY: 2048, 31787 BAM_CMATCH: 0, 31788 BAM_CINS: 1, 31789 BAM_CDEL: 2, 31790 BAM_CREF_SKIP: 3, 31791 BAM_CSOFT_CLIP: 4, 31792 BAM_CHARD_CLIP: 5, 31793 BAM_CPAD: 6, 31794 BAM_CEQUAL: 7, 31795 BAM_CDIFF: 8, 31796 BAM_CBACK: 9, 31797 BAM_CIGAR_STR: "MIDNSHP:XB", 31798 BAM_CIGAR_SHIFT: 4, 31799 BAM_CIGAR_MASK: 15, 31800 BAM_CIGAR_TYPE: 246183 31801 }; 31802 }, function (t, e, r) { 31803 t.exports = r(368); 31804 }, function (t, e, r) { 31805 t.exports = r(396); 31806 }, function (t, e, r) { 31807 t.exports = r(399); 31808 }, function (t, e, r) { 31809 31810 var n = r(164); 31811 t.exports = n; 31812 }, function (t, e) { 31813 var r = {}.toString; 31814 31815 t.exports = Array.isArray || function (t) { 31816 return "[object Array]" == r.call(t); 31817 }; 31818 }, function (t, e, r) { 31819 var n = r(17), 31820 i = r(12), 31821 o = r(79); 31822 t.exports = !n && !i(function () { 31823 return 7 != Object.defineProperty(o("div"), "a", { 31824 get: function () { 31825 return 7; 31826 } 31827 }).a; 31828 }); 31829 }, function (t, e, r) { 31830 var n = r(12), 31831 i = /#|\.prototype\./, 31832 o = function (t, e) { 31833 var r = s[a(t)]; 31834 return r == f || r != u && ("function" == typeof e ? n(e) : !!e); 31835 }, 31836 a = o.normalize = function (t) { 31837 return String(t).replace(i, ".").toLowerCase(); 31838 }, 31839 s = o.data = {}, 31840 u = o.NATIVE = "N", 31841 f = o.POLYFILL = "P"; 31842 31843 t.exports = o; 31844 }, function (t, e, r) { 31845 31846 var n, 31847 i, 31848 o, 31849 a = r(66), 31850 s = r(20), 31851 u = r(24), 31852 f = r(6), 31853 c = r(4), 31854 l = f("iterator"), 31855 h = !1; 31856 [].keys && ("next" in (o = [].keys()) ? (i = a(a(o))) !== Object.prototype && (n = i) : h = !0), null == n && (n = {}), c || u(n, l) || s(n, l, function () { 31857 return this; 31858 }), t.exports = { 31859 IteratorPrototype: n, 31860 BUGGY_SAFARI_ITERATORS: h 31861 }; 31862 }, function (t, e, r) { 31863 var n = r(12); 31864 t.exports = !n(function () { 31865 function t() {} 31866 31867 return t.prototype.constructor = null, Object.getPrototypeOf(new t()) !== t.prototype; 31868 }); 31869 }, function (t, e, r) { 31870 var n = r(12); 31871 t.exports = !!Object.getOwnPropertySymbols && !n(function () { 31872 return !String(Symbol()); 31873 }); 31874 }, function (t, e, r) { 31875 var n = r(24), 31876 i = r(28), 31877 o = r(82).indexOf, 31878 a = r(50); 31879 31880 t.exports = function (t, e) { 31881 var r, 31882 s = i(t), 31883 u = 0, 31884 f = []; 31885 31886 for (r in s) !n(a, r) && n(s, r) && f.push(r); 31887 31888 for (; e.length > u;) n(s, r = e[u++]) && (~o(f, r) || f.push(r)); 31889 31890 return f; 31891 }; 31892 }, function (t, e, r) { 31893 var n = r(26); 31894 t.exports = n("document", "documentElement"); 31895 }, function (t, e, r) { 31896 var n = r(14), 31897 i = r(53), 31898 o = r(6)("species"); 31899 31900 t.exports = function (t, e) { 31901 var r; 31902 return i(t) && ("function" != typeof (r = t.constructor) || r !== Array && !i(r.prototype) ? n(r) && null === (r = r[o]) && (r = void 0) : r = void 0), new (void 0 === r ? Array : r)(0 === e ? 0 : e); 31903 }; 31904 }, function (t, e, r) { 31905 31906 var n = r(0), 31907 i = r(12), 31908 o = r(53), 31909 a = r(14), 31910 s = r(22), 31911 u = r(29), 31912 f = r(87), 31913 c = r(113), 31914 l = r(68), 31915 h = r(6)("isConcatSpreadable"), 31916 d = !i(function () { 31917 var t = []; 31918 return t[h] = !1, t.concat()[0] !== t; 31919 }), 31920 p = l("concat"), 31921 g = function (t) { 31922 if (!a(t)) return !1; 31923 var e = t[h]; 31924 return void 0 !== e ? !!e : o(t); 31925 }; 31926 31927 n({ 31928 target: "Array", 31929 proto: !0, 31930 forced: !d || !p 31931 }, { 31932 concat: function (t) { 31933 var e, 31934 r, 31935 n, 31936 i, 31937 o, 31938 a = s(this), 31939 l = c(a, 0), 31940 h = 0; 31941 31942 for (e = -1, n = arguments.length; e < n; e++) if (o = -1 === e ? a : arguments[e], g(o)) { 31943 if (h + (i = u(o.length)) >
31943 9007199254740991) throw TypeError("Maximum allowed index exceeded"); 31944 31945 for (r = 0; r < i; r++, h++) r in o && f(l, h, o[r]); 31946 } else { 31947 if (h >= 9007199254740991) throw TypeError("Maximum allowed index exceeded"); 31948 f(l, h++, o); 31949 } 31950 31951 return l.length = h, l; 31952 } 31953 }); 31954 }, function (t, e, r) { 31955 r(88), r(46), r(41), r(188), r(125), r(191); 31956 var n = r(3); 31957 t.exports = n.Promise; 31958 }, function (t, e, r) { 31959 var n = r(13); 31960 t.exports = n.Promise; 31961 }, function (t, e, r) { 31962 var n = r(52); 31963 31964 t.exports = function (t, e, r) { 31965 for (var i in e) r && r.unsafe && t[i] ? t[i] = e[i] : n(t, i, e[i], r); 31966 31967 return t; 31968 }; 31969 }, function (t, e, r) { 31970 31971 var n = r(26), 31972 i = r(21), 31973 o = r(6), 31974 a = r(17), 31975 s = o("species"); 31976 31977 t.exports = function (t) { 31978 var e = n(t), 31979 r = i.f; 31980 a && e && !e[s] && r(e, s, { 31981 configurable: !0, 31982 get: function () { 31983 return this; 31984 } 31985 }); 31986 }; 31987 }, function (t, e, r) { 31988 var n = r(6), 31989 i = r(35), 31990 o = n("iterator"), 31991 a = Array.prototype; 31992 31993 t.exports = function (t) { 31994 return void 0 !== t && (i.Array === t || a[o] === t); 31995 }; 31996 }, function (t, e, r) { 31997 var n = r(2); 31998 31999 t.exports = function (t, e, r, i) { 32000 try { 32001 return i ? e(n(r)[0], r[1]) : e(r); 32002 } catch (e) { 32003 var o = t.return; 32004 throw void 0 !== o && n(o.call(t)), e; 32005 } 32006 }; 32007 }, function (t, e, r) { 32008 var n = r(6)("iterator"), 32009 i = !1; 32010 32011 try { 32012 var o = 0, 32013 a = { 32014 next: function () { 32015 return { 32016 done: !!o++ 32017 }; 32018 }, 32019 return: function () { 32020 i = !0; 32021 } 32022 }; 32023 a[n] = function () { 32024 return this; 32025 }, Array.from(a, function () { 32026 throw 2; 32027 }); 32028 } catch (t) {} 32029 32030 t.exports = function (t, e) { 32031 if (!e && !i) return !1; 32032 var r = !1; 32033 32034 try { 32035 var o = {}; 32036 o[n] = function () { 32037 return { 32038 next: function () { 32039 return { 32040 done: r = !0 32041 }; 32042 } 32043 }; 32044 }, t(o); 32045 } catch (t) {} 32046 32047 return r; 32048 }; 32049 }, function (t, e, r) { 32050 var n, 32051 i, 32052 o, 32053 a = r(13), 32054 s = r(12), 32055 u = r(34), 32056 f = r(15), 32057 c = r(112), 32058 l = r(79), 32059 h = a.location, 32060 d = a.setImmediate, 32061 p = a.clearImmediate, 32062 g = a.process, 32063 v = a.MessageChannel, 32064 y = a.Dispatch, 32065 m = 0, 32066 b = {}, 32067 _ = function (t) { 32068 if (b.hasOwnProperty(t)) { 32069 var e = b[t]; 32070 delete b[t], e(); 32071 } 32072 }, 32073 w = function (t) { 32074 return function () { 32075 _(t); 32076 }; 32077 }, 32078 x = function (t) { 32079 _(t.data); 32080 }, 32081 E = function (t) { 32082 a.postMessage(t + "", h.protocol + "//" + h.host); 32083 }; 32084 32085 d && p || (d = function (t) { 32086 for (var e = [], r = 1; arguments.length > r;) e.push(arguments[r++]); 32087 32088 return b[++m] = function () { 32089 ("function" == typeof t ? t : Function(t)).apply(void 0, e); 32090 }, n(m), m; 32091 }, p = function (t) { 32092 delete b[t]; 32093 }, "process" == u(g) ? n = function (t) { 32094 g.nextTick(w(t)); 32095 } : y && y.now ? n = function (t) { 32096 y.now(w(t)); 32097 } : v ? (o = (i = new v()).port2, i.port1.onmessage = x, n = f(o.postMessage, o, 1)) : !a.addEventListener || "function" != typeof postMessage || a.importScripts || s(E) ? n = "onreadystatechange" in l("script") ? function (t) { 32098 c.appendChild(l("script")).onreadystatechange = function () { 32099 c.removeChild(this), _(t); 32100 }; 32101 } : function (t) { 32102 setTimeout(w(t), 0); 32103 } : (n = E, a.addEventListener("message", x, !1))), t.exports = { 32104 set: d, 32105 clear: p 32106 }; 32107 }, function (t, e, r) { 32108 var n = r(26); 32109 t.exports = n("navigator", "userAgent") || ""; 32110 }, function (t, e, r) { 32111 var n = r(2), 32112 i = r(14), 32113 o = r(56); 32114 32115 t.exports = function (t, e) { 32116 if (n(t), i(e) && e.constructor === t) return e; 32117 var r = o.f(t); 32118 return (0, r.resolve)(e), r.promise; 32119 }; 32120 }, function (t, e, r) { 32121 32122 var n = r(0), 32123 i = r(5), 32124 o = r(56), 32125 a = r(69), 32126 s = r(8); 32127 n({ 32128 target: "Promise", 32129 stat: !0 32130 }, { 32131 allSettled: function (t) { 32132 var e = this, 32133 r = o.f(e), 32134 n = r.resolve, 32135 u = r.reject, 32136 f = a(function () { 32137 var r = i(e.resolve), 32138 o = [], 32139 a = 0, 32140 u = 1; 32141 s(t, function (t) { 32142 var i = a++, 32143 s = !1; 32144 o.push(void 0), u++, r.call(e, t).then(function (t) { 32145 s || (s = !0, o[i] = { 32146 status: "fulfilled", 32147 value: t 32148 }, --u || n(o)); 32149 }, function (t) { 32150 s || (s = !0, o[i] = { 32151 status: "rejected", 32152 reason: t 32153 }, --u || n(o)); 32154 }); 32155 }), --u || n(o); 32156 }); 32157 return f.error && u(f.value), r.promise; 32158 } 32159 }); 32160 }, function (t, e, r) { 32161 32162 (function (t) { 32163 var n = r(19).Buffer, 32164 i = r(200).Transform, 32165 o = r(212), 32166 a = r(133), 32167 s = r(132).ok, 32168 u = r(19).kMaxLength,
32169 f = "Cannot create final Buffer. It would be larger than 0x" + u.toString(16) + " bytes"; 32170 o.Z_MIN_WINDOWBITS = 8, o.Z_MAX_WINDOWBITS = 15, o.Z_DEFAULT_WINDOWBITS = 15, o.Z_MIN_CHUNK = 64, o.Z_MAX_CHUNK = 1 / 0, o.Z_DEFAULT_CHUNK = 16384, o.Z_MIN_MEMLEVEL = 1, o.Z_MAX_MEMLEVEL = 9, o.Z_DEFAULT_MEMLEVEL = 8, o.Z_MIN_LEVEL = -1, o.Z_MAX_LEVEL = 9, o.Z_DEFAULT_LEVEL = o.Z_DEFAULT_COMPRESSION; 32171 32172 for (var c = Object.keys(o), l = 0; l < c.length; l++) { 32173 var h = c[l]; 32174 h.match(/^Z/) && Object.defineProperty(e, h, { 32175 enumerable: !0, 32176 value: o[h], 32177 writable: !1 32178 }); 32179 } 32180 32181 for (var d = { 32182 Z_OK: o.Z_OK, 32183 Z_STREAM_END: o.Z_STREAM_END, 32184 Z_NEED_DICT: o.Z_NEED_DICT, 32185 Z_ERRNO: o.Z_ERRNO, 32186 Z_STREAM_ERROR: o.Z_STREAM_ERROR, 32187 Z_DATA_ERROR: o.Z_DATA_ERROR, 32188 Z_MEM_ERROR: o.Z_MEM_ERROR, 32189 Z_BUF_ERROR: o.Z_BUF_ERROR, 32190 Z_VERSION_ERROR: o.Z_VERSION_ERROR 32191 }, p = Object.keys(d), g = 0; g < p.length; g++) { 32192 var v = p[g]; 32193 d[d[v]] = v; 32194 } 32195 32196 function y(t, e, r) { 32197 var i = [], 32198 o = 0; 32199 32200 function a() { 32201 for (var e; null !== (e = t.read());) i.push(e), o += e.length; 32202 32203 t.once("readable", a); 32204 } 32205 32206 function s() { 32207 var e, 32208 a = null; 32209 o >= u ? a = new RangeError(f) : e = n.concat(i, o), i = [], t.close(), r(a, e); 32210 } 32211 32212 t.on("error", function (e) { 32213 t.removeListener("end", s), t.removeListener("readable", a), r(e); 32214 }), t.on("end", s), t.end(e), a(); 32215 } 32216 32217 function m(t, e) { 32218 if ("string" == typeof e && (e = n.from(e)), !n.isBuffer(e)) throw new TypeError("Not a string or buffer"); 32219 var r = t._finishFlushFlag; 32220 return t._processChunk(e, r); 32221 } 32222 32223 function b(t) { 32224 if (!(this instanceof b)) return new b(t); 32225 C.call(this, t, o.DEFLATE); 32226 } 32227 32228 function _(t) { 32229 if (!(this instanceof _)) return new _(t); 32230 C.call(this, t, o.INFLATE); 32231 } 32232 32233 function w(t) { 32234 if (!(this instanceof w)) return new w(t); 32235 C.call(this, t, o.GZIP); 32236 } 32237 32238 function x(t) { 32239 if (!(this instanceof x)) return new x(t); 32240 C.call(this, t, o.GUNZIP); 32241 } 32242 32243 function E(t) { 32244 if (!(this instanceof E)) return new E(t); 32245 C.call(this, t, o.DEFLATERAW); 32246 } 32247 32248 function S(t) { 32249 if (!(this instanceof S)) return new S(t); 32250 C.call(this, t, o.INFLATERAW); 32251 } 32252 32253 function k(t) { 32254 if (!(this instanceof k)) return new k(t); 32255 C.call(this, t, o.UNZIP); 32256 } 32257 32258 function A(t) { 32259 return t === o.Z_NO_FLUSH || t === o.Z_PARTIAL_FLUSH || t === o.Z_SYNC_FLUSH || t === o.Z_FULL_FLUSH || t === o.Z_FINISH || t === o.Z_BLOCK; 32260 } 32261 32262 function C(t, r) { 32263 var a = this; 32264 if (this._opts = t = t || {}, this._chunkSize = t.chunkSize || e.Z_DEFAULT_CHUNK, i.call(this, t), t.flush && !A(t.flush)) throw new Error("Invalid flush flag: " + t.flush); 32265 if (t.finishFlush && !A(t.finishFlush)) throw new Error("Invalid flush flag: " + t.finishFlush); 32266 if (this._flushFlag = t.flush || o.Z_NO_FLUSH, this._finishFlushFlag = void 0 !== t.finishFlush ? t.finishFlush : o.Z_FINISH, t.chunkSize && (t.chunkSize < e.Z_MIN_CHUNK || t.chunkSize > e.Z_MAX_CHUNK)) throw new Error("Invalid chunk size: " + t.chunkSize); 32267 if (t.windowBits && (t.windowBits < e.Z_MIN_WINDOWBITS || t.windowBits > e.Z_MAX_WINDOWBITS)) throw new Error("Invalid windowBits: " + t.windowBits); 32268 if (t.level && (t.level < e.Z_MIN_LEVEL || t.level > e.Z_MAX_LEVEL)) throw new Error("Invalid compression level: " + t.level); 32269 if (t.memLevel && (t.memLevel < e.Z_MIN_MEMLEVEL || t.memLevel > e.Z_MAX_MEMLEVEL)) throw new Error("Invalid memLevel: " + t.memLevel); 32270 if (t.strategy && t.strategy != e.Z_FILTERED && t.strategy != e.Z_HUFFMAN_ONLY && t.strategy != e.Z_RLE && t.strategy != e.Z_FIXED && t.strategy != e.Z_DEFAULT_STRATEGY) throw new Error("Invalid strategy: " + t.strategy); 32271 if (t.dictionary && !n.isBuffer(t.dictionary)) throw new Error("Invalid dictionary: it should be a Buffer instance"); 32272 this._handle = new o.Zlib(r); 32273 var s = this; 32274 this._hadError = !1, this._handle.onerror = function (t, r) { 32275 T(s), s._hadError = !0; 32276 var n = new Error(t); 32277 n.errno = r, n.code = e.codes[r], s.emit("error", n); 32278 }; 32279 var u = e.Z_DEFAULT_COMPRESSION; 32280 "number" == typeof t.level && (u = t.level); 32281 var f = e.Z_DEFAULT_STRATEGY; 32282 "number" == typeof t.strategy && (f = t.strategy), this._handle.init(t.windowBits || e.Z_DEFAULT_WINDOWBITS, u, t.memLevel || e.Z_DEFAULT_MEMLEVEL, f, t.dictionary), this._buffer = n.allocUnsafe(this._chunkSize), this._offset = 0, this._level = u, this._strategy = f, this.once("end", this.close), Object.defineProperty(this, "_closed", { 32283 get: function () { 32284 return !a._handle; 32285 }, 32286 configurable: !0, 32287 enumerable: !0 32288 }); 32289 } 32290 32291 function T(e, r) { 32292 r && t.nextTick(r), e._handle && (e._handle.close(), e._handle = null); 32293 } 32294 32295 function R(t) { 32296 t.emit("close"); 32297 } 32298 32299 Object.defineProperty(e, "codes", { 32300 enumerable: !0, 32301 value: Object.freeze(d), 32302 writable: !1 32303 }), e.Deflate = b, e.Inflate = _, e.Gzip = w, e.Gunzip = x, e.DeflateRaw = E, e.InflateRaw = S, e.Unzip = k, e.createDeflate = function (t) { 32304 return new b(t); 32305 }, e.createInflate = function (t) { 32306 return new _(t); 32307 }, e.createDeflateRaw = function (t) { 32308 return new E(t); 32309 }, e.createInflateRaw = function (t) { 32310 return new S(t); 32311 }, e.createGzip = function (t) { 32312 return new w(t); 32313 }, e.createGunzip = function (t) { 32314 return new x(t); 32315 }, e.createUnzip = function (t) { 32316 return new k(t); 32317 }, e.deflate = function (t, e, r) { 32318 return "function" == typeof e && (r = e, e = {}), y(new b(e), t, r); 32319 }, e.deflateSync = function (t, e) { 32320 return m(new b(e), t); 32321 }, e.gzip = function (t, e, r) { 32322 return "function" == typeof e && (r = e, e = {}), y(new w(e), t, r); 32323 }, e.gzipSync = function (t, e) { 32324 return m(new w(e), t); 32325 }, e.deflateRaw = function (t, e, r) { 32326 return "function" == typeof e && (r = e, e = {}), y(new E(e), t, r); 32327 }, e.deflateRawSync = function (t, e) { 32328 return m(new E(e), t); 32329 }, e.unzip = function (t, e, r) { 32330 return "function" == typeof e && (r = e, e = {}), y(new k(e), t, r); 32331 }, e.unzipSync = function (t, e) { 32332 return m(new k(e), t); 32333 }, e.inflate = function (t, e, r) { 32334 return "function" == typeof e && (r = e, e = {}), y(new _(e), t, r); 32335 }, e.inflateSync = function (t, e) { 32336 return m(new _(e), t); 32337 }, e.gunzip = function (t, e, r) { 32338 return "function" == typeof e && (r = e, e = {}), y(new x(e), t, r); 32339 }, e.gunzipSync = function (t, e) { 32340 return m(new x(e), t); 32341 }, e.inflateRaw = function (t, e, r) { 32342 return "function" == typeof e && (r = e, e = {}), y(new S(e), t, r); 32343 }, e.inflateRawSync = function (t, e) { 32344 return m(new S(e), t); 32345 }, a.inherits(C, i), C.prototype.params = function (r, n, i) { 32346 if (r < e.Z_MIN_LEVEL || r > e.Z_MAX_LEVEL) throw new RangeError("Invalid compression level: " + r); 32347 if (n != e.Z_FILTERED && n != e.Z_HUFFMAN_ONLY && n != e.Z_RLE && n != e.Z_FIXED && n != e.Z_DEFAULT_STRATEGY) throw new TypeError("Invalid strategy: " + n); 32348 32349 if (this._level !== r || this._strategy !== n) { 32350 var a = this; 32351 this.flush(o.Z_SYNC_FLUSH, function () { 32352 s(a._handle, "zlib binding closed"), a._handle.params(r, n), a._hadError || (a._level = r, a._strategy = n, i && i()); 32353 }); 32354 } else t.nextTick(i); 32355 }, C.prototype.reset = function () { 32356 return s(this._handle, "zlib binding closed"), this._handle.reset(); 32357 }, C.prototype._flush = function (t) { 32358 this._transform(n.alloc(0), "", t); 32359 }, C.prototype.flush = function (e, r) { 32360 var i = this, 32361 a = this._writableState; 32362 ("function" == typeof e || void 0 === e && !r) && (r = e, e = o.Z_FULL_FLUSH), a.ended ? r && t.nextTick(r) : a.ending ? r && this.once("end", r) : a.needDrain ? r && this.once("drain", function () { 32363 return i.flush(e, r); 32364 }) : (this._flushFlag = e, this.write(n.alloc(0), "", r)); 32365 }, C.prototype.close = function (e) { 32366 T(this, e), t.nextTick(R, this); 32367 }, C.prototype._transform = function (t, e, r) { 32368 var i, 32369 a = this._writableState, 32370 s = (a.ending || a.ended) && (!t || a.length === t.length); 32371 return null === t || n.isBuffer(t) ? this._handle ? (s ? i = this._finishFlushFlag : (i = this._flushFlag, t.length >= a.length && (this._flushFlag = this._opts.flush || o.Z_NO_FLUSH)), void this._processChunk(t, i, r)) : r(new Error("zlib binding closed")) : r(new Error("invalid input")); 32372 }, C.prototype._processChunk = function (t, e, r) { 32373 var i = t && t.length, 32374 o = this._chunkSize - this._offset, 32375 a = 0, 32376 c = this, 32377 l = "function" == typeof r; 32378 32379 if (!l) { 32380 var h, 32381 d = [], 32382 p = 0; 32383 this.on("error", function (t) { 32384 h = t; 32385 }), s(this._handle, "zlib binding closed"); 32386 32387 do { 32388 var g = this._handle.writeSync(e, t, a, i, this._buffer, this._offset, o); 32389 } while (!this._hadError && m(g[0], g[1])); 32390 32391 if (this._hadError) throw h; 32392 if (p >= u) throw T(this), new RangeError(f); 32393 var v = n.concat(d, p); 32394 return T(this), v; 32395 } 32396 32397 s(this._handle, "zlib binding closed"); 32398 32399 var y = this._handle.write(e, t, a, i, this._buffer, this._offset, o); 32400 32401 function m(u, f) { 32402 if (this && (this.buffer = null, this.callback = null), !c._hadError) { 32403 var h = o - f; 32404 32405 if (s(h >= 0, "have should not go down"), h > 0) { 32406 var g = c._buffer.slice(c._offset, c._offset + h); 32407 32408 c._offset += h, l ? c.push(g) : (d.push(g), p += g.length); 32409 } 32410 32411 if ((0 === f || c._offset >= c._chunkSize) && (o = c._chunkSize, c._offset = 0, c._buffer = n.allocUnsafe(c._chunkSize)), 0 === f) { 32412 if (a += i - u, i = u, !l) return !0; 32413 32414 var v = c._handle.write(e, t, a, i, c._buffer, c._offset, c._chunkSize); 32415 32416 return v.callback = m, void (v.buffer = t); 32417 } 32418 32419 if (!l) return !1; 32420 r(); 32421 } 32422 } 32423 32424 y.buffer = t, y.callback = m; 32425 }, a.inherits(b, C), a.inherits(_, C), a.inherits(w, C), a.inherits(x, C), a.inherits(E, C), a.inherits(S, C), a.inherits(k, C); 32426 }).call(this, r(38)); 32427 }, function (t, e, r) { 32428 32429 (function (e, n) { 32430 var i = r(70); 32431 t.exports = b; 32432 var o,
32433 a = r(105); 32434 b.ReadableState = m; 32435 r(91).EventEmitter; 32436 32437 var s = function (t, e) { 32438 return t.listeners(e).length; 32439 }, 32440 u = r(128), 32441 f = r(71).Buffer, 32442 c = e.Uint8Array || function () {}; 32443 32444 var l = r(57); 32445 l.inherits = r(47); 32446 var h = r(201), 32447 d = void 0; 32448 d = h && h.debuglog ? h.debuglog("stream") : function () {}; 32449 var p, 32450 g = r(202), 32451 v = r(129); 32452 l.inherits(b, u); 32453 var y = ["error", "close", "destroy", "pause", "resume"]; 32454 32455 function m(t, e) { 32456 t = t || {}; 32457 var n = e instanceof (o = o || r(39)); 32458 this.objectMode = !!t.objectMode, n && (this.objectMode = this.objectMode || !!t.readableObjectMode); 32459 var i = t.highWaterMark, 32460 a = t.readableHighWaterMark, 32461 s = this.objectMode ? 16 : 16384; 32462 this.highWaterMark = i || 0 === i ? i : n && (a || 0 === a) ? a : s, this.highWaterMark = Math.floor(this.highWaterMark), this.buffer = new g(), this.length = 0, this.pipes = null, this.pipesCount = 0, this.flowing = null, this.ended = !1, this.endEmitted = !1, this.reading = !1, this.sync = !0, this.needReadable = !1, this.emittedReadable = !1, this.readableListening = !1, this.resumeScheduled = !1, this.destroyed = !1, this.defaultEncoding = t.defaultEncoding || "utf8", this.awaitDrain = 0, this.readingMore = !1, this.decoder = null, this.encoding = null, t.encoding && (p || (p = r(130).StringDecoder), this.decoder = new p(t.encoding), this.encoding = t.encoding); 32463 } 32464 32465 function b(t) { 32466 if (o = o || r(39), !(this instanceof b)) return new b(t); 32467 this._readableState = new m(t, this), this.readable = !0, t && ("function" == typeof t.read && (this._read = t.read), "function" == typeof t.destroy && (this._destroy = t.destroy)), u.call(this); 32468 } 32469 32470 function _(t, e, r, n, i) { 32471 var o, 32472 a = t._readableState; 32473 null === e ? (a.reading = !1, function (t, e) { 32474 if (e.ended) return; 32475 32476 if (e.decoder) { 32477 var r = e.decoder.end(); 32478 r && r.length && (e.buffer.push(r), e.length += e.objectMode ? 1 : r.length); 32479 } 32480 32481 e.ended = !0, S(t); 32482 }(t, a)) : (i || (o = function (t, e) { 32483 var r; 32484 n = e, f.isBuffer(n) || n instanceof c || "string" == typeof e || void 0 === e || t.objectMode || (r = new TypeError("Invalid non-string/buffer chunk")); 32485 var n; 32486 return r; 32487 }(a, e)), o ? t.emit("error", o) : a.objectMode || e && e.length > 0 ? ("string" == typeof e || a.objectMode || Object.getPrototypeOf(e) === f.prototype || (e = function (t) { 32488 return f.from(t); 32489 }(e)), n ? a.endEmitted ? t.emit("error", new Error("stream.unshift() after end event")) : w(t, a, e, !0) : a.ended ? t.emit("error", new Error("stream.push() after EOF")) : (a.reading = !1, a.decoder && !r ? (e = a.decoder.write(e), a.objectMode || 0 !== e.length ? w(t, a, e, !1) : A(t, a)) : w(t, a, e, !1))) : n || (a.reading = !1)); 32490 return function (t) { 32491 return !t.ended && (t.needReadable || t.length < t.highWaterMark || 0 === t.length); 32492 }(a); 32493 } 32494 32495 function w(t, e, r, n) { 32496 e.flowing && 0 === e.length && !e.sync ? (t.emit("data", r), t.read(0)) : (e.length += e.objectMode ? 1 : r.length, n ? e.buffer.unshift(r) : e.buffer.push(r), e.needReadable && S(t)), A(t, e); 32497 } 32498 32499 Object.defineProperty(b.prototype, "destroyed", { 32500 get: function () { 32501 return void 0 !== this._readableState && this._readableState.destroyed; 32502 }, 32503 set: function (t) { 32504 this._readableState && (this._readableState.destroyed = t); 32505 } 32506 }), b.prototype.destroy = v.destroy, b.prototype._undestroy = v.undestroy, b.prototype._destroy = function (t, e) { 32507 this.push(null), e(t); 32508 }, b.prototype.push = function (t, e) { 32509 var r, 32510 n = this._readableState; 32511 return n.objectMode ? r = !0 : "string" == typeof t && ((e = e || n.defaultEncoding) !== n.encoding && (t = f.from(t, e), e = ""), r = !0), _(this, t, e, !1, r); 32512 }, b.prototype.unshift = function (t) { 32513 return _(this, t, null, !0, !1); 32514 }, b.prototype.isPaused = function () { 32515 return !1 === this._readableState.flowing; 32516 }, b.prototype.setEncoding = function (t) { 32517 return p || (p = r(130).StringDecoder), this._readableState.decoder = new p(t), this._readableState.encoding = t, this; 32518 }; 32519 var x = 8388608; 32520 32521 function E(t, e) { 32522 return t <= 0 || 0 === e.length && e.ended ? 0 : e.objectMode ? 1 : t != t ? e.flowing && e.length ? e.buffer.head.data.length : e.length : (t > e.highWaterMark && (e.highWaterMark = function (t) { 32523 return t >= x ? t = x : (t--, t |= t >>> 1, t |= t >>> 2, t |= t >>> 4, t |= t >>> 8, t |= t >>> 16, t++), t;
vendor: 16,526 bytes, lines 32524-32947
32524 }(t)), t <= e.length ? t : e.ended ? e.length : (e.needReadable = !0, 0)); 32525 } 32526 32527 function S(t) { 32528 var e = t._readableState; 32529 e.needReadable = !1, e.emittedReadable || (d("emitReadable", e.flowing), e.emittedReadable = !0, e.sync ? i.nextTick(k, t) : k(t)); 32530 } 32531 32532 function k(t) { 32533 d("emit readable"), t.emit("readable"), O(t); 32534 } 32535 32536 function A(t, e) { 32537 e.readingMore || (e.readingMore = !0, i.nextTick(C, t, e)); 32538 } 32539 32540 function C(t, e) { 32541 for (var r = e.length; !e.reading && !e.flowing && !e.ended && e.length < e.highWaterMark && (d("maybeReadMore read 0"), t.read(0), r !== e.length);) r = e.length; 32542 32543 e.readingMore = !1; 32544 } 32545 32546 function T(t) { 32547 d("readable nexttick read 0"), t.read(0); 32548 } 32549 32550 function R(t, e) { 32551 e.reading || (d("resume read 0"), t.read(0)), e.resumeScheduled = !1, e.awaitDrain = 0, t.emit("resume"), O(t), e.flowing && !e.reading && t.read(0); 32552 } 32553 32554 function O(t) { 32555 var e = t._readableState; 32556 32557 for (d("flow", e.flowing); e.flowing && null !== t.read();); 32558 } 32559 32560 function I(t, e) { 32561 return 0 === e.length ? null : (e.objectMode ? r = e.buffer.shift() : !t || t >= e.length ? (r = e.decoder ? e.buffer.join("") : 1 === e.buffer.length ? e.buffer.head.data : e.buffer.concat(e.length), e.buffer.clear()) : r = function (t, e, r) { 32562 var n; 32563 t < e.head.data.length ? (n = e.head.data.slice(0, t), e.head.data = e.head.data.slice(t)) : n = t === e.head.data.length ? e.shift() : r ? function (t, e) { 32564 var r = e.head, 32565 n = 1, 32566 i = r.data; 32567 t -= i.length; 32568 32569 for (; r = r.next;) { 32570 var o = r.data, 32571 a = t > o.length ? o.length : t; 32572 32573 if (a === o.length ? i += o : i += o.slice(0, t), 0 === (t -= a)) { 32574 a === o.length ? (++n, r.next ? e.head = r.next : e.head = e.tail = null) : (e.head = r, r.data = o.slice(a)); 32575 break; 32576 } 32577 32578 ++n; 32579 } 32580 32581 return e.length -= n, i; 32582 }(t, e) : function (t, e) { 32583 var r = f.allocUnsafe(t), 32584 n = e.head, 32585 i = 1; 32586 n.data.copy(r), t -= n.data.length; 32587 32588 for (; n = n.next;) { 32589 var o = n.data, 32590 a = t > o.length ? o.length : t; 32591 32592 if (o.copy(r, r.length - t, 0, a), 0 === (t -= a)) { 32593 a === o.length ? (++i, n.next ? e.head = n.next : e.head = e.tail = null) : (e.head = n, n.data = o.slice(a)); 32594 break; 32595 } 32596 32597 ++i; 32598 } 32599 32600 return e.length -= i, r; 32601 }(t, e); 32602 return n; 32603 }(t, e.buffer, e.decoder), r); 32604 var r; 32605 } 32606 32607 function L(t) { 32608 var e = t._readableState; 32609 if (e.length > 0) throw new Error('"endReadable()" called on non-empty stream'); 32610 e.endEmitted || (e.ended = !0, i.nextTick(B, e, t)); 32611 } 32612 32613 function B(t, e) { 32614 t.endEmitted || 0 !== t.length || (t.endEmitted = !0, e.readable = !1, e.emit("end")); 32615 } 32616 32617 function P(t, e) { 32618 for (var r = 0, n = t.length; r < n; r++) if (t[r] === e) return r; 32619 32620 return -1; 32621 } 32622 32623 b.prototype.read = function (t) { 32624 d("read", t), t = parseInt(t, 10); 32625 var e = this._readableState, 32626 r = t; 32627 if (0 !== t && (e.emittedReadable = !1), 0 === t && e.needReadable && (e.length >= e.highWaterMark || e.ended)) return d("read: emitReadable", e.length, e.ended), 0 === e.length && e.ended ? L(this) : S(this), null; 32628 if (0 === (t = E(t, e)) && e.ended) return 0 === e.length && L(this), null; 32629 var n, 32630 i = e.needReadable; 32631 return d("need readable", i), (0 === e.length || e.length - t < e.highWaterMark) && d("length less than watermark", i = !0), e.ended || e.reading ? d("reading or ended", i = !1) : i && (d("do read"), e.reading = !0, e.sync = !0, 0 === e.length && (e.needReadable = !0), this._read(e.highWaterMark), e.sync = !1, e.reading || (t = E(r, e))), null === (n = t > 0 ? I(t, e) : null) ? (e.needReadable = !0, t = 0) : e.length -= t, 0 === e.length && (e.ended || (e.needReadable = !0), r !== t && e.ended && L(this)), null !== n && this.emit("data", n), n; 32632 }, b.prototype._read = function (t) { 32633 this.emit("error", new Error("_read() is not implemented")); 32634 }, b.prototype.pipe = function (t, e) { 32635 var r = this, 32636 o = this._readableState; 32637 32638 switch (o.pipesCount) { 32639 case 0: 32640 o.pipes = t; 32641 break; 32642 32643 case 1: 32644 o.pipes = [o.pipes, t]; 32645 break; 32646 32647 default: 32648 o.pipes.push(t); 32649 } 32650 32651 o.pipesCount += 1, d("pipe count=%d opts=%j", o.pipesCount, e); 32652 var u = (!e || !1 !== e.end) && t !== n.stdout && t !== n.stderr ? c : b; 32653 32654 function f(e, n) { 32655 d("onunpipe"), e === r && n && !1 === n.hasUnpiped && (n.hasUnpiped = !0, d("cleanup"), t.removeListener("close", y), t.removeListener("finish", m), t.removeListener("drain", l), t.removeListener("error", v), t.removeListener("unpipe", f), r.removeListener("end", c), r.removeListener("end", b), r.removeListener("data", g), h = !0, !o.awaitDrain || t._writableState && !t._writableState.needDrain || l()); 32656 } 32657 32658 function c() { 32659 d("onend"), t.end(); 32660 } 32661 32662 o.endEmitted ? i.nextTick(u) : r.once("end", u), t.on("unpipe", f); 32663 32664 var l = function (t) { 32665 return function () { 32666 var e = t._readableState; 32667 d("pipeOnDrain", e.awaitDrain), e.awaitDrain && e.awaitDrain--, 0 === e.awaitDrain && s(t, "data") && (e.flowing = !0, O(t)); 32668 }; 32669 }(r); 32670 32671 t.on("drain", l); 32672 var h = !1; 32673 var p = !1; 32674 32675 function g(e) { 32676 d("ondata"), p = !1, !1 !== t.write(e) || p || ((1 === o.pipesCount && o.pipes === t || o.pipesCount > 1 && -1 !== P(o.pipes, t)) && !h && (d("false write response, pause", r._readableState.awaitDrain), r._readableState.awaitDrain++, p = !0), r.pause()); 32677 } 32678 32679 function v(e) { 32680 d("onerror", e), b(), t.removeListener("error", v), 0 === s(t, "error") && t.emit("error", e); 32681 } 32682 32683 function y() { 32684 t.removeListener("finish", m), b(); 32685 } 32686 32687 function m() { 32688 d("onfinish"), t.removeListener("close", y), b(); 32689 } 32690 32691 function b() { 32692 d("unpipe"), r.unpipe(t); 32693 } 32694 32695 return r.on("data", g), function (t, e, r) { 32696 if ("function" == typeof t.prependListener) return t.prependListener(e, r); 32697 t._events && t._events[e] ? a(t._events[e]) ? t._events[e].unshift(r) : t._events[e] = [r, t._events[e]] : t.on(e, r); 32698 }(t, "error", v), t.once("close", y), t.once("finish", m), t.emit("pipe", r), o.flowing || (d("pipe resume"), r.resume()), t; 32699 }, b.prototype.unpipe = function (t) { 32700 var e = this._readableState, 32701 r = { 32702 hasUnpiped: !1 32703 }; 32704 if (0 === e.pipesCount) return this; 32705 if (1 === e.pipesCount) return t && t !== e.pipes ? this : (t || (t = e.pipes), e.pipes = null, e.pipesCount = 0, e.flowing = !1, t && t.emit("unpipe", this, r), this); 32706 32707 if (!t) { 32708 var n = e.pipes, 32709 i = e.pipesCount; 32710 e.pipes = null, e.pipesCount = 0, e.flowing = !1; 32711 32712 for (var o = 0; o < i; o++) n[o].emit("unpipe", this, r); 32713 32714 return this; 32715 } 32716 32717 var a = P(e.pipes, t); 32718 return -1 === a ? this : (e.pipes.splice(a, 1), e.pipesCount -= 1, 1 === e.pipesCount && (e.pipes = e.pipes[0]), t.emit("unpipe", this, r), this); 32719 }, b.prototype.on = function (t, e) { 32720 var r = u.prototype.on.call(this, t, e); 32721 if ("data" === t) !1 !== this._readableState.flowing && this.resume();else if ("readable" === t) { 32722 var n = this._readableState; 32723 n.endEmitted || n.readableListening || (n.readableListening = n.needReadable = !0, n.emittedReadable = !1, n.reading ? n.length && S(this) : i.nextTick(T, this)); 32724 } 32725 return r; 32726 }, b.prototype.addListener = b.prototype.on, b.prototype.resume = function () { 32727 var t = this._readableState; 32728 return t.flowing || (d("resume"), t.flowing = !0, function (t, e) { 32729 e.resumeScheduled || (e.resumeScheduled = !0, i.nextTick(R, t, e)); 32730 }(this, t)), this; 32731 }, b.prototype.pause = function () { 32732 return d("call pause flowing=%j", this._readableState.flowing), !1 !== this._readableState.flowing && (d("pause"), this._readableState.flowing = !1, this.emit("pause")), this; 32733 }, b.prototype.wrap = function (t) { 32734 var e = this, 32735 r = this._readableState, 32736 n = !1; 32737 32738 for (var i in t.on("end", function () { 32739 if (d("wrapped end"), r.decoder && !r.ended) { 32740 var t = r.decoder.end(); 32741 t && t.length && e.push(t); 32742 } 32743 32744 e.push(null); 32745 }), t.on("data", function (i) { 32746 (d("wrapped data"), r.decoder && (i = r.decoder.write(i)), r.objectMode && null == i) || (r.objectMode || i && i.length) && (e.push(i) || (n = !0, t.pause())); 32747 }), t) void 0 === this[i] && "function" == typeof t[i] && (this[i] = function (e) { 32748 return function () { 32749 return t[e].apply(t, arguments); 32750 }; 32751 }(i)); 32752 32753 for (var o = 0; o < y.length; o++) t.on(y[o], this.emit.bind(this, y[o])); 32754 32755 return this._read = function (e) { 32756 d("wrapped _read", e), n && (n = !1, t.resume()); 32757 }, this; 32758 }, Object.defineProperty(b.prototype, "readableHighWaterMark", { 32759 enumerable: !1, 32760 get: function () { 32761 return this._readableState.highWaterMark; 32762 } 32763 }), b._fromList = I; 32764 }).call(this, r(23), r(38)); 32765 }, function (t, e, r) { 32766 t.exports = r(91).EventEmitter; 32767 }, function (t, e, r) { 32768 32769 var n = r(70); 32770 32771 function i(t, e) { 32772 t.emit("error", e); 32773 } 32774 32775 t.exports = { 32776 destroy: function (t, e) { 32777 var r = this, 32778 o = this._readableState && this._readableState.destroyed, 32779 a = this._writableState && this._writableState.destroyed; 32780 return o || a ? (e ? e(t) : !t || this._writableState && this._writableState.errorEmitted || n.nextTick(i, this, t), this) : (this._readableState && (this._readableState.destroyed = !0), this._writableState && (this._writableState.destroyed = !0), this._destroy(t || null, function (t) { 32781 !e && t ? (n.nextTick(i, r, t), r._writableState && (r._writableState.errorEmitted = !0)) : e && e(t); 32782 }), this); 32783 }, 32784 undestroy: function () { 32785 this._readableState && (this._readableState.destroyed = !1, this._readableState.reading = !1, this._readableState.ended = !1, this._readableState.endEmitted = !1), this._writableState && (this._writableState.destroyed = !1, this._writableState.ended = !1, this._writableState.ending = !1, this._writableState.finished = !1, this._writableState.errorEmitted = !1); 32786 } 32787 }; 32788 }, function (t, e, r) { 32789 32790 var n = r(71).Buffer, 32791 i = n.isEncoding || function (t) { 32792 switch ((t = "" + t) && t.toLowerCase()) { 32793 case "hex": 32794 case "utf8": 32795 case "utf-8": 32796 case "ascii": 32797 case "binary": 32798 case "base64": 32799 case "ucs2": 32800 case "ucs-2": 32801 case "utf16le": 32802 case "utf-16le": 32803 case "raw": 32804 return !0; 32805 32806 default: 32807 return !1; 32808 } 32809 }; 32810 32811 function o(t) { 32812 var e; 32813 32814 switch (this.encoding = function (t) { 32815 var e = function (t) { 32816 if (!t) return "utf8"; 32817 32818 for (var e;;) switch (t) { 32819 case "utf8": 32820 case "utf-8": 32821 return "utf8"; 32822 32823 case "ucs2": 32824 case "ucs-2": 32825 case "utf16le": 32826 case "utf-16le": 32827 return "utf16le"; 32828 32829 case "latin1": 32830 case "binary": 32831 return "latin1"; 32832 32833 case "base64": 32834 case "ascii": 32835 case "hex": 32836 return t; 32837 32838 default: 32839 if (e) return; 32840 t = ("" + t).toLowerCase(), e = !0; 32841 } 32842 }(t); 32843 32844 if ("string" != typeof e && (n.isEncoding === i || !i(t))) throw new Error("Unknown encoding: " + t); 32845 return e || t; 32846 }(t), this.encoding) { 32847 case "utf16le": 32848 this.text = u, this.end = f, e = 4; 32849 break; 32850 32851 case "utf8": 32852 this.fillLast = s, e = 4; 32853 break; 32854 32855 case "base64": 32856 this.text = c, this.end = l, e = 3; 32857 break; 32858 32859 default: 32860 return this.write = h, void (this.end = d); 32861 } 32862 32863 this.lastNeed = 0, this.lastTotal = 0, this.lastChar = n.allocUnsafe(e); 32864 } 32865 32866 function a(t) { 32867 return t <= 127 ? 0 : t >> 5 == 6 ? 2 : t >> 4 == 14 ? 3 : t >> 3 == 30 ? 4 : t >> 6 == 2 ? -1 : -2; 32868 } 32869 32870 function s(t) { 32871 var e = this.lastTotal - this.lastNeed, 32872 r = function (t, e, r) { 32873 if (128 != (192 & e[0])) return t.lastNeed = 0, "�"; 32874 32875 if (t.lastNeed > 1 && e.length > 1) { 32876 if (128 != (192 & e[1])) return t.lastNeed = 1, "�"; 32877 if (t.lastNeed > 2 && e.length > 2 && 128 != (192 & e[2])) return t.lastNeed = 2, "�"; 32878 } 32879 }(this, t); 32880 32881 return void 0 !== r ? r : this.lastNeed <= t.length ? (t.copy(this.lastChar, e, 0, this.lastNeed), this.lastChar.toString(this.encoding, 0, this.lastTotal)) : (t.copy(this.lastChar, e, 0, t.length), void (this.lastNeed -= t.length)); 32882 } 32883 32884 function u(t, e) { 32885 if ((t.length - e) % 2 == 0) { 32886 var r = t.toString("utf16le", e); 32887 32888 if (r) { 32889 var n = r.charCodeAt(r.length - 1); 32890 if (n >= 55296 && n <= 56319) return this.lastNeed = 2, this.lastTotal = 4, this.lastChar[0] = t[t.length - 2], this.lastChar[1] = t[t.length - 1], r.slice(0, -1); 32891 } 32892 32893 return r; 32894 } 32895 32896 return this.lastNeed = 1, this.lastTotal = 2, this.lastChar[0] = t[t.length - 1], t.toString("utf16le", e, t.length - 1); 32897 } 32898 32899 function f(t) { 32900 var e = t && t.length ? this.write(t) : ""; 32901 32902 if (this.lastNeed) { 32903 var r = this.lastTotal - this.lastNeed; 32904 return e + this.lastChar.toString("utf16le", 0, r); 32905 } 32906 32907 return e; 32908 } 32909 32910 function c(t, e) { 32911 var r = (t.length - e) % 3; 32912 return 0 === r ? t.toString("base64", e) : (this.lastNeed = 3 - r, this.lastTotal = 3, 1 === r ? this.lastChar[0] = t[t.length - 1] : (this.lastChar[0] = t[t.length - 2], this.lastChar[1] = t[t.length - 1]), t.toString("base64", e, t.length - r)); 32913 } 32914 32915 function l(t) { 32916 var e = t && t.length ? this.write(t) : ""; 32917 return this.lastNeed ? e + this.lastChar.toString("base64", 0, 3 - this.lastNeed) : e; 32918 } 32919 32920 function h(t) { 32921 return t.toString(this.encoding); 32922 } 32923 32924 function d(t) { 32925 return t && t.length ? this.write(t) : ""; 32926 } 32927 32928 e.StringDecoder = o, o.prototype.write = function (t) { 32929 if (0 === t.length) return ""; 32930 var e, r; 32931 32932 if (this.lastNeed) { 32933 if (void 0 === (e = this.fillLast(t))) return ""; 32934 r = this.lastNeed, this.lastNeed = 0; 32935 } else r = 0; 32936 32937 return r < t.length ? e ? e + this.text(t, r) : this.text(t, r) : e || ""; 32938 }, o.prototype.end = function (t) { 32939 var e = t && t.length ? this.write(t) : ""; 32940 return this.lastNeed ? e + "�" : e; 32941 }, o.prototype.text = function (t, e) { 32942 var r = function (t, e, r) { 32943 var n = e.length - 1; 32944 if (n < r) return 0; 32945 var i = a(e[n]); 32946 if (i >= 0) return i > 0 && (t.lastNeed = i - 1), i; 32947 if (--n < r || -2 === i) return 0;
32948 if ((i = a(e[n])) >= 0) return i > 0 && (t.lastNeed = i - 2), i; 32949 if (--n < r || -2 === i) return 0; 32950 if ((i = a(e[n])) >= 0) return i > 0 && (2 === i ? i = 0 : t.lastNeed = i - 3), i; 32951 return 0; 32952 }(this, t, e); 32953 32954 if (!this.lastNeed) return t.toString("utf8", e); 32955 this.lastTotal = r; 32956 var n = t.length - (r - this.lastNeed); 32957 return t.copy(this.lastChar, 0, n), t.toString("utf8", e, n); 32958 }, o.prototype.fillLast = function (t) { 32959 if (this.lastNeed <= t.length) return t.copy(this.lastChar, this.lastTotal - this.lastNeed, 0, this.lastNeed), this.lastChar.toString(this.encoding, 0, this.lastTotal); 32960 t.copy(this.lastChar, this.lastTotal - this.lastNeed, 0, t.length), this.lastNeed -= t.length; 32961 }; 32962 }, function (t, e, r) { 32963 32964 t.exports = a; 32965 var n = r(39), 32966 i = r(57); 32967 32968 function o(t, e) { 32969 var r = this._transformState; 32970 r.transforming = !1; 32971 var n = r.writecb; 32972 if (!n) return this.emit("error", new Error("write callback called multiple times")); 32973 r.writechunk = null, r.writecb = null, null != e && this.push(e), n(t); 32974 var i = this._readableState; 32975 i.reading = !1, (i.needReadable || i.length < i.highWaterMark) && this._read(i.highWaterMark); 32976 } 32977 32978 function a(t) { 32979 if (!(this instanceof a)) return new a(t); 32980 n.call(this, t), this._transformState = { 32981 afterTransform: o.bind(this), 32982 needTransform: !1, 32983 transforming: !1, 32984 writecb: null, 32985 writechunk: null, 32986 writeencoding: null 32987 }, this._readableState.needReadable = !0, this._readableState.sync = !1, t && ("function" == typeof t.transform && (this._transform = t.transform), "function" == typeof t.flush && (this._flush = t.flush)), this.on("prefinish", s); 32988 } 32989 32990 function s() { 32991 var t = this; 32992 "function" == typeof this._flush ? this._flush(function (e, r) { 32993 u(t, e, r); 32994 }) : u(this, null, null); 32995 } 32996 32997 function u(t, e, r) { 32998 if (e) return t.emit("error", e); 32999 if (null != r && t.push(r), t._writableState.length) throw new Error("Calling transform done when ws.length != 0"); 33000 if (t._transformState.transforming) throw new Error("Calling transform done when still transforming"); 33001 return t.push(null); 33002 } 33003 33004 i.inherits = r(47), i.inherits(a, n), a.prototype.push = function (t, e) { 33005 return this._transformState.needTransform = !1, n.prototype.push.call(this, t, e); 33006 }, a.prototype._transform = function (t, e, r) { 33007 throw new Error("_transform() is not implemented"); 33008 }, a.prototype._write = function (t, e, r) { 33009 var n = this._transformState; 33010 33011 if (n.writecb = r, n.writechunk = t, n.writeencoding = e, !n.transforming) { 33012 var i = this._readableState; 33013 (n.needTransform || i.needReadable || i.length < i.highWaterMark) && this._read(i.highWaterMark); 33014 } 33015 }, a.prototype._read = function (t) { 33016 var e = this._transformState; 33017 null !== e.writechunk && e.writecb && !e.transforming ? (e.transforming = !0, this._transform(e.writechunk, e.writeencoding, e.afterTransform)) : e.needTransform = !0; 33018 }, a.prototype._destroy = function (t, e) { 33019 var r = this; 33020 33021 n.prototype._destroy.call(this, t, function (t) { 33022 e(t), r.emit("close"); 33023 }); 33024 }; 33025 }, function (t, e, r) { 33026 33027 (function (e) { 33028 var n = r(213); 33029 /*! 33030 * The buffer module from node.js, for the browser. 33031 * 33032 * @author Feross Aboukhadijeh <[email protected]> <http://feross.org> 33033 * @license MIT 33034 */ 33035 33036 function i(t, e) { 33037 if (t === e) return 0; 33038 33039 for (var r = t.length, n = e.length, i = 0, o = Math.min(r, n); i < o; ++i) if (t[i] !== e[i]) { 33040 r = t[i], n = e[i]; 33041 break; 33042 } 33043 33044 return r < n ? -1 : n < r ? 1 : 0; 33045 } 33046 33047 function o(t) { 33048 return e.Buffer && "function" == typeof e.Buffer.isBuffer ? e.Buffer.isBuffer(t) : !(null == t || !t._isBuffer); 33049 } 33050 33051 var a = r(133), 33052 s = Object.prototype.hasOwnProperty, 33053 u = Array.prototype.slice, 33054 f = "foo" === function () {}.name; 33055 33056 function c(t) { 33057 return Object.prototype.toString.call(t); 33058 } 33059 33060 function l(t) { 33061 return !o(t) && "function" == typeof e.ArrayBuffer && ("function" == typeof ArrayBuffer.isView ? ArrayBuffer.isView(t) : !!t && (t instanceof DataView || !!(t.buffer && t.buffer instanceof ArrayBuffer))); 33062 } 33063 33064 var h = t.exports = m, 33065 d = /\s*function\s+([^\(\s]*)\s*/; 33066 33067 function p(t) { 33068 if (a.isFunction(t)) { 33069 if (f) return t.name; 33070 var e = t.toString().match(d); 33071 return e && e[1]; 33072 } 33073 } 33074 33075 function g(t, e) { 33076 return "string" == typeof t ? t.length < e ? t : t.slice(0, e) : t; 33077 } 33078 33079 function v(t) { 33080 if (f || !a.isFunction(t)) return a.inspect(t); 33081 var e = p(t); 33082 return "[Function" + (e ? ": " + e : "") + "]"; 33083 } 33084 33085 function y(t, e, r, n, i) { 33086 throw new h.AssertionError({ 33087 message: r, 33088 actual: t, 33089 expected: e, 33090 operator: n, 33091 stackStartFunction: i 33092 }); 33093 } 33094 33095 function m(t, e) { 33096 t || y(t, !0, e, "==", h.ok); 33097 } 33098 33099 function b(t, e, r, n) { 33100 if (t === e) return !0; 33101 if (o(t) && o(e)) return 0 === i(t, e); 33102 if (a.isDate(t) && a.isDate(e)) return t.getTime() === e.getTime(); 33103 if (a.isRegExp(t) && a.isRegExp(e)) return t.source === e.source && t.global === e.global && t.multiline === e.multiline && t.lastIndex === e.lastIndex && t.ignoreCase === e.ignoreCase; 33104 33105 if (null !== t && "object" == typeof t || null !== e && "object" == typeof e) { 33106 if (l(t) && l(e) && c(t) === c(e) && !(t instanceof Float32Array || t instanceof Float64Array)) return 0 === i(new Uint8Array(t.buffer), new Uint8Array(e.buffer)); 33107 if (o(t) !== o(e)) return !1; 33108 var s = (n = n || { 33109 actual: [], 33110 expected: [] 33111 }).actual.indexOf(t); 33112 return -1 !== s && s === n.expected.indexOf(e) || (n.actual.push(t), n.expected.push(e), function (t, e, r, n) { 33113 if (null == t || null == e) return !1; 33114 if (a.isPrimitive(t) || a.isPrimitive(e)) return t === e; 33115 if (r && Object.getPrototypeOf(t) !== Object.getPrototypeOf(e)) return !1; 33116 33117 var i = _(t), 33118 o = _(e); 33119 33120 if (i && !o || !i && o) return !1; 33121 if (i) return t = u.call(t), e = u.call(e), b(t, e, r); 33122 var s, 33123 f, 33124 c = E(t), 33125 l = E(e); 33126 if (c.length !== l.length) return !1; 33127 33128 for (c.sort(), l.sort(), f = c.length - 1; f >= 0;
33128 f--) if (c[f] !== l[f]) return !1; 33129 33130 for (f = c.length - 1; f >= 0; f--) if (s = c[f], !b(t[s], e[s], r, n)) return !1; 33131 33132 return !0; 33133 }(t, e, r, n)); 33134 } 33135 33136 return r ? t === e : t == e; 33137 } 33138 33139 function _(t) { 33140 return "[object Arguments]" == Object.prototype.toString.call(t); 33141 } 33142 33143 function w(t, e) { 33144 if (!t || !e) return !1; 33145 if ("[object RegExp]" == Object.prototype.toString.call(e)) return e.test(t); 33146 33147 try { 33148 if (t instanceof e) return !0; 33149 } catch (t) {} 33150 33151 return !Error.isPrototypeOf(e) && !0 === e.call({}, t); 33152 } 33153 33154 function x(t, e, r, n) { 33155 var i; 33156 if ("function" != typeof e) throw new TypeError('"block" argument must be a function'); 33157 "string" == typeof r && (n = r, r = null), i = function (t) { 33158 var e; 33159 33160 try { 33161 t(); 33162 } catch (t) { 33163 e = t; 33164 } 33165 33166 return e; 33167 }(e), n = (r && r.name ? " (" + r.name + ")." : ".") + (n ? " " + n : "."), t && !i && y(i, r, "Missing expected exception" + n); 33168 var o = "string" == typeof n, 33169 s = !t && i && !r; 33170 if ((!t && a.isError(i) && o && w(i, r) || s) && y(i, r, "Got unwanted exception" + n), t && i && r && !w(i, r) || !t && i) throw i; 33171 } 33172 33173 h.AssertionError = function (t) { 33174 this.name = "AssertionError", this.actual = t.actual, this.expected = t.expected, this.operator = t.operator, t.message ? (this.message = t.message, this.generatedMessage = !1) : (this.message = function (t) { 33175 return g(v(t.actual), 128) + " " + t.operator + " " + g(v(t.expected), 128); 33176 }(this), this.generatedMessage = !0); 33177 var e = t.stackStartFunction || y; 33178 if (Error.captureStackTrace) Error.captureStackTrace(this, e);else { 33179 var r = new Error(); 33180 33181 if (r.stack) { 33182 var n = r.stack, 33183 i = p(e), 33184 o = n.indexOf("\n" + i); 33185 33186 if (o >= 0) { 33187 var a = n.indexOf("\n", o + 1); 33188 n = n.substring(a + 1); 33189 } 33190 33191 this.stack = n; 33192 } 33193 } 33194 }, a.inherits(h.AssertionError, Error), h.fail = y, h.ok = m, h.equal = function (t, e, r) { 33195 t != e && y(t, e, r, "==", h.equal); 33196 }, h.notEqual = function (t, e, r) { 33197 t == e && y(t, e, r, "!=", h.notEqual); 33198 }, h.deepEqual = function (t, e, r) { 33199 b(t, e, !1) || y(t, e, r, "deepEqual", h.deepEqual); 33200 }, h.deepStrictEqual = function (t, e, r) { 33201 b(t, e, !0) || y(t, e, r, "deepStrictEqual", h.deepStrictEqual); 33202 }, h.notDeepEqual = function (t, e, r) { 33203 b(t, e, !1) && y(t, e, r, "notDeepEqual", h.notDeepEqual); 33204 }, h.notDeepStrictEqual = function t(e, r, n) { 33205 b(e, r, !0) && y(e, r, n, "notDeepStrictEqual", t); 33206 }, h.strictEqual = function (t, e, r) { 33207 t !== e && y(t, e, r, "===", h.strictEqual); 33208 }, h.notStrictEqual = function (t, e, r) { 33209 t === e && y(t, e, r, "!==", h.notStrictEqual); 33210 }, h.throws = function (t, e, r) { 33211 x(!0, t, e, r); 33212 }, h.doesNotThrow = function (t, e, r) { 33213 x(!1, t, e, r); 33214 }, h.ifError = function (t) { 33215 if (t) throw t; 33216 }, h.strict = n(function t(e, r) { 33217 e || y(e, !0, r, "==", t); 33218 }, h, { 33219 equal: h.strictEqual, 33220 deepEqual: h.deepStrictEqual, 33221 notEqual: h.notStrictEqual, 33222 notDeepEqual: h.notDeepStrictEqual 33223 }), h.strict.strict = h.strict; 33224 33225 var E = Object.keys || function (t) { 33226 var e = []; 33227 33228 for (var r in t) s.call(t, r) && e.push(r); 33229 33230 return e; 33231 }; 33232 }).call(this, r(23)); 33233 }, function (t, e, r) { 33234 (function (t) { 33235 var n = Object.getOwnPropertyDescriptors || function (t) { 33236 for (var e = Object.keys(t), r = {}, n = 0; n < e.length; n++) r[e[n]] = Object.getOwnPropertyDescriptor(t, e[n]); 33237 33238 return r; 33239 }, 33240 i = /%[sdj%]/g; 33241 33242 e.format = function (t) { 33243 if (!y(t)) { 33244 for (var e = [], r = 0; r < arguments.length; r++) e.push(s(arguments[r])); 33245 33246 return e.join(" "); 33247 } 33248 33249 r = 1; 33250 33251 for (var n = arguments, o = n.length, a = String(t).replace(i, function (t) { 33252 if ("%%" === t) return "%"; 33253 if (r >= o) return t; 33254 33255 switch (t) { 33256 case "%s": 33257 return String(n[r++]); 33258 33259 case "%d": 33260 return Number(n[r++]); 33261 33262 case "%j": 33263 try { 33264 return JSON.stringify(n[r++]); 33265 } catch (t) { 33266 return "[Circular]"; 33267 } 33268 33269 default: 33270 return t; 33271 } 33272 }), u = n[r]; r < o; u = n[++r]) g(u) || !_(u) ? a += " " + u : a += " " + s(u); 33273 33274 return a; 33275 }, e.deprecate = function (r, n) { 33276 if (void 0 !== t && !0 === t.noDeprecation) return r; 33277 if (void 0 === t) return function () { 33278 return e.deprecate(r, n).apply(this, arguments); 33279 }; 33280 var i = !1; 33281 return function () { 33282 if (!i) { 33283 if (t.throwDeprecation) throw new Error(n);
vendor: 4,125 bytes, lines 33284-33382
33284 t.traceDeprecation ? console.trace(n) : console.error(n), i = !0; 33285 } 33286 33287 return r.apply(this, arguments); 33288 }; 33289 }; 33290 var o, 33291 a = {}; 33292 33293 function s(t, r) { 33294 var n = { 33295 seen: [], 33296 stylize: f 33297 }; 33298 return arguments.length >= 3 && (n.depth = arguments[2]), arguments.length >= 4 && (n.colors = arguments[3]), p(r) ? n.showHidden = r : r && e._extend(n, r), m(n.showHidden) && (n.showHidden = !1), m(n.depth) && (n.depth = 2), m(n.colors) && (n.colors = !1), m(n.customInspect) && (n.customInspect = !0), n.colors && (n.stylize = u), c(n, t, n.depth); 33299 } 33300 33301 function u(t, e) { 33302 var r = s.styles[e]; 33303 return r ? "�[" + s.colors[r][0] + "m" + t + "�[" + s.colors[r][1] + "m" : t; 33304 } 33305 33306 function f(t, e) { 33307 return t; 33308 } 33309 33310 function c(t, r, n) { 33311 if (t.customInspect && r && E(r.inspect) && r.inspect !== e.inspect && (!r.constructor || r.constructor.prototype !== r)) { 33312 var i = r.inspect(n, t); 33313 return y(i) || (i = c(t, i, n)), i; 33314 } 33315 33316 var o = function (t, e) { 33317 if (m(e)) return t.stylize("undefined", "undefined"); 33318 33319 if (y(e)) { 33320 var r = "'" + JSON.stringify(e).replace(/^"|"$/g, "").replace(/'/g, "\\'").replace(/\\"/g, '"') + "'"; 33321 return t.stylize(r, "string"); 33322 } 33323 33324 if (v(e)) return t.stylize("" + e, "number"); 33325 if (p(e)) return t.stylize("" + e, "boolean"); 33326 if (g(e)) return t.stylize("null", "null"); 33327 }(t, r); 33328 33329 if (o) return o; 33330 33331 var a = Object.keys(r), 33332 s = function (t) { 33333 var e = {}; 33334 return t.forEach(function (t, r) { 33335 e[t] = !0; 33336 }), e; 33337 }(a); 33338 33339 if (t.showHidden && (a = Object.getOwnPropertyNames(r)), x(r) && (a.indexOf("message") >= 0 || a.indexOf("description") >= 0)) return l(r); 33340 33341 if (0 === a.length) { 33342 if (E(r)) { 33343 var u = r.name ? ": " + r.name : ""; 33344 return t.stylize("[Function" + u + "]", "special"); 33345 } 33346 33347 if (b(r)) return t.stylize(RegExp.prototype.toString.call(r), "regexp"); 33348 if (w(r)) return t.stylize(Date.prototype.toString.call(r), "date"); 33349 if (x(r)) return l(r); 33350 } 33351 33352 var f, 33353 _ = "", 33354 S = !1, 33355 k = ["{", "}"]; 33356 (d(r) && (S = !0, k = ["[", "]"]), E(r)) && (_ = " [Function" + (r.name ? ": " + r.name : "") + "]"); 33357 return b(r) && (_ = " " + RegExp.prototype.toString.call(r)), w(r) && (_ = " " + Date.prototype.toUTCString.call(r)), x(r) && (_ = " " + l(r)), 0 !== a.length || S && 0 != r.length ? n < 0 ? b(r) ? t.stylize(RegExp.prototype.toString.call(r), "regexp") : t.stylize("[Object]", "special") : (t.seen.push(r), f = S ? function (t, e, r, n, i) { 33358 for (var o = [], a = 0, s = e.length; a < s; ++a) T(e, String(a)) ? o.push(h(t, e, r, n, String(a), !0)) : o.push(""); 33359 33360 return i.forEach(function (i) { 33361 i.match(/^\d+$/) || o.push(h(t, e, r, n, i, !0)); 33362 }), o; 33363 }(t, r, n, s, a) : a.map(function (e) { 33364 return h(t, r, n, s, e, S); 33365 }), t.seen.pop(), function (t, e, r) { 33366 if (t.reduce(function (t, e) { 33367 return e.indexOf("\n") >= 0 && 0, t + e.replace(/\u001b\[\d\d?m/g, "").length + 1; 33368 }, 0) > 60) return r[0] + ("" === e ? "" : e + "\n ") + " " + t.join(",\n ") + " " + r[1]; 33369 return r[0] + e + " " + t.join(", ") + " " + r[1]; 33370 }(f, _, k)) : k[0] + _ + k[1]; 33371 } 33372 33373 function l(t) { 33374 return "[" + Error.prototype.toString.call(t) + "]"; 33375 } 33376 33377 function h(t, e, r, n, i, o) { 33378 var a, s, u; 33379 33380 if ((u = Object.getOwnPropertyDescriptor(e, i) || { 33381 value: e[i] 33382 }).get ? s = u.set ? t.stylize("[Getter/Setter]", "special") : t.stylize("[Getter]", "special") : u.set && (s = t.stylize("[
33382Setter]", "special")), T(n, i) || (a = "[" + i + "]"), s || (t.seen.indexOf(u.value) < 0 ? (s = g(r) ? c(t, u.value, null) : c(t, u.value, r - 1)).indexOf("\n") > -1 && (s = o ? s.split("\n").map(function (t) { 33383 return " " + t; 33384 }).join("\n").substr(2) : "\n" + s.split("\n").map(function (t) { 33385 return " " + t; 33386 }).join("\n")) : s = t.stylize("[Circular]", "special")), m(a)) { 33387 if (o && i.match(/^\d+$/)) return s; 33388 (a = JSON.stringify("" + i)).match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/) ? (a = a.substr(1, a.length - 2), a = t.stylize(a, "name")) : (a = a.replace(/'/g, "\\'").replace(/\\"/g, '"').replace(/(^"|"$)/g, "'"), a = t.stylize(a, "string")); 33389 } 33390 33391 return a + ": " + s; 33392 } 33393 33394 function d(t) { 33395 return Array.isArray(t); 33396 } 33397 33398 function p(t) { 33399 return "boolean" == typeof t; 33400 } 33401 33402 function g(t) { 33403 return null === t; 33404 } 33405 33406 function v(t) { 33407 return "number" == typeof t; 33408 } 33409 33410 function y(t) { 33411 return "string" == typeof t; 33412 } 33413 33414 function m(t) { 33415 return void 0 === t; 33416 } 33417 33418 function b(t) { 33419 return _(t) && "[object RegExp]" === S(t); 33420 } 33421 33422 function _(t) { 33423 return "object" == typeof t && null !== t; 33424 } 33425 33426 function w(t) { 33427 return _(t) && "[object Date]" === S(t); 33428 } 33429 33430 function x(t) { 33431 return _(t) && ("[object Error]" === S(t) || t instanceof Error); 33432 } 33433 33434 function E(t) { 33435 return "function" == typeof t; 33436 } 33437 33438 function S(t) { 33439 return Object.prototype.toString.call(t); 33440 } 33441 33442 function k(t) { 33443 return t < 10 ? "0" + t.toString(10) : t.toString(10); 33444 } 33445 33446 e.debuglog = function (r) { 33447 if (m(o) && (o = t.env.NODE_DEBUG || ""), r = r.toUpperCase(), !a[r]) if (new RegExp("\\b" + r + "\\b", "i").test(o)) { 33448 var n = t.pid; 33449 33450 a[r] = function () { 33451 var t = e.format.apply(e, arguments); 33452 console.error("%s %d: %s", r, n, t); 33453 }; 33454 } else a[r] = function () {}; 33455 return a[r]; 33456 }, e.inspect = s, s.colors = { 33457 bold: [1, 22], 33458 italic: [3, 23], 33459 underline: [4, 24], 33460 inverse: [7, 27], 33461 white: [37, 39], 33462 grey: [90, 39], 33463 black: [30, 39], 33464 blue: [34, 39], 33465 cyan: [36, 39], 33466 green: [32, 39], 33467 magenta: [35, 39], 33468 red: [31, 39], 33469 yellow: [33, 39] 33470 }, s.styles = { 33471 special: "cyan", 33472 number: "yellow", 33473 boolean: "yellow", 33474 undefined: "grey", 33475 null: "bold", 33476 string: "green", 33477 date: "magenta", 33478 regexp: "red" 33479 }, e.isArray = d, e.isBoolean = p, e.isNull = g, e.isNullOrUndefined = function (t) { 33480 return null == t; 33481 }, e.isNumber = v, e.isString = y, e.isSymbol = function (t) { 33482 return "symbol" == typeof t; 33483 }, e.isUndefined = m, e.isRegExp = b, e.isObject = _, e.isDate = w, e.isError = x, e.isFunction = E, e.isPrimitive = function (t) { 33484 return null === t || "boolean" == typeof t || "number" == typeof t || "string" == typeof t || "symbol" == typeof t || void 0 === t; 33485 }, e.isBuffer = r(214); 33486 var A = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; 33487 33488 function C() { 33489 var t = new Date(), 33490 e = [k(t.getHours()), k(t.getMinutes()), k(t.getSeconds())].join(":"); 33491 return [t.getDate(), A[t.getMonth()], e].join(" "); 33492 } 33493 33494 function T(t, e) { 33495 return Object.prototype.hasOwnProperty.call(t, e); 33496 } 33497 33498 e.log = function () { 33499 console.log("%s - %s", C(), e.format.apply(e, arguments)); 33500 }, e.inherits = r(215), e._extend = function (t, e) { 33501 if (!e || !_(e)) return t; 33502 33503 for (var r = Object.keys(e), n = r.length; n--;) t[r[n]] = e[r[n]]; 33504 33505 return t; 33506 }; 33507 var R = "undefined" != typeof Symbol ? Symbol("util.promisify.custom") : void 0; 33508 33509 function O(t, e) { 33510 if (!t) { 33511 var r = new Error("Promise was rejected with a falsy value"); 33512 r.reason = t, t = r; 33513 } 33514 33515 return e(t); 33516 } 33517 33518 e.promisify = function (t) { 33519 if ("function" != typeof t) throw new TypeError('The "original" argument must be of type Function'); 33520 33521 if (R && t[R]) { 33522 var e; 33523 if ("function" != typeof (e = t[R])) throw new TypeError('The "util.promisify.custom" argument must be of type Function'); 33524 return Object.defineProperty(e, R, { 33525 value: e, 33526 enumerable: !1, 33527 writable: !1, 33528 configurable: !0 33529 }), e; 33530 } 33531 33532 function e() { 33533 for (var e, r, n = new Promise(function (t, n) { 33534 e = t, r = n; 33535 }), i = [], o = 0; o < arguments.length; o++) i.push(arguments[o]); 33536 33537 i.push(function (t, n) { 33538 t ? r(t) : e(n); 33539 }); 33540 33541 try { 33542 t.apply(this, i); 33543 } catch (t) { 33544 r(t); 33545 } 33546 33547 return n; 33548 } 33549 33550 return Object.setPrototypeOf(e, Object.getPrototypeOf(t)), R && Object.defineProperty(e, R, { 33551 value: e, 33552 enumerable: !1, 33553 writable: !1, 33554 configurable: !0 33555 }), Object.defineProperties(e, n(t)); 33556 }, e.promisify.custom = R, e.callbackify = function (e) { 33557 if ("function" != typeof e) throw new TypeError('The "original" argument must be of type Function'); 33558 33559 function r() { 33560 for (var r = [], n = 0; n < arguments.length;
33560 n++) r.push(arguments[n]); 33561 33562 var i = r.pop(); 33563 if ("function" != typeof i) throw new TypeError("The last argument must be of type Function"); 33564 33565 var o = this, 33566 a = function () { 33567 return i.apply(o, arguments); 33568 }; 33569 33570 e.apply(this, r).then(function (e) { 33571 t.nextTick(a, null, e); 33572 }, function (e) { 33573 t.nextTick(O, e, a); 33574 }); 33575 } 33576 33577 return Object.setPrototypeOf(r, Object.getPrototypeOf(e)), Object.defineProperties(r, n(e)), r; 33578 }; 33579 }).call(this, r(38)); 33580 }, function (t, e, r) { 33581 33582 t.exports = function (t, e, r, n) { 33583 for (var i = 65535 & t | 0, o = t >>> 16 & 65535 | 0, a = 0; 0 !== r;) { 33584 r -= a = r > 2e3 ? 2e3 : r; 33585 33586 do { 33587 o = o + (i = i + e[n++] | 0) | 0; 33588 } while (--a); 33589 33590 i %= 65521, o %= 65521; 33591 } 33592 33593 return i | o << 16 | 0; 33594 }; 33595 }, function (t, e, r) { 33596 33597 var n = function () { 33598 for (var t, e = [], r = 0; r < 256; r++) { 33599 t = r; 33600 33601 for (var n = 0; n < 8; n++) t = 1 & t ? 3988292384 ^ t >>> 1 : t >>> 1; 33602 33603 e[r] = t; 33604 } 33605 33606 return e; 33607 }(); 33608 33609 t.exports = function (t, e, r, i) { 33610 var o = n, 33611 a = i + r; 33612 t ^= -1; 33613 33614 for (var s = i; s < a; s++) t = t >>> 8 ^ o[255 & (t ^ e[s])]; 33615 33616 return -1 ^ t; 33617 }; 33618 }, function (t, e, r) { 33619 r(11)("iterator"); 33620 }, function (t, e, r) { 33621 var n = r(111), 33622 i = r(85).concat("length", "prototype"); 33623 33624 e.f = Object.getOwnPropertyNames || function (t) { 33625 return n(t, i); 33626 }; 33627 }, function (t, e) { 33628 e.f = Object.getOwnPropertySymbols; 33629 }, function (t, e, r) { 33630 t.exports = r(259); 33631 }, function (t, e, r) { 33632 t.exports = r(262); 33633 }, function (t, e, r) { 33634 var n = r(50), 33635 i = r(14), 33636 o = r(24), 33637 a = r(21).f, 33638 s = r(64), 33639 u = r(271), 33640 f = s("meta"), 33641 c = 0, 33642 l = Object.isExtensible || function () { 33643 return !0; 33644 }, 33645 h = function (t) { 33646 a(t, f, { 33647 value: { 33648 objectID: "O" + ++c, 33649 weakData: {} 33650 } 33651 }); 33652 }, 33653 d = t.exports = { 33654 REQUIRED: !1, 33655 fastKey: function (t, e) { 33656 if (!i(t)) return "symbol" == typeof t ? t : ("string" == typeof t ? "S" : "P") + t; 33657 33658 if (!o(t, f)) { 33659 if (!l(t)) return "F"; 33660 if (!e) return "E"; 33661 h(t); 33662 } 33663 33664 return t[f].objectID; 33665 }, 33666 getWeakData: function (t, e) { 33667 if (!o(t, f)) { 33668 if (!l(t)) return !0; 33669 if (!e) return !1; 33670 h(t); 33671 } 33672 33673 return t[f].weakData; 33674 }, 33675 onFreeze: function (t) { 33676 return u && d.REQUIRED && l(t) && !o(t, f) && h(t), t; 33677 } 33678 }; 33679 33680 n[f] = !0; 33681 }, function (t, e, r) { 33682 var n = r(2), 33683 i = r(90); 33684 33685 t.exports = function (t) { 33686 var e = i(t); 33687 if ("function" != typeof e) throw TypeError(String(t) + " is not iterable"); 33688 return n(e.call(t)); 33689 }; 33690 }, function (t, e, r) { 33691 var n = r(298), 33692 i = Array.prototype; 33693 33694 t.exports = function (t) { 33695 var e = t.indexOf; 33696 return t === i || t instanceof Array && e === i.indexOf ? n : e; 33697 }; 33698 }, function (t, e, r) { 33699 var n = r(303), 33700 i = Function.prototype; 33701 33702 t.exports = function (t) { 33703 var e = t.bind; 33704 return t === i || t instanceof Function && e === i.bind ? n : e; 33705 }; 33706 }, function (t, e, r) { 33707 33708 var n = r(5), 33709 i = r(14), 33710 o = [].slice, 33711 a = {}, 33712 s = function (t, e, r) { 33713 if (!(e in a)) { 33714 for (var n = [], i = 0; i < e; i++) n[i] = "a[" + i + "]"; 33715 33716 a[e] = Function("C,a", "return new C(" + n.join(",") + ")"); 33717 } 33718 33719 return a[e](t, r); 33720 }; 33721 33722 t.exports = Function.bind || function (t) { 33723 var e = n(this), 33724 r = o.call(arguments, 1), 33725 a = function () { 33726 var n = r.concat(o.call(arguments)); 33727 return this instanceof a ? s(e, n.length, n) : e.apply(t, n); 33728 }; 33729 33730 return i(e.prototype) && (a.prototype = e.prototype), a; 33731 }; 33732 }, function (t, e) { 33733 t.exports = n; 33734 var r = null; 33735
33736 try { 33737 r = new WebAssembly.Instance(new WebAssembly.Module(new Uint8Array([0, 97, 115, 109, 1, 0, 0, 0, 1, 13, 2, 96, 0, 1, 127, 96, 4, 127, 127, 127, 127, 1, 127, 3, 7, 6, 0, 1, 1, 1, 1, 1, 6, 6, 1, 127, 1, 65, 0, 11, 7, 50, 6, 3, 109, 117, 108, 0, 1, 5, 100, 105, 118, 95, 115, 0, 2, 5, 100, 105, 118, 95, 117, 0, 3, 5, 114, 101, 109, 95, 115, 0, 4, 5, 114, 101, 109, 95, 117, 0, 5, 8, 103, 101, 116, 95, 104, 105, 103, 104, 0, 0, 10, 191, 1, 6, 4, 0, 35, 0, 11, 36, 1, 1, 126, 32, 0, 173, 32, 1, 173, 66, 32, 134, 132, 32, 2, 173, 32, 3, 173, 66, 32, 134, 132, 126, 34, 4, 66, 32, 135, 167, 36, 0, 32, 4, 167, 11, 36, 1, 1, 126, 32, 0, 173, 32, 1, 173, 66, 32, 134, 132, 32, 2, 173, 32, 3, 173, 66, 32, 134, 132, 127, 34, 4, 66, 32, 135, 167, 36, 0, 32, 4, 167, 11, 36, 1, 1, 126, 32, 0, 173, 32, 1, 173, 66, 32, 134, 132, 32, 2, 173, 32, 3, 173, 66, 32, 134, 132, 128, 34, 4, 66, 32, 135, 167, 36, 0, 32, 4, 167, 11, 36, 1, 1, 126, 32, 0, 173, 32, 1, 173, 66, 32, 134, 132, 32, 2, 173, 32, 3, 173, 66, 32, 134, 132, 129, 34, 4, 66, 32, 135, 167, 36, 0, 32, 4, 167, 11, 36, 1, 1, 126, 32, 0, 173, 32, 1, 173, 66, 32, 134, 132, 32, 2, 173, 32, 3, 173, 66, 32, 134, 132, 130, 34, 4, 66, 32, 135, 167, 36, 0, 32, 4, 167, 11])), {}).exports; 33738 } catch (t) {} 33739 33740 function n(t, e, r) { 33741 this.low = 0 | t, this.high = 0 | e, this.unsigned = !!r; 33742 } 33743 33744 function i(t) { 33745 return !0 === (t && t.__isLong__); 33746 } 33747 33748 n.prototype.__isLong__, Object.defineProperty(n.prototype, "__isLong__", { 33749 value: !0 33750 }), n.isLong = i; 33751 var o = {}, 33752 a = {}; 33753 33754 function s(t, e) { 33755 var r, n, i; 33756 return e ? (i = 0 <= (t >>>= 0) && t < 256) && (n = a[t]) ? n : (r = f(t, (0 | t) < 0 ? -1 : 0, !0), i && (a[t] = r), r) : (i = -128 <= (t |= 0) && t < 128) && (n = o[t]) ? n : (r = f(t, t < 0 ? -1 : 0, !1), i && (o[t] = r), r); 33757 } 33758 33759 function u(t, e) { 33760 if (isNaN(t)) return e ? m : y; 33761 33762 if (e) { 33763 if (t < 0) return m; 33764 if (t >= p) return E; 33765 } else { 33766 if (t <= -g) return S; 33767 if (t + 1 >= g) return x; 33768 } 33769 33770 return t < 0 ? u(-t, e).neg() : f(t % d | 0, t / d | 0, e); 33771 } 33772 33773 function f(t, e, r) { 33774 return new n(t, e, r); 33775 } 33776 33777 n.fromInt = s, n.fromNumber = u, n.fromBits = f; 33778 var c = Math.pow; 33779 33780 function l(t, e, r) { 33781 if (0 === t.length) throw Error("empty string"); 33782 if ("NaN" === t || "Infinity" === t || "+Infinity" === t || "-Infinity" === t) return y; 33783 if ("number" == typeof e ? (r = e, e = !1) : e = !!e, (r = r || 10) < 2 || 36 < r) throw RangeError("radix"); 33784 var n; 33785 if ((n = t.indexOf("-")) > 0) throw Error("interior hyphen"); 33786 if (0 === n) return l(t.substring(1), e, r).neg(); 33787 33788 for (var i = u(c(r, 8)), o = y, a = 0; a < t.length; a += 8) { 33789 var s = Math.min(8, t.length - a), 33790 f = parseInt(t.substring(a, a + s), r); 33791 33792 if (s < 8) { 33793 var h = u(c(r, s)); 33794 o = o.mul(h).add(u(f)); 33795 } else o = (o = o.mul(i)).add(u(f)); 33796 } 33797 33798 return o.unsigned = e, o; 33799 } 33800 33801 function h(t, e) { 33802 return "number" == typeof t ? u(t, e) : "string" == typeof t ? l(t, e) : f(t.low, t.high, "boolean" == typeof e ? e : t.unsigned); 33803 } 33804 33805 n.fromString = l, n.fromValue = h; 33806 var d = 4294967296, 33807 p = d * d, 33808 g = p / 2, 33809 v = s(1 << 24), 33810 y = s(0); 33811 n.ZERO = y; 33812 var m = s(0, !0); 33813 n.UZERO = m; 33814 var b = s(1); 33815 n.ONE = b; 33816 33817 var _ = s(1, !0); 33818 33819 n.UONE = _; 33820 var w = s(-1); 33821 n.NEG_ONE = w; 33822 var x = f(-1, 2147483647, !1); 33823 n.MAX_VALUE = x; 33824 var E = f(-1, -1, !0); 33825 n.MAX_UNSIGNED_VALUE = E; 33826 var S = f(0, -2147483648, !1); 33827 n.MIN_VALUE = S; 33828 var k = n.prototype; 33829 k.toInt = function () { 33830 return this.unsigned ? this.low >>> 0 : this.low; 33831 }, k.toNumber = function () { 33832 return this.unsigned ? (this.high >>> 0) * d + (this.low >>> 0) : this.high * d + (this.low >>> 0); 33833 }, k.toString = function (t) { 33834 if ((t = t || 10) < 2 || 36 < t) throw RangeError("radix"); 33835 if (this.isZero()) return "0"; 33836 33837 if (this.isNegative()) { 33838 if (this.eq(S)) { 33839 var e = u(t), 33840 r = this.div(e), 33841 n = r.mul(e).sub(this); 33842 return r.toString(t) + n.toInt().toString(t); 33843 } 33844 33845 return "-" + this.neg().toString(t); 33846 } 33847 33848 for (var i = u(c(t, 6), this.unsigned), o = this, a = "";;) { 33849 var s = o.div(i), 33850 f = (o.sub(s.mul(i)).toInt() >>> 0).toString(t); 33851 if ((o = s).isZero()) return f + a; 33852 33853 for (; f.length < 6;) f = "0" + f; 33854 33855 a = "" + f + a; 33856 } 33857 }, k.getHighBits = function () { 33858 return this.high; 33859 }, k.getHighBitsUnsigned = function () { 33860 return this.high >>> 0; 33861 }, k.getLowBits = function () { 33862 return this.low; 33863 }, k.getLowBitsUnsigned = function () { 33864 return this.low >>> 0; 33865 }, k.getNumBitsAbs = function () { 33866 if (this.isNegative()) return this.eq(S) ? 64 : this.neg().getNumBitsAbs(); 33867 33868 for (var t = 0 != this.high ? this.high : this.low, e = 31; e > 0 && 0 == (t & 1 << e); e--); 33869 33870 return 0 != this.high ? e + 33 : e + 1; 33871 }, k.isZero = function () { 33872 return 0 === this.high && 0 === this.low; 33873 }, k.eqz = k.isZero, k.isNegative = function () { 33874 return !this.unsigned && this.high < 0; 33875 }, k.isPositive = function () { 33876 return this.unsigned || this.high >= 0; 33877 }, k.isOdd = function () { 33878 return 1 == (1 & this.low); 33879 }, k.isEven = function () { 33880 return 0 == (1 & this.low); 33881 }, k.equals = function (t) { 33882 return i(t) || (t = h(t)), (this.unsigned === t.unsigned || this.high >>> 31 != 1 || t.high >>> 31 != 1) && this.high === t.high && this.low === t.low; 33883 }, k.eq = k.equals, k.notEquals = function (t) { 33884 return !this.eq(t); 33885 }
33885, k.neq = k.notEquals, k.ne = k.notEquals, k.lessThan = function (t) { 33886 return this.comp(t) < 0; 33887 }, k.lt = k.lessThan, k.lessThanOrEqual = function (t) { 33888 return this.comp(t) <= 0; 33889 }, k.lte = k.lessThanOrEqual, k.le = k.lessThanOrEqual, k.greaterThan = function (t) { 33890 return this.comp(t) > 0; 33891 }, k.gt = k.greaterThan, k.greaterThanOrEqual = function (t) { 33892 return this.comp(t) >= 0; 33893 }, k.gte = k.greaterThanOrEqual, k.ge = k.greaterThanOrEqual, k.compare = function (t) { 33894 if (i(t) || (t = h(t)), this.eq(t)) return 0; 33895 var e = this.isNegative(), 33896 r = t.isNegative(); 33897 return e && !r ? -1 : !e && r ? 1 : this.unsigned ? t.high >>> 0 > this.high >>> 0 || t.high === this.high && t.low >>> 0 > this.low >>> 0 ? -1 : 1 : this.sub(t).isNegative() ? -1 : 1; 33898 }, k.comp = k.compare, k.negate = function () { 33899 return !this.unsigned && this.eq(S) ? S : this.not().add(b); 33900 }, k.neg = k.negate, k.add = function (t) { 33901 i(t) || (t = h(t)); 33902 var e = this.high >>> 16, 33903 r = 65535 & this.high, 33904 n = this.low >>> 16, 33905 o = 65535 & this.low, 33906 a = t.high >>> 16, 33907 s = 65535 & t.high, 33908 u = t.low >>> 16, 33909 c = 0, 33910 l = 0, 33911 d = 0, 33912 p = 0; 33913 return d += (p += o + (65535 & t.low)) >>> 16, l += (d += n + u) >>> 16, c += (l += r + s) >>> 16, c += e + a, f((d &= 65535) << 16 | (p &= 65535), (c &= 65535) << 16 | (l &= 65535), this.unsigned); 33914 }, k.subtract = function (t) { 33915 return i(t) || (t = h(t)), this.add(t.neg()); 33916 }, k.sub = k.subtract, k.multiply = function (t) { 33917 if (this.isZero()) return y; 33918 if (i(t) || (t = h(t)), r) return f(r.mul(this.low, this.high, t.low, t.high), r.get_high(), this.unsigned); 33919 if (t.isZero()) return y; 33920 if (this.eq(S)) return t.isOdd() ? S : y; 33921 if (t.eq(S)) return this.isOdd() ? S : y; 33922 if (this.isNegative()) return t.isNegative() ? this.neg().mul(t.neg()) : this.neg().mul(t).neg(); 33923 if (t.isNegative()) return this.mul(t.neg()).neg(); 33924 if (this.lt(v) && t.lt(v)) return u(this.toNumber() * t.toNumber(), this.unsigned); 33925 var e = this.high >>> 16, 33926 n = 65535 & this.high, 33927 o = this.low >>> 16, 33928 a = 65535 & this.low, 33929 s = t.high >>> 16, 33930 c = 65535 & t.high, 33931 l = t.low >>> 16, 33932 d = 65535 & t.low, 33933 p = 0, 33934 g = 0, 33935 m = 0, 33936 b = 0; 33937 return m += (b += a * d) >>> 16, g += (m += o * d) >>> 16, m &= 65535, g += (m += a * l) >>> 16, p += (g += n * d) >>> 16, g &= 65535, p += (g += o * l) >>> 16, g &= 65535, p += (g += a * c) >>> 16, p += e * d + n * l + o * c + a * s, f((m &= 65535) << 16 | (b &= 65535), (p &= 65535) << 16 | (g &= 65535), this.unsigned); 33938 }, k.mul = k.multiply, k.divide = function (t) { 33939 if (i(t) || (t = h(t)), t.isZero()) throw Error("division by zero"); 33940 var e, n, o; 33941 if (r) return this.unsigned || -2147483648 !== this.high || -1 !== t.low || -1 !== t.high ? f((this.unsigned ? r.div_u : r.div_s)(this.low, this.high, t.low, t.high), r.get_high(), this.unsigned) : this; 33942 if (this.isZero()) return this.unsigned ? m : y; 33943 33944 if (this.unsigned) { 33945 if (t.unsigned || (t = t.toUnsigned()), t.gt(this)) return m; 33946 if (t.gt(this.shru(1))) return _; 33947 o = m; 33948 } else { 33949 if (this.eq(S)) return t.eq(b) || t.eq(w) ? S : t.eq(S) ? b : (e = this.shr(1).div(t).shl(1)).eq(y) ? t.isNegative() ? b : w : (n = this.sub(t.mul(e)), o = e.add(n.div(t))); 33950 if (t.eq(S)) return this.unsigned ? m : y; 33951 if (this.isNegative()) return t.isNegative() ? this.neg().div(t.neg()) : this.neg().div(t).neg(); 33952 if (t.isNegative()) return this.div(t.neg()).neg(); 33953 o = y; 33954 } 33955 33956 for (n = this; n.gte(t);) { 33957 e = Math.max(1, Math.floor(n.toNumber() / t.toNumber())); 33958 33959 for (var a = Math.ceil(Math.log(e) / Math.LN2), s = a <= 48 ? 1 : c(2, a - 48), l = u(e), d = l.mul(t); d.isNegative() || d.gt(n);
33959) d = (l = u(e -= s, this.unsigned)).mul(t); 33960 33961 l.isZero() && (l = b), o = o.add(l), n = n.sub(d); 33962 } 33963 33964 return o; 33965 }, k.div = k.divide, k.modulo = function (t) { 33966 return i(t) || (t = h(t)), r ? f((this.unsigned ? r.rem_u : r.rem_s)(this.low, this.high, t.low, t.high), r.get_high(), this.unsigned) : this.sub(this.div(t).mul(t)); 33967 }, k.mod = k.modulo, k.rem = k.modulo, k.not = function () { 33968 return f(~this.low, ~this.high, this.unsigned); 33969 }, k.and = function (t) { 33970 return i(t) || (t = h(t)), f(this.low & t.low, this.high & t.high, this.unsigned); 33971 }, k.or = function (t) { 33972 return i(t) || (t = h(t)), f(this.low | t.low, this.high | t.high, this.unsigned); 33973 }, k.xor = function (t) { 33974 return i(t) || (t = h(t)), f(this.low ^ t.low, this.high ^ t.high, this.unsigned); 33975 }, k.shiftLeft = function (t) { 33976 return i(t) && (t = t.toInt()), 0 == (t &= 63) ? this : t < 32 ? f(this.low << t, this.high << t | this.low >>> 32 - t, this.unsigned) : f(0, this.low << t - 32, this.unsigned); 33977 }, k.shl = k.shiftLeft, k.shiftRight = function (t) { 33978 return i(t) && (t = t.toInt()), 0 == (t &= 63) ? this : t < 32 ? f(this.low >>> t | this.high << 32 - t, this.high >> t, this.unsigned) : f(this.high >> t - 32, this.high >= 0 ? 0 : -1, this.unsigned); 33979 }, k.shr = k.shiftRight, k.shiftRightUnsigned = function (t) { 33980 if (i(t) && (t = t.toInt()), 0 === (t &= 63)) return this; 33981 var e = this.high; 33982 return t < 32 ? f(this.low >>> t | e << 32 - t, e >>> t, this.unsigned) : f(32 === t ? e : e >>> t - 32, 0, this.unsigned); 33983 }, k.shru = k.shiftRightUnsigned, k.shr_u = k.shiftRightUnsigned, k.toSigned = function () { 33984 return this.unsigned ? f(this.low, this.high, !1) : this; 33985 }, k.toUnsigned = function () { 33986 return this.unsigned ? this : f(this.low, this.high, !0); 33987 }, k.toBytes = function (t) { 33988 return t ? this.toBytesLE() : this.toBytesBE(); 33989 }, k.toBytesLE = function () { 33990 var t = this.high, 33991 e = this.low; 33992 return [255 & e, e >>> 8 & 255, e >>> 16 & 255, e >>> 24, 255 & t, t >>> 8 & 255, t >>> 16 & 255, t >>> 24]; 33993 }, k.toBytesBE = function () { 33994 var t = this.high, 33995 e = this.low; 33996 return [t >>> 24, t >>> 16 & 255, t >>> 8 & 255, 255 & t, e >>> 24, e >>> 16 & 255, e >>> 8 & 255, 255 & e]; 33997 }, n.fromBytes = function (t, e, r) { 33998 return r ? n.fromBytesLE(t, e) : n.fromBytesBE(t, e); 33999 }, n.fromBytesLE = function (t, e) { 34000 return new n(t[0] | t[1] << 8 | t[2] << 16 | t[3] << 24, t[4] | t[5] << 8 | t[6] << 16 | t[7] << 24, e); 34001 }, n.fromBytesBE = function (t, e) { 34002 return new n(t[4] << 24 | t[5] << 16 | t[6] << 8 | t[7], t[0] << 24 | t[1] << 16 | t[2] << 8 | t[3], e); 34003 }; 34004 }, function (t, e) { 34005 var r = { 34006 utf8: { 34007 stringToBytes: function (t) { 34008 return r.bin.stringToBytes(unescape(encodeURIComponent(t))); 34009 }, 34010 bytesToString: function (t) { 34011 return decodeURIComponent(escape(r.bin.bytesToString(t))); 34012 } 34013 }, 34014 bin: { 34015 stringToBytes: function (t) { 34016 for (var e = [], r = 0; r < t.length; r++) e.push(255 & t.charCodeAt(r)); 34017 34018 return e; 34019 }, 34020 bytesToString: function (t) { 34021 for (var e = [], r = 0; r < t.length; r++) e.push(String.fromCharCode(t[r])); 34022 34023 return e.join(""); 34024 } 34025 } 34026 }; 34027 t.exports = r; 34028 }, function (t, e, r) { 34029 t.exports = r(335); 34030 }, function (t, e, r) { 34031 var n = r(17), 34032 i = r(51), 34033 o = r(28), 34034 a = r(65).f, 34035 s = function (t) { 34036 return function (e) { 34037 for (var r, s = o(e), u = i(s), f = u.length, c = 0, l = []; f > c;) r = u[c++], n && !a.call(s, r) || l.push(t ? [r, s[r]] : s[r]); 34038 34039 return l; 34040 }; 34041 }; 34042 34043 t.exports = { 34044 entries: s(!0), 34045 values: s(!1) 34046 }; 34047 }, function (t, e, r) { 34048 t.exports = r(338); 34049 }, function (t, e, r) { 34050 t.exports = r(352); 34051 }, function (t, e, r) { 34052 var n = r(355), 34053 i = r(153); 34054 34055 t.exports = function (t) { 34056 if (i(Object(t)) || "[object Arguments]" === Object.prototype.toString.call(t)) return n(t); 34057 }; 34058 }, function (t, e, r) { 34059 t.exports = r(360); 34060 }, function (t, e, r) { 34061 t.exports = r(372); 34062 }, function (t, e, r) { 34063 var n = r(13), 34064 i = r(375).trim, 34065 o = r(156), 34066 a = n.parseInt, 34067 s = /^[+-]?0[Xx]/, 34068 u = 8 !== a(o + "08") || 22 !== a(o + "0x16"); 34069 t.exports = u ? function (t, e) { 34070 var r = i(String(t)); 34071 return a(r, e >>> 0 || (s.test(r) ? 16 : 10)); 34072 } : a; 34073 }, function (t, e) { 34074 t.exports = "\t\n\v\f\r  áââââââ ââââââ¯âã\u2028\u2029\ufeff"; 34075 }, function (t, e, r) { 34076 var n = r(151); 34077 34078 t.exports = function (t) { 34079 if (n(t)) return t; 34080 }; 34081 }, function (t, e) { 34082 t.exports = function () {
34083 throw new TypeError("Invalid attempt to destructure non-iterable instance"); 34084 }; 34085 }, function (t, e, r) { 34086 t.exports = r(393); 34087 }, function (t, e, r) { 34088 34089 var n = r(419), 34090 i = r(426), 34091 o = r(429); 34092 34093 function a(t) { 34094 var e = n.parse(t), 34095 r = e.protocol, 34096 a = e.pathname; 34097 return "file:" === r ? new o(unescape(a)) : new i(t); 34098 } 34099 34100 t.exports = { 34101 LocalFile: o, 34102 RemoteFile: i, 34103 fromUrl: a, 34104 open: function (t, e, r) { 34105 if (r) return r; 34106 if (t) return a(t); 34107 if (e) return new o(e); 34108 throw new Error("no url, path, or filehandle provided, cannot open"); 34109 } 34110 }; 34111 }, function (t, e, r) { 34112 34113 Object.defineProperty(e, "__esModule", { 34114 value: !0 34115 }), e.promisify = i; 34116 var n = "__ES6-PROMISIFY--CUSTOM-ARGUMENTS__"; 34117 34118 function i(t) { 34119 if ("function" != typeof t) throw new TypeError("Argument to promisify must be a function"); 34120 var e = t[n], 34121 r = i.Promise || Promise; 34122 if ("function" != typeof r) throw new Error("No Promise implementation found; do you need a polyfill?"); 34123 return function () { 34124 for (var n = this, i = arguments.length, o = new Array(i), a = 0; a < i; a++) o[a] = arguments[a]; 34125 34126 return new r(function (r, i) { 34127 o.push(function (t) { 34128 if (t) return i(t); 34129 34130 for (var n = arguments.length, o = new Array(n > 1 ? n - 1 : 0), a = 1; a < n; a++) o[a - 1] = arguments[a]; 34131 34132 if (1 === o.length || !e) return r(o[0]); 34133 var s = {}; 34134 o.forEach(function (t, r) { 34135 var n = e[r]; 34136 n && (s[n] = t); 34137 }), r(s); 34138 }), t.call.apply(t, [n].concat(o)); 34139 }); 34140 }; 34141 } 34142 34143 i.argumentNames = n, i.Promise = void 0; 34144 }, function (t, e, r) { 34145 34146 (function (t) { 34147 Object.defineProperty(e, "__esModule", { 34148 value: !0 34149 }); 34150 34151 var n = r(449), 34152 i = function () { 34153 if ("undefined" != typeof self) return self; 34154 if ("undefined" != typeof window) return window; 34155 if (void 0 !== t) return t; 34156 throw new Error("unable to locate global object"); 34157 }, 34158 o = void 0 === i().AbortController ? n.AbortController : i().AbortController; 34159 34160 e.AbortController = o; 34161 var a = void 0 === i().AbortController ? n.AbortSignal : i().AbortSignal; 34162 e.AbortSignal = a; 34163 }).call(this, r(23)); 34164 }, function (t, e, r) { 34165 34166 var n = r(104), 34167 i = r(432), 34168 o = r(439); 34169 t.exports = { 34170 CramFile: n, 34171 IndexedCramFile: i, 34172 CraiIndex: o 34173 }; 34174 }, function (t, e, r) { 34175 34176 (function (e) { 34177 var n, 34178 i = r(1), 34179 o = i(r(16)), 34180 a = i(r(37)), 34181 s = i(r(30)), 34182 u = i(r(31)), 34183 f = i(r(7)), 34184 c = i(r(10)), 34185 l = r(126), 34186 h = r(224), 34187 d = r(94), 34188 p = r(9), 34189 g = p.CramUnimplementedError, 34190 v = p.CramMalformedError, 34191 y = r(309), 34192 m = r(318), 34193 b = m.cramFileDefinition, 34194 _ = m.getSectionParsers, 34195 w = r(329), 34196 x = r(160).open, 34197 E = r(58), 34198 S = E.parseItem, 34199 k = E.tinyMemoize, 34200 A = r(430).parseHeaderText, 34201 C = function () { 34202 function t(e) { 34203 (0, f.default)(this, t), this.file = x(e.url, e.path, e.filehandle), this.validateChecksums = !0, this.fetchReferenceSequenceCallback = e.seqFetch, this.options = { 34204 checkSequenceMD5: !1 !== e.checkSequenceMD5, 34205 cacheSize: void 0 !== e.cacheSize ? e.cacheSize : 2e4 34206 }, this.featureCache = new d({ 34207 maxSize: this.options.cacheSize 34208 }); 34209 } 34210 34211 var r, n, i, o, p, m, E, k, C, T; 34212 return (0, c.default)(t, [{ 34213 key: "toString", 34214 value: function () { 34215 return this.file.filename ? this.file.filename : this.file.url ? this.file.url : "(cram file)"; 34216 } 34217 }, { 34218 key: "read", 34219 value: function (t, e, r, n) { 34220 return this.file.read(t, e, r, n); 34221 } 34222 }, { 34223 key: "stat", 34224 value: function () { 34225 return this.file.stat(); 34226 } 34227 }, { 34228 key: "getDefinition", 34229 value: (T = (0, u.default)(s.default.mark(function t() { 34230 var r, n; 34231 return s.default.wrap(function (t) { 34232 for (;;) switch (t.prev = t.next) { 34233 case 0: 34234 return r = e.allocUnsafe(b.maxLength), t.next = 3, this.file.read(r, 0, b.maxLength, 0); 34235 34236 case 3: 34237 if (2 === (n = b.parser.parse(r).result).majorVersion || 3 === n.majorVersion) { 34238 t.next = 6; 34239 break; 34240 } 34241 34242 throw new g("CRAM version ".concat(n.majorVersion, " not supported")); 34243 34244 case 6: 34245 return t.abrupt("return", n); 34246 34247 case 7: 34248 case "end": 34249 return t.stop(); 34250 } 34251 }, t, this); 34252 })), function () { 34253 return T.apply(this, arguments); 34254 }) 34255 }, { 34256 key: "getSamHeader", 34257 value: (C = (0, u.default)(s.default.mark(function t() { 34258 var e, r, n, i, o; 34259 return s.default.wrap(function (t) { 34260 for (;;) switch (t.prev = t.next) { 34261 case 0: 34262 return t.next = 2, this.getContainerById(0); 34263 34264 case 2: 34265 if (e = t.sent) { 34266 t.next = 5; 34267 break; 34268 } 34269
34270 throw new v("file contains no containers"); 34271 34272 case 5: 34273 return t.next = 7, e.getFirstBlock(); 34274 34275 case 7: 34276 return r = t.sent, n = r.content, i = n.readInt32LE(0), o = n.toString("utf8", 4, 4 + i), this.header = o, t.abrupt("return", A(o)); 34277 34278 case 14: 34279 case "end": 34280 return t.stop(); 34281 } 34282 }, t, this); 34283 })), function () { 34284 return C.apply(this, arguments); 34285 }) 34286 }, { 34287 key: "getHeaderText", 34288 value: (k = (0, u.default)(s.default.mark(function t() { 34289 return s.default.wrap(function (t) { 34290 for (;;) switch (t.prev = t.next) { 34291 case 0: 34292 return t.next = 2, this.getSamHeader(); 34293 34294 case 2: 34295 return t.abrupt("return", this.header); 34296 34297 case 3: 34298 case "end": 34299 return t.stop(); 34300 } 34301 }, t, this); 34302 })), function () { 34303 return k.apply(this, arguments); 34304 }) 34305 }, { 34306 key: "getSectionParsers", 34307 value: (E = (0, u.default)(s.default.mark(function t() { 34308 var e, r; 34309 return s.default.wrap(function (t) { 34310 for (;;) switch (t.prev = t.next) { 34311 case 0: 34312 return t.next = 2, this.getDefinition(); 34313 34314 case 2: 34315 return e = t.sent, r = e.majorVersion, t.abrupt("return", _(r)); 34316 34317 case 5: 34318 case "end": 34319 return t.stop(); 34320 } 34321 }, t, this); 34322 })), function () { 34323 return E.apply(this, arguments); 34324 }) 34325 }, { 34326 key: "getContainerById", 34327 value: (m = (0, u.default)(s.default.mark(function t(e) { 34328 var r, n, i, o, a, u, f, c, l, h; 34329 return s.default.wrap(function (t) { 34330 for (;;) switch (t.prev = t.next) { 34331 case 0: 34332 return t.next = 2, this.getSectionParsers(); 34333 34334 case 2: 34335 return r = t.sent, n = r.cramFileDefinition.maxLength, t.next = 6, this.file.stat(); 34336 34337 case 6: 34338 i = t.sent, o = i.size, a = r.cramContainerHeader1, f = 0; 34339 34340 case 10: 34341 if (!(f <= e)) { 34342 t.next = 36; 34343 break; 34344 } 34345 34346 if (!(n + a.maxLength + 8 >= o)) { 34347 t.next = 13; 34348 break; 34349 } 34350 34351 return t.abrupt("return", void 0); 34352 34353 case 13: 34354 return u = this.getContainerAtPosition(n), t.next = 16, u.getHeader(); 34355 34356 case 16: 34357 if (c = t.sent) { 34358 t.next = 19; 34359 break; 34360 } 34361 34362 throw new v("container ".concat(e, " not found in file")); 34363 34364 case 19: 34365 if (0 !== f) { 34366 t.next = 32; 34367 break; 34368 } 34369 34370 n = c._endPosition, l = 0; 34371 34372 case 22: 34373 if (!(l < c.numBlocks)) { 34374 t.next = 30; 34375 break; 34376 } 34377 34378 return t.next = 25, this.readBlock(n); 34379 34380 case 25: 34381 h = t.sent, n = h._endPosition; 34382 34383 case 27: 34384 l += 1, t.next = 22; 34385 break; 34386 34387 case 30: 34388 t.next = 33; 34389 break; 34390 34391 case 32: 34392 n += c._size + c.length; 34393 34394 case 33: 34395 f += 1, t.next = 10; 34396 break; 34397 34398 case 36: 34399 return t.abrupt("return", u); 34400 34401 case 37: 34402 case "end": 34403 return t.stop(); 34404 } 34405 }, t, this); 34406 })), function (t) { 34407 return m.apply(this, arguments); 34408 }) 34409 }, { 34410 key: "checkCrc32", 34411 value: (p = (0, u.default)(s.default.mark(function t(r, n, i, o) { 34412 var u, f, c, l; 34413 return s.default.wrap(function (t) { 34414 for (;;) switch (t.prev = t.next) { 34415 case 0: 34416 return u = e.allocUnsafe(n), t.next = 3, this.file.read(u, 0, n, r); 34417 34418 case 3: 34419 if ((f = h.unsigned(u)) === i) { 34420 t.next = 6; 34421 break; 34422 } 34423 34424 throw new v((0, a.default)(c = (0, a.default)(l = "crc mismatch in ".concat(o, ": recorded CRC32 = ")).call(l, i, ", but calculated CRC32 = ")).call(c, f)); 34425 34426 case 6: 34427 case "end": 34428 return t.stop(); 34429 } 34430 }, t, this); 34431 })), function (t, e, r, n) { 34432 return p.apply(this, arguments); 34433 }) 34434 }, { 34435 key: "containerCount", 34436 value: (o = (0, u.default)(s.default.mark(function t() { 34437 var e, r, n, i, o, a, u, f, c; 34438 return s.default.wrap(function (t) { 34439 for (;;) switch (t.prev = t.next) { 34440 case 0:
34441 return t.next = 2, this.getSectionParsers(); 34442 34443 case 2: 34444 return e = t.sent, t.next = 5, this.file.stat(); 34445 34446 case 5: 34447 r = t.sent, n = r.size, i = e.cramContainerHeader1, o = 0, a = e.cramFileDefinition.maxLength; 34448 34449 case 10: 34450 if (!(a + i.maxLength + 8 < n)) { 34451 t.next = 33; 34452 break; 34453 } 34454 34455 return t.next = 13, this.getContainerAtPosition(a).getHeader(); 34456 34457 case 13: 34458 if (u = t.sent) { 34459 t.next = 16; 34460 break; 34461 } 34462 34463 return t.abrupt("break", 33); 34464 34465 case 16: 34466 if (0 !== o) { 34467 t.next = 29; 34468 break; 34469 } 34470 34471 a = u._endPosition, f = 0; 34472 34473 case 19: 34474 if (!(f < u.numBlocks)) { 34475 t.next = 27; 34476 break; 34477 } 34478 34479 return t.next = 22, this.readBlock(a); 34480 34481 case 22: 34482 c = t.sent, a = c._endPosition; 34483 34484 case 24: 34485 f += 1, t.next = 19; 34486 break; 34487 34488 case 27: 34489 t.next = 30; 34490 break; 34491 34492 case 29: 34493 a += u._size + u.length; 34494 34495 case 30: 34496 o += 1, t.next = 10; 34497 break; 34498 34499 case 33: 34500 return t.abrupt("return", o); 34501 34502 case 34: 34503 case "end": 34504 return t.stop(); 34505 } 34506 }, t, this); 34507 })), function () { 34508 return o.apply(this, arguments); 34509 }) 34510 }, { 34511 key: "getContainerAtPosition", 34512 value: function (t) { 34513 return new w(this, t); 34514 } 34515 }, { 34516 key: "readBlockHeader", 34517 value: (i = (0, u.default)(s.default.mark(function t(r) { 34518 var n, i, o, a, u; 34519 return s.default.wrap(function (t) { 34520 for (;;) switch (t.prev = t.next) { 34521 case 0: 34522 return t.next = 2, this.getSectionParsers(); 34523 34524 case 2: 34525 return n = t.sent, i = n.cramBlockHeader, t.next = 6, this.file.stat(); 34526 34527 case 6: 34528 if (o = t.sent, a = o.size, !(r + i.maxLength >= a)) { 34529 t.next = 10; 34530 break; 34531 } 34532 34533 return t.abrupt("return", void 0); 34534 34535 case 10: 34536 return u = e.allocUnsafe(i.maxLength), t.next = 13, this.file.read(u, 0, i.maxLength, r); 34537 34538 case 13: 34539 return t.abrupt("return", S(u, i.parser, 0, r)); 34540 34541 case 14: 34542 case "end": 34543 return t.stop(); 34544 } 34545 }, t, this); 34546 })), function (t) { 34547 return i.apply(this, arguments); 34548 }) 34549 }, { 34550 key: "_parseSection", 34551 value: (n = (0, u.default)(s.default.mark(function t(r, n) { 34552 var i, 34553 o, 34554 u, 34555 f, 34556 c, 34557 l, 34558 h, 34559 d = arguments; 34560 return s.default.wrap(function (t) { 34561 for (;;) switch (t.prev = t.next) { 34562 case 0: 34563 if (o = d.length > 2 && void 0 !== d[2] ? d[2] : r.maxLength, !(u = d.length > 3 ? d[3] : void 0)) { 34564 t.next = 6; 34565 break; 34566 } 34567 34568 f = u, t.next = 15; 34569 break; 34570 34571 case 6: 34572 return t.next = 8, this.file.stat(); 34573 34574 case 8: 34575 if (c = t.sent, l = c.size, !(n + o >= l)) { 34576 t.next = 12; 34577 break; 34578 } 34579 34580 return t.abrupt("return", void 0); 34581 34582 case 12: 34583 return f = e.allocUnsafe(o), t.next = 15, this.file.read(f, 0, o, n); 34584 34585 case 15: 34586 if ((h = S(f, r.parser, 0, n))._size === o) { 34587 t.next = 18; 34588 break; 34589 } 34590 34591 throw new v((0, a.default)(i = "section read error: requested size ".concat(o, " does not equal parsed size ")).call(i, h._size)); 34592 34593 case 18: 34594 return t.abrupt("return", h); 34595 34596 case 19: 34597 case "end": 34598 return t.stop(); 34599 } 34600 }, t, this); 34601 })), function (t, e) { 34602 return n.apply(this, arguments); 34603 }) 34604 }, { 34605 key: "_uncompress", 34606 value: function (t, e, r) { 34607 if ("gzip" === t) { 34608 l.gunzipSync(e).copy(r); 34609 } else { 34610 if ("rans" !== t) throw new g("".concat(t, " decompression not yet implemented")); 34611 y.uncompress(e, r); 34612 } 34613 } 34614 }, { 34615 key: "readBlock", 34616 value: (r = (0, u.default)(s.default.mark(function t(r) { 34617 var n, i, o, a, u, f, c, l; 34618 return s.default.wrap(function (t) { 34619 for (;;) switch (t.prev = t.next) { 34620 case 0: 34621 return t.next = 2, this.getDefinition(); 34622 34623 case 2: 34624 return n = t.sent, i = n.majorVersion, t.next = 6, this.get
34624SectionParsers(); 34625 34626 case 6: 34627 return o = t.sent, t.next = 9, this.readBlockHeader(r); 34628 34629 case 9: 34630 if (a = t.sent, u = a._endPosition, a.contentPosition = a._endPosition, f = e.allocUnsafe(a.uncompressedSize), "raw" === a.compressionMethod) { 34631 t.next = 20; 34632 break; 34633 } 34634 34635 return c = e.allocUnsafe(a.compressedSize), t.next = 17, this.read(c, 0, a.compressedSize, u); 34636 34637 case 17: 34638 this._uncompress(a.compressionMethod, c, f), t.next = 22; 34639 break; 34640 34641 case 20: 34642 return t.next = 22, this.read(f, 0, a.uncompressedSize, u); 34643 34644 case 22: 34645 if (a.content = f, !(i >= 3)) { 34646 t.next = 35; 34647 break; 34648 } 34649 34650 return t.next = 26, this._parseSection(o.cramBlockCrc32, u + a.compressedSize); 34651 34652 case 26: 34653 if (l = t.sent, a.crc32 = l.crc32, !this.validateChecksums) { 34654 t.next = 31; 34655 break; 34656 } 34657 34658 return t.next = 31, this.checkCrc32(r, a._size + a.compressedSize, a.crc32, "block data"); 34659 34660 case 31: 34661 a._endPosition = l._endPosition, a._size = a.compressedSize + o.cramBlockCrc32.maxLength, t.next = 37; 34662 break; 34663 34664 case 35: 34665 a._endPosition = u + a.compressedSize, a._size = a.compressedSize; 34666 34667 case 37: 34668 return t.abrupt("return", a); 34669 34670 case 38: 34671 case "end": 34672 return t.stop(); 34673 } 34674 }, t, this); 34675 })), function (t) { 34676 return r.apply(this, arguments); 34677 }) 34678 }]), t; 34679 }(); 34680 34681 (0, o.default)(n = "getDefinition getSectionParsers getSamHeader".split(" ")).call(n, function (t) { 34682 return k(C, t); 34683 }), t.exports = C; 34684 }).call(this, r(19).Buffer); 34685 }, function (t, e, r) { 34686 34687 e.byteLength = function (t) { 34688 var e = f(t), 34689 r = e[0], 34690 n = e[1]; 34691 return 3 * (r + n) / 4 - n; 34692 }, e.toByteArray = function (t) { 34693 var e, 34694 r, 34695 n = f(t), 34696 a = n[0], 34697 s = n[1], 34698 u = new o(function (t, e, r) { 34699 return 3 * (e + r) / 4 - r; 34700 }(0, a, s)), 34701 c = 0, 34702 l = s > 0 ? a - 4 : a; 34703 34704 for (r = 0; r < l; r += 4) e = i[t.charCodeAt(r)] << 18 | i[t.charCodeAt(r + 1)] << 12 | i[t.charCodeAt(r + 2)] << 6 | i[t.charCodeAt(r + 3)], u[c++] = e >> 16 & 255, u[c++] = e >> 8 & 255, u[c++] = 255 & e; 34705 34706 2 === s && (e = i[t.charCodeAt(r)] << 2 | i[t.charCodeAt(r + 1)] >> 4, u[c++] = 255 & e); 34707 1 === s && (e = i[t.charCodeAt(r)] << 10 | i[t.charCodeAt(r + 1)] << 4 | i[t.charCodeAt(r + 2)] >> 2, u[c++] = e >> 8 & 255, u[c++] = 255 & e); 34708 return u; 34709 }, e.fromByteArray = function (t) { 34710 for (var e, r = t.length, i = r % 3, o = [], a = 0, s = r - i; a < s; a += 16383) o.push(c(t, a, a + 16383 > s ? s : a + 16383)); 34711 34712 1 === i ? (e = t[r - 1], o.push(n[e >> 2] + n[e << 4 & 63] + "==")) : 2 === i && (e = (t[r - 2] << 8) + t[r - 1], o.push(n[e >> 10] + n[e >> 4 & 63] + n[e << 2 & 63] + "=")); 34713 return o.join(""); 34714 }; 34715 34716 for (var n = [], i = [], o = "undefined" != typeof Uint8Array ? Uint8Array : Array, a = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", s = 0, u = a.length; s < u; ++s) n[s] = a[s], i[a.charCodeAt(s)] = s; 34717 34718 function f(t) { 34719 var e = t.length; 34720 if (e % 4 > 0) throw new Error("Invalid string. Length must be a multiple of 4"); 34721 var r = t.indexOf("="); 34722 return -1 === r && (r = e), [r, r === e ? 0 : 4 - r % 4]; 34723 } 34724 34725 function c(t, e, r) { 34726 for (var i, o, a = [], s = e; s < r; s += 3) i = (t[s] << 16 & 16711680) + (t[s + 1] << 8 & 65280) + (255 & t[s + 2]), a.push(n[(o = i) >> 18 & 63] + n[o >> 12 & 63] + n[o >> 6 & 63] + n[63 & o]); 34727 34728 return a.join(""); 34729 } 34730 34731 i["-".charCodeAt(0)] = 62, i["_".charCodeAt(0)] = 63; 34732 }, function (t, e) { 34733 e.read = function (t, e, r, n, i) { 34734 var o, 34735 a, 34736 s = 8 * i - n - 1, 34737 u = (1 << s) - 1, 34738 f = u >> 1, 34739 c = -7, 34740 l = r ? i - 1 : 0, 34741 h = r ? -1 : 1, 34742 d = t[e + l]; 34743 34744 for (l += h, o = d & (1 << -c) - 1, d >>= -c, c += s; c > 0; o = 256 * o + t[e + l], l += h, c -= 8); 34745 34746 for (a = o & (1 << -c) - 1, o >>= -c, c += n;
34746 c > 0; a = 256 * a + t[e + l], l += h, c -= 8); 34747 34748 if (0 === o) o = 1 - f;else { 34749 if (o === u) return a ? NaN : 1 / 0 * (d ? -1 : 1); 34750 a += Math.pow(2, n), o -= f; 34751 } 34752 return (d ? -1 : 1) * a * Math.pow(2, o - n); 34753 }, e.write = function (t, e, r, n, i, o) { 34754 var a, 34755 s, 34756 u, 34757 f = 8 * o - i - 1, 34758 c = (1 << f) - 1, 34759 l = c >> 1, 34760 h = 23 === i ? Math.pow(2, -24) - Math.pow(2, -77) : 0, 34761 d = n ? 0 : o - 1, 34762 p = n ? 1 : -1, 34763 g = e < 0 || 0 === e && 1 / e < 0 ? 1 : 0; 34764 34765 for (e = Math.abs(e), isNaN(e) || e === 1 / 0 ? (s = isNaN(e) ? 1 : 0, a = c) : (a = Math.floor(Math.log(e) / Math.LN2), e * (u = Math.pow(2, -a)) < 1 && (a--, u *= 2), (e += a + l >= 1 ? h / u : h * Math.pow(2, 1 - l)) * u >= 2 && (a++, u /= 2), a + l >= c ? (s = 0, a = c) : a + l >= 1 ? (s = (e * u - 1) * Math.pow(2, i), a += l) : (s = e * Math.pow(2, l - 1) * Math.pow(2, i), a = 0)); i >= 8; t[r + d] = 255 & s, d += p, s /= 256, i -= 8); 34766 34767 for (a = a << i | s, f += i; f > 0; t[r + d] = 255 & a, d += p, a /= 256, f -= 8); 34768 34769 t[r + d - p] |= 128 * g; 34770 }; 34771 }, function (t, e, r) { 34772 r(41); 34773 var n = r(177), 34774 i = r(67), 34775 o = Array.prototype, 34776 a = { 34777 DOMTokenList: !0, 34778 NodeList: !0 34779 }; 34780 34781 t.exports = function (t) { 34782 var e = t.forEach; 34783 return t === o || t instanceof Array && e === o.forEach || a.hasOwnProperty(i(t)) ? n : e; 34784 }; 34785 }, function (t, e, r) { 34786 34787 var n = r(28), 34788 i = r(78), 34789 o = r(35), 34790 a = r(42), 34791 s = r(80), 34792 u = a.set, 34793 f = a.getterFor("Array Iterator"); 34794 t.exports = s(Array, "Array", function (t, e) { 34795 u(this, { 34796 type: "Array Iterator", 34797 target: n(t), 34798 index: 0, 34799 kind: e 34800 }); 34801 }, function () { 34802 var t = f(this), 34803 e = t.target, 34804 r = t.kind, 34805 n = t.index++; 34806 return !e || n >= e.length ? (t.target = void 0, { 34807 value: void 0, 34808 done: !0 34809 }) : "keys" == r ? { 34810 value: n, 34811 done: !1 34812 } : "values" == r ? { 34813 value: e[n], 34814 done: !1 34815 } : { 34816 value: [n, e[n]], 34817 done: !1 34818 }; 34819 }, "values"), o.Arguments = o.Array, i("keys"), i("values"), i("entries"); 34820 }, function (t, e, r) { 34821 var n = r(13), 34822 i = r(170), 34823 o = n.WeakMap; 34824 t.exports = "function" == typeof o && /native code/.test(i.call(o)); 34825 }, function (t, e, r) { 34826 var n = r(61); 34827 t.exports = n("native-function-to-string", Function.toString); 34828 }, function (t, e, r) { 34829 var n = r(13), 34830 i = r(20); 34831 34832 t.exports = function (t, e) { 34833 try { 34834 i(n, t, e); 34835 } catch (r) { 34836 n[t] = e; 34837 } 34838 34839 return e; 34840 }; 34841 }, function (t, e, r) { 34842 34843 var n = r(108).IteratorPrototype, 34844 i = r(44), 34845 o = r(43), 34846 a = r(36), 34847 s = r(35), 34848 u = function () { 34849 return this; 34850 }; 34851 34852 t.exports = function (t, e, r) { 34853 var f = e + " Iterator"; 34854 return t.prototype = i(n, { 34855 next: o(1, r) 34856 }), a(t, f, !1, !0), s[f] = u, t; 34857 }; 34858 }, function (t, e, r) { 34859 var n = r(17), 34860 i = r(21), 34861 o = r(2), 34862 a = r(51); 34863 t.exports = n ? Object.defineProperties : function (t, e) { 34864 o(t); 34865 34866 for (var r, n = a(e), s = n.length, u = 0; s > u;) i.f(t, r = n[u++], e[r]); 34867 34868 return t; 34869 }; 34870 }, function (t, e, r) { 34871 34872 var n = r(67), 34873 i = {}; 34874 i[r(6)("toStringTag")] = "z", t.exports = "[object z]" !== String(i) ? function () { 34875 return "[object " + n(this) + "]"; 34876 } : i.toString; 34877 }, function (t, e, r) { 34878 var n = r(14); 34879 34880 t.exports = function (t) { 34881 if (!n(t) && null !== t) throw TypeError("Can't set " + String(t) + " as a prototype"); 34882 return t; 34883 }; 34884 }, function (t, e) { 34885 t.exports = { 34886 CSSRuleList: 0, 34887 CSSStyleDeclaration: 0, 34888 CSSValueList: 0, 34889 ClientRectList: 0, 34890 DOMRectList: 0, 34891 DOMStringList: 0, 34892 DOMTokenList: 1, 34893 DataTransferItemList: 0, 34894 FileList: 0, 34895 HTMLAllCollection: 0, 34896 HTMLCollection: 0, 34897 HTMLFormElement: 0, 34898 HTMLSelectElement: 0, 34899 MediaList: 0, 34900 MimeTypeArray: 0, 34901 NamedNodeMap: 0, 34902 NodeList: 1, 34903 PaintRequestList: 0, 34904 Plugin: 0, 34905 PluginArray: 0, 34906 SVGLengthList: 0, 34907 SVGNumberList: 0, 34908 SVGPathSegList: 0, 34909 SVGPointList: 0, 34910 SVGStringList: 0, 34911 SVGTransformList: 0, 34912 SourceBufferList: 0, 34913 StyleSheetList: 0, 34914 TextTrackCueList: 0, 34915 TextTrackList: 0, 34916 TouchList: 0 34917 }; 34918 }, function (t, e, r) { 34919 t.exports = r(178); 34920 }, function (t, e, r) { 34921 r(179); 34922 var n = r(18); 34923 t.exports = n("Array").forEach; 34924 }, function (t, e, r) { 34925 34926 var n = r(0), 34927 i = r(180); 34928 n({ 34929 target: "Array", 34930 proto: !0, 34931 forced: [].forEach != i 34932 }, {
34933 forEach: i 34934 }); 34935 }, function (t, e, r) { 34936 34937 var n = r(45).forEach, 34938 i = r(54); 34939 t.exports = i("forEach") ? function (t) { 34940 return n(this, t, arguments.length > 1 ? arguments[1] : void 0); 34941 } : [].forEach; 34942 }, function (t, e, r) { 34943 t.exports = r(182); 34944 }, function (t, e, r) { 34945 var n = r(183), 34946 i = Array.prototype; 34947 34948 t.exports = function (t) { 34949 var e = t.concat; 34950 return t === i || t instanceof Array && e === i.concat ? n : e; 34951 }; 34952 }, function (t, e, r) { 34953 r(114); 34954 var n = r(18); 34955 t.exports = n("Array").concat; 34956 }, function (t, e, r) { 34957 var n = function (t) { 34958 34959 var e, 34960 r = Object.prototype, 34961 n = r.hasOwnProperty, 34962 i = "function" == typeof Symbol ? Symbol : {}, 34963 o = i.iterator || "@@iterator", 34964 a = i.asyncIterator || "@@asyncIterator", 34965 s = i.toStringTag || "@@toStringTag"; 34966 34967 function u(t, e, r, n) { 34968 var i = e && e.prototype instanceof g ? e : g, 34969 o = Object.create(i.prototype), 34970 a = new C(n || []); 34971 return o._invoke = function (t, e, r) { 34972 var n = c; 34973 return function (i, o) { 34974 if (n === h) throw new Error("Generator is already running"); 34975 34976 if (n === d) { 34977 if ("throw" === i) throw o; 34978 return R(); 34979 } 34980 34981 for (r.method = i, r.arg = o;;) { 34982 var a = r.delegate; 34983 34984 if (a) { 34985 var s = S(a, r); 34986 34987 if (s) { 34988 if (s === p) continue; 34989 return s; 34990 } 34991 } 34992 34993 if ("next" === r.method) r.sent = r._sent = r.arg;else if ("throw" === r.method) { 34994 if (n === c) throw n = d, r.arg; 34995 r.dispatchException(r.arg); 34996 } else "return" === r.method && r.abrupt("return", r.arg); 34997 n = h; 34998 var u = f(t, e, r); 34999 35000 if ("normal" === u.type) { 35001 if (n = r.done ? d : l, u.arg === p) continue; 35002 return { 35003 value: u.arg, 35004 done: r.done 35005 }; 35006 } 35007 35008 "throw" === u.type && (n = d, r.method = "throw", r.arg = u.arg); 35009 } 35010 }; 35011 }(t, r, a), o; 35012 } 35013 35014 function f(t, e, r) { 35015 try { 35016 return { 35017 type: "normal", 35018 arg: t.call(e, r) 35019 }; 35020 } catch (t) { 35021 return { 35022 type: "throw", 35023 arg: t 35024 }; 35025 } 35026 } 35027 35028 t.wrap = u; 35029 var c = "suspendedStart", 35030 l = "suspendedYield", 35031 h = "executing", 35032 d = "completed", 35033 p = {}; 35034 35035 function g() {} 35036 35037 function v() {} 35038 35039 function y() {} 35040 35041 var m = {}; 35042 35043 m[o] = function () { 35044 return this; 35045 }; 35046 35047 var b = Object.getPrototypeOf, 35048 _ = b && b(b(T([]))); 35049 35050 _ && _ !== r && n.call(_, o) && (m = _); 35051 var w = y.prototype = g.prototype = Object.create(m); 35052 35053 function x(t) { 35054 ["next", "throw", "return"].forEach(function (e) { 35055 t[e] = function (t) { 35056 return this._invoke(e, t); 35057 }; 35058 }); 35059 } 35060 35061 function E(t, e) { 35062 var r; 35063 35064 this._invoke = function (i, o) { 35065 function a() { 35066 return new e(function (r, a) { 35067 !function r(i, o, a, s) { 35068 var u = f(t[i], t, o); 35069 35070 if ("throw" !== u.type) { 35071 var c = u.arg, 35072 l = c.value; 35073 return l && "object" == typeof l && n.call(l, "__await") ? e.resolve(l.__await).then(function (t) { 35074 r("next", t, a, s); 35075 }, function (t) { 35076 r("throw", t, a, s); 35077 }) : e.resolve(l).then(function (t) { 35078 c.value = t, a(c); 35079 }, function (t) { 35080 return r("throw", t, a, s); 35081 }); 35082 } 35083 35084 s(u.arg); 35085 }(i, o, r, a); 35086 }); 35087 } 35088 35089 return r = r ? r.then(a, a) : a(); 35090 }; 35091 } 35092 35093 function S(t, r) { 35094 var n = t.iterator[r.method]; 35095 35096 if (n === e) { 35097 if (r.delegate = null, "throw" === r.method) { 35098 if (t.iterator.return && (r.method = "return", r.arg = e, S(t, r), "throw" === r.method)) return p; 35099 r.method = "throw", r.arg = new TypeError("The iterator does not provide a 'throw' method"); 35100 } 35101 35102 return p; 35103 } 35104 35105 var i = f(n, t.iterator, r.arg); 35106 if ("throw" === i.type) return r.method = "throw", r.arg = i.arg, r.delegate = null, p; 35107 var o = i.arg; 35108 return o ? o.done ? (r[t.resultName] = o.value, r.next = t.nextLoc, "return" !== r.method && (r.method = "next", r.arg = e), r.delegate = null, p) : o : (r.method = "throw", r.arg = new TypeError("iterator result is not an object"), r.delegate = null, p); 35109 } 35110 35111 function k(t) { 35112 var e = { 35113 tryLoc: t[0] 35114 }; 35115 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); 35116 } 35117 35118 function A(t) { 35119 var e = t.completion || {}; 35120 e.type = "normal", delete e.arg, t.completion = e; 35121 } 35122 35123 function C(t) { 35124 this.tryEntries = [{ 35125 tryLoc: "root" 35126 }], t.forEach(k, this), this.reset(!0); 35127 } 35128 35129 function T(t) { 35130 if (t) { 35131 var r = t[o]; 35132 if (r) return r.call(t); 35133 if ("function" == typeof t.next) return t; 35134 35135 if (!isNaN(t.length)) { 35136 var i = -1, 35137 a = function r() { 35138 for (; ++i < t.length;) if (n.call(t, i)) return r.value = t[i], r.done = !1, r; 35139 35140 return r.value = e, r.done = !0, r; 35141 }; 35142 35143 return a.next = a; 35144 } 35145 } 35146 35147 return { 35148 next: R 35149 }; 35150 } 35151 35152 function R() { 35153 return { 35154 value: e, 35155 done: !0 35156 }; 35157 } 35158 35159 return v.prototype = w.constructor = y, y.constructor = v, y[s] = v.displayName = "GeneratorFunction", t.isGeneratorFunction = function (t) { 35160 var e = "function" == typeof t && t.constructor; 35161 return !!e && (e === v || "GeneratorFunction" === (e.displayName || e.name)); 35162 }, t.mark = function (t) { 35163 return Object.setPrototypeOf ? Object.setPrototypeOf(t, y) : (t.__proto__ = y, s in t || (t[s] = "GeneratorFunction")), t.prototype = Object.create(w), t; 35164 }, t.awrap = function (t) { 35165 return { 35166 __await: t 35167 }; 35168 }, x(E.prototype), E.prototype[a] = function () { 35169 return this; 35170 }, t.AsyncIterator = E, t.async = function (e, r, n, i, o) { 35171 void 0 === o && (o = Promise); 35172 var a = new E(u(e, r, n, i), o); 35173 return t.isGeneratorFunction(r) ? a : a.next().then(function (t) { 35174 return t.done ? t.value : a.next(); 35175 }); 35176 }, x(w), w[s] = "Generator", w[o] = function () { 35177 return this; 35178 }, w.toString = function () { 35179 return "[object Generator]"; 35180 }, t.keys = function (t) { 35181 var e = []; 35182 35183 for (var r in t) e.push(r); 35184 35185 return e.reverse(), function r() { 35186 for (; e.length;) { 35187 var n = e.pop(); 35188 if (n in t) return r.value = n, r.done = !1, r; 35189 } 35190 35191 return r.done = !0, r; 35192 }; 35193 }, t.values = T, C.prototype = { 35194 constructor: C, 35195 reset: function (t) { 35196 if (this.prev = 0, this.next = 0, this.sent = this._sent = e, this.done = !1, this.delegate = null, this.method = "next", this.arg = e, this.tryEntries.forEac
35196h(A), !t) for (var r in this) "t" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = e); 35197 }, 35198 stop: function () { 35199 this.done = !0; 35200 var t = this.tryEntries[0].completion; 35201 if ("throw" === t.type) throw t.arg; 35202 return this.rval; 35203 }, 35204 dispatchException: function (t) { 35205 if (this.done) throw t; 35206 var r = this; 35207 35208 function i(n, i) { 35209 return s.type = "throw", s.arg = t, r.next = n, i && (r.method = "next", r.arg = e), !!i; 35210 } 35211 35212 for (var o = this.tryEntries.length - 1; o >= 0; --o) { 35213 var a = this.tryEntries[o], 35214 s = a.completion; 35215 if ("root" === a.tryLoc) return i("end"); 35216 35217 if (a.tryLoc <= this.prev) { 35218 var u = n.call(a, "catchLoc"), 35219 f = n.call(a, "finallyLoc"); 35220 35221 if (u && f) { 35222 if (this.prev < a.catchLoc) return i(a.catchLoc, !0); 35223 if (this.prev < a.finallyLoc) return i(a.finallyLoc); 35224 } else if (u) { 35225 if (this.prev < a.catchLoc) return i(a.catchLoc, !0); 35226 } else { 35227 if (!f) throw new Error("try statement without catch or finally"); 35228 if (this.prev < a.finallyLoc) return i(a.finallyLoc); 35229 } 35230 } 35231 } 35232 }, 35233 abrupt: function (t, e) { 35234 for (var r = this.tryEntries.length - 1; r >= 0; --r) { 35235 var i = this.tryEntries[r]; 35236 35237 if (i.tryLoc <= this.prev && n.call(i, "finallyLoc") && this.prev < i.finallyLoc) { 35238 var o = i; 35239 break; 35240 } 35241 } 35242 35243 o && ("break" === t || "continue" === t) && o.tryLoc <= e && e <= o.finallyLoc && (o = null); 35244 var a = o ? o.completion : {}; 35245 return a.type = t, a.arg = e, o ? (this.method = "next", this.next = o.finallyLoc, p) : this.complete(a); 35246 }, 35247 complete: function (t, e) { 35248 if ("throw" === t.type) throw t.arg; 35249 return "break" === t.type || "continue" === t.type ? this.next = t.arg : "return" === t.type ? (this.rval = this.arg = t.arg, this.method = "return", this.next = "end") : "normal" === t.type && e && (this.next = e), p; 35250 }, 35251 finish: function (t) { 35252 for (var e = this.tryEntries.length - 1; e >= 0; --e) { 35253 var r = this.tryEntries[e]; 35254 if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), A(r), p; 35255 } 35256 }, 35257 catch: function (t) { 35258 for (var e = this.tryEntries.length - 1; e >= 0; --e) { 35259 var r = this.tryEntries[e]; 35260 35261 if (r.tryLoc === t) { 35262 var n = r.completion; 35263 35264 if ("throw" === n.type) { 35265 var i = n.arg; 35266 A(r); 35267 } 35268 35269 return i; 35270 } 35271 } 35272 35273 throw new Error("illegal catch attempt"); 35274 }, 35275 delegateYield: function (t, r, n) { 35276 return this.delegate = { 35277 iterator: T(t), 35278 resultName: r, 35279 nextLoc: n 35280 }, "next" === this.method && (this.arg = e), p; 35281 } 35282 }, t; 35283 }(t.exports); 35284 35285 try { 35286 regeneratorRuntime = n; 35287 } catch (t) { 35288 Function("r", "regeneratorRuntime = r")(n); 35289 } 35290 }, function (t, e, r) { 35291 t.exports = r(186); 35292 }, function (t, e, r) { 35293 t.exports = r(115), r(192), r(193), r(194), r(195); 35294 }, function (t, e, r) { 35295 var n = r(83), 35296 i = r(49), 35297 o = function (t) { 35298 return function (e, r) { 35299 var o, 35300 a, 35301 s = String(i(e)), 35302 u = n(r), 35303 f = s.length; 35304 return u < 0 || u >= f ? t ? "" : void 0 : (o = s.charCodeAt(u)) < 55296 || o > 56319 || u + 1 === f || (a = s.charCodeAt(u + 1)) < 56320 || a > 57343 ? t ? s.charAt(u) : o : t ? s.slice(u, u + 2) : a - 56320 + (o - 55296 << 10) + 65536; 35305 }; 35306 }; 35307 35308 t.exports = { 35309 codeAt: o(!1), 35310 charAt: o(!0) 35311 }; 35312 }, function (t, e, r) { 35313 35314 var n, 35315 i, 35316 o, 35317 a, 35318 s = r(0), 35319 u = r(4),
35320 f = r(13), 35321 c = r(3), 35322 l = r(116), 35323 h = r(52), 35324 d = r(117), 35325 p = r(36), 35326 g = r(118), 35327 v = r(14), 35328 y = r(5), 35329 m = r(89), 35330 b = r(34), 35331 _ = r(8), 35332 w = r(121), 35333 x = r(55), 35334 E = r(122).set, 35335 S = r(189), 35336 k = r(124), 35337 A = r(190), 35338 C = r(56), 35339 T = r(69), 35340 R = r(123), 35341 O = r(42), 35342 I = r(107), 35343 L = r(6)("species"), 35344 B = "Promise", 35345 P = O.get, 35346 F = O.set, 35347 N = O.getterFor(B), 35348 M = l, 35349 j = f.TypeError, 35350 z = f.document, 35351 U = f.process, 35352 D = f.fetch, 35353 q = U && U.versions, 35354 Z = q && q.v8 || "", 35355 H = C.f, 35356 V = H, 35357 G = "process" == b(U), 35358 Y = !!(z && z.createEvent && f.dispatchEvent), 35359 W = I(B, function () { 35360 var t = M.resolve(1), 35361 e = function () {}, 35362 r = (t.constructor = {})[L] = function (t) { 35363 t(e, e); 35364 }; 35365 35366 return !((G || "function" == typeof PromiseRejectionEvent) && (!u || t.finally) && t.then(e) instanceof r && 0 !== Z.indexOf("6.6") && -1 === R.indexOf("Chrome/66")); 35367 }), 35368 K = W || !w(function (t) { 35369 M.all(t).catch(function () {}); 35370 }), 35371 Q = function (t) { 35372 var e; 35373 return !(!v(t) || "function" != typeof (e = t.then)) && e; 35374 }, 35375 X = function (t, e, r) { 35376 if (!e.notified) { 35377 e.notified = !0; 35378 var n = e.reactions; 35379 S(function () { 35380 for (var i = e.value, o = 1 == e.state, a = 0; n.length > a;) { 35381 var s, 35382 u, 35383 f, 35384 c = n[a++], 35385 l = o ? c.ok : c.fail, 35386 h = c.resolve, 35387 d = c.reject, 35388 p = c.domain; 35389 35390 try { 35391 l ? (o || (2 === e.rejection && et(t, e), e.rejection = 1), !0 === l ? s = i : (p && p.enter(), s = l(i), p && (p.exit(), f = !0)), s === c.promise ? d(j("Promise-chain cycle")) : (u = Q(s)) ? u.call(s, h, d) : h(s)) : d(i); 35392 } catch (t) { 35393 p && !f && p.exit(), d(t); 35394 } 35395 } 35396 35397 e.reactions = [], e.notified = !1, r && !e.rejection && J(t, e); 35398 }); 35399 } 35400 }, 35401 $ = function (t, e, r) { 35402 var n, i; 35403 Y ? ((n = z.createEvent("Event")).promise = e, n.reason = r, n.initEvent(t, !1, !0), f.dispatchEvent(n)) : n = { 35404 promise: e, 35405 reason: r 35406 }, (i = f["on" + t]) ? i(n) : "unhandledrejection" === t && A("Unhandled promise rejection", r); 35407 }, 35408 J = function (t, e) { 35409 E.call(f, function () { 35410 var r, 35411 n = e.value; 35412 if (tt(e) && (r = T(function () { 35413 G ? U.emit("unhandledRejection", n, t) : $("unhandledrejection", t, n); 35414 }), e.rejection = G || tt(e) ? 2 : 1, r.error)) throw r.value; 35415 }); 35416 }, 35417 tt = function (t) { 35418 return 1 !== t.rejection && !t.parent; 35419 }, 35420 et = function (t, e) { 35421 E.call(f, function () { 35422 G ? U.emit("rejectionHandled", t) : $("rejectionhandled", t, e.value); 35423 }); 35424 }, 35425 rt = function (t, e, r, n) { 35426 return function (i) { 35427 t(e, r, i, n); 35428 }; 35429 }, 35430 nt = function (t, e, r, n) { 35431 e.done || (e.done = !0, n && (e = n), e.value = r, e.state = 2, X(t, e, !0)); 35432 }, 35433 it = function (t, e, r, n) { 35434 if (!e.done) { 35435 e.done = !0, n && (e = n); 35436 35437 try { 35438 if (t === r) throw j("Promise can't be resolved itself"); 35439 var i = Q(r); 35440 i ? S(function () { 35441 var n = { 35442 done: !1 35443 }; 35444 35445 try { 35446 i.call(r, rt(it, t, n, e), rt(nt, t, n, e)); 35447 } catch (r) { 35448 nt(t, n, r, e); 35449 } 35450 }) : (e.value = r, e.state = 1, X(t, e, !1)); 35451 } catch (r) { 35452 nt(t, { 35453 done: !1 35454 }, r, e); 35455 } 35456 } 35457 }; 35458 35459 W && (M = function (t) { 35460 m(this, M, B), y(t), n.call(this); 35461 var e = P(this); 35462 35463 try { 35464 t(rt(it, this, e), rt(nt, this, e)); 35465 } catch (t) { 35466 nt(this, e, t); 35467 } 35468 }, (n = function (t) { 35469 F(this, { 35470 type: B, 35471 done: !1, 35472 notified: !1, 35473 parent: !1, 35474 reactions: [], 35475 rejection: !1, 35476 state: 0, 35477 value: void 0 35478 }); 35479 }).prototype = d(M.prototype, { 35480 then: function (t, e) { 35481 var r = N(this), 35482 n = H(x(this, M)); 35483 return n.ok = "function" != typeof t || t, n.fail = "function" == typeof e && e, n.domain = G ? U.domain : void 0, r.parent = !0, r.reactions.push(n), 0 != r.state && X(this, r, !1), n.promise; 35484 }, 35485 catch: function (t) { 35486 return this.then(void 0, t); 35487 } 35488 }), i = function () { 35489 var t = new n(), 35490 e = P(t); 35491 this.promise = t, this.resolve = rt(it, t, e), this.reject = rt(nt, t, e); 35492 }, C.f = H = function (t) { 35493 return t === M || t === o ? new i(t) : V(t); 35494 }, u || "function" != typeof l || (a = l.prototype.then, h(l.prototype, "then", function (t, e) { 35495 var r = this; 35496 return new M(function (t, e) { 35497 a.call(r, t, e); 35498 }).then(t, e); 35499 }), "function" == typeof D && s({ 35500 global: !0, 35501 enumerable: !0, 35502 forced: !0 35503 }, { 35504 fetch: function (t) { 35505 return k(M, D.apply(f, arguments)); 35506 } 35507 }))), s({ 35508 global: !0, 35509 wrap: !0, 35510 forced: W 35511 }, { 35512 Promise: M 35513 }), p(M, B, !1, !0), g(B), o = c.Promise, s({ 35514 target: B, 35515 stat: !0, 35516 forced: W 35517 }, { 35518 reject: function (t) { 35519 var e = H(this); 35520 return e.reject.call(void 0, t), e.promise; 35521 } 35522 }), s({ 35523 target: B, 35524 stat: !0, 35525 forced: u || W 35526 }, { 35527 resolve: function (t) { 35528 return k(u && this === o ? M : this, t); 35529 } 35530 }), s({ 35531 target: B, 35532 stat: !0, 35533 forced: K 35534 }, { 35535 all: function (t) { 35536 var e = this, 35537 r = H(e), 35538 n = r.resolve, 35539 i = r.reject, 35540 o = T(function () { 35541 var r = y(e.resolve), 35542 o = [], 35543 a = 0, 35544 s = 1; 35545 _(t, function (t) { 35546 var u = a++, 35547 f = !1; 35548 o.push(void 0), s++, r.call(e, t).then(function (t) { 35549 f || (f = !0, o[u] = t, --s || n(o)); 35550 }, i); 35551 }), --s || n(o); 35552 }); 35553 return o.error && i(o.value), r.promise; 35554 }, 35555 race: function (t) { 35556 var e = this, 35557 r = H(e), 35558 n = r.reject, 35559 i = T(function () { 35560 var i = y(e.resolve); 35561 35562 _(t, function (t) { 35563 i.call(e, t).then(r.resolve, n); 35564 }); 35565 }); 35566 return i.error && n(i.value), r.promise; 35567 } 35568 }); 35569 }, function (t, e, r) { 35570 var n, 35571 i, 35572 o, 35573 a, 35574 s, 35575 u, 35576 f, 35577 c, 35578 l = r(13), 35579 h = r(81).f, 35580 d = r(34), 35581 p = r(122).set, 35582 g = r(123), 35583 v = l.MutationObserver || l.WebKitMutationObserver, 35584 y = l.process, 35585 m = l.Promise, 35586 b = "process" == d(y), 35587 _ = h(l, "queueMicrotask"), 35588 w = _ && _.value; 35589 35590 w || (n = function () { 35591 var t, e; 35592 35593 for (b && (t = y.domain) && t.exit(); i;) { 35594 e = i.fn, i = i.next; 35595 35596 try { 35597 e(); 35598 } catch (t) { 35599 throw i ? a() : o = void 0, t; 35600 } 35601 } 35602 35603 o = void 0, t && t.enter(); 35604 }, b ? a = function () { 35605 y.nextTick(n); 35606 } : v && !/(iphone|ipod|ipad).*applewebkit/i.test(g) ? (s = !0, u = document.createTextNode(""), new v(n).observe(u, { 35607 characterData: !0 35608 }), a = function () { 35609 u.data = s = !s; 35610 }) : m && m.resolve ? (f = m.resolve(void 0), c = f.then, a = function () { 35611 c.call(f, n); 35612 }) : a = function () { 35613 p.call(l, n); 35614 }), t.exports = w || function (t) { 35615 var e = { 35616 fn: t, 35617 next: void 0 35618 }; 35619 o && (o.next = e), i || (i = e, a()), o = e; 35620 }; 35621 }, function (t, e, r) { 35622 var n = r(13); 35623 35624 t.exports = function (t, e) { 35625 var r = n.console; 35626 r && r.error && (1 === arguments.length ? r.error(t) : r.error(t, e)); 35627 }; 35628 }, function (t, e, r) { 35629 35630 var n = r(0), 35631 i = r(4), 35632 o = r(116), 35633 a = r(26), 35634 s = r(55), 35635 u = r(124), 35636 f = r(52); 35637 n({ 35638 target: "Promise", 35639 proto: !0, 35640 real: !0 35641 }, { 35642 finally: function (t) { 35643 var e = s(this, a("Promise")), 35644 r = "function" == typeof t; 35645 return this.then(r ? function (r) { 35646 return u(e, t()).then(function () { 35647 return r; 35648 }); 35649 } : t, r ? function (r) { 35650 return u(e, t()).then(function () { 35651 throw r; 35652 }); 35653 } : t); 35654 } 35655 }), i || "function" != typeof o || o.prototype.finally || f(o.prototype, "finally", a("Promise").prototype.finally); 35656 }, function (t, e, r) { 35657 var n = r(0), 35658 i = r(66), 35659 o = r(86), 35660 a = r(44), 35661 s = r(43), 35662 u = r(8), 35663 f = r(20), 35664 c = function (t, e) { 35665 var r = this; 35666 if (!(r instanceof c)) return new c(t, e); 35667 o && (r = o(new Error(e), i(r))); 35668 var n = []; 35669 return u(t, n.push, n), f(r, "errors", n), void 0 !== e && f(r, "message", Str
35669ing(e)), r; 35670 }; 35671 35672 c.prototype = a(Error.prototype, { 35673 constructor: s(5, c), 35674 name: s(5, "AggregateError") 35675 }), n({ 35676 global: !0 35677 }, { 35678 AggregateError: c 35679 }); 35680 }, function (t, e, r) { 35681 r(125); 35682 }, function (t, e, r) { 35683 35684 var n = r(0), 35685 i = r(56), 35686 o = r(69); 35687 n({ 35688 target: "Promise", 35689 stat: !0 35690 }, { 35691 try: function (t) { 35692 var e = i.f(this), 35693 r = o(t); 35694 return (r.error ? e.reject : e.resolve)(r.value), e.promise; 35695 } 35696 }); 35697 }, function (t, e, r) { 35698 35699 var n = r(0), 35700 i = r(5), 35701 o = r(26), 35702 a = r(56), 35703 s = r(69), 35704 u = r(8); 35705 n({ 35706 target: "Promise", 35707 stat: !0 35708 }, { 35709 any: function (t) { 35710 var e = this, 35711 r = a.f(e), 35712 n = r.resolve, 35713 f = r.reject, 35714 c = s(function () { 35715 var r = i(e.resolve), 35716 a = [], 35717 s = 0, 35718 c = 1, 35719 l = !1; 35720 u(t, function (t) { 35721 var i = s++, 35722 u = !1; 35723 a.push(void 0), c++, r.call(e, t).then(function (t) { 35724 u || l || (l = !0, n(t)); 35725 }, function (t) { 35726 u || l || (u = !0, a[i] = t, --c || f(new (o("AggregateError"))(a, "No one promise resolved"))); 35727 }); 35728 }), --c || f(new (o("AggregateError"))(a, "No one promise resolved")); 35729 }); 35730 return c.error && f(c.value), r.promise; 35731 } 35732 }); 35733 }, function (t, e, r) { 35734 t.exports = r(197); 35735 }, function (t, e, r) { 35736 t.exports = r(198); 35737 }, function (t, e, r) { 35738 r(199); 35739 35740 var n = r(3).Object, 35741 i = t.exports = function (t, e, r) { 35742 return n.defineProperty(t, e, r); 35743 }; 35744 35745 n.defineProperty.sham && (i.sham = !0); 35746 }, function (t, e, r) { 35747 var n = r(0), 35748 i = r(17); 35749 n({ 35750 target: "Object", 35751 stat: !0, 35752 forced: !i, 35753 sham: !i 35754 }, { 35755 defineProperty: r(21).f 35756 }); 35757 }, function (t, e, r) { 35758 t.exports = i; 35759 var n = r(91).EventEmitter; 35760 35761 function i() { 35762 n.call(this); 35763 } 35764 35765 r(47)(i, n), i.Readable = r(92), i.Writable = r(208), i.Duplex = r(209), i.Transform = r(210), i.PassThrough = r(211), i.Stream = i, i.prototype.pipe = function (t, e) { 35766 var r = this; 35767 35768 function i(e) { 35769 t.writable && !1 === t.write(e) && r.pause && r.pause(); 35770 } 35771 35772 function o() { 35773 r.readable && r.resume && r.resume(); 35774 } 35775 35776 r.on("data", i), t.on("drain", o), t._isStdio || e && !1 === e.end || (r.on("end", s), r.on("close", u)); 35777 var a = !1; 35778 35779 function s() { 35780 a || (a = !0, t.end()); 35781 } 35782 35783 function u() { 35784 a || (a = !0, "function" == typeof t.destroy && t.destroy()); 35785 } 35786 35787 function f(t) { 35788 if (c(), 0 === n.listenerCount(this, "error")) throw t; 35789 } 35790 35791 function c() { 35792 r.removeListener("data", i), t.removeListener("drain", o), r.removeListener("end", s), r.removeListener("close", u), r.removeListener("error", f), t.removeListener("error", f), r.removeListener("end", c), r.removeListener("close", c), t.removeListener("close", c); 35793 } 35794 35795 return r.on("error", f), t.on("error", f), r.on("end", c), r.on("close", c), t.on("close", c), t.emit("pipe", r), t; 35796 }; 35797 }, function (t, e) {}, function (t, e, r) { 35798 35799 var n = r(71).Buffer, 35800 i = r(203); 35801 t.exports = function () { 35802 function t() { 35803 !function (t, e) { 35804 if (!(t instanceof e)) throw new TypeError("Cannot call a class as a function"); 35805 }(this, t), this.head = null, this.tail = null, this.length = 0; 35806 } 35807 35808 return t.prototype.push = function (t) { 35809 var e = { 35810 data: t, 35811 next: null 35812 }; 35813 this.length > 0 ? this.tail.next = e : this.head = e, this.tail = e, ++this.length; 35814 }, t.prototype.unshift = function (t) { 35815 var e = { 35816 data: t, 35817 next: this.head 35818 }; 35819 0 === this.length && (this.tail = e), this.head = e, ++this.length; 35820 }, t.prototype.shift = function () { 35821 if (0 !== this.length) { 35822 var t = this.head.data; 35823 return 1 === this.length ? this.head = this.tail = null : this.head = this.head.next, --this.length, t; 35824 } 35825 }, t.prototype.clear = function () { 35826 this.head = this.tail = null, this.length = 0; 35827 }, t.prototype.join = function (t) { 35828 if (0 === this.length) return ""; 35829 35830 for (var e = this.head, r = "" + e.data; e = e.next;) r += t + e.data; 35831 35832 return r; 35833 }, t.prototype.concat = function (t) { 35834 if (0 === this.length) return n.alloc(0); 35835 if (1 === this.length) return this.head.data; 35836 35837 for (var e, r, i, o = n.allocUnsafe(t >>> 0), a = this.head, s = 0; a;) e = a.data, r = o, i = s, e.copy(r, i), s += a.data.length, a = a.next; 35838 35839 return o; 35840 }, t; 35841 }(), i && i.inspect && i.inspect.custom && (t.exports.prototype[i.inspect.custom] = function () { 35842 var t = i.inspect({ 35843 length: this.length 35844 }); 35845 return this.constructor.name + " " + t; 35846 }); 35847 }, function (t, e) {}, function (t, e, r) { 35848 (function (t) { 35849 var n = void 0 !== t && t || "undefined" != typeof self && self || window, 35850 i = Function.prototype.apply; 35851 35852 function o(t, e) { 35853 this._id = t, this._clearFn = e; 35854 } 35855 35856 e.setTimeout = function () { 35857 return new o(i.call(setTimeout, n, arguments), clearTimeout); 35858 }, e.setInterval = function () { 35859 return new o(i.call(setInterval, n, arguments), clearInterval); 35860 }, e.clearTimeout = e.clearInterval = function (t) { 35861 t && t.close(); 35862 }, o.prototype.unref = o.prototype.ref = function () {}, o.prototype.close = function () { 35863 this._clearFn.call(n, this._id); 35864 }, e.enroll = function (t, e) { 35865 clearTimeout(t._idleTimeoutId), t._idleTimeout = e; 35866 }, e.unenroll = function (t) { 35867 clearTimeout(t._idleTimeoutId), t._idleTimeout = -1; 35868 }, e._unrefActive = e.active = function (t) { 35869 clearTimeout(t._idleTimeoutId); 35870 var e = t._idleTimeout; 35871 e >= 0 && (t._idleTimeoutId = setTimeout(function () { 35872 t._onTimeout && t._onTimeout(); 35873 }, e)); 35874 }, r(205), e.setImmediate = "undefined" != typeof self && self.setImmediate || void 0 !== t && t.setImmediate || this && this.setImmediate, e.clearImmediate = "undefined" != typeof self && self.clearImmediate || void 0 !== t && t.clearImmediate || this && this.clearImmediate; 35875 }).call(this, r(23)); 35876 }, function (t, e, r) { 35877 (function (t, e) { 35878 !function (t, r) { 35879 35880 if (!t.setImmediate) { 35881 var n, 35882 i, 35883 o, 35884 a, 35885 s, 35886 u = 1, 35887 f = {}, 35888 c = !1, 35889 l = t.document, 35890 h = Object.getPrototypeOf && Object.getPrototypeOf(t); 35891 h = h && h.setTimeout ? h : t, "[object process]" === {}.toString.call(t.process) ? n = function (t) { 35892 e.nextTick(function () { 35893 p(t); 35894 }); 35895 } : !function () { 35896 if (t.postMessage && !t.importScripts) { 35897 var e = !0, 35898 r = t.onmessage; 35899 return t.onmessage = function () { 35900 e = !1; 35901 }, t.postMessage("", "*"), t.onmessage = r, e; 35902 } 35903 }() ? t.MessageChannel ? ((o = new MessageChannel()).port1.onmessage = function (t) { 35904 p(t.data); 35905 }, n = function (t) { 35906 o.port2.postMessage(t); 35907 }) : l && "onreadystatechange" in l.createElement("script") ? (i = l.documentElement, n = function (t) { 35908 var e = l.createElement("script"); 35909 e.onreadystatechange = function () { 35910 p(t), e.onreadystatechange = null, i.removeChild(e), e = null; 35911 }, i.appendChild(e); 35912 }) : n = function (t) { 35913 setTimeout(p, 0, t); 35914 } : (a = "setImmediate$" + Math.random() + "$", s = function (e) { 35915 e.source === t && "string" == typeof e.data && 0 === e.data.indexOf(a) && p(+e.data.slice(a.length)); 35916 }, t.addEventListener ? t.addEventListener("message", s, !1) : t.attachEvent("onmessage", s), n = function (e) {
35917 t.postMessage(a + e, "*"); 35918 }), h.setImmediate = function (t) { 35919 "function" != typeof t && (t = new Function("" + t)); 35920 35921 for (var e = new Array(arguments.length - 1), r = 0; r < e.length; r++) e[r] = arguments[r + 1]; 35922 35923 var i = { 35924 callback: t, 35925 args: e 35926 }; 35927 return f[u] = i, n(u), u++; 35928 }, h.clearImmediate = d; 35929 } 35930 35931 function d(t) { 35932 delete f[t]; 35933 } 35934 35935 function p(t) { 35936 if (c) setTimeout(p, 0, t);else { 35937 var e = f[t]; 35938 35939 if (e) { 35940 c = !0; 35941 35942 try { 35943 !function (t) { 35944 var e = t.callback, 35945 n = t.args; 35946 35947 switch (n.length) { 35948 case 0: 35949 e(); 35950 break; 35951 35952 case 1: 35953 e(n[0]); 35954 break; 35955 35956 case 2: 35957 e(n[0], n[1]); 35958 break; 35959 35960 case 3: 35961 e(n[0], n[1], n[2]); 35962 break; 35963 35964 default: 35965 e.apply(r, n); 35966 } 35967 }(e); 35968 } finally { 35969 d(t), c = !1; 35970 } 35971 } 35972 } 35973 } 35974 }("undefined" == typeof self ? void 0 === t ? this : t : self); 35975 }).call(this, r(23), r(38)); 35976 }, function (t, e, r) { 35977 (function (e) { 35978 function r(t) { 35979 try { 35980 if (!e.localStorage) return !1; 35981 } catch (t) { 35982 return !1; 35983 } 35984 35985 var r = e.localStorage[t]; 35986 return null != r && "true" === String(r).toLowerCase(); 35987 } 35988 35989 t.exports = function (t, e) { 35990 if (r("noDeprecation")) return t; 35991 var n = !1; 35992 return function () { 35993 if (!n) { 35994 if (r("throwDeprecation")) throw new Error(e); 35995 r("traceDeprecation") ? console.trace(e) : console.warn(e), n = !0; 35996 } 35997 35998 return t.apply(this, arguments); 35999 }; 36000 }; 36001 }).call(this, r(23)); 36002 }, function (t, e, r) { 36003 36004 t.exports = o; 36005 var n = r(131), 36006 i = r(57); 36007 36008 function o(t) { 36009 if (!(this instanceof o)) return new o(t); 36010 n.call(this, t); 36011 } 36012 36013 i.inherits = r(47), i.inherits(o, n), o.prototype._transform = function (t, e, r) { 36014 r(null, t); 36015 }; 36016 }, function (t, e, r) { 36017 t.exports = r(93); 36018 }, function (t, e, r) { 36019 t.exports = r(39); 36020 }, function (t, e, r) { 36021 t.exports = r(92).Transform; 36022 }, function (t, e, r) { 36023 t.exports = r(92).PassThrough; 36024 }, function (t, e, r) { 36025 36026 (function (t, n) { 36027 var i = r(132), 36028 o = r(216), 36029 a = r(217), 36030 s = r(220), 36031 u = r(223); 36032 36033 for (var f in u) e[f] = u[f]; 36034 36035 e.NONE = 0, e.DEFLATE = 1, e.INFLATE = 2, e.GZIP = 3, e.GUNZIP = 4, e.DEFLATERAW = 5, e.INFLATERAW = 6, e.UNZIP = 7; 36036 36037 function c(t) { 36038 if ("number" != typeof t || t < e.DEFLATE || t > e.UNZIP) throw new TypeError("Bad argument"); 36039 this.dictionary = null, this.err = 0, this.flush = 0, this.init_done = !1, this.level = 0, this.memLevel = 0, this.mode = t, this.strategy = 0, this.windowBits = 0, this.write_in_progress = !1, this.pending_close = !1, this.gzip_id_bytes_read = 0; 36040 } 36041 36042 c.prototype.close = function () { 36043 this.write_in_progress ? this.pending_close = !0 : (this.pending_close = !1, i(this.init_done, "close before init"), i(this.mode <= e.UNZIP), this.mode === e.DEFLATE || this.mode === e.GZIP || this.mode === e.DEFLATERAW ? a.deflateEnd(this.strm) : this.mode !== e.INFLATE && this.mode !== e.GUNZIP && this.mode !== e.INFLATERAW && this.mode !== e.UNZIP || s.inflateEnd(this.strm), this.mode = e.NONE, this.dictionary = null); 36044 }, c.prototype.write = function (t, e, r, n, i, o, a) { 36045 return this._write(!0, t, e, r, n, i, o, a); 36046 }, c.prototype.writeSync = function (t, e, r, n, i, o, a) { 36047 return this._write(!1, t, e, r, n, i, o, a); 36048 }, c.prototype._write = function (r, o, a, s, u, f, c, l) { 36049 if (i.equal(arguments.length, 8), i(this.init_done, "write before init"), i(this.mode !== e.NONE, "already finalized"), i.equal(!1, this.write_in_progress, "write already in progress"), i.equal(!1, this.pending_close, "close is pending"), this.write_in_progress = !0, i.equal(!1, void 0 === o, "must provide flush value"), this.write_in_progress = !0, o !== e.Z_NO_FLUSH && o !== e.Z_PARTIAL_FLUSH && o !== e.Z_SYNC_FLUSH && o !== e.Z_FULL_FLUSH && o !== e.Z_FINISH && o !== e.Z_BLOCK) throw new Error("Invalid flush value"); 36050 if (null == a && (a = t.alloc(0), u = 0, s = 0), this.strm.avail_in = u, this.strm.input = a, this.strm.next_in = s, this.strm.avail_out = l, this.strm.output = f, this.strm.next_out = c, this.flush = o, !r) return this._process(), this._checkError() ? this._afterSync() : void 0; 36051 var h = this; 36052 return n.nextTick(function () { 36053 h._process(), h._after(); 36054 }), this; 36055 }, c.prototype._afterSync = function () { 36056 var t = this.strm.avail_out, 36057 e = this.strm.avail_in; 36058 return this.write_in_progress = !1, [e, t]; 36059 }, c.prototype._process = function () { 36060 var t = null; 36061 36062 switch (this.mode) { 36063 case e.DEFLATE: 36064 case e.GZIP: 36065 case e.DEFLATERAW: 36066 this.err = a.deflate(this.strm, this.flush); 36067 break; 36068 36069 case e.UNZIP: 36070 switch (this.strm.avail_in > 0 && (t = this.strm.next_in), this.gzip_id_bytes_read) { 36071 case 0: 36072 if (null === t) break; 36073 36074 if (31 !== this.strm.input[t]) { 36075 this.mode = e.INFLATE; 36076 break; 36077 } 36078 36079 if (this.gzip_id_bytes_read = 1, t++, 1 === this.strm.avail_in) break; 36080 36081 case 1: 36082 if (null === t) break; 36083 139 === this.strm.input[t] ? (this.gzip_id_bytes_read = 2, this.mode = e.GUNZIP) : this.mode = e.INFLATE; 36084 break; 36085 36086 default: 36087 throw new Error("invalid number of gzip magic number bytes read"); 36088 } 36089 36090 case e.INFLATE: 36091 case e.GUNZIP: 36092 case e.INFLATERAW: 36093 for (this.err = s.inflate(this.strm, this.flush), this.err === e.Z_NEED_DICT && this.dictionary && (this.err = s.inflateSetDictionary(this.strm, this.dictionary), this.err === e.Z_OK ? this.err = s.inflate(this.strm, this.flush) : this.err === e.Z_DATA_ERROR && (this.err = e.Z_NEED_DICT)); this.strm.avail_in > 0 && this.mode === e.GUNZIP && this.err === e.Z_STREAM_END && 0 !== this.strm.next_in[0];) this.reset(), this.err = s.inflate(this.strm, this.flush); 36094 36095 break; 36096 36097 default: 36098 throw new Error("Unknown mode " + this.mode); 36099 } 36100 }, c.prototype._checkError = function () { 36101 switch (this.err) { 36102 case e.Z_OK:
36103 case e.Z_BUF_ERROR: 36104 if (0 !== this.strm.avail_out && this.flush === e.Z_FINISH) return this._error("unexpected end of file"), !1; 36105 break; 36106 36107 case e.Z_STREAM_END: 36108 break; 36109 36110 case e.Z_NEED_DICT: 36111 return null == this.dictionary ? this._error("Missing dictionary") : this._error("Bad dictionary"), !1; 36112 36113 default: 36114 return this._error("Zlib error"), !1; 36115 } 36116 36117 return !0; 36118 }, c.prototype._after = function () { 36119 if (this._checkError()) { 36120 var t = this.strm.avail_out, 36121 e = this.strm.avail_in; 36122 this.write_in_progress = !1, this.callback(e, t), this.pending_close && this.close(); 36123 } 36124 }, c.prototype._error = function (t) { 36125 this.strm.msg && (t = this.strm.msg), this.onerror(t, this.err), this.write_in_progress = !1, this.pending_close && this.close(); 36126 }, c.prototype.init = function (t, r, n, o, a) { 36127 i(4 === arguments.length || 5 === arguments.length, "init(windowBits, level, memLevel, strategy, [dictionary])"), i(t >= 8 && t <= 15, "invalid windowBits"), i(r >= -1 && r <= 9, "invalid compression level"), i(n >= 1 && n <= 9, "invalid memlevel"), i(o === e.Z_FILTERED || o === e.Z_HUFFMAN_ONLY || o === e.Z_RLE || o === e.Z_FIXED || o === e.Z_DEFAULT_STRATEGY, "invalid strategy"), this._init(r, t, n, o, a), this._setDictionary(); 36128 }, c.prototype.params = function () { 36129 throw new Error("deflateParams Not supported"); 36130 }, c.prototype.reset = function () { 36131 this._reset(), this._setDictionary(); 36132 }, c.prototype._init = function (t, r, n, i, u) { 36133 switch (this.level = t, this.windowBits = r, this.memLevel = n, this.strategy = i, this.flush = e.Z_NO_FLUSH, this.err = e.Z_OK, this.mode !== e.GZIP && this.mode !== e.GUNZIP || (this.windowBits += 16), this.mode === e.UNZIP && (this.windowBits += 32), this.mode !== e.DEFLATERAW && this.mode !== e.INFLATERAW || (this.windowBits = -1 * this.windowBits), this.strm = new o(), this.mode) { 36134 case e.DEFLATE: 36135 case e.GZIP: 36136 case e.DEFLATERAW: 36137 this.err = a.deflateInit2(this.strm, this.level, e.Z_DEFLATED, this.windowBits, this.memLevel, this.strategy); 36138 break; 36139 36140 case e.INFLATE: 36141 case e.GUNZIP: 36142 case e.INFLATERAW: 36143 case e.UNZIP: 36144 this.err = s.inflateInit2(this.strm, this.windowBits); 36145 break; 36146 36147 default: 36148 throw new Error("Unknown mode " + this.mode); 36149 } 36150 36151 this.err !== e.Z_OK && this._error("Init error"), this.dictionary = u, this.write_in_progress = !1, this.init_done = !0; 36152 }, c.prototype._setDictionary = function () { 36153 if (null != this.dictionary) { 36154 switch (this.err = e.Z_OK, this.mode) { 36155 case e.DEFLATE: 36156 case e.DEFLATERAW: 36157 this.err = a.deflateSetDictionary(this.strm, this.dictionary); 36158 } 36159 36160 this.err !== e.Z_OK && this._error("Failed to set dictionary"); 36161 } 36162 }, c.prototype._reset = function () { 36163 switch (this.err = e.Z_OK, this.mode) { 36164 case e.DEFLATE: 36165 case e.DEFLATERAW: 36166 case e.GZIP: 36167 this.err = a.deflateReset(this.strm); 36168 break; 36169 36170 case e.INFLATE: 36171 case e.INFLATERAW: 36172 case e.GUNZIP: 36173 this.err = s.inflateReset(this.strm); 36174 } 36175 36176 this.err !== e.Z_OK && this._error("Failed to reset stream"); 36177 }, e.Zlib = c; 36178 }).call(this, r(19).Buffer, r(38)); 36179 }, function (t, e, r) { 36180 /* 36181 object-assign 36182 (c) Sindre Sorhus 36183 @license MIT 36184 */ 36185 36186 var n = Object.getOwnPropertySymbols, 36187 i = Object.prototype.hasOwnProperty, 36188 o = Object.prototype.propertyIsEnumerable; 36189 36190 function a(t) { 36191 if (null == t) throw new TypeError("Object.assign cannot be called with null or undefined"); 36192 return Object(t); 36193 } 36194 36195 t.exports = function () { 36196 try { 36197 if (!Object.assign) return !1; 36198 var t = new String("abc"); 36199 if (t[5] = "de", "5" === Object.getOwnPropertyNames(t)[0]) return !1; 36200 36201 for (var e = {}, r = 0; r < 10; r++) e["_" + String.fromCharCode(r)] = r; 36202 36203 if ("0123456789" !== Object.getOwnPropertyNames(e).map(function (t) { 36204 return e[t]; 36205 }).join("")) return !1; 36206 var n = {}; 36207 return "abcdefghijklmnopqrst".split("").forEach(function (t) { 36208 n[t] = t; 36209 }), "abcdefghijklmnopqrst" === Object.keys(Object.assign({}, n)).join(""); 36210 } catch (t) { 36211 return !1; 36212 } 36213 }() ? Object.assign : function (t, e) { 36214 for (var r, s, u = a(t), f = 1; f < arguments.length; f++) { 36215 for (var c in r = Object(arguments[f])) i.call(r, c) && (u[c] = r[c]); 36216 36217 if (n) { 36218 s = n(r); 36219 36220 for (var l = 0; l < s.length; l++) o.call(r, s[l]) && (u[s[l]] = r[s[l]]); 36221 } 36222 } 36223 36224 return u; 36225 }; 36226 }, function (t, e) { 36227 t.exports = function (t) { 36228 return t && "object" == typeof t && "function" == typeof t.copy && "function" == typeof t.fill && "function" == typeof t.readUInt8; 36229 }; 36230 }, function (t, e) { 36231 "function" == typeof Object.create ? t.exports = function (t, e) { 36232 t.super_ = e, t.prototype = Object.create(e.prototype, { 36233 constructor: { 36234 value: t, 36235 enumerable: !1, 36236 writable: !0, 36237 configurable: !0 36238 } 36239 }); 36240 } : t.exports = function (t, e) { 36241 t.super_ = e; 36242 36243 var r = function () {}; 36244 36245 r.prototype = e.prototype, t.prototype = new r(), t.prototype.constructor = t; 36246 }; 36247 }, function (t, e, r) { 36248 36249 t.exports = function () { 36250 this.input = null, this.next_in = 0, this.avail_in = 0, this.total_in = 0, this.output = null, this.next_out = 0, this.avail_out = 0, this.total_out = 0, this.msg = "", this.state = null, this.data_type = 2, this.adler = 0; 36251 }; 36252 }, function (t, e, r) { 36253 36254 var n, 36255 i = r(72), 36256 o = r(218), 36257 a = r(134), 36258 s = r(135), 36259 u = r(219), 36260 f = 0, 36261 c = 1, 36262 l = 3, 36263 h = 4, 36264 d = 5, 36265 p = 0, 36266 g = 1, 36267 v = -2, 36268 y = -3, 36269 m = -5, 36270 b = -1, 36271 _ = 1, 36272 w = 2, 36273 x = 3, 36274 E = 4, 36275 S = 0, 36276 k = 2, 36277 A = 8, 36278 C = 9, 36279 T = 15, 36280 R = 8, 36281 O = 286, 36282 I = 30, 36283 L = 19, 36284 B = 2 * O + 1, 36285 P = 15, 36286 F = 3, 36287 N = 258, 36288 M = N + F + 1, 36289 j = 32, 36290 z = 42, 36291 U = 69, 36292 D = 73, 36293 q = 91, 36294 Z = 103, 36295 H = 113, 36296 V = 666, 36297 G = 1, 36298 Y = 2, 36299 W = 3, 36300 K = 4, 36301 Q = 3; 36302 36303 function X(t, e) { 36304 return t.msg = u[e], e; 36305 } 36306 36307 function $(t) { 36308 return (t << 1) - (t > 4 ? 9 : 0); 36309 } 36310 36311 function J(t) { 36312 for (var e = t.length; --e >= 0;) t[e] = 0; 36313 } 36314 36315 function tt(t) { 36316 var e = t.state,
36317 r = e.pending; 36318 r > t.avail_out && (r = t.avail_out), 0 !== r && (i.arraySet(t.output, e.pending_buf, e.pending_out, r, t.next_out), t.next_out += r, e.pending_out += r, t.total_out += r, t.avail_out -= r, e.pending -= r, 0 === e.pending && (e.pending_out = 0)); 36319 } 36320 36321 function et(t, e) { 36322 o._tr_flush_block(t, t.block_start >= 0 ? t.block_start : -1, t.strstart - t.block_start, e), t.block_start = t.strstart, tt(t.strm); 36323 } 36324 36325 function rt(t, e) { 36326 t.pending_buf[t.pending++] = e; 36327 } 36328 36329 function nt(t, e) { 36330 t.pending_buf[t.pending++] = e >>> 8 & 255, t.pending_buf[t.pending++] = 255 & e; 36331 } 36332 36333 function it(t, e) { 36334 var r, 36335 n, 36336 i = t.max_chain_length, 36337 o = t.strstart, 36338 a = t.prev_length, 36339 s = t.nice_match, 36340 u = t.strstart > t.w_size - M ? t.strstart - (t.w_size - M) : 0, 36341 f = t.window, 36342 c = t.w_mask, 36343 l = t.prev, 36344 h = t.strstart + N, 36345 d = f[o + a - 1], 36346 p = f[o + a]; 36347 t.prev_length >= t.good_match && (i >>= 2), s > t.lookahead && (s = t.lookahead); 36348 36349 do { 36350 if (f[(r = e) + a] === p && f[r + a - 1] === d && f[r] === f[o] && f[++r] === f[o + 1]) { 36351 o += 2, r++; 36352 36353 do {} while (f[++o] === f[++r] && f[++o] === f[++r] && f[++o] === f[++r] && f[++o] === f[++r] && f[++o] === f[++r] && f[++o] === f[++r] && f[++o] === f[++r] && f[++o] === f[++r] && o < h); 36354 36355 if (n = N - (h - o), o = h - N, n > a) { 36356 if (t.match_start = e, a = n, n >= s) break; 36357 d = f[o + a - 1], p = f[o + a]; 36358 } 36359 } 36360 } while ((e = l[e & c]) > u && 0 != --i); 36361 36362 return a <= t.lookahead ? a : t.lookahead; 36363 } 36364 36365 function ot(t) { 36366 var e, 36367 r, 36368 n, 36369 o, 36370 u, 36371 f, 36372 c, 36373 l, 36374 h, 36375 d, 36376 p = t.w_size; 36377 36378 do { 36379 if (o = t.window_size - t.lookahead - t.strstart, t.strstart >= p + (p - M)) { 36380 i.arraySet(t.window, t.window, p, p, 0), t.match_start -= p, t.strstart -= p, t.block_start -= p, e = r = t.hash_size; 36381 36382 do { 36383 n = t.head[--e], t.head[e] = n >= p ? n - p : 0; 36384 } while (--r); 36385 36386 e = r = p; 36387 36388 do { 36389 n = t.prev[--e], t.prev[e] = n >= p ? n - p : 0; 36390 } while (--r); 36391 36392 o += p; 36393 } 36394 36395 if (0 === t.strm.avail_in) break; 36396 if (f = t.strm, c = t.window, l = t.strstart + t.lookahead, h = o, d = void 0, (d = f.avail_in) > h && (d = h), r = 0 === d ? 0 : (f.avail_in -= d, i.arraySet(c, f.input, f.next_in, d, l), 1 === f.state.wrap ? f.adler = a(f.adler, c, d, l) : 2 === f.state.wrap && (f.adler = s(f.adler, c, d, l)), f.next_in += d, f.total_in += d, d), t.lookahead += r, t.lookahead + t.insert >= F) for (u = t.strstart - t.insert, t.ins_h = t.window[u], t.ins_h = (t.ins_h << t.hash_shift ^ t.window[u + 1]) & t.hash_mask; t.insert && (t.ins_h = (t.ins_h << t.hash_shift ^ t.window[u + F - 1]) & t.hash_mask, t.prev[u & t.w_mask] = t.head[t.ins_h], t.head[t.ins_h] = u, u++, t.insert--, !(t.lookahead + t.insert < F));); 36397 } while (t.lookahead < M && 0 !== t.strm.avail_in); 36398 } 36399 36400 function at(t, e) { 36401 for (var r, n;;) { 36402 if (t.lookahead < M) { 36403 if (ot(t), t.lookahead < M && e === f) return G; 36404 if (0 === t.lookahead) break; 36405 } 36406 36407 if (r = 0, t.lookahead >= F && (t.ins_h = (t.ins_h << t.hash_shift ^ t.window[t.strstart + F - 1]) & t.hash_mask, r = t.prev[t.strstart & t.w_mask] = t.head[t.ins_h], t.head[t.ins_h] = t.strstart), 0 !== r && t.strstart - r <= t.w_size - M && (t.match_length = it(t, r)), t.match_length >= F) { 36408 if (n = o._tr_tally(t, t.strstart - t.match_start, t.match_length - F), t.lookahead -= t.match_length, t.match_length <= t.max_lazy_match && t.lookahead >= F) { 36409 t.match_length--; 36410 36411 do { 36412 t.strstart++, t.ins_h = (t.ins_h << t.hash_shift ^ t.window[t.strstart + F - 1]) & t.hash_mask, r = t.prev[t.strstart & t.w_mask] = t.head[t.ins_h], t.head[t.ins_h] = t.strstart; 36413 } while (0 != --t.match_length); 36414 36415 t.strstart++; 36416 } else t.strstart += t.match_length, t.match_length = 0, t.ins_h = t.window[t.strstart], t.ins_h = (t.ins_h << t.hash_shift ^ t.window[t.strstart + 1]) & t.hash_mask; 36417 } else n = o._tr_tally(t, 0, t.window[t.strstart]), t.lookahead--, t.strstart++; 36418 if (n && (et(t, !1), 0 === t.strm.avail_out)) return G; 36419 } 36420 36421 return t.insert = t.strstart < F - 1 ? t.strstart : F - 1, e === h ? (et(t, !0), 0 === t.strm.avail_out ? W : K) : t.last_lit && (et(t, !1), 0 === t.strm.avail_out) ? G : Y; 36422 } 36423 36424 function st(t, e) { 36425 for (var r, n, i;;) { 36426 if (t.lookahead < M) { 36427 if (ot(t), t.lookahead < M && e === f) return G; 36428 if (0 === t.lookahead) break; 36429 } 36430 36431 if (r = 0, t.lookahead >= F && (t.ins_h = (t.ins_h << t.hash_shift ^ t.window[t.strstart + F - 1]) & t.hash_mask, r = t.prev[t.strstart & t.w_mask] = t.head[t.ins_h], t.head[t.ins_h] = t.strstart), t.prev_length = t.match_length, t.prev_match = t.match_start, t.match_length = F - 1, 0 !== r && t.prev_length < t.max_lazy_match && t.strstart - r <= t.w_size - M && (t.match_length = it(t, r), t.match_length <= 5 && (t.strategy === _ || t.match_length === F && t.strstart - t.match_start > 4096) && (t.match_length = F - 1)), t.prev_length >= F && t.match_length <= t.prev_length) { 36432 i = t.strstart + t.lookahead - F, n = o._tr_tally(t, t.strstart - 1 - t.prev_match, t.prev_length - F), t.lookahead -= t.prev_length - 1, t.prev_length -= 2; 36433 36434 do { 36435 ++t.strstart <= i && (t.ins_h = (t.ins_h << t.hash_shift ^ t.window[t.strstart + F - 1]) & t.hash_mask, r = t.prev[t.strstart & t.w_mask] = t.head[t.ins_h], t.head[t.ins_h] = t.strstart); 36436 } while (0 != --t.prev_length); 36437 36438 if (t.match_available = 0, t.match_length = F - 1, t.strstart++, n && (et(t, !1), 0 === t.strm.avail_out)) return G; 36439 } else if (t.match_available) { 36440 if ((n = o._tr_tally(t, 0, t.window[t.strstart - 1])) && et(t, !1), t.strstart++, t.lookahead--, 0 === t.strm.avail_out) return G; 36441 } else t.match_available = 1, t.strstart++, t.lookahead--; 36442 } 36443 36444 return t.match_available && (n = o._tr_tally(t, 0, t.window[t.strstart - 1]), t.match_available = 0), t.insert = t.strstart < F - 1 ? t.strstart : F - 1, e === h ? (et(t, !0), 0 === t.strm.avail_out ? W : K) : t.last_lit && (et(t, !1), 0 === t.strm.avail_out) ? G : Y; 36445 } 36446 36447 function ut(t, e, r, n, i) { 36448 this.good_length = t, this.max_lazy = e, this.nice_length = r, this.max_chain = n, this.func = i; 36449 } 36450 36451 function ft() { 36452 this.strm = null, this.status = 0, this.pending_buf = null, this.pending_buf_size = 0, this.pending_out = 0, this.pending = 0, this.wrap = 0, this.gzhead = null, this.gzindex = 0, this.method = A, this.last_flush = -1, this.w_size = 0, this.w_bits = 0, this.w_mask = 0, this.window = null, this.window_size = 0, this.prev = null, this.head = null, this.ins_h = 0, this.hash_size = 0, this.hash_bits = 0, this.hash_mask = 0, this.hash_shift = 0, this.block_start = 0, this.match_length = 0, this.prev_match = 0, this.match_available = 0, this.strstart = 0, this.match_start = 0, this.lookahead = 0, this.prev_length = 0, this.max_chain_length = 0, this.max_lazy_match = 0, this.level = 0, this.strategy = 0, this.good_match = 0, this.nice_match = 0, this.dyn_ltree = new i.Buf16(2 * B), this.dyn_dtree = new i.Buf16(2 * (2 * I + 1)), this.bl_tree = new i.Buf16(2 * (2 * L + 1)), J(this.dyn_ltree), J(this.dyn_dtree), J(this.bl_tree), this.l_desc = null, this.d_desc
36452= null, this.bl_desc = null, this.bl_count = new i.Buf16(P + 1), this.heap = new i.Buf16(2 * O + 1), J(this.heap), this.heap_len = 0, this.heap_max = 0, this.depth = new i.Buf16(2 * O + 1), J(this.depth), this.l_buf = 0, this.lit_bufsize = 0, this.last_lit = 0, this.d_buf = 0, this.opt_len = 0, this.static_len = 0, this.matches = 0, this.insert = 0, this.bi_buf = 0, this.bi_valid = 0; 36453 } 36454 36455 function ct(t) { 36456 var e; 36457 return t && t.state ? (t.total_in = t.total_out = 0, t.data_type = k, (e = t.state).pending = 0, e.pending_out = 0, e.wrap < 0 && (e.wrap = -e.wrap), e.status = e.wrap ? z : H, t.adler = 2 === e.wrap ? 0 : 1, e.last_flush = f, o._tr_init(e), p) : X(t, v); 36458 } 36459 36460 function lt(t) { 36461 var e, 36462 r = ct(t); 36463 return r === p && ((e = t.state).window_size = 2 * e.w_size, J(e.head), e.max_lazy_match = n[e.level].max_lazy, e.good_match = n[e.level].good_length, e.nice_match = n[e.level].nice_length, e.max_chain_length = n[e.level].max_chain, e.strstart = 0, e.block_start = 0, e.lookahead = 0, e.insert = 0, e.match_length = e.prev_length = F - 1, e.match_available = 0, e.ins_h = 0), r; 36464 } 36465 36466 function ht(t, e, r, n, o, a) { 36467 if (!t) return v; 36468 var s = 1; 36469 if (e === b && (e = 6), n < 0 ? (s = 0, n = -n) : n > 15 && (s = 2, n -= 16), o < 1 || o > C || r !== A || n < 8 || n > 15 || e < 0 || e > 9 || a < 0 || a > E) return X(t, v); 36470 8 === n && (n = 9); 36471 var u = new ft(); 36472 return t.state = u, u.strm = t, u.wrap = s, u.gzhead = null, u.w_bits = n, u.w_size = 1 << u.w_bits, u.w_mask = u.w_size - 1, u.hash_bits = o + 7, u.hash_size = 1 << u.hash_bits, u.hash_mask = u.hash_size - 1, u.hash_shift = ~~((u.hash_bits + F - 1) / F), u.window = new i.Buf8(2 * u.w_size), u.head = new i.Buf16(u.hash_size), u.prev = new i.Buf16(u.w_size), u.lit_bufsize = 1 << o + 6, u.pending_buf_size = 4 * u.lit_bufsize, u.pending_buf = new i.Buf8(u.pending_buf_size), u.d_buf = 1 * u.lit_bufsize, u.l_buf = 3 * u.lit_bufsize, u.level = e, u.strategy = a, u.method = r, lt(t); 36473 } 36474 36475 n = [new ut(0, 0, 0, 0, function (t, e) { 36476 var r = 65535; 36477 36478 for (r > t.pending_buf_size - 5 && (r = t.pending_buf_size - 5);;) { 36479 if (t.lookahead <= 1) { 36480 if (ot(t), 0 === t.lookahead && e === f) return G; 36481 if (0 === t.lookahead) break; 36482 } 36483 36484 t.strstart += t.lookahead, t.lookahead = 0; 36485 var n = t.block_start + r; 36486 if ((0 === t.strstart || t.strstart >= n) && (t.lookahead = t.strstart - n, t.strstart = n, et(t, !1), 0 === t.strm.avail_out)) return G; 36487 if (t.strstart - t.block_start >= t.w_size - M && (et(t, !1), 0 === t.strm.avail_out)) return G; 36488 } 36489 36490 return t.insert = 0, e === h ? (et(t, !0), 0 === t.strm.avail_out ? W : K) : (t.strstart > t.block_start && (et(t, !1), t.strm.avail_out), G); 36491 }), new ut(4, 4, 8, 4, at), new ut(4, 5, 16, 8, at), new ut(4, 6, 32, 32, at), new ut(4, 4, 16, 16, st), new ut(8, 16, 32, 32, st), new ut(8, 16, 128, 128, st), new ut(8, 32, 128, 256, st), new ut(32, 128, 258, 1024, st), new ut(32, 258, 258, 4096, st)], e.deflateInit = function (t, e) { 36492 return ht(t, e, A, T, R, S); 36493 }, e.deflateInit2 = ht, e.deflateReset = lt, e.deflateResetKeep = ct, e.deflateSetHeader = function (t, e) { 36494 return t && t.state ? 2 !== t.state.wrap ? v : (t.state.gzhead = e, p) : v; 36495 }, e.deflate = function (t, e) { 36496 var r, i, a, u; 36497 if (!t || !t.state || e > d || e < 0) return t ? X(t, v) : v; 36498 if (i = t.state, !t.output || !t.input && 0 !== t.avail_in || i.status === V && e !== h) return X(t, 0 === t.avail_out ? m : v); 36499 if (i.strm = t, r = i.last_flush, i.last_flush = e, i.status === z) if (2 === i.wrap) t.adler = 0, rt(i, 31), rt(i, 139), rt(i, 8), i.gzhead ? (rt(i, (i.gzhead.text ? 1 : 0) + (i.gzhead.hcrc ? 2 : 0) + (i.gzhead.extra ? 4 : 0) + (i.gzhead.name ? 8 : 0) + (i.gzhead.comment ? 16 : 0)), rt(i, 255 & i.gzhead.time), rt(i, i.gzhead.time >> 8 & 255), rt(i, i.gzhead.time >> 16 & 255), rt(i, i.gzhead.time >> 24 & 255), rt(i, 9 === i.level ? 2 : i.strategy >= w || i.level < 2 ? 4 : 0), rt(i, 255 & i.gzhead.os), i.gzhead.extra && i.gzhead.extra.length && (rt(i, 255 & i.gzhead.extra.length), rt(i, i.gzhead.extra.length >> 8 & 255)), i.gzhead.hcrc && (t.adler = s(t.adler, i.pending_buf, i.pending, 0)), i.gzindex = 0, i.status = U) : (rt(i, 0), rt(i, 0), rt(i, 0), rt(i, 0), rt(i, 0), rt(i, 9 === i.level ? 2 : i.strategy >= w || i.level < 2 ? 4 : 0), rt(i, Q), i.status = H);else { 36500 var y = A + (i.w_bits - 8 << 4) << 8; 36501 y |= (i.strategy >= w || i.level < 2 ? 0 : i.level < 6 ? 1 : 6 === i.level ? 2 : 3) << 6, 0 !== i.strstart && (y |= j), y += 31 - y % 31, i.status = H, nt(i, y), 0 !== i.strstart && (nt(i, t.adler >>> 16), nt(i, 65535 & t.adler)), t.adler = 1; 36502 } 36503 if (i.status === U) if (i.gzhead.extra) { 36504 for (a = i.pending; i.gzindex < (65535 & i.gzhead.extra.length) && (i.pending !== i.pending_buf_size || (i.gzhead.hcrc && i.pending > a && (t.adler = s(t.adler, i.pending_buf, i.pending - a, a)), tt(t), a = i.pending, i.pending !== i.pending_buf_size));
36504) rt(i, 255 & i.gzhead.extra[i.gzindex]), i.gzindex++; 36505 36506 i.gzhead.hcrc && i.pending > a && (t.adler = s(t.adler, i.pending_buf, i.pending - a, a)), i.gzindex === i.gzhead.extra.length && (i.gzindex = 0, i.status = D); 36507 } else i.status = D; 36508 if (i.status === D) if (i.gzhead.name) { 36509 a = i.pending; 36510 36511 do { 36512 if (i.pending === i.pending_buf_size && (i.gzhead.hcrc && i.pending > a && (t.adler = s(t.adler, i.pending_buf, i.pending - a, a)), tt(t), a = i.pending, i.pending === i.pending_buf_size)) { 36513 u = 1; 36514 break; 36515 } 36516 36517 u = i.gzindex < i.gzhead.name.length ? 255 & i.gzhead.name.charCodeAt(i.gzindex++) : 0, rt(i, u); 36518 } while (0 !== u); 36519 36520 i.gzhead.hcrc && i.pending > a && (t.adler = s(t.adler, i.pending_buf, i.pending - a, a)), 0 === u && (i.gzindex = 0, i.status = q); 36521 } else i.status = q; 36522 if (i.status === q) if (i.gzhead.comment) { 36523 a = i.pending; 36524 36525 do { 36526 if (i.pending === i.pending_buf_size && (i.gzhead.hcrc && i.pending > a && (t.adler = s(t.adler, i.pending_buf, i.pending - a, a)), tt(t), a = i.pending, i.pending === i.pending_buf_size)) { 36527 u = 1; 36528 break; 36529 } 36530 36531 u = i.gzindex < i.gzhead.comment.length ? 255 & i.gzhead.comment.charCodeAt(i.gzindex++) : 0, rt(i, u); 36532 } while (0 !== u); 36533 36534 i.gzhead.hcrc && i.pending > a && (t.adler = s(t.adler, i.pending_buf, i.pending - a, a)), 0 === u && (i.status = Z); 36535 } else i.status = Z; 36536 36537 if (i.status === Z && (i.gzhead.hcrc ? (i.pending + 2 > i.pending_buf_size && tt(t), i.pending + 2 <= i.pending_buf_size && (rt(i, 255 & t.adler), rt(i, t.adler >> 8 & 255), t.adler = 0, i.status = H)) : i.status = H), 0 !== i.pending) { 36538 if (tt(t), 0 === t.avail_out) return i.last_flush = -1, p; 36539 } else if (0 === t.avail_in && $(e) <= $(r) && e !== h) return X(t, m); 36540 36541 if (i.status === V && 0 !== t.avail_in) return X(t, m); 36542 36543 if (0 !== t.avail_in || 0 !== i.lookahead || e !== f && i.status !== V) { 36544 var b = i.strategy === w ? function (t, e) { 36545 for (var r;;) { 36546 if (0 === t.lookahead && (ot(t), 0 === t.lookahead)) { 36547 if (e === f) return G; 36548 break; 36549 } 36550 36551 if (t.match_length = 0, r = o._tr_tally(t, 0, t.window[t.strstart]), t.lookahead--, t.strstart++, r && (et(t, !1), 0 === t.strm.avail_out)) return G; 36552 } 36553 36554 return t.insert = 0, e === h ? (et(t, !0), 0 === t.strm.avail_out ? W : K) : t.last_lit && (et(t, !1), 0 === t.strm.avail_out) ? G : Y; 36555 }(i, e) : i.strategy === x ? function (t, e) { 36556 for (var r, n, i, a, s = t.window;;) { 36557 if (t.lookahead <= N) { 36558 if (ot(t), t.lookahead <= N && e === f) return G; 36559 if (0 === t.lookahead) break; 36560 } 36561 36562 if (t.match_length = 0, t.lookahead >= F && t.strstart > 0 && (n = s[i = t.strstart - 1]) === s[++i] && n === s[++i] && n === s[++i]) { 36563 a = t.strstart + N; 36564 36565 do {} while (n === s[++i] && n === s[++i] && n === s[++i] && n === s[++i] && n === s[++i] && n === s[++i] && n === s[++i] && n === s[++i] && i < a); 36566 36567 t.match_length = N - (a - i), t.match_length > t.lookahead && (t.match_length = t.lookahead); 36568 } 36569 36570 if (t.match_length >= F ? (r = o._tr_tally(t, 1, t.match_length - F), t.lookahead -= t.match_length, t.strstart += t.match_length, t.match_length = 0) : (r = o._tr_tally(t, 0, t.window[t.strstart]), t.lookahead--, t.strstart++), r && (et(t, !1), 0 === t.strm.avail_out)) return G; 36571 } 36572 36573 return t.insert = 0, e === h ? (et(t, !0), 0 === t.strm.avail_out ? W : K) : t.last_lit && (et(t, !1), 0 === t.strm.avail_out) ? G : Y; 36574 }(i, e) : n[i.level].func(i, e); 36575 if (b !== W && b !== K || (i.status = V), b === G || b === W) return 0 === t.avail_out && (i.last_flush = -1), p; 36576 if (b === Y && (e === c ? o._tr_align(i) : e !== d && (o._tr_stored_block(i, 0, 0, !1), e === l && (J(i.head), 0 === i.lookahead && (i.strstart = 0, i.block_start = 0, i.insert = 0))), tt(t), 0 === t.avail_out)) return i.last_flush = -1, p; 36577 } 36578 36579 return e !== h ? p : i.wrap <= 0 ? g : (2 === i.wrap ? (rt(i, 255 & t.adler), rt(i, t.adler >> 8 & 255), rt(i, t.adler >> 16 & 255), rt(i, t.adler >> 24 & 255), rt(i, 255 & t.total_in), rt(i, t.total_in >> 8 & 255), rt(i, t.total_in >> 16 & 255), rt(i, t.total_in >> 24 & 255)) : (nt(i, t.adler >>> 16), nt(i, 65535 & t.adler)), tt(t), i.wrap > 0 && (i.wrap = -i.wrap), 0 !== i.pending ? p : g); 36580 }, e.deflateEnd = function (t) { 36581 var e; 36582 return t && t.state ? (e = t.state.status) !== z && e !== U && e !== D && e !== q && e !== Z && e !== H && e !== V ? X(t, v) : (t.state = null, e === H ? X(t, y) : p) : v; 36583 }, e.deflateSetDictionary = function (t, e) { 36584 var r, 36585 n, 36586 o, 36587 s, 36588 u, 36589 f, 36590 c, 36591 l, 36592 h = e.length; 36593 if (!t || !t.state) return v; 36594 if (2 === (s = (r = t.state).wrap) || 1 === s && r.status !== z || r.lookahead) return v; 36595 36596 for (1 === s && (t.adler = a(t.adler, e, h, 0)), r.wrap = 0, h >= r.w_size && (0 === s && (J(r.head), r.strstart = 0, r.block_start = 0, r.insert = 0), l = new i.Buf8(r.w_size), i.arraySet(l, e, h - r.w_size, r.w_size, 0), e = l, h = r.w_size), u = t.avail_in, f = t.next_in, c = t.input, t.avail_in = h, t.next_in = 0, t.input = e, ot(r); r.lookahead >= F;) { 36597 n = r.strstart, o = r.lookahead - (F - 1); 36598 36599 do { 36600 r.ins_h = (r.ins_h << r.hash_shift ^ r.window[n + F - 1]) & r.hash_mask, r.prev[n & r.w_mask] = r.head[r.ins_h], r.head[r.ins_h] = n, n++; 36601 } while (--o); 36602 36603 r.strstart = n, r.lookahead = F - 1, ot(r); 36604 } 36605 36606 return r.strstart += r.lookahead, r.block_start = r.strstart, r.insert = r.lookahead, r.lookahead = 0, r.match_length = r.prev_length = F - 1, r.match_available = 0, t.next_in = f, t.input = c, t.avail_in = u, r.wrap = s, p; 36607 }, e.deflateInfo = "pako deflate (from Nodeca project)"; 36608 }, function (t, e, r) { 36609 36610 var n = r(72), 36611 i = 4, 36612 o = 0, 36613 a = 1, 36614 s = 2; 36615 36616 function u(t) { 36617 for (var e = t.length; --e >= 0;) t[e] = 0; 36618 } 36619 36620 var f = 0, 36621 c = 1, 36622 l = 2, 36623 h = 29, 36624 d = 256, 36625 p = d + 1 + h, 36626 g = 30, 36627 v = 19, 36628 y = 2 * p + 1, 36629 m = 15, 36630 b = 16, 36631 _ = 7, 36632 w = 256, 36633 x = 16, 36634 E = 17, 36635 S = 18, 36636 k = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0], 36637 A = [0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13], 36638 C = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 7], 36639 T = [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15], 36640 R = new Array(2 * (p + 2)); 36641 u(R); 36642 var O = new Array(2 * g); 36643 u(O); 36644 var I = new Array(512); 36645 u(I); 36646 var L = new Array(256); 36647 u(L); 36648 var B = new Array(h); 36649 u(B); 36650 var P, 36651 F, 36652 N, 36653 M = new Array(g); 36654 36655 function j(t, e, r, n, i) { 36656 this.static_tree = t, this.extra_bits = e, this.extra_base = r, this.elems = n, this.max_length = i, this.has_stree = t && t.length; 36657 } 36658 36659 function z(t, e) { 36660 this.dyn_tree = t, this.max_code = 0, this.stat_desc = e; 36661 } 36662 36663 function U(t) { 36664 return t < 256 ? I[t] : I[256 + (t >>> 7)]; 36665 } 36666 36667 function D(t, e) { 36668 t.pending_buf[t.pending++] = 255 & e, t.pending_buf[t.pending++] = e >>> 8 & 255; 36669 } 36670 36671 function q(t, e, r) { 36672 t.bi_valid > b - r ? (t.bi_buf |= e << t.bi_valid & 65535, D(t, t.bi_buf), t.bi_buf = e >> b - t.bi_valid, t.bi_valid += r - b) : (t.bi_buf |= e << t.bi_valid & 65535, t.bi_valid += r); 36673 } 36674 36675 function Z(t, e, r) { 36676 q(t, r[2 * e], r[2 * e + 1]); 36677 } 36678 36679 function H(t, e) { 36680 var r = 0; 36681 36682 do { 36683 r |= 1 & t, t >>>= 1, r <<= 1; 36684 } while (--e > 0); 36685 36686 return r >>> 1; 36687 } 36688 36689 function V(t, e, r) { 36690 var n, 36691 i, 36692 o = new Array(m + 1), 36693 a = 0; 36694 36695 for (n = 1; n <= m; n++) o[n] = a = a + r[n - 1] << 1; 36696 36697 for (i = 0; i <= e; i++) { 36698 var s = t[2 * i + 1]; 36699 0 !== s && (t[2 * i] = H(o[s]++, s)); 36700 } 36701 } 36702 36703 function G(t) { 36704 var e; 36705 36706 for (e = 0; e < p; e++) t.dyn_ltree[2 * e] = 0; 36707 36708 for (e = 0; e < g; e++) t.dyn_dtree[2 * e] = 0; 36709 36710 for (e = 0; e < v; e++) t.bl_tree[2 * e] = 0; 36711 36712 t.dyn_ltree[2 * w] = 1, t.opt_len = t.static_len = 0, t.last_lit = t.matches = 0; 36713 } 36714 36715 function Y(t) { 36716 t.bi_valid > 8 ? D(t, t.bi_buf) : t.bi_valid >
36716 0 && (t.pending_buf[t.pending++] = t.bi_buf), t.bi_buf = 0, t.bi_valid = 0; 36717 } 36718 36719 function W(t, e, r, n) { 36720 var i = 2 * e, 36721 o = 2 * r; 36722 return t[i] < t[o] || t[i] === t[o] && n[e] <= n[r]; 36723 } 36724 36725 function K(t, e, r) { 36726 for (var n = t.heap[r], i = r << 1; i <= t.heap_len && (i < t.heap_len && W(e, t.heap[i + 1], t.heap[i], t.depth) && i++, !W(e, n, t.heap[i], t.depth));) t.heap[r] = t.heap[i], r = i, i <<= 1; 36727 36728 t.heap[r] = n; 36729 } 36730 36731 function Q(t, e, r) { 36732 var n, 36733 i, 36734 o, 36735 a, 36736 s = 0; 36737 if (0 !== t.last_lit) do { 36738 n = t.pending_buf[t.d_buf + 2 * s] << 8 | t.pending_buf[t.d_buf + 2 * s + 1], i = t.pending_buf[t.l_buf + s], s++, 0 === n ? Z(t, i, e) : (Z(t, (o = L[i]) + d + 1, e), 0 !== (a = k[o]) && q(t, i -= B[o], a), Z(t, o = U(--n), r), 0 !== (a = A[o]) && q(t, n -= M[o], a)); 36739 } while (s < t.last_lit); 36740 Z(t, w, e); 36741 } 36742 36743 function X(t, e) { 36744 var r, 36745 n, 36746 i, 36747 o = e.dyn_tree, 36748 a = e.stat_desc.static_tree, 36749 s = e.stat_desc.has_stree, 36750 u = e.stat_desc.elems, 36751 f = -1; 36752 36753 for (t.heap_len = 0, t.heap_max = y, r = 0; r < u; r++) 0 !== o[2 * r] ? (t.heap[++t.heap_len] = f = r, t.depth[r] = 0) : o[2 * r + 1] = 0; 36754 36755 for (; t.heap_len < 2;) o[2 * (i = t.heap[++t.heap_len] = f < 2 ? ++f : 0)] = 1, t.depth[i] = 0, t.opt_len--, s && (t.static_len -= a[2 * i + 1]); 36756 36757 for (e.max_code = f, r = t.heap_len >> 1; r >= 1; r--) K(t, o, r); 36758 36759 i = u; 36760 36761 do { 36762 r = t.heap[1], t.heap[1] = t.heap[t.heap_len--], K(t, o, 1), n = t.heap[1], t.heap[--t.heap_max] = r, t.heap[--t.heap_max] = n, o[2 * i] = o[2 * r] + o[2 * n], t.depth[i] = (t.depth[r] >= t.depth[n] ? t.depth[r] : t.depth[n]) + 1, o[2 * r + 1] = o[2 * n + 1] = i, t.heap[1] = i++, K(t, o, 1); 36763 } while (t.heap_len >= 2); 36764 36765 t.heap[--t.heap_max] = t.heap[1], function (t, e) { 36766 var r, 36767 n, 36768 i, 36769 o, 36770 a, 36771 s, 36772 u = e.dyn_tree, 36773 f = e.max_code, 36774 c = e.stat_desc.static_tree, 36775 l = e.stat_desc.has_stree, 36776 h = e.stat_desc.extra_bits, 36777 d = e.stat_desc.extra_base, 36778 p = e.stat_desc.max_length, 36779 g = 0; 36780 36781 for (o = 0; o <= m; o++) t.bl_count[o] = 0; 36782 36783 for (u[2 * t.heap[t.heap_max] + 1] = 0, r = t.heap_max + 1; r < y; r++) (o = u[2 * u[2 * (n = t.heap[r]) + 1] + 1] + 1) > p && (o = p, g++), u[2 * n + 1] = o, n > f || (t.bl_count[o]++, a = 0, n >= d && (a = h[n - d]), s = u[2 * n], t.opt_len += s * (o + a), l && (t.static_len += s * (c[2 * n + 1] + a))); 36784 36785 if (0 !== g) { 36786 do { 36787 for (o = p - 1; 0 === t.bl_count[o];) o--; 36788 36789 t.bl_count[o]--, t.bl_count[o + 1] += 2, t.bl_count[p]--, g -= 2; 36790 } while (g > 0); 36791 36792 for (o = p; 0 !== o; o--) for (n = t.bl_count[o]; 0 !== n;) (i = t.heap[--r]) > f || (u[2 * i + 1] !== o && (t.opt_len += (o - u[2 * i + 1]) * u[2 * i], u[2 * i + 1] = o), n--); 36793 } 36794 }(t, e), V(o, f, t.bl_count); 36795 } 36796 36797 function $(t, e, r) { 36798 var n, 36799 i, 36800 o = -1, 36801 a = e[1], 36802 s = 0, 36803 u = 7, 36804 f = 4; 36805 36806 for (0 === a && (u = 138, f = 3), e[2 * (r + 1) + 1] = 65535, n = 0; n <= r; n++) i = a, a = e[2 * (n + 1) + 1], ++s < u && i === a || (s < f ? t.bl_tree[2 * i] += s : 0 !== i ? (i !== o && t.bl_tree[2 * i]++, t.bl_tree[2 * x]++) : s <= 10 ? t.bl_tree[2 * E]++ : t.bl_tree[2 * S]++, s = 0, o = i, 0 === a ? (u = 138, f = 3) : i === a ? (u = 6, f = 3) : (u = 7, f = 4)); 36807 } 36808 36809 function J(t, e, r) { 36810 var n, 36811 i, 36812 o = -1, 36813 a = e[1], 36814 s = 0, 36815 u = 7, 36816 f = 4; 36817 36818 for (0 === a && (u = 138, f = 3), n = 0; n <= r; n++) if (i = a, a = e[2 * (n + 1) + 1], !(++s < u && i === a)) { 36819 if (s < f) do { 36820 Z(t, i, t.bl_tree); 36821 } while (0 != --s);else 0 !== i ? (i !== o && (Z(t, i, t.bl_tree), s--), Z(t, x, t.bl_tree), q(t, s - 3, 2)) : s <= 10 ? (Z(t, E, t.bl_tree), q(t, s - 3, 3)) : (Z(t, S, t.bl_tree), q(t, s - 11, 7)); 36822 s = 0, o = i, 0 === a ? (u = 138, f = 3) : i === a ? (u = 6, f = 3) : (u = 7, f = 4); 36823 } 36824 } 36825 36826 u(M); 36827 var tt = !1; 36828 36829 function et(t, e, r, i) { 36830 q(t, (f << 1) + (i ? 1 : 0), 3), function (t, e, r, i) { 36831 Y(t), i && (D(t, r), D(t, ~r)), n.arraySet(t.pending_buf, t.window, e, r, t.pending), t.pending += r; 36832 }(t, e, r, !0); 36833 } 36834 36835 e._tr_init = function (t) { 36836 tt || (!function () { 36837 var t, 36838 e, 36839 r, 36840 n, 36841 i, 36842 o = new Array(m + 1); 36843 36844 for (r = 0, n = 0; n < h - 1; n++) for (B[n] = r, t = 0; t < 1 << k[n]; t++) L[r++] = n; 36845 36846 for (L[r - 1] = n, i = 0, n = 0; n < 16; n++) for (M[n] = i, t = 0; t < 1 << A[n]; t++) I[i++] = n; 36847 36848 for (i >>= 7; n < g; n++) for (M[n] = i << 7, t = 0; t < 1 << A[n] - 7; t++) I[256 + i++] = n; 36849 36850 for (e = 0; e <= m; e++) o[e] = 0; 36851 36852 for (t = 0; t <= 143;) R[2 * t + 1] = 8, t++, o[8]++; 36853 36854 for (; t <= 255;) R[2 * t + 1] = 9, t++, o[9]++; 36855 36856 for (; t <= 279;) R[2 * t + 1] = 7, t++, o[7]++; 36857 36858 for (; t <= 287;) R[2 * t + 1] = 8, t++, o[8]++; 36859 36860 for (V(R, p + 1, o), t = 0; t < g; t++) O[2 * t + 1] = 5, O[2 * t] = H(t, 5); 36861 36862 P = new j(R, k, d + 1, p, m), F = new j(O, A, 0, g, m), N = new j(new Array(0), C, 0, v, _); 36863 }(), tt = !0), t.l_desc = new z(t.dyn_ltree, P), t.d_desc = new z(t.dyn_dtree, F), t.bl_desc = new z(t.bl_tree, N), t.bi_buf = 0, t.bi_valid = 0, G(t); 36864 }, e._tr_stored_block = et, e._tr_flush_block = function (t, e, r, n) { 36865 var u, 36866 f, 36867 h = 0; 36868 t.level > 0 ? (t.strm.data_type === s && (t.strm.data_type = function (t) { 36869 var e, 36870 r = 4093624447; 36871 36872 for (e = 0; e <= 31; e++, r >>>= 1) if (1 & r && 0 !== t.dyn_ltree[2 * e]) return o; 36873 36874 if (0 !== t.dyn_ltree[18] || 0 !== t.dyn_ltree[20] || 0 !== t.dyn_ltree[26]) return a; 36875 36876 for (e = 32; e < d; e++) if (0 !== t.dyn_ltree[2 * e]) return a; 36877 36878 return o; 36879 }
36879(t)), X(t, t.l_desc), X(t, t.d_desc), h = function (t) { 36880 var e; 36881 36882 for ($(t, t.dyn_ltree, t.l_desc.max_code), $(t, t.dyn_dtree, t.d_desc.max_code), X(t, t.bl_desc), e = v - 1; e >= 3 && 0 === t.bl_tree[2 * T[e] + 1]; e--); 36883 36884 return t.opt_len += 3 * (e + 1) + 5 + 5 + 4, e; 36885 }(t), u = t.opt_len + 3 + 7 >>> 3, (f = t.static_len + 3 + 7 >>> 3) <= u && (u = f)) : u = f = r + 5, r + 4 <= u && -1 !== e ? et(t, e, r, n) : t.strategy === i || f === u ? (q(t, (c << 1) + (n ? 1 : 0), 3), Q(t, R, O)) : (q(t, (l << 1) + (n ? 1 : 0), 3), function (t, e, r, n) { 36886 var i; 36887 36888 for (q(t, e - 257, 5), q(t, r - 1, 5), q(t, n - 4, 4), i = 0; i < n; i++) q(t, t.bl_tree[2 * T[i] + 1], 3); 36889 36890 J(t, t.dyn_ltree, e - 1), J(t, t.dyn_dtree, r - 1); 36891 }(t, t.l_desc.max_code + 1, t.d_desc.max_code + 1, h + 1), Q(t, t.dyn_ltree, t.dyn_dtree)), G(t), n && Y(t); 36892 }, e._tr_tally = function (t, e, r) { 36893 return t.pending_buf[t.d_buf + 2 * t.last_lit] = e >>> 8 & 255, t.pending_buf[t.d_buf + 2 * t.last_lit + 1] = 255 & e, t.pending_buf[t.l_buf + t.last_lit] = 255 & r, t.last_lit++, 0 === e ? t.dyn_ltree[2 * r]++ : (t.matches++, e--, t.dyn_ltree[2 * (L[r] + d + 1)]++, t.dyn_dtree[2 * U(e)]++), t.last_lit === t.lit_bufsize - 1; 36894 }, e._tr_align = function (t) { 36895 q(t, c << 1, 3), Z(t, w, R), function (t) { 36896 16 === t.bi_valid ? (D(t, t.bi_buf), t.bi_buf = 0, t.bi_valid = 0) : t.bi_valid >= 8 && (t.pending_buf[t.pending++] = 255 & t.bi_buf, t.bi_buf >>= 8, t.bi_valid -= 8); 36897 }(t); 36898 }; 36899 }, function (t, e, r) { 36900 36901 t.exports = { 36902 2: "need dictionary", 36903 1: "stream end", 36904 0: "", 36905 "-1": "file error", 36906 "-2": "stream error", 36907 "-3": "data error", 36908 "-4": "insufficient memory", 36909 "-5": "buffer error", 36910 "-6": "incompatible version" 36911 }; 36912 }, function (t, e, r) { 36913 36914 var n = r(72), 36915 i = r(134), 36916 o = r(135), 36917 a = r(221), 36918 s = r(222), 36919 u = 0, 36920 f = 1, 36921 c = 2, 36922 l = 4, 36923 h = 5, 36924 d = 6, 36925 p = 0, 36926 g = 1, 36927 v = 2, 36928 y = -2, 36929 m = -3, 36930 b = -4, 36931 _ = -5, 36932 w = 8, 36933 x = 1, 36934 E = 2, 36935 S = 3, 36936 k = 4, 36937 A = 5, 36938 C = 6, 36939 T = 7, 36940 R = 8, 36941 O = 9, 36942 I = 10, 36943 L = 11, 36944 B = 12, 36945 P = 13, 36946 F = 14, 36947 N = 15, 36948 M = 16, 36949 j = 17, 36950 z = 18, 36951 U = 19, 36952 D = 20, 36953 q = 21, 36954 Z = 22, 36955 H = 23, 36956 V = 24, 36957 G = 25, 36958 Y = 26, 36959 W = 27, 36960 K = 28, 36961 Q = 29, 36962 X = 30, 36963 $ = 31, 36964 J = 32, 36965 tt = 852, 36966 et = 592, 36967 rt = 15; 36968 36969 function nt(t) { 36970 return (t >>> 24 & 255) + (t >>> 8 & 65280) + ((65280 & t) << 8) + ((255 & t) << 24); 36971 } 36972 36973 function it() { 36974 this.mode = 0, this.last = !1, this.wrap = 0, this.havedict = !1, this.flags = 0, this.dmax = 0, this.check = 0, this.total = 0, this.head = null, this.wbits = 0, this.wsize = 0, this.whave = 0, this.wnext = 0, this.window = null, this.hold = 0, this.bits = 0, this.length = 0, this.offset = 0, this.extra = 0, this.lencode = null, this.distcode = null, this.lenbits = 0, this.distbits = 0, this.ncode = 0, this.nlen = 0, this.ndist = 0, this.have = 0, this.next = null, this.lens = new n.Buf16(320), this.work = new n.Buf16(288), this.lendyn = null, this.distdyn = null, this.sane = 0, this.back = 0, this.was = 0; 36975 } 36976 36977 function ot(t) { 36978 var e; 36979 return t && t.state ? (e = t.state, t.total_in = t.total_out = e.total = 0, t.msg = "", e.wrap && (t.adler = 1 & e.wrap), e.mode = x, e.last = 0, e.havedict = 0, e.dmax = 32768, e.head = null, e.hold = 0, e.bits = 0, e.lencode = e.lendyn = new n.Buf32(tt), e.distcode = e.distdyn = new n.Buf32(et), e.sane = 1, e.back = -1, p) : y; 36980 } 36981 36982 function at(t) { 36983 var e; 36984 return t && t.state ? ((e = t.state).wsize = 0, e.whave = 0, e.wnext = 0, ot(t)) : y; 36985 } 36986 36987 function st(t, e) { 36988 var r, n; 36989 return t && t.state ? (n = t.state, e < 0 ? (r = 0, e = -e) : (r = 1 + (e >> 4), e < 48 && (e &= 15)), e && (e < 8 || e > 15) ? y : (null !== n.window && n.wbits !== e && (n.window = null), n.wrap = r, n.wbits = e, at(t))) : y; 36990 } 36991 36992 function ut(t, e) { 36993 var r, n; 36994 return t ? (n = new it(), t.state = n, n.window = null, (r = st(t, e)) !== p && (t.state = null), r) : y; 36995 } 36996 36997 var ft, 36998 ct, 36999 lt = !0; 37000 37001 function ht(t) { 37002 if (lt) { 37003 var e; 37004 37005 for (ft = new n.Buf32(512), ct = new n.Buf32(32), e = 0; e < 144;) t.lens[e++] = 8; 37006 37007 for (; e < 256;) t.lens[e++] = 9; 37008 37009 for (; e < 280;) t.lens[e++] = 7; 37010 37011 for (; e < 288;) t.lens[e++] = 8; 37012 37013 for (s(f, t.lens, 0, 288, ft, 0, t.work, { 37014 bits: 9 37015 }), e = 0; e < 32;) t.lens[e++] = 5; 37016 37017 s(c, t.lens, 0, 32, ct, 0, t.work, { 37018 bits: 5 37019 }), lt = !1; 37020 } 37021 37022 t.lencode = ft, t.lenbits = 9, t.distcode = ct, t.distbits = 5; 37023 } 37024 37025 function dt(t, e, r, i) { 37026 var o, 37027 a = t.state; 37028 return null === a.window && (a.wsize = 1 << a.wbits, a.wnext = 0, a.whave = 0, a.window = new n.Buf8(a.wsize)), i >= a.wsize ? (n.arraySet(a.window, e, r - a.wsize, a.wsize, 0), a.wnext = 0, a.whave = a.wsize) : ((o = a.wsize - a.wnext) > i && (o = i), n.arraySet(a.window, e, r - i, o, a.wnext), (i -= o) ? (n.arraySet(a.window, e, r - i, i, 0), a.wnext = i, a.whave = a.wsize) : (a.wnext += o, a.wnext === a.wsize && (a.wnext = 0), a.whave < a.wsize && (a.whave += o))), 0; 37029 } 37030 37031 e.inflateReset = at, e.inflateReset2 = st, e.inflateResetKeep = ot, e.inflateInit = function (t) { 37032 return ut(t, rt); 37033 }, e.inflateInit2 = ut, e.inflate = function (t, e) { 37034 var r, 37035 tt, 37036 et, 37037 rt, 37038 it, 37039 ot, 37040 at, 37041 st, 37042 ut, 37043 ft, 37044 ct, 37045 lt, 37046 pt, 37047 gt, 37048 vt, 37049 yt, 37050 mt, 37051 bt, 37052 _t, 37053 wt, 37054 xt, 37055 Et, 37056 St, 37057 kt, 37058 At = 0, 37059 Ct = new n.Buf8(4), 37060 Tt = [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]; 37061 37062 if (!t || !t.state || !t.output || !t.input && 0 !== t.avail_in) return y; 37063 (r = t.state).mode === B && (r.mode = P), it = t.next_out, et = t.output, at = t.avail_out, rt = t.next_in, tt = t.input, ot = t.avail_in, st = r.hold, ut = r.bits, ft = ot, ct = at, Et = p; 37064 37065 t: for (;;) switch (r.mode) { 37066 case x: 37067 if (0 === r.wrap) { 37068 r.mode = P; 37069 break; 37070 } 37071 37072 for (; ut < 16;) { 37073 if (0 === ot) break t; 37074 ot--, st += tt[rt++] << ut, ut += 8; 37075 } 37076 37077 if (2 & r.wrap && 35615 === st) {
37078 r.check = 0, Ct[0] = 255 & st, Ct[1] = st >>> 8 & 255, r.check = o(r.check, Ct, 2, 0), st = 0, ut = 0, r.mode = E; 37079 break; 37080 } 37081 37082 if (r.flags = 0, r.head && (r.head.done = !1), !(1 & r.wrap) || (((255 & st) << 8) + (st >> 8)) % 31) { 37083 t.msg = "incorrect header check", r.mode = X; 37084 break; 37085 } 37086 37087 if ((15 & st) !== w) { 37088 t.msg = "unknown compression method", r.mode = X; 37089 break; 37090 } 37091 37092 if (ut -= 4, xt = 8 + (15 & (st >>>= 4)), 0 === r.wbits) r.wbits = xt;else if (xt > r.wbits) { 37093 t.msg = "invalid window size", r.mode = X; 37094 break; 37095 } 37096 r.dmax = 1 << xt, t.adler = r.check = 1, r.mode = 512 & st ? I : B, st = 0, ut = 0; 37097 break; 37098 37099 case E: 37100 for (; ut < 16;) { 37101 if (0 === ot) break t; 37102 ot--, st += tt[rt++] << ut, ut += 8; 37103 } 37104 37105 if (r.flags = st, (255 & r.flags) !== w) { 37106 t.msg = "unknown compression method", r.mode = X; 37107 break; 37108 } 37109 37110 if (57344 & r.flags) { 37111 t.msg = "unknown header flags set", r.mode = X; 37112 break; 37113 } 37114 37115 r.head && (r.head.text = st >> 8 & 1), 512 & r.flags && (Ct[0] = 255 & st, Ct[1] = st >>> 8 & 255, r.check = o(r.check, Ct, 2, 0)), st = 0, ut = 0, r.mode = S; 37116 37117 case S: 37118 for (; ut < 32;) { 37119 if (0 === ot) break t; 37120 ot--, st += tt[rt++] << ut, ut += 8; 37121 } 37122 37123 r.head && (r.head.time = st), 512 & r.flags && (Ct[0] = 255 & st, Ct[1] = st >>> 8 & 255, Ct[2] = st >>> 16 & 255, Ct[3] = st >>> 24 & 255, r.check = o(r.check, Ct, 4, 0)), st = 0, ut = 0, r.mode = k; 37124 37125 case k: 37126 for (; ut < 16;) { 37127 if (0 === ot) break t; 37128 ot--, st += tt[rt++] << ut, ut += 8; 37129 } 37130 37131 r.head && (r.head.xflags = 255 & st, r.head.os = st >> 8), 512 & r.flags && (Ct[0] = 255 & st, Ct[1] = st >>> 8 & 255, r.check = o(r.check, Ct, 2, 0)), st = 0, ut = 0, r.mode = A; 37132 37133 case A: 37134 if (1024 & r.flags) { 37135 for (; ut < 16;) { 37136 if (0 === ot) break t; 37137 ot--, st += tt[rt++] << ut, ut += 8; 37138 } 37139 37140 r.length = st, r.head && (r.head.extra_len = st), 512 & r.flags && (Ct[0] = 255 & st, Ct[1] = st >>> 8 & 255, r.check = o(r.check, Ct, 2, 0)), st = 0, ut = 0; 37141 } else r.head && (r.head.extra = null); 37142 37143 r.mode = C; 37144 37145 case C: 37146 if (1024 & r.flags && ((lt = r.length) > ot && (lt = ot), lt && (r.head && (xt = r.head.extra_len - r.length, r.head.extra || (r.head.extra = new Array(r.head.extra_len)), n.arraySet(r.head.extra, tt, rt, lt, xt)), 512 & r.flags && (r.check = o(r.check, tt, lt, rt)), ot -= lt, rt += lt, r.length -= lt), r.length)) break t; 37147 r.length = 0, r.mode = T; 37148 37149 case T: 37150 if (2048 & r.flags) { 37151 if (0 === ot) break t; 37152 lt = 0; 37153 37154 do { 37155 xt = tt[rt + lt++], r.head && xt && r.length < 65536 && (r.head.name += String.fromCharCode(xt)); 37156 } while (xt && lt < ot); 37157 37158 if (512 & r.flags && (r.check = o(r.check, tt, lt, rt)), ot -= lt, rt += lt, xt) break t; 37159 } else r.head && (r.head.name = null); 37160 37161 r.length = 0, r.mode = R; 37162 37163 case R: 37164 if (4096 & r.flags) { 37165 if (0 === ot) break t; 37166 lt = 0; 37167 37168 do { 37169 xt = tt[rt + lt++], r.head && xt && r.length < 65536 && (r.head.comment += String.fromCharCode(xt)); 37170 } while (xt && lt < ot); 37171 37172 if (512 & r.flags && (r.check = o(r.check, tt, lt, rt)), ot -= lt, rt += lt, xt) break t; 37173 } else r.head && (r.head.comment = null); 37174 37175 r.mode = O; 37176 37177 case O: 37178 if (512 & r.flags) { 37179 for (; ut < 16;) { 37180 if (0 === ot) break t; 37181 ot--, st += tt[rt++] << ut, ut += 8; 37182 } 37183 37184 if (st !== (65535 & r.check)) { 37185 t.msg = "header crc mismatch", r.mode = X; 37186 break; 37187 } 37188 37189 st = 0, ut = 0; 37190 } 37191 37192 r.head && (r.head.hcrc = r.flags >>
37192 9 & 1, r.head.done = !0), t.adler = r.check = 0, r.mode = B; 37193 break; 37194 37195 case I: 37196 for (; ut < 32;) { 37197 if (0 === ot) break t; 37198 ot--, st += tt[rt++] << ut, ut += 8; 37199 } 37200 37201 t.adler = r.check = nt(st), st = 0, ut = 0, r.mode = L; 37202 37203 case L: 37204 if (0 === r.havedict) return t.next_out = it, t.avail_out = at, t.next_in = rt, t.avail_in = ot, r.hold = st, r.bits = ut, v; 37205 t.adler = r.check = 1, r.mode = B; 37206 37207 case B: 37208 if (e === h || e === d) break t; 37209 37210 case P: 37211 if (r.last) { 37212 st >>>= 7 & ut, ut -= 7 & ut, r.mode = W; 37213 break; 37214 } 37215 37216 for (; ut < 3;) { 37217 if (0 === ot) break t; 37218 ot--, st += tt[rt++] << ut, ut += 8; 37219 } 37220 37221 switch (r.last = 1 & st, ut -= 1, 3 & (st >>>= 1)) { 37222 case 0: 37223 r.mode = F; 37224 break; 37225 37226 case 1: 37227 if (ht(r), r.mode = D, e === d) { 37228 st >>>= 2, ut -= 2; 37229 break t; 37230 } 37231 37232 break; 37233 37234 case 2: 37235 r.mode = j; 37236 break; 37237 37238 case 3: 37239 t.msg = "invalid block type", r.mode = X; 37240 } 37241 37242 st >>>= 2, ut -= 2; 37243 break; 37244 37245 case F: 37246 for (st >>>= 7 & ut, ut -= 7 & ut; ut < 32;) { 37247 if (0 === ot) break t; 37248 ot--, st += tt[rt++] << ut, ut += 8; 37249 } 37250 37251 if ((65535 & st) != (st >>> 16 ^ 65535)) { 37252 t.msg = "invalid stored block lengths", r.mode = X; 37253 break; 37254 } 37255 37256 if (r.length = 65535 & st, st = 0, ut = 0, r.mode = N, e === d) break t; 37257 37258 case N: 37259 r.mode = M; 37260 37261 case M: 37262 if (lt = r.length) { 37263 if (lt > ot && (lt = ot), lt > at && (lt = at), 0 === lt) break t; 37264 n.arraySet(et, tt, rt, lt, it), ot -= lt, rt += lt, at -= lt, it += lt, r.length -= lt; 37265 break; 37266 } 37267 37268 r.mode = B; 37269 break; 37270 37271 case j: 37272 for (; ut < 14;) { 37273 if (0 === ot) break t; 37274 ot--, st += tt[rt++] << ut, ut += 8; 37275 } 37276 37277 if (r.nlen = 257 + (31 & st), st >>>= 5, ut -= 5, r.ndist = 1 + (31 & st), st >>>= 5, ut -= 5, r.ncode = 4 + (15 & st), st >>>= 4, ut -= 4, r.nlen > 286 || r.ndist > 30) { 37278 t.msg = "too many length or distance symbols", r.mode = X; 37279 break; 37280 } 37281 37282 r.have = 0, r.mode = z; 37283 37284 case z: 37285 for (; r.have < r.ncode;) { 37286 for (; ut < 3;) { 37287 if (0 === ot) break t; 37288 ot--, st += tt[rt++] << ut, ut += 8; 37289 } 37290 37291 r.lens[Tt[r.have++]] = 7 & st, st >>>= 3, ut -= 3; 37292 } 37293 37294 for (; r.have < 19;) r.lens[Tt[r.have++]] = 0; 37295 37296 if (r.lencode = r.lendyn, r.lenbits = 7, St = { 37297 bits: r.lenbits 37298 }, Et = s(u, r.lens, 0, 19, r.lencode, 0, r.work, St), r.lenbits = St.bits, Et) { 37299 t.msg = "invalid code lengths set", r.mode = X; 37300 break; 37301 } 37302 37303 r.have = 0, r.mode = U; 37304 37305 case U: 37306 for (; r.have < r.nlen + r.ndist;) { 37307 for (; yt = (At = r.lencode[st & (1 << r.lenbits) - 1]) >>> 16 & 255, mt = 65535 & At, !((vt = At >>> 24) <= ut);) { 37308 if (0 === ot) break t; 37309 ot--, st += tt[rt++] << ut, ut += 8; 37310 } 37311 37312 if (mt < 16) st >>>= vt, ut -= vt, r.lens[r.have++] = mt;else { 37313 if (16 === mt) { 37314 for (kt = vt + 2; ut < kt;) { 37315 if (0 === ot) break t; 37316 ot--, st += tt[rt++] << ut, ut += 8; 37317 } 37318 37319 if (st >>>= vt, ut -= vt, 0 === r.have) { 37320 t.msg = "invalid bit length repeat", r.mode = X; 37321 break; 37322 } 37323 37324 xt = r.lens[r.have - 1], lt = 3 + (3 & st), st >>>= 2, ut -= 2; 37325 }
37325 else if (17 === mt) { 37326 for (kt = vt + 3; ut < kt;) { 37327 if (0 === ot) break t; 37328 ot--, st += tt[rt++] << ut, ut += 8; 37329 } 37330 37331 ut -= vt, xt = 0, lt = 3 + (7 & (st >>>= vt)), st >>>= 3, ut -= 3; 37332 } else { 37333 for (kt = vt + 7; ut < kt;) { 37334 if (0 === ot) break t; 37335 ot--, st += tt[rt++] << ut, ut += 8; 37336 } 37337 37338 ut -= vt, xt = 0, lt = 11 + (127 & (st >>>= vt)), st >>>= 7, ut -= 7; 37339 } 37340 37341 if (r.have + lt > r.nlen + r.ndist) { 37342 t.msg = "invalid bit length repeat", r.mode = X; 37343 break; 37344 } 37345 37346 for (; lt--;) r.lens[r.have++] = xt; 37347 } 37348 } 37349 37350 if (r.mode === X) break; 37351 37352 if (0 === r.lens[256]) { 37353 t.msg = "invalid code -- missing end-of-block", r.mode = X; 37354 break; 37355 } 37356 37357 if (r.lenbits = 9, St = { 37358 bits: r.lenbits 37359 }, Et = s(f, r.lens, 0, r.nlen, r.lencode, 0, r.work, St), r.lenbits = St.bits, Et) { 37360 t.msg = "invalid literal/lengths set", r.mode = X; 37361 break; 37362 } 37363 37364 if (r.distbits = 6, r.distcode = r.distdyn, St = { 37365 bits: r.distbits 37366 }, Et = s(c, r.lens, r.nlen, r.ndist, r.distcode, 0, r.work, St), r.distbits = St.bits, Et) { 37367 t.msg = "invalid distances set", r.mode = X; 37368 break; 37369 } 37370 37371 if (r.mode = D, e === d) break t; 37372 37373 case D: 37374 r.mode = q; 37375 37376 case q: 37377 if (ot >= 6 && at >= 258) { 37378 t.next_out = it, t.avail_out = at, t.next_in = rt, t.avail_in = ot, r.hold = st, r.bits = ut, a(t, ct), it = t.next_out, et = t.output, at = t.avail_out, rt = t.next_in, tt = t.input, ot = t.avail_in, st = r.hold, ut = r.bits, r.mode === B && (r.back = -1); 37379 break; 37380 } 37381 37382 for (r.back = 0; yt = (At = r.lencode[st & (1 << r.lenbits) - 1]) >>> 16 & 255, mt = 65535 & At, !((vt = At >>> 24) <= ut);) { 37383 if (0 === ot) break t; 37384 ot--, st += tt[rt++] << ut, ut += 8; 37385 } 37386 37387 if (yt && 0 == (240 & yt)) { 37388 for (bt = vt, _t = yt, wt = mt; yt = (At = r.lencode[wt + ((st & (1 << bt + _t) - 1) >> bt)]) >>> 16 & 255, mt = 65535 & At, !(bt + (vt = At >>> 24) <= ut);) { 37389 if (0 === ot) break t; 37390 ot--, st += tt[rt++] << ut, ut += 8; 37391 } 37392 37393 st >>>= bt, ut -= bt, r.back += bt; 37394 } 37395 37396 if (st >>>= vt, ut -= vt, r.back += vt, r.length = mt, 0 === yt) { 37397 r.mode = Y; 37398 break; 37399 } 37400 37401 if (32 & yt) { 37402 r.back = -1, r.mode = B; 37403 break; 37404 } 37405 37406 if (64 & yt) { 37407 t.msg = "invalid literal/length code", r.mode = X; 37408 break; 37409 } 37410 37411 r.extra = 15 & yt, r.mode = Z; 37412 37413 case Z: 37414 if (r.extra) { 37415 for (kt = r.extra; ut < kt;) { 37416 if (0 === ot) break t; 37417 ot--, st += tt[rt++] << ut, ut += 8; 37418 } 37419 37420 r.length += st & (1 << r.extra) - 1, st >>>= r.extra, ut -= r.extra, r.back += r.extra; 37421 } 37422 37423 r.was = r.length, r.mode = H; 37424 37425 case H: 37426 for (; yt = (At = r.distcode[st & (1 << r.distbits) - 1]) >>> 16 & 255, mt = 65535 & At, !((vt = At >>> 24) <= ut);) { 37427 if (0 === ot) break t; 37428 ot--, st += tt[rt++] << ut, ut += 8; 37429 } 37430 37431 if (0 == (240 & yt)) { 37432 for (bt = vt, _t = yt, wt = mt; yt = (At = r.distcode[wt + ((st & (1 << bt + _t) - 1) >> bt)]) >>> 16 & 255, mt = 65535 & At, !(bt + (vt = At >>> 24) <= ut);) { 37433 if (0 === ot) break t; 37434 ot--, st += tt[rt++] << ut, ut += 8; 37435 } 37436 37437 st >>>= bt, ut -= bt, r.back += bt; 37438 } 37439 37440 if (st >>>= vt, ut -= vt, r.back += vt, 64 & yt) {
37441 t.msg = "invalid distance code", r.mode = X; 37442 break; 37443 } 37444 37445 r.offset = mt, r.extra = 15 & yt, r.mode = V; 37446 37447 case V: 37448 if (r.extra) { 37449 for (kt = r.extra; ut < kt;) { 37450 if (0 === ot) break t; 37451 ot--, st += tt[rt++] << ut, ut += 8; 37452 } 37453 37454 r.offset += st & (1 << r.extra) - 1, st >>>= r.extra, ut -= r.extra, r.back += r.extra; 37455 } 37456 37457 if (r.offset > r.dmax) { 37458 t.msg = "invalid distance too far back", r.mode = X; 37459 break; 37460 } 37461 37462 r.mode = G; 37463 37464 case G: 37465 if (0 === at) break t; 37466 37467 if (lt = ct - at, r.offset > lt) { 37468 if ((lt = r.offset - lt) > r.whave && r.sane) { 37469 t.msg = "invalid distance too far back", r.mode = X; 37470 break; 37471 } 37472 37473 lt > r.wnext ? (lt -= r.wnext, pt = r.wsize - lt) : pt = r.wnext - lt, lt > r.length && (lt = r.length), gt = r.window; 37474 } else gt = et, pt = it - r.offset, lt = r.length; 37475 37476 lt > at && (lt = at), at -= lt, r.length -= lt; 37477 37478 do { 37479 et[it++] = gt[pt++]; 37480 } while (--lt); 37481 37482 0 === r.length && (r.mode = q); 37483 break; 37484 37485 case Y: 37486 if (0 === at) break t; 37487 et[it++] = r.length, at--, r.mode = q; 37488 break; 37489 37490 case W: 37491 if (r.wrap) { 37492 for (; ut < 32;) { 37493 if (0 === ot) break t; 37494 ot--, st |= tt[rt++] << ut, ut += 8; 37495 } 37496 37497 if (ct -= at, t.total_out += ct, r.total += ct, ct && (t.adler = r.check = r.flags ? o(r.check, et, ct, it - ct) : i(r.check, et, ct, it - ct)), ct = at, (r.flags ? st : nt(st)) !== r.check) { 37498 t.msg = "incorrect data check", r.mode = X; 37499 break; 37500 } 37501 37502 st = 0, ut = 0; 37503 } 37504 37505 r.mode = K; 37506 37507 case K: 37508 if (r.wrap && r.flags) { 37509 for (; ut < 32;) { 37510 if (0 === ot) break t; 37511 ot--, st += tt[rt++] << ut, ut += 8; 37512 } 37513 37514 if (st !== (4294967295 & r.total)) { 37515 t.msg = "incorrect length check", r.mode = X; 37516 break; 37517 } 37518 37519 st = 0, ut = 0; 37520 } 37521 37522 r.mode = Q; 37523 37524 case Q: 37525 Et = g; 37526 break t; 37527 37528 case X: 37529 Et = m; 37530 break t; 37531 37532 case $: 37533 return b; 37534 37535 case J: 37536 default: 37537 return y; 37538 } 37539 37540 return t.next_out = it, t.avail_out = at, t.next_in = rt, t.avail_in = ot, r.hold = st, r.bits = ut, (r.wsize || ct !== t.avail_out && r.mode < X && (r.mode < W || e !== l)) && dt(t, t.output, t.next_out, ct - t.avail_out) ? (r.mode = $, b) : (ft -= t.avail_in, ct -= t.avail_out, t.total_in += ft, t.total_out += ct, r.total += ct, r.wrap && ct && (t.adler = r.check = r.flags ? o(r.check, et, ct, t.next_out - ct) : i(r.check, et, ct, t.next_out - ct)), t.data_type = r.bits + (r.last ? 64 : 0) + (r.mode === B ? 128 : 0) + (r.mode === D || r.mode === N ? 256 : 0), (0 === ft && 0 === ct || e === l) && Et === p && (Et = _), Et); 37541 }, e.inflateEnd = function (t) { 37542 if (!t || !t.state) return y; 37543 var e = t.state; 37544 return e.window && (e.window = null), t.state = null, p; 37545 }, e.inflateGetHeader = function (t, e) { 37546 var r; 37547 return t && t.state ? 0 == (2 & (r = t.state).wrap) ? y : (r.head = e, e.done = !1, p) : y; 37548 }, e.inflateSetDictionary = function (t, e) { 37549 var r, 37550 n = e.length; 37551 return t && t.state ? 0 !== (r = t.state).wrap && r.mode !== L ? y : r.mode === L && i(1, e, n, 0) !== r.check ? m : dt(t, e, n, n) ? (r.mode = $, b) : (r.havedict = 1, p) : y; 37552 }, e.inflateInfo = "pako inflate (from Nodeca project)"; 37553 }, function (t, e, r) { 37554 37555 t.exports = function (t, e) { 37556 var r, n, i, o, a, s, u, f, c, l, h, d, p, g, v, y, m, b, _, w, x, E, S, k, A; 37557 37558 r = t.state, n = t.next_in, k = t.input, i = n + (t.avail_in - 5), o = t.next_out, A = t.output, a = o - (e - t.avail_out), s = o + (t.avail_out - 257), u = r.dmax, f = r.wsize, c = r.whave, l = r.wnext, h = r.window, d = r.hold, p = r.bits, g = r.lencode, v = r.distcode, y = (1 << r.lenbits) - 1, m = (1 << r.distbits) - 1; 37559 37560 t: do { 37561 p < 15 && (d += k[n++] << p, p += 8, d += k[n++] << p, p += 8), b = g[d & y]; 37562 37563 e: for (;;) { 37564 if (d >>>= _ = b >>> 24, p -= _, 0 === (_ = b >>> 16 & 255)) A[o++] = 65535 & b;else { 37565 if (!(16 & _)) { 37566 if (0 == (64 & _)) { 37567 b = g[(65535 & b) + (d & (1 << _) - 1)]; 37568 continue e; 37569 } 37570 37571 if (32 & _) { 37572 r.mode = 12; 37573 break t; 37574 } 37575
37576 t.msg = "invalid literal/length code", r.mode = 30; 37577 break t; 37578 } 37579 37580 w = 65535 & b, (_ &= 15) && (p < _ && (d += k[n++] << p, p += 8), w += d & (1 << _) - 1, d >>>= _, p -= _), p < 15 && (d += k[n++] << p, p += 8, d += k[n++] << p, p += 8), b = v[d & m]; 37581 37582 r: for (;;) { 37583 if (d >>>= _ = b >>> 24, p -= _, !(16 & (_ = b >>> 16 & 255))) { 37584 if (0 == (64 & _)) { 37585 b = v[(65535 & b) + (d & (1 << _) - 1)]; 37586 continue r; 37587 } 37588 37589 t.msg = "invalid distance code", r.mode = 30; 37590 break t; 37591 } 37592 37593 if (x = 65535 & b, p < (_ &= 15) && (d += k[n++] << p, (p += 8) < _ && (d += k[n++] << p, p += 8)), (x += d & (1 << _) - 1) > u) { 37594 t.msg = "invalid distance too far back", r.mode = 30; 37595 break t; 37596 } 37597 37598 if (d >>>= _, p -= _, x > (_ = o - a)) { 37599 if ((_ = x - _) > c && r.sane) { 37600 t.msg = "invalid distance too far back", r.mode = 30; 37601 break t; 37602 } 37603 37604 if (E = 0, S = h, 0 === l) { 37605 if (E += f - _, _ < w) { 37606 w -= _; 37607 37608 do { 37609 A[o++] = h[E++]; 37610 } while (--_); 37611 37612 E = o - x, S = A; 37613 } 37614 } else if (l < _) { 37615 if (E += f + l - _, (_ -= l) < w) { 37616 w -= _; 37617 37618 do { 37619 A[o++] = h[E++]; 37620 } while (--_); 37621 37622 if (E = 0, l < w) { 37623 w -= _ = l; 37624 37625 do { 37626 A[o++] = h[E++]; 37627 } while (--_); 37628 37629 E = o - x, S = A; 37630 } 37631 } 37632 } else if (E += l - _, _ < w) { 37633 w -= _; 37634 37635 do { 37636 A[o++] = h[E++]; 37637 } while (--_); 37638 37639 E = o - x, S = A; 37640 } 37641 37642 for (; w > 2;) A[o++] = S[E++], A[o++] = S[E++], A[o++] = S[E++], w -= 3; 37643 37644 w && (A[o++] = S[E++], w > 1 && (A[o++] = S[E++])); 37645 } else { 37646 E = o - x; 37647 37648 do { 37649 A[o++] = A[E++], A[o++] = A[E++], A[o++] = A[E++], w -= 3; 37650 } while (w > 2); 37651 37652 w && (A[o++] = A[E++], w > 1 && (A[o++] = A[E++])); 37653 } 37654 37655 break; 37656 } 37657 } 37658 break; 37659 } 37660 } while (n < i && o < s); 37661 37662 n -= w = p >> 3, d &= (1 << (p -= w << 3)) - 1, t.next_in = n, t.next_out = o, t.avail_in = n < i ? i - n + 5 : 5 - (n - i), t.avail_out = o < s ? s - o + 257 : 257 - (o - s), r.hold = d, r.bits = p; 37663 }; 37664 }, function (t, e, r) { 37665 37666 var n = r(72), 37667 i = [3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0], 37668 o = [16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 78], 37669 a = [1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577, 0, 0], 37670 s = [16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 64, 64]; 37671 37672 t.exports = function (t, e, r, u, f, c, l, h) { 37673 var d, 37674 p, 37675 g, 37676 v, 37677 y, 37678 m, 37679 b, 37680 _, 37681 w, 37682 x = h.bits, 37683 E = 0, 37684 S = 0, 37685 k = 0, 37686 A = 0, 37687 C = 0, 37688 T = 0, 37689 R = 0, 37690 O = 0, 37691 I = 0, 37692 L = 0, 37693 B = null, 37694 P = 0, 37695 F = new n.Buf16(16), 37696 N = new n.Buf16(16), 37697 M = null, 37698 j = 0; 37699 37700 for (E = 0; E <= 15; E++) F[E] = 0; 37701 37702 for (S = 0; S < u; S++) F[e[r + S]]++; 37703 37704 for (C = x, A = 15; A >= 1 && 0 === F[A]; A--); 37705 37706 if (C > A && (C = A), 0 === A) return f[c++] = 20971520, f[c++] = 20971520, h.bits = 1, 0; 37707 37708 for (k = 1; k < A && 0 === F[k]; k++); 37709 37710 for (C < k && (C = k), O = 1, E = 1; E <= 15; E++) if (O <<= 1, (O -= F[E]) < 0) return -1; 37711 37712 if (O > 0 && (0 === t || 1 !== A)) return -1; 37713 37714 for (N[1] = 0, E = 1; E < 15;
37714 E++) N[E + 1] = N[E] + F[E]; 37715 37716 for (S = 0; S < u; S++) 0 !== e[r + S] && (l[N[e[r + S]]++] = S); 37717 37718 if (0 === t ? (B = M = l, m = 19) : 1 === t ? (B = i, P -= 257, M = o, j -= 257, m = 256) : (B = a, M = s, m = -1), L = 0, S = 0, E = k, y = c, T = C, R = 0, g = -1, v = (I = 1 << C) - 1, 1 === t && I > 852 || 2 === t && I > 592) return 1; 37719 37720 for (;;) { 37721 b = E - R, l[S] < m ? (_ = 0, w = l[S]) : l[S] > m ? (_ = M[j + l[S]], w = B[P + l[S]]) : (_ = 96, w = 0), d = 1 << E - R, k = p = 1 << T; 37722 37723 do { 37724 f[y + (L >> R) + (p -= d)] = b << 24 | _ << 16 | w | 0; 37725 } while (0 !== p); 37726 37727 for (d = 1 << E - 1; L & d;) d >>= 1; 37728 37729 if (0 !== d ? (L &= d - 1, L += d) : L = 0, S++, 0 == --F[E]) { 37730 if (E === A) break; 37731 E = e[r + l[S]]; 37732 } 37733 37734 if (E > C && (L & v) !== g) { 37735 for (0 === R && (R = C), y += k, O = 1 << (T = E - R); T + R < A && !((O -= F[T + R]) <= 0);) T++, O <<= 1; 37736 37737 if (I += 1 << T, 1 === t && I > 852 || 2 === t && I > 592) return 1; 37738 f[g = L & v] = C << 24 | T << 16 | y - c | 0; 37739 } 37740 } 37741 37742 return 0 !== L && (f[y + L] = E - R << 24 | 64 << 16 | 0), h.bits = C, 0; 37743 }; 37744 }, function (t, e, r) { 37745 37746 t.exports = { 37747 Z_NO_FLUSH: 0, 37748 Z_PARTIAL_FLUSH: 1, 37749 Z_SYNC_FLUSH: 2, 37750 Z_FULL_FLUSH: 3, 37751 Z_FINISH: 4, 37752 Z_BLOCK: 5, 37753 Z_TREES: 6, 37754 Z_OK: 0, 37755 Z_STREAM_END: 1, 37756 Z_NEED_DICT: 2, 37757 Z_ERRNO: -1, 37758 Z_STREAM_ERROR: -2, 37759 Z_DATA_ERROR: -3, 37760 Z_BUF_ERROR: -5, 37761 Z_NO_COMPRESSION: 0, 37762 Z_BEST_SPEED: 1, 37763 Z_BEST_COMPRESSION: 9, 37764 Z_DEFAULT_COMPRESSION: -1, 37765 Z_FILTERED: 1, 37766 Z_HUFFMAN_ONLY: 2, 37767 Z_RLE: 3, 37768 Z_FIXED: 4, 37769 Z_DEFAULT_STRATEGY: 0, 37770 Z_BINARY: 0, 37771 Z_TEXT: 1, 37772 Z_UNKNOWN: 2, 37773 Z_DEFLATED: 8 37774 }; 37775 }, function (t, e, r) { 37776 var n = r(19).Buffer, 37777 i = [0, 1996959894, 3993919788, 2567524794, 124634137, 1886057615, 3915621685, 2657392035, 249268274, 2044508324, 3772115230, 2547177864, 162941995, 2125561021, 3887607047, 2428444049, 498536548, 1789927666, 4089016648, 2227061214, 450548861, 1843258603, 4107580753, 2211677639, 325883990, 1684777152, 4251122042, 2321926636, 335633487, 1661365465, 4195302755, 2366115317, 997073096, 1281953886, 3579855332, 2724688242, 1006888145, 1258607687, 3524101629, 2768942443, 901097722, 1119000684, 3686517206, 2898065728, 853044451, 1172266101, 3705015759, 2882616665, 651767980, 1373503546, 3369554304, 3218104598, 565507253, 1454621731, 3485111705, 3099436303, 671266974, 1594198024, 3322730930, 2970347812, 795835527, 1483230225, 3244367275, 3060149565, 1994146192, 31158534, 2563907772, 4023717930, 1907459465, 112637215, 2680153253, 3904427059, 2013776290, 251722036, 2517215374, 3775830040, 2137656763, 141376813, 2439277719, 3865271297, 1802195444, 476864866, 2238001368, 4066508878, 1812370925, 453092731, 2181625025, 4111451223, 1706088902, 314042704, 2344532202, 4240017532, 1658658271, 366619977, 2362670323, 4224994405, 1303535960, 984961486, 2747007092, 3569037538, 1256170817, 1037604311, 2765210733, 3554079995, 1131014506, 879679996, 2909243462, 3663771856, 1141124467, 855842277, 2852801631, 3708648649, 1342533948, 654459306, 3188396048, 3373015174, 1466479909, 544179635, 3110523913, 3462522015, 1591671054, 702138776, 2966460450, 3352799412, 1504918807, 783551873, 3082640443, 3233442989, 3988292384, 2596254646, 62317068, 1957810842, 3939845945, 2647816111, 81470997, 1943803523, 3814918930, 2489596804, 225274430, 2053790376, 3826175755, 2466906013, 167816743, 2097651377, 4027552580, 2265490386, 503444072, 1762050814, 4150417245, 2154129355, 426522225, 1852507879, 4275313526, 2312317920, 282753626, 1742555852, 4189708143, 2394877945, 397917763, 1622183637, 3604390888, 2714866558, 953729732, 1340076626, 3518719985, 2797360999, 1068828381, 1219638859, 3624741850, 2936675148, 906185462, 1090812512, 3747672003, 2825379669, 829329135, 1181335161, 3412177804, 3160834842, 628085408, 1382605366, 3423369109, 3138078467, 570562233, 1426400815, 3317316542, 2998733608, 733239954, 1555261956, 3268935591, 3050360625, 752459403, 1541320221, 2607071920, 3965973030, 1969922972, 40735498, 2617837225, 3943577151, 1913087877, 83908371, 2512341634, 3803740692, 2075208622, 213261112, 2463272603, 3855990285, 2094854071, 198958881, 2262029012, 4057260610, 1759359992, 534414190, 2176718541, 4139329115, 1873836001, 414664567, 2282248934, 4279200368, 1711684554, 285281116, 2405801727, 4167216745, 1634467795, 376229701, 2685067896, 3608007406, 1308918612, 956543938, 2808555105, 3495958263, 1231636301, 1047427035, 2932959818, 3654703836, 1088359270, 936918e3, 2847714899, 3736837829, 1202900863, 817233897, 3183342108, 3401237130, 1404277552, 615818150, 3134207493, 3453421203, 1423857449, 601450431, 3009837614, 3294710456, 1567103746, 711928724, 3020668471, 3272380065, 1510334235, 755167117]; 37778 37779 function o(t) { 37780 if (n.isBuffer(t)) return t; 37781 var e = "function" == typeof n.alloc && "function" == typeof n.from; 37782 if ("number" == typeof t) return e ? n.alloc(t) : new n(t); 37783 if ("string" == typeof t) return e ? n.from(t) : new n(t); 37784 throw new Error("input must be buffer, number, or string, received " + typeof t); 37785 } 37786 37787 function a(t, e) { 37788 t = o(t), n.isBuffer(e) && (e = e.readUInt32BE(0)); 37789 37790 for (var r = -1 ^ ~~e, a = 0; a < t.length; a++) r = i[255 & (r ^ t[a])] ^ r >>> 8; 37791 37792 return -1 ^ r; 37793 } 37794 37795 function s() { 37796 return t = a.apply(null, arguments), (e = o(4)).writeInt32BE(t, 0), e; 37797 var t, e; 37798 } 37799 37800 "undefined" != typeof Int32Array && (i = new Int32Array(i)), s.signed = function () { 37801 return a.apply(null, arguments); 37802 }, s.unsigned = function () { 37803 return a.apply(null, arguments) >>> 0; 37804 }, t.exports = s; 37805 }, function (t, e, r) { 37806 var n = r(226), 37807 i = r(229); 37808 37809 function o(t) { 37810 return (o = "function" == typeof i && "symbol" == typeof n ? function (t) { 37811 return typeof t; 37812 } : function (t) { 37813 return t && "function" == typeof i && t.constructor === i && t !== i.prototype ? "symbol" : typeof t; 37814 })(t); 37815 } 37816 37817 function a(e) { 37818 return "function" == typeof i && "symbol" === o(n) ? t.exports = a = function (t) { 37819 return o(t); 37820 } : t.exports = a = function (t) { 37821 return t && "function" == typeof i && t.constructor === i && t !== i.prototype ? "symbol" : o(t); 37822 }, a(e); 37823 } 37824 37825 t.exports = a; 37826 }, function (t, e, r) { 37827 t.exports = r(227); 37828 }, function (t, e, r) { 37829 t.exports = r(228); 37830 }, function (t, e, r) { 37831 r(136), r(46), r(41); 37832 var n = r(95); 37833 t.exports = n.f("iterator"); 37834 }, function (t, e, r) { 37835 t.exports = r(230); 37836 }, function (t, e, r) { 37837 t.exports = r(231), r(249), r(250), r(251), r(252), r(253); 37838 }, function (t, e, r) { 37839 r(114), r(88), r(232), r(234), r(235), r(236), r(237), r(136), r(238), r(239), r(240), r(241), r(242), r(243), r(244), r(245), r(246), r(247), r(248); 37840 var n = r(3); 37841 t.exports = n.Symbol; 37842 }, function (t, e, r) { 37843 37844 var n = r(0), 37845 i = r(13), 37846 o = r(4), 37847 a = r(17), 37848 s = r(110), 37849 u = r(12), 37850 f = r(24), 37851 c = r(53), 37852 l = r(14), 37853 h = r(2), 37854 d = r(22), 37855 p = r(28), 37856 g = r(62), 37857 v = r(43), 37858 y = r(44), 37859 m = r(51), 37860 b = r(137), 37861 _ = r(233), 37862 w = r(138), 37863 x = r(81), 37864 E = r(21), 37865 S = r(65), 37866 k = r(20), 37867 A = r(52), 37868 C = r(61), 37869 T = r(63), 37870 R = r(50), 37871 O = r(64), 37872 I = r(6), 37873 L = r(95), 37874 B = r(11), 37875 P = r(36), 37876 F = r(42),
37877 N = r(45).forEach, 37878 M = T("hidden"), 37879 j = I("toPrimitive"), 37880 z = F.set, 37881 U = F.getterFor("Symbol"), 37882 D = Object.prototype, 37883 q = i.Symbol, 37884 Z = i.JSON, 37885 H = Z && Z.stringify, 37886 V = x.f, 37887 G = E.f, 37888 Y = _.f, 37889 W = S.f, 37890 K = C("symbols"), 37891 Q = C("op-symbols"), 37892 X = C("string-to-symbol-registry"), 37893 $ = C("symbol-to-string-registry"), 37894 J = C("wks"), 37895 tt = i.QObject, 37896 et = !tt || !tt.prototype || !tt.prototype.findChild, 37897 rt = a && u(function () { 37898 return 7 != y(G({}, "a", { 37899 get: function () { 37900 return G(this, "a", { 37901 value: 7 37902 }).a; 37903 } 37904 })).a; 37905 }) ? function (t, e, r) { 37906 var n = V(D, e); 37907 n && delete D[e], G(t, e, r), n && t !== D && G(D, e, n); 37908 } : G, 37909 nt = function (t, e) { 37910 var r = K[t] = y(q.prototype); 37911 return z(r, { 37912 type: "Symbol", 37913 tag: t, 37914 description: e 37915 }), a || (r.description = e), r; 37916 }, 37917 it = s && "symbol" == typeof q.iterator ? function (t) { 37918 return "symbol" == typeof t; 37919 } : function (t) { 37920 return Object(t) instanceof q; 37921 }, 37922 ot = function (t, e, r) { 37923 t === D && ot(Q, e, r), h(t); 37924 var n = g(e, !0); 37925 return h(r), f(K, n) ? (r.enumerable ? (f(t, M) && t[M][n] && (t[M][n] = !1), r = y(r, { 37926 enumerable: v(0, !1) 37927 })) : (f(t, M) || G(t, M, v(1, {})), t[M][n] = !0), rt(t, n, r)) : G(t, n, r); 37928 }, 37929 at = function (t, e) { 37930 h(t); 37931 var r = p(e), 37932 n = m(r).concat(ct(r)); 37933 return N(n, function (e) { 37934 a && !st.call(r, e) || ot(t, e, r[e]); 37935 }), t; 37936 }, 37937 st = function (t) { 37938 var e = g(t, !0), 37939 r = W.call(this, e); 37940 return !(this === D && f(K, e) && !f(Q, e)) && (!(r || !f(this, e) || !f(K, e) || f(this, M) && this[M][e]) || r); 37941 }, 37942 ut = function (t, e) { 37943 var r = p(t), 37944 n = g(e, !0); 37945 37946 if (r !== D || !f(K, n) || f(Q, n)) { 37947 var i = V(r, n); 37948 return !i || !f(K, n) || f(r, M) && r[M][n] || (i.enumerable = !0), i; 37949 } 37950 }, 37951 ft = function (t) { 37952 var e = Y(p(t)), 37953 r = []; 37954 return N(e, function (t) { 37955 f(K, t) || f(R, t) || r.push(t); 37956 }), r; 37957 }, 37958 ct = function (t) { 37959 var e = t === D, 37960 r = Y(e ? Q : p(t)), 37961 n = []; 37962 return N(r, function (t) { 37963 !f(K, t) || e && !f(D, t) || n.push(K[t]); 37964 }), n; 37965 }; 37966 37967 s || (A((q = function () { 37968 if (this instanceof q) throw TypeError("Symbol is not a constructor"); 37969 37970 var t = arguments.length && void 0 !== arguments[0] ? String(arguments[0]) : void 0, 37971 e = O(t), 37972 r = function (t) { 37973 this === D && r.call(Q, t), f(this, M) && f(this[M], e) && (this[M][e] = !1), rt(this, e, v(1, t)); 37974 }; 37975 37976 return a && et && rt(D, e, { 37977 configurable: !0, 37978 set: r 37979 }), nt(e, t); 37980 }).prototype, "toString", function () { 37981 return U(this).tag; 37982 }), S.f = st, E.f = ot, x.f = ut, b.f = _.f = ft, w.f = ct, a && (G(q.prototype, "description", { 37983 configurable: !0, 37984 get: function () { 37985 return U(this).description; 37986 } 37987 }), o || A(D, "propertyIsEnumerable", st, { 37988 unsafe: !0 37989 })), L.f = function (t) { 37990 return nt(I(t), t); 37991 }), n({ 37992 global: !0, 37993 wrap: !0, 37994 forced: !s, 37995 sham: !s 37996 }, { 37997 Symbol: q 37998 }), N(m(J), function (t) { 37999 B(t); 38000 }), n({ 38001 target: "Symbol", 38002 stat: !0, 38003 forced: !s 38004 }, { 38005 for: function (t) { 38006 var e = String(t); 38007 if (f(X, e)) return X[e]; 38008 var r = q(e); 38009 return X[e] = r, $[r] = e, r; 38010 }, 38011 keyFor: function (t) { 38012 if (!it(t)) throw TypeError(t + " is not a symbol"); 38013 if (f($, t)) return $[t]; 38014 }, 38015 useSetter: function () { 38016 et = !0; 38017 }, 38018 useSimple: function () { 38019 et = !1; 38020 } 38021 }), n({ 38022 target: "Object", 38023 stat: !0, 38024 forced: !s, 38025 sham: !a 38026 }, { 38027 create: function (t, e) { 38028 return void 0 === e ? y(t) : at(y(t), e); 38029 }, 38030 defineProperty: ot, 38031 defineProperties: at, 38032 getOwnPropertyDescriptor: ut 38033 }), n({ 38034 target: "Object", 38035 stat: !0, 38036 forced: !s 38037 }, { 38038 getOwnPropertyNames: ft, 38039 getOwnPropertySymbols: ct 38040 }), n({ 38041 target: "Object", 38042 stat: !0, 38043 forced: u(function () { 38044 w.f(1); 38045 }) 38046 }, { 38047 getOwnPropertySymbols: function (t) { 38048 return w.f(d(t)); 38049 } 38050 }), Z && n({ 38051 target: "JSON", 38052 stat: !0, 38053 forced: !s || u(function () { 38054 var t = q(); 38055 return "[null]" != H([t]) || "{}" != H({ 38056 a: t 38057 }) || "{}" != H(Object(t)); 38058 }) 38059 }, {
38060 stringify: function (t) { 38061 for (var e, r, n = [t], i = 1; arguments.length > i;) n.push(arguments[i++]); 38062 38063 if (r = e = n[1], (l(e) || void 0 !== t) && !it(t)) return c(e) || (e = function (t, e) { 38064 if ("function" == typeof r && (e = r.call(this, t, e)), !it(e)) return e; 38065 }), n[1] = e, H.apply(Z, n); 38066 } 38067 }), q.prototype[j] || k(q.prototype, j, q.prototype.valueOf), P(q, "Symbol"), R[M] = !0; 38068 }, function (t, e, r) { 38069 var n = r(28), 38070 i = r(137).f, 38071 o = {}.toString, 38072 a = "object" == typeof window && window && Object.getOwnPropertyNames ? Object.getOwnPropertyNames(window) : []; 38073 38074 t.exports.f = function (t) { 38075 return a && "[object Window]" == o.call(t) ? function (t) { 38076 try { 38077 return i(t); 38078 } catch (t) { 38079 return a.slice(); 38080 } 38081 }(t) : i(n(t)); 38082 }; 38083 }, function (t, e, r) { 38084 r(11)("asyncIterator"); 38085 }, function (t, e) {}, function (t, e, r) { 38086 r(11)("hasInstance"); 38087 }, function (t, e, r) { 38088 r(11)("isConcatSpreadable"); 38089 }, function (t, e, r) { 38090 r(11)("match"); 38091 }, function (t, e, r) { 38092 r(11)("matchAll"); 38093 }, function (t, e, r) { 38094 r(11)("replace"); 38095 }, function (t, e, r) { 38096 r(11)("search"); 38097 }, function (t, e, r) { 38098 r(11)("species"); 38099 }, function (t, e, r) { 38100 r(11)("split"); 38101 }, function (t, e, r) { 38102 r(11)("toPrimitive"); 38103 }, function (t, e, r) { 38104 r(11)("toStringTag"); 38105 }, function (t, e, r) { 38106 r(11)("unscopables"); 38107 }, function (t, e, r) { 38108 r(36)(Math, "Math", !0); 38109 }, function (t, e, r) { 38110 var n = r(13); 38111 r(36)(n.JSON, "JSON", !0); 38112 }, function (t, e, r) { 38113 r(11)("asyncDispose"); 38114 }, function (t, e, r) { 38115 r(11)("dispose"); 38116 }, function (t, e, r) { 38117 r(11)("observable"); 38118 }, function (t, e, r) { 38119 r(11)("patternMatch"); 38120 }, function (t, e, r) { 38121 r(11)("replaceAll"); 38122 }, function (t, e) { 38123 t.exports = function (t) { 38124 if (void 0 === t) throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); 38125 return t; 38126 }; 38127 }, function (t, e, r) { 38128 t.exports = r(256); 38129 }, function (t, e, r) { 38130 t.exports = r(257); 38131 }, function (t, e, r) { 38132 r(258); 38133 var n = r(3); 38134 t.exports = n.Object.getPrototypeOf; 38135 }, function (t, e, r) { 38136 var n = r(0), 38137 i = r(12), 38138 o = r(22), 38139 a = r(66), 38140 s = r(109); 38141 n({ 38142 target: "Object", 38143 stat: !0, 38144 forced: i(function () { 38145 a(1); 38146 }), 38147 sham: !s 38148 }, { 38149 getPrototypeOf: function (t) { 38150 return a(o(t)); 38151 } 38152 }); 38153 }, function (t, e, r) { 38154 t.exports = r(260); 38155 }, function (t, e, r) { 38156 r(261); 38157 var n = r(3); 38158 t.exports = n.Object.setPrototypeOf; 38159 }, function (t, e, r) { 38160 r(0)({ 38161 target: "Object", 38162 stat: !0 38163 }, { 38164 setPrototypeOf: r(86) 38165 }); 38166 }, function (t, e, r) { 38167 t.exports = r(263); 38168 }, function (t, e, r) { 38169 r(264); 38170 var n = r(3).Object; 38171 38172 t.exports = function (t, e) { 38173 return n.create(t, e); 38174 }; 38175 }, function (t, e, r) { 38176 r(0)({ 38177 target: "Object", 38178 stat: !0, 38179 sham: !r(17) 38180 }, { 38181 create: r(44) 38182 }); 38183 }, function (t, e, r) { 38184 var n = r(140), 38185 i = r(266), 38186 o = r(27), 38187 a = r(96), 38188 s = r(295), 38189 u = r(300); 38190 38191 function f(e) { 38192 var r = "function" == typeof i ? new i() : void 0; 38193 return t.exports = f = function (t) { 38194 if (null === t || !s(t)) return t; 38195 if ("function" != typeof t) throw new TypeError("Super expression must either be null or a function"); 38196 38197 if (void 0 !== r) { 38198 if (r.has(t)) return r.get(t); 38199 r.set(t, e); 38200 } 38201 38202 function e() { 38203 return u(t, arguments, o(this).constructor); 38204 } 38205 38206 return e.prototype = n(t.prototype, { 38207 constructor: { 38208 value: e, 38209 enumerable: !1, 38210 writable: !0, 38211 configurable: !0 38212 } 38213 }), a(e, t); 38214 }, f(e); 38215 } 38216 38217 t.exports = f; 38218 }, function (t, e, r) { 38219 t.exports = r(267); 38220 }, function (t, e, r) { 38221 t.exports = r(268), r(273), r(275), r(277), r(279), r(280), r(281), r(282), r(283), r(284), r(286), r(287), r(288), r(289), r(290), r(291), r(292), r(293), r(294); 38222 }, function (t, e, r) { 38223 r(269), r(88), r(46), r(41); 38224 var n = r(3); 38225 t.exports = n.Map; 38226 }, function (t, e, r) { 38227 38228 var n = r(270), 38229 i = r(272); 38230 t.exports = n("Map", function (t) { 38231 return function () { 38232 return t(this, arguments.length ? arguments[0] : void 0); 38233 }; 38234 }, i, !0); 38235 }, function (t, e, r) { 38236 38237 var n = r(0), 38238 i = r(13), 38239 o = r(141), 38240 a = r(12), 38241 s = r(20), 38242 u = r(8), 38243 f = r(89), 38244 c = r(14), 38245 l = r(36), 38246 h = r(21).f,
38247 d = r(45).forEach, 38248 p = r(17), 38249 g = r(42), 38250 v = g.set, 38251 y = g.getterFor; 38252 38253 t.exports = function (t, e, r, g, m) { 38254 var b, 38255 _ = i[t], 38256 w = _ && _.prototype, 38257 x = g ? "set" : "add", 38258 E = {}; 38259 38260 if (p && "function" == typeof _ && (m || w.forEach && !a(function () { 38261 new _().entries().next(); 38262 }))) { 38263 b = e(function (e, r) { 38264 v(f(e, b, t), { 38265 type: t, 38266 collection: new _() 38267 }), null != r && u(r, e[x], e, g); 38268 }); 38269 var S = y(t); 38270 d(["add", "clear", "delete", "forEach", "get", "has", "set", "keys", "values", "entries"], function (t) { 38271 var e = "add" == t || "set" == t; 38272 t in w && (!m || "clear" != t) && s(b.prototype, t, function (r, n) { 38273 var i = S(this).collection; 38274 if (!e && m && !c(r)) return "get" == t && void 0; 38275 var o = i[t](0 === r ? 0 : r, n); 38276 return e ? this : o; 38277 }); 38278 }), m || h(b.prototype, "size", { 38279 get: function () { 38280 return S(this).collection.size; 38281 } 38282 }); 38283 } else b = r.getConstructor(e, t, g, x), o.REQUIRED = !0; 38284 38285 return l(b, t, !1, !0), E[t] = b, n({ 38286 global: !0, 38287 forced: !0 38288 }, E), m || r.setStrong(b, t, g), b; 38289 }; 38290 }, function (t, e, r) { 38291 var n = r(12); 38292 t.exports = !n(function () { 38293 return Object.isExtensible(Object.preventExtensions({})); 38294 }); 38295 }, function (t, e, r) { 38296 38297 var n = r(21).f, 38298 i = r(44), 38299 o = r(117), 38300 a = r(15), 38301 s = r(89), 38302 u = r(8), 38303 f = r(80), 38304 c = r(118), 38305 l = r(17), 38306 h = r(141).fastKey, 38307 d = r(42), 38308 p = d.set, 38309 g = d.getterFor; 38310 t.exports = { 38311 getConstructor: function (t, e, r, f) { 38312 var c = t(function (t, n) { 38313 s(t, c, e), p(t, { 38314 type: e, 38315 index: i(null), 38316 first: void 0, 38317 last: void 0, 38318 size: 0 38319 }), l || (t.size = 0), null != n && u(n, t[f], t, r); 38320 }), 38321 d = g(e), 38322 v = function (t, e, r) { 38323 var n, 38324 i, 38325 o = d(t), 38326 a = y(t, e); 38327 return a ? a.value = r : (o.last = a = { 38328 index: i = h(e, !0), 38329 key: e, 38330 value: r, 38331 previous: n = o.last, 38332 next: void 0, 38333 removed: !1 38334 }, o.first || (o.first = a), n && (n.next = a), l ? o.size++ : t.size++, "F" !== i && (o.index[i] = a)), t; 38335 }, 38336 y = function (t, e) { 38337 var r, 38338 n = d(t), 38339 i = h(e); 38340 if ("F" !== i) return n.index[i]; 38341 38342 for (r = n.first; r; r = r.next) if (r.key == e) return r; 38343 }; 38344 38345 return o(c.prototype, { 38346 clear: function () { 38347 for (var t = d(this), e = t.index, r = t.first; r;) r.removed = !0, r.previous && (r.previous = r.previous.next = void 0), delete e[r.index], r = r.next; 38348 38349 t.first = t.last = void 0, l ? t.size = 0 : this.size = 0; 38350 }, 38351 delete: function (t) { 38352 var e = d(this), 38353 r = y(this, t); 38354 38355 if (r) { 38356 var n = r.next, 38357 i = r.previous; 38358 delete e.index[r.index], r.removed = !0, i && (i.next = n), n && (n.previous = i), e.first == r && (e.first = n), e.last == r && (e.last = i), l ? e.size-- : this.size--; 38359 } 38360 38361 return !!r; 38362 }, 38363 forEach: function (t) { 38364 for (var e, r = d(this), n = a(t, arguments.length > 1 ? arguments[1] : void 0, 3); e = e ? e.next : r.first;) for (n(e.value, e.key, this); e && e.removed;) e = e.previous; 38365 }, 38366 has: function (t) { 38367 return !!y(this, t); 38368 } 38369 }), o(c.prototype, r ? { 38370 get: function (t) { 38371 var e = y(this, t); 38372 return e && e.value; 38373 }, 38374 set: function (t, e) { 38375 return v(this, 0 === t ? 0 : t, e); 38376 } 38377 } : { 38378 add: function (t) { 38379 return v(this, t = 0 === t ? 0 : t, t); 38380 } 38381 }), l && n(c.prototype, "size", { 38382 get: function () { 38383 return d(this).size; 38384 } 38385 }), c; 38386 }, 38387 setStrong: function (t, e, r) { 38388 var n = e + " Iterator", 38389 i = g(e), 38390 o = g(n); 38391 f(t, e, function (t, e) { 38392 p(this, { 38393 type: n, 38394 target: t, 38395 state: i(t), 38396 kind: e, 38397 last: void 0 38398 }); 38399 }, function () { 38400 for (var t = o(this), e = t.kind, r = t.last; r && r.removed;) r = r.previous; 38401 38402 return t.target && (t.last = r = r ? r.next : t.state.first) ? "keys" == e ? { 38403 value: r.key, 38404 done: !1 38405 } : "values" == e ? { 38406 value: r.value, 38407 done: !1 38408 } : { 38409 value: [r.key, r.value], 38410 done: !1 38411 } : (t.target = void 0, { 38412 value: void 0, 38413 done: !0 38414 }); 38415 }, r ? "entries" : "values", !r, !0), c(e); 38416 } 38417 }; 38418 }, function (t, e, r) { 38419 r(0)({ 38420 target: "Map", 38421 stat: !0 38422 }, { 38423 from: r(274) 38424 }); 38425 }, function (t, e, r) { 38426 38427 var n = r(5), 38428 i = r(15), 38429 o = r(8); 38430 38431 t.exports = function (t) { 38432 var e, 38433 r, 38434 a, 38435 s, 38436 u = arguments.length, 38437 f = u > 1 ? arguments[1] : void 0; 38438 return n(this), (e = void 0 !== f) && n(f), null == t ? new this() : (r = [], e ? (a = 0, s = i(f, u > 2 ? arguments[2] : void 0, 2), o(t, function (t) { 38439 r.push(s(t, a++)); 38440 })) : o(t, r.push, r), new this(r)); 38441 }; 38442 }, function (t, e, r) { 38443 r(0)({ 38444 target: "Map", 38445 stat: !0 38446 }, { 38447 of: r(276) 38448 }); 38449 }, function (t, e, r) { 38450 38451 t.exports = function () { 38452 for (var t = arguments.length, e = new Array(t); t--;) e[t] = arguments[t]; 38453 38454 return new this(e); 38455 }; 38456 }, function (t, e, r) { 38457 38458 var n = r(0), 38459 i = r(4), 38460 o = r(278); 38461 n({ 38462 target: "Map", 38463 proto: !0, 38464 real: !0, 38465 forced: i 38466 }, { 38467 deleteAll: function () { 38468 return o.apply(this, arguments); 38469 } 38470 }); 38471 }, function (t, e, r) { 38472 38473 var n = r(2), 38474 i = r(5); 38475 38476 t.exports = function () { 38477 for (var t, e = n(this), r = i(e.delete), o = !0, a = 0, s = arguments.length; a < s; a++) t = r.call(e, arguments[a]), o = o && t; 38478 38479 return !!o; 38480 }; 38481 }, function (t, e, r) { 38482 38483 var n = r(0), 38484 i = r(4), 38485 o = r(2), 38486 a = r(15), 38487 s = r(25), 38488 u = r(8); 38489 n({ 38490 target: "Map", 38491 proto: !0, 38492 real: !0, 38493 forced: i 38494 }, { 38495 every: function (t) { 38496 var e = o(this), 38497 r = s(e), 38498 n = a(t, arguments.length > 1 ? arguments[1] : void 0, 3); 38499 return !u(r, function (t, r) { 38500 if (!n(r, t, e)) return u.stop(); 38501 }, void 0, !0, !0).stopped; 38502 } 38503 }); 38504 }, function (t, e, r) { 38505 38506 var n = r(0), 38507 i = r(4), 38508 o = r(26), 38509 a = r(2), 38510 s = r(5), 38511 u = r(15), 38512 f = r(55), 38513 c = r(25), 38514 l = r(8); 38515 n({ 38516 target: "Map", 38517 proto: !0, 38518 real: !0, 38519 forced: i 38520 }, { 38521 filter: function (t) { 38522 var e = a(this), 38523 r = c(e), 38524 n = u(t, arguments.length > 1 ? arguments[1] : void 0, 3), 38525 i = new (f(e, o("Map")))(), 38526 h = s(i.set); 38527 return l(r, function (t, r) { 38528 n(r, t, e) && h.call(i, t, r); 38529 }, void 0, !0, !0), i; 38530 } 38531 }); 38532 }, function (t, e, r) { 38533 38534 var n = r(0), 38535 i = r(4), 38536 o = r(2), 38537 a = r(15), 38538 s = r(25), 38539 u = r(8); 38540 n({ 38541 target: "Map", 38542 proto: !0, 38543 real: !0, 38544 forced: i 38545 }, { 38546 find: function (t) { 38547 var e = o(this), 38548 r = s(e), 38549 n = a(t, arguments.length > 1 ? arguments[1] : void 0, 3); 38550 return u(r, function (t, r) { 38551 if (n(r, t, e)) return u.stop(r); 38552 }, void 0, !0, !0).result; 38553 } 38554 }); 38555 }, function (t, e, r) { 38556 38557 var n = r(0), 38558 i = r(4), 38559 o = r(2), 38560 a = r(15), 38561 s = r(25), 38562 u = r(8); 38563 n({ 38564 target: "Map", 38565 proto: !0, 38566 real: !0, 38567 forced: i 38568 }, { 38569 findKey: function (t) { 38570 var e = o(this), 38571 r = s(e), 38572 n = a(t, arguments.length > 1 ? arguments[1] : void 0, 3); 38573 return u(r, function (t, r) { 38574 if (n(r, t, e)) return u.stop(t); 38575 }, void 0, !0, !0).result; 38576 } 38577 }); 38578 }, function (t, e, r) { 38579 38580 var n = r(0), 38581 i = r(8), 38582 o = r(5); 38583 n({ 38584 target: "Map", 38585 stat: !0 38586 }, { 38587 groupBy: function (t, e) { 38588 var r = new this(); 38589 o(e); 38590 var n = o(r.has), 38591 a = o(r.get), 38592 s = o(r.set); 38593 return i(t, function (t) { 38594 var i = e(t); 38595 n.call(r, i) ? a.call(r, i).push(t) : s.call(r, i, [t]); 38596 }), r; 38597 } 38598 }); 38599 }, function (t, e, r) { 38600 38601 var n = r(0), 38602 i = r(4), 38603 o = r(2), 38604 a = r(25), 38605 s = r(285), 38606 u = r(8); 38607 n({ 38608 target: "Map", 38609 proto: !0, 38610 real: !0, 38611 forced: i 38612 }, { 38613 includes: function (t) { 38614 return u(a(o(this)), function (e, r) { 38615 if (s(r, t)) return u.stop(); 38616 }, void 0, !0, !0).stopped; 38617 } 38618 }); 38619 }, function (t, e) { 38620 t.exports = function (t, e) { 38621 return t === e || t != t && e != e; 38622 }; 38623 }, function (t, e, r) { 38624 38625 var n = r(0), 38626 i = r(8), 38627 o = r(5); 38628 n({ 38629 target: "Map", 38630 stat: !0 38631 }, { 38632 keyBy: function (t, e) { 38633 var r = new this(); 38634 o(e); 38635 var n = o(r.set); 38636 return i(t, function (t) { 38637 n.call(r, e(t), t); 38638 }), r; 38639 } 38640 }); 38641 }, function (t, e, r) { 38642 38643 var n = r(0), 38644 i = r(4), 38645 o = r(2), 38646 a = r(25), 38647 s = r(8); 38648 n({ 38649 target: "Map", 38650 proto: !0, 38651 real: !0, 38652 forced: i 38653 }, { 38654 keyOf: function (t) { 38655 return s(a(o(this)), function (e, r) { 38656 if (r === t) return s.stop(e); 38657 }, void 0, !0, !0).result; 38658 } 38659 }); 38660 }, function (t, e, r) { 38661 38662 var n = r(0), 38663 i = r(4), 38664 o = r(26), 38665 a = r(2), 38666 s = r(5), 38667 u = r(15), 38668 f = r(55), 38669 c = r(25), 38670 l = r(8); 38671 n({ 38672 target: "Map", 38673 proto: !0, 38674 real: !0, 38675 forced: i 38676 }, { 38677 mapKeys: function (t) { 38678 var e = a(this), 38679 r = c(e), 38680 n = u(t, arguments.length > 1 ? arguments[1] : void 0, 3), 38681 i = new (f(e, o("Map")))(), 38682 h = s(i.set); 38683 return l(r, function (t, r) { 38684 h.call(i, n(r, t, e), r); 38685 }, void 0, !0, !0), i; 38686 } 38687 }); 38688 }, function (t, e, r) { 38689 38690 var n = r(0), 38691 i = r(4), 38692 o = r(26), 38693 a = r(2), 38694 s = r(5), 38695 u = r(15), 38696 f = r(55), 38697 c = r(25), 38698 l = r(8); 38699 n({ 38700 target: "Map", 38701 proto: !0, 38702 real: !0, 38703 forced: i 38704 }, { 38705 mapValues: function (t) { 38706 var e = a(this), 38707 r = c(e), 38708 n = u(t, arguments.length > 1 ? arguments[1] : void 0, 3), 38709 i = new (f(e, o("Map")))(), 38710 h = s(i.set); 38711 return l(r, function (t, r) { 38712 h.call(i, t, n(r, t, e)); 38713 }, void 0, !0, !0), i; 38714 } 38715 }); 38716 }, function (t, e, r) { 38717 38718 var n = r(0), 38719 i = r(4), 38720 o = r(2), 38721 a = r(5), 38722 s = r(8); 38723 n({ 38724 target: "Map", 38725 proto: !0, 38726 real: !0, 38727 forced: i 38728 }, { 38729 merge: function (t) { 38730 for (var e = o(this), r = a(e.set), n = 0; n < arguments.length;) s(arguments[n++], r, e, !0); 38731 38732 return e; 38733 } 38734 }); 38735 }, function (t, e, r) { 38736 38737 var n = r(0), 38738 i = r(4), 38739 o = r(2), 38740 a = r(5), 38741 s = r(25), 38742 u = r(8); 38743 n({ 38744 target: "Map", 38745 proto: !0, 38746 real: !0, 38747 forced: i 38748 }, { 38749 reduce: function (t) { 38750 var e, 38751 r, 38752 n = o(this), 38753 i = s(n); 38754 if (a(t), arguments.length > 1) e = arguments[1];else { 38755 if ((r = i.next()).done) throw TypeError("Reduce of empty map with no initial value"); 38756 e = r.value[1]; 38757 } 38758 return u(i, function (r, i) { 38759 e = t(e, i, r, n); 38760 }, void 0, !0, !0), e; 38761 } 38762 }); 38763 }, function (t, e, r) { 38764 38765 var n = r(0), 38766 i = r(4), 38767 o = r(2), 38768 a = r(15), 38769 s = r(25), 38770 u = r(8); 38771 n({ 38772 target: "Map", 38773 proto: !0, 38774 real: !0, 38775 forced: i 38776 }, { 38777 some: function (t) { 38778 var e = o(this), 38779 r = s(e), 38780 n = a(t, arguments.length > 1 ? arguments[1] : void 0, 3); 38781 return u(r, function (t, r) { 38782 if (n(r, t, e)) return u.stop(); 38783 }, void 0, !0, !0).stopped; 38784 } 38785 }); 38786 }, function (t, e, r) { 38787 38788 var n = r(0), 38789 i = r(4), 38790 o = r(2), 38791 a = r(5); 38792 n({ 38793 target: "Map", 38794 proto: !0, 38795 real: !0, 38796 forced: i 38797 }, { 38798 update: function (t, e) { 38799 var r = o(this), 38800 n = arguments.length; 38801 a(e); 38802 var i = r.has(t); 38803 if (!i && n < 3) throw TypeError("Updating absent value"); 38804 var s = i ? r.get(t) : a(n > 2 ? arguments[2] : void 0)(t, r); 38805 return r.set(t, e(s, t, r)), r; 38806 } 38807 }); 38808 }, function (t, e, r) { 38809 38810 var n = r(0), 38811 i = r(4), 38812 o = r(2), 38813 a = r(5); 38814 n({ 38815 target: "Map", 38816 proto: !0, 38817 real: !0, 38818 forced: i 38819 }, { 38820 updateOrInsert: function (t, e, r) { 38821 var n = o(this); 38822 a(e), a(r); 38823 var i = n.has(t) ? e(n.get(t)) : r(); 38824 return n.set(t, i), i; 38825 } 38826 }); 38827 }, function (t, e, r) { 38828 var n = r(296); 38829 38830 t.exports = function (t) { 38831 var e; 38832 return -1 !== n(e = Function.toString.call(t)).call(e, "[native code]"); 38833 }; 38834 }, function (t, e, r) { 38835 t.exports = r(297); 38836 }, function (t, e, r) { 38837 t.exports = r(143); 38838 }, function (t, e, r) { 38839 r(299); 38840 var n = r(18); 38841 t.exports = n("Array").indexOf; 38842 }, function (t, e, r) { 38843 38844 var n = r(0), 38845 i = r(82).indexOf, 38846 o = r(54), 38847 a = [].indexOf, 38848 s = !!a && 1 / [1].indexOf(1, -0) < 0, 38849 u = o("indexOf"); 38850 n({ 38851 target: "Array", 38852 proto: !0, 38853 forced: s || u 38854 }, { 38855 indexOf: function (t) { 38856 return s ? a.apply(this, arguments) || 0 : i(this, t, arguments.length > 1 ? arguments[1] : void 0); 38857 } 38858 }); 38859 }, function (t, e, r) { 38860 var n = r(301), 38861 i = r(305), 38862 o = r(96); 38863 38864 function a(e, r, s) { 38865 return !function () { 38866 if ("undefined" == typeof Reflect || !i) return !1; 38867 if (i.sham) return !1; 38868 if ("function" == typeof Proxy) return !0; 38869 38870 try { 38871 return Date.prototype.toString.call(i(Date, [], function () {})), !0; 38872 } catch (t) { 38873
38873return !1; 38874 } 38875 }() ? t.exports = a = function (t, e, r) { 38876 var i = [null]; 38877 i.push.apply(i, e); 38878 var a = new (n(Function).apply(t, i))(); 38879 return r && o(a, r.prototype), a; 38880 } : t.exports = a = i, a.apply(null, arguments); 38881 } 38882 38883 t.exports = a; 38884 }, function (t, e, r) { 38885 t.exports = r(302); 38886 }, function (t, e, r) { 38887 t.exports = r(144); 38888 }, function (t, e, r) { 38889 r(304); 38890 var n = r(18); 38891 t.exports = n("Function").bind; 38892 }, function (t, e, r) { 38893 r(0)({ 38894 target: "Function", 38895 proto: !0 38896 }, { 38897 bind: r(145) 38898 }); 38899 }, function (t, e, r) { 38900 t.exports = r(306); 38901 }, function (t, e, r) { 38902 t.exports = r(307); 38903 }, function (t, e, r) { 38904 r(308); 38905 var n = r(3); 38906 t.exports = n.Reflect.construct; 38907 }, function (t, e, r) { 38908 var n = r(0), 38909 i = r(26), 38910 o = r(5), 38911 a = r(2), 38912 s = r(14), 38913 u = r(44), 38914 f = r(145), 38915 c = r(12), 38916 l = i("Reflect", "construct"), 38917 h = c(function () { 38918 function t() {} 38919 38920 return !(l(function () {}, [], t) instanceof t); 38921 }), 38922 d = !c(function () { 38923 l(function () {}); 38924 }), 38925 p = h || d; 38926 n({ 38927 target: "Reflect", 38928 stat: !0, 38929 forced: p, 38930 sham: p 38931 }, { 38932 construct: function (t, e) { 38933 o(t), a(e); 38934 var r = arguments.length < 3 ? t : o(arguments[2]); 38935 if (d && !h) return l(t, e, r); 38936 38937 if (t == r) { 38938 switch (e.length) { 38939 case 0: 38940 return new t(); 38941 38942 case 1: 38943 return new t(e[0]); 38944 38945 case 2: 38946 return new t(e[0], e[1]); 38947 38948 case 3: 38949 return new t(e[0], e[1], e[2]); 38950 38951 case 4: 38952 return new t(e[0], e[1], e[2], e[3]); 38953 } 38954 38955 var n = [null]; 38956 return n.push.apply(n, e), new (f.apply(t, n))(); 38957 } 38958 38959 var i = r.prototype, 38960 c = u(s(i) ? i : Object.prototype), 38961 p = Function.apply.call(t, c, e); 38962 return s(p) ? p : c; 38963 } 38964 }); 38965 }, function (t, e, r) { 38966 38967 (function (e) { 38968 var n = r(1), 38969 i = n(r(97)), 38970 o = n(r(7)), 38971 a = n(r(10)), 38972 s = r(9).CramMalformedError, 38973 u = r(73), 38974 f = r(315), 38975 c = r(316), 38976 l = r(317), 38977 h = 4; 38978 38979 var d = function () { 38980 function t(e) { 38981 var r = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : 0; 38982 (0, o.default)(this, t), this._buffer = e, this._position = r, this.length = e.length; 38983 } 38984 38985 return (0, a.default)(t, [{ 38986 key: "get", 38987 value: function () { 38988 var t = this._buffer[this._position]; 38989 return this._position += 1, t; 38990 } 38991 }, { 38992 key: "getByte", 38993 value: function () { 38994 return this.get(); 38995 } 38996 }, { 38997 key: "getByteAt", 38998 value: function (t) { 38999 return this._buffer[t]; 39000 } 39001 }, { 39002 key: "position", 39003 value: function () { 39004 return this._position; 39005 } 39006 }, { 39007 key: "put", 39008 value: function (t) { 39009 return this._buffer[this._position] = t, this._position += 1, t; 39010 } 39011 }, { 39012 key: "putAt", 39013 value: function (t, e) { 39014 return this._buffer[t] = e, e; 39015 } 39016 }, { 39017 key: "setPosition", 39018 value: function (t) { 39019 return this._position = t, t; 39020 } 39021 }, { 39022 key: "getInt", 39023 value: function () { 39024 var t = this._buffer.readInt32LE(this._position); 39025 39026 return this._position += 4, t; 39027 } 39028 }, { 39029 key: "remaining", 39030 value: function () { 39031 return this._buffer.length - this._position; 39032 } 39033 }]), t; 39034 }(); 39035 39036 t.exports = { 39037 uncompress: function (t, r) { 39038 var n = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : 0; 39039 if (0 === t.length) return (0, i.default)(r).call(r, 0), r; 39040 var o = new d(t, n), 39041 a = o.get(); 39042 if (0 !== a && 1 !== a) throw new s("Invalid rANS order ".concat(a)); 39043 if (o.getInt() !== o.remaining() - h) throw new s("Incorrect input length."); 39044 var p = o.getInt(), 39045 g = new d(r || e.allocUnsafe(p)); 39046 if (g.length < p) throw new s("Output buffer too small to fit ".concat(p, " bytes.")); 39047 39048 switch (a) { 39049 case 0: 39050 return function (t, e) { 39051 for (var r = new u.AriDecoder(), n = new Array(256), i = 0; i < n.length; i += 1) n[i] = new u.Symbol(); 39052 39053 return f.readStatsO0(t, r, n), c.uncompress(t, r, n, e), e; 39054 }(o, g); 39055 39056 case 1: 39057 return function (t, e) { 39058 for (var r = new Array(256), n = 0; n < r.length; n += 1) r[n] = new u.AriDecoder(); 39059 39060 for (var i = new Array(256), o = 0; o < i.length; o += 1) { 39061 i[o] = new Array(256); 39062 39063 for (var a = 0; a < i[o].length; a += 1) i[o][a] = new u.Symbol(); 39064 } 39065 39066 return f.readStatsO1(t, r, i), l.uncompress(t, e, r, i), e; 39067 }(o, g); 39068 39069 default: 39070 throw new s("Invalid rANS order: ".concat(a)); 39071 } 39072 } 39073 }; 39074 }).call(this, r(19).Buffer); 39075 }, function (t, e, r) { 39076 t.exports = r(311); 39077 }, function (t, e, r) { 39078 var n = r(312), 39079 i = Array.prototype; 39080 39081 t.exports = function (t) { 39082 var e = t.fill; 39083 return t === i || t instanceof Array && e === i.fill ? n : e; 39084 }; 39085 }, function (t, e, r) { 39086 r(313); 39087 var n = r(18); 39088 t.exports = n("Array").fill; 39089 }, function (t, e, r) { 39090 var n = r(0), 39091 i = r(314), 39092 o = r(78); 39093 n({ 39094 target: "Array", 39095 proto: !0 39096 }, { 39097 fill: i 39098 }), o("fill"); 39099 }, function (t, e, r) { 39100 39101 var n = r(22), 39102 i = r(84), 39103 o = r(29); 39104 39105 t.exports = function (t) { 39106 for (var e = n(this), r = o(e.length), a = arguments.length, s = i(a > 1 ? arguments[1] : void 0, r), u = a > 2 ? arguments[2] : void 0, f = void 0 === u ? r : i(u, r); f > s;) e[s++] = t; 39107 39108 return e; 39109 }; 39110 }, function (t, e, r) { 39111 39112 var n = r(1)(r(97)), 39113 i = r(9).CramMalformedError, 39114 o = r(74), 39115 a = r(73); 39116 39117 function s(t) { 39118 if (!t) throw new i("assertion failed"); 39119 } 39120 39121 t.exports = { 39122 readStatsO0: function (t, e, r) { 39123 var i = 0, 39124 u = 0, 39125 f = 255 & t.get(); 39126 39127 do { 39128 var c; 39129 null == e.fc[f] && (e.fc[f] = new a.FC()), e.fc[f].F = 255 & t.get(), e.fc[f].F >= 128 && (e.fc[f].F &= -129, e.fc[f].F = (127 & e.fc[f].F) << 8 | 255 & t.get()), e.fc[f].C = u, a.symbolInit(r[f], e.fc[f].C, e.fc[f].F), e.R || (e.R = new Array(o.TOTFREQ)), (0, n.default)(c = e.R).call(c, f, u, u + e.fc[f].F), u += e.fc[f].F, 0 === i && f + 1 === (255 & t.getByteAt(t.position())) ? (f = 255 & t.get(), i = 255 & t.get()) : 0 !== i ? (i -= 1, f += 1) : f = 255 & t.get(); 39130 } while (0 !== f); 39131 39132 s(u < o.TOTFREQ); 39133 }, 39134 readStatsO1: function (t, e, r) { 39135 var i = 0, 39136 u = 255 & t.get(); 39137 39138 do { 39139 var f = 0, 39140 c = 0, 39141 l = 255 & t.get(); 39142 null == e[u] && (e[u] = new a.AriDecoder()); 39143 39144 do { 39145 var h; 39146 null == e[u].fc[l] && (e[u].fc[l] = new a.FC()), e[u].fc[l].F = 255 & t.get(), e[u].fc[l].F >= 128 && (e[u].fc[l].F &= -129, e[u].fc[l].F = (127 & e[u].fc[l].F) << 8 | 255 & t.get()), e[u].fc[l].C = c, 0 === e[u].fc[l].F && (e[u].fc[l].F = o.TOTFREQ), null == r[u][l] && (r[u][l] = new a.RansDecSymbol()), a.symbolInit(r[u][l], e[u].fc[l].C, e[u].fc[l].F), null == e[u].R && (e[u].R = new Array(o.TOTFREQ)), (0, n.default)(h = e[u].R).call(h, l, c, c + e[u].fc[l].F), s((c += e[u].fc[l].F) <= o.TOTFREQ), 0 === f && l + 1 === (255 & t.getByteAt(t.position())) ? (l = 255 & t.get(), f = 255 & t.get()) : 0 !== f ? (f -= 1, l += 1) : l = 255 & t.get(); 39147 } while (0 !== l); 39148 39149 0 === i && u + 1 === (255 & t.getByteAt(t.position())) ? (u = 255 & t.get(), i = 255 & t.get()) : 0 !== i ? (i -= 1, u += 1) : u = 255 & t.get(); 39150 } while (0 !== u); 39151 } 39152 }; 39153 }, function (t, e, r) { 39154 39155 var n = r(9).CramMalformedError, 39156 i = r(74), 39157 o = r(73); 39158 t.exports = { 39159 uncompress: function (t, e, r, a) { 39160 for (var s, u = t.getInt(), f = t.getInt(), c = t.getInt(), l = t.getInt(), h = a.remaining(), d = -4 & h, p = 0; p < d; p += 4) { 39161 var g = e.R[o.get(u, i.TF_SHIFT)], 39162 v = e.R[o.get(f, i.TF_SHIFT)], 39163 y = e.R[o.get(c, i.TF_SHIFT)], 39164 m = e.R[o.get(l, i.TF_SHIFT)]; 39165 a.putAt(p, g), a.putAt(p + 1, v), a.putAt(p + 2, y), a.putAt(p + 3, m), u = o.advanceSymbolStep(u, r[255 & g], i.TF_SHIFT), f = o.advanceSymbolStep(f, r[255 & v], i.TF_SHIFT), c = o.advanceSymbolStep(c, r[255 & y], i.TF_SHIFT), l = o.advanceSymbolStep(l, r[255 & m], i.TF_SHIFT), u = o.renormalize(u, t), f = o.renormalize(f, t), c = o.renormalize(c, t), l = o.renormalize(l, t); 39166 } 39167 39168 switch (a.setPosition(d), 3 & h) { 39169 case 0: 39170 break; 39171 39172 case 1: 39173 s = e.R[o.get(u, i.TF_SHIFT)], o.advanceSymbol(u, t, r[255 & s], i.TF_SHIFT), a.put(s); 39174 break; 39175 39176 case 2: 39177 s = e.R[o.get(u, i.TF_SHIFT)], o.advanceSymbol(u, t, r[255 & s], i.TF_SHIFT), a.put(s), s = e.R[o.get(f, i.TF_SHIFT)], o.advanceSymbol(f, t, r[255 & s], i.TF_SHIFT), a.put(s); 39178 break; 39179 39180 case 3: 39181 s = e.R[o.get(u, i.TF_SHIFT)], o.advanceSymbol(u, t, r[255 & s], i.TF_SHIFT), a.put(s), s = e.R[o.get(f, i.TF_SHIFT)], o.advanceSymbol(f, t, r[255 & s], i.TF_SHIFT), a.put(s), s = e.R[o.get(c, i.TF_SHIFT)], o.advanceSymbol(c, t, r[255 & s], i.TF_SHIFT), a.put(s); 39182 break; 39183 39184 default: 39185 throw new n("invalid output size encountered during rANS decoding"); 39186 } 39187 39188 a.setPosition(0); 39189 } 39190 }; 39191 }, function (t, e, r) { 39192 39193 var n = r(74), 39194 i = r(73); 39195 t.exports = { 39196 uncompress: function (t, e, r, o) { 39197 for (var a = e.remaining(), s = t.getInt(), u = t.getInt(), f = t.getInt(), c = t.getInt(), l = a >> 2, h = 0, d = l, p = 2 * l, g = 3 * l, v = 0, y = 0, m = 0, b = 0; h < l; h += 1, d += 1, p += 1, g += 1) { 39198 var _ = 255 & r[v].R[i.get(s, n.TF_SHIFT)], 39199 w = 255 & r[y].R[i.get(u, n.TF_SHIFT)], 39200 x = 255 & r[m].R[i.get(f, n.TF_SHIFT)], 39201 E = 255 & r[b].R[i.get(c, n.TF_SHIFT)]; 39202 39203 e.putAt(h, _), e.putAt(d, w), e.putAt(p, x), e.putAt(g, E), s = i.advanceSymbolStep(s, o[v][_], n.TF_SHIFT), u = i.advanceSymbolStep(u, o[y][w], n.TF_SHIFT), f = i.advanceSymbolStep(f, o[m][x], n.TF_SHIFT), c = i.advanceSymbolStep(c, o[b][E], n.TF_SHIFT), s = i.renormalize(s, t), u = i.renormalize(u, t), f = i.renormalize(f, t), c = i.renormalize(c, t), v = _, y = w, m = x, b = E; 39204 } 39205 39206 for (; g < a; g += 1) { 39207 var S = 255 & r[b].R[i.get(c, n.TF_SHIFT)]; 39208 e.putAt(g, S), c = i.advanceSymbol(c, t, o[b][S], n.TF_SHIFT), b = S; 39209 } 39210 } 39211 }; 39212 }, function (t, e, r) { 39213 39214 var n = r(1), 39215 i = n(r(98)), 39216 o = n(r(16)), 39217 a = n(r(75)), 39218 s = r(326).Parser, 39219 u = new s().itf8(), 39220 f = { 39221 parser: new s().string("magic", { 39222 length: 4 39223 }).uint8("majorVersion").uint8("minorVersion").string("fileId", { 39224 length: 20,
39225 stripNull: !0 39226 }), 39227 maxLength: 26 39228 }, 39229 c = { 39230 parser: new s().uint8("compressionMethod", { 39231 formatter: function (t) { 39232 var e = ["raw", "gzip", "bzip2", "lzma", "rans"][t]; 39233 if (!e) throw new Error("compression method number ".concat(t, " not implemented")); 39234 return e; 39235 } 39236 }).uint8("contentType", { 39237 formatter: function (t) { 39238 var e = ["FILE_HEADER", "COMPRESSION_HEADER", "MAPPED_SLICE_HEADER", "UNMAPPED_SLICE_HEADER", "EXTERNAL_DATA", "CORE_DATA"][t]; 39239 if (!e) throw new Error("invalid block content type id ".concat(t)); 39240 return e; 39241 } 39242 }).itf8("contentId").itf8("compressedSize").itf8("uncompressedSize"), 39243 maxLength: 17 39244 }, 39245 l = { 39246 parser: new s().uint32("crc32"), 39247 maxLength: 4 39248 }, 39249 h = new s().itf8("size").buffer("ents", { 39250 length: "size", 39251 formatter: function (t) { 39252 function e(e, r) { 39253 for (var n = t.toString("utf8", e, r), i = [], o = 0; o < n.length; o += 3) i.push(n.substr(o, 3)); 39254 39255 return i; 39256 } 39257 39258 var r, 39259 n = [], 39260 i = 0; 39261 39262 for (r = 0; r < t.length; r += 1) t[r] || (n.push(e(i, r)), i = r + 1); 39263 39264 return r > i && n.push(e(i, r)), n; 39265 } 39266 }), 39267 d = new s().uint8(null, { 39268 formatter: function (t) { 39269 return !!t; 39270 } 39271 }), 39272 p = new s().itf8("mapSize").itf8("mapCount").array("ents", { 39273 length: "mapCount", 39274 type: new s().string("key", { 39275 length: 2, 39276 stripNull: !1 39277 }).choice("value", { 39278 tag: "key", 39279 choices: { 39280 MI: d, 39281 UI: d, 39282 PI: d, 39283 RN: d, 39284 AP: d, 39285 RR: d, 39286 SM: new s().array(null, { 39287 type: "uint8", 39288 length: 5 39289 }), 39290 TD: new s().nest(null, { 39291 type: h, 39292 formatter: function (t) { 39293 return t.ents; 39294 } 39295 }) 39296 } 39297 }) 39298 }); 39299 39300 function g(t) { 39301 for (var e = {}, r = 0; r < t.ents.length; r += 1) { 39302 var n = t.ents[r], 39303 i = n.key, 39304 o = n.value; 39305 e[i] && console.warn("duplicate key ".concat(i, " in map")), e[i] = o; 39306 } 39307 39308 return e; 39309 } 39310 39311 var v = { 39312 cramFileDefinition: f, 39313 cramBlockHeader: c, 39314 cramBlockCrc32: l 39315 }, 39316 y = { 39317 cramUnmappedSliceHeader: function (t) { 39318 var e = 0, 39319 r = new s().itf8("numRecords"); 39320 e += 5, t >= 3 ? (r = r.ltf8("recordCounter"), e += 9) : 2 === t && (r = r.itf8("recordCounter"), e += 5), r = r.itf8("numBlocks").itf8("numContentIds").array("contentIds", { 39321 type: u, 39322 length: "numContentIds" 39323 }), e += 10, t >= 2 && (r = r.array("md5", { 39324 type: "uint8", 39325 length: 16 39326 }), e += 16); 39327 return { 39328 parser: r, 39329 maxLength: function (t) { 39330 return e + 5 * t; 39331 } 39332 }; 39333 }, 39334 cramMappedSliceHeader: function (t) { 39335 var e = new s().itf8("refSeqId").itf8("refSeqStart").itf8("refSeqSpan").itf8("numRecords"), 39336 r = 20; 39337 t >= 3 ? (e = e.ltf8("recordCounter"), r += 9) : 2 === t && (e = e.itf8("recordCounter"), r += 5), e = e.itf8("numBlocks").itf8("numContentIds").array("contentIds", { 39338 type: u, 39339 length: "numContentIds" 39340 }).itf8("refBaseBlockId"), r += 15, t >= 2 && (e = e.array("md5", { 39341 type: "uint8", 39342 length: 16 39343 }), r += 16); 39344 return { 39345 parser: e, 39346 maxLength: function (t) { 39347 return r + 5 * t; 39348 } 39349 }; 39350 }, 39351 cramEncoding: function (t) { 39352 return { 39353 parser: new s().namely("cramEncoding").itf8("codecId").itf8("parametersBytes").choice("parameters", { 39354 tag: "codecId", 39355 choices: { 39356 0: new s(), 39357 1: new s().itf8("blockContentId"), 39358 2: new s().itf8("offset").itf8("M"),
39359 3: s.start().itf8("numCodes").array("symbols", { 39360 length: "numCodes", 39361 type: u 39362 }).itf8("numLengths").array("bitLengths", { 39363 length: "numLengths", 39364 type: u 39365 }), 39366 4: s.start().nest("lengthsEncoding", { 39367 type: "cramEncoding" 39368 }).nest("valuesEncoding", { 39369 type: "cramEncoding" 39370 }), 39371 5: new s().uint8("stopByte")[t > 1 ? "itf8" : "int"]("blockContentId"), 39372 6: new s().itf8("offset").itf8("length"), 39373 7: new s().itf8("offset").itf8("K"), 39374 8: new s().itf8("offset").itf8("log2m"), 39375 9: new s().itf8("offset") 39376 } 39377 }) 39378 }; 39379 }, 39380 cramDataSeriesEncodingMap: function (t) { 39381 return new s().itf8("mapSize").itf8("mapCount").array("ents", { 39382 length: "mapCount", 39383 type: new s().string("key", { 39384 length: 2, 39385 stripNull: !1 39386 }).nest("value", { 39387 type: this.cramEncoding(t).parser 39388 }) 39389 }); 39390 }, 39391 cramTagEncodingMap: function (t) { 39392 return new s().itf8("mapSize").itf8("mapCount").array("ents", { 39393 length: "mapCount", 39394 type: new s().itf8("key", { 39395 formatter: function (t) { 39396 return String.fromCharCode(t >> 16 & 255) + String.fromCharCode(t >> 8 & 255) + String.fromCharCode(255 & t); 39397 } 39398 }).nest("value", { 39399 type: this.cramEncoding(t).parser 39400 }) 39401 }); 39402 }, 39403 cramCompressionHeader: function (t) { 39404 var e = new s(); 39405 return { 39406 parser: e = e.nest("preservation", { 39407 type: p, 39408 formatter: g 39409 }).nest("dataSeriesEncoding", { 39410 type: this.cramDataSeriesEncodingMap(t), 39411 formatter: g 39412 }).nest("tagEncoding", { 39413 type: this.cramTagEncodingMap(t), 39414 formatter: g 39415 }) 39416 }; 39417 }, 39418 cramContainerHeader1: function (t) { 39419 var e = new s().int32("length").itf8("refSeqId").itf8("refSeqStart").itf8("alignmentSpan").itf8("numRecords"), 39420 r = 24; 39421 return t >= 3 ? (e = e.ltf8("recordCounter"), r += 9) : 2 === t && (e = e.itf8("recordCounter"), r += 5), t > 1 && (e = e.ltf8("numBases"), r += 9), { 39422 parser: e = e.itf8("numBlocks").itf8("numLandmarks"), 39423 maxLength: r += 10 39424 }; 39425 }, 39426 cramContainerHeader2: function (t) { 39427 var e = new s().itf8("numLandmarks").array("landmarks", { 39428 type: new s().itf8(), 39429 length: "numLandmarks" 39430 }), 39431 r = 0; 39432 return t >= 3 && (e = e.uint32("crc32"), r = 4), { 39433 parser: e, 39434 maxLength: function (t) { 39435 return 5 + 5 * t + r; 39436 } 39437 }; 39438 } 39439 }; 39440 t.exports = { 39441 cramFileDefinition: f, 39442 getSectionParsers: function (t) { 39443 var e, 39444 r = (0, a.default)({}, v); 39445 return (0, o.default)(e = (0, i.default)(y)).call(e, function (e) { 39446 r[e] = y[e](t); 39447 }), r; 39448 } 39449 }; 39450 }, function (t, e, r) { 39451 t.exports = r(320); 39452 }, function (t, e, r) { 39453 r(321); 39454 var n = r(3); 39455 t.exports = n.Object.keys; 39456 }, function (t, e, r) { 39457 var n = r(0), 39458 i = r(22), 39459 o = r(51); 39460 n({ 39461 target: "Object", 39462 stat: !0, 39463 forced: r(12)(function () { 39464 o(1); 39465 }) 39466 }, { 39467 keys: function (t) { 39468 return o(i(t)); 39469 } 39470 }); 39471 }, function (t, e, r) { 39472 t.exports = r(323); 39473 }, function (t, e, r) { 39474 r(324); 39475 var n = r(3); 39476 t.exports = n.Object.assign; 39477 }, function (t, e, r) { 39478 var n = r(0), 39479 i = r(325); 39480 n({ 39481 target: "Object", 39482 stat: !0, 39483 forced: Object.assign !== i 39484 }, { 39485 assign: i 39486 }); 39487 }, function (t, e, r) { 39488 39489 var n = r(17), 39490 i = r(12), 39491 o = r(51), 39492 a = r(138), 39493 s = r(65), 39494 u = r(22), 39495 f = r(60), 39496 c = Object.assign; 39497 t.exports = !c || i(function () { 39498 var t = {}, 39499 e = {}, 39500 r = Symbol(); 39501 return t[r] = 7, "abcdefghijklmnopqrst".split("").forEach(function (t) { 39502 e[t] = t; 39503 }), 7 != c({}, t)[r] || "abcdefghijklmnopqrst" != o(c({}, e)).join(""); 39504 }) ? function (t, e) { 39505 for (var r = u(t), i = arguments.length, c = 1, l = a.f, h = s.f; i > c;) for (var d, p = f(arguments[c++]), g = l ? o(p).concat(l(p)) : o(p), v = g.length, y = 0; v > y;) d = g[y++], n && !h.call(p, d) || (r[d] = p[d]); 39506 39507 return r; 39508 } : c; 39509 }, function (t, e, r) { 39510 39511 (function (t) { 39512 function n(t) { 39513 return (n = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (t) { 39514 return typeof t; 39515 } : function (t) { 39516 return t && "function" == typeof Symbol && t.constructor === Symbol && t !== Symbol.prototype ? "symbol" : typeof t; 39517 })(t); 39518 } 39519 39520 var i = r(327), 39521 o = r(328).Context, 39522 a = r(146); 39523 "undefined" != typeof window && (window.Buffer = t), "undefined" != typeof self && (self.Buffer = t); 39524 var s = { 39525 UInt8: 1, 39526 UInt16LE: 2, 39527 UInt16BE: 2, 39528 UInt32LE: 4, 39529 UInt32BE: 4, 39530 Int8: 1, 39531 Int16LE: 2, 39532 Int16BE: 2, 39533 Int32LE: 4, 39534 Int32BE: 4, 39535 FloatLE: 4, 39536 FloatBE: 4, 39537 DoubleLE: 8, 39538 DoubleBE: 8, 39539 UInt64: 8, 39540 Int64: 8 39541 }, 39542 u = {}, 39543 f = []; 39544 !function () { 39545 var t; 39546 39547 for (t = 1; t <= 32; t++) f.push(t); 39548 }(); 39549 var c = {}; 39550 Object.keys(s).concat(Object.keys({ 39551 String: null, 39552 Buffer: null, 39553 Array: null, 39554 Skip: null, 39555 Choice: null, 39556 Nest: null, 39557 Bit: null, 39558 Itf8: null, 39559 Ltf8: null 39560 }
39560)).forEach(function (t) { 39561 c[t.toLowerCase()] = t; 39562 }); 39563 39564 var l = function () { 39565 this.varName = "", this.type = "", this.options = {}, this.next = null, this.head = null, this.compiled = null, this.endian = "le", this.constructorFn = null, this.alias = null; 39566 }; 39567 39568 l.start = function () { 39569 return new l(); 39570 }, Object.keys(s).forEach(function (t) { 39571 l.prototype[t.toLowerCase()] = function (e, r) { 39572 return this.setNextParser(t.toLowerCase(), e, r); 39573 }; 39574 39575 var e = t.replace(/BE|LE/, "").toLowerCase(); 39576 e in l.prototype || (l.prototype[e] = function (t, r) { 39577 return this[e + this.endian](t, r); 39578 }); 39579 }), f.forEach(function (t) { 39580 l.prototype["bit".concat(t.toString())] = function (e, r) { 39581 return r || (r = {}), r.length = t, this.setNextParser("bit", e, r); 39582 }; 39583 }), l.prototype.namely = function (t) { 39584 return u[t] = this, this.alias = t, this; 39585 }, l.prototype.skip = function (t, e) { 39586 if (e && e.assert) throw new Error("assert option on skip is not allowed."); 39587 return this.setNextParser("skip", "", { 39588 length: t 39589 }); 39590 }, l.prototype.string = function (t, e) { 39591 if (!e.zeroTerminated && !e.length && !e.greedy) throw new Error("Neither length, zeroTerminated, nor greedy is defined for string."); 39592 if ((e.zeroTerminated || e.length) && e.greedy) throw new Error("greedy is mutually exclusive with length and zeroTerminated for string."); 39593 if (e.stripNull && !e.length && !e.greedy) throw new Error("Length or greedy must be defined if stripNull is defined."); 39594 return e.encoding = e.encoding || "utf8", this.setNextParser("string", t, e); 39595 }, l.prototype.buffer = function (t, e) { 39596 if (!e.length && !e.readUntil) throw new Error("Length nor readUntil is defined in buffer parser"); 39597 return this.setNextParser("buffer", t, e); 39598 }, l.prototype.array = function (t, e) { 39599 if (!e.readUntil && !e.length && !e.lengthInBytes) throw new Error("Length option of array is not defined."); 39600 if (!e.type) throw new Error("Type option of array is not defined."); 39601 if ("string" == typeof e.type && !u[e.type] && Object.keys(s).indexOf(c[e.type]) < 0) throw new Error('Specified primitive type "'.concat(e.type, '" is not supported.')); 39602 return this.setNextParser("array", t, e); 39603 }, l.prototype.choice = function (t, e) { 39604 if (1 === arguments.length && "object" === n(t) && (e = t, t = null), !e.tag) throw new Error("Tag option of array is not defined."); 39605 if (!e.choices) throw new Error("Choices option of array is not defined."); 39606 return Object.keys(e.choices).forEach(function (r) { 39607 if (!e.choices[r]) throw new Error("Choice Case ".concat(r, " of ").concat(t, " is not valid.")); 39608 if ("string" == typeof e.choices[r] && !u[e.choices[r]] && Object.keys(s).indexOf(c[e.choices[r]]) < 0) throw new Error('Specified primitive type "'.concat(e.choices[r], '" is not supported.')); 39609 }, this), this.setNextParser("choice", t, e); 39610 }, l.prototype.nest = function (t, e) { 39611 if (1 === arguments.length && "object" === n(t) && (e = t, t = null), !e.type) throw new Error("Type option of nest is not defined."); 39612 if (!(e.type instanceof l || u[e.type])) throw new Error("Type option of nest must be a Parser object."); 39613 if (!(e.type instanceof l || t)) throw new Error("options.type must be a object if variable name is omitted."); 39614 return this.setNextParser("nest", t, e); 39615 }, l.prototype.endianess = function (t) { 39616 switch (t.toLowerCase()) { 39617 case "little": 39618 this.endian = "le"; 39619 break; 39620 39621 case "big": 39622 this.endian = "be"; 39623 break; 39624 39625 default: 39626 throw new Error("Invalid endianess: ".concat(t)); 39627 } 39628 39629 return this; 39630 }, l.prototype.create = function (t) { 39631 if (!(t instanceof Function)) throw new Error("Constructor must be a Function object."); 39632 return this.constructorFn = t, this; 39633 }, l.prototype.getCode = function () { 39634 var t = new o(); 39635 return t.pushCode("if (!Buffer.isBuffer(buffer)) {"), t.generateError('"argument buffer is not a Buffer object"'), t.pushCode("}"), this.alias ? this.addAliasedCode(t) : this.addRawCode(t), this.alias ? t.pushCode("return {0}(0)", "___parser_" + this.alias) : t.pushCode("return { offset: offset, result: vars };"), t.code; 39636 }, l.prototype.addRawCode = function (t) { 39637 t.pushCode("var offset = 0;"), this.constructorFn ? t.pushCode("var vars = new constructorFn();") : t.pushCode("var vars = {};"), this.generate(t), this.resolveReferences(t), t.pushCode("return { offset: offset, result: vars };"); 39638 }, l.prototype.addAliasedCode = function (t) { 39639 return t.pushCode("function {0}(offset) {", "___parser_" + this.alias), this.constructorFn ? t.pushCode("var vars = new constructorFn();") : t.pushCode("var vars = {};"), this.generate(t), t.markResolved(this.alias), this.resolveReferences(t), t.pushCode("return { offset: offset, result: vars };"), t.pushCode("}"), t; 39640 }, l.prototype.resolveReferences = function (t) { 39641 var e = t.getUnresolvedReferences(); 39642 t.markRequested(e), e.forEach(function (e) { 39643 u[e].addAliasedCode(t); 39644 }); 39645 }, l.prototype.compile = function () { 39646 var t = "(function(buffer, constructorFn, Long) { ".concat(this.getCode(), " })"); 39647 this.compiled = i.runInThisContext(t); 39648 }, l.prototype.sizeOf = function () { 39649 var t = NaN; 39650 if (Object.keys(s).indexOf(this.type) >= 0) t = s[this.type];else if ("String" === this.type && "number" == typeof this.options.length) t = this.options.length;else if ("Buffer" === this.type && "number" == typeof this.options.length) t = this.options.length;else if ("Array" === this.type && "number" == typeof this.options.length) { 39651 var e = NaN; 39652 "string" == typeof this.options.type ? e = s[c[this.options.type]] : this.options.type instanceof l && (e = this.options.type.sizeOf()), t = this.options.length * e; 39653 } else "Skip" === this.type ? t = this.options.length : "Nest" === this.type ? t = this.options.type.sizeOf() : this.type || (t = 0); 39654 return this.next && (t += this.next.sizeOf()), t; 39655 }, l.prototype.parse = function (t) { 39656 return this.compiled || this.compile(), this.compiled(t, this.constructorFn, a); 39657 }, l.prototype.setNextParser = function (t, e, r) { 39658 var n = new l(); 39659 return n.type = c[t], n.varName = e, n.options = r || n.options, n.endian = this.endian, this.head ? this.head.next = n : this.next = n, this.head = n, this; 39660 }, l.prototype.generate = function (t) {
39661 this.type && (this["generate".concat(this.type)](t), this.generateAssert(t)); 39662 var e = t.generateVariable(this.varName); 39663 return this.options.formatter && this.generateFormatter(t, e, this.options.formatter), this.generateNext(t); 39664 }, l.prototype.generateAssert = function (t) { 39665 if (this.options.assert) { 39666 var e = t.generateVariable(this.varName); 39667 39668 switch (n(this.options.assert)) { 39669 case "function": 39670 t.pushCode("if (!({0}).call(vars, {1})) {", this.options.assert, e); 39671 break; 39672 39673 case "number": 39674 t.pushCode("if ({0} !== {1}) {", this.options.assert, e); 39675 break; 39676 39677 case "string": 39678 t.pushCode('if ("{0}" !== {1}) {', this.options.assert, e); 39679 break; 39680 39681 default: 39682 throw new Error("Assert option supports only strings, numbers and assert functions."); 39683 } 39684 39685 t.generateError('"Assert error: {0} is " + {0}', e), t.pushCode("}"); 39686 } 39687 }, l.prototype.generateNext = function (t) { 39688 return this.next && (t = this.next.generate(t)), t; 39689 }, Object.keys(s).forEach(function (t) { 39690 l.prototype["generate".concat(t)] = function (e) { 39691 "UInt64" === t ? e.pushCode("{0} = Long.fromBytes(buffer.slice(offset,offset+8), true, this.endian === 'le').toNumber();", e.generateVariable(this.varName), t) : "Int64" === t ? e.pushCode("{0} = Long.fromBytes(buffer.slice(offset,offset+8), false, this.endian === 'le').toNumber();", e.generateVariable(this.varName), t) : e.pushCode("{0} = buffer.read{1}(offset);", e.generateVariable(this.varName), t), e.pushCode("offset += {0};", s[t]); 39692 }; 39693 }), l.prototype.generateBit = function (t) { 39694 var e = JSON.parse(JSON.stringify(this)); 39695 39696 if (e.varName = t.generateVariable(e.varName), t.bitFields.push(e), !this.next || this.next && ["Bit", "Nest"].indexOf(this.next.type) < 0) { 39697 var r = 0; 39698 t.bitFields.forEach(function (t) { 39699 r += t.options.length; 39700 }); 39701 var n = t.generateTmpVariable(); 39702 if (r <= 8) t.pushCode("var {0} = buffer.readUInt8(offset);", n), r = 8;else if (r <= 16) t.pushCode("var {0} = buffer.readUInt16BE(offset);", n), r = 16;else if (r <= 24) { 39703 var i = t.generateTmpVariable(), 39704 o = t.generateTmpVariable(); 39705 t.pushCode("var {0} = buffer.readUInt16BE(offset);", i), t.pushCode("var {0} = buffer.readUInt8(offset + 2);", o), t.pushCode("var {2} = ({0} << 8) | {1};", i, o, n), r = 24; 39706 } else { 39707 if (!(r <= 32)) throw new Error("Currently, bit field sequence longer than 4-bytes is not supported."); 39708 t.pushCode("var {0} = buffer.readUInt32BE(offset);", n), r = 32; 39709 } 39710 t.pushCode("offset += {0};", r / 8); 39711 var a = 0, 39712 s = "be" === this.endian; 39713 t.bitFields.forEach(function (e) { 39714 t.pushCode("{0} = {1} >> {2} & {3};", e.varName, n, s ? r - a - e.options.length : a, (1 << e.options.length) - 1), a += e.options.length; 39715 }), t.bitFields = []; 39716 } 39717 }, l.prototype.generateSkip = function (t) { 39718 var e = t.generateOption(this.options.length); 39719 t.pushCode("offset += {0};", e); 39720 }, l.prototype.generateString = function (t) { 39721 var e = t.generateVariable(this.varName), 39722 r = t.generateTmpVariable(); 39723 this.options.length && this.options.zeroTerminated ? (t.pushCode("var {0} = offset;", r), t.pushCode("while(buffer.readUInt8(offset++) !== 0 && offset - {0} < {1});", r, this.options.length), t.pushCode("{0} = buffer.toString('{1}', {2}, offset - {2} < {3} ? offset - 1 : offset);", e, this.options.encoding, r, this.options.length)) : this.options.length ? (t.pushCode("{0} = buffer.toString('{1}', offset, offset + {2});", e, this.options.encoding, t.generateOption(this.options.length)), t.pushCode("offset += {0};", t.generateOption(this.options.length))) : this.options.zeroTerminated ? (t.pushCode("var {0} = offset;", r), t.pushCode("while(buffer.readUInt8(offset++) !== 0);"), t.pushCode("{0} = buffer.toString('{1}', {2}, offset - 1);", e, this.options.encoding, r)) : this.options.greedy && (t.pushCode("var {0} = offset;", r), t.pushCode("while(buffer.length > offset++);"), t.pushCode("{0} = buffer.toString('{1}', {2}, offset);", e, this.options.encoding, r)), this.options.stripNull && t.pushCode("{0} = {0}.replace(/\\x00+$/g, '')", e); 39724 }, l.prototype.generateBuffer = function (t) { 39725 "eof" === this.options.readUntil ? t.pushCode("{0} = buffer.slice(offset);", t.generateVariable(this.varName)) : (t.pushCode("{0} = buffer.slice(offset, offset + {1});", t.generateVariable(this.varName), t.generateOption(this.options.length)), t.pushCode("offset += {0};", t.generateOption(this.options.length))), this.options.clone && t.pushCode("{0} = Buffer.from({0});", t.generateVariable(this.varName)); 39726 }, l.prototype.generateArray = function (t) { 39727 var e = t.generateOption(this.options.length), 39728 r = t.generateOption(this.options.lengthInBytes), 39729 n = this.options.type, 39730 i = t.generateTmpVariable(), 39731 o = t.generateVariable(this.varName), 39732 a = t.generateTmpVariable(), 39733 f = this.options.key, 39734 h = "string" == typeof f; 39735 if (h ? t.pushCode("{0} = {};", o) : t.pushCode("{0} = [];", o), "function" == typeof this.options.readUntil ? t.pushCode("do {") : "eof" === this.options.readUntil ? t.pushCode("for (var {0} = 0; offset < buffer.length; {0}++) {", i) : void 0 !== r ? t.pushCode("for (var {0} = offset; offset - {0} < {1}; ) {", i, r) : t.pushCode("for (var {0} = 0; {0} < {1}; {0}++) {", i, e), "string" == typeof n) { 39736 if (u[n]) { 39737 var d = t.generateTmpVariable(); 39738 t.pushCode("var {0} = {1}(offset);", d, "___parser_" + n), t.pushCode("var {0} = {1}.result; offset = {1}.offset;", a, d), n !== this.alias && t.addReference(n); 39739 } else t.pushCode("var {0} = buffer.read{1}(offset);", a, c[n]), t.pushCode("offset += {0};", s[c[n]]); 39740 } else n instanceof l && (t.pushCode("var {0} = {};", a), t.pushScope(a), n.generate(t), t.popScope()); 39741 h ? t.pushCode("{0}[{2}.{1}] = {2};", o, f, a) : t.pushCode("{0}.push({1});", o, a), t.pushCode("}"), "function" == typeof this.options.readUntil && t.pushCode(" while (!({0}).call(this, {1}, buffer.slice(offset)));", this.options.readUntil, a); 39742 }, l.prototype.generateChoiceCase = function (t, e, r) { 39743 if ("string" == typeof r) { 39744 if (u[r]) { 39745 var n = t.generateTmpVariable(); 39746 t.pushCode("var {0} = {1}(offset);", n, "___parser_" + r), t.pushCode("{0} = {1}.result; offset = {1}.offset;", t.generateVariable(this.varName), n), r !== this.alias && t.addReference(r); 39747 } else t.pushCode("{0} = buffer.read{1}(offset);", t.generateVariable(this.varName), c[r]), t.pushCode("offset += {0};", s[c[r]]); 39748 } else r instanceof l && (t.pushPath(e), r.generate(t), t.popPath(e)); 39749 }, l.prototype.generateChoice = function (t) { 39750 var e = t.generateOption(this.options.tag); 39751 this.varName && t.pushCode("{0} = {};", t.generateVariable(this.varName)), t.pushCode("switch({0}
39751) {", e), Object.keys(this.options.choices).forEach(function (e) { 39752 var r = this.options.choices[e]; 39753 Number.isNaN(parseInt(e, 10)) ? t.pushCode("case '{0}':", e) : t.pushCode("case {0}:", e), this.generateChoiceCase(t, this.varName, r), t.pushCode("break;"); 39754 }, this), t.pushCode("default:"), this.options.defaultChoice ? this.generateChoiceCase(t, this.varName, this.options.defaultChoice) : t.generateError('"Met undefined tag value " + {0} + " at choice"', e), t.pushCode("}"); 39755 }, l.prototype.generateNest = function (t) { 39756 var e = t.generateVariable(this.varName); 39757 if (this.options.type instanceof l) this.varName && t.pushCode("{0} = {};", e), t.pushPath(this.varName), this.options.type.generate(t), t.popPath(this.varName);else if (u[this.options.type]) { 39758 var r = t.generateTmpVariable(); 39759 t.pushCode("var {0} = {1}(offset);", r, "___parser_" + this.options.type), t.pushCode("{0} = {1}.result; offset = {1}.offset;", e, r), this.options.type !== this.alias && t.addReference(this.options.type); 39760 } 39761 }, l.prototype.generateFormatter = function (t, e, r) { 39762 "function" == typeof r && t.pushCode("{0} = ({1}).call(this, {0});", e, r); 39763 }, l.prototype.isInteger = function () { 39764 return !!this.type.match(/U?Int[8|16|32][BE|LE]?|Bit\d+/); 39765 }, l.prototype.itf8 = function (t, e) { 39766 return this.setNextParser("itf8", t, e); 39767 }, l.prototype.itf8 = function (t, e) { 39768 return this.setNextParser("itf8", t, e); 39769 }, l.prototype.generateItf8 = function (t) { 39770 var e = t.generateVariable(this.varName), 39771 r = t.generateTmpVariable(); 39772 t.pushCode("\n var ".concat(r, " = buffer[offset];\n if (").concat(r, " < 0x80) {\n ").concat(e, " = ").concat(r, ";\n offset += 1;\n } else if (").concat(r, " < 0xc0) {\n ").concat(e, " = ((").concat(r, "<<8) | buffer[offset+1]) & 0x3fff;\n offset += 2;\n } else if (").concat(r, " < 0xe0) {\n ").concat(e, " = ((").concat(r, "<<16) | (buffer[offset+1]<< 8) | buffer[offset+2]) & 0x1fffff;\n offset += 3;\n } else if (").concat(r, " < 0xf0) {\n ").concat(e, " = ((").concat(r, "<<24) | (buffer[offset+1]<<16) | (buffer[offset+2]<<8) | buffer[offset+3]) & 0x0fffffff;\n offset += 4\n } else {\n ").concat(e, " = ((").concat(r, " & 0x0f)<<28) | (buffer[offset+1]<<20) | (buffer[offset+2]<<12) | (buffer[offset+3]<<4) | (buffer[offset+4] & 0x0f);\n // x=((0xff & 0x0f)<<28) | (0xff<<20) | (0xff<<12) | (0xff<<4) | (0x0f & 0x0f);\n // TODO *val_p = uv < 0x80000000UL ? uv : -((int32_t) (0xffffffffUL - uv)) - 1;\n offset += 5\n }\n ")); 39773 }, l.prototype.ltf8 = function (t, e) { 39774 return this.setNextParser("ltf8", t, e); 39775 }, l.prototype.generateLtf8 = function (t) { 39776 var e = t.generateVariable(this.varName), 39777 r = t.generateTmpVariable(); 39778 t.pushCode("\n var ".concat(r, " = buffer[offset];\n if (").concat(r, " < 0x80) {\n ").concat(e, " = ").concat(r, ";\n offset += 1;\n } else if (").concat(r, " < 0xc0) {\n ").concat(e, " = ((buffer[offset]<<8) | buffer[offset+1]) & 0x3fff;\n offset += 2;\n } else if (").concat(r, " < 0xe0) {\n ").concat(e, " = ((buffer[offset]<<16) | (buffer[offset+1]<<8) | buffer[offset+2]) & 0x1fffff;\n ").concat(e, " = (((").concat(r, " & 63) << 16) | buffer.readUInt16LE(offset + 1));\n offset += 3;\n } else if (").concat(r, " < 0xf0) {\n ").concat(e, " = ((buffer[offset]<<24) | (buffer[offset+1]<<16) | (buffer[offset+2]<<8) | buffer[offset+3]) & 0x0fffffff;\n offset += 4;\n } else if (").concat(r, " < 0xf8) {\n ").concat(e, " = (((buffer[offset] & 15) * Math.pow(2,32))) +\n (buffer[offset+1]<<24) | (buffer[offset+2]<<16 | buffer[offset+3]<<8 | buffer[offset+4])\n // TODO *val_p = uv < 0x80000000UL ? uv : -((int32_t) (0xffffffffUL - uv)) - 1;\n offset += 5;\n } else if (").concat(r, " < 0xfc) {\n ").concat(e, " = ((((buffer[offset] & 7) << 8) | buffer[offset+1] )) * Math.pow(2,32) +\n (buffer[offset+2]<<24) | (buffer[offset+3]<<16 | buffer[offset+4]<<8 | buffer[offset+5])\n offset += 6;\n } else if (").concat(r, " < 0xfe) {\n ").concat(e, " = ((((buffer[offset] & 3) << 16) | buffer[offset+1]<<8 | buffer[offset+2])) * Math.pow(2,32) +\n (buffer[offset+3]<<24) | (buffer[offset+4]<<16 | buffer[offset+5]<<8 | buffer[offset+6])\n offset += 7;\n } else if (").concat(r, " < 0xff) {\n ").concat(e, " = Long.fromBytesBE(buffer.slice(offset+1,offset+8));\n if (").concat(e, ".greaterThan(Number.MAX_SAFE_INTEGER) || ").concat(e, ".lessThan(Number.MIN_SAFE_INTEGER))\n throw new Error('integer overflow')\n ").concat(e, " = ").concat(e, ".toNumber()\n offset += 8;\n } else {\n ").concat(e, " = Long.fromBytesBE(buffer.slice(offset+1,offset+9));\n if (").concat(e, ".greaterThan(Number.MAX_SAFE_INTEGER) || ").concat(e, ".lessThan(Number.MIN_SAFE_INTEGER))\n throw new Error('integer overflow')\n ").concat(e, " = ").concat(e, ".toNumber()\n offset += 9;\n }\n ")); 39779 }, e.Parser = l; 39780 }).call(this, r(19).Buffer); 39781 }
39781, function (module, exports) { 39782 var indexOf = function (t, e) { 39783 if (t.indexOf) return t.indexOf(e); 39784 39785 for (var r = 0; r < t.length; r++) if (t[r] === e) return r; 39786 39787 return -1; 39788 }, 39789 Object_keys = function (t) { 39790 if (Object.keys) return Object.keys(t); 39791 var e = []; 39792 39793 for (var r in t) e.push(r); 39794 39795 return e; 39796 }, 39797 forEach = function (t, e) { 39798 if (t.forEach) return t.forEach(e); 39799 39800 for (var r = 0; r < t.length; r++) e(t[r], r, t); 39801 }, 39802 defineProp = function () { 39803 try { 39804 return Object.defineProperty({}, "_", {}), function (t, e, r) { 39805 Object.defineProperty(t, e, { 39806 writable: !0, 39807 enumerable: !1, 39808 configurable: !0, 39809 value: r 39810 }); 39811 }; 39812 } catch (t) { 39813 return function (t, e, r) { 39814 t[e] = r; 39815 }; 39816 } 39817 }(), 39818 globals = ["Array", "Boolean", "Date", "Error", "EvalError", "Function", "Infinity", "JSON", "Math", "NaN", "Number", "Object", "RangeError", "ReferenceError", "RegExp", "String", "SyntaxError", "TypeError", "URIError", "decodeURI", "decodeURIComponent", "encodeURI", "encodeURIComponent", "escape", "eval", "isFinite", "isNaN", "parseFloat", "parseInt", "undefined", "unescape"]; 39819 39820 function Context() {} 39821 39822 Context.prototype = {}; 39823 39824 var Script = exports.Script = function (t) { 39825 if (!(this instanceof Script)) return new Script(t); 39826 this.code = t; 39827 }; 39828 39829 Script.prototype.runInContext = function (t) { 39830 if (!(t instanceof Context)) throw new TypeError("needs a 'context' argument."); 39831 var e = document.createElement("iframe"); 39832 e.style || (e.style = {}), e.style.display = "none", document.body.appendChild(e); 39833 var r = e.contentWindow, 39834 n = r.eval, 39835 i = r.execScript; 39836 !n && i && (i.call(r, "null"), n = r.eval), forEach(Object_keys(t), function (e) { 39837 r[e] = t[e]; 39838 }), forEach(globals, function (e) { 39839 t[e] && (r[e] = t[e]); 39840 }); 39841 var o = Object_keys(r), 39842 a = n.call(r, this.code); 39843 return forEach(Object_keys(r), function (e) { 39844 (e in t || -1 === indexOf(o, e)) && (t[e] = r[e]); 39845 }), forEach(globals, function (e) { 39846 e in t || defineProp(t, e, r[e]); 39847 }), document.body.removeChild(e), a; 39848 }, Script.prototype.runInThisContext = function () { 39849 return eval2(this.code); 39850 }, Script.prototype.runInNewContext = function (t) { 39851 var e = Script.createContext(t), 39852 r = this.runInContext(e); 39853 return t && forEach(Object_keys(e), function (r) { 39854 t[r] = e[r]; 39855 }), r; 39856 }, forEach(Object_keys(Script.prototype), function (t) { 39857 exports[t] = Script[t] = function (e) { 39858 var r = Script(e); 39859 return r[t].apply(r, [].slice.call(arguments, 1)); 39860 }; 39861 }), exports.isContext = function (t) { 39862 return t instanceof Context; 39863 }, exports.createScript = function (t) { 39864 return exports.Script(t); 39865 }, exports.createContext = Script.createContext = function (t) { 39866 var e = new Context(); 39867 return "object" == typeof t && forEach(Object_keys(t), function (r) { 39868 e[r] = t[r]; 39869 }), e; 39870 }; 39871 }, function (t, e, r) { 39872 39873 function n(t) { 39874 return (n = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (t) { 39875 return typeof t; 39876 } : function (t) { 39877 return t && "function" == typeof Symbol && t.constructor === Symbol && t !== Symbol.prototype ? "symbol" : typeof t; 39878 })(t); 39879 } 39880 39881 var i = function () { 39882 this.code = "", this.scopes = [["vars"]], this.isAsync = !1, this.bitFields = [], this.tmpVariableCount = 0, this.references = {}; 39883 }; 39884 39885 i.prototype.generateVariable = function (t) { 39886 var e = []; 39887 39888 for (Array.prototype.push.apply(e, this.scopes[this.scopes.length - 1]); /^\$parent\./.test(t);) e.pop(), t = t.replace(/^\$parent\./, ""); 39889 39890 return t && e.push(t), e.join("."); 39891 }, i.prototype.generateOption = function (t) { 39892 switch (n(t)) { 39893 case "number": 39894 return t.toString(); 39895 39896 case "string": 39897 return this.generateVariable(t); 39898 39899 case "function": 39900 return "(".concat(t, ").call(").concat(this.generateVariable(), ", vars)"); 39901 39902 default: 39903 return; 39904 } 39905 }, i.prototype.generateError = function () { 39906 var t = Array.prototype.slice.call(arguments), 39907 e = i.interpolate.apply(this, t); 39908 this.isAsync ? this.pushCode("return process.nextTick(function() { callback(new Error(".concat(e, "), vars); });")) : this.pushCode("throw new Error(".concat(e, ");")); 39909 }, i.prototype.generateTmpVariable = function () { 39910 return "$tmp".concat(this.tmpVariableCount++); 39911 }, i.prototype.pushCode = function () { 39912 var t = Array.prototype.slice.call(arguments); 39913 this.code += "".concat(i.interpolate.apply(this, t), "\n"); 39914 }, i.prototype.pushPath = function (t) { 39915 t && this.scopes[this.scopes.length - 1].push(t); 39916 }, i.prototype.popPath = function (t) { 39917 t && this.scopes[this.scopes.length - 1].pop(); 39918 }, i.prototype.pushScope = function (t) { 39919 this.scopes.push([t]); 39920 }, i.prototype.popScope = function () { 39921 this.scopes.pop(); 39922 }, i.prototype.addReference = function (t) { 39923 this.references[t] || (this.references[t] = { 39924 resolved: !1, 39925 requested: !1 39926 }); 39927 }, i.prototype.markResolved = function (t) { 39928 this.references[t].resolved = !0; 39929 }, i.prototype.markRequested = function (t) { 39930 t.forEach(function (t) { 39931 this.references[t].requested = !0; 39932 }.bind(this)); 39933 }, i.prototype.getUnresolvedReferences = function () { 39934 var t = this.references; 39935 return Object.keys(this.references).filter(function (e) { 39936 return !t[e].resolved && !t[e].requested; 39937 }); 39938 }, i.interpolate = function (t) { 39939 var e = /{\d+}/g, 39940 r = t.match(e), 39941 n = Array.prototype.slice.call(arguments, 1); 39942 return r && r.forEach(function (e) { 39943 var r = parseInt(e.substr(1, e.length - 2), 10); 39944 t = t.replace(e, n[r].toString()); 39945 }), t; 39946 }, e.Context = i; 39947 }, function (t, e, r) { 39948 39949 (function (e) { 39950 var n, 39951 i = r(1), 39952 o = i(r(16)), 39953 a = i(r(75)), 39954 s = i(r(37)), 39955 u = i(r(30)), 39956 f = i(r(31)), 39957 c = i(r(7)), 39958 l = i(r(10)), 39959 h = r(9).CramMalformedError, 39960 d = r(58), 39961 p = d.itf8Size, 39962 g = d.parseItem, 39963 v = d.tinyMemoize, 39964 y = r(334), 39965 m = r(390), 39966 b = function () { 39967 function t(e, r) { 39968 (0, c.default)(this, t), this.file = e, this.filePosition = r; 39969 } 39970 39971 var r, n, i, o; 39972 return (0, l.default)(t, [{ 39973 key: "getHeader", 39974 value: function () { 39975 return this._readContainerHeader(this.filePosition); 39976 } 39977 }, { 39978 key: "getCompressionHeaderBlock", 39979 value: (o = (0, f.default)(u.default.mark(function t() { 39980 var e, r, n; 39981 return u.default.wrap(function (t) { 39982 for (;;) switch (t.prev = t.next) { 39983 case 0: 39984 return t.next = 2, this.getHeader(); 39985 39986 case 2: 39987 if (t.sent.numRecords) { 39988 t.next = 5; 39989 break; 39990 } 39991 39992 return t.abrupt("return", null); 39993 39994 case 5: 39995 return t.next = 7, this.file.getSectionParsers(); 39996 39997 case 7: 39998 return e = t.sent, t.next = 10, this.getFirstBlock(); 39999 40000 case 10: 40001 if ("COMPRESSION_HEADER" === (r = t.sent).contentType) { 40002 t.next = 13; 40003 break; 40004 } 40005 40006 throw new h("invalid content type ".concat(r.contentType, " in what is supposed to be the compression header block")); 40007 40008 case 13: 40009 return n = g(r.content, e.cramCompressionHeader.parser, 0, r.contentPosition), r.content = n, t.abrupt("return", r); 40010 40011 case 16: 40012 case "end": 40013 return t.stop(); 40014 } 40015 }, t, this); 40016 })), function () { 40017 return o.apply(this, arguments); 40018 }) 40019 }, { 40020 key: "getFirstBlock", 40021 value: (i = (0, f.default)(u.default.mark(function t() { 40022 var e; 40023 return u.default.wrap(function (t) { 40024 for (;;) switch (t.prev = t.next) { 40025 case 0: 40026 return t.next = 2, this.getHeader(); 40027 40028 case 2: 40029 return e = t.sent, t.abrupt("return", this.file.readBlock(e._endPosition)); 40030 40031 case 4: 40032 case "end": 40033 return t.stop(); 40034 } 40035 }, t, this); 40036 })), function () { 40037 return i.apply(this, arguments); 40038 }) 40039 }, { 40040 key: "getCompressionScheme", 40041 value: (n = (0, f.default)(u.default.mark(function t() { 40042 var e; 40043 return u.default.wrap(function (t) { 40044 for (;;) switch (t.prev = t.next) { 40045 case 0: 40046 return t.next = 2, this.getCompressionHeaderBlock(); 40047 40048 case 2: 40049 if (e = t.sent) { 40050 t.next = 5; 40051 break; 40052 } 40053 40054 return t.abrupt("return", void 0); 40055 40056 case 5: 40057 return t.abrupt("return", new m(e.content)); 40058 40059 case 6: 40060 case "end": 40061 return t.stop(); 40062 } 40063 }, t, this); 40064 })), function () { 40065 return n.apply(this, arguments); 40066 }) 40067 }, { 40068 key: "getSlice", 40069 value: function (t, e) { 40070 return new y(this, t, e); 40071 } 40072 }, { 40073 key: "_readContainerHeader", 40074 value: (r = (0, f.default)(u.default.mark(function t(r) { 40075 var n, i, o, f, c, l, h, d, v, y, m, b, _; 40076 40077 return u.default.wrap(function (t) { 40078 for (;;) switch (t.prev = t.next) { 40079 case 0: 40080 return t.next = 2, this.file.getSectionParsers(); 40081 40082 case 2: 40083 return n = t.sent, i = n.cramContainerHeader1, o = n.cramContainerHeader2, t.next = 6, this.file.stat(); 40084 40085 case 6: 40086 if (f = t.sent, c = f.size, !(r >= c)) { 40087 t.next = 10; 40088 break; 40089 } 40090 40091 return t.abrupt("return", void 0); 40092 40093 case 10: 40094 return l = e.allocUnsafe(i.maxLength), t.next = 13, this.file.read(l, 0, i.maxLength, r); 40095 40096 case 13: 40097 if (h = g(l, i.parser), d = p(h.numLandmarks), !(r + h.length >= c)) { 40098 t.next = 18; 40099 break; 40100 } 40101 40102 return console.warn((0, s.default)(v = (0, s.default)(y = "".concat(this.file, ": container header at ")).call(y, r, " indicates that the container has length ")).call(v, h.length, ", which extends beyond the length of the file. Skipping this container.")), t.abrupt("return", void 0); 40103 40104 case 18: 40105 return m = e.allocUnsafe(o.maxLength(h.numLandmarks)), t.next = 21, this.file.read(m, 0, o.maxLength(h.numLandmarks), r + h._size - d); 40106 40107 case 21: 40108 if (b = g(m, o.parser), !this.file.validateChecksums || void 0 === b.crc32) { 40109 t.next = 25; 40110 break; 40111 } 40112 40113 return t.next = 25, this.file.checkCrc32(r, h._size + b._size - d - 4, b.crc32, "container header beginning at position ".concat(r)); 40114 40115 case 25: 40116 return _ = (0, a.default)(h, b, { 40117 _size: h._size + b._size - d, 40118 _endPosition: h._size + b._size - d + r 40119 }), t.abrupt("return", _); 40120 40121 case 27: 40122 case "end": 40123 return t.stop(); 40124 } 40125 }, t, this); 40126 })), function (t) { 40127 return r.apply(this, arguments); 40128 }) 40129 }]), t; 40130 }(); 40131 40132 (0, o.default)(n = "getHeader getCompressionHeaderBlock getCompressionScheme".split(" ")).call(n, function (t) { 40133 return v(b, t); 40134 }), t.exports = b; 40135 }).call(this, r(19).Buffer); 40136 }, function (t, e, r) { 40137 t.exports = r(115); 40138 }, function (t, e, r) { 40139 var n, i, o, a, s; 40140 n = r(332), i = r(147).utf8, o = r(333), a = r(147).bin, (s = function (t, e) { 40141 t.constructor == String ? t = e && "binary" === e.encoding ? a.stringToBytes(t) : i.stringToBytes(t) : o(t) ? t = Array.prototype.slice.call(t, 0) : Array.isArray(t) || (t = t.toString()); 40142 40143 for (var r = n.bytesToWords(t), u = 8 * t.length, f = 1732584193, c = -271733879, l = -1732584194, h = 271733878, d = 0; d < r.length; d++) r[d] = 16711935 & (r[d] << 8 | r[d] >>> 24) | 4278255360 & (r[d] << 24 | r[d] >>> 8); 40144 40145 r[u >>> 5] |= 128 << u % 32, r[14 + (u + 64 >>> 9 << 4)] = u; 40146 var p = s._ff, 40147 g = s._gg, 40148 v = s._hh, 40149 y = s._ii; 40150 40151 for (d = 0; d < r.length; d += 16) { 40152 var m = f, 40153 b = c, 40154 _ = l, 40155 w = h; 40156 f = p(f, c, l, h, r[d + 0], 7, -680876936), h = p(h, f, c, l, r[d + 1], 12, -389564586), l = p(l, h, f, c, r[d + 2], 17, 606105819), c = p(c, l, h, f, r[d + 3], 22, -1044525330), f = p(f, c, l, h, r[d + 4], 7, -176418897), h = p(h, f, c, l, r[d + 5], 12, 1200080426), l = p(l, h, f, c, r[d + 6], 17, -1473231341), c = p(c, l, h, f, r[d + 7], 22, -45705983), f = p(f, c, l, h, r[d + 8], 7, 1770035416), h = p(h, f, c, l, r[d + 9], 12, -1958414417), l = p(l, h, f, c, r[d + 10], 17, -42063), c = p(c, l, h, f, r[d + 11], 22, -1990404162), f = p(f, c, l, h, r[d + 12], 7, 1804603682), h = p(h, f, c, l, r[d + 13], 12, -40341101), l = p(l, h, f, c, r[d + 14], 17, -1502002290), f = g(f, c = p(c, l, h, f, r[d + 15], 22,
401561236535329), l, h, r[d + 1], 5, -165796510), h = g(h, f, c, l, r[d + 6], 9, -1069501632), l = g(l, h, f, c, r[d + 11], 14, 643717713), c = g(c, l, h, f, r[d + 0], 20, -373897302), f = g(f, c, l, h, r[d + 5], 5, -701558691), h = g(h, f, c, l, r[d + 10], 9, 38016083), l = g(l, h, f, c, r[d + 15], 14, -660478335), c = g(c, l, h, f, r[d + 4], 20, -405537848), f = g(f, c, l, h, r[d + 9], 5, 568446438), h = g(h, f, c, l, r[d + 14], 9, -1019803690), l = g(l, h, f, c, r[d + 3], 14, -187363961), c = g(c, l, h, f, r[d + 8], 20, 1163531501), f = g(f, c, l, h, r[d + 13], 5, -1444681467), h = g(h, f, c, l, r[d + 2], 9, -51403784), l = g(l, h, f, c, r[d + 7], 14, 1735328473), f = v(f, c = g(c, l, h, f, r[d + 12], 20, -1926607734), l, h, r[d + 5], 4, -378558), h = v(h, f, c, l, r[d + 8], 11, -2022574463), l = v(l, h, f, c, r[d + 11], 16, 1839030562), c = v(c, l, h, f, r[d + 14], 23, -35309556), f = v(f, c, l, h, r[d + 1], 4, -1530992060), h = v(h, f, c, l, r[d + 4], 11, 1272893353), l = v(l, h, f, c, r[d + 7], 16, -155497632), c = v(c, l, h, f, r[d + 10], 23, -1094730640), f = v(f, c, l, h, r[d + 13], 4, 681279174), h = v(h, f, c, l, r[d + 0], 11, -358537222), l = v(l, h, f, c, r[d + 3], 16, -722521979), c = v(c, l, h, f, r[d + 6], 23, 76029189), f = v(f, c, l, h, r[d + 9], 4, -640364487), h = v(h, f, c, l, r[d + 12], 11, -421815835), l = v(l, h, f, c, r[d + 15], 16, 530742520), f = y(f, c = v(c, l, h, f, r[d + 2], 23, -995338651), l, h, r[d + 0], 6, -198630844), h = y(h, f, c, l, r[d + 7], 10, 1126891415), l = y(l, h, f, c, r[d + 14], 15, -1416354905), c = y(c, l, h, f, r[d + 5], 21, -57434055), f = y(f, c, l, h, r[d + 12], 6, 1700485571), h = y(h, f, c, l, r[d + 3], 10, -1894986606), l = y(l, h, f, c, r[d + 10], 15, -1051523), c = y(c, l, h, f, r[d + 1], 21, -2054922799), f = y(f, c, l, h, r[d + 8], 6, 1873313359), h = y(h, f, c, l, r[d + 15], 10, -30611744), l = y(l, h, f, c, r[d + 6], 15, -1560198380), c = y(c, l, h, f, r[d + 13], 21, 1309151649), f = y(f, c, l, h, r[d + 4], 6, -145523070), h = y(h, f, c, l, r[d + 11], 10, -1120210379), l = y(l, h, f, c, r[d + 2], 15, 718787259), c = y(c, l, h, f, r[d + 9], 21, -343485551), f = f + m >>> 0, c = c + b >>> 0, l = l + _ >>> 0, h = h + w >>> 0; 40157 } 40158 40159 return n.endian([f, c, l, h]); 40160 })._ff = function (t, e, r, n, i, o, a) { 40161 var s = t + (e & r | ~e & n) + (i >>> 0) + a; 40162 return (s << o | s >>> 32 - o) + e; 40163 }, s._gg = function (t, e, r, n, i, o, a) { 40164 var s = t + (e & n | r & ~n) + (i >>> 0) + a; 40165 return (s << o | s >>> 32 - o) + e; 40166 }, s._hh = function (t, e, r, n, i, o, a) { 40167 var s = t + (e ^ r ^ n) + (i >>> 0) + a; 40168 return (s << o | s >>> 32 - o) + e; 40169 }, s._ii = function (t, e, r, n, i, o, a) { 40170 var s = t + (r ^ (e | ~n)) + (i >>> 0) + a; 40171 return (s << o | s >>> 32 - o) + e; 40172 }, s._blocksize = 16, s._digestsize = 16, t.exports = function (t, e) { 40173 if (null == t) throw new Error("Illegal argument " + t); 40174 var r = n.wordsToBytes(s(t, e)); 40175 return e && e.asBytes ? r : e && e.asString ? a.bytesToString(r) : n.bytesToHex(r); 40176 }; 40177 }, function (t, e) { 40178 var r, n; 40179 r = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", n = { 40180 rotl: function (t, e) { 40181 return t << e | t >>> 32 - e; 40182 }, 40183 rotr: function (t, e) { 40184 return t << 32 - e | t >>> e; 40185 }, 40186 endian: function (t) { 40187 if (t.constructor == Number) return 16711935 & n.rotl(t, 8) | 4278255360 & n.rotl(t, 24); 40188 40189 for (var e = 0; e < t.length; e++) t[e] = n.endian(t[e]); 40190 40191 return t; 40192 }, 40193 randomBytes: function (t) { 40194 for (var e = []; t > 0; t--) e.push(Math.floor(256 * Math.random())); 40195 40196 return e; 40197 }, 40198 bytesToWords: function (t) { 40199 for (var e = [], r = 0, n = 0; r < t.length; r++, n += 8) e[n >>> 5] |= t[r] << 24 - n % 32; 40200 40201 return e; 40202 }, 40203 wordsToBytes: function (t) { 40204 for (var e = [], r = 0; r < 32 * t.length; r += 8) e.push(t[r >>> 5] >>> 24 - r % 32 & 255); 40205 40206 return e; 40207 }, 40208 bytesToHex: function (t) { 40209 for (var e = [], r = 0; r < t.length; r++) e.push((t[r] >>> 4).toString(16)), e.push((15 & t[r]).toString(16)); 40210 40211 return e.join(""); 40212 }, 40213 hexToBytes: function (t) { 40214 for (var e = [], r = 0; r < t.length; r += 2) e.push(parseInt(t.substr(r, 2), 16)); 40215 40216 return e; 40217 }, 40218 bytesToBase64: function (t) { 40219 for (var e = [], n = 0; n < t.length; n += 3) for (var i = t[n] << 16 | t[n + 1] << 8 | t[n + 2], o = 0; o < 4; o++) 8 * n + 6 * o <= 8 * t.length ? e.push(r.charAt(i >>> 6 * (3 - o) & 63)) : e.push("="); 40220 40221 return e.join(""); 40222 }, 40223 base64ToBytes: function (t) { 40224 t = t.replace(/[^A-Z0-9+\/]/gi, ""); 40225 40226 for (var e = [], n = 0, i = 0; n < t.length; i = ++n % 4) 0 != i && e.push((r.indexOf(t.charAt(n - 1)) & Math.pow(2, -2 * i + 8) - 1) << 2 * i | r.indexOf(t.charAt(n)) >>> 6 - 2 * i); 40227 40228 return e; 40229 } 40230 }, t.exports = n; 40231 }, function (t, e) { 40232 function r(t) { 40233 return !!t.constructor && "function" == typeof t.constructor.isBuffer && t.constructor.isBuffer(t); 40234 } 40235 /*! 40236 * Determine if an object is a Buffer 40237 * 40238 * @author Feross Aboukhadijeh <https://feross.org> 40239 * @license MIT 40240 */ 40241 40242 40243 t.exports = function (t) { 40244 return null != t && (r(t) || function (t) { 40245 return "function" == typeof t.readFloatLE && "function" == typeof t.slice && r(t.slice(0, 0)); 40246 }(t) || !!t._isBuffer); 40247 }; 40248 }, function (t, e, r) { 40249 40250 var n, 40251 i = r(1), 40252 o = i(r(148)), 40253 a = i(r(76)), 40254 s = i(r(150)), 40255 u = i(r(37)), 40256 f = i(r(30)), 40257 c = i(r(31)), 40258 l = i(r(7)), 40259 h = i(r(10)), 40260 d = i(r(99)), 40261 p = i(r(16)), 40262 g = i(r(77)), 40263 v = i(r(59)), 40264 y = r(9), 40265 m = y.CramMalformedError, 40266 b = y.CramBufferOverrunError, 40267 _ = y.CramArgumentError, 40268 w = r(58), 40269 x = w.parseItem, 40270 E = w.tinyMemoize, 40271 S = w.sequenceMD5, 40272 k = r(100), 40273 A = r(363); 40274 40275 function C(t, e, r, n) {
40276 if (!n) throw new m("could not resolve intra-slice mate pairs, file seems truncated or malformed"); 40277 var i = !!(n.mate || void 0 !== n.mateRecordNumber && n.mateRecordNumber !== e); 40278 r.readName || (r.readName = String(r.uniqueId), n.readName = r.readName), r.mate = { 40279 sequenceId: n.sequenceId, 40280 alignmentStart: n.alignmentStart, 40281 uniqueId: n.uniqueId 40282 }, n.readName && (r.mate.readName = n.readName), n.mate || void 0 !== n.mateRecordNumber || (n.mate = { 40283 sequenceId: r.sequenceId, 40284 alignmentStart: r.alignmentStart, 40285 uniqueId: r.uniqueId 40286 }, r.readName && (n.mate.readName = r.readName)), r.flags |= k.BAM_FPAIRED, (0, d.default)(n) & k.BAM_FUNMAP && (r.flags |= k.BAM_FMUNMAP), (0, d.default)(r) & k.BAM_FUNMAP && (n.flags |= k.BAM_FMUNMAP), (0, d.default)(n) & k.BAM_FREVERSE && (r.flags |= k.BAM_FMREVERSE), (0, d.default)(r) & k.BAM_FREVERSE && (n.flags |= k.BAM_FMREVERSE), void 0 === r.templateLength && (i ? function (t, e, r) { 40287 var n = function e(r) { 40288 var n = [r]; 40289 40290 if (r.mateRecordNumber >= 0) { 40291 var i = t[r.mateRecordNumber]; 40292 if (!i) throw new m("intra-slice mate record not found, this file seems malformed"); 40293 n.push.apply(n, (0, v.default)(e(i))); 40294 } 40295 40296 return n; 40297 }(r), 40298 i = (0, g.default)(n).call(n, function (t) { 40299 return t.alignmentStart; 40300 }), 40301 o = (0, g.default)(n).call(n, function (t) { 40302 return t.alignmentStart + t.readLength - 1; 40303 }), 40304 a = Math.max.apply(Math, (0, v.default)(o)) - Math.min.apply(Math, (0, v.default)(i)) + 1; 40305 40306 a >= 0 && (0, p.default)(n).call(n, function (t) { 40307 if (void 0 !== t.templateLength) throw new m("mate pair group has some members that have template lengths already, this file seems malformed"); 40308 t.templateLength = a; 40309 }); 40310 }(t, 0, r) : function (t, e) { 40311 var r = Math.min(t.alignmentStart, e.alignmentStart), 40312 n = Math.max(t.alignmentStart + t.readLength - 1, e.alignmentStart + e.readLength - 1) - r + 1; 40313 t.templateLength = n, e.templateLength = n; 40314 }(r, n)), delete r.mateRecordNumber; 40315 } 40316 40317 var T = function () { 40318 function t(e, r) { 40319 (0, l.default)(this, t), this.container = e, this.file = e.file, this.containerPosition = r; 40320 } 40321 40322 var e, r, n, i, d, v, y, w; 40323 return (0, h.default)(t, [{ 40324 key: "getHeader", 40325 value: (w = (0, c.default)(f.default.mark(function t() { 40326 var e, r, n; 40327 return f.default.wrap(function (t) { 40328 for (;;) switch (t.prev = t.next) { 40329 case 0: 40330 return t.next = 2, this.file.getSectionParsers(); 40331 40332 case 2: 40333 return e = t.sent, t.next = 5, this.container.getHeader(); 40334 40335 case 5: 40336 return r = t.sent, t.next = 8, this.file.readBlock(r._endPosition + this.containerPosition); 40337 40338 case 8: 40339 if ("MAPPED_SLICE_HEADER" !== (n = t.sent).contentType) { 40340 t.next = 13; 40341 break; 40342 } 40343 40344 n.content = x(n.content, e.cramMappedSliceHeader.parser, 0, r._endPosition), t.next = 18; 40345 break; 40346 40347 case 13: 40348 if ("UNMAPPED_SLICE_HEADER" !== n.contentType) { 40349 t.next = 17; 40350 break; 40351 } 40352 40353 n.content = x(n.content, e.cramUnmappedSliceHeader.parser, 0, r._endPosition), t.next = 18; 40354 break; 40355 40356 case 17: 40357 throw new m("error reading slice header block, invalid content type ".concat(n._contentType)); 40358 40359 case 18: 40360 return t.abrupt("return", n); 40361 40362 case 19: 40363 case "end": 40364 return t.stop(); 40365 } 40366 }, t, this); 40367 })), function () { 40368 return w.apply(this, arguments); 40369 }) 40370 }, { 40371 key: "getBlocks", 40372 value: (y = (0, c.default)(f.default.mark(function t() { 40373 var e, r, n, i; 40374 return f.default.wrap(function (t) { 40375 for (;;) switch (t.prev = t.next) { 40376 case 0: 40377 return t.next = 2, this.getHeader(); 40378 40379 case 2: 40380 e = t.sent, r = e._endPosition, n = new Array(e.content.numBlocks), i = 0; 40381 40382 case 6: 40383 if (!(i < n.length)) { 40384 t.next = 14; 40385 break; 40386 } 40387 40388 return t.next = 9, this.file.readBlock(r); 40389 40390 case 9: 40391 n[i] = t.sent, r = n[i]._endPosition; 40392 40393 case 11: 40394 i += 1, t.next = 6; 40395 break; 40396 40397 case 14: 40398 return t.abrupt("return", n); 40399 40400 case 15: 40401 case "end": 40402 return t.stop(); 40403 } 40404 }, t, this); 40405 })), function () { 40406 return y.apply(this, arguments); 40407 }) 40408 }, { 40409 key: "getCoreDataBlock", 40410 value: (v = (0, c.default)(f.default.mark(function t() { 40411 var e; 40412 return f.default.wrap(function (t) { 40413 for (;;) switch (t.prev = t.next) { 40414 case 0: 40415 return t.next = 2, this.getBlocks(); 40416 40417 case 2: 40418 return e = t.sent, t.abrupt("return", e[0]); 40419 40420 case 4: 40421 case "end": 40422 return t.stop(); 40423 } 40424 }, t, this); 40425 })), function () { 40426 return v.apply(this, arguments); 40427 }) 40428 }, { 40429 key: "_getBlocksContentIdIndex", 40430 value: (d = (0, c.default)(f.default.mark(function t() { 40431 var e, r; 40432 return f.default.wrap(function (t) { 40433 for (;;) switch (t.prev = t.next) { 40434 case 0: 40435 return t.next = 2, this.getBlocks(); 40436 40437 case 2: 40438 return e = t.sent, r = {}, (0, p.default)(e).call(e, function (t) { 40439 "EXTERNAL_DATA" === t.contentType && (r[t.contentId] = t); 40440 }), t.abrupt("return", r); 40441 40442 case 6: 40443 case "end": 40444 return t.stop(); 40445 } 40446 }, t, this); 40447 })), function () { 40448 return d.apply(this, arguments); 40449 }) 40450 }, { 40451 key: "getBlockByContentId", 40452 value: (i = (0, c.default)(f.default.mark(function t(e) { 40453 var r; 40454 return f.default.wrap(function (t) { 40455 for (;;) switch (t.prev = t.next) { 40456 case 0: 40457 return t.next = 2, this._getBlocksContentIdIndex(); 40458 40459 case 2: 40460 return r = t.sent, t.abrupt("return", r[e]); 40461 40462 case 4: 40463 case "end": 40464 return t.stop(); 40465 } 40466 }, t, this); 40467 })), function (t) { 40468 return i.apply(this, arguments); 40469 }) 40470 }, { 40471 key: "getReferenceRegion", 40472 value: (n = (0, c.default)(f.default.mark(function t() { 40473 var e, r, n, i; 40474 return f.default.wrap(function (t) { 40475 for (;;) switch (t.prev = t.next) { 40476 case 0: 40477 return t.next = 2, this.getHeader(); 40478 40479 case 2: 40480 if (!((e = t.sent.content).refSeqId < 0)) { 40481 t.next = 5; 40482 break; 40483 } 40484 40485 return t.abrupt("return", void 0); 40486 40487 case 5: 40488 return t.next = 7, this.container.getCompressionScheme(); 40489 40490 case 7: 40491 if (r = t.sent, !(e.refBaseBlockId >= 0)) { 40492 t.next = 15; 40493 break; 40494 } 40495 40496 if (n = this.getBlockByContentId(e.refBaseBlockId)) { 40497 t.next = 12; 40498 break; 40499 } 40500
40501 throw new m("embedded reference specified, but reference block does not exist"); 40502 40503 case 12: 40504 if (!(e.span > n.uncompressedSize)) { 40505 t.next = 14; 40506 break; 40507 } 40508 40509 throw new m("Embedded reference is too small"); 40510 40511 case 14: 40512 return t.abrupt("return", { 40513 seq: n.data.toString("utf8"), 40514 start: e.refSeqStart, 40515 end: e.refSeqStart + e.refSeqSpan - 1, 40516 span: e.refSeqSpan 40517 }); 40518 40519 case 15: 40520 if (!r.referenceRequired && !this.file.fetchReferenceSequenceCallback) { 40521 t.next = 24; 40522 break; 40523 } 40524 40525 if (this.file.fetchReferenceSequenceCallback) { 40526 t.next = 18; 40527 break; 40528 } 40529 40530 throw new Error("reference sequence not embedded, and seqFetch callback not provided, cannot fetch reference sequence"); 40531 40532 case 18: 40533 return t.next = 20, this.file.fetchReferenceSequenceCallback(e.refSeqId, e.refSeqStart, e.refSeqStart + e.refSeqSpan - 1); 40534 40535 case 20: 40536 if ((i = t.sent).length === e.refSeqSpan) { 40537 t.next = 23; 40538 break; 40539 } 40540 40541 throw new _("seqFetch callback returned a reference sequence of the wrong length"); 40542 40543 case 23: 40544 return t.abrupt("return", { 40545 seq: i, 40546 start: e.refSeqStart, 40547 end: e.refSeqStart + e.refSeqSpan - 1, 40548 span: e.refSeqSpan 40549 }); 40550 40551 case 24: 40552 return t.abrupt("return", void 0); 40553 40554 case 25: 40555 case "end": 40556 return t.stop(); 40557 } 40558 }, t, this); 40559 })), function () { 40560 return n.apply(this, arguments); 40561 }) 40562 }, { 40563 key: "getAllRecords", 40564 value: function () { 40565 return this.getRecords(function () { 40566 return !0; 40567 }); 40568 } 40569 }, { 40570 key: "_fetchRecords", 40571 value: (r = (0, c.default)(f.default.mark(function t() { 40572 var e, 40573 r, 40574 n, 40575 i, 40576 o, 40577 a, 40578 c, 40579 l, 40580 h, 40581 d, 40582 p, 40583 v, 40584 y, 40585 _, 40586 w, 40587 x, 40588 E, 40589 k, 40590 T, 40591 R, 40592 O, 40593 I, 40594 L, 40595 B = this; 40596 40597 return f.default.wrap(function (t) { 40598 for (;;) switch (t.prev = t.next) { 40599 case 0: 40600 return t.next = 2, this.file.getDefinition(); 40601 40602 case 2: 40603 return e = t.sent, r = e.majorVersion, t.next = 6, this.container.getCompressionScheme(); 40604 40605 case 6: 40606 return n = t.sent, t.next = 9, this.getHeader(); 40607 40608 case 9: 40609 return i = t.sent, t.next = 12, this._getBlocksContentIdIndex(); 40610 40611 case 12: 40612 if (o = t.sent, !(r > 1 && this.file.options.checkSequenceMD5 && i.content.refSeqId >= 0 && "0000000000000000" !== i.content.md5.join(""))) { 40613 t.next = 23; 40614 break; 40615 } 40616 40617 return t.next = 16, this.getReferenceRegion(); 40618 40619 case 16: 40620 if (!(a = t.sent)) { 40621 t.next = 23; 40622 break; 40623 } 40624 40625 if (v = a.seq, y = a.start, _ = a.end, w = S(v), x = (0, g.default)(c = i.content.md5).call(c, function (t) { 40626 return (t < 16 ? "0" : "") + t.toString(16); 40627 }).join(""), w === x) { 40628 t.next = 23; 40629 break; 40630 } 40631
40632 throw new m((0, u.default)(l = (0, u.default)(h = (0, u.default)(d = (0, u.default)(p = "MD5 checksum reference mismatch for ref ".concat(i.content.refSeqId, " pos ")).call(p, y, "..")).call(d, _, ". recorded MD5: ")).call(h, x, ", calculated MD5: ")).call(l, w)); 40633 40634 case 23: 40635 return t.next = 25, this.getCoreDataBlock(); 40636 40637 case 25: 40638 E = t.sent, k = { 40639 lastAlignmentStart: i.content.refSeqStart || 0, 40640 coreBlock: { 40641 bitPosition: 7, 40642 bytePosition: 0 40643 }, 40644 externalBlocks: { 40645 getCursor: function (t) { 40646 return this[t] || (this[t] = { 40647 bitPosition: 7, 40648 bytePosition: 0 40649 }), this[t]; 40650 } 40651 } 40652 }, T = function (t) { 40653 var e = n.getCodecForDataSeries(t); 40654 if (!e) throw new m("no codec defined for ".concat(t, " data series")); 40655 return e.decode(B, E, o, k); 40656 }, R = new Array(i.content.numRecords), O = 0; 40657 40658 case 30: 40659 if (!(O < R.length)) { 40660 t.next = 48; 40661 break; 40662 } 40663 40664 t.prev = 31, R[O] = A(this, T, n, i, E, o, k, r, O), R[O].uniqueId = i.contentPosition + i.content.recordCounter + O + 1, t.next = 45; 40665 break; 40666 40667 case 36: 40668 if (t.prev = 36, t.t0 = t.catch(31), !(t.t0 instanceof b)) { 40669 t.next = 44; 40670 break; 40671 } 40672 40673 return console.warn("read attempted beyond end of buffer, file seems truncated."), R = (0, s.default)(R).call(R, function (t) { 40674 return !!t; 40675 }), t.abrupt("break", 48); 40676 40677 case 44: 40678 throw t.t0; 40679 40680 case 45: 40681 O += 1, t.next = 30; 40682 break; 40683 40684 case 48: 40685 for (I = 0; I < R.length; I += 1) (L = R[I].mateRecordNumber) >= 0 && C(R, I, R[I], R[L]); 40686 40687 return t.abrupt("return", R); 40688 40689 case 50: 40690 case "end": 40691 return t.stop(); 40692 } 40693 }, t, this, [[31, 36]]); 40694 })), function () { 40695 return r.apply(this, arguments); 40696 }) 40697 }, { 40698 key: "getRecords", 40699 value: (e = (0, c.default)(f.default.mark(function t(e) { 40700 var r, 40701 n, 40702 i, 40703 u, 40704 l, 40705 h, 40706 d, 40707 p, 40708 v, 40709 y, 40710 m, 40711 b, 40712 _, 40713 w, 40714 x, 40715 E, 40716 S = this; 40717 40718 return f.default.wrap(function (t) { 40719 for (;;) switch (t.prev = t.next) { 40720 case 0: 40721 return n = this.container.filePosition + this.containerPosition, (i = this.file.featureCache.get(n)) || (i = this._fetchRecords(), this.file.featureCache.set(n, i)), t.t0 = s.default, t.next = 6, i; 40722 40723 case 6: 40724 if (t.t1 = r = t.sent, t.t2 = r, t.t3 = e, !(u = (0, t.t0)(t.t1).call(t.t2, t.t3)).length || !this.file.fetchReferenceSequenceCallback) { 40725 t.next = 24; 40726 break; 40727 } 40728 40729 return t.next = 13, this.getHeader(); 40730 40731 case 13: 40732 if (!((l = t.sent).content.refSeqId >= 0 || -2 === l.content.refSeqId)) { 40733 t.next = 24; 40734 break; 40735 } 40736 40737 return d = l.content.refSeqId >= 0 ? l.content.refSeqId : void 0, t.next = 18, this.container.getCompressionScheme(); 40738 40739 case 18: 40740 for (p = t.sent, v = {}, y = 0; y < u.length; y += 1) m = void 0 !== d ? d : u[y].sequenceId, (b = v[m]) || (b = { 40741 id: m, 40742 start: u[y].alignmentStart, 40743 end: -1 / 0 40744 }
40744, v[m] = b), (_ = u[y].alignmentStart + (u[y].lengthOnRef || u[y].readLength) - 1) > b.end && (b.end = _), u[y].alignmentStart < b.start && (b.start = u[y].alignmentStart); 40745 40746 return t.next = 23, a.default.all((0, g.default)(h = (0, o.default)(v)).call(h, function () { 40747 var t = (0, c.default)(f.default.mark(function t(e) { 40748 return f.default.wrap(function (t) { 40749 for (;;) switch (t.prev = t.next) { 40750 case 0: 40751 if (!(-1 !== e.id && e.start <= e.end)) { 40752 t.next = 4; 40753 break; 40754 } 40755 40756 return t.next = 3, S.file.fetchReferenceSequenceCallback(e.id, e.start, e.end); 40757 40758 case 3: 40759 e.seq = t.sent; 40760 40761 case 4: 40762 case "end": 40763 return t.stop(); 40764 } 40765 }, t); 40766 })); 40767 return function (e) { 40768 return t.apply(this, arguments); 40769 }; 40770 }())); 40771 40772 case 23: 40773 for (w = 0; w < u.length; w += 1) x = void 0 !== d ? d : u[w].sequenceId, (E = v[x]) && E.seq && u[w].addReferenceSequence(E, p); 40774 40775 case 24: 40776 return t.abrupt("return", u); 40777 40778 case 25: 40779 case "end": 40780 return t.stop(); 40781 } 40782 }, t, this); 40783 })), function (t) { 40784 return e.apply(this, arguments); 40785 }) 40786 }]), t; 40787 }(); 40788 40789 (0, p.default)(n = "getHeader getBlocks _getBlocksContentIdIndex".split(" ")).call(n, function (t) { 40790 return E(T, t); 40791 }), t.exports = T; 40792 }, function (t, e, r) { 40793 t.exports = r(336); 40794 }, function (t, e, r) { 40795 r(337); 40796 var n = r(3); 40797 t.exports = n.Object.values; 40798 }, function (t, e, r) { 40799 var n = r(0), 40800 i = r(149).values; 40801 n({ 40802 target: "Object", 40803 stat: !0 40804 }, { 40805 values: function (t) { 40806 return i(t); 40807 } 40808 }); 40809 }, function (t, e, r) { 40810 t.exports = r(339); 40811 }, function (t, e, r) { 40812 var n = r(340), 40813 i = Array.prototype; 40814 40815 t.exports = function (t) { 40816 var e = t.filter; 40817 return t === i || t instanceof Array && e === i.filter ? n : e; 40818 }; 40819 }, function (t, e, r) { 40820 r(341); 40821 var n = r(18); 40822 t.exports = n("Array").filter; 40823 }, function (t, e, r) { 40824 40825 var n = r(0), 40826 i = r(45).filter; 40827 n({ 40828 target: "Array", 40829 proto: !0, 40830 forced: !r(68)("filter") 40831 }, { 40832 filter: function (t) { 40833 return i(this, t, arguments.length > 1 ? arguments[1] : void 0); 40834 } 40835 }); 40836 }, function (t, e, r) { 40837 t.exports = r(343); 40838 }, function (t, e, r) { 40839 var n = r(344), 40840 i = RegExp.prototype; 40841 40842 t.exports = function (t) { 40843 return !(t === i || t instanceof RegExp) || "flags" in t ? t.flags : n(t); 40844 }; 40845 }, function (t, e, r) { 40846 r(345); 40847 var n = r(346); 40848 40849 t.exports = function (t) { 40850 return n.call(t); 40851 }; 40852 }, function (t, e) {}, function (t, e, r) { 40853 40854 var n = r(2); 40855 40856 t.exports = function () { 40857 var t = n(this), 40858 e = ""; 40859 return t.global && (e += "g"), t.ignoreCase && (e += "i"), t.multiline && (e += "m"), t.dotAll && (e += "s"), t.unicode && (e += "u"), t.sticky && (e += "y"), e; 40860 }; 40861 }, function (t, e, r) { 40862 t.exports = r(348); 40863 }, function (t, e, r) { 40864 var n = r(349), 40865 i = Array.prototype; 40866 40867 t.exports = function (t) { 40868 var e = t.map; 40869 return t === i || t instanceof Array && e === i.map ? n : e; 40870 }; 40871 }, function (t, e, r) { 40872 r(350); 40873 var n = r(18); 40874 t.exports = n("Array").map; 40875 }, function (t, e, r) { 40876 40877 var n = r(0), 40878 i = r(45).map; 40879 n({ 40880 target: "Array", 40881 proto: !0, 40882 forced: !r(68)("map") 40883 }, { 40884 map: function (t) { 40885 return i(this, t, arguments.length > 1 ? arguments[1] : void 0); 40886 } 40887 }); 40888 }, function (t, e, r) { 40889 var n = r(151); 40890 40891 t.exports = function (t) { 40892 if (n(t)) { 40893 for (var e = 0, r = new Array(t.length); e < t.length; e++) r[e] = t[e]; 40894 40895 return r; 40896 } 40897 }; 40898 }, function (t, e, r) { 40899 t.exports = r(353); 40900 }, function (t, e, r) { 40901 r(354); 40902 var n = r(3); 40903 t.exports = n.Array.isArray; 40904 }, function (t, e, r) { 40905 r(0)({ 40906 target: "Array", 40907 stat: !0 40908 }, { 40909 isArray: r(53) 40910 }); 40911 }, function (t, e, r) { 40912 t.exports = r(356); 40913 }, function (t, e, r) { 40914 t.exports = r(357); 40915 }, function (t, e, r) { 40916 r(46), r(358); 40917 var n = r(3); 40918 t.exports = n.Array.from; 40919 }, function (t, e, r) { 40920 var n = r(0), 40921 i = r(359); 40922 n({ 40923 target: "Array", 40924 stat: !0, 40925 forced: !r(121)(function (t) { 40926 Array.from(t); 40927 }) 40928 }, { 40929 from: i 40930 }); 40931 }, function (t, e, r) { 40932 40933 var n = r(15), 40934 i = r(22), 40935 o = r(120), 40936 a = r(119), 40937 s = r(29), 40938 u = r(87), 40939 f = r(90); 40940 40941 t.exports = function (t) { 40942 var e, 40943 r, 40944 c, 40945 l, 40946 h = i(t),
40947 d = "function" == typeof this ? this : Array, 40948 p = arguments.length, 40949 g = p > 1 ? arguments[1] : void 0, 40950 v = void 0 !== g, 40951 y = 0, 40952 m = f(h); 40953 if (v && (g = n(g, p > 2 ? arguments[2] : void 0, 2)), null == m || d == Array && a(m)) for (r = new d(e = s(h.length)); e > y; y++) u(r, y, v ? g(h[y], y) : h[y]);else for (l = m.call(h), r = new d(); !(c = l.next()).done; y++) u(r, y, v ? o(l, g, [c.value, y], !0) : c.value); 40954 return r.length = y, r; 40955 }; 40956 }, function (t, e, r) { 40957 r(41), r(46), t.exports = r(361); 40958 }, function (t, e, r) { 40959 var n = r(67), 40960 i = r(6), 40961 o = r(35), 40962 a = i("iterator"); 40963 40964 t.exports = function (t) { 40965 var e = Object(t); 40966 return void 0 !== e[a] || "@@iterator" in e || o.hasOwnProperty(n(e)); 40967 }; 40968 }, function (t, e) { 40969 t.exports = function () { 40970 throw new TypeError("Invalid attempt to spread non-iterable instance"); 40971 }; 40972 }, function (t, e, r) { 40973 40974 (function (e) { 40975 var n = r(1), 40976 i = n(r(37)), 40977 o = n(r(364)), 40978 a = n(r(16)), 40979 s = n(r(99)), 40980 u = n(r(101)), 40981 f = n(r(59)), 40982 c = n(r(154)), 40983 l = n(r(376)), 40984 h = n(r(380)), 40985 d = n(r(48)), 40986 p = n(r(387)), 40987 g = r(146), 40988 v = r(9), 40989 y = v.CramMalformedError, 40990 m = v.CramUnimplementedError, 40991 b = r(389), 40992 _ = r(100); 40993 40994 function w(t) { 40995 var e = (0, p.default)(t).call(t, 0); 40996 return -1 === e ? t.toString("utf8") : t.toString("utf8", 0, e); 40997 } 40998 40999 function x(t, r) { 41000 if (r.readInt32LE || (r = e.from(r)), "Z" === t) return w(r); 41001 if ("A" === t) return String.fromCharCode(r[0]); 41002 41003 if ("I" === t) { 41004 var n = g.fromBytesLE(r); 41005 if (n.greaterThan(h.default) || n.lessThan(l.default)) throw new m("integer overflow"); 41006 return n.toNumber(); 41007 } 41008 41009 if ("i" === t) return r.readInt32LE(0); 41010 if ("s" === t) return r.readInt16LE(0); 41011 if ("S" === t) return r.readUInt16LE(0); 41012 if ("c" === t) return r.readInt8(0); 41013 if ("C" === t) return r.readUInt8(0); 41014 if ("f" === t) return r.readFloatLE(0); 41015 41016 if ("H" === t) { 41017 var i = w(r); 41018 return (0, c.default)(i.replace(/^0x/, ""), 16); 41019 } 41020 41021 if ("B" === t) return function (t) { 41022 var e = String.fromCharCode(t[0]), 41023 r = t.readInt32LE(1), 41024 n = { 41025 c: ["readInt8", 1], 41026 C: ["readUInt8", 1], 41027 s: ["readInt16LE", 2], 41028 S: ["readUInt16LE", 2], 41029 i: ["readInt32LE", 4], 41030 I: ["readUInt32LE", 4], 41031 f: ["readFloatLE", 4] 41032 }[e]; 41033 if (!n) throw new y("invalid tag value array type '".concat(e, "'")); 41034 41035 for (var i = (0, d.default)(n, 2), o = i[0], a = i[1], s = new Array(r), u = 5, f = 0; f < r; f += 1) s[f] = t[o](u), u += a; 41036 41037 return s; 41038 }(r); 41039 throw new y("Unrecognized tag type ".concat(t)); 41040 } 41041 41042 function E(t) { 41043 if (t instanceof e) return w(t); 41044 41045 if (t.length && (0, p.default)(t)) { 41046 if (!t[t.length - 1]) { 41047 var r = (0, p.default)(t).call(t, 0); 41048 return String.fromCharCode.apply(String, (0, f.default)((0, u.default)(t).call(t, 0, r))); 41049 } 41050 41051 return String.fromCharCode.apply(String, (0, f.default)(t)); 41052 } 41053 41054 return String(t); 41055 } 41056 41057 t.exports = function (t, e, r, n, u, f, c, l, h) { 41058 var p = new b(); 41059 41060 if (p.flags = e("BF"), p.cramFlags = e("CF"), l > 1 && -2 === n.content.refSeqId ? p.sequenceId = e("RI") : p.sequenceId = n.content.refSeqId, p.readLength = e("RL"), p.alignmentStart = e("AP"), r.APdelta && (p.alignmentStart += c.lastAlignmentStart), c.lastAlignmentStart = p.alignmentStart, p.readGroupId = e("RG"), r.readNamesIncluded && (p.readName = E(e("RN"))), p.isDetached()) { 41061 var g = {}; 41062 g.flags = e("MF"), r.readNamesIncluded || (g.readName = E(e("RN")), p.readName = g.readName), g.sequenceId = e("NS"), g.alignmentStart = e("NP"), ((0, s.default)(g) || g.sequenceId > -1) && (p.mate = g), p.templateSize = e("TS"), (0, s.default)(g) & _.CRAM_M_UNMAP && (p.flags |= _.BAM_FMUNMAP), (0, s.default)(g) & _.CRAM_M_REVERSE && (p.flags |= _.BAM_FMREVERSE); 41063 } else p.hasMateDownStream() && (p.mateRecordNumber = e("NF") + h + 1); 41064 41065 var v = e("TL"); 41066 if (v < 0) throw new y("invalid TL index"); 41067 41068 for (var m = r.getTagNames(v), w = m.length, S = 0; S < w; S += 1) { 41069 var k = m[S], 41070 A = k.substr(0, 2), 41071 C = k.substr(2, 1), 41072 T = r.getCodecForTag(k); 41073 if (!T) throw new y("no codec defined for auxiliary tag ".concat(k)); 41074 var R = T.decode(t, u, f, c); 41075 p.tags[A] = x(C, R); 41076 } 41077 41078 if (p.isSegmentUnmapped()) { 41079 if (p.isUnknownBases()) p.readBases = null, p.qualityScores = null;else { 41080 for (var O = new Array(p.readLength), I = 0; I < O.length; I += 1) O[I] = e("BA"); 41081 41082 if (p.readBases = String.fromCharCode.apply(String, O), p.isPreservingQualityScores()) { 41083 for (var L = 0; L < O.length; L += 1) O[L] = e("QS"); 41084
41085 p.qualityScores = O; 41086 } 41087 } 41088 } else { 41089 var B, 41090 P = e("FN"); 41091 P && (p.readFeatures = function (t, e, r, n, i) { 41092 var o = 0, 41093 a = t.alignmentStart - 1, 41094 s = new Array(e); 41095 41096 function u(t) { 41097 var e = (0, d.default)(t, 2), 41098 n = e[0], 41099 i = e[1], 41100 o = r(i); 41101 return "character" === n ? String.fromCharCode(o) : "string" === n ? o.toString("utf8") : "numArray" === n ? o.toArray() : o; 41102 } 41103 41104 for (var f = 0; f < e; f += 1) { 41105 var c = String.fromCharCode(r("FC")), 41106 l = r("FP"), 41107 h = { 41108 code: c 41109 }, 41110 p = { 41111 B: ["character", "BA"], 41112 S: ["string", i > 1 ? "SC" : "IN"], 41113 X: ["number", "BS"], 41114 D: ["number", "DL"], 41115 I: ["string", "IN"], 41116 i: ["character", "BA"], 41117 b: ["string", "BB"], 41118 q: ["numArray", "QQ"], 41119 Q: ["number", "QS"], 41120 H: ["number", "HC"], 41121 P: ["number", "PD"], 41122 N: ["number", "RS"] 41123 }[c]; 41124 if (!p) throw new y('invalid read feature code "'.concat(c, '"')); 41125 h.data = u(p); 41126 var g = { 41127 B: ["number", "QS"] 41128 }[c]; 41129 g && (h.data = [h.data, u(g)]), o += l, h.pos = o, a += l, h.refPos = a, "D" === c || "N" === c ? a += h.data : "I" === c || "S" === c ? a -= h.data.length : "i" === c && (a -= 1), s[f] = h; 41130 } 41131 41132 return s; 41133 }(p, P, e, 0, l)); 41134 var F, 41135 N = p.readLength; 41136 if (p.readFeatures && (0, a.default)(B = p.readFeatures).call(B, function (t) { 41137 var e = t.code, 41138 r = t.data; 41139 "D" === e || "N" === e ? N += r : "I" === e || "S" === e ? N -= r.length : "i" === e && (N -= 1); 41140 }), (0, o.default)(N)) console.warn("".concat(p.readName || (0, i.default)(F = "".concat(p.sequenceId, ":")).call(F, p.alignmentStart), " record has invalid read features")), N = p.readLength; 41141 41142 if (p.lengthOnRef = N, p.mappingQuality = e("MQ"), p.isPreservingQualityScores()) { 41143 for (var M = new Array(p.readLength), j = 0; j < M.length; j += 1) M[j] = e("QS"); 41144 41145 p.qualityScores = M; 41146 } 41147 } 41148 return p; 41149 }; 41150 }).call(this, r(19).Buffer); 41151 }, function (t, e, r) { 41152 t.exports = r(365); 41153 }, function (t, e, r) { 41154 t.exports = r(366); 41155 }, function (t, e, r) { 41156 r(367); 41157 var n = r(3); 41158 t.exports = n.Number.isNaN; 41159 }, function (t, e, r) { 41160 r(0)({ 41161 target: "Number", 41162 stat: !0 41163 }, { 41164 isNaN: function (t) { 41165 return t != t; 41166 } 41167 }); 41168 }, function (t, e, r) { 41169 t.exports = r(369); 41170 }, function (t, e, r) { 41171 var n = r(370), 41172 i = Array.prototype; 41173 41174 t.exports = function (t) { 41175 var e = t.slice; 41176 return t === i || t instanceof Array && e === i.slice ? n : e; 41177 }; 41178 }, function (t, e, r) { 41179 r(371); 41180 var n = r(18); 41181 t.exports = n("Array").slice; 41182 }, function (t, e, r) { 41183 41184 var n = r(0), 41185 i = r(14), 41186 o = r(53), 41187 a = r(84), 41188 s = r(29), 41189 u = r(28), 41190 f = r(87), 41191 c = r(68), 41192 l = r(6)("species"), 41193 h = [].slice, 41194 d = Math.max; 41195 n({ 41196 target: "Array", 41197 proto: !0, 41198 forced: !c("slice") 41199 }, { 41200 slice: function (t, e) { 41201 var r, 41202 n, 41203 c, 41204 p = u(this), 41205 g = s(p.length), 41206 v = a(t, g), 41207 y = a(void 0 === e ? g : e, g); 41208 if (o(p) && ("function" != typeof (r = p.constructor) || r !== Array && !o(r.prototype) ? i(r) && null === (r = r[l]) && (r = void 0) : r = void 0, r === Array || void 0 === r)) return h.call(p, v, y); 41209 41210 for (n = new (void 0 === r ? Array : r)(d(y - v, 0)), c = 0; v < y; v++, c++) v in p && f(n, c, p[v]); 41211 41212 return n.length = c, n; 41213 } 41214 }); 41215 }, function (t, e, r) { 41216 t.exports = r(373); 41217 }, function (t, e, r) { 41218 r(374); 41219 var n = r(3); 41220 t.exports = n.Number.parseInt; 41221 }, function (t, e, r) { 41222 var n = r(0), 41223 i = r(155); 41224 n({ 41225 target: "Number", 41226 stat: !0, 41227 forced: Number.parseInt != i 41228 }, { 41229 parseInt: i 41230 }); 41231 }, function (t, e, r) { 41232 var n = r(49), 41233 i = "[" + r(156) + "]", 41234 o = RegExp("^" + i + i + "*"), 41235 a = RegExp(i + i + "*$"), 41236 s = function (t) { 41237 return function (e) { 41238 var r = String(n(e)); 41239 return 1 & t && (r = r.replace(o, "")), 2 & t && (r = r.replace(a, "")), r; 41240 }; 41241 }; 41242 41243 t.exports = { 41244 start: s(1), 41245 end: s(2), 41246 trim: s(3) 41247 }; 41248 }, function (t, e, r) { 41249 t.exports = r(377); 41250 }, function (t, e, r) { 41251 t.exports = r(378); 41252 }, function (t, e, r) { 41253 r(379), t.exports = -9007199254740991; 41254 }, function (t, e, r) { 41255 r(0)({ 41256 target: "Number", 41257 stat: !0 41258 }, { 41259 MIN_SAFE_INTEGER: -9007199254740991 41260 }); 41261 }, function (t, e, r) { 41262 t.exports = r(381); 41263 }, function (t, e, r) { 41264 t.exports = r(382); 41265 }, function (t, e, r) { 41266 r(383), t.exports = 9007199254740991; 41267 }, function (t, e, r) { 41268 r(0)({ 41269 target: "Number", 41270 stat: !0 41271 }, { 41272 MAX_SAFE_INTEGER: 9007199254740991 41273 }); 41274 }, function (t, e, r) { 41275 var n = r(385), 41276 i = r(153); 41277 41278 t.exports = function (t, e) { 41279 if (i(Object(t)) || "[object Arguments]" === Object.prototype.toString.call(t)) { 41280 var r = [], 41281 o = !0, 41282 a = !1, 41283 s = void 0; 41284 41285 try { 41286 for (var u, f = n(t); !(o = (u = f.next()).done) && (r.push(u.value), !e || r.length !== e); o = !0); 41287 } catch (t) { 41288 a = !0, s = t; 41289 } finally { 41290 try { 41291 o || null == f.return || f.return(); 41292 } finally { 41293 if (a) throw s; 41294 } 41295 } 41296 41297 return r; 41298 } 41299 }; 41300 }, function (t, e, r) {
41301 t.exports = r(386); 41302 }, function (t, e, r) { 41303 r(41), r(46), t.exports = r(142); 41304 }, function (t, e, r) { 41305 t.exports = r(388); 41306 }, function (t, e, r) { 41307 t.exports = r(143); 41308 }, function (t, e, r) { 41309 41310 var n = r(1), 41311 i = n(r(98)), 41312 o = n(r(16)), 41313 a = n(r(99)), 41314 s = n(r(7)), 41315 u = n(r(10)), 41316 f = n(r(59)), 41317 c = r(100); 41318 var l = { 41319 a: 0, 41320 A: 0, 41321 c: 1, 41322 C: 1, 41323 g: 2, 41324 G: 2, 41325 t: 3, 41326 T: 3, 41327 n: 4, 41328 N: 4 41329 }; 41330 41331 var h = function () { 41332 function t() { 41333 (0, s.default)(this, t), this.tags = {}; 41334 } 41335 41336 return (0, u.default)(t, [{ 41337 key: "isPaired", 41338 value: function () { 41339 return !!((0, a.default)(this) & c.BAM_FPAIRED); 41340 } 41341 }, { 41342 key: "isProperlyPaired", 41343 value: function () { 41344 return !!((0, a.default)(this) & c.BAM_FPROPER_PAIR); 41345 } 41346 }, { 41347 key: "isSegmentUnmapped", 41348 value: function () { 41349 return !!((0, a.default)(this) & c.BAM_FUNMAP); 41350 } 41351 }, { 41352 key: "isMateUnmapped", 41353 value: function () { 41354 return !!((0, a.default)(this) & c.BAM_FMUNMAP); 41355 } 41356 }, { 41357 key: "isReverseComplemented", 41358 value: function () { 41359 return !!((0, a.default)(this) & c.BAM_FREVERSE); 41360 } 41361 }, { 41362 key: "isMateReverseComplemented", 41363 value: function () { 41364 return !!((0, a.default)(this) & c.BAM_FMREVERSE); 41365 } 41366 }, { 41367 key: "isRead1", 41368 value: function () { 41369 return !!((0, a.default)(this) & c.BAM_FREAD1); 41370 } 41371 }, { 41372 key: "isRead2", 41373 value: function () { 41374 return !!((0, a.default)(this) & c.BAM_FREAD2); 41375 } 41376 }, { 41377 key: "isSecondary", 41378 value: function () { 41379 return !!((0, a.default)(this) & c.BAM_FSECONDARY); 41380 } 41381 }, { 41382 key: "isFailedQc", 41383 value: function () { 41384 return !!((0, a.default)(this) & c.BAM_FQCFAIL); 41385 } 41386 }, { 41387 key: "isDuplicate", 41388 value: function () { 41389 return !!((0, a.default)(this) & c.BAM_FDUP); 41390 } 41391 }, { 41392 key: "isSupplementary", 41393 value: function () { 41394 return !!((0, a.default)(this) & c.BAM_FSUPPLEMENTARY); 41395 } 41396 }, { 41397 key: "isDetached", 41398 value: function () { 41399 return !!(this.cramFlags & c.CRAM_FLAG_DETACHED); 41400 } 41401 }, { 41402 key: "hasMateDownStream", 41403 value: function () { 41404 return !!(this.cramFlags & c.CRAM_FLAG_MATE_DOWNSTREAM); 41405 } 41406 }, { 41407 key: "isPreservingQualityScores", 41408 value: function () { 41409 return !!(this.cramFlags & c.CRAM_FLAG_PRESERVE_QUAL_SCORES); 41410 } 41411 }, { 41412 key: "isUnknownBases", 41413 value: function () { 41414 return !!(this.cramFlags & c.CRAM_FLAG_NO_SEQ); 41415 } 41416 }, { 41417 key: "getReadBases", 41418 value: function () { 41419 return !this.readBases && this._refRegion && (this.readBases = function (t, e) { 41420 if ((t.lengthOnRef || t.readLength) && !t.isUnknownBases()) { 41421 var r = t.alignmentStart - e.start; 41422 if (!t.readFeatures) return e.seq.substr(r, t.lengthOnRef).toUpperCase(); 41423 41424 for (var n = "", i = r, o = 0; n.length < t.readLength;) if (o < t.readFeatures.length) { 41425 var a = t.readFeatures[o]; 41426 if ("Q" === a.code || "q" === a.code) o += 1;else if (a.pos === n.length + 1) { 41427 if (o += 1, "b" === a.code) { 41428 var s = a.data.split(","), 41429 u = String.fromCharCode.apply(String, (0, f.default)(s)); 41430 n += u, i += u.length; 41431 } else "B" === a.code ? (n += a.data[0], i += 1) : "X" === a.code ? (n += a.sub, i += 1) : "I" === a.code ? n += a.data : "D" === a.code ? i += a.data : "i" === a.code ? n += a.data : "N" === a.code ? i += a.data : "S" === a.code ? n += a.data : "P" === a.code || a.code;
41432 } else if (o < t.readFeatures.length) { 41433 var c = e.seq.substr(i, t.readFeatures[o].pos - n.length - 1); 41434 n += c, i += c.length; 41435 } 41436 } else { 41437 var l = e.seq.substr(i, t.readLength - n.length); 41438 n += l, i += l.length; 41439 } 41440 41441 return n.toUpperCase(); 41442 } 41443 }(this, this._refRegion)), this.readBases; 41444 } 41445 }, { 41446 key: "getPairOrientation", 41447 value: function () { 41448 if (!this.isSegmentUnmapped() && this.isPaired() && !this.isMateUnmapped() && this.mate && this.sequenceId === this.mate.sequenceId) { 41449 var t = this.isReverseComplemented() ? "R" : "F", 41450 e = this.isMateReverseComplemented() ? "R" : "F", 41451 r = " ", 41452 n = " "; 41453 this.isRead1() ? (r = "1", n = "2") : this.isRead2() && (r = "2", n = "1"); 41454 var i = [], 41455 o = this.templateLength || this.templateSize; 41456 return this.alignmentStart > this.mate.alignmentStart && o > 0 && (o = -o), o > 0 ? (i[0] = t, i[1] = r, i[2] = e, i[3] = n) : (i[2] = t, i[3] = r, i[0] = e, i[1] = n), i.join(""); 41457 } 41458 41459 return null; 41460 } 41461 }, { 41462 key: "addReferenceSequence", 41463 value: function (t, e) { 41464 var r; 41465 this.readFeatures && (0, o.default)(r = this.readFeatures).call(r, function (r) { 41466 "X" === r.code && function (t, e, r, n) { 41467 if (e) { 41468 var i = n.refPos - e.start, 41469 o = e.seq.charAt(i); 41470 o && (n.ref = o); 41471 var a = l[o]; 41472 void 0 === a && (a = 4); 41473 var s = r.substitutionMatrix[a][n.data]; 41474 s && (n.sub = s); 41475 } 41476 }(0, t, e, r); 41477 }); 41478 !this.readBases && t.start <= this.alignmentStart && t.end >= this.alignmentStart + (this.lengthOnRef || this.readLength) - 1 && (this._refRegion = t); 41479 } 41480 }, { 41481 key: "toJSON", 41482 value: function () { 41483 var t, 41484 e = this, 41485 r = {}; 41486 return (0, o.default)(t = (0, i.default)(this)).call(t, function (t) { 41487 "_" !== t.charAt(0) && (r[t] = e[t]); 41488 }), r.readBases = this.getReadBases(), r; 41489 } 41490 }]), t; 41491 }(); 41492 41493 t.exports = h; 41494 }, function (t, e, r) { 41495 41496 var n = r(1), 41497 i = n(r(98)), 41498 o = n(r(16)), 41499 a = n(r(75)), 41500 s = n(r(7)), 41501 u = n(r(10)), 41502 f = r(9).CramMalformedError, 41503 c = r(391).instantiateCodec, 41504 l = { 41505 BF: "int", 41506 CF: "int", 41507 RI: "int", 41508 RL: "int", 41509 AP: "int", 41510 RG: "int", 41511 MF: "int", 41512 NS: "int", 41513 NP: "int", 41514 TS: "int", 41515 NF: "int", 41516 TC: "byte", 41517 TN: "int", 41518 FN: "int", 41519 FC: "byte", 41520 FP: "int", 41521 BS: "byte", 41522 IN: "byteArray", 41523 SC: "byteArray", 41524 DL: "int", 41525 BA: "byte", 41526 BB: "byteArray", 41527 RS: "int", 41528 PD: "int", 41529 HC: "int", 41530 MQ: "int", 41531 RN: "byteArray", 41532 QS: "byte", 41533 QQ: "byteArray", 41534 TL: "int", 41535 TM: "ignore", 41536 TV: "ignore" 41537 }; 41538 41539 var h = function () { 41540 function t(e) { 41541 (0, s.default)(this, t), (0, a.default)(this, e), this.readNamesIncluded = e.preservation.RN, this.APdelta = e.preservation.AP, this.referenceRequired = !!e.preservation.RR, this.tagIdsDictionary = e.preservation.TD, this.substitutionMatrix = function (t) { 41542 for (var e = new Array(5), r = 0; r < 5; r += 1) e[r] = new Array(4); 41543 41544 return e[0][t[0] >> 6 & 3] = "C", e[0][t[0] >> 4 & 3] = "G", e[0][t[0] >> 2 & 3] = "T", e[0][t[0] >> 0 & 3] = "N", e[1][t[1] >> 6 & 3] = "A", e[1][t[1] >> 4 & 3] = "G", e[1][t[1] >> 2 & 3] = "T", e[1][t[1] >> 0 & 3] = "N", e[2][t[2] >>
41544 6 & 3] = "A", e[2][t[2] >> 4 & 3] = "C", e[2][t[2] >> 2 & 3] = "T", e[2][t[2] >> 0 & 3] = "N", e[3][t[3] >> 6 & 3] = "A", e[3][t[3] >> 4 & 3] = "C", e[3][t[3] >> 2 & 3] = "G", e[3][t[3] >> 0 & 3] = "N", e[4][t[4] >> 6 & 3] = "A", e[4][t[4] >> 4 & 3] = "C", e[4][t[4] >> 2 & 3] = "G", e[4][t[4] >> 0 & 3] = "T", e; 41545 }(e.preservation.SM), this.dataSeriesCodecCache = {}, this.tagCodecCache = {}; 41546 } 41547 41548 return (0, u.default)(t, [{ 41549 key: "getCodecForTag", 41550 value: function (t) { 41551 if (!this.tagCodecCache[t]) { 41552 var e = this.tagEncoding[t]; 41553 e && (this.tagCodecCache[t] = c(e, "byteArray")); 41554 } 41555 41556 return this.tagCodecCache[t]; 41557 } 41558 }, { 41559 key: "getTagNames", 41560 value: function (t) { 41561 return this.tagIdsDictionary[t]; 41562 } 41563 }, { 41564 key: "getCodecForDataSeries", 41565 value: function (t) { 41566 if (!this.dataSeriesCodecCache[t]) { 41567 var e = this.dataSeriesEncoding[t]; 41568 41569 if (e) { 41570 var r = l[t]; 41571 if (!r) throw new f("data series name ".concat(t, " not defined in file compression header")); 41572 this.dataSeriesCodecCache[t] = c(e, r); 41573 } 41574 } 41575 41576 return this.dataSeriesCodecCache[t]; 41577 } 41578 }, { 41579 key: "toJSON", 41580 value: function () { 41581 var t, 41582 e = this, 41583 r = {}; 41584 return (0, o.default)(t = (0, i.default)(this)).call(t, function (t) { 41585 /Cache$/.test(t) || (r[t] = e[t]); 41586 }), r; 41587 } 41588 }]), t; 41589 }(); 41590 41591 t.exports = h; 41592 }, function (t, e, r) { 41593 41594 var n = r(9).CramUnimplementedError, 41595 i = r(392), 41596 o = r(413), 41597 a = r(414), 41598 s = r(415), 41599 u = r(416), 41600 f = r(417), 41601 c = { 41602 1: o, 41603 3: i, 41604 4: s, 41605 5: a, 41606 6: u, 41607 7: r(418), 41608 9: f 41609 }; 41610 41611 function l(t) { 41612 return c[t]; 41613 } 41614 41615 t.exports = { 41616 getCodecClassWithId: l, 41617 instantiateCodec: function t(e, r) { 41618 var i = l("ignore" === r ? 0 : e.codecId); 41619 if (!i) throw new n("no codec implemented for codec ID ".concat(e.codecId)); 41620 return new i(e.parameters, r, t); 41621 } 41622 }; 41623 }, function (t, e, r) { 41624 41625 var n = r(1), 41626 i = n(r(97)), 41627 o = n(r(59)), 41628 a = n(r(77)), 41629 s = n(r(148)), 41630 u = n(r(159)), 41631 f = n(r(48)), 41632 c = n(r(102)), 41633 l = n(r(16)), 41634 h = n(r(103)), 41635 d = n(r(403)), 41636 p = n(r(7)), 41637 g = n(r(10)), 41638 v = n(r(32)), 41639 y = n(r(27)), 41640 m = n(r(33)), 41641 b = r(9).CramMalformedError; 41642 41643 var _ = function (t) { 41644 function e() { 41645 var t, 41646 r, 41647 n = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {}, 41648 i = arguments.length > 1 ? arguments[1] : void 0; 41649 if ((0, p.default)(this, e), r = (0, v.default)(this, (0, y.default)(e).call(this, n, i)), !(0, d.default)(t = ["byte", "int"]).call(t, r.dataType)) throw new TypeError("".concat(r.dataType, " decoding not yet implemented by HUFFMAN_INT codec")); 41650 return r.buildCodeBook(), r.buildCodes(), r.buildCaches(), 0 === r.sortedCodes[0].bitLength && (r._decode = r._decodeZeroLengthCode), r; 41651 } 41652 41653 return (0, m.default)(e, t), (0, g.default)(e, [{ 41654 key: "buildCodeBook", 41655 value: function () { 41656 for (var t = this, e = new Array(this.parameters.numCodes), r = 0; r < this.parameters.numCodes; r += 1) e[r] = { 41657 symbol: this.parameters.symbols[r], 41658 bitLength: this.parameters.bitLengths[r] 41659 }; 41660 41661 e = (0, h.default)(e).call(e, function (t, e) { 41662 return t.bitLength - e.bitLength || t.symbol - e.symbol; 41663 }), this.codeBook = {}, (0, l.default)(e).call(e, function (e) { 41664 t.codeBook[e.bitLength] || (t.codeBook[e.bitLength] = []), t.codeBook[e.bitLength].push(e.symbol); 41665 }); 41666 } 41667 }, { 41668 key: "buildCodes", 41669 value: function () { 41670 var t, 41671 e = this; 41672 this.codes = {}; 41673 var r = 0, 41674 n = -1; 41675 (0, l.default)(t = (0, c.default)(this.codeBook)).call(t, function (t) { 41676 var i = (0, f.default)(t, 2), 41677 o = i[0], 41678 a = i[1]; 41679 o = (0, u.default)(o, 10), (0, l.default)(a).call(a, function (t) { 41680 var i = { 41681 bitLength: o, 41682 value: t 41683 }; 41684 n += 1; 41685 var a, 41686 s, 41687 u = o - r; 41688 if (n <<= u, i.bitCode = n, r += u, 16843009 * ((s = (858993459 & (s = (a = n) - (a >> 1) & 1431655765)) + (s >> 2 & 858993459)) + (s >> 4) & 252645135) >> 24 > o) throw new b("Symbol out of range"); 41689 e.codes[t] = i; 41690 }); 41691 }); 41692 } 41693 }, { 41694 key: "buildCaches", 41695 value: function () { 41696 var t, e, r, n, u, f; 41697 this.sortedCodes = (0, h.default)(t = (0, s.default)(this.codes)).call(t, function (t, e) { 41698 return t.bitLength - e.bitLength || t.bitCode - e.bitCode; 41699 }), this.sortedByValue = (0, h.default)(e = (0, s.default)(this.codes)).call(e, function (t, e) { 41700 return t.value - e.value; 41701 }), this.sortedValuesByBitCode = (0, a.default)(r = this.sortedCodes).call(r, function (t) { 41702 return t.value; 41703 }), this.sortedBitCodes = (0, a.default)(n = this.sortedCodes).call(n, function (t) { 41704 return t.bitCode; 41705 }), this.sortedBitLengthsByBitCode = (0, a.default)(u = this.sortedCodes).call(u, function (t) { 41706 return t.bitLength; 41707 }); 41708 var c = Math.max.apply(Math, (0, o.default)(this.sortedBitCodes)); 41709 this.bitCodeToValue = (0, i.default)(f = new Array(c + 1)).call(f, -1); 41710 41711 for (var l = 0; l < this.sortedBitCodes.length; l += 1) this.bitCodeToValue[this.sortedCodes[l].bitCode] = l; 41712 } 41713 }, { 41714 key: "decode", 41715 value: function (t, e, r, n) { 41716 return this._decode(t, e, n.coreBlock); 41717 } 41718 }, { 41719 key: "_decodeZeroLengthCode", 41720 value: function () { 41721 return this.sortedCodes[0].value; 41722 } 41723 }, { 41724 key: "_decode", 41725 value: function (t, e, r) { 41726 for (var n = e.content, i = 0, o = 0, a = 0; a < this.sortedCodes.length; a += 1) { 41727 var s = this.sortedCodes[a].bitLength; 41728 o <<= s - i, o |= this._getBits(n, r, s - i), i = s; 41729 var u = this.bitCodeToValue[o]; 41730 if (u > -1 && this.sortedBitLengthsByBitCode[u] === s) return this.sortedValuesByBitCode[u]; 41731 41732 for (var f = a; this.sortedCodes[f + 1].bitLength === s && f < this.sortedCodes.length; f += 1) a += 1; 41733 } 41734 41735 throw new b("Huffman symbol not found."); 41736 } 41737 }]), e; 41738 }
41738(r(40)); 41739 41740 t.exports = _; 41741 }, function (t, e, r) { 41742 t.exports = r(394); 41743 }, function (t, e, r) { 41744 r(395); 41745 var n = r(3); 41746 t.exports = n.parseInt; 41747 }, function (t, e, r) { 41748 var n = r(0), 41749 i = r(155); 41750 n({ 41751 global: !0, 41752 forced: parseInt != i 41753 }, { 41754 parseInt: i 41755 }); 41756 }, function (t, e, r) { 41757 t.exports = r(397); 41758 }, function (t, e, r) { 41759 r(398); 41760 var n = r(3); 41761 t.exports = n.Object.entries; 41762 }, function (t, e, r) { 41763 var n = r(0), 41764 i = r(149).entries; 41765 n({ 41766 target: "Object", 41767 stat: !0 41768 }, { 41769 entries: function (t) { 41770 return i(t); 41771 } 41772 }); 41773 }, function (t, e, r) { 41774 t.exports = r(400); 41775 }, function (t, e, r) { 41776 var n = r(401), 41777 i = Array.prototype; 41778 41779 t.exports = function (t) { 41780 var e = t.sort; 41781 return t === i || t instanceof Array && e === i.sort ? n : e; 41782 }; 41783 }, function (t, e, r) { 41784 r(402); 41785 var n = r(18); 41786 t.exports = n("Array").sort; 41787 }, function (t, e, r) { 41788 41789 var n = r(0), 41790 i = r(5), 41791 o = r(22), 41792 a = r(12), 41793 s = r(54), 41794 u = [].sort, 41795 f = [1, 2, 3], 41796 c = a(function () { 41797 f.sort(void 0); 41798 }), 41799 l = a(function () { 41800 f.sort(null); 41801 }), 41802 h = s("sort"); 41803 n({ 41804 target: "Array", 41805 proto: !0, 41806 forced: c || !l || h 41807 }, { 41808 sort: function (t) { 41809 return void 0 === t ? u.call(o(this)) : u.call(o(this), i(t)); 41810 } 41811 }); 41812 }, function (t, e, r) { 41813 t.exports = r(404); 41814 }, function (t, e, r) { 41815 t.exports = r(405); 41816 }, function (t, e, r) { 41817 var n = r(406), 41818 i = r(408), 41819 o = Array.prototype, 41820 a = String.prototype; 41821 41822 t.exports = function (t) { 41823 var e = t.includes; 41824 return t === o || t instanceof Array && e === o.includes ? n : "string" == typeof t || t === a || t instanceof String && e === a.includes ? i : e; 41825 }; 41826 }, function (t, e, r) { 41827 r(407); 41828 var n = r(18); 41829 t.exports = n("Array").includes; 41830 }, function (t, e, r) { 41831 41832 var n = r(0), 41833 i = r(82).includes, 41834 o = r(78); 41835 n({ 41836 target: "Array", 41837 proto: !0 41838 }, { 41839 includes: function (t) { 41840 return i(this, t, arguments.length > 1 ? arguments[1] : void 0); 41841 } 41842 }), o("includes"); 41843 }, function (t, e, r) { 41844 r(409); 41845 var n = r(18); 41846 t.exports = n("String").includes; 41847 }, function (t, e, r) { 41848 41849 var n = r(0), 41850 i = r(410), 41851 o = r(49); 41852 n({ 41853 target: "String", 41854 proto: !0, 41855 forced: !r(412)("includes") 41856 }, { 41857 includes: function (t) { 41858 return !!~String(o(this)).indexOf(i(t), arguments.length > 1 ? arguments[1] : void 0); 41859 } 41860 }); 41861 }, function (t, e, r) { 41862 var n = r(411); 41863 41864 t.exports = function (t) { 41865 if (n(t)) throw TypeError("The method doesn't accept regular expressions"); 41866 return t; 41867 }; 41868 }, function (t, e, r) { 41869 var n = r(14), 41870 i = r(34), 41871 o = r(6)("match"); 41872 41873 t.exports = function (t) { 41874 var e; 41875 return n(t) && (void 0 !== (e = t[o]) ? !!e : "RegExp" == i(t)); 41876 }; 41877 }, function (t, e, r) { 41878 var n = r(6)("match"); 41879 41880 t.exports = function (t) { 41881 var e = /./; 41882 41883 try { 41884 "/./"[t](e); 41885 } catch (r) { 41886 try { 41887 return e[n] = !1, "/./"[t](e); 41888 } catch (t) {} 41889 } 41890 41891 return !1; 41892 }; 41893 }, function (t, e, r) { 41894 41895 var n = r(1), 41896 i = n(r(48)), 41897 o = n(r(7)), 41898 a = n(r(10)), 41899 s = n(r(32)), 41900 u = n(r(27)), 41901 f = n(r(33)), 41902 c = r(9), 41903 l = c.CramUnimplementedError, 41904 h = c.CramMalformedError, 41905 d = c.CramBufferOverrunError, 41906 p = r(40), 41907 g = r(58).parseItf8, 41908 v = function (t) { 41909 function e() { 41910 var t, 41911 r = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {}, 41912 n = arguments.length > 1 ? arguments[1] : void 0; 41913 if ((0, o.default)(this, e), "int" === (t = (0, s.default)(this, (0, u.default)(e).call(this, r, n))).dataType) t._decodeData = t._decodeInt;else { 41914 if ("byte" !== t.dataType) throw new l("".concat(t.dataType, " decoding not yet implemented by EXTERNAL codec")); 41915 t._decodeData = t._decodeByte; 41916 } 41917 return t; 41918 } 41919 41920 return (0, f.default)(e, t), (0, a.default)(e, [{ 41921 key: "decode", 41922 value: function (t, e, r, n) { 41923 var i = this.parameters.blockContentId, 41924 o = r[i]; 41925 if (!o) throw new h("no block found with content ID ".concat(i)); 41926 var a = n.externalBlocks.getCursor(i); 41927 return this._decodeData(o, a); 41928 } 41929 }, { 41930 key: "_decodeInt", 41931 value: function (t, e) { 41932 var r = g(t.content, e.bytePosition), 41933 n = (0, i.default)(r, 2), 41934 o = n[0], 41935 a = n[1]; 41936 return e.bytePosition += a, o; 41937 } 41938 }, { 41939 key: "_decodeByte", 41940 value: function (t, e) { 41941 if (e.bytePosition >= t.content.length) throw new d("attempted to read beyond end of block. this file seems truncated."); 41942 var r = t.content[e.bytePosition]; 41943 return e.bytePosition += 1, r; 41944 } 41945 }]), e; 41946 }(p); 41947 41948 t.exports = v; 41949 }, function (t, e, r) { 41950 41951 var n = r(1), 41952 i = n(r(101)), 41953 o = n(r(7)), 41954 a = n(r(10)), 41955 s = n(r(32)), 41956 u = n(r(27)), 41957 f = n(r(33)), 41958 c = r(9), 41959 l = c.CramBufferOverrunError, 41960 h = c.CramMalformedError, 41961 d = function (t) { 41962 function e() { 41963 var t, 41964 r = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {}, 41965 n = arguments.length > 1 ? arguments[1] : void 0; 41966 if ((0, o.default)(this, e), t = (0, s.default)(this, (0, u.default)(e).call(this, r, n)), "byteArray" !== n) throw new TypeError("byteArrayStop codec does not support data type ".concat(n)); 41967 return t._decode = t._decodeByteArray, t; 41968 } 41969 41970 return (0, f.default)(e, t), (0, a.default)(e, [{ 41971 key: "decode", 41972 value: function (t, e, r, n) { 41973 var i = this.parameters.blockContentId, 41974 o = r[i]; 41975 if (!o) throw new h("no block found with content ID ".concat(i)); 41976 var a = n.externalBlocks.getCursor(i); 41977 return this._decode(o, a); 41978 } 41979 }, { 41980 key: "_decodeByteArray", 41981 value: function (t, e) { 41982 for (var r = t.content, n = this.parameters.stopByte, o = e.bytePosition, a = e.bytePosition; r[a] !== n && a < r.length;) { 41983 if (a === r.length) throw new l("byteArrayStop reading beyond length of data buffer?"); 41984 a += 1; 41985 } 41986 41987 return e.bytePosition = a + 1, (0, i.default)(r).call(r, o, a); 41988 } 41989 }]), e; 41990 }
41990(r(40)); 41991 41992 t.exports = d; 41993 }, function (t, e, r) { 41994 41995 var n, 41996 i = r(1), 41997 o = i(r(16)), 41998 a = i(r(7)), 41999 s = i(r(10)), 42000 u = i(r(32)), 42001 f = i(r(27)), 42002 c = i(r(33)), 42003 l = r(58).tinyMemoize, 42004 h = function (t) { 42005 function e() { 42006 var t, 42007 r = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {}, 42008 n = arguments.length > 1 ? arguments[1] : void 0, 42009 i = arguments.length > 2 ? arguments[2] : void 0; 42010 if ((0, a.default)(this, e), (t = (0, u.default)(this, (0, f.default)(e).call(this, r, n))).instantiateCodec = i, "byteArray" !== n) throw new TypeError("byteArrayLength does not support data type ".concat(n)); 42011 return t; 42012 } 42013 42014 return (0, c.default)(e, t), (0, s.default)(e, [{ 42015 key: "decode", 42016 value: function (t, e, r, n) { 42017 for (var i = this._getLengthCodec().decode(t, e, r, n), o = this._getDataCodec(), a = new Array(i), s = 0; s < i; s += 1) a[s] = o.decode(t, e, r, n); 42018 42019 return a; 42020 } 42021 }, { 42022 key: "_getLengthCodec", 42023 value: function () { 42024 var t = this.parameters.lengthsEncoding; 42025 return this.instantiateCodec(t, "int"); 42026 } 42027 }, { 42028 key: "_getDataCodec", 42029 value: function () { 42030 var t = this.parameters.valuesEncoding; 42031 return this.instantiateCodec(t, "byte"); 42032 } 42033 }]), e; 42034 }(r(40)); 42035 42036 (0, o.default)(n = "_getLengthCodec _getDataCodec".split(" ")).call(n, function (t) { 42037 return l(h, t); 42038 }), t.exports = h; 42039 }, function (t, e, r) { 42040 42041 var n = r(1), 42042 i = n(r(7)), 42043 o = n(r(10)), 42044 a = n(r(32)), 42045 s = n(r(27)), 42046 u = n(r(33)), 42047 f = r(9).CramUnimplementedError, 42048 c = function (t) { 42049 function e() { 42050 var t, 42051 r = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {}, 42052 n = arguments.length > 1 ? arguments[1] : void 0; 42053 if ((0, i.default)(this, e), "int" !== (t = (0, a.default)(this, (0, s.default)(e).call(this, r, n))).dataType) throw new f("".concat(t.dataType, " decoding not yet implemented by BETA codec")); 42054 return t; 42055 } 42056 42057 return (0, u.default)(e, t), (0, o.default)(e, [{ 42058 key: "decode", 42059 value: function (t, e, r, n) { 42060 return this._getBits(e.content, n.coreBlock, this.parameters.length) - this.parameters.offset; 42061 } 42062 }]), e; 42063 }(r(40)); 42064 42065 t.exports = c; 42066 }, function (t, e, r) { 42067 42068 var n = r(1), 42069 i = n(r(7)), 42070 o = n(r(10)), 42071 a = n(r(32)), 42072 s = n(r(27)), 42073 u = n(r(33)), 42074 f = r(9).CramUnimplementedError, 42075 c = function (t) { 42076 function e() { 42077 var t, 42078 r = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {}, 42079 n = arguments.length > 1 ? arguments[1] : void 0; 42080 if ((0, i.default)(this, e), "int" !== (t = (0, a.default)(this, (0, s.default)(e).call(this, r, n))).dataType) throw new f("".concat(t.dataType, " decoding not yet implemented by GAMMA codec")); 42081 return t; 42082 } 42083 42084 return (0, u.default)(e, t), (0, o.default)(e, [{ 42085 key: "decode", 42086 value: function (t, e, r, n) { 42087 for (var i = 1; 0 === this._getBits(e.content, n.coreBlock, 1);) i += 1; 42088 42089 return (this._getBits(e.content, n.coreBlock, i - 1) | 1 << i - 1) - this.parameters.offset; 42090 } 42091 }]), e; 42092 }(r(40)); 42093 42094 t.exports = c; 42095 }, function (t, e, r) { 42096 42097 var n = r(1), 42098 i = n(r(7)), 42099 o = n(r(10)), 42100 a = n(r(32)), 42101 s = n(r(27)), 42102 u = n(r(33)), 42103 f = r(9).CramUnimplementedError, 42104 c = function (t) { 42105 function e() { 42106 var t, 42107 r = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {}, 42108 n = arguments.length > 1 ? arguments[1] : void 0; 42109 if ((0, i.default)(this, e), "int" !== (t = (0, a.default)(this, (0, s.default)(e).call(this, r, n))).dataType) throw new f("".concat(t.dataType, " decoding not yet implemented by SUBEXP codec")); 42110 return t; 42111 } 42112 42113 return (0, u.default)(e, t), (0, o.default)(e, [{ 42114 key: "decode", 42115 value: function (t, e, r, n) { 42116 for (var i, o, a = 0; this._getBits(e.content, n.coreBlock, 1);) a += 1; 42117 42118 return 0 === a ? (i = this.parameters.K, o = this._getBits(e.content, n.coreBlock, i)) : o = 1 << (i = a + this.parameters.K - 1) | this._getBits(e.content, n.coreBlock, i), o - this.parameters.offset; 42119 } 42120 }]), e; 42121 }
42121(r(40)); 42122 42123 t.exports = c; 42124 }, function (t, e, r) { 42125 42126 var n = r(420), 42127 i = r(422); 42128 42129 function o() { 42130 this.protocol = null, this.slashes = null, this.auth = null, this.host = null, this.port = null, this.hostname = null, this.hash = null, this.search = null, this.query = null, this.pathname = null, this.path = null, this.href = null; 42131 } 42132 42133 e.parse = b, e.resolve = function (t, e) { 42134 return b(t, !1, !0).resolve(e); 42135 }, e.resolveObject = function (t, e) { 42136 return t ? b(t, !1, !0).resolveObject(e) : e; 42137 }, e.format = function (t) { 42138 i.isString(t) && (t = b(t)); 42139 return t instanceof o ? t.format() : o.prototype.format.call(t); 42140 }, e.Url = o; 42141 var a = /^([a-z0-9.+-]+:)/i, 42142 s = /:[0-9]*$/, 42143 u = /^(\/\/?(?!\/)[^\?\s]*)(\?[^\s]*)?$/, 42144 f = ["{", "}", "|", "\\", "^", "`"].concat(["<", ">", '"', "`", " ", "\r", "\n", "\t"]), 42145 c = ["'"].concat(f), 42146 l = ["%", "/", "?", ";", "#"].concat(c), 42147 h = ["/", "?", "#"], 42148 d = /^[+a-z0-9A-Z_-]{0,63}$/, 42149 p = /^([+a-z0-9A-Z_-]{0,63})(.*)$/, 42150 g = { 42151 javascript: !0, 42152 "javascript:": !0 42153 }, 42154 v = { 42155 javascript: !0, 42156 "javascript:": !0 42157 }, 42158 y = { 42159 http: !0, 42160 https: !0, 42161 ftp: !0, 42162 gopher: !0, 42163 file: !0, 42164 "http:": !0, 42165 "https:": !0, 42166 "ftp:": !0, 42167 "gopher:": !0, 42168 "file:": !0 42169 }, 42170 m = r(423); 42171 42172 function b(t, e, r) { 42173 if (t && i.isObject(t) && t instanceof o) return t; 42174 var n = new o(); 42175 return n.parse(t, e, r), n; 42176 } 42177 42178 o.prototype.parse = function (t, e, r) { 42179 if (!i.isString(t)) throw new TypeError("Parameter 'url' must be a string, not " + typeof t); 42180 var o = t.indexOf("?"), 42181 s = -1 !== o && o < t.indexOf("#") ? "?" : "#", 42182 f = t.split(s); 42183 f[0] = f[0].replace(/\\/g, "/"); 42184 var b = t = f.join(s); 42185 42186 if (b = b.trim(), !r && 1 === t.split("#").length) { 42187 var _ = u.exec(b); 42188 42189 if (_) return this.path = b, this.href = b, this.pathname = _[1], _[2] ? (this.search = _[2], this.query = e ? m.parse(this.search.substr(1)) : this.search.substr(1)) : e && (this.search = "", this.query = {}), this; 42190 } 42191 42192 var w = a.exec(b); 42193 42194 if (w) { 42195 var x = (w = w[0]).toLowerCase(); 42196 this.protocol = x, b = b.substr(w.length); 42197 } 42198 42199 if (r || w || b.match(/^\/\/[^@\/]+@[^@\/]+/)) { 42200 var E = "//" === b.substr(0, 2); 42201 !E || w && v[w] || (b = b.substr(2), this.slashes = !0); 42202 } 42203 42204 if (!v[w] && (E || w && !y[w])) { 42205 for (var S, k, A = -1, C = 0; C < h.length; C++) { 42206 -1 !== (T = b.indexOf(h[C])) && (-1 === A || T < A) && (A = T); 42207 } 42208 42209 -1 !== (k = -1 === A ? b.lastIndexOf("@") : b.lastIndexOf("@", A)) && (S = b.slice(0, k), b = b.slice(k + 1), this.auth = decodeURIComponent(S)), A = -1; 42210 42211 for (C = 0; C < l.length; C++) { 42212 var T; 42213 -1 !== (T = b.indexOf(l[C])) && (-1 === A || T < A) && (A = T); 42214 } 42215 42216 -1 === A && (A = b.length), this.host = b.slice(0, A), b = b.slice(A), this.parseHost(), this.hostname = this.hostname || ""; 42217 var R = "[" === this.hostname[0] && "]" === this.hostname[this.hostname.length - 1]; 42218 if (!R) for (var O = this.hostname.split(/\./), I = (C = 0, O.length); C < I; C++) { 42219 var L = O[C]; 42220 42221 if (L && !L.match(d)) { 42222 for (var B = "", P = 0, F = L.length; P < F; P++) L.charCodeAt(P) > 127 ? B += "x" : B += L[P]; 42223 42224 if (!B.match(d)) { 42225 var N = O.slice(0, C), 42226 M = O.slice(C + 1), 42227 j = L.match(p); 42228 j && (N.push(j[1]), M.unshift(j[2])), M.length && (b = "/" + M.join(".") + b), this.hostname = N.join("."); 42229 break; 42230 } 42231 } 42232 } 42233 this.hostname.length > 255 ? this.hostname = "" : this.hostname = this.hostname.toLowerCase(), R || (this.hostname = n.toASCII(this.hostname)); 42234 var z = this.port ? ":" + this.port : "", 42235 U = this.hostname || ""; 42236 this.host = U + z, this.href += this.host, R && (this.hostname = this.hostname.substr(1, this.hostname.length - 2), "/" !== b[0] && (b = "/" + b)); 42237 } 42238 42239 if (!g[x]) for (C = 0, I = c.length; C < I; C++) { 42240 var D = c[C]; 42241 42242 if (-1 !== b.indexOf(D)) { 42243 var q = encodeURIComponent(D); 42244 q === D && (q = escape(D)), b = b.split(D).join(q); 42245 } 42246 } 42247 var Z = b.indexOf("#"); 42248 -1 !== Z && (this.hash = b.substr(Z), b = b.slice(0, Z)); 42249 var H = b.indexOf("?"); 42250 42251 if (-1 !== H ? (this.search = b.substr(H), this.query = b.substr(H + 1), e && (this.query = m.parse(this.query)), b = b.slice(0, H)) : e && (this.search = "", this.query = {}), b && (this.pathname = b), y[x] && this.hostname && !this.pathname && (this.pathname = "/"), this.pathname || this.search) { 42252 z = this.pathname || ""; 42253 var V = this.search || ""; 42254 this.path = z + V; 42255 } 42256 42257 return this.href = this.format(), this; 42258 }, o.prototype.format = function () { 42259 var t = this.auth || ""; 42260 t && (t = (t = encodeURIComponent(t)).replace(/%3A/i, ":"), t += "@"); 42261 var e = this.protocol || "", 42262 r = this.pathname || "", 42263 n = this.hash || "", 42264 o = !1, 42265 a = ""; 42266 this.host ? o = t + this.host : this.hostname && (o = t + (-1 === this.hostname.indexOf(":") ? this.hostname : "[" + this.hostname + "]"), this.port && (o += ":" + this.port)), this.query && i.isObject(this.query) && Object.keys(this.query).length && (a = m.stringify(this.query)); 42267 var s = this.search || a && "?" + a || ""; 42268 return e && ":" !== e.substr(-1) && (e += ":"), this.slashes || (!e || y[e]) && !1 !== o ? (o = "//" + (o || ""), r && "/" !== r.charAt(0) && (r = "/" + r)) : o || (
42268o = ""), n && "#" !== n.charAt(0) && (n = "#" + n), s && "?" !== s.charAt(0) && (s = "?" + s), e + o + (r = r.replace(/[?#]/g, function (t) { 42269 return encodeURIComponent(t); 42270 })) + (s = s.replace("#", "%23")) + n; 42271 }, o.prototype.resolve = function (t) { 42272 return this.resolveObject(b(t, !1, !0)).format(); 42273 }, o.prototype.resolveObject = function (t) { 42274 if (i.isString(t)) { 42275 var e = new o(); 42276 e.parse(t, !1, !0), t = e; 42277 } 42278 42279 for (var r = new o(), n = Object.keys(this), a = 0; a < n.length; a++) { 42280 var s = n[a]; 42281 r[s] = this[s]; 42282 } 42283 42284 if (r.hash = t.hash, "" === t.href) return r.href = r.format(), r; 42285 42286 if (t.slashes && !t.protocol) { 42287 for (var u = Object.keys(t), f = 0; f < u.length; f++) { 42288 var c = u[f]; 42289 "protocol" !== c && (r[c] = t[c]); 42290 } 42291 42292 return y[r.protocol] && r.hostname && !r.pathname && (r.path = r.pathname = "/"), r.href = r.format(), r; 42293 } 42294 42295 if (t.protocol && t.protocol !== r.protocol) { 42296 if (!y[t.protocol]) { 42297 for (var l = Object.keys(t), h = 0; h < l.length; h++) { 42298 var d = l[h]; 42299 r[d] = t[d]; 42300 } 42301 42302 return r.href = r.format(), r; 42303 } 42304 42305 if (r.protocol = t.protocol, t.host || v[t.protocol]) r.pathname = t.pathname;else { 42306 for (var p = (t.pathname || "").split("/"); p.length && !(t.host = p.shift());); 42307 42308 t.host || (t.host = ""), t.hostname || (t.hostname = ""), "" !== p[0] && p.unshift(""), p.length < 2 && p.unshift(""), r.pathname = p.join("/"); 42309 } 42310 42311 if (r.search = t.search, r.query = t.query, r.host = t.host || "", r.auth = t.auth, r.hostname = t.hostname || t.host, r.port = t.port, r.pathname || r.search) { 42312 var g = r.pathname || "", 42313 m = r.search || ""; 42314 r.path = g + m; 42315 } 42316 42317 return r.slashes = r.slashes || t.slashes, r.href = r.format(), r; 42318 } 42319 42320 var b = r.pathname && "/" === r.pathname.charAt(0), 42321 _ = t.host || t.pathname && "/" === t.pathname.charAt(0), 42322 w = _ || b || r.host && t.pathname, 42323 x = w, 42324 E = r.pathname && r.pathname.split("/") || [], 42325 S = (p = t.pathname && t.pathname.split("/") || [], r.protocol && !y[r.protocol]); 42326 42327 if (S && (r.hostname = "", r.port = null, r.host && ("" === E[0] ? E[0] = r.host : E.unshift(r.host)), r.host = "", t.protocol && (t.hostname = null, t.port = null, t.host && ("" === p[0] ? p[0] = t.host : p.unshift(t.host)), t.host = null), w = w && ("" === p[0] || "" === E[0])), _) r.host = t.host || "" === t.host ? t.host : r.host, r.hostname = t.hostname || "" === t.hostname ? t.hostname : r.hostname, r.search = t.search, r.query = t.query, E = p;else if (p.length) E || (E = []), E.pop(), E = E.concat(p), r.search = t.search, r.query = t.query;else if (!i.isNullOrUndefined(t.search)) { 42328 if (S) r.hostname = r.host = E.shift(), (R = !!(r.host && r.host.indexOf("@") > 0) && r.host.split("@")) && (r.auth = R.shift(), r.host = r.hostname = R.shift()); 42329 return r.search = t.search, r.query = t.query, i.isNull(r.pathname) && i.isNull(r.search) || (r.path = (r.pathname ? r.pathname : "") + (r.search ? r.search : "")), r.href = r.format(), r; 42330 } 42331 if (!E.length) return r.pathname = null, r.search ? r.path = "/" + r.search : r.path = null, r.href = r.format(), r; 42332 42333 for (var k = E.slice(-1)[0], A = (r.host || t.host || E.length > 1) && ("." === k || ".." === k) || "" === k, C = 0, T = E.length; T >= 0; T--) "." === (k = E[T]) ? E.splice(T, 1) : ".." === k ? (E.splice(T, 1), C++) : C && (E.splice(T, 1), C--); 42334 42335 if (!w && !x) for (; C--; C) E.unshift(".."); 42336 !w || "" === E[0] || E[0] && "/" === E[0].charAt(0) || E.unshift(""), A && "/" !== E.join("/").substr(-1) && E.push(""); 42337 var R, 42338 O = "" === E[0] || E[0] && "/" === E[0].charAt(0); 42339 S && (r.hostname = r.host = O ? "" : E.length ? E.shift() : "", (
42339R = !!(r.host && r.host.indexOf("@") > 0) && r.host.split("@")) && (r.auth = R.shift(), r.host = r.hostname = R.shift())); 42340 return (w = w || r.host && E.length) && !O && E.unshift(""), E.length ? r.pathname = E.join("/") : (r.pathname = null, r.path = null), i.isNull(r.pathname) && i.isNull(r.search) || (r.path = (r.pathname ? r.pathname : "") + (r.search ? r.search : "")), r.auth = t.auth || r.auth, r.slashes = r.slashes || t.slashes, r.href = r.format(), r; 42341 }, o.prototype.parseHost = function () { 42342 var t = this.host, 42343 e = s.exec(t); 42344 e && (":" !== (e = e[0]) && (this.port = e.substr(1)), t = t.substr(0, t.length - e.length)), t && (this.hostname = t); 42345 }; 42346 }, function (t, e, r) { 42347 (function (t, n) { 42348 var i; 42349 /*! https://mths.be/punycode v1.4.1 by @mathias */ 42350 42351 !function (o) { 42352 e && e.nodeType, t && t.nodeType; 42353 var a = "object" == typeof n && n; 42354 a.global !== a && a.window !== a && a.self; 42355 var s, 42356 u = 2147483647, 42357 f = 36, 42358 c = 1, 42359 l = 26, 42360 h = 38, 42361 d = 700, 42362 p = 72, 42363 g = 128, 42364 v = "-", 42365 y = /^xn--/, 42366 m = /[^\x20-\x7E]/, 42367 b = /[\x2E\u3002\uFF0E\uFF61]/g, 42368 _ = { 42369 overflow: "Overflow: input needs wider integers to process", 42370 "not-basic": "Illegal input >= 0x80 (not a basic code point)", 42371 "invalid-input": "Invalid input" 42372 }, 42373 w = f - c, 42374 x = Math.floor, 42375 E = String.fromCharCode; 42376 42377 function S(t) { 42378 throw new RangeError(_[t]); 42379 } 42380 42381 function k(t, e) { 42382 for (var r = t.length, n = []; r--;) n[r] = e(t[r]); 42383 42384 return n; 42385 } 42386 42387 function A(t, e) { 42388 var r = t.split("@"), 42389 n = ""; 42390 return r.length > 1 && (n = r[0] + "@", t = r[1]), n + k((t = t.replace(b, ".")).split("."), e).join("."); 42391 } 42392 42393 function C(t) { 42394 for (var e, r, n = [], i = 0, o = t.length; i < o;) (e = t.charCodeAt(i++)) >= 55296 && e <= 56319 && i < o ? 56320 == (64512 & (r = t.charCodeAt(i++))) ? n.push(((1023 & e) << 10) + (1023 & r) + 65536) : (n.push(e), i--) : n.push(e); 42395 42396 return n; 42397 } 42398 42399 function T(t) { 42400 return k(t, function (t) { 42401 var e = ""; 42402 return t > 65535 && (e += E((t -= 65536) >>> 10 & 1023 | 55296), t = 56320 | 1023 & t), e += E(t); 42403 }).join(""); 42404 } 42405 42406 function R(t, e) { 42407 return t + 22 + 75 * (t < 26) - ((0 != e) << 5); 42408 } 42409 42410 function O(t, e, r) { 42411 var n = 0; 42412 42413 for (t = r ? x(t / d) : t >> 1, t += x(t / e); t > w * l >> 1; n += f) t = x(t / w); 42414 42415 return x(n + (w + 1) * t / (t + h)); 42416 } 42417 42418 function I(t) { 42419 var e, 42420 r, 42421 n, 42422 i, 42423 o, 42424 a, 42425 s, 42426 h, 42427 d, 42428 y, 42429 m, 42430 b = [], 42431 _ = t.length, 42432 w = 0, 42433 E = g, 42434 k = p; 42435 42436 for ((r = t.lastIndexOf(v)) < 0 && (r = 0), n = 0; n < r; ++n) t.charCodeAt(n) >= 128 && S("not-basic"), b.push(t.charCodeAt(n)); 42437 42438 for (i = r > 0 ? r + 1 : 0; i < _;) { 42439 for (o = w, a = 1, s = f; i >= _ && S("invalid-input"), ((h = (m = t.charCodeAt(i++)) - 48 < 10 ? m - 22 : m - 65 < 26 ? m - 65 : m - 97 < 26 ? m - 97 : f) >= f || h > x((u - w) / a)) && S("overflow"), w += h * a, !(h < (d = s <= k ? c : s >= k + l ? l : s - k)); s += f) a > x(u / (y = f - d)) && S("overflow"), a *= y; 42440 42441 k = O(w - o, e = b.length + 1, 0 == o), x(w / e) > u - E && S("overflow"), E += x(w / e), w %= e, b.splice(w++, 0, E); 42442 } 42443 42444 return T(b); 42445 } 42446 42447 function L(t) { 42448 var e, 42449 r, 42450 n, 42451 i, 42452 o, 42453 a, 42454 s, 42455 h, 42456 d, 42457 y, 42458 m, 42459 b, 42460 _, 42461 w, 42462 k, 42463 A = []; 42464 42465 for (b = (t = C(t)).length, e = g, r = 0, o = p, a = 0; a < b; ++a) (m = t[a]) < 128 && A.push(E(m)); 42466 42467 for (n = i = A.length, i && A.push(v); n < b;) { 42468 for (s = u, a = 0; a < b; ++a) (m = t[a]) >= e && m < s && (s = m); 42469 42470 for (s - e > x((u - r) / (_ = n + 1)) && S("overflow"), r += (s - e) * _, e = s, a = 0; a < b; ++a) if ((m = t[a]) < e && ++r > u && S("overflow"), m == e) { 42471 for (h = r, d = f; !(h < (y = d <= o ? c : d >= o + l ? l : d - o)); d += f) k = h - y, w = f - y, A.push(E(R(y + k % w, 0))), h = x(k / w); 42472
42473 A.push(E(R(h, 0))), o = O(r, _, n == i), r = 0, ++n; 42474 } 42475 42476 ++r, ++e; 42477 } 42478 42479 return A.join(""); 42480 } 42481 42482 s = { 42483 version: "1.4.1", 42484 ucs2: { 42485 decode: C, 42486 encode: T 42487 }, 42488 decode: I, 42489 encode: L, 42490 toASCII: function (t) { 42491 return A(t, function (t) { 42492 return m.test(t) ? "xn--" + L(t) : t; 42493 }); 42494 }, 42495 toUnicode: function (t) { 42496 return A(t, function (t) { 42497 return y.test(t) ? I(t.slice(4).toLowerCase()) : t; 42498 }); 42499 } 42500 }, void 0 === (i = function () { 42501 return s; 42502 }.call(e, r, e, t)) || (t.exports = i); 42503 }(); 42504 }).call(this, r(421)(t), r(23)); 42505 }, function (t, e) { 42506 t.exports = function (t) { 42507 return t.webpackPolyfill || (t.deprecate = function () {}, t.paths = [], t.children || (t.children = []), Object.defineProperty(t, "loaded", { 42508 enumerable: !0, 42509 get: function () { 42510 return t.l; 42511 } 42512 }), Object.defineProperty(t, "id", { 42513 enumerable: !0, 42514 get: function () { 42515 return t.i; 42516 } 42517 }), t.webpackPolyfill = 1), t; 42518 }; 42519 }, function (t, e, r) { 42520 42521 t.exports = { 42522 isString: function (t) { 42523 return "string" == typeof t; 42524 }, 42525 isObject: function (t) { 42526 return "object" == typeof t && null !== t; 42527 }, 42528 isNull: function (t) { 42529 return null === t; 42530 }, 42531 isNullOrUndefined: function (t) { 42532 return null == t; 42533 } 42534 }; 42535 }, function (t, e, r) { 42536 42537 e.decode = e.parse = r(424), e.encode = e.stringify = r(425); 42538 }, function (t, e, r) { 42539 42540 function n(t, e) { 42541 return Object.prototype.hasOwnProperty.call(t, e); 42542 } 42543 42544 t.exports = function (t, e, r, o) { 42545 e = e || "&", r = r || "="; 42546 var a = {}; 42547 if ("string" != typeof t || 0 === t.length) return a; 42548 var s = /\+/g; 42549 t = t.split(e); 42550 var u = 1e3; 42551 o && "number" == typeof o.maxKeys && (u = o.maxKeys); 42552 var f = t.length; 42553 u > 0 && f > u && (f = u); 42554 42555 for (var c = 0; c < f; ++c) { 42556 var l, 42557 h, 42558 d, 42559 p, 42560 g = t[c].replace(s, "%20"), 42561 v = g.indexOf(r); 42562 v >= 0 ? (l = g.substr(0, v), h = g.substr(v + 1)) : (l = g, h = ""), d = decodeURIComponent(l), p = decodeURIComponent(h), n(a, d) ? i(a[d]) ? a[d].push(p) : a[d] = [a[d], p] : a[d] = p; 42563 } 42564 42565 return a; 42566 }; 42567 42568 var i = Array.isArray || function (t) { 42569 return "[object Array]" === Object.prototype.toString.call(t); 42570 }; 42571 }, function (t, e, r) { 42572 42573 var n = function (t) { 42574 switch (typeof t) { 42575 case "string": 42576 return t; 42577 42578 case "boolean": 42579 return t ? "true" : "false"; 42580 42581 case "number": 42582 return isFinite(t) ? t : ""; 42583 42584 default: 42585 return ""; 42586 } 42587 }; 42588 42589 t.exports = function (t, e, r, s) { 42590 return e = e || "&", r = r || "=", null === t && (t = void 0), "object" == typeof t ? o(a(t), function (a) { 42591 var s = encodeURIComponent(n(a)) + r; 42592 return i(t[a]) ? o(t[a], function (t) { 42593 return s + encodeURIComponent(n(t)); 42594 }).join(e) : s + encodeURIComponent(n(t[a])); 42595 }).join(e) : s ? encodeURIComponent(n(s)) + r + encodeURIComponent(n(t)) : ""; 42596 }; 42597 42598 var i = Array.isArray || function (t) { 42599 return "[object Array]" === Object.prototype.toString.call(t); 42600 }; 42601 42602 function o(t, e) { 42603 if (t.map) return t.map(e); 42604 42605 for (var r = [], n = 0; n < t.length; n++) r.push(e(t[n], n)); 42606 42607 return r; 42608 } 42609 42610 var a = Object.keys || function (t) { 42611 var e = []; 42612 42613 for (var r in t) Object.prototype.hasOwnProperty.call(t, r) && e.push(r); 42614 42615 return e; 42616 }; 42617 }, function (t, e, r) { 42618 42619 (function (e) { 42620 var n = r(1), 42621 i = n(r(30)), 42622 o = n(r(159)), 42623 a = n(r(37)), 42624 s = n(r(31)), 42625 u = n(r(7)), 42626 f = n(r(10)), 42627 c = r(427), 42628 l = r(428), 42629 h = function () { 42630 function t(e) { 42631 var r = this; 42632 (0, u.default)(this, t), this.position = 0, this.url = e, this.cache = new l({ 42633 fetch: function (t, e) { 42634 return r._fetch(t, e); 42635 } 42636 }); 42637 } 42638 42639 var r, n, h; 42640 return (0, f.default)(t, [{ 42641 key: "_fetch", 42642 value: (h = (0, s.default)(i.default.mark(function t(r, n) { 42643 var s, u, f, l, h, d; 42644 return i.default.wrap(function (t) { 42645 for (;;) switch (t.prev = t.next) { 42646 case 0: 42647 return u = {}, n < 1 / 0 ? u.range = (0, a.default)(f = "bytes=".concat(r, "-")).call(f, r + n) : n === 1 / 0 && 0 !== r && (u.range = "bytes=".concat(r, "-")), t.next = 4, c(this.url, { 42648 method: "GET", 42649 headers: u, 42650 redirect: "follow", 42651 mode: "cors" 42652 }); 42653 42654 case 4: 42655 if ((200 !== (l = t.sent).status || 0 !== r) && 206 !== l.status) { 42656 t.next = 14; 42657 break; 42658 } 42659 42660 return t.t0 = e, t.next = 9, l.arrayBuffer(); 42661 42662 case 9: 42663 return t.t1 = t.sent, h = t.t0.from.call(t.t0, t.t1), (d = /\/(\d+)$/.exec(l.headers.get("content-range")))[1] && (this._stat = { 42664 size: (0, o.default)(d[1], 10) 42665 }), t.abrupt("return", h); 42666 42667 case 14: 42668 throw new Error((0, a.default)(s = "HTTP ".concat(l.status, " fetching ")).call(s, this.url)); 42669 42670 case 15: 42671 case "end": 42672 return t.stop(); 42673 } 42674 }, t, this); 42675 })), function (t, e) { 42676 return h.apply(this, arguments); 42677 }) 42678 }, { 42679 key: "read", 42680 value: function (t) { 42681 var e = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : 0, 42682 r = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : 1 / 0, 42683 n = arguments.length > 3 && void 0 !== arguments[3] ? arguments[3] : 0, 42684 i = n; 42685 return null === i && (i = this.position, this.position += r), this.cache.get(t, e, r, n); 42686 } 42687 }, { 42688 key: "readFile", 42689 value: (n = (0, s.default)(i.default.mark(function t() { 42690 var r; 42691 return i.default.wrap(function (t) { 42692 for (;;) switch (t.prev = t.next) { 42693 case 0: 42694 return t.next = 2, c(this.url, { 42695 method: "GET", 42696 redirect: "follow", 42697 mode: "cors" 42698 }); 42699 42700 case 2: 42701 return r = t.sent, t.t0 = e, t.next = 6, r.arrayBuffer(); 42702 42703 case 6: 42704 return t.t1 = t.sent, t.abrupt("return", t.t0.from.call(t.t0, t.t1)); 42705 42706 case 8: 42707 case "end": 42708 return t.stop(); 42709 } 42710 }, t, this); 42711 })), function () { 42712 return n.apply(this, arguments); 42713 }) 42714 }, { 42715 key: "stat", 42716 value: (r = (0, s.default)(i.default.mark(function t() { 42717 var r; 42718 return i.default.wrap(function (t) { 42719 for (;;) switch (t.prev = t.next) { 42720 case 0: 42721 if (this._stat) { 42722 t.next = 6; 42723 break; 42724 } 42725 42726 return r = e.allocUnsafe(10), t.next = 4, this.read(r, 0, 10, 0); 42727 42728 case 4: 42729 if (this._stat) { 42730 t.next = 6; 42731 break; 42732 } 42733 42734 throw new Error("unable to determine size of file at ".concat(this.url)); 42735 42736 case 6: 42737 return t.abrupt("return", this._stat); 42738 42739 case 7: 42740 case "end": 42741 return t.stop(); 42742 } 42743 }, t, this); 42744 })), function () { 42745 return r.apply(this, arguments); 42746 }) 42747 }]), t; 42748 }(); 42749 42750 t.exports = h; 42751 }).call(this, r(19).Buffer); 42752 }, function (t, e) { 42753 var r = function (t) { 42754 function e() { 42755 this.fetch = !1, this.DOMException = t.DOMException; 42756 } 42757 42758 return e.prototype = t, new e(); 42759 }("undefined" != typeof self ? self : this); 42760 42761 !function (t) { 42762 !function (e) { 42763 var r = { 42764 searchParams: "URLSearchParams" in t, 42765 iterable: "Symbol" in t && "iterator" in Symbol, 42766 blob: "FileReader" in t && "Blob" in t && function () { 42767 try { 42768 return new Blob(), !0; 42769 } catch (t) { 42770 return !1; 42771 } 42772 }(), 42773 formData: "FormData" in t, 42774 arrayBuffer: "ArrayBuffer" in t 42775 }; 42776 if (r.arrayBuffer) var n = ["[object Int8Array]", "[object Uint8Array]", "[object Uint8ClampedArray]", "[object Int16Array]", "[object Uint16Array]", "[object Int32Array]", "[object Uint32Array]", "[object Float32Array]", "[object Float64Array
42776]"], 42777 i = ArrayBuffer.isView || function (t) { 42778 return t && n.indexOf(Object.prototype.toString.call(t)) > -1; 42779 }; 42780 42781 function o(t) { 42782 if ("string" != typeof t && (t = String(t)), /[^a-z0-9\-#$%&'*+.^_`|~]/i.test(t)) throw new TypeError("Invalid character in header field name"); 42783 return t.toLowerCase(); 42784 } 42785 42786 function a(t) { 42787 return "string" != typeof t && (t = String(t)), t; 42788 } 42789 42790 function s(t) { 42791 var e = { 42792 next: function () { 42793 var e = t.shift(); 42794 return { 42795 done: void 0 === e, 42796 value: e 42797 }; 42798 } 42799 }; 42800 return r.iterable && (e[Symbol.iterator] = function () { 42801 return e; 42802 }), e; 42803 } 42804 42805 function u(t) { 42806 this.map = {}, t instanceof u ? t.forEach(function (t, e) { 42807 this.append(e, t); 42808 }, this) : Array.isArray(t) ? t.forEach(function (t) { 42809 this.append(t[0], t[1]); 42810 }, this) : t && Object.getOwnPropertyNames(t).forEach(function (e) { 42811 this.append(e, t[e]); 42812 }, this); 42813 } 42814 42815 function f(t) { 42816 if (t.bodyUsed) return Promise.reject(new TypeError("Already read")); 42817 t.bodyUsed = !0; 42818 } 42819 42820 function c(t) { 42821 return new Promise(function (e, r) { 42822 t.onload = function () { 42823 e(t.result); 42824 }, t.onerror = function () { 42825 r(t.error); 42826 }; 42827 }); 42828 } 42829 42830 function l(t) { 42831 var e = new FileReader(), 42832 r = c(e); 42833 return e.readAsArrayBuffer(t), r; 42834 } 42835 42836 function h(t) { 42837 if (t.slice) return t.slice(0); 42838 var e = new Uint8Array(t.byteLength); 42839 return e.set(new Uint8Array(t)), e.buffer; 42840 } 42841 42842 function d() { 42843 return this.bodyUsed = !1, this._initBody = function (t) { 42844 var e; 42845 this._bodyInit = t, t ? "string" == typeof t ? this._bodyText = t : r.blob && Blob.prototype.isPrototypeOf(t) ? this._bodyBlob = t : r.formData && FormData.prototype.isPrototypeOf(t) ? this._bodyFormData = t : r.searchParams && URLSearchParams.prototype.isPrototypeOf(t) ? this._bodyText = t.toString() : r.arrayBuffer && r.blob && (e = t) && DataView.prototype.isPrototypeOf(e) ? (this._bodyArrayBuffer = h(t.buffer), this._bodyInit = new Blob([this._bodyArrayBuffer])) : r.arrayBuffer && (ArrayBuffer.prototype.isPrototypeOf(t) || i(t)) ? this._bodyArrayBuffer = h(t) : this._bodyText = t = Object.prototype.toString.call(t) : this._bodyText = "", this.headers.get("content-type") || ("string" == typeof t ? this.headers.set("content-type", "text/plain;charset=UTF-8") : this._bodyBlob && this._bodyBlob.type ? this.headers.set("content-type", this._bodyBlob.type) : r.searchParams && URLSearchParams.prototype.isPrototypeOf(t) && this.headers.set("content-type", "application/x-www-form-urlencoded;charset=UTF-8")); 42846 }, r.blob && (this.blob = function () { 42847 var t = f(this); 42848 if (t) return t; 42849 if (this._bodyBlob) return Promise.resolve(this._bodyBlob); 42850 if (this._bodyArrayBuffer) return Promise.resolve(new Blob([this._bodyArrayBuffer])); 42851 if (this._bodyFormData) throw new Error("could not read FormData body as blob"); 42852 return Promise.resolve(new Blob([this._bodyText])); 42853 }, this.arrayBuffer = function () { 42854 return this._bodyArrayBuffer ? f(this) || Promise.resolve(this._bodyArrayBuffer) : this.blob().then(l); 42855 }), this.text = function () { 42856 var t, 42857 e, 42858 r, 42859 n = f(this); 42860 if (n) return n; 42861 if (this._bodyBlob) return t = this._bodyBlob, e = new FileReader(), r = c(e), e.readAsText(t), r; 42862 if (this._bodyArrayBuffer) return Promise.resolve(function (t) { 42863 for (var e = new Uint8Array(t), r = new Array(e.length), n = 0; n < e.length; n++) r[n] = String.fromCharCode(e[n]); 42864 42865 return r.join(""); 42866 }(this._bodyArrayBuffer)); 42867 if (this._bodyFormData) throw new Error("could not read FormData body as text"); 42868 return Promise.resolve(this._bodyText); 42869 }, r.formData && (this.formData = function () { 42870 return this.text().then(v); 42871 }), this.json = function () { 42872 return this.text().then(JSON.parse); 42873 }, this; 42874 } 42875 42876 u.prototype.append = function (t, e) { 42877 t = o(t), e = a(e); 42878 var r = this.map[t]; 42879 this.map[t] = r ? r + ", " + e : e; 42880 }, u.prototype.delete = function (t) { 42881 delete this.map[o(t)]; 42882 }, u.prototype.get = function (t) { 42883 return t = o(t), this.has(t) ? this.map[t] : null; 42884 }, u.prototype.has = function (t) { 42885 return this.map.hasOwnProperty(o(t)); 42886 }, u.prototype.set = function (t, e) { 42887 this.map[o(t)] = a(e); 42888 }, u.prototype.forEach = function (t, e) { 42889 for (var r in this.map) this.map.hasOwnProperty(r) && t.call(e, this.map[r], r, this); 42890 }, u.prototype.keys = function () { 42891 var t = []; 42892 return this.forEach(function (e, r) { 42893 t.push(r); 42894 }), s(t); 42895 }, u.prototype.values = function () { 42896 var t = []; 42897 return this.forEach(function (e) { 42898 t.push(e); 42899 }), s(t); 42900 }, u.prototype.entries = function () { 42901 var t = []; 42902 return this.forEach(function (e, r) { 42903 t.push([r, e]); 42904 }), s(t); 42905 }, r.iterable && (u.prototype[Symbol.iterator] = u.prototype.entries); 42906 var p = ["DELETE", "GET", "HEAD", "OPTIONS", "POST", "PUT"]; 42907 42908 function g(t, e) { 42909 var r, 42910 n, 42911 i = (e = e || {}).body; 42912 42913 if (t instanceof g) { 42914 if (t.bodyUsed) throw new TypeError("Already read"); 42915 this.url = t.url, this.credentials = t.credentials, e.headers || (this.headers = new u(t.headers)), this.method = t.method, this.mode = t.mode, this.signal = t.signal, i || null == t._bodyInit || (i = t._bodyInit, t.bodyUsed = !0); 42916 } else this.url = String(t); 42917 42918 if (this.credentials = e.credentials || this.credentials || "same-origin", !e.headers && this.headers || (this.headers = new u(e.headers)), this.method = (r = e.method || this.method || "GET", n = r.toUpperCase(), p.indexOf(n) > -1 ? n : r), this.mode = e.mode || this.mode || null, this.signal = e.signal || this.signal, this.referrer = null, ("GET" === this.method || "HEAD" === this.method) && i) throw new TypeError("Body not allowed for GET or HEAD requests"); 42919 42920 this._initBody(i); 42921 } 42922 42923 function v(t) { 42924 var e = new FormData(); 42925 return t.trim().split("&").forEach(function (t) { 42926 if (t) { 42927 var r = t.split("="), 42928 n = r.shift().replace(/\+/g, " "), 42929 i = r.join("=").replace(/\+/g, " "); 42930 e.append(decodeURIComponent(n), decodeURIComponent(i)); 42931 } 42932 }), e; 42933 } 42934 42935 function y(t, e) { 42936 e || (e = {}), this.type = "default", this.status = void 0 === e.status ? 200 : e.status, this.ok = this.status >= 200 && this.status < 300, this.statusText = "statusText" in e ? e.statusText : "OK", this.headers = new u(e.headers), this.url = e.url || "", this._initBody(t); 42937 } 42938 42939 g.prototype.clone = function () { 42940 return new g(this, { 42941 body: this._bodyInit 42942 }); 42943 }, d.call(g.prototype), d.call(y.prototype), y.prototype.clone = function () { 42944 return new y(this._bodyInit, { 42945 status: this.status, 42946 statusText: this.statusText, 42947 headers: new u(this.headers), 42948 url: this.url 42949 }); 42950 }, y.error = function () { 42951 var t = new y(null, { 42952 status: 0, 42953 statusText: "" 42954 }); 42955 return t.type = "error", t; 42956 }; 42957 var m = [301, 302, 303, 307, 308]; 42958 y.redirect = function (t, e) { 42959 if (-1 === m.indexOf(e)) throw new RangeError("Invalid status code"); 42960 return new y(null, { 42961 status: e, 42962 headers: { 42963 location: t 42964 } 42965 }); 42966 }, e.DOMException = t.DOMException; 42967 42968 try { 42969 new e.DOMException(); 42970 } catch (t) { 42971 e.DOMException = function (t, e) { 42972 this.message = t, this.name = e; 42973 var r = Error(t); 42974 this.stack = r.stack; 42975 }, e.DOMException.prototype = Object.create(Error.prototype), e.DOMException.prototype.constructor = e.DOMException; 42976 } 42977 42978 function b(t, n) { 42979 return new Promise(function (i, o) { 42980 var a = new g(t, n); 42981 if (a.signal && a.signal.aborted) return o(new e.DOMException("Aborted", "AbortError")); 42982 var s = new XMLHttpRequest(); 42983 42984 function f() { 42985 s.abort(); 42986 } 42987 42988 s.onload = function () { 42989 var t, 42990 e, 42991 r = { 42992 status: s.status, 42993 statusText: s.statusText, 42994 headers: (t = s.getAllResponseHeaders() || "", e = new u(), t.replace(/\r?\n[\t ]+/g, " ").split(/\r?\n/).forEac
42994h(function (t) { 42995 var r = t.split(":"), 42996 n = r.shift().trim(); 42997 42998 if (n) { 42999 var i = r.join(":").trim(); 43000 e.append(n, i); 43001 } 43002 }), e) 43003 }; 43004 r.url = "responseURL" in s ? s.responseURL : r.headers.get("X-Request-URL"); 43005 var n = "response" in s ? s.response : s.responseText; 43006 i(new y(n, r)); 43007 }, s.onerror = function () { 43008 o(new TypeError("Network request failed")); 43009 }, s.ontimeout = function () { 43010 o(new TypeError("Network request failed")); 43011 }, s.onabort = function () { 43012 o(new e.DOMException("Aborted", "AbortError")); 43013 }, s.open(a.method, a.url, !0), "include" === a.credentials ? s.withCredentials = !0 : "omit" === a.credentials && (s.withCredentials = !1), "responseType" in s && r.blob && (s.responseType = "blob"), a.headers.forEach(function (t, e) { 43014 s.setRequestHeader(e, t); 43015 }), a.signal && (a.signal.addEventListener("abort", f), s.onreadystatechange = function () { 43016 4 === s.readyState && a.signal.removeEventListener("abort", f); 43017 }), s.send(void 0 === a._bodyInit ? null : a._bodyInit); 43018 }); 43019 } 43020 43021 b.polyfill = !0, t.fetch || (t.fetch = b, t.Headers = u, t.Request = g, t.Response = y), e.Headers = u, e.Request = g, e.Response = y, e.fetch = b; 43022 }({}); 43023 }(r), delete r.fetch.polyfill, (e = r.fetch).default = r.fetch, e.fetch = r.fetch, e.Headers = r.Headers, e.Request = r.Request, e.Response = r.Response, t.exports = e; 43024 }, function (t, e, r) { 43025 43026 var n = r(1), 43027 i = n(r(30)), 43028 o = n(r(16)), 43029 a = n(r(76)), 43030 s = n(r(31)), 43031 u = n(r(7)), 43032 f = n(r(10)), 43033 c = r(94), 43034 l = function () { 43035 function t(e) { 43036 var r = e.fetch, 43037 n = e.size, 43038 i = void 0 === n ? 1e7 : n, 43039 o = e.chunkSize, 43040 a = void 0 === o ? 32768 : o; 43041 if ((0, u.default)(this, t), !r) throw new Error("fetch function required"); 43042 this.fetch = r, this.chunkSize = a, this.lruCache = new c({ 43043 maxSize: Math.floor(i / a) 43044 }); 43045 } 43046 43047 var e; 43048 return (0, f.default)(t, [{ 43049 key: "get", 43050 value: (e = (0, s.default)(i.default.mark(function t(e, r, n, s) { 43051 var u, 43052 f, 43053 c, 43054 l, 43055 h, 43056 d, 43057 p, 43058 g = this; 43059 return i.default.wrap(function (t) { 43060 for (;;) switch (t.prev = t.next) { 43061 case 0: 43062 if (!(e.length < r + n)) { 43063 t.next = 2; 43064 break; 43065 } 43066 43067 throw new Error("output buffer not big enough for request"); 43068 43069 case 2: 43070 for (u = Math.floor(s / this.chunkSize), f = Math.floor((s + n) / this.chunkSize), c = new Array(f - u + 1), l = function (t) { 43071 c[t - u] = g._getChunk(t).then(function (e) { 43072 return { 43073 data: e, 43074 chunkNumber: t 43075 }; 43076 }); 43077 }, h = u; h <= f; h += 1) l(h); 43078 43079 return t.next = 9, a.default.all(c); 43080 43081 case 9: 43082 d = t.sent, p = s - d[0].chunkNumber * this.chunkSize, (0, o.default)(d).call(d, function (t) { 43083 var i = t.data, 43084 o = t.chunkNumber, 43085 a = o * g.chunkSize, 43086 c = 0, 43087 l = g.chunkSize, 43088 h = r + (o - u) * g.chunkSize - p; 43089 o === u && (h = r, c = p), o === f && (l = s + n - a), i.copy(e, h, c, l); 43090 }); 43091 43092 case 12: 43093 case "end": 43094 return t.stop(); 43095 } 43096 }, t, this); 43097 })), function (t, r, n, i) { 43098 return e.apply(this, arguments); 43099 }) 43100 }, { 43101 key: "_getChunk", 43102 value: function (t) { 43103 var e = this.lruCache.get(t); 43104 if (e) return e; 43105 var r = this.fetch(t * this.chunkSize, this.chunkSize); 43106 return this.lruCache.set(t, r), r; 43107 } 43108 }]), t; 43109 }(); 43110 43111 t.exports = l; 43112 }, function (t, e, r) { 43113 43114 var n = r(1), 43115 i = n(r(30)), 43116 o = n(r(31)), 43117 a = n(r(7)), 43118 s = n(r(10)), 43119 u = (r(161).promisify, null), 43120 f = u, 43121 c = function () { 43122 function t(e) { 43123 (0, a.default)(this, t), this.position = 0, this.filename = e, this.fd = f(this.filename, "r"); 43124 } 43125 43126 var e, r, n; 43127 return (0, s.default)(t, [{ 43128 key: "read", 43129 value: (n = (0, o.default)(i.default.mark(function t(e) { 43130 var r, 43131 n, 43132 o, 43133 a = arguments; 43134 return i.default.wrap(function (t) { 43135 for (;;) switch (t.prev = t.next) { 43136 case 0: 43137 return r = a.length > 1 && void 0 !== a[1] ? a[1] : 0, n = a.length > 2 ? a[2] : void 0, null === (o = a.length >
43137 3 ? a[3] : void 0) && (this.position, this.position += n), t.t0 = null, t.next = 8, this.fd; 43138 43139 case 8: 43140 return t.t1 = t.sent, t.t2 = e, t.t3 = r, t.t4 = n, t.t5 = o, t.abrupt("return", (0, t.t0)(t.t1, t.t2, t.t3, t.t4, t.t5)); 43141 43142 case 14: 43143 case "end": 43144 return t.stop(); 43145 } 43146 }, t, this); 43147 })), function (t) { 43148 return n.apply(this, arguments); 43149 }) 43150 }, { 43151 key: "readFile", 43152 value: (r = (0, o.default)(i.default.mark(function t() { 43153 return i.default.wrap(function (t) { 43154 for (;;) switch (t.prev = t.next) { 43155 case 0: 43156 return t.t0 = null, t.next = 3, this.fd; 43157 43158 case 3: 43159 return t.t1 = t.sent, t.abrupt("return", (0, t.t0)(t.t1)); 43160 43161 case 5: 43162 case "end": 43163 return t.stop(); 43164 } 43165 }, t, this); 43166 })), function () { 43167 return r.apply(this, arguments); 43168 }) 43169 }, { 43170 key: "stat", 43171 value: (e = (0, o.default)(i.default.mark(function t() { 43172 return i.default.wrap(function (t) { 43173 for (;;) switch (t.prev = t.next) { 43174 case 0: 43175 if (this._stat) { 43176 t.next = 8; 43177 break; 43178 } 43179 43180 return t.t0 = null, t.next = 4, this.fd; 43181 43182 case 4: 43183 return t.t1 = t.sent, t.next = 7, (0, t.t0)(t.t1); 43184 43185 case 7: 43186 this._stat = t.sent; 43187 43188 case 8: 43189 return t.abrupt("return", this._stat); 43190 43191 case 9: 43192 case "end": 43193 return t.stop(); 43194 } 43195 }, t, this); 43196 })), function () { 43197 return e.apply(this, arguments); 43198 }) 43199 }]), t; 43200 }(); 43201 43202 t.exports = c; 43203 }, function (t, e, r) { 43204 43205 var n = r(1), 43206 i = n(r(48)), 43207 o = n(r(77)), 43208 a = n(r(101)), 43209 s = n(r(431)), 43210 u = n(r(16)); 43211 t.exports = { 43212 parseHeaderText: function (t) { 43213 var e = t.split(/\r?\n/), 43214 r = []; 43215 return (0, u.default)(e).call(e, function (t) { 43216 var e = t.split(/\t/), 43217 n = (0, s.default)(e), 43218 u = n[0], 43219 f = (0, a.default)(n).call(n, 1), 43220 c = (0, o.default)(f).call(f, function (t) { 43221 var e = t.split(":", 2), 43222 r = (0, i.default)(e, 2); 43223 return { 43224 tag: r[0], 43225 value: r[1] 43226 }; 43227 }); 43228 u && r.push({ 43229 tag: u.substr(1), 43230 data: c 43231 }); 43232 }), r; 43233 } 43234 }; 43235 }, function (t, e, r) { 43236 var n = r(157), 43237 i = r(152), 43238 o = r(158); 43239 43240 t.exports = function (t) { 43241 return n(t) || i(t) || o(); 43242 }; 43243 }, function (t, e, r) { 43244 43245 var n = r(1), 43246 i = n(r(30)), 43247 o = n(r(103)), 43248 a = n(r(150)), 43249 s = n(r(48)), 43250 u = n(r(102)), 43251 f = n(r(16)), 43252 c = n(r(59)), 43253 l = n(r(76)), 43254 h = n(r(37)), 43255 d = n(r(77)), 43256 p = n(r(433)), 43257 g = n(r(31)), 43258 v = n(r(7)), 43259 y = n(r(10)), 43260 m = r(9), 43261 b = m.CramUnimplementedError, 43262 _ = m.CramSizeLimitError, 43263 w = r(104), 43264 x = function () { 43265 function t(e) { 43266 if ((0, v.default)(this, t), e.cram ? this.cram = e.cram : this.cram = new w({ 43267 url: e.cramUrl, 43268 path: e.cramPath, 43269 filehandle: e.cramFilehandle, 43270 seqFetch: e.seqFetch, 43271 checkSequenceMD5: e.checkSequenceMD5, 43272 cacheSize: e.cacheSize 43273 }), !(this.cram instanceof w)) throw new Error("invalid arguments: no cramfile"); 43274 if (this.index = e.index, !this.index.getEntriesForRange) throw new Error("invalid arguments: not an index"); 43275 this.fetchSizeLimit = e.fetchSizeLimit || 3e6; 43276 } 43277 43278 var e; 43279 return (0, y.default)(t, [{ 43280 key: "getRecordsForRange", 43281 value: (e = (0, g.default)(i.default.mark(function t(e, r, n) { 43282 var g, 43283 v, 43284 y, 43285 m, 43286 w, 43287 x, 43288 E, 43289 S, 43290 k, 43291 A, 43292 C, 43293 T, 43294 R, 43295 O, 43296 I, 43297 L, 43298 B, 43299 P, 43300 F, 43301 N, 43302 M, 43303 j, 43304 z, 43305 U, 43306 D, 43307 q, 43308 Z, 43309 H, 43310 V, 43311 G, 43312 Y, 43313 W, 43314 K, 43315 Q, 43316 X, 43317 $ = this, 43318 J = arguments; 43319 return i.default.wrap(function (t) { 43320 for (;;) switch (t.prev = t.next) { 43321 case 0: 43322 if ((x = J.length > 3 && void 0 !== J[3] ? J[3] : {}).viewAsPairs = x.viewAsPairs || !1, x.pairAcrossChr = x.pairAcrossChr || !1, x.maxInsertSize = x.maxInsertSize || 2e5, "string" != typeof e) { 43323 t.next = 6; 43324 break; 43325 } 43326 43327 throw new b("string sequence names not yet supported"); 43328 43329 case 6: 43330 return E = e, t.next = 9, this.index.getEntriesForRange(E, r, n); 43331 43332 case 9: 43333 if (S = t.sent, !((k = (0, p.default)(g = (0, d.default)(S).call(S, function (t) { 43334 return t.sliceBytes; 43335 })).call(g, function (t, e) { 43336 return t + e; 43337 }, 0)) > this.fetchSizeLimit)) { 43338 t.next = 13; 43339 break; 43340 } 43341 43342 throw new _((0, h.default)(v = "data size of ".concat(k.toLocaleStr
43342ing(), " bytes exceeded fetch size limit of ")).call(v, this.fetchSizeLimit.toLocaleString(), " bytes")); 43343 43344 case 13: 43345 return A = function (t) { 43346 return t.sequenceId === e && t.alignmentStart <= n && t.alignmentStart + t.lengthOnRef - 1 >= r; 43347 }, t.next = 16, l.default.all((0, d.default)(S).call(S, function (t) { 43348 return $.getRecordsInSlice(t, A); 43349 })); 43350 43351 case 16: 43352 if (C = t.sent, T = (m = (0, h.default)(y = Array.prototype)).call.apply(m, (0, h.default)(w = [y]).call(w, (0, c.default)(C))), !x.viewAsPairs) { 43353 t.next = 42; 43354 break; 43355 } 43356 43357 for (L = {}, B = {}, P = 0; P < T.length; P += 1) F = T[P].readName, N = T[P].uniqueId, L[F] || (L[F] = 0), L[F] += 1, B[N] = 1; 43358 43359 for (M = {}, (0, f.default)(R = (0, u.default)(L)).call(R, function (t) { 43360 var e = (0, s.default)(t, 2), 43361 r = e[0]; 43362 1 === e[1] && (M[r] = !0); 43363 }), j = [], z = 0; z < T.length; z += 1) U = T[z].readName, M[U] && T[z].mate && (T[z].mate.sequenceId === E || x.pairAcrossChr) && Math.abs(T[z].alignmentStart - T[z].mate.alignmentStart) < x.maxInsertSize && (D = this.index.getEntriesForRange(T[z].mate.sequenceId, T[z].mate.alignmentStart, T[z].mate.alignmentStart + 1), j.push(D)); 43364 43365 return t.next = 28, l.default.all(j); 43366 43367 case 28: 43368 for (q = t.sent, Z = [], H = 0; H < q.length; H += 1) (V = Z).push.apply(V, (0, c.default)(q[H])); 43369 43370 if (Z = (0, a.default)(O = (0, o.default)(Z).call(Z, function (t, e) { 43371 return t.toString().localeCompare(e.toString()); 43372 })).call(O, function (t, e, r) { 43373 return !e || t.toString() !== r[e - 1].toString(); 43374 }), G = [], Y = [], !((W = (0, p.default)(I = (0, d.default)(Z).call(Z, function (t) { 43375 return t.sliceBytes; 43376 })).call(I, function (t, e) { 43377 return t + e; 43378 }, 0)) > this.fetchSizeLimit)) { 43379 t.next = 37; 43380 break; 43381 } 43382 43383 throw new Error((0, h.default)(K = "mate data size of ".concat(W.toLocaleString(), " bytes exceeded fetch size limit of ")).call(K, this.fetchSizeLimit.toLocaleString(), " bytes")); 43384 43385 case 37: 43386 return (0, f.default)(Z).call(Z, function (t) { 43387 var e = $.cram.featureCache.get(t.toString()); 43388 e || (e = $.getRecordsInSlice(t, function () { 43389 return !0; 43390 }), $.cram.featureCache.set(t.toString(), e)), G.push(e); 43391 var r = e.then(function (t) { 43392 for (var e = [], r = 0; r < t.length; r += 1) { 43393 var n = t[r]; 43394 M[n.readName] && !B[n.uniqueId] && e.push(n); 43395 } 43396 43397 return e; 43398 }); 43399 Y.push(r); 43400 }), t.next = 40, l.default.all(Y); 43401 43402 case 40: 43403 (Q = t.sent).length && (X = (0, p.default)(Q).c
43403all(Q, function (t, e) { 43404 return (0, h.default)(t).call(t, e); 43405 }), T = (0, h.default)(T).call(T, X)); 43406 43407 case 42: 43408 return t.abrupt("return", T); 43409 43410 case 43: 43411 case "end": 43412 return t.stop(); 43413 } 43414 }, t, this); 43415 })), function (t, r, n) { 43416 return e.apply(this, arguments); 43417 }) 43418 }, { 43419 key: "getRecordsInSlice", 43420 value: function (t, e) { 43421 var r = t.containerStart, 43422 n = t.sliceStart, 43423 i = t.sliceBytes; 43424 return this.cram.getContainerAtPosition(r).getSlice(n, i).getRecords(e); 43425 } 43426 }, { 43427 key: "hasDataForReferenceSequence", 43428 value: function (t) { 43429 return this.index.hasDataForReferenceSequence(t); 43430 } 43431 }]), t; 43432 }(); 43433 43434 t.exports = x; 43435 }, function (t, e, r) { 43436 t.exports = r(434); 43437 }, function (t, e, r) { 43438 t.exports = r(435); 43439 }, function (t, e, r) { 43440 var n = r(436), 43441 i = Array.prototype; 43442 43443 t.exports = function (t) { 43444 var e = t.reduce; 43445 return t === i || t instanceof Array && e === i.reduce ? n : e; 43446 }; 43447 }, function (t, e, r) { 43448 r(437); 43449 var n = r(18); 43450 t.exports = n("Array").reduce; 43451 }, function (t, e, r) { 43452 43453 var n = r(0), 43454 i = r(438).left; 43455 n({ 43456 target: "Array", 43457 proto: !0, 43458 forced: r(54)("reduce") 43459 }, { 43460 reduce: function (t) { 43461 return i(this, t, arguments.length, arguments.length > 1 ? arguments[1] : void 0); 43462 } 43463 }); 43464 }, function (t, e, r) { 43465 var n = r(5), 43466 i = r(22), 43467 o = r(60), 43468 a = r(29), 43469 s = function (t) { 43470 return function (e, r, s, u) { 43471 n(r); 43472 var f = i(e), 43473 c = o(f), 43474 l = a(f.length), 43475 h = t ? l - 1 : 0, 43476 d = t ? -1 : 1; 43477 if (s < 2) for (;;) { 43478 if (h in c) { 43479 u = c[h], h += d; 43480 break; 43481 } 43482 43483 if (h += d, t ? h < 0 : l <= h) throw TypeError("Reduce of empty array with no initial value"); 43484 } 43485 43486 for (; t ? h >= 0 : l > h; h += d) h in c && (u = r(u, c[h], h, f)); 43487 43488 return u; 43489 }; 43490 }; 43491 43492 t.exports = { 43493 left: s(!1), 43494 right: s(!0) 43495 }; 43496 }, function (t, e, r) { 43497 43498 var n = r(1), 43499 i = n(r(30)), 43500 o = n(r(31)), 43501 a = n(r(103)), 43502 s = n(r(102)), 43503 u = n(r(16)), 43504 f = n(r(154)), 43505 c = n(r(440)), 43506 l = n(r(48)), 43507 h = n(r(442)), 43508 d = n(r(37)), 43509 p = n(r(75)), 43510 g = n(r(7)), 43511 v = n(r(10)), 43512 y = r(447).default, 43513 m = r(94), 43514 b = (0, r(161).promisify)(r(126).gunzip), 43515 _ = r(160).open, 43516 w = r(9).CramMalformedError, 43517 x = function () { 43518 function t(e) { 43519 (0, g.default)(this, t), (0, p.default)(this, e); 43520 } 43521 43522 return (0, v.default)(t, [{ 43523 key: "toString", 43524 value: function () { 43525 var t, e, r, n; 43526 return (0, d.default)(t = (0, d.default)(e = (0, d.default)(r = (0, d.default)(n = "".concat(this.start, ":")).call(n, this.span, ":")).call(r, this.containerStart, ":")).call(e, this.sliceStart, ":")).call(t, this.sliceBytes); 43527 } 43528 }]), t; 43529 }(); 43530 43531 function E(t, e) { 43532 if ((0, h.default)(e).call(e, function (t) { 43533 return void 0 === t; 43534 })) throw new w("invalid .crai index file"); 43535 var r = (0, l.default)(e, 6), 43536 n = r[0], 43537 i = r[1], 43538 o = r[2], 43539 a = r[3], 43540 s = r[4], 43541 u = r[5]; 43542 t[n] || (t[n] = []), t[n].push(new x({ 43543 start: i, 43544 span: o, 43545 containerStart: a, 43546 sliceStart: s, 43547 sliceBytes: u 43548 })); 43549 } 43550 43551 var S = function () { 43552 function t(e) { 43553 var r, 43554 n = this; 43555 (0, g.default)(this, t); 43556 43557 var i = _(e.url, e.path, e.filehandle); 43558 43559 this._parseCache = new y({ 43560 cache: new m({ 43561 maxSize: 1 43562 }), 43563 fill: function (t, e) { 43564 return n.parseIndex({ 43565 signal: e 43566 }); 43567 } 43568 }), this.readFile = (0, c.default)(r = i.readFile).call(r, i); 43569 } 43570 43571 var e, r; 43572 return (0, v.default)(t, [{ 43573 key: "parseIndex", 43574 value: function () { 43575 var t = {}; 43576 return this.readFile().then(function (t) {
43577 return 31 === t[0] && 139 === t[1] ? b(t) : t; 43578 }).then(function (e) { 43579 var r; 43580 if (e.length > 4 && 21578050 === e.readUInt32LE(0)) throw new w("invalid .crai index file. note: file appears to be a .bai index. this is technically legal but please open a github issue if you need support"); 43581 43582 for (var n = [], i = "", o = 0; o < e.length; o += 1) { 43583 var c = e[o]; 43584 if (c >= 48 && c <= 57 || !i && 45 === c) i += String.fromCharCode(c);else if (9 === c) n.push((0, f.default)(i, 10)), i = "";else if (10 === c) n.push((0, f.default)(i, 10)), i = "", E(t, n), n = [];else if (13 !== c && 32 !== c) throw new w("invalid .crai index file"); 43585 } 43586 43587 return i && n.push((0, f.default)(i, 10)), 6 === n.length && E(t, n), (0, u.default)(r = (0, s.default)(t)).call(r, function (e) { 43588 var r = (0, l.default)(e, 2), 43589 n = r[0], 43590 i = r[1]; 43591 t[n] = (0, a.default)(i).call(i, function (t, e) { 43592 return t.start - e.start || t.span - e.span; 43593 }); 43594 }), t; 43595 }); 43596 } 43597 }, { 43598 key: "getIndex", 43599 value: function () { 43600 var t = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {}; 43601 return this._parseCache.get("index", null, t.signal); 43602 } 43603 }, { 43604 key: "hasDataForReferenceSequence", 43605 value: (r = (0, o.default)(i.default.mark(function t(e) { 43606 return i.default.wrap(function (t) { 43607 for (;;) switch (t.prev = t.next) { 43608 case 0: 43609 return t.next = 2, this.getIndex(); 43610 43611 case 2: 43612 return t.t0 = e, t.abrupt("return", !!t.sent[t.t0]); 43613 43614 case 4: 43615 case "end": 43616 return t.stop(); 43617 } 43618 }, t, this); 43619 })), function (t) { 43620 return r.apply(this, arguments); 43621 }) 43622 }, { 43623 key: "getEntriesForRange", 43624 value: (e = (0, o.default)(i.default.mark(function t(e, r, n) { 43625 var o, a, s, u; 43626 return i.default.wrap(function (t) { 43627 for (;;) switch (t.prev = t.next) { 43628 case 0: 43629 return t.next = 2, this.getIndex(); 43630 43631 case 2: 43632 if (t.t0 = e, o = t.sent[t.t0]) { 43633 t.next = 6; 43634 break; 43635 } 43636 43637 return t.abrupt("return", []); 43638 43639 case 6: 43640 for (a = function (t) { 43641 var e = t.start, 43642 i = t.start + t.span; 43643 return e >= n ? -1 : i <= r ? 1 : 0; 43644 }, s = [], u = 0; u < o.length; u += 1) 0 === a(o[u]) && s.push(o[u]); 43645 43646 return t.abrupt("return", s); 43647 43648 case 10: 43649 case "end": 43650 return t.stop(); 43651 } 43652 }, t, this); 43653 })), function (t, r, n) { 43654 return e.apply(this, arguments); 43655 }) 43656 }]), t; 43657 }(); 43658 43659 t.exports = S; 43660 }, function (t, e, r) { 43661 t.exports = r(441); 43662 }, function (t, e, r) { 43663 t.exports = r(144); 43664 }, function (t, e, r) { 43665 t.exports = r(443); 43666 }, function (t, e, r) { 43667 t.exports = r(444); 43668 }, function (t, e, r) { 43669 var n = r(445), 43670 i = Array.prototype; 43671 43672 t.exports = function (t) { 43673 var e = t.some; 43674 return t === i || t instanceof Array && e === i.some ? n : e; 43675 }; 43676 }, function (t, e, r) { 43677 r(446); 43678 var n = r(18); 43679 t.exports = n("Array").some; 43680 }, function (t, e, r) { 43681 43682 var n = r(0), 43683 i = r(45).some; 43684 n({ 43685 target: "Array", 43686 proto: !0, 43687 forced: r(54)("some") 43688 }, { 43689 some: function (t) { 43690 return i(this, t, arguments.length > 1 ? arguments[1] : void 0); 43691 } 43692 }); 43693 }, function (t, e, r) { 43694 43695 var n = this && this.__importDefault || function (t) { 43696 return t && t.__esModule ? t : { 43697 default: t 43698 }; 43699 }; 43700 43701 Object.defineProperty(e, "__esModule", { 43702 value: !0 43703 }); 43704 var i = n(r(448)); 43705 e.default = i.default; 43706 }, function (t, e, r) { 43707 43708 var n = this && this.__importDefault || function (t) { 43709 return t && t.__esModule ? t : { 43710 default: t 43711 }; 43712 }; 43713 43714 Object.defineProperty(e, "__esModule", { 43715 value: !0 43716 }); 43717 43718 var i = r(162), 43719 o = n(r(450)), 43720 a = function () { 43721 function t(t) { 43722 var e = t.fill, 43723 r = t.cache; 43724 if ("function" != typeof e) throw new TypeError("must pass a fill function"); 43725 if ("object" != typeof r) throw new TypeError("must pass a cache object"); 43726 if ("function" != typeof r.get || "function" != typeof r.set || "function" != typeof r.delete) throw new TypeError("cache must implement get(key), set(key, val), and and delete(key)"); 43727 this.cache = r, this.fillCallback = e; 43728 } 43729 43730 return t.isAbortException = function (t) { 43731 return "AbortError" === t.name || "ERR_ABORTED" === t.code || "AbortError: aborted" === t.message || "Error: aborted" === t.message; 43732 }, t.prototype.evict = function (t, e) { 43733 this.cache.get(t) === e && this.cache.delete(t); 43734 }, t.prototype.fill = function (t, e, r) { 43735 var n = this, 43736 i = new o.default(), 43737 a = { 43738 aborter: i, 43739 promise: this.fillCallback(e, i.signal), 43740 settled: !1, 43741 43742 get aborted() { 43743 return this.aborter.signal.aborted; 43744 } 43745 43746 }; 43747 a.aborter.addSignal(r), a.aborter.signal.addEventListener("abort", function () { 43748 n.evict(t, a); 43749 }), a.promise.then(function () { 43750 a.settled = !0; 43751 }, function (e) { 43752 a.settled = !0, n.evict(t, a); 43753 }).catch(function (t) { 43754 throw console.error(t), t; 43755 }), this.cache.set(t, a); 43756 }, t.checkSinglePromise = function (t, e) { 43757 function r() { 43758 if (e && e.aborted) throw Object.assign(new Error("aborted"), { 43759 code: "ERR_ABORTED" 43760 }); 43761 } 43762 43763 return t.then(function (t) { 43764 return r(), t; 43765 }, function (t) { 43766 throw r(), t; 43767 }); 43768 }, t.prototype.has = function (t) { 43769 return this.cache.has(t); 43770 }, t.prototype.get = function (e, r, n) { 43771 if (!n && r instanceof i.AbortSignal) throw new TypeError("second get argument appears to be an AbortSignal, perhaps y
43771ou meant to pass `null` for the fill data?"); 43772 var o = this.cache.get(e); 43773 return o ? o.aborted ? (this.evict(e, o), this.get(e, r, n)) : o.settled ? o.promise : (o.aborter.addSignal(n), t.checkSinglePromise(o.promise, n)) : (this.fill(e, r, n), t.checkSinglePromise(this.cache.get(e).promise, n)); 43774 }, t.prototype.delete = function (t) { 43775 var e = this.cache.get(t); 43776 e && (e.settled || e.aborter.abort(), this.cache.delete(t)); 43777 }, t.prototype.clear = function () { 43778 for (var t = this.cache.keys(), e = 0, r = t.next(); !r.done; r = t.next()) this.delete(r.value), e += 1; 43779 43780 return e; 43781 }, t; 43782 }(); 43783 43784 e.default = a; 43785 }, function (t, e, r) { 43786 43787 function n(t, e) { 43788 if (!(t instanceof e)) throw new TypeError("Cannot call a class as a function"); 43789 } 43790 43791 function i(t, e) { 43792 for (var r = 0; r < e.length; r++) { 43793 var n = e[r]; 43794 n.enumerable = n.enumerable || !1, n.configurable = !0, "value" in n && (n.writable = !0), Object.defineProperty(t, n.key, n); 43795 } 43796 } 43797 43798 function o(t, e, r) { 43799 return e && i(t.prototype, e), r && i(t, r), t; 43800 } 43801 43802 function a(t) { 43803 return (a = Object.setPrototypeOf ? Object.getPrototypeOf : function (t) { 43804 return t.__proto__ || Object.getPrototypeOf(t); 43805 })(t); 43806 } 43807 43808 function s(t, e) { 43809 return (s = Object.setPrototypeOf || function (t, e) { 43810 return t.__proto__ = e, t; 43811 })(t, e); 43812 } 43813 43814 function u(t) { 43815 if (void 0 === t) throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); 43816 return t; 43817 } 43818 43819 function f(t, e, r) { 43820 return (f = "undefined" != typeof Reflect && Reflect.get ? Reflect.get : function (t, e, r) { 43821 var n = function (t, e) { 43822 for (; !Object.prototype.hasOwnProperty.call(t, e) && null !== (t = a(t));); 43823 43824 return t; 43825 }(t, e); 43826 43827 if (n) { 43828 var i = Object.getOwnPropertyDescriptor(n, e); 43829 return i.get ? i.get.call(r) : i.value; 43830 } 43831 })(t, e, r || t); 43832 } 43833 43834 Object.defineProperty(e, "__esModule", { 43835 value: !0 43836 }); 43837 43838 var c = function () { 43839 function t() { 43840 n(this, t), Object.defineProperty(this, "listeners", { 43841 value: {}, 43842 writable: !0, 43843 configurable: !0 43844 }); 43845 } 43846 43847 return o(t, [{ 43848 key: "addEventListener", 43849 value: function (t, e) { 43850 t in this.listeners || (this.listeners[t] = []), this.listeners[t].push(e); 43851 } 43852 }, { 43853 key: "removeEventListener", 43854 value: function (t, e) { 43855 if (t in this.listeners) for (var r = this.listeners[t], n = 0, i = r.length; n < i; n++) if (r[n] === e) return void r.splice(n, 1); 43856 } 43857 }, { 43858 key: "dispatchEvent", 43859 value: function (t) { 43860 var e = this; 43861 43862 if (t.type in this.listeners) { 43863 for (var r = function (r) { 43864 setTimeout(function () { 43865 return r.call(e, t); 43866 }); 43867 }, n = this.listeners[t.type], i = 0, o = n.length; i < o; i++) r(n[i]); 43868 43869 return !t.defaultPrevented; 43870 } 43871 } 43872 }]), t; 43873 }(), 43874 l = function (t) { 43875 function e() { 43876 var t; 43877 return n(this, e), (t = function (t, e) { 43878 return !e || "object" != typeof e && "function" != typeof e ? u(t) : e; 43879 }(this, a(e).call(this))).listeners || c.call(u(t)), Object.defineProperty(u(t), "aborted", { 43880 value: !1, 43881 writable: !0, 43882 configurable: !0 43883 }), Object.defineProperty(u(t), "onabort", { 43884 value: null, 43885 writable: !0, 43886 configurable: !0 43887 }), t; 43888 } 43889 43890 return function (t, e) { 43891 if ("function" != typeof e && null !== e) throw new TypeError("Super expression must either be null or a function"); 43892 t.prototype = Object.create(e && e.prototype, { 43893 constructor: { 43894 value: t, 43895 writable: !0, 43896 configurable: !0 43897 } 43898 }), e && s(t, e); 43899 }(e, t), o(e, [{ 43900 key: "toString", 43901 value: function () { 43902 return "[object AbortSignal]"; 43903 } 43904 }, { 43905 key: "dispatchEvent", 43906 value: function (t) { 43907 "abort" === t.type && (this.aborted = !0, "function" == typeof this.onabort && this.onabort.call(this, t)), f(a(e.prototype), "dispatchEvent", this).call(this, t); 43908 } 43909 }]), e; 43910 }(c), 43911 h = function () { 43912 function t() { 43913 n(this, t), Object.defineProperty(this, "signal", { 43914 value: new l(), 43915 writable: !0, 43916 configurable: !0 43917 }); 43918 } 43919 43920 return o(t, [{ 43921 key: "abort", 43922 value: function () { 43923 var t; 43924 43925 try { 43926 t = new Event("abort"); 43927 } catch (e) { 43928 "undefined" != typeof document ? document.createEvent ? (t = document.createEvent("Event")).initEvent("abort", !1, !1) : (t = document.createEventObject()).type = "abort" : t = { 43929 type: "abort", 43930 bubbles: !1, 43931 cancelable: !1 43932 }; 43933 } 43934
43935 this.signal.dispatchEvent(t); 43936 } 43937 }, { 43938 key: "toString", 43939 value: function () { 43940 return "[object AbortController]"; 43941 } 43942 }]), t; 43943 }(); 43944 43945 "undefined" != typeof Symbol && Symbol.toStringTag && (h.prototype[Symbol.toStringTag] = "AbortController", l.prototype[Symbol.toStringTag] = "AbortSignal"), e.AbortController = h, e.AbortSignal = l, e.abortableFetch = function (t) { 43946 "function" == typeof t && (t = { 43947 fetch: t 43948 }); 43949 var e = t, 43950 r = e.fetch, 43951 n = e.Request, 43952 i = void 0 === n ? r.Request : n, 43953 o = e.AbortController, 43954 a = e.__FORCE_INSTALL_ABORTCONTROLLER_POLYFILL, 43955 s = void 0 !== a && a; 43956 if (!function (t) { 43957 return t.__FORCE_INSTALL_ABORTCONTROLLER_POLYFILL ? (console.log("__FORCE_INSTALL_ABORTCONTROLLER_POLYFILL=true is set, will force install polyfill"), !0) : "function" == typeof t.Request && !t.Request.prototype.hasOwnProperty("signal") || !t.AbortController; 43958 }({ 43959 fetch: r, 43960 Request: i, 43961 AbortController: o, 43962 __FORCE_INSTALL_ABORTCONTROLLER_POLYFILL: s 43963 })) return { 43964 fetch: r, 43965 Request: u 43966 }; 43967 var u = i; 43968 (u && !u.prototype.hasOwnProperty("signal") || s) && ((u = function (t, e) { 43969 var r; 43970 e && e.signal && (r = e.signal, delete e.signal); 43971 var n = new i(t, e); 43972 return r && Object.defineProperty(n, "signal", { 43973 writable: !1, 43974 enumerable: !1, 43975 configurable: !0, 43976 value: r 43977 }), n; 43978 }).prototype = i.prototype); 43979 var f = r; 43980 return { 43981 fetch: function (t, e) { 43982 var r = u && u.prototype.isPrototypeOf(t) ? t.signal : e ? e.signal : void 0; 43983 43984 if (r) { 43985 var n; 43986 43987 try { 43988 n = new DOMException("Aborted", "AbortError"); 43989 } catch (t) { 43990 (n = new Error("Aborted")).name = "AbortError"; 43991 } 43992 43993 if (r.aborted) return Promise.reject(n); 43994 var i = new Promise(function (t, e) { 43995 r.addEventListener("abort", function () { 43996 return e(n); 43997 }, { 43998 once: !0 43999 }); 44000 }); 44001 return e && e.signal && delete e.signal, Promise.race([i, f(t, e)]); 44002 } 44003 44004 return f(t, e); 44005 }, 44006 Request: u 44007 }; 44008 }; 44009 }, function (t, e, r) { 44010 44011 Object.defineProperty(e, "__esModule", { 44012 value: !0 44013 }); 44014 44015 var n = r(162), 44016 i = function () {}, 44017 o = function () { 44018 function t() { 44019 this.signals = new Set(), this.abortController = new n.AbortController(); 44020 } 44021 44022 return t.prototype.addSignal = function (t) { 44023 var e = this; 44024 if (void 0 === t && (t = new i()), this.signal.aborted) throw new Error("cannot add a signal, already aborted!"); 44025 this.signals.add(t), t.aborted ? this.handleAborted(t) : "function" == typeof t.addEventListener && t.addEventListener("abort", function () { 44026 e.handleAborted(t); 44027 }); 44028 }, t.prototype.handleAborted = function (t) { 44029 this.signals.delete(t), 0 === this.signals.size && this.abortController.abort(); 44030 }, Object.defineProperty(t.prototype, "signal", { 44031 get: function () { 44032 return this.abortController.signal; 44033 }, 44034 enumerable: !0, 44035 configurable: !0 44036 }), t.prototype.abort = function () { 44037 this.abortController.abort(); 44038 }, t; 44039 }(); 44040 44041 e.default = o; 44042 }]); 44043 44044 /* 44045 * The MIT License (MIT) 44046 * 44047 * Copyright (c) 2018 The Regents of the University of California 44048 * Author: Jim Robinson 44049 * 44050 * Permission is hereby granted, free of charge, to any person obtaining a copy 44051 * of this software and associated documentation files (the "Software"), to deal 44052 * in the Software without restriction, including without limitation the rights 44053 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 44054 * copies of the Software, and to permit persons to whom the Software is 44055 * furnished to do so, subject to the following conditions: 44056 * 44057 * The above copyright notice and this permission notice shall be included in 44058 * all copies or substantial portions of the Software. 44059 * 44060 * 44061 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 44062 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 44063 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 44064 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 44065 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 44066 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 44067 * THE SOFTWARE. 44068 */ 44069 const READ_STRAND_FLAG = 0x10; 44070 const MATE_STRAND_FLAG = 0x20; 44071 const CRAM_MATE_STRAND_FLAG = 0x1; 44072 /** 44073 * Class for reading a cram file. Wraps the gMOD Cram package. 44074 * 44075 * @param config 44076 * @constructor 44077 */ 44078 44079 class CramReader { 44080 constructor(config, genome, browser) { 44081 this.config = config; 44082 this.browser = browser; 44083 this.genome = genome; 44084 this.cramFile = new gmodCRAM.CramFile({ 44085 filehandle: new FileHandler(config.url, config), 44086 seqFetch: config.seqFetch || seqFetch.bind(this), 44087 checkSequenceMD5: config.checkSequenceMD5 !== undefined ? config.checkSequenceMD5 : true 44088 }); 44089 const indexFileHandle = new FileHandler(config.indexURL, config); 44090 this.indexedCramFile = new gmodCRAM.IndexedCramFile({ 44091 cram: this.cramFile, 44092 index: new gmodCRAM.CraiIndex({ 44093 filehandle: indexFileHandle 44094 }), 44095 fetchSizeLimit: 30000000 44096 }); 44097 BamUtils.setReaderDefaults(this, config); 44098 44099 function seqFetch(seqID, start, end) { 44100 const sequence = this.genome.sequence; 44101 const genome = this.genome; 44102 return this.getHeader().then(function (header) { 44103 const chr = genome.getChromosomeName(header.chrNames[seqID]); 44104 return sequence.getSequence(chr, start - 1, end); 44105 }); 44106 } 44107 } 44108 /** 44109 * Parse the sequence dictionary from the SAM header and build chr name tables. This function 44110 * is public so it can be unit tested. 44111 * 44112 * @returns {PromiseLike<chrName, chrToIndex, chrAliasTable}>} 44113 */ 44114 44115 44116 async getHeader() { 44117 if (!this.header) { 44118 const genome = this.genome; 44119 const samHeader = await this.cramFile.getSamHeader(); 44120 const chrToIndex = {}; 44121 const chrNames = []; 44122 const chrAliasTable = {}; 44123 const readGroups = []; 44124 44125 for (let line of samHeader) { 44126 if ('SQ' === line.tag) { 44127 for (let d of line.data) { 44128 if (d.tag === "SN") { 44129 const seq = d.value; 44130 chrToIndex[seq] = chrNames.length; 44131 chrNames.push(seq); 44132 44133 if (genome) { 44134 const alias = genome.getChromosomeName(seq); 44135 chrAliasTable[alias] = seq; 44136 } 44137 44138 break; 44139 } 44140 } 44141 } else if ('RG' === line.tag) { 44142 readGroups.push(line.data); 44143 } 44144 } 44145 44146 this.header = { 44147 chrNames: chrNames, 44148 chrToIndex: chrToIndex, 44149 chrAliasTable: chrAliasTable, 44150 readGroups: readGroups 44151 }; 44152 } 44153 44154 return this.header; 44155 } 44156 44157 async readAlignments(chr, bpStart, bpEnd) { 44158 this.browser; 44159 const header = await this.getHeader(); 44160 const queryChr = header.chrAliasTable.hasOwnProperty(chr) ? header.chrAliasTable[chr] : chr; 44161 const chrIdx = header.chrToIndex[queryChr]; 44162 const alignmentContainer = new AlignmentContainer(chr, bpStart, bpEnd, this.samplingWindowSize, this.samplingDepth, this.pairsSupported, this.alleleFreqThreshold); 44163 44164 if (chrIdx === undefined) { 44165 return alignmentContainer; 44166 } else { 44167 try { 44168 const records = await this.indexedCramFile.getRecordsForRange(chrIdx, bpStart, bpEnd); 44169 44170 for (let record of records) { 44171 const refID = record.sequenceId; 44172 const pos = record.alignmentStart; 44173 const alignmentEnd = pos + record.lengthOnRef; 44174 44175 if (refID < 0) { 44176 continue; // unmapped read 44177 } else if (refID > chrIdx || pos > bpEnd) { 44178 return; // off right edge, we're done 44179 } else if (refID < chrIdx) { 44180 continue; // Sequence to left of start, not sure this is possible 44181 } 44182 44183 if (alignmentEnd < bpStart) { 44184 continue; 44185 } // Record out-of-range "to the left", skip to next one 44186 44187 44188 const alignment = decodeCramRecord(record, header.chrNames); 44189 44190 if (this.filter.pass(alignment)) { 44191 alignmentContainer.push(alignment); 44192 } 44193 } 44194 44195 alignmentContainer.finish(); 44196 return alignmentContainer; 44197 } catch (error) { 44198 let message = error.message; 44199 44200 if (message && message.indexOf("MD5") >= 0) { 44201 message = "Sequence mismatch. Is this the correct genome for the loaded CRAM?"; 44202 } 44203 44204 Alert.presentAlert(new Error(message)); 44205 throw error; 44206 } 44207 } 44208 44209 function decodeCramRecord(record, chrNames) { 44210 const alignment = new BamAlignment(); 44211 alignment.chr = chrNames[record.sequenceId];
44212 alignment.start = record.alignmentStart - 1; 44213 alignment.lengthOnRef = record.lengthOnRef; 44214 alignment.flags = record.flags; 44215 alignment.strand = !(record.flags & READ_STRAND_FLAG); 44216 alignment.fragmentLength = record.templateLength || record.templateSize; 44217 alignment.mq = record.mappingQuality; 44218 alignment.end = record.alignmentStart + record.lengthOnRef; 44219 alignment.readGroupId = record.readGroupId; 44220 44221 if (record.mate && record.mate.sequenceId !== undefined) { 44222 const strand = record.mate.flags !== undefined ? !(record.mate.flags & CRAM_MATE_STRAND_FLAG) : !(record.flags & MATE_STRAND_FLAG); 44223 alignment.mate = { 44224 chr: chrNames[record.mate.sequenceId], 44225 position: record.mate.alignmentStart, 44226 strand: strand 44227 }; 44228 } 44229 44230 alignment.seq = record.getReadBases(); 44231 alignment.qual = record.qualityScores; 44232 alignment.tagDict = record.tags; 44233 alignment.readName = record.readName; // TODO -- cigar encoded in tag? 44234 // BamUtils.bam_tag2cigar(ba, blockEnd, p, lseq, alignment, cigarArray); 44235 44236 makeBlocks(record, alignment); 44237 44238 if (alignment.mate && alignment.start > alignment.mate.position && alignment.fragmentLength > 0) { 44239 alignment.fragmentLength = -alignment.fragmentLength; 44240 } 44241 44242 BamUtils.setPairOrientation(alignment); 44243 return alignment; 44244 } 44245 44246 function makeBlocks(cramRecord, alignment) { 44247 const blocks = []; 44248 let insertions; 44249 let gaps; 44250 let basesUsed = 0; 44251 let cigarString = ''; 44252 alignment.scStart = alignment.start; 44253 alignment.scLengthOnRef = alignment.lengthOnRef; 44254 44255 if (cramRecord.readFeatures) { 44256 for (let feature of cramRecord.readFeatures) { 44257 const code = feature.code; 44258 const data = feature.data; 44259 const readPos = feature.pos - 1; 44260 const refPos = feature.refPos - 1; 44261 44262 switch (code) { 44263 case 'S': 44264 case 'I': 44265 case 'i': 44266 case 'N': 44267 case 'D': 44268 if (readPos > basesUsed) { 44269 const len = readPos - basesUsed; 44270 blocks.push(new AlignmentBlock({ 44271 start: refPos - len, 44272 seqOffset: basesUsed, 44273 len: len, 44274 type: 'M' 44275 })); 44276 basesUsed += len; 44277 cigarString += len + 'M'; 44278 } 44279 44280 if ('S' === code) { 44281 let scPos = refPos; 44282 alignment.scLengthOnRef += data.length; 44283 44284 if (readPos === 0) { 44285 alignment.scStart -= data.length; 44286 scPos -= data.length; 44287 } 44288 44289 const len = data.length; 44290 blocks.push(new AlignmentBlock({ 44291 start: scPos, 44292 seqOffset: basesUsed, 44293 len: len, 44294 type: 'S' 44295 })); 44296 basesUsed += len; 44297 cigarString += len + code; 44298 } else if ('I' === code || 'i' === code) { 44299 if (insertions === undefined) { 44300 insertions = []; 44301 } 44302 44303 const len = 'i' === code ? 1 : data.length; 44304 insertions.push(new AlignmentBlock({ 44305 start: refPos, 44306 len: len, 44307 seqOffset: basesUsed, 44308 type: 'I' 44309 })); 44310 basesUsed += len; 44311 cigarString += len + code; 44312 } else if ('D' === code || 'N' === code) { 44313 if (!gaps) { 44314 gaps = []; 44315 } 44316 44317 gaps.push({ 44318 start: refPos, 44319 len: data, 44320 type: code 44321 }); 44322 cigarString += data + code; 44323 } 44324 44325 break; 44326 44327 case 'H': 44328 case 'P': 44329 cigarString += data + code; 44330 break; 44331 44332 } 44333 } 44334 } // Last block 44335 44336 44337 const len = cramRecord.readLength - basesUsed; 44338 44339 if (len > 0) { 44340 blocks.push(new AlignmentBlock({ 44341 start: cramRecord.alignmentStart + cramRecord.lengthOnRef - len - 1,
44342 seqOffset: basesUsed, 44343 len: len, 44344 type: 'M' 44345 })); 44346 cigarString += len + 'M'; 44347 } 44348 44349 alignment.blocks = blocks; 44350 alignment.insertions = insertions; 44351 alignment.gaps = gaps; 44352 alignment.cigar = cigarString; 44353 } 44354 } 44355 44356 } 44357 44358 class FileHandler { 44359 constructor(source, config) { 44360 this.position = 0; 44361 this.url = source; 44362 this.config = config; 44363 this.cache = new BufferCache({ 44364 fetch: (start, length) => this._fetch(start, length) 44365 }); 44366 } 44367 44368 async _fetch(position, length) { 44369 const loadRange = { 44370 start: position, 44371 size: length 44372 }; 44373 this._stat = { 44374 size: undefined 44375 }; 44376 const arrayBuffer = await igvxhr.loadArrayBuffer(this.url, buildOptions(this.config, { 44377 range: loadRange 44378 })); 44379 return Buffer.from(arrayBuffer); 44380 } 44381 44382 async read(buffer) { 44383 let offset = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; 44384 let length = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : Infinity; 44385 let position = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0; 44386 let readPosition = position; 44387 44388 if (readPosition === null) { 44389 readPosition = this.position; 44390 this.position += length; 44391 } 44392 44393 return this.cache.get(buffer, offset, length, position); 44394 } 44395 44396 async readFile() { 44397 const arrayBuffer = await igvxhr.loadArrayBuffer(this.url, buildOptions(this.config)); 44398 return Buffer.from(arrayBuffer); 44399 } 44400 44401 async stat() { 44402 if (!this._stat) { 44403 const buf = Buffer.allocUnsafe(10); 44404 await this.read(buf, 0, 10, 0); 44405 if (!this._stat) throw new Error(`unable to determine size of file at ${this.url}`); 44406 } 44407 44408 return this._stat; 44409 } 44410 44411 } 44412 44413 class BufferCache { 44414 constructor(_ref) { 44415 let { 44416 fetch, 44417 size = 10000000, 44418 chunkSize = 32768 44419 } = _ref; 44420 this.fetch = fetch; 44421 this.chunkSize = chunkSize; 44422 this.lruCache = new QuickLRU({ 44423 maxSize: Math.floor(size / chunkSize) 44424 }); 44425 } 44426 44427 async get(outputBuffer, offset, length, position) { 44428 if (outputBuffer.length < offset + length) throw new Error('output buffer not big enough for request'); // calculate the list of chunks involved in this fetch 44429 44430 const firstChunk = Math.floor(position / this.chunkSize); 44431 const lastChunk = Math.floor((position + length) / this.chunkSize); // fetch them all as necessary 44432 44433 const fetches = new Array(lastChunk - firstChunk + 1); 44434 44435 for (let chunk = firstChunk; chunk <= lastChunk; chunk += 1) { 44436 fetches[chunk - firstChunk] = this._getChunk(chunk).then(data => ({ 44437 data, 44438 chunkNumber: chunk 44439 })); 44440 } // stitch together the response buffer using them 44441 44442 44443 const chunks = await Promise.all(fetches); 44444 const chunksOffset = position - chunks[0].chunkNumber * this.chunkSize; 44445 chunks.forEach(_ref2 => { 44446 let { 44447 data, 44448 chunkNumber 44449 } = _ref2; 44450 const chunkPositionStart = chunkNumber * this.chunkSize; 44451 let copyStart = 0; 44452 let copyEnd = this.chunkSize; 44453 let copyOffset = offset + (chunkNumber - firstChunk) * this.chunkSize - chunksOffset; 44454 44455 if (chunkNumber === firstChunk) { 44456 copyOffset = offset; 44457 copyStart = chunksOffset; 44458 } 44459 44460 if (chunkNumber === lastChunk) { 44461 copyEnd = position + length - chunkPositionStart; 44462 } 44463 44464 data.copy(outputBuffer, copyOffset, copyStart, copyEnd); 44465 }); 44466 } 44467 44468 _getChunk(chunkNumber) { 44469 const cachedPromise = this.lruCache.get(chunkNumber); 44470 if (cachedPromise) return cachedPromise; 44471 const freshPromise = this.fetch(chunkNumber * this.chunkSize, this.chunkSize); 44472 this.lruCache.set(chunkNumber, freshPromise); 44473 return freshPromise; 44474 } 44475 44476 } // From https://github.com/sindresorhus/quick-lru 44477 44478 class QuickLRU { 44479 constructor() { 44480 let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; 44481 44482 if (!(options.maxSize && options.maxSize > 0)) { 44483 throw new TypeError('`maxSize` must be a number greater than 0'); 44484 } 44485 44486 this.maxSize = options.maxSize; 44487 this.cache = new Map(); 44488 this.oldCache = new Map(); 44489 this._size = 0; 44490 } 44491 44492 _set(key, value) { 44493 this.cache.set(key, value); 44494 this._size++; 44495 44496 if (this._size >= this.maxSize) { 44497 this._size = 0; 44498 this.oldCache = this.cache; 44499 this.cache = new Map(); 44500 } 44501 } 44502 44503 get(key) { 44504 if (this.cache.has(key)) { 44505 return this.cache.get(key); 44506 } 44507 44508 if (this.oldCache.has(key)) { 44509 const value = this.oldCache.get(key); 44510 44511 this._set(key, value); 44512 44513 return value; 44514 } 44515 } 44516 44517 set(key, value) { 44518 if (this.cache.has(key)) { 44519 this.cache.set(key, value); 44520 } else { 44521 this._set(key, value); 44522 } 44523 44524 return this; 44525 } 44526 44527 has(key) { 44528 return this.cache.has(key) || this.oldCache.has(key); 44529 } 44530 44531 peek(key) { 44532 if (this.cache.has(key)) { 44533 return this.cache.get(key); 44534 } 44535 44536 if (this.oldCache.has(key)) { 44537 return this.oldCache.get(key); 44538 } 44539 } 44540 44541 delete(key) { 44542 const deleted = this.cache.delete(key); 44543 44544 if (deleted) { 44545 this._size--; 44546 } 44547 44548 return this.oldCache.delete(key) || deleted; 44549 } 44550 44551 clear() { 44552 this.cache.clear(); 44553 this.oldCache.clear(); 44554 this._size = 0; 44555 } 44556 44557 *keys() { 44558 for (const [key] of this) { 44559 yield key; 44560 } 44561 } 44562 44563 *values() { 44564 for (const [, value] of this) { 44565 yield value; 44566 } 44567 } 44568 44569 *[Symbol.iterator]() { 44570 for (const item of this.cache) { 44571 yield item; 44572 } 44573 44574 for (const item of this.oldCache) { 44575 const [key] = item; 44576 44577 if (!this.cache.has(key)) { 44578 yield item; 44579 } 44580 } 44581 } 44582 44583 get size() { 44584 let oldCacheSize = 0; 44585 44586 for (const key of this.oldCache.keys()) { 44587 if (!this.cache.has(key)) { 44588 oldCacheSize++; 44589 } 44590 } 44591 44592 return this._size + oldCacheSize; 44593 } 44594 44595 } 44596 44597 /* 44598 * The MIT License (MIT) 44599 * 44600 * Copyright (c) 2014 Broad Institute 44601 * 44602 * Permission is hereby granted, free of charge, to any person obtaining a copy 44603 * of this software and associated documentation files (the "Software"), to deal 44604 * in the Software without restriction, including without limitation the rights 44605 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 44606 * copies of the Software, and to permit persons to whom the Software is 44607 * furnished to do so, subject to the following conditions: 44608 * 44609 * The above copyright notice and this permission notice shall be included in 44610 * all copies or substantial portions of the Software. 44611 * 44612 * 44613 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 44614 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 44615 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 44616 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 44617 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 44618 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 44619 * THE SOFTWARE. 44620 */ 44621 const apiKey = igvxhr.apiKey; 44622 44623 function ga4ghGet(options) { 44624 var url = options.url + "/" + options.entity + "/" + options.entity
44624Id; 44625 options.headers = ga4ghHeaders(); 44626 return igvxhr.loadJson(url, options); // Returns a promise 44627 } 44628 44629 function ga4ghSearch(options) { 44630 return new Promise(function (fulfill, reject) { 44631 var results = options.results ? options.results : [], 44632 url = options.url, 44633 body = options.body, 44634 decode = options.decode, 44635 paramSeparator = "?", 44636 fields = options.fields; // Partial response 44637 44638 if (apiKey) { 44639 url = url + paramSeparator + "key=" + apiKey; 44640 paramSeparator = "&"; 44641 } 44642 44643 if (fields) { 44644 url = url + paramSeparator + "fields=" + fields; 44645 } // Start the recursive load cycle. Data is fetched in chunks, if more data is available a "nextPageToken" is returned. 44646 44647 44648 return loadChunk(); 44649 44650 function loadChunk(pageToken) { 44651 if (pageToken) { 44652 body.pageToken = pageToken; 44653 } else { 44654 if (body.pageToken !== undefined) delete body.pageToken; // Remove previous page token, if any 44655 } 44656 44657 var sendData = JSON.stringify(body); 44658 igvxhr.loadJson(url, { 44659 sendData: sendData, 44660 contentType: "application/json", 44661 headers: ga4ghHeaders() // oauthToken: ga4ghToken() 44662 44663 }).then(function (json) { 44664 var nextPageToken, tmp; 44665 44666 if (json) { 44667 tmp = decode ? decode(json) : json; 44668 44669 if (tmp) { 44670 tmp.forEach(function (a) { 44671 44672 { 44673 results.push(a); 44674 } 44675 }); 44676 } 44677 44678 nextPageToken = json["nextPageToken"]; 44679 44680 if (nextPageToken) { 44681 loadChunk(nextPageToken); 44682 } else { 44683 fulfill(results); 44684 } 44685 } else { 44686 fulfill(results); 44687 } 44688 }).catch(function (error) { 44689 reject(error); 44690 }); 44691 } 44692 }); 44693 } 44694 44695 function ga4ghHeaders() { 44696 return { 44697 "Cache-Control": "no-cache" 44698 }; 44699 } 44700 44701 /* 44702 * The MIT License (MIT) 44703 * 44704 * Copyright (c) 2014 Broad Institute 44705 * 44706 * Permission is hereby granted, free of charge, to any person obtaining a copy 44707 * of this software and associated documentation files (the "Software"), to deal 44708 * in the Software without restriction, including without limitation the rights 44709 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 44710 * copies of the Software, and to permit persons to whom the Software is 44711 * furnished to do so, subject to the following conditions: 44712 * 44713 * The above copyright notice and this permission notice shall be included in 44714 * all copies or substantial portions of the Software. 44715 * 44716 * 44717 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 44718 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 44719 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 44720 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 44721 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 44722 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 44723 * THE SOFTWARE. 44724 */ 44725 var CigarOperationTable = { 44726 "ALIGNMENT_MATCH": "M", 44727 "INSERT": "I", 44728 "DELETE": "D", 44729 "SKIP": "N", 44730 "CLIP_SOFT": "S", 44731 "CLIP_HARD": "H", 44732 "PAD": "P", 44733 "SEQUENCE_MATCH": "=", 44734 "SEQUENCE_MISMATCH": "X" 44735 }; 44736 44737 const Ga4ghAlignmentReader = function (config, genome) { 44738 this.config = config; 44739 this.genome = genome; 44740 this.url = config.url; 44741 this.filter = new BamFilter(config.filter); 44742 this.readGroupSetIds = config.readGroupSetIds; 44743 this.authKey = config.authKey; // Might be undefined or nill 44744 44745 this.samplingWindowSize = config.samplingWindowSize === undefined ? 100 : config.samplingWindowSize; 44746 this.samplingDepth = config.samplingDepth === undefined ? 1000 : config.samplingDepth; 44747 44748 if (config.viewAsPairs) { 44749 this.pairsSupported = true; 44750 } else { 44751 this.pairsSupported = config.pairsSupported === undefined ? true : config.pairsSupported; 44752 } 44753 }; 44754 44755 Ga4ghAlignmentReader.prototype.readAlignments = function (chr, bpStart, bpEnd) { 44756 const genome = this.genome; 44757 const self = this; 44758 return getChrAliasTable().then(function (chrAliasTable) { 44759 var queryChr = chrAliasTable.hasOwnProperty(chr) ? chrAliasTable[chr] : chr, 44760 readURL = self.url + "/reads/search"; 44761 return ga4ghSearch({ 44762 url: readURL, 44763 body: { 44764 "readGroupSetIds": [self.readGroupSetIds], 44765 "referenceName": queryChr, 44766 "start": bpStart, 44767 "end": bpEnd, 44768 "pageSize": "10000" 44769 }, 44770 decode: decodeGa4ghReads,
44771 results: new AlignmentContainer(chr, bpStart, bpEnd, self.samplingWindowSize, self.samplingDepth, self.pairsSupported, self.alleleFreqThreshold) 44772 }); 44773 }); 44774 44775 function getChrAliasTable() { 44776 if (self.chrAliasTable) { 44777 return Promise.resolve(self.chrAliasTable); 44778 } else { 44779 return self.readMetadata().then(function (json) { 44780 self.chrAliasTable = {}; 44781 44782 if (genome && json.readGroups && json.readGroups.length > 0) { 44783 var referenceSetId = json.readGroups[0].referenceSetId; 44784 44785 if (referenceSetId) { 44786 // Query for reference names to build an alias table (map of genome ref names -> dataset ref names) 44787 var readURL = self.url + "/references/search"; 44788 return ga4ghSearch({ 44789 url: readURL, 44790 body: { 44791 "referenceSetId": referenceSetId 44792 }, 44793 decode: function (j) { 44794 return j.references; 44795 } 44796 }).then(function (references) { 44797 references.forEach(function (ref) { 44798 var refName = ref.name, 44799 alias = genome.getChromosomeName(refName); 44800 self.chrAliasTable[alias] = refName; 44801 }); 44802 return self.chrAliasTable; 44803 }); 44804 } else { 44805 // Try hardcoded constants -- workaround for non-compliant data at Google 44806 populateChrAliasTable(self.chrAliasTable, self.config.datasetId); 44807 return self.chrAliasTable; 44808 } 44809 } else { 44810 // No browser object, can't build map. This can occur when run from unit tests 44811 return self.chrAliasTable; 44812 } 44813 }); 44814 } 44815 } 44816 /** 44817 * Decode an array of ga4gh read records 44818 * 44819 */ 44820 44821 44822 function decodeGa4ghReads(j) { 44823 var i, 44824 jsonRecords = j.alignments, 44825 len = jsonRecords.length, 44826 alignment, 44827 jsonAlignment, 44828 cigarDecoded, 44829 alignments = [], 44830 mate, 44831 blocks; 44832 44833 for (i = 0; i < len; i++) { 44834 let record = jsonRecords[i]; 44835 alignment = new BamAlignment(); 44836 alignment.readName = record.fragmentName; 44837 alignment.properPlacement = record.properPlacement; 44838 alignment.duplicateFragment = record.duplicateFragment; 44839 alignment.numberReads = record.numberReads; 44840 alignment.fragmentLength = record.fragmentLength; 44841 alignment.readNumber = record.readNumber; 44842 alignment.failedVendorQualityChecks = record.failedVendorQualityChecks; 44843 alignment.secondaryAlignment = record.secondaryAlignment; 44844 alignment.supplementaryAlignment = record.supplementaryAlignment; 44845 alignment.seq = record.alignedSequence; 44846 alignment.qual = record.alignedQuality; 44847 alignment.matePos = record.nextMatePosition; 44848 alignment.tagDict = record.info; 44849 alignment.flags = encodeFlags(); 44850 jsonAlignment = record.alignment; 44851 44852 if (jsonAlignment) { 44853 alignment.mapped = true; 44854 alignment.chr = record.alignment.position.referenceName; 44855 if (genome) alignment.chr = genome.getChromosomeName(alignment.chr); 44856 alignment.start = parseInt(record.alignment.position.position); 44857 alignment.strand = !record.alignment.position.reverseStrand; 44858 alignment.mq = record.alignment.mappingQuality; 44859 alignment.cigar = encodeCigar(record.alignment.cigar); 44860 cigarDecoded = translateCigar(record.alignment.cigar); 44861 alignment.lengthOnRef = cigarDecoded.lengthOnRef; 44862 blocks = makeBlocks(alignment, cigarDecoded.array); 44863 alignment.blocks = blocks.blocks; 44864 alignment.insertions = blocks.insertions; 44865 } else { 44866 alignment.mapped = false; 44867 } 44868 44869 mate = record.nextMatePosition; 44870 44871 if (mate) { 44872 alignment.mate = { 44873 chr: mate.referenceFrame, 44874 position: parseInt(mate.position), 44875 strand: !mate.reverseStrand 44876 }; 44877 } 44878 44879 if (self.filter.pass(alignment)) { 44880 alignments.push(alignment); 44881 } 44882 } 44883 44884 return alignments; // Encode a cigar string -- used for popup text 44885 44886 function encodeCigar(cigarArray) { 44887 var cigarString = ""; 44888 cigarArray.forEach(function (cigarUnit) { 44889 var op = CigarOperationTable[cigarUnit.operation], 44890 len = cigarUnit.operationLength; 44891 cigarString = cigarString + (len + op); 44892 }); 44893 return cigarString; 44894 } // TODO -- implement me 44895 44896 44897 function encodeFlags(json) { 44898 return 0; 44899 } 44900 44901 function translateCigar(cigar) { 44902 var cigarUnit, 44903 opLen, 44904 opLtr, 44905 lengthOnRef = 0, 44906 cigarArray = [], 44907 i; 44908 44909 for (i = 0; i < cigar.length; i++) { 44910 cigarUnit = cigar[i]; 44911 opLtr = CigarOperationTable[cigarUnit.operation]; 44912 opLen = parseInt(cigarUnit.operationLength); // Google represents long as a String 44913 44914 if (opLtr === 'M' || opLtr === 'EQ' || opLtr === 'X' || opLtr === 'D' || opLtr === 'N' || opLtr === '=') lengthOnRef += opLen; 44915 cigarArray.push({
44916 len: opLen, 44917 ltr: opLtr 44918 }); 44919 } 44920 44921 return { 44922 lengthOnRef: lengthOnRef, 44923 array: cigarArray 44924 }; 44925 } 44926 /** 44927 * Split the alignment record into blocks as specified in the cigarArray. Each aligned block contains 44928 * its portion of the read sequence and base quality strings. A read sequence or base quality string 44929 * of "*" indicates the value is not recorded. In all other cases the length of the block sequence (block.seq) 44930 * and quality string (block.qual) must == the block length. 44931 * 44932 * NOTE: Insertions are not yet treated // TODO 44933 * 44934 * @param record 44935 * @param cigarArray 44936 * @returns array of blocks 44937 */ 44938 44939 44940 function makeBlocks(record, cigarArray) { 44941 var blocks = [], 44942 gaps, 44943 insertions, 44944 seqOffset = 0, 44945 pos = record.start, 44946 len = cigarArray.length, 44947 gapType; 44948 44949 for (var i = 0; i < len; i++) { 44950 var c = cigarArray[i]; 44951 44952 switch (c.ltr) { 44953 case 'H': 44954 break; 44955 // ignore hard clips 44956 44957 case 'P': 44958 break; 44959 // ignore pads 44960 44961 case 'S': 44962 seqOffset += c.len; 44963 gapType = 'S'; 44964 break; 44965 // soft clip read bases 44966 44967 case 'N': 44968 case 'D': 44969 if (gaps === undefined) { 44970 gaps = []; 44971 } 44972 44973 gaps.push({ 44974 start: pos, 44975 len: c.len, 44976 type: c.ltr 44977 }); 44978 pos += c.len; 44979 break; 44980 44981 case 'I': 44982 if (insertions === undefined) insertions = []; 44983 insertions.push(new AlignmentBlock({ 44984 start: pos, 44985 len: c.len, 44986 seqOffset: seqOffset 44987 })); 44988 seqOffset += c.len; 44989 break; 44990 44991 case 'M': 44992 case 'EQ': 44993 case '=': 44994 case 'X': 44995 blocks.push(new AlignmentBlock({ 44996 start: pos, 44997 len: c.len, 44998 seqOffset: seqOffset, 44999 gapType: gapType 45000 })); 45001 seqOffset += c.len; 45002 pos += c.len; 45003 break; 45004 45005 default: 45006 console.log("Error processing cigar element: " + c.len + c.ltr); 45007 } 45008 } 45009 45010 return { 45011 blocks: blocks, 45012 insertions: insertions, 45013 gaps: gaps 45014 }; 45015 } 45016 } 45017 }; 45018 45019 Ga4ghAlignmentReader.prototype.readMetadata = function () { 45020 return ga4ghGet({ 45021 url: this.url, 45022 entity: "readgroupsets", 45023 entityId: this.readGroupSetIds 45024 }); 45025 }; 45026 /** 45027 * Hardcoded hack to work around some non-compliant google datasets 45028 * 45029 * @param chrAliasTable 45030 * @param datasetId 45031 */ 45032 45033 45034 function populateChrAliasTable(chrAliasTable, datasetId) { 45035 var i; 45036 45037 if ("461916304629" === datasetId || "337315832689" === datasetId) { 45038 for (i = 1; i < 23; i++) { 45039 chrAliasTable["chr" + i] = i; 45040 } 45041 45042 chrAliasTable["chrX"] = "X"; 45043 chrAliasTable["chrY"] = "Y"; 45044 chrAliasTable["chrM"] = "MT"; 45045 } 45046 } 45047 45048 /* 45049 * The MIT License (MIT) 45050 * 45051 * Copyright (c) 2014 Broad Institute 45052 * 45053 * Permission is hereby granted, free of charge, to any person obtaining a copy 45054 * of this software and associated documentation files (the "Software"), to deal 45055 * in the Software without restriction, including without limitation the rights 45056 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 45057 * copies of the Software, and to permit persons to whom the Software is 45058 * furnished to do so, subject to the following conditions: 45059 * 45060 * The above copyright notice and this permission notice shall be included in 45061 * all copies or substantial portions of the Software. 45062 * 45063 * 45064 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 45065 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 45066 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 45067 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 45068 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 45069 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 45070 * THE SOFTWARE. 45071 */ 45072 45073 class BamSource { 45074 constructor(config, browser) { 45075 const genome = browser.genome; 45076 this.config = config; 45077 this.genome = genome; 45078 this.alignmentContainer = undefined; 45079 45080 if (isDataURL(config.url)) { 45081 if ("cram" === config.format) { 45082 throw "CRAM data uris are not supported"; 45083 } 45084 45085 this.config.indexed = false;
45086 } 45087 45088 if ("ga4gh" === config.sourceType) { 45089 this.bamReader = new Ga4ghAlignmentReader(config, genome); 45090 } else if ("pysam" === config.sourceType) { 45091 this.bamReader = new BamWebserviceReader(config, genome); 45092 } else if ("htsget" === config.sourceType) { 45093 this.bamReader = new HtsgetBamReader(config, genome); 45094 } else if ("shardedBam" === config.sourceType) { 45095 this.bamReader = new ShardedBamReader(config, genome); 45096 } else if ("cram" === config.format) { 45097 this.bamReader = new CramReader(config, genome, browser); 45098 } else { 45099 if (!this.config.indexURL && config.indexed !== false) { 45100 if (isString$3(this.config.url)) { 45101 const inferIndexPath$1 = inferIndexPath(this.config.url, "bai"); 45102 45103 if (inferIndexPath$1) { 45104 console.error(`Warning: no indexURL specified for ${this.config.url}. Guessing ${this.baiPath}`); 45105 this.config.indexURL = inferIndexPath$1; 45106 } else { 45107 console.error(`Warning: no indexURL specified for ${this.config.url}.`); 45108 this.config.indexed = false; 45109 } 45110 } else { 45111 console.error(`Warning: no indexURL specified for ${this.config.name}.`); 45112 this.config.indexed = false; 45113 } 45114 } 45115 45116 if (this.config.indexed !== false) { 45117 // && this.config.indexURL) { 45118 this.bamReader = new BamReader(config, genome); 45119 } else { 45120 this.bamReader = new BamReaderNonIndexed(config, genome); 45121 } 45122 } 45123 45124 this.viewAsPairs = config.viewAsPairs; 45125 this.showSoftClips = config.showSoftClips; 45126 } 45127 45128 setViewAsPairs(bool) { 45129 45130 if (this.viewAsPairs !== bool) { 45131 this.viewAsPairs = bool; // if (this.alignmentContainer) { 45132 // this.alignmentContainer.setViewAsPairs(bool); 45133 // } 45134 } 45135 } 45136 45137 setShowSoftClips(bool) { 45138 if (this.showSoftClips !== bool) { 45139 this.showSoftClips = bool; 45140 } 45141 } 45142 45143 async getAlignments(chr, bpStart, bpEnd) { 45144 const genome = this.genome; 45145 const showSoftClips = this.showSoftClips; 45146 45147 if (this.alignmentContainer && this.alignmentContainer.contains(chr, bpStart, bpEnd)) { 45148 return this.alignmentContainer; 45149 } else { 45150 const alignmentContainer = await this.bamReader.readAlignments(chr, bpStart, bpEnd); 45151 let alignments = alignmentContainer.alignments; 45152 45153 if (!this.viewAsPairs) { 45154 alignments = unpairAlignments([{ 45155 alignments: alignments 45156 }]); 45157 } 45158 45159 const hasAlignments = alignments.length > 0; 45160 alignmentContainer.packedAlignmentRows = packAlignmentRows(alignments, alignmentContainer.start, alignmentContainer.end, showSoftClips); 45161 alignmentContainer.alignments = undefined; // Don't need to hold onto these anymore 45162 45163 this.alignmentContainer = alignmentContainer; 45164 45165 if (hasAlignments) { 45166 const sequence = await genome.sequence.getSequence(chr, alignmentContainer.start, alignmentContainer.end); 45167 45168 if (sequence) { 45169 alignmentContainer.coverageMap.refSeq = sequence; // TODO -- fix this 45170 45171 alignmentContainer.sequence = sequence; // TODO -- fix this 45172 45173 return alignmentContainer; 45174 } else { 45175 console.error("No sequence for: " + chr + ":" + alignmentContainer.start + "-" + alignmentContainer.end); 45176 } 45177 } 45178 45179 return alignmentContainer; 45180 } 45181 } 45182 45183 } 45184 45185 /* 45186 * The MIT License (MIT) 45187 * 45188 * Copyright (c) 2018 Regents of the University of California 45189 * 45190 * Permission is hereby granted, free of charge, to any person obtaining a copy 45191 * of this software and associated documentation files (the "Software"), to deal 45192 * in the Software without restriction, including without limitation the rights 45193 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 45194 * copies of the Software, and to permit persons to whom the Software is 45195 * furnished to do so, subject to the following conditions: 45196 * 45197 * The above copyright notice and this permission notice shall be included in 45198 * all copies or substantial portions of the Software. 45199 * 45200 * 45201 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 45202 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 45203 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 45204 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 45205 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 45206 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 45207 * THE SOFTWARE. 45208 */ 45209 /** 45210 * A collection of properties and methods shared by all (or most) track types. 45211 * 45212 * @param config 45213 * @param browser 45214 * @constructor 45215 */ 45216 45217 class TrackBase { 45218 constructor(config, browser) { 45219 this.browser = browser; 45220 this.init(config); 45221 } 45222 /** 45223 * Initialize track properties from the config object. This method is typically overriden in subclasses, which 45224 * will call this implementation as super.init(config). 45225 * 45226 * @param config 45227 */ 45228 45229 45230 init(config) { 45231 if (config.displayMode) { 45232 config.displayMode = config.displayMode.toUpperCase(); 45233 } 45234 45235 this.config = config; 45236 this.url = config.url; 45237 this.type = config.type; 45238 this.description = config.description;
45239 this.supportHiDPI = config.supportHiDPI === undefined ? true : config.supportHiDPI; 45240 45241 if (config.name || config.label) { 45242 this.name = config.name || config.label; 45243 } else if (isFile(config.url)) { 45244 this.name = config.url.name; 45245 } else if (isString$3(config.url) && !config.url.startsWith("data:")) { 45246 this.name = getFilename$1(config.url); 45247 } 45248 45249 this.id = this.config.id === undefined ? this.name : this.config.id; 45250 this.order = config.order; 45251 this.color = config.color; 45252 this.altColor = config.altColor; 45253 45254 if ("civic-ws" === config.sourceType) { 45255 // Ugly proxy for specialized track type 45256 this.defaultColor = "rgb(155,20,20)"; 45257 } else { 45258 this.defaultColor = "rgb(0,0,150)"; 45259 } 45260 45261 this.autoscaleGroup = config.autoscaleGroup; 45262 this.removable = config.removable === undefined ? true : config.removable; // Defaults to true 45263 45264 this.height = config.height || 100; 45265 this.autoHeight = config.autoHeight; 45266 this.minHeight = config.minHeight || Math.min(25, this.height); 45267 this.maxHeight = config.maxHeight || Math.max(1000, this.height); 45268 this.visibilityWindow = config.visibilityWindow; 45269 45270 if (config.onclick) { 45271 this.onclick = config.onclick; 45272 config.onclick = undefined; // functions cannot be saved in sessions, clear it here. 45273 } 45274 } 45275 45276 get name() { 45277 return this._name; 45278 } 45279 45280 set name(name) { 45281 this._name = name; 45282 45283 if (this.trackView) { 45284 this.trackView.setTrackLabelName(name); 45285 } 45286 } 45287 /** 45288 * Update track properties from the config object. 45289 * 45290 * @param config 45291 */ 45292 45293 45294 updateConfig(config) { 45295 this.init(config); 45296 } 45297 /** 45298 * Default implementation -- update config with current values. 45299 * to create session object for bookmarking, sharing. Updates the track "config" object to reflect the 45300 * current state. Only simple properties (string, number, boolean) are updated. 45301 */ 45302 45303 45304 getState() { 45305 // Create copy of config, minus transient properties (convention is name starts with '_'). Also, all 45306 // function properties are transient as they cannot be saved in json 45307 const state = {}; 45308 45309 for (let key of Object.keys(this.config)) { 45310 if (!key.startsWith("_") && typeof this.config[key] !== "function" && this.config[key] !== undefined) { 45311 state[key] = this.config[key]; 45312 } 45313 } // Update original config values with any changes 45314 45315 45316 for (let key of Object.keys(state)) { 45317 if (key.startsWith("_")) continue; // transient property 45318 45319 const value = this[key]; 45320 45321 if (value && (isSimpleType(value) || typeof value === "boolean")) { 45322 state[key] = value; 45323 } 45324 } 45325 45326 if (this.color) state.color = this.color; 45327 if (this.altColor) state.altColor = this.altColor; // Flatten dataRange if present 45328 45329 if (!this.autoscale && this.dataRange) { 45330 state.min = this.dataRange.min; 45331 state.max = this.dataRange.max; 45332 } // Check for non-json-if-yable properties. Perhaps we should test what can be saved. 45333 45334 45335 for (let key of Object.keys(state)) { 45336 if (typeof state[key] === 'function') { 45337 throw Error(`Property '${key}' of track '${this.name} is a function. Functions cannot be saved in sessions.`); 45338 } 45339 45340 if (isFile(state[key])) { 45341 const str = `Track ${this.name} is a local file. Sessions cannot be saved with local file references.`; 45342 throw Error(str); 45343 } 45344 45345 if (state[key] instanceof Promise) { 45346 throw Error(`Property '${key}' of track '${this.name} is a Promise. Promises cannot be saved in sessions.`); 45347 } 45348 } 45349 45350 return state; 45351 } 45352 45353 supportsWholeGenome() { 45354 return false; 45355 } 45356 /** 45357 * Does the track support sample names. Current sample aware tracks include VCF (with genotypes), MUT, MAF, and SEG 45358 * @returns {boolean} 45359 */ 45360 45361 45362 hasSamples() { 45363 return false;
45364 } 45365 45366 getGenomeId() { 45367 return this.browser.genome ? this.browser.genome.id : undefined; 45368 } 45369 /** 45370 * Set certain track properties, usually from a "track" line. Not all UCSC properties are supported. 45371 * 45372 * Track configuration settings have precendence over track line properties, so if both are present ignore the 45373 * track line. 45374 * 45375 * @param properties 45376 */ 45377 45378 45379 setTrackProperties(properties) { 45380 const tracklineConfg = {}; 45381 let tokens; 45382 45383 for (let key of Object.keys(properties)) { 45384 switch (key.toLowerCase()) { 45385 case "usescore": 45386 tracklineConfg.useScore = properties[key] === 1 || properties[key] === "1" || properties[key] === "on" || properties[key] === true; 45387 break; 45388 45389 case "visibility": 45390 //0 - hide, 1 - dense, 2 - full, 3 - pack, and 4 - squish 45391 switch (properties[key]) { 45392 case "2": 45393 case "3": 45394 case "pack": 45395 case "full": 45396 tracklineConfg.displayMode = "EXPANDED"; 45397 break; 45398 45399 case "4": 45400 case "squish": 45401 tracklineConfg.displayMode = "SQUISHED"; 45402 break; 45403 45404 case "1": 45405 case "dense": 45406 tracklineConfg.displayMode = "COLLAPSED"; 45407 } 45408 45409 break; 45410 45411 case "color": 45412 case "altcolor": 45413 tracklineConfg[key] = properties[key].startsWith("rgb(") ? properties[key] : "rgb(" + properties[key] + ")"; 45414 break; 45415 45416 case "featurevisiblitywindow": 45417 case "visibilitywindow": 45418 tracklineConfg.visibilityWindow = Number.parseInt(properties[key]); 45419 break; 45420 45421 case "maxheightpixels": 45422 tokens = properties[key].split(":"); 45423 45424 if (tokens.length === 3) { 45425 tracklineConfg.minHeight = Number.parseInt(tokens[2]); 45426 tracklineConfg.height = Number.parseInt(tokens[1]); 45427 tracklineConfg.maxHeight = Number.parseInt(tokens[0]); 45428 } 45429 45430 break; 45431 45432 case "viewlimits": 45433 if (!this.config.autoscale) { 45434 // autoscale in the config has precedence 45435 tokens = properties[key].split(":"); 45436 let min = 0; 45437 let max; 45438 45439 if (tokens.length == 1) { 45440 max = Number(tokens[0]); 45441 } else if (tokens.length == 2) { 45442 min = Number(tokens[0]); 45443 max = Number(tokens[1]); 45444 } 45445 45446 tracklineConfg.autoscale = false; 45447 tracklineConfg.dataRange = { 45448 min, 45449 max 45450 }; 45451 } 45452 45453 case "name": 45454 tracklineConfg[key] = properties[key]; 45455 break; 45456 45457 case "url": 45458 tracklineConfg["infoURL"] = properties[key]; 45459 break; 45460 45461 case "type": 45462 const v = properties[key]; 45463 45464 if (UCSCTypeMappings.has(v)) { 45465 tracklineConfg[key] = UCSCTypeMappings.get(v); 45466 } else { 45467 tracklineConfg[key] = v; 45468 } 45469 45470 break; 45471 45472 case "graphtype": 45473 tracklineConfg["graphType"] = properties[key]; 45474 break; 45475 45476 default: 45477 tracklineConfg[key] = properties[key]; 45478 } 45479 } // Track configuration objects have precedence over track line properties in general. The "name" property 45480 // is an exception if it was derived and not explicitly entered (that is derived from the web app from filename). 45481 45482 45483 for (let key of Object.keys(tracklineConfg)) { 45484 if (!this.config.hasOwnProperty(key) || key === "name" && this.config._derivedName) { 45485 let value = tracklineConfg[key]; 45486 if ("true" === value) value = true; 45487 if ("false" === value) value = false; 45488 this[key] = value; 45489 45490 if (key === "height" && this.trackView) { 45491 try { 45492 const h = Number.parseInt(value); 45493 this.trackView.setTrackHeight(h); 45494 } catch (e) { 45495 console.error(e); 45496 } 45497 } 45498 } 45499 } 45500 } 45501 /** 45502 * Return the features clicked over. Default implementation assumes a single row of features and only considers 45503 * the genomic location. Overriden by most subclasses. 45504 * 45505 * @param clickState 45506 * @param features 45507 * @returns {[]|*[]} 45508 */ 45509 45510 45511 clickedFeatures(clickState, features) { 45512 // We use the cached features rather than method to avoid async load. If the 45513 // feature is not already loaded this won't work, but the user wouldn't be mousing over it either. 45514 if (!features) features = clickState.viewport.getCachedFeatures(); 45515 45516 if (!features || features.length === 0) { 45517 return []; 45518 } 45519 45520 const genomicLocation = clickState.genomicLocation; // When zoomed out we need some tolerance around genomicLocation 45521 45522 const tolerance = clickState.referenceFrame.bpPerPixel > 0.2 ? 3 * clickState.referenceFrame.bpPerPixel : 0.2; 45523 const ss = genomicLocation - tolerance; 45524 const ee = genomicLocation + tolerance; 45525 return FeatureUtils.findOverlapping(features, ss, ee); 45526 } 45527 /** 45528 * Default popup text function -- just extracts string and number properties in random order. 45529 * @param feature 45530 * @returns {Array} 45531 */ 45532 45533 45534 extractPopupData(feature, genomeId) { 45535 const filteredProperties = new Set(['row', 'color', 'chr', 'start', 'end', 'cdStart', 'cdEnd', 'strand', 'alpha']); 45536 const data = []; 45537 let alleles, alleleFreqs; 45538 45539 for (let property in feature) { 45540 if (feature.hasOwnProperty(property) && !filteredProperties.has(property) && isSimpleType(feature[property])) { 45541 let value = feature[property]; 45542 data.push({ 45543 name: capitalize(property), 45544 value: value 45545 }); 45546 45547 if (property === "alleles") { 45548 alleles = feature[property]; 45549 } else if (property === "alleleFreqs") { 45550 alleleFreqs = feature[property]; 45551 } 45552 } 45553 } 45554 45555 if (alleles && alleleFreqs) { 45556 if (alleles.endsWith(",")) { 45557 alleles = alleles.substr(0, alleles.length - 1); 45558 } 45559 45560 if (alleleFreqs.endsWith(",")) { 45561 alleleFreqs = alleleFreqs.substr(0, alleleFreqs.length - 1); 45562 } 45563 45564 let a = alleles.split(","); 45565 let af = alleleFreqs.split(","); 45566 45567 if (af.length > 1) { 45568 let b = []; 45569 45570 for (let i = 0; i < af.length; i++) { 45571 b.push({ 45572 a: a[i], 45573 af: Number(af[i]) 45574 }); 45575 } 45576 45577 b.sort(function (x, y) { 45578 return x.af - y.af; 45579 }); 45580 let ref = b[b.length - 1].a; 45581 45582 if (ref.length === 1) { 45583 for (let i = b.length - 2; i >= 0; i--) { 45584 let alt = b[i].a; 45585 45586 if (alt.length === 1) { 45587 if (!genomeId) genomeId = this.getGenomeId(); 45588 const cravatLink = TrackBase.getCravatLink(feature.chr, feature.start + 1, ref, alt, genomeId); 45589 console.log(cravatLink); 45590 45591 if (cravatLink) { 45592 data.push('<hr/>'); 45593 data.push({ 45594 html: cravatLink 45595 }); 45596 data.push('<hr/>'); 45597 } 45598 } 45599 } 45600 } 45601 } 45602 } 45603 45604 if (feature.attributes) { 45605 for (let key of Object.keys(feature.attributes)) { 45606 data.push({ 45607 name: key, 45608 value: feature.attributes[key] 45609 }); 45610 } 45611 } // final chr position 45612 45613 45614 let posString = `${feature.chr}:${numberFormatter$1(feature.start + 1)}
45614-${numberFormatter$1(feature.end)}`; 45615 45616 if (feature.strand) { 45617 posString += ` (${feature.strand})`; 45618 } 45619 45620 data.push({ 45621 name: 'Location', 45622 value: posString 45623 }); 45624 return data; 45625 } 45626 45627 static getCravatLink(chr, position, ref, alt, genomeID) { 45628 if ("hg38" === genomeID || "GRCh38" === genomeID) { 45629 const cravatChr = chr.startsWith("chr") ? chr : "chr" + chr; 45630 return `<a target="_blank" href="https://run.opencravat.org/result/nocache/variant.html` + `?chrom=${cravatChr}&pos=${position}&ref_base=${ref}&alt_base=${alt}"><b>Cravat ${ref}->${alt}</b></a>`; 45631 } else { 45632 return undefined; 45633 } 45634 } 45635 45636 } 45637 /** 45638 * Map UCSC track line "type" setting to file format. In igv.js "type" refers to the track type, not the input file format 45639 * @type {Map<string, string>} 45640 */ 45641 45642 45643 const UCSCTypeMappings = new Map([["wiggle_0", "wig"], ["bed", "bed"], ["bigBed", "bigBed"], ["bigWig", "bigWig"]]); 45644 45645 function paintAxis(ctx, pixelWidth, pixelHeight) { 45646 var x1, 45647 x2, 45648 y1, 45649 y2, 45650 a, 45651 b, 45652 reference, 45653 shim, 45654 font = { 45655 'font': 'normal 10px Arial', 45656 'textAlign': 'right', 45657 'strokeStyle': "black" 45658 }; 45659 45660 if (undefined === this.dataRange || undefined === this.dataRange.max || undefined === this.dataRange.min) { 45661 return; 45662 } 45663 45664 IGVGraphics.fillRect(ctx, 0, 0, pixelWidth, pixelHeight, { 45665 'fillStyle': "rgb(255, 255, 255)" 45666 }); 45667 reference = 0.95 * pixelWidth; 45668 x1 = reference - 8; 45669 x2 = reference; //shim = 0.5 * 0.125; 45670 45671 shim = .01; 45672 y1 = y2 = shim * pixelHeight; 45673 a = { 45674 x: x2, 45675 y: y1 45676 }; // tick 45677 45678 IGVGraphics.strokeLine(ctx, x1, y1, x2, y2, font); 45679 IGVGraphics.fillText(ctx, prettyPrint(this.dataRange.max), x1 + 4, y1 + 12, font); //shim = 0.25 * 0.125; 45680 45681 y1 = y2 = (1.0 - shim) * pixelHeight; 45682 b = { 45683 x: x2, 45684 y: y1 45685 }; // tick 45686 45687 IGVGraphics.strokeLine(ctx, x1, y1, x2, y2, font); 45688 IGVGraphics.fillText(ctx, prettyPrint(this.dataRange.min), x1 + 4, y1 - 4, font); 45689 IGVGraphics.strokeLine(ctx, a.x, a.y, b.x, b.y, font); 45690 45691 function prettyPrint(number) { 45692 // if number >= 100, show whole number 45693 // if >= 1 show 1 significant digits 45694 // if < 1 show 2 significant digits 45695 if (number === 0) { 45696 return "0"; 45697 } else if (Math.abs(number) >= 10) { 45698 return number.toFixed(); 45699 } else if (Math.abs(number) >= 1) { 45700 return number.toFixed(1); 45701 } else { 45702 return number.toFixed(2); 45703 } 45704 } 45705 } 45706 45707 const appleCrayonRGBPalette = { 45708 cantaloupe: { 45709 r: 255, 45710 g: 206, 45711 b: 110 45712 }, 45713 honeydew: { 45714 r: 206, 45715 g: 250, 45716 b: 110 45717 }, 45718 spindrift: { 45719 r: 104, 45720 g: 251, 45721 b: 208 45722 }, 45723 sky: { 45724 r: 106, 45725 g: 207, 45726 b: 255 45727 }, 45728 lavender: { 45729 r: 210, 45730 g: 120, 45731 b: 255 45732 }, 45733 carnation: { 45734 r: 255, 45735 g: 127, 45736 b: 211 45737 }, 45738 licorice: { 45739 r: 0, 45740 g: 0, 45741 b: 0 45742 }, 45743 snow: { 45744 r: 255, 45745 g: 255, 45746 b: 255 45747 }, 45748 salmon: { 45749 r: 255, 45750 g: 114, 45751 b: 110 45752 }, 45753 banana: { 45754 r: 255, 45755 g: 251, 45756 b: 109 45757 }, 45758 flora: { 45759 r: 104, 45760 g: 249, 45761 b: 110 45762 }, 45763 ice: { 45764 r: 104, 45765 g: 253, 45766 b: 255 45767 }, 45768 orchid: { 45769 r: 110, 45770 g: 118, 45771 b: 255 45772 }, 45773 bubblegum: { 45774 r: 255, 45775 g: 122, 45776 b: 255 45777 }, 45778 lead: { 45779 r: 30, 45780 g: 30, 45781 b: 30 45782 }, 45783 mercury: { 45784 r: 232, 45785 g: 232, 45786 b: 232 45787 }, 45788 tangerine: { 45789 r: 255, 45790 g: 136, 45791 b: 2 45792 }, 45793 lime: { 45794 r: 131, 45795 g: 249, 45796 b: 2 45797 }, 45798 sea_foam: { 45799 r: 3, 45800 g: 249, 45801 b: 135 45802 }, 45803 aqua: { 45804 r: 0, 45805 g: 140, 45806 b: 255 45807 }, 45808 grape: { 45809 r: 137, 45810 g: 49, 45811 b: 255 45812 }, 45813 strawberry: { 45814 r: 255, 45815 g: 41, 45816 b: 135 45817 }, 45818 tungsten: { 45819 r: 58, 45820 g: 58, 45821 b: 58 45822 }, 45823 silver: { 45824 r: 208, 45825 g: 208, 45826 b: 208 45827 }, 45828 maraschino: { 45829 r: 255, 45830 g: 33, 45831 b: 1 45832 }, 45833 lemon: { 45834 r: 255, 45835 g: 250, 45836 b: 3 45837 }, 45838 spring: { 45839 r: 5, 45840 g: 248, 45841 b: 2 45842 }, 45843 turquoise: { 45844 r: 0, 45845 g: 253, 45846 b: 255 45847 }, 45848 blueberry: { 45849 r: 0, 45850 g: 46, 45851 b: 255 45852 }, 45853 magenta: { 45854 r: 255, 45855 g: 57, 45856 b: 255 45857 }, 45858 iron: { 45859 r: 84, 45860 g: 84, 45861 b: 83 45862 }, 45863 magnesium: { 45864 r: 184, 45865 g: 184, 45866 b: 184 45867 }, 45868 mocha: { 45869 r: 137, 45870 g: 72, 45871 b: 0 45872 }, 45873 fern: { 45874 r: 69, 45875 g: 132, 45876 b: 1 45877 }, 45878 moss: { 45879 r: 1, 45880 g: 132, 45881 b: 72 45882 }, 45883 ocean: { 45884 r: 0, 45885 g: 74, 45886 b: 136 45887 }, 45888 eggplant: { 45889 r: 73, 45890 g: 26, 45891 b: 136 45892 }, 45893 maroon: { 45894 r: 137, 45895 g: 22, 45896 b: 72 45897 }, 45898 steel: { 45899 r: 110, 45900 g: 110, 45901 b: 110 45902 }, 45903 aluminum: { 45904 r: 160,
45905 g: 159, 45906 b: 160 45907 }, 45908 cayenne: { 45909 r: 137, 45910 g: 17, 45911 b: 0 45912 }, 45913 aspargus: { 45914 r: 136, 45915 g: 133, 45916 b: 1 45917 }, 45918 clover: { 45919 r: 2, 45920 g: 132, 45921 b: 1 45922 }, 45923 teal: { 45924 r: 0, 45925 g: 134, 45926 b: 136 45927 }, 45928 midnight: { 45929 r: 0, 45930 g: 24, 45931 b: 136 45932 }, 45933 plum: { 45934 r: 137, 45935 g: 30, 45936 b: 136 45937 }, 45938 tin: { 45939 r: 135, 45940 g: 134, 45941 b: 135 45942 }, 45943 nickel: { 45944 r: 136, 45945 g: 135, 45946 b: 135 45947 } 45948 }; 45949 45950 function appleCrayonRGB(name) { 45951 const { 45952 r, 45953 g, 45954 b 45955 } = appleCrayonRGBPalette[name]; 45956 return `rgb(${r},${g},${b})`; 45957 } 45958 45959 const colorPalettes = { 45960 Set1: ["rgb(228,26,28)", "rgb(55,126,184)", "rgb(77,175,74)", "rgb(166,86,40)", "rgb(152,78,163)", "rgb(255,127,0)", "rgb(247,129,191)", "rgb(153,153,153)", "rgb(255,255,51)"], 45961 Dark2: ["rgb(27,158,119)", "rgb(217,95,2)", "rgb(117,112,179)", "rgb(231,41,138)", "rgb(102,166,30)", "rgb(230,171,2)", "rgb(166,118,29)", "rgb(102,102,102)"], 45962 Set2: ["rgb(102, 194,165)", "rgb(252,141,98)", "rgb(141,160,203)", "rgb(231,138,195)", "rgb(166,216,84)", "rgb(255,217,47)", "rgb(229,196,148)", "rgb(179,179,179)"], 45963 Set3: ["rgb(141,211,199)", "rgb(255,255,179)", "rgb(190,186,218)", "rgb(251,128,114)", "rgb(128,177,211)", "rgb(253,180,98)", "rgb(179,222,105)", "rgb(252,205,229)", "rgb(217,217,217)", "rgb(188,128,189)", "rgb(204,235,197)", "rgb(255,237,111)"], 45964 Pastel1: ["rgb(251,180,174)", "rgb(179,205,227)", "rgb(204,235,197)", "rgb(222,203,228)", "rgb(254,217,166)", "rgb(255,255,204)", "rgb(229,216,189)", "rgb(253,218,236)"], 45965 Pastel2: ["rgb(173,226,207)", "rgb(253,205,172)", "rgb(203,213,232)", "rgb(244,202,228)", "rgb(230,245,201)", "rgb(255,242,174)", "rgb(243,225,206)"], 45966 Accent: ["rgb(127,201,127)", "rgb(190,174,212)", "rgb(253,192,134)", "rgb(255,255,153)", "rgb(56,108,176)", "rgb(240,2,127)", "rgb(191,91,23)"] 45967 }; 45968 45969 class PaletteColorTable { 45970 constructor(palette) { 45971 this.colors = colorPalettes[palette]; 45972 if (!Array.isArray(this.colors)) this.colors = []; 45973 this.colorTable = {}; 45974 this.nextIdx = 0; 45975 this.colorGenerator = new RandomColorGenerator(); 45976 } 45977 45978 getColor(key) { 45979 if (!this.colorTable.hasOwnProperty(key)) { 45980 if (this.nextIdx < this.colors.length) { 45981 this.colorTable[key] = this.colors[this.nextIdx]; 45982 } else { 45983 this.colorTable[key] = this.colorGenerator.get(); 45984 } 45985 45986 this.nextIdx++; 45987 } 45988 45989 return this.colorTable[key]; 45990 } 45991 45992 } 45993 45994 class ColorTable { 45995 constructor(colors) { 45996 this.colorTable = colors || {}; 45997 this.nextIdx = 0; 45998 this.colorGenerator = new RandomColorGenerator(); 45999 } 46000 46001 getColor(key) { 46002 if (!this.colorTable.hasOwnProperty(key)) { 46003 if (this.colorTable.hasOwnProperty("*")) { 46004 return this.colorTable["*"]; 46005 } 46006 46007 this.colorTable[key] = this.colorGenerator.get(); 46008 } 46009 46010 return this.colorTable[key]; 46011 } 46012 46013 } // Random color generator from https://github.com/sterlingwes/RandomColor/blob/master/rcolor.js 46014 // Free to use & distribute under the MIT license 46015 // Wes Johnson (@SterlingWes) 46016 // 46017 // inspired by http://martin.ankerl.com/2009/12/09/how-to-create-random-colors-programmatically/ 46018 46019 46020 function RandomColorGenerator() { 46021 this.hue = Math.random(); 46022 this.goldenRatio = 0.618033988749895; 46023 this.hexwidth = 2; 46024 } 46025 46026 RandomColorGenerator.prototype.hsvToRgb = function (h, s, v) { 46027 var h_i = Math.floor(h * 6), 46028 f = h * 6 - h_i, 46029 p = v * (1 - s), 46030 q = v * (1 - f * s), 46031 t = v * (1 - (1 - f) * s), 46032 r = 255, 46033 g = 255, 46034 b = 255; 46035 46036 switch (h_i) { 46037 case 0: 46038 r = v, g = t, b = p; 46039 break; 46040 46041 case 1: 46042 r = q, g = v, b = p; 46043 break; 46044 46045 case 2: 46046 r = p, g = v, b = t; 46047 break; 46048 46049 case 3: 46050 r = p, g = q, b = v; 46051 break; 46052 46053 case 4: 46054 r = t, g = p, b = v; 46055 break; 46056 46057 case 5: 46058 r = v, g = p, b = q; 46059 break; 46060 } 46061 46062 return [Math.floor(r * 256), Math.floor(g * 256), Math.floor(b * 256)]; 46063 }; 46064 46065 RandomColorGenerator.prototype.padHex = function (str) { 46066 if (str.length > this.hexwidth) return str; 46067 return new Array(this.hexwidth - str.length + 1).join('0') + str; 46068 }; 46069 46070 RandomColorGenerator.prototype.get = function (saturation, value) { 46071 this.hue += this.goldenRatio; 46072 this.hue %= 1; 46073 if (typeof saturation !== "number") saturation = 0.5;
46074 if (typeof value !== "number") value = 0.95; 46075 var rgb = this.hsvToRgb(this.hue, saturation, value); 46076 return "#" + this.padHex(rgb[0].toString(16)) + this.padHex(rgb[1].toString(16)) + this.padHex(rgb[2].toString(16)); 46077 }; 46078 46079 const randomColorGenerator = new RandomColorGenerator(); 46080 46081 function randomColor() { 46082 return randomColorGenerator.get(); 46083 } // Returns a random number between min (inclusive) and max (exclusive) 46084 46085 class Locus { 46086 constructor(_ref) { 46087 let { 46088 chr, 46089 start, 46090 end 46091 } = _ref; 46092 this.chr = chr; 46093 this.start = start; 46094 this.end = end; 46095 } 46096 46097 contains(locus) { 46098 return locus.chr === this.chr && locus.start >= this.start && locus.end <= this.end; 46099 } 46100 46101 overlaps(locus) { 46102 return locus.chr === this.chr && !(locus.end < this.start || locus.start > this.end); 46103 } 46104 46105 extend(l) { 46106 if (l.chr !== this.chr) return; 46107 this.start = Math.min(l.start, this.start); 46108 this.end = Math.max(l.end, this.end); 46109 } 46110 46111 getLocusString() { 46112 if ('all' === this.chr) { 46113 return 'all'; 46114 } else { 46115 const ss = numberFormatter$1(Math.floor(this.start) + 1); 46116 const ee = numberFormatter$1(Math.round(this.end)); 46117 return `${this.chr}:${ss}-${ee}`; 46118 } 46119 } 46120 46121 static fromLocusString(str) { 46122 if ('all' === str) { 46123 return new Locus({ 46124 chr: 'all' 46125 }); 46126 } 46127 46128 const parts = str.split(':'); 46129 const chr = parts[0]; 46130 const se = parts[1].split("-"); 46131 const start = Number.parseInt(se[0].replace(/,/g, "")) - 1; 46132 const end = Number.parseInt(se[1].replace(/,/g, "")); 46133 return new Locus({ 46134 chr, 46135 start, 46136 end 46137 }); 46138 } 46139 46140 } 46141 46142 /*! 46143 * vanilla-picker v2.12.1 46144 * https://vanilla-picker.js.org 46145 * 46146 * Copyright 2017-2021 Andreas Borgen (https://github.com/Sphinxxxx), Adam Brooks (https://github.com/dissimulate) 46147 * Released under the ISC license. 46148 */ 46149 var classCallCheck = function (instance, Constructor) { 46150 if (!(instance instanceof Constructor)) { 46151 throw new TypeError("Cannot call a class as a function"); 46152 } 46153 }; 46154 46155 var createClass = function () { 46156 function defineProperties(target, props) { 46157 for (var i = 0; i < props.length; i++) { 46158 var descriptor = props[i]; 46159 descriptor.enumerable = descriptor.enumerable || false; 46160 descriptor.configurable = true; 46161 if ("value" in descriptor) descriptor.writable = true; 46162 Object.defineProperty(target, descriptor.key, descriptor); 46163 } 46164 } 46165 46166 return function (Constructor, protoProps, staticProps) { 46167 if (protoProps) defineProperties(Constructor.prototype, protoProps); 46168 if (staticProps) defineProperties(Constructor, staticProps); 46169 return Constructor; 46170 }; 46171 }(); 46172 46173 var slicedToArray = function () { 46174 function sliceIterator(arr, i) { 46175 var _arr = []; 46176 var _n = true; 46177 var _d = false; 46178 var _e = undefined; 46179 46180 try { 46181 for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { 46182 _arr.push(_s.value); 46183 46184 if (i && _arr.length === i) break; 46185 } 46186 } catch (err) { 46187 _d = true; 46188 _e = err; 46189 } finally { 46190 try { 46191 if (!_n && _i["return"]) _i["return"](); 46192 } finally { 46193 if (_d) throw _e; 46194 } 46195 } 46196 46197 return _arr; 46198 } 46199 46200 return function (arr, i) { 46201 if (Array.isArray(arr)) { 46202 return arr; 46203 } else if (Symbol.iterator in Object(arr)) { 46204 return sliceIterator(arr, i); 46205 } else { 46206 throw new TypeError("Invalid attempt to destructure non-iterable instance"); 46207 } 46208 }; 46209 }(); 46210 46211 String.prototype.startsWith = String.prototype.startsWith || function (needle) { 46212 return this.indexOf(needle) === 0; 46213 }; 46214 46215 String.prototype.padStart = String.prototype.padStart || function (len, pad) { 46216 var str = this; 46217 46218 while (str.length < len) { 46219 str = pad + str; 46220 } 46221 46222 return str; 46223 }; 46224 46225 var colorNames = { 46226 cb: '0f8ff', 46227 tqw: 'aebd7', 46228 q: '-ffff', 46229 qmrn: '7fffd4', 46230 zr: '0ffff', 46231 bg: '5f5dc', 46232 bsq: 'e4c4', 46233 bck: '---', 46234 nch: 'ebcd', 46235 b: '--ff', 46236 bvt: '8a2be2', 46237 brwn: 'a52a2a', 46238 brw: 'deb887', 46239 ctb: '5f9ea0', 46240 hrt: '7fff-', 46241 chcT: 'd2691e', 46242 cr: '7f50', 46243 rnw: '6495ed', 46244 crns: '8dc', 46245 crms: 'dc143c', 46246 cn: '-ffff', 46247 Db: '--8b', 46248 Dcn: '-8b8b', 46249 Dgnr: 'b8860b', 46250 Dgr: 'a9a9a9', 46251 Dgrn: '-64-', 46252 Dkhk: 'bdb76b', 46253 Dmgn: '8b-8b', 46254 Dvgr: '556b2f', 46255 Drng: '8c-', 46256 Drch: '9932cc', 46257 Dr: '8b--', 46258 Dsmn: 'e9967a', 46259 Dsgr: '8fbc8f', 46260 DsTb: '483d8b', 46261 DsTg: '2f4f4f', 46262 Dtrq: '-ced1', 46263 Dvt: '94-d3',
46264 ppnk: '1493', 46265 pskb: '-bfff', 46266 mgr: '696969', 46267 grb: '1e90ff', 46268 rbrc: 'b22222', 46269 rwht: 'af0', 46270 stg: '228b22', 46271 chs: '-ff', 46272 gnsb: 'dcdcdc', 46273 st: '8f8ff', 46274 g: 'd7-', 46275 gnr: 'daa520', 46276 gr: '808080', 46277 grn: '-8-0', 46278 grnw: 'adff2f', 46279 hnw: '0fff0', 46280 htpn: '69b4', 46281 nnr: 'cd5c5c', 46282 ng: '4b-82', 46283 vr: '0', 46284 khk: '0e68c', 46285 vnr: 'e6e6fa', 46286 nrb: '0f5', 46287 wngr: '7cfc-', 46288 mnch: 'acd', 46289 Lb: 'add8e6', 46290 Lcr: '08080', 46291 Lcn: 'e0ffff', 46292 Lgnr: 'afad2', 46293 Lgr: 'd3d3d3', 46294 Lgrn: '90ee90', 46295 Lpnk: 'b6c1', 46296 Lsmn: 'a07a', 46297 Lsgr: '20b2aa', 46298 Lskb: '87cefa', 46299 LsTg: '778899', 46300 Lstb: 'b0c4de', 46301 Lw: 'e0', 46302 m: '-ff-', 46303 mgrn: '32cd32', 46304 nn: 'af0e6', 46305 mgnt: '-ff', 46306 mrn: '8--0', 46307 mqm: '66cdaa', 46308 mmb: '--cd', 46309 mmrc: 'ba55d3', 46310 mmpr: '9370db', 46311 msg: '3cb371', 46312 mmsT: '7b68ee', 46313 '': '-fa9a', 46314 mtr: '48d1cc', 46315 mmvt: 'c71585', 46316 mnLb: '191970', 46317 ntc: '5fffa', 46318 mstr: 'e4e1', 46319 mccs: 'e4b5', 46320 vjw: 'dead', 46321 nv: '--80', 46322 c: 'df5e6', 46323 v: '808-0', 46324 vrb: '6b8e23', 46325 rng: 'a5-', 46326 rngr: '45-', 46327 rch: 'da70d6', 46328 pgnr: 'eee8aa', 46329 pgrn: '98fb98', 46330 ptrq: 'afeeee', 46331 pvtr: 'db7093', 46332 ppwh: 'efd5', 46333 pchp: 'dab9', 46334 pr: 'cd853f', 46335 pnk: 'c0cb', 46336 pm: 'dda0dd', 46337 pwrb: 'b0e0e6', 46338 prp: '8-080', 46339 cc: '663399', 46340 r: '--', 46341 sbr: 'bc8f8f', 46342 rb: '4169e1', 46343 sbrw: '8b4513', 46344 smn: 'a8072', 46345 nbr: '4a460', 46346 sgrn: '2e8b57', 46347 ssh: '5ee', 46348 snn: 'a0522d', 46349 svr: 'c0c0c0', 46350 skb: '87ceeb', 46351 sTb: '6a5acd', 46352 sTgr: '708090', 46353 snw: 'afa', 46354 n: '-ff7f', 46355 stb: '4682b4', 46356 tn: 'd2b48c', 46357 t: '-8080', 46358 thst: 'd8bfd8', 46359 tmT: '6347', 46360 trqs: '40e0d0', 46361 vt: 'ee82ee', 46362 whT: '5deb3', 46363 wht: '', 46364 hts: '5f5f5', 46365 w: '-', 46366 wgrn: '9acd32' 46367 }; 46368 46369 function printNum(num) { 46370 var decs = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1; 46371 var str = decs > 0 ? num.toFixed(decs).replace(/0+$/, '').replace(/\.$/, '') : num.toString(); 46372 return str || '0'; 46373 } 46374 46375 var Color = function () { 46376 function Color(r, g, b, a) { 46377 classCallCheck(this, Color); 46378 var that = this; 46379 46380 function parseString(input) { 46381 if (input.startsWith('hsl')) { 46382 var _input$match$map = input.match(/([\-\d\.e]+)/g).map(Number), 46383 _input$match$map2 = slicedToArray(_input$match$map, 4), 46384 h = _input$match$map2[0], 46385 s = _input$match$map2[1], 46386 l = _input$match$map2[2], 46387 _a = _input$match$map2[3]; 46388 46389 if (_a === undefined) { 46390 _a = 1; 46391 } 46392 46393 h /= 360; 46394 s /= 100; 46395 l /= 100; 46396 that.hsla = [h, s, l, _a]; 46397 } else if (input.startsWith('rgb')) { 46398 var _input$match$map3 = input.match(/([\-\d\.e]+)/g).map(Number), 46399 _input$match$map4 = slicedToArray(_input$match$map3, 4), 46400 _r = _input$match$map4[0], 46401 _g = _input$match$map4[1], 46402 _b = _input$match$map4[2], 46403 _a2 = _input$match$map4[3]; 46404 46405 if (_a2 === undefined) { 46406 _a2 = 1; 46407 } 46408 46409 that.rgba = [_r, _g, _b, _a2]; 46410 } else { 46411 if (input.startsWith('#')) { 46412 that.rgba = Color.hexToRgb(input); 46413 } else { 46414 that.rgba = Color.nameToRgb(input) || Color.hexToRgb(input); 46415 } 46416 } 46417 } 46418 46419 if (r === undefined) ;else if (Array.isArray(r)) { 46420 this.rgba = r; 46421 } else if (b === undefined) { 46422 var color = r && '' + r; 46423 46424 if (color) { 46425 parseString(color.toLowerCase()); 46426 } 46427 } else { 46428 this.rgba = [r, g, b, a === undefined ? 1 : a]; 46429 } 46430 } 46431 46432 createClass(Color, [{ 46433 key: 'printRGB', 46434 value: function printRGB(alpha) { 46435 var rgb = alpha ? this.rgba : this.rgba.slice(0, 3), 46436 vals = rgb.map(function (x, i) {
46437 return printNum(x, i === 3 ? 3 : 0); 46438 }); 46439 return alpha ? 'rgba(' + vals + ')' : 'rgb(' + vals + ')'; 46440 } 46441 }, { 46442 key: 'printHSL', 46443 value: function printHSL(alpha) { 46444 var mults = [360, 100, 100, 1], 46445 suff = ['', '%', '%', '']; 46446 var hsl = alpha ? this.hsla : this.hsla.slice(0, 3), 46447 vals = hsl.map(function (x, i) { 46448 return printNum(x * mults[i], i === 3 ? 3 : 1) + suff[i]; 46449 }); 46450 return alpha ? 'hsla(' + vals + ')' : 'hsl(' + vals + ')'; 46451 } 46452 }, { 46453 key: 'printHex', 46454 value: function printHex(alpha) { 46455 var hex = this.hex; 46456 return alpha ? hex : hex.substring(0, 7); 46457 } 46458 }, { 46459 key: 'rgba', 46460 get: function get() { 46461 if (this._rgba) { 46462 return this._rgba; 46463 } 46464 46465 if (!this._hsla) { 46466 throw new Error('No color is set'); 46467 } 46468 46469 return this._rgba = Color.hslToRgb(this._hsla); 46470 }, 46471 set: function set(rgb) { 46472 if (rgb.length === 3) { 46473 rgb[3] = 1; 46474 } 46475 46476 this._rgba = rgb; 46477 this._hsla = null; 46478 } 46479 }, { 46480 key: 'rgbString', 46481 get: function get() { 46482 return this.printRGB(); 46483 } 46484 }, { 46485 key: 'rgbaString', 46486 get: function get() { 46487 return this.printRGB(true); 46488 } 46489 }, { 46490 key: 'hsla', 46491 get: function get() { 46492 if (this._hsla) { 46493 return this._hsla; 46494 } 46495 46496 if (!this._rgba) { 46497 throw new Error('No color is set'); 46498 } 46499 46500 return this._hsla = Color.rgbToHsl(this._rgba); 46501 }, 46502 set: function set(hsl) { 46503 if (hsl.length === 3) { 46504 hsl[3] = 1; 46505 } 46506 46507 this._hsla = hsl; 46508 this._rgba = null; 46509 } 46510 }, { 46511 key: 'hslString', 46512 get: function get() { 46513 return this.printHSL(); 46514 } 46515 }, { 46516 key: 'hslaString', 46517 get: function get() { 46518 return this.printHSL(true); 46519 } 46520 }, { 46521 key: 'hex', 46522 get: function get() { 46523 var rgb = this.rgba, 46524 hex = rgb.map(function (x, i) { 46525 return i < 3 ? x.toString(16) : Math.round(x * 255).toString(16); 46526 }); 46527 return '#' + hex.map(function (x) { 46528 return x.padStart(2, '0'); 46529 }).join(''); 46530 }, 46531 set: function set(hex) { 46532 this.rgba = Color.hexToRgb(hex); 46533 } 46534 }], [{ 46535 key: 'hexToRgb', 46536 value: function hexToRgb(input) { 46537 var hex = (input.startsWith('#') ? input.slice(1) : input).replace(/^(\w{3})$/, '$1F').replace(/^(\w)(\w)(\w)(\w)$/, '$1$1$2$2$3$3$4$4').replace(/^(\w{6})$/, '$1FF'); 46538 46539 if (!hex.match(/^([0-9a-fA-F]{8})$/)) { 46540 throw new Error('Unknown hex color; ' + input); 46541 } 46542 46543 var rgba = hex.match(/^(\w\w)(\w\w)(\w\w)(\w\w)$/).slice(1).map(function (x) { 46544 return parseInt(x, 16); 46545 }); 46546 rgba[3] = rgba[3] / 255; 46547 return rgba; 46548 } 46549 }, { 46550 key: 'nameToRgb', 46551 value: function nameToRgb(input) { 46552 var hash = input.toLowerCase().replace('at', 'T').replace(/[aeiouyldf]/g, '').replace('ght', 'L').replace('rk', 'D').slice(-5, 4), 46553 hex = colorNames[hash]; 46554 return hex === undefined ? hex : Color.hexToRgb(hex.replace(/\-/g, '00').padStart(6, 'f')); 46555 } 46556 }, { 46557 key: 'rgbToHsl', 46558 value: function rgbToHsl(_ref) { 46559 var _ref2 = slicedToArray(_ref, 4), 46560 r = _ref2[0], 46561 g = _ref2[1], 46562 b = _ref2[2], 46563 a = _ref2[3]; 46564 46565 r /= 255; 46566 g /= 255; 46567 b /= 255; 46568 var max = Math.max(r, g, b), 46569 min = Math.min(r, g, b); 46570 var h = void 0, 46571 s = void 0, 46572 l = (max + min) / 2; 46573 46574 if (max === min) { 46575 h = s = 0; 46576 } else { 46577 var d = max - min; 46578 s = l > 0.5 ? d / (2 - max - min) : d / (max + min); 46579 46580 switch (max) { 46581 case r: 46582 h = (g - b) / d + (g < b ? 6 : 0); 46583 break; 46584 46585 case g: 46586 h = (b - r) / d + 2; 46587 break; 46588 46589 case b: 46590 h = (r - g) / d + 4; 46591 break; 46592 } 46593 46594 h /= 6; 46595 } 46596 46597 return [h, s, l, a]; 46598 } 46599 }, { 46600 key: 'hslToRgb', 46601 value: function hslToRgb(_ref3) { 46602 var _ref4 = slicedToArray(_ref3, 4), 46603 h = _ref4[0], 46604 s = _ref4[1], 46605 l = _ref4[2], 46606 a = _ref4[3]; 46607 46608 var r = void 0, 46609 g = void 0, 46610 b = void 0; 46611 46612 if (s === 0) { 46613 r = g = b = l; 46614 } else { 46615 var hue2rgb = function hue2rgb(p, q, t) { 46616 if (t < 0) t += 1; 46617 if (t > 1) t -= 1; 46618 if (t < 1 / 6) return p + (q - p) * 6 * t; 46619 if (t < 1 / 2) return q; 46620 if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6; 46621 return p; 46622 }; 46623 46624 var q = l < 0.5 ? l * (1 + s) : l + s - l * s, 46625 p = 2 * l - q; 46626 r = hue2rgb(p, q, h + 1 / 3); 46627 g = hue2rgb(p, q, h); 46628 b = hue2rgb(p, q, h - 1 / 3); 46629 } 46630 46631 var rgba = [r * 255, g * 255, b * 255].map(Math.round); 46632 rgba[3] = a; 46633 return rgba; 46634 } 46635 }]); 46636 return Color; 46637 }(); 46638 46639 var EventBucket = function () { 46640 function EventBucket() { 46641 classCallCheck(this, EventBucket); 46642 this._events = []; 46643 } 46644 46645 createClass(EventBucket, [{ 46646 key: 'add', 46647 value: function add(target, type, handler) { 46648 target.addEventListener(type, handler, false); 46649 46650 this._events.push({ 46651 target: target, 46652 type: type, 46653 handler: handler 46654 }); 46655 } 46656 }, { 46657 key: 'remove', 46658 value: function remove(target, type, handler) { 46659 this._events = this._events.filter(function (e) { 46660 var isMatch = true; 46661 46662 if (target && target !== e.target) { 46663 isMatch = false;
46664 } 46665 46666 if (type && type !== e.type) { 46667 isMatch = false; 46668 } 46669 46670 if (handler && handler !== e.handler) { 46671 isMatch = false; 46672 } 46673 46674 if (isMatch) { 46675 EventBucket._doRemove(e.target, e.type, e.handler); 46676 } 46677 46678 return !isMatch; 46679 }); 46680 } 46681 }, { 46682 key: 'destroy', 46683 value: function destroy() { 46684 this._events.forEach(function (e) { 46685 return EventBucket._doRemove(e.target, e.type, e.handler); 46686 }); 46687 46688 this._events = []; 46689 } 46690 }], [{ 46691 key: '_doRemove', 46692 value: function _doRemove(target, type, handler) { 46693 target.removeEventListener(type, handler, false); 46694 } 46695 }]); 46696 return EventBucket; 46697 }(); 46698 46699 function parseHTML(htmlString) { 46700 var div = document.createElement('div'); 46701 div.innerHTML = htmlString; 46702 return div.firstElementChild; 46703 } 46704 46705 function dragTrack(eventBucket, area, callback) { 46706 var dragging = false; 46707 46708 function clamp(val, min, max) { 46709 return Math.max(min, Math.min(val, max)); 46710 } 46711 46712 function onMove(e, info, starting) { 46713 if (starting) { 46714 dragging = true; 46715 } 46716 46717 if (!dragging) { 46718 return; 46719 } 46720 46721 e.preventDefault(); 46722 var bounds = area.getBoundingClientRect(), 46723 w = bounds.width, 46724 h = bounds.height, 46725 x = info.clientX, 46726 y = info.clientY; 46727 var relX = clamp(x - bounds.left, 0, w), 46728 relY = clamp(y - bounds.top, 0, h); 46729 callback(relX / w, relY / h); 46730 } 46731 46732 function onMouse(e, starting) { 46733 var button = e.buttons === undefined ? e.which : e.buttons; 46734 46735 if (button === 1) { 46736 onMove(e, e, starting); 46737 } else { 46738 dragging = false; 46739 } 46740 } 46741 46742 function onTouch(e, starting) { 46743 if (e.touches.length === 1) { 46744 onMove(e, e.touches[0], starting); 46745 } else { 46746 dragging = false; 46747 } 46748 } 46749 46750 eventBucket.add(area, 'mousedown', function (e) { 46751 onMouse(e, true); 46752 }); 46753 eventBucket.add(area, 'touchstart', function (e) { 46754 onTouch(e, true); 46755 }); 46756 eventBucket.add(window, 'mousemove', onMouse); 46757 eventBucket.add(area, 'touchmove', onTouch); 46758 eventBucket.add(window, 'mouseup', function (e) { 46759 dragging = false; 46760 }); 46761 eventBucket.add(area, 'touchend', function (e) { 46762 dragging = false; 46763 }); 46764 eventBucket.add(area, 'touchcancel', function (e) { 46765 dragging = false; 46766 }); 46767 } 46768 46769 var BG_TRANSP = 'linear-gradient(45deg, lightgrey 25%, transparent 25%, transparent 75%, lightgrey 75%) 0 0 / 2em 2em,\n linear-gradient(45deg, lightgrey 25%, white 25%, white 75%, lightgrey 75%) 1em 1em / 2em 2em'; 46770 var HUES = 360; 46771 var EVENT_KEY = 'keydown', 46772 EVENT_CLICK_OUTSIDE = 'mousedown', 46773 EVENT_TAB_MOVE = 'focusin'; 46774 46775 function $(selector, context) { 46776 return (context || document).querySelector(selector); 46777 } 46778 46779 function stopEvent(e) { 46780 e.preventDefault(); 46781 e.stopPropagation(); 46782 } 46783 46784 function onKey(bucket, target, keys, handler, stop) { 46785 bucket.add(target, EVENT_KEY, function (e) { 46786 if (keys.indexOf(e.key) >= 0) { 46787 if (stop) { 46788 stopEvent(e); 46789 } 46790 46791 handler(e); 46792 } 46793 }); 46794 } 46795 46796 var Picker = function () { 46797 function Picker(options) { 46798 classCallCheck(this, Picker); 46799 this.settings = { 46800 popup: 'right', 46801 layout: 'default', 46802 alpha: true, 46803 editor: true, 46804 editorFormat: 'hex',
46805 cancelButton: false, 46806 defaultColor: '#0cf' 46807 }; 46808 this._events = new EventBucket(); 46809 this.onChange = null; 46810 this.onDone = null; 46811 this.onOpen = null; 46812 this.onClose = null; 46813 this.setOptions(options); 46814 } 46815 46816 createClass(Picker, [{ 46817 key: 'setOptions', 46818 value: function setOptions(options) { 46819 var _this = this; 46820 46821 if (!options) { 46822 return; 46823 } 46824 46825 var settings = this.settings; 46826 46827 function transfer(source, target, skipKeys) { 46828 for (var key in source) { 46829 if (skipKeys && skipKeys.indexOf(key) >= 0) { 46830 continue; 46831 } 46832 46833 target[key] = source[key]; 46834 } 46835 } 46836 46837 if (options instanceof HTMLElement) { 46838 settings.parent = options; 46839 } else { 46840 if (settings.parent && options.parent && settings.parent !== options.parent) { 46841 this._events.remove(settings.parent); 46842 46843 this._popupInited = false; 46844 } 46845 46846 transfer(options, settings); 46847 46848 if (options.onChange) { 46849 this.onChange = options.onChange; 46850 } 46851 46852 if (options.onDone) { 46853 this.onDone = options.onDone; 46854 } 46855 46856 if (options.onOpen) { 46857 this.onOpen = options.onOpen; 46858 } 46859 46860 if (options.onClose) { 46861 this.onClose = options.onClose; 46862 } 46863 46864 var col = options.color || options.colour; 46865 46866 if (col) { 46867 this._setColor(col); 46868 } 46869 } 46870 46871 var parent = settings.parent; 46872 46873 if (parent && settings.popup && !this._popupInited) { 46874 var openProxy = function openProxy(e) { 46875 return _this.openHandler(e); 46876 }; 46877 46878 this._events.add(parent, 'click', openProxy); 46879 46880 onKey(this._events, parent, [' ', 'Spacebar', 'Enter'], openProxy); 46881 this._popupInited = true; 46882 } else if (options.parent && !settings.popup) { 46883 this.show(); 46884 } 46885 } 46886 }, { 46887 key: 'openHandler', 46888 value: function openHandler(e) { 46889 if (this.show()) { 46890 e && e.preventDefault(); 46891 this.settings.parent.style.pointerEvents = 'none'; 46892 var toFocus = e && e.type === EVENT_KEY ? this._domEdit : this.domElement; 46893 setTimeout(function () { 46894 return toFocus.focus(); 46895 }, 100); 46896 46897 if (this.onOpen) { 46898 this.onOpen(this.colour); 46899 } 46900 } 46901 } 46902 }, { 46903 key: 'closeHandler', 46904 value: function closeHandler(e) { 46905 var event = e && e.type; 46906 var doHide = false;
46907 46908 if (!e) { 46909 doHide = true; 46910 } else if (event === EVENT_CLICK_OUTSIDE || event === EVENT_TAB_MOVE) { 46911 var knownTime = (this.__containedEvent || 0) + 100; 46912 46913 if (e.timeStamp > knownTime) { 46914 doHide = true; 46915 } 46916 } else { 46917 stopEvent(e); 46918 doHide = true; 46919 } 46920 46921 if (doHide && this.hide()) { 46922 this.settings.parent.style.pointerEvents = ''; 46923 46924 if (event !== EVENT_CLICK_OUTSIDE) { 46925 this.settings.parent.focus(); 46926 } 46927 46928 if (this.onClose) { 46929 this.onClose(this.colour); 46930 } 46931 } 46932 } 46933 }, { 46934 key: 'movePopup', 46935 value: function movePopup(options, open) { 46936 this.closeHandler(); 46937 this.setOptions(options); 46938 46939 if (open) { 46940 this.openHandler(); 46941 } 46942 } 46943 }, { 46944 key: 'setColor', 46945 value: function setColor(color, silent) { 46946 this._setColor(color, { 46947 silent: silent 46948 }); 46949 } 46950 }, { 46951 key: '_setColor', 46952 value: function _setColor(color, flags) { 46953 if (typeof color === 'string') { 46954 color = color.trim(); 46955 } 46956 46957 if (!color) { 46958 return; 46959 } 46960 46961 flags = flags || {}; 46962 var c = void 0; 46963 46964 try { 46965 c = new Color(color); 46966 } catch (ex) { 46967 if (flags.failSilently) { 46968 return; 46969 } 46970 46971 throw ex; 46972 } 46973 46974 if (!this.settings.alpha) { 46975 var hsla = c.hsla; 46976 hsla[3] = 1; 46977 c.hsla = hsla; 46978 } 46979 46980 this.colour = this.color = c; 46981 46982 this._setHSLA(null, null, null, null, flags); 46983 } 46984 }, { 46985 key: 'setColour', 46986 value: function setColour(colour, silent) { 46987 this.setColor(colour, silent); 46988 } 46989 }, { 46990 key: 'show', 46991 value: function show() { 46992 var parent = this.settings.parent; 46993 46994 if (!parent) { 46995 return false; 46996 } 46997 46998 if (this.domElement) { 46999 var toggled = this._toggleDOM(true); 47000 47001 this._setPosition(); 47002 47003 return toggled; 47004 } 47005 47006 var html = this.settings.template || '<div class="picker_wrapper" tabindex="-1"><div class="picker_arrow"></div><div class="picker_hue picker_slider"><div class="picker_selector"></div></div><div class="picker_sl"><div class="picker_selector"></div></div><div class="picker_alpha picker_slider"><div class="picker_selector"></div></div><div class="picker_editor"><input aria-label="Type a color name or hex value"/></div><div class="picker_sample"></div><div class="picker_done"><button>Ok</button></div><div class="picker_cancel"><button>Cancel</button></div></div>'; 47007 var wrapper = parseHTML(html); 47008 this.domElement = wrapper; 47009 this._domH = $('.picker_hue', wrapper); 47010 this._domSL = $('.picker_sl', wrapper); 47011 this._domA = $('.picker_alpha', wrapper); 47012 this._domEdit = $('.picker_editor input', wrapper); 47013 this._domSample = $('.picker_sample', wrapper); 47014 this._domOkay = $('.picker_done button', wrapper); 47015 this._domCancel = $('.picker_cancel button', wrapper); 47016 wrapper.classList.add('layout_' + this.settings.layout); 47017 47018 if (!this.settings.alpha) { 47019 wrapper.classList.add('no_alpha'); 47020 } 47021 47022 if (!this.settings.editor) { 47023 wrapper.classList.add('no_editor'); 47024 } 47025 47026 if (!this.settings.cancelButton) { 47027 wrapper.classList.add('no_cancel'); 47028 } 47029 47030 this._ifPopup(function () { 47031 return wrapper.classList.add('popup'); 47032 }); 47033 47034 this._setPosition(); 47035 47036 if (this.colour) { 47037 this._updateUI(); 47038 } else { 47039 this._setColor(this.settings.defaultColor); 47040 } 47041 47042 this._bindEvents(); 47043 47044 return true; 47045 } 47046 }, { 47047 key: 'hide', 47048 value: function hide() { 47049 return this._toggleDOM(false); 47050 } 47051 }, { 47052 key: 'destroy', 47053 value: function destroy() { 47054 this._events.destroy(); 47055 47056 if (this.domElement) { 47057 this.settings.parent.removeChild(this.domElement); 47058 } 47059 } 47060 }, { 47061 key: '_bindEvents', 47062 value: function _bindEvents() { 47063 var _this2 = this; 47064 47065 var that = this, 47066 dom = this.domElement, 47067 events = this._events; 47068 47069 function addEvent(target, type, handler) { 47070 events.add(target, type, handler); 47071 } 47072 47073 addEvent(dom, 'click', function (e) { 47074 return e.preventDefault(); 47075 }); 47076 dragTrack(events, this._domH, function (x, y) { 47077 return that._setHSLA(x); 47078 }); 47079 dragTrack(events, this._domSL, function (x, y) { 47080 return that._setHSLA(null, x, 1 - y); 47081 }); 47082 47083 if (this.settings.alpha) { 47084 dragTrack(events, this._domA, function (x, y) { 47085 return that._setHSLA(null, null, null, 1 - y); 47086 }); 47087 } 47088 47089 var editInput = this._domEdit; 47090 { 47091 addEvent(editInput, 'input', function (e) { 47092 that._setColor(this.value, { 47093 fromEditor: true, 47094 failSilently: true 47095 }); 47096 }); 47097 addEvent(editInput, 'focus', function (e) { 47098 var input = this; 47099 47100 if (input.selectionStart === input.selectionEnd) { 47101 input.select(); 47102 } 47103 }); 47104 } 47105 47106 this._ifPopup(function () { 47107 var popupCloseProxy = function popupCloseProxy(e) { 47108 return _this2.closeHandler(e); 47109 }; 47110 47111 addEvent(window, EVENT_CLICK_OUTSIDE, popupCloseProxy); 47112 addEvent(window, EVENT_TAB_MOVE, popupCloseProxy); 47113 onKey(events, dom, ['Esc', 'Escape'], popupCloseProxy); 47114 47115 var timeKeeper = function timeKeeper(e) { 47116 _this2.__containedEvent = e.timeStamp; 47117 }; 47118 47119 addEvent(dom, EVENT_CLICK_OUTSIDE, timeKeeper); 47120 addEvent(dom, EVENT_TAB_MOVE, timeKeeper); 47121 addEvent(_this2._domCancel, 'click', popupCloseProxy); 47122 }); 47123 47124 var onDoneProxy = function onDoneProxy(e) { 47125 _this2._ifPopup(function () { 47126 return _this2.closeHandler(e); 47127 }); 47128 47129 if (_this2.onDone) { 47130 _this2.onDone(_this2.colour); 47131 } 47132 }; 47133 47134 addEvent(this._domOkay, 'click', onDoneProxy); 47135 onKey(events, dom, ['Enter'], onDoneProxy); 47136 } 47137 }, { 47138 key: '_setPosition', 47139 value: function _setPosition() { 47140 var parent = this.settings.parent, 47141 elm = this.domElement; 47142 47143 if (parent !== elm.parentNode) { 47144 parent.appendChild(elm); 47145 } 47146 47147 this._ifPopup(function (popup) { 47148 if (getComputedStyle(parent).position === 'static') { 47149 parent.style.position = 'relative'; 47150 } 47151 47152 var cssClass = popup === true ? 'popup_right' : 'popup_' + popup; 47153 ['popup_top', 'popup_bottom', 'popup_left', 'popup_right'].forEach(function (c) { 47154 if (c === cssClass) { 47155 elm.classList.add(c); 47156 } else { 47157 elm.classList.remove(c); 47158 } 47159 }); 47160 elm.classList.add(cssClass); 47161 }); 47162 } 47163 }, { 47164 key: '_setHSLA', 47165 value: function _setHSLA(h, s, l, a, flags) { 47166 flags = flags || {}; 47167 var col = this.colour, 47168 hsla = col.hsla;
47169 [h, s, l, a].forEach(function (x, i) { 47170 if (x || x === 0) { 47171 hsla[i] = x; 47172 } 47173 }); 47174 col.hsla = hsla; 47175 47176 this._updateUI(flags); 47177 47178 if (this.onChange && !flags.silent) { 47179 this.onChange(col); 47180 } 47181 } 47182 }, { 47183 key: '_updateUI', 47184 value: function _updateUI(flags) { 47185 if (!this.domElement) { 47186 return; 47187 } 47188 47189 flags = flags || {}; 47190 var col = this.colour, 47191 hsl = col.hsla, 47192 cssHue = 'hsl(' + hsl[0] * HUES + ', 100%, 50%)', 47193 cssHSL = col.hslString, 47194 cssHSLA = col.hslaString; 47195 var uiH = this._domH, 47196 uiSL = this._domSL, 47197 uiA = this._domA, 47198 thumbH = $('.picker_selector', uiH), 47199 thumbSL = $('.picker_selector', uiSL), 47200 thumbA = $('.picker_selector', uiA); 47201 47202 function posX(parent, child, relX) { 47203 child.style.left = relX * 100 + '%'; 47204 } 47205 47206 function posY(parent, child, relY) { 47207 child.style.top = relY * 100 + '%'; 47208 } 47209 47210 posX(uiH, thumbH, hsl[0]); 47211 this._domSL.style.backgroundColor = this._domH.style.color = cssHue; 47212 posX(uiSL, thumbSL, hsl[1]); 47213 posY(uiSL, thumbSL, 1 - hsl[2]); 47214 uiSL.style.color = cssHSL; 47215 posY(uiA, thumbA, 1 - hsl[3]); 47216 var opaque = cssHSL, 47217 transp = opaque.replace('hsl', 'hsla').replace(')', ', 0)'), 47218 bg = 'linear-gradient(' + [opaque, transp] + ')'; 47219 this._domA.style.background = bg + ', ' + BG_TRANSP; 47220 47221 if (!flags.fromEditor) { 47222 var format = this.settings.editorFormat, 47223 alpha = this.settings.alpha; 47224 var value = void 0; 47225 47226 switch (format) { 47227 case 'rgb': 47228 value = col.printRGB(alpha); 47229 break; 47230 47231 case 'hsl': 47232 value = col.printHSL(alpha); 47233 break; 47234 47235 default: 47236 value = col.printHex(alpha); 47237 } 47238 47239 this._domEdit.value = value; 47240 } 47241 47242 this._domSample.style.color = cssHSLA; 47243 } 47244 }, { 47245 key: '_ifPopup', 47246 value: function _ifPopup(actionIf, actionElse) { 47247 if (this.settings.parent && this.settings.popup) { 47248 actionIf && actionIf(this.settings.popup); 47249 } else { 47250 actionElse && actionElse(); 47251 } 47252 } 47253 }, { 47254 key: '_toggleDOM', 47255 value: function _toggleDOM(toVisible) { 47256 var dom = this.domElement; 47257 47258 if (!dom) { 47259 return false; 47260 } 47261 47262 var displayStyle = toVisible ? '' : 'none', 47263 toggle = dom.style.display !== displayStyle; 47264 47265 if (toggle) { 47266 dom.style.display = displayStyle; 47267 } 47268 47269 return toggle; 47270 } 47271 }]); 47272 return Picker; 47273 }(); 47274 47275 { 47276 var style = document.createElement('style'); 47277 style.textContent = '.picker_wrapper.no_alpha .picker_alpha{display:none}.picker_wrapper.no_editor .picker_editor{position:absolute;z-index:-1;opacity:0}.picker_wrapper.no_cancel .picker_cancel{display:none}.layout_default.picker_wrapper{display:flex;flex-flow:row wrap;justify-content:space-between;align-items:stretch;font-size:10px;width:25em;padding:.5em}.layout_default.picker_wrapper input,.layout_default.picker_wrapper button{font-size:1rem}.layout_default.picker_wrapper>*{margin:.5em}.layout_default.picker_wrapper::before{content:"";display:block;width:100%;height:0;order:1}.layout_default .picker_slider,.layout_default .picker_selector{padding:1em}.layout_default .picker_hue{width:100%}.layout_default .picker_sl{flex:1 1 auto}.layout_default .picker_sl::before{content:"";display:block;padding-bottom:100%}.layout_default .picker_editor{order:1;width:6.5rem}.layout_default .picker_editor input{width:100%;height:100%}.layout_default .picker_sample{order:1;flex:1 1 auto}.layout_default .picker_done,.layout_default .picker_cancel{order:1}.picker_wrapper{box-sizing:border-box;background:#f2f2f2;box-shadow:0 0 0 1px silver;cursor:default;font-family:sans-serif;color:#444;pointer-events:auto}.picker_wrapper:focus{outline:none}.picker_wrapper button,.picker_wrapper input{box-sizing:border-box;border:none;box-shadow:0 0 0 1px silver;outline:none}.picker_wrapper button:focus,.picker_wrapper button:active,.picker_wrapper input:focus,.picker_wrapper input:active{box-shadow:0 0 2px 1px #1e90ff}.picker_wrapper button{padding:.4em .6em;cursor:pointer;background-color:#f5f5f5;background-image:linear-gradient(0deg, gainsboro, transparent)}.picker_wrapper button:active{background-image:linear-gradient(0deg, transparent, gainsboro)}.picker_wrapper button:hover{background-color:#fff}.picker_selector{position:absolute;z-index:1;display:block;-webkit-transform:translate(-50%, -50%);transform:translate(-50%, -50%);border:2px solid #fff;border-radius:100%;box-shadow:0 0 3px 1px #67b9ff;background:currentColor;cursor:pointer}.picker_slider .picker_selector{border-radius:2px}.picker_hue{position:relative;background-image:linear-gradient(90deg, red, yellow, lime, cyan, blue, magenta, red);box-shadow:0 0 0 1px silver}.picker_sl{position:relative;box-shadow:0 0 0 1px silver;background-image:linear-gradient(180deg, white, rgba(255, 255, 255, 0) 50%),linear-gradient(0deg, black, rgba(0, 0, 0, 0) 50%),linear-gradient(90deg, #808080, rgba(128, 128, 128, 0))}.picker_alpha,.picker_sample{position:relative;background:linear-gradient(45deg, lightgrey 25%, transparent 25%, transparent 75%, lightgrey 75%) 0 0/2em 2em,linear-gradient(45deg, lightgrey 25%, white 25%, white 75%, lightgrey 75%) 1em 1em/2em 2em;box-shadow:0 0 0 1px silver}.picker_alpha .picker_selector,.picker_sample .picker_selector{background:none}.picker_editor input{font-family:monospace;padding:.2em .4em}.picker_sample::before{content:"";position:absolute;display:block;width:100%;height:100%;background:currentColor}.picker_arrow{position:absolute;z-index:-1}.picker_wrapper.popup{position:absolute;z-index:2;margin:1.5em}.picker_wrapper.popup,.picker_wrapper.popup .picker_arrow::before,.picker_wrapper.popup .picker_arrow::after{background:#f2f2f2;box-shadow:0 0 10px 1px rgba(0,0,0,.4)}.picker_wrapper.popup .picker_arrow{width:3em;height:3em;margin:0}.picker_wrapper.popup .picker_arrow::before,.picker_wrapper.popup .picker_arrow::after{content:"";display:block;position:absolute;top:0;left:0;z-index:-99}.picker_wrapper.popup .picker_arrow::before{width:100%;height:100%;-webkit-transform:skew(45deg);transform:skew(45deg);-webkit-transform-origin:0 100%;transform-origin:0 100%}.picker_wrapper.popup .picker_arrow::after{width:150%;height:150%;box-shadow:none}.popup.popup_top{bottom:100%;left:0}.popup.popup_top .picker_arrow{bottom:0;left:0;-webkit-transform:rotate(-90deg);transform:rotate(-90deg)}.popup.popup_bottom{top:100%;left:0}.popup.popup_bottom .picker_arrow{top:0;left:0;-webkit-transform:rotate(90deg) scale(1, -1);transform:rotate(90deg) scale(1, -1)}.popup.popup_left{top:0;right:100%}.popup.popup_left .picker_arrow{top:0;right:0;-webkit-transform:scale(-1, 1);transform:scale(-1, 1)}.popup.popup_right{top:0;left:100%}.popup.popup_right .picker_arrow{top:0;left:0}'; 47278 document.documentElement.firstElementChild.appendChild(style); 47279 Picker.StyleElement = style; 47280 } 47281 47282 function getChrColor$1(chr) { 47283 if (chrColorMap$1[chr]) { 47284 return chrColorMap$1[chr]; 47285 } else if (chrColorMap$1["chr" + chr]) { 47286 const color = chrColorMap$1["chr" + chr]; 47287 chrColorMap$1[chr] = color; 47288 return color; 47289 } else { 47290 const color = randomRGB(); 47291 chrColorMap$1[chr] = color; 47292 return color; 47293 } 47294 } 47295 47296 function randomRGB(min, max) { 47297 var r = Math.round(Math.random() * 255).toString(10); 47298 var g = Math.round(Math.random() * 255).toString(10); 47299 var b = Math.round(Math.random() * 255).toString(10); 47300 return "rgb(" + r + "," + g + "," + b + ")"; 47301 } 47302 47303 const chrColorMap$1 = { 47304 "chrX": "rgb(204, 153, 0)", 47305 "chrY": "rgb(153, 204, 0", 47306 "chrUn": "rgb(50, 50, 50)", 47307 "chr1": "rgb(80, 80, 255)", 47308 "chrI": "rgb(139, 155, 187)", 47309 "chr2": "rgb(206, 61, 50)", 47310 "chrII": "rgb(206, 61, 50)", 47311 "chr2a": "rgb(216, 71, 60)", 47312 "chr2b": "rgb(226, 81, 70)", 47313 "chr3": "rgb(116, 155, 88)", 47314 "chrIII": "rgb(116, 155, 88)", 47315 "chr4": "rgb(240, 230, 133)", 47316 "chrIV": "rgb(240, 230, 133)", 47317 "chr5": "rgb(70, 105, 131)", 47318 "chr6": "rgb(186, 99, 56)", 47319 "chr7": "rgb(93, 177, 221)", 47320 "chr8": "rgb(128, 34, 104)", 47321 "chr9": "rgb(107, 215, 107)", 47322 "chr10": "rgb(213, 149, 167)", 47323 "chr11": "rgb(146, 72, 34)", 47324 "chr12": "rgb(131, 123, 141)", 47325 "chr13": "rgb(199, 81, 39)", 47326 "chr14": "rgb(213, 143, 92)", 47327 "chr15": "rgb(122, 101, 165)", 47328 "chr16": "rgb(228, 175, 105)", 47329 "chr17": "rgb(59, 27, 83)", 47330 "chr18": "rgb(205, 222, 183)", 47331 "chr19": "rgb(97, 42, 121)", 47332 "chr20": "rgb(174, 31, 99)", 47333 "chr21": "rgb(231, 199, 111)", 47334 "chr22": "rgb(90, 101, 94)", 47335 "chr23": "rgb(204, 153, 0)", 47336 "chr24": "rgb(153, 204, 0)", 47337 "chr25": "rgb(51, 204, 0)", 47338 "chr26": "rgb(0, 204, 51)", 47339 "chr27": "rgb(0, 204, 153)", 47340 "chr28": "rgb(0, 153, 204)", 47341 "chr29": "rgb(10, 71, 255)", 47342 "chr30": "rgb(71, 117, 255)", 47343 "chr31": "rgb(255, 194, 10)", 47344 "chr32": "rgb(255, 209, 71)", 47345 "chr33": "rgb(153, 0, 51)", 47346 "chr34": "rgb(153, 26, 0)", 47347 "chr35": "rgb(153, 102, 0)", 47348 "chr36": "rgb(128, 153, 0)", 47349 "chr37": "rgb(51, 153, 0)", 47350 "chr38": "rgb(0, 153, 26)", 47351 "chr39": "rgb(0, 153, 102)", 47352 "chr40": "rgb(0, 128, 153)", 47353 "chr41": "rgb(0, 51, 153)", 47354 "chr42": "rgb(26, 0, 153)", 47355 "chr43": "rgb(102, 0, 153)", 47356 "chr44": "rgb(153, 0, 128)", 47357 "chr45": "rgb(214, 0, 71)", 47358 "chr46": "rgb(255, 20, 99)", 47359 "chr47": "rgb(0, 214, 143)", 47360 "chr48": "rgb(20, 255, 177)" 47361 }; 47362 47363 class CircularView { 47364 static isInstalled() { 47365 return window["JBrowseReactCircularGenomeView"] !== undefined && window["React"] !== undefined && window["ReactDOM"] !== undefined; 47366 } 47367 /** 47368 * Create a new CircularView 47369 * 47370 * @param parent 47371 * @param config - configuration options 47372 * { 47373 * assembly: {name: string, id: string, chromosomes: [{name: string, bpLength: integer, color: string}] 47374 * onChordClick: function called upon chord click with chord feature as argument 47375 * } 47376 */ 47377 47378 47379 constructor(parent, config) { 47380 config = config || {}; 47381 this.config = config; 47382 47383 if (CircularView.isInstalled()) { 47384 this.parent = parent; // wrapper for toolbar and circular-view container 47385 47386 const wrapper = document.createElement('div'); 47387 wrapper.className = 'igv-circview-container'; 47388 parent.appendChild(wrapper); // toolbar 47389 47390 this.createToolbarAndTrackPanel(wrapper); // circular view container 47391 47392 const element = document.createElement('div'); 47393 element.className = 'igv-circview-circular-genome-view'; 47394 wrapper.appendChild(element); 47395 this.container = element; 47396 47397 if (config.assembly) { 47398 this.setAssembly(config.assembly); 47399 } 47400 47401 this.tracks = config.tracks || []; 47402 this.width = config.width || 500; 47403 this.height = config.height || 500; 47404 this.setSize(this.width, this.height); 47405 } else { 47406 console.error("JBrowse circular view is not installed"); 47407 } 47408 } 47409 47410 createToolbarAndTrackPanel(parent) { 47411 let element; // toolbar 47412 47413 element = document.createElement('div'); 47414 element.className = 'igv-circview-toolbar'; 47415 parent.appendChild(element); 47416 this.toolbar = element; // track panel 47417 47418 element = document.createElement('div'); 47419 element.className = 'igv-circview-track-panel'; 47420 parent.appendChild(element); 47421 this.trackPanel = element; 47422 this.trackPanel.style.display = 'none'; // toolbar button container - Track Options - Clear All 47423 47424 let buttonContainer = document.createElement('div'); 47425 buttonContainer.className = 'igv-circview-toolbar-button-container'; 47426 this.toolbar.appendChild(buttonContainer); // Track Options 47427 47428 this.trackPanelPresentationButton = document.createElement('div'); 47429 this.trackPanelPresentationButton.className = 'igv-circview-button'; 47430 buttonContainer.appendChild(this.trackPanelPresentationButton); 47431 this.trackPanelPresentationButton.innerText = 'none' === this.trackPanel.style.display ? 'Show Track Options' : 'Hide Track Options'; 47432 this.trackPanelPresentationButton.addEventListener('click', event => { 47433 const trackPanelRows = this.trackPanel.querySelectorAll('div'); 47434 47435 if (trackPanelRows.length > 0) { 47436 if ('none' === this.trackPanel.style.display) { 47437 this.trackPanel.style.display = 'flex'; 47438 event.target.innerText = 'Hide Track Options'; 47439 } else { 47440 this.trackPanel.style.display = 'none'; 47441 event.target.innerText = 'Show Track Options'; 47442 } 47443 } 47444 }); // Clear All Chords 47445 47446 let button = document.createElement('div'); 47447 button.className = 'igv-circview-button'; 47448 buttonContainer.appendChild(button); 47449 button.innerText = 'Clear All'; 47450 button.addEventListener('click', () => { 47451 this.clearChords(); 47452 }); // toolbar button container - Close Window 47453 47454 buttonContainer = document.createElement('div'); 47455 buttonContainer.className = 'igv-circview-toolbar-button-container'; 47456 this.toolbar.appendChild(buttonContainer); // Close Window 47457 47458 if (false !== this.config.showCloseButton) { 47459 button = document.createElement('div'); 47460 button.className = 'igv-circview-button'; 47461 buttonContainer.appendChild(button); 47462 button.innerText = 'Close'; 47463 button.addEventListener('click', () => { 47464 this.visible = false;
47465 }); 47466 } 47467 } 47468 47469 addToTrackPanel(track) { 47470 // single track row - container for hide-button | color-picker-swatch | track-name 47471 const trackPanelRow = document.createElement('div'); 47472 this.trackPanel.appendChild(trackPanelRow); 47473 let element; // track hide|show 47474 47475 element = document.createElement('div'); 47476 element.className = 'igv-circview-button'; 47477 trackPanelRow.appendChild(element); 47478 element.innerText = true === track.visible ? 'Hide' : 'Show'; 47479 element.addEventListener('click', event => { 47480 if (true === track.visible) { 47481 this.hideTrack(track.id); 47482 event.target.innerText = "Show"; 47483 } else { 47484 this.showTrack(track.id); 47485 event.target.innerText = "Hide"; 47486 } 47487 }); // track color 47488 47489 element.clientHeight; 47490 const pickerButton = document.createElement('div'); 47491 pickerButton.className = 'igv-circview-button'; 47492 pickerButton.innerHTML = ' '; // <- important for button to size properly 47493 47494 trackPanelRow.appendChild(pickerButton); 47495 pickerButton.style.backgroundColor = setAlpha(track.color, 1); 47496 const pickerConfig = { 47497 parent: pickerButton, 47498 popup: 'right', 47499 editorFormat: 'rgb', 47500 color: track.color, 47501 onChange: ({ 47502 rgbaString 47503 }) => { 47504 pickerButton.style.backgroundColor = setAlpha(rgbaString, 1); 47505 this.setTrackColor(track.id, rgbaString); 47506 } 47507 }; 47508 new Picker(pickerConfig); // track name 47509 47510 element = document.createElement('div'); 47511 element.style.color = 'black'; 47512 trackPanelRow.appendChild(element); 47513 element.innerText = element.title = track.name; 47514 } 47515 /** 47516 * Reset view with a new set of chromosomes. 47517 * 47518 * @param igvGenome {name: string, id: string, chromosomes: [{name: string, bpLength: integer, color: string} 47519 */ 47520 47521 47522 setAssembly(igvGenome) { 47523 if (this.genomeId === igvGenome.id) { 47524 return; 47525 } 47526 47527 this.tracks = []; 47528 this.genomeId = igvGenome.id; 47529 this.chrNames = new Set(igvGenome.chromosomes.map(chr => shortChrName$1(chr.name))); 47530 const regions = []; 47531 const colors = []; 47532 47533 for (let chr of igvGenome.chromosomes) { 47534 const shortName = shortChrName$1(chr.name); 47535 colors.push(chr.color || getChrColor$1(shortName)); 47536 regions.push({ 47537 refName: shortName, 47538 uniqueId: shortName, 47539 start: 0, 47540 end: chr.bpLength 47541 }); 47542 } 47543 47544 this.assembly = { 47545 name: igvGenome.name, 47546 sequence: { 47547 trackId: igvGenome.id, 47548 type: 'ReferenceSequenceTrack', 47549 adapter: { 47550 type: 'FromConfigSequenceAdapter', 47551 features: regions 47552 } 47553 }, 47554 refNameColors: colors 47555 }; 47556 this.render(); 47557 } 47558 /** 47559 * Append or replace current set of chords to the global set or a specific track. 47560 * 47561 * @param newChords array of chord feature objects. Example: 47562 * [ 47563 * { 47564 * "uniqueId": "chr1:129763372-129763376_chr1:129806775-129806790", 47565 * "color": "rgba(0, 0, 255, 0.1)", 47566 * "refName": "1", 47567 * "start": 129763372, 47568 * "end": 129763376, 47569 * "mate": { 47570 * "refName": "2", 47571 * "start": 129806775, 47572 * "end": 129806790 47573 * } 47574 * } 47575 * ] 47576 * @param options { 47577 * name: string, // Track name 47578 * color: string, // Track color 47579 * append: boolean // Replace or append chords to current set. Default is append (true) 47580 * } 47581 */ 47582 47583 47584 addChords(newChords, options = {}) { 47585 const name = options.track || options.name || "*"; 47586 let track = this.tracks.find(t => name === t.name); // Override track options or create new track 47587 47588 if (track) { 47589 if (options.color) { 47590 track.color = options.color; 47591 } 47592 } else { 47593 track = { 47594 name, 47595 chords: [], 47596 color: options.color || "black", 47597 visible: true, 47598 id: options.id || guid() 47599 }; 47600 this.tracks.push(track); 47601 this.addToTrackPanel(track); 47602 } // Append chords to track 47603 47604 47605 const currentIDs = new Set(track.chords.map(c => c.uniqueId)); 47606 47607 for (let c of newChords) { 47608 if (!currentIDs.has(c.uniqueId) && this.chrNames.has(shortChrName$1(c.refName)) && this.chrNames.has(shortChrName$1(c.mate.refName))) { 47609 track.chords.push(c); 47610 currentIDs.add(c.uniqueId); 47611 } 47612 } 47613 47614 this.render(); 47615 } 47616 /** 47617 * Set the nominal size of the view in pixels. Size is reduced some aribtrary amount to account for borders and margins 47618 */ 47619 47620 47621 setSize(width, height) { 47622 height = height || width; 47623 this.width = width; 47624 this.height = height; 47625 47626 if (this.viewState) { 47627 const view = this.viewState.session.view; 47628 view.setWidth(width); 47629 view.setHeight(height 47630 /* this is the height of the area inside the border in pixels */ 47631 ); 47632 view.setBpPerPx(view.minBpPerPx); 47633 } 47634 } 47635 47636 getSize() { 47637 return Math.min(this.width, this.height); 47638 } 47639 47640 clearChords() { 47641 this.tracks = []; 47642 this.trackPanel.innerHTML = ''; 47643 this.render(); 47644 } 47645 47646 clearSelection() { 47647 this.viewState.pluginManager.rootModel.session.clearSelection(); 47648 } 47649 47650 getFeature(featureId) { 47651 // TODO -- broken 47652 // const display = this.viewState.pluginManager.rootModel.session.view.tracks[0].displays[0] 47653 // const feature = display.data.features.get(featureId) 47654 // return feature; 47655 const features = [...this.viewState.config.tracks[0].adapter.features.value]; 47656 47657 for (let f of features) { 47658 if (featureId === f.uniqueId) { 47659 return f; 47660 } 47661 } 47662 } 47663 /** 47664 * Deprecated, use "visible" property 47665 */ 47666 47667 47668 show() { 47669 this.parent.style.display = 'block'; 47670 } 47671 /** 47672 * Deprecated, use "visible" property 47673 */ 47674 47675 47676 hide() { 47677 this.parent.style.display = 'none'; 47678 } 47679 47680 get visible() { 47681 return this.parent.style.display !== 'none'; 47682 } 47683 47684 set visible(isVisible) { 47685 this.parent.style.display = isVisible ? 'block' : 'none'; 47686 } 47687 47688 hideTrack(trackID) { 47689 let track = this.tracks.find(t => trackID === t.id); 47690 47691 if (track) { 47692 track.visible = false;
47693 this.render(); 47694 } else { 47695 console.warn(`No track with name: ${name}`); 47696 } 47697 } 47698 47699 showTrack(trackID) { 47700 let idx = this.tracks.findIndex(t => trackID === t.id); 47701 47702 if (idx >= 0) { 47703 const track = this.tracks[idx]; 47704 track.visible = true; 47705 this.tracks.splice(idx, 1); // Change z-order 47706 47707 this.tracks.push(track); 47708 this.render(); 47709 } else { 47710 console.warn(`No track with name: ${name}`); 47711 } 47712 } // TODO -- remove corresponding row from track panel 47713 47714 47715 deleteTrack(trackID) { 47716 let idx = this.tracks.findIndex(t => trackID === t.id); 47717 47718 if (idx >= 0) { 47719 this.tracks.splice(idx, 1); 47720 } 47721 47722 this.render(); 47723 } 47724 47725 getTrack(trackID) { 47726 return this.tracks.find(t => trackID === t.id); 47727 } 47728 47729 setTrackColor(trackID, color) { 47730 const t = this.getTrack(trackID); 47731 47732 if (t) { 47733 t.color = color; 47734 const trackID = t.id; 47735 47736 for (let jbrowseTrack of this.viewState.config.tracks) { 47737 if (trackID === jbrowseTrack.trackId) { 47738 jbrowseTrack.displays[0].renderer.strokeColor.set(color); 47739 break; 47740 } 47741 } 47742 } 47743 } 47744 /** 47745 * The main render function. Render here means build the React DOM. Trying to change react state dynamically 47746 * has been buggy, so we completely rebuild the DOM ("render") on any state change. 47747 */ 47748 47749 47750 render() { 47751 const { 47752 createViewState, 47753 JBrowseCircularGenomeView 47754 } = JBrowseReactCircularGenomeView; // Remove all children from possible previous renders. React might do this for us when we render, but just in case. 47755 47756 ReactDOM.unmountComponentAtNode(this.container); 47757 const visibleTracks = this.tracks.filter(t => false !== t.visible); 47758 const jbrowseTracks = []; 47759 const colors = []; 47760 47761 for (let trackConfig of visibleTracks) { 47762 jbrowseTracks.push({ 47763 trackId: trackConfig.id, 47764 name: trackConfig.name, 47765 assemblyNames: ['forIGV'], 47766 type: 'VariantTrack', 47767 adapter: { 47768 type: 'FromConfigAdapter', 47769 features: trackConfig.chords 47770 } 47771 }); 47772 colors.push(trackConfig.color); 47773 } 47774 47775 this.viewState = createViewState({ 47776 assembly: this.assembly, 47777 tracks: jbrowseTracks 47778 }); // Set view colors 47779 47780 for (let i = 0; i < visibleTracks.length; i++) { 47781 this.viewState.config.tracks[i].displays[0].renderer.strokeColor.set(colors[i]); //this.viewState.config.tracks[i].displays[0].renderer.strokeColor.set("jexl:get(feature, 'color') || 'black'"); 47782 //this.viewState.config.tracks[i].displays[0].renderer.strokeColorSelected.set("jexl:get(feature, 'highlightColor') || 'red'"); 47783 } 47784 47785 this.element = React.createElement(JBrowseCircularGenomeView, { 47786 viewState: this.viewState 47787 }); 47788 this.setSize(this.width, this.height); 47789 ReactDOM.render(this.element, this.container); 47790 47791 for (let i = 0; i < visibleTracks.length; i++) { 47792 this.viewState.session.view.showTrack(this.viewState.config.tracks[i].trackId); 47793 47794 if (this.config.onChordClick) { 47795 this.viewState.pluginManager.jexl.addFunction('onChordClick', this.config.onChordClick); 47796 this.viewState.config.tracks[i].displays[0].onChordClick.set('jexl:onChordClick(feature, track, pluginManager)'); 47797 } 47798 } 47799 } 47800 47801 } 47802 47803 function setAlpha(rgba, alpha) { 47804 const [a, b, c, ignore] = rgba.split(','); // rgba(r g b alpha) 47805 47806 return `${a},${b},${c},${alpha})`; 47807 } 47808 47809 function shortChrName$1(chrName) { 47810 return chrName.startsWith("chr") ? chrName.substring(3) : chrName; 47811 } 47812 47813 function guid() { 47814 return ("0000" + (Math.random() * Math.pow(36, 4) << 0).toString(36)).slice(-4); 47815 } 47816 47817 function embedCSS$1() { 47818 const css = '.igv-circview-container {\n z-index: 2048;\n position: absolute;\n width: fit-content;\n height: fit-content;\n box-sizing: content-box;\n color: dimgray;\n font-family: \"Open Sans\", sans-serif;\n font-size: 12px;\n background-color: white;\n border-color: dimgray;\n border-style: solid;\n border-width: thin;\n display: flex;\n flex-direction: column;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: flex-start; }\n\n.igv-circview-toolbar {\n position: relative;\n width: 100%;\n height: 32px;\n background-color: lightgrey;\n border-bottom-style: solid;\n border-bottom-color: dimgray;\n border-bottom-width: thin;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: space-between;\n align-items: center; }\n\n.igv-circview-toolbar-button-container {\n height: 100%;\n width: fit-content;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: center; }\n .igv-circview-toolbar-button-container > div {\n margin: 4px; }\n\n.igv-circview-track-panel {\n z-index: 1024;\n position: absolute;\n top: 33px;\n left: 0;\n width: 100%;\n height: fit-content;\n border-bottom-style: solid;\n border-bottom-color: dimgray;\n border-bottom-width: thin;\n background-color: white;\n display: flex;\n flex-flow: column;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: flex-start; }\n .igv-circview-track-panel > div {\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: flex-start;
47818\n align-items: center; }\n .igv-circview-track-panel > div > div {\n margin: 4px; }\n\n.igv-circview-swatch-button {\n cursor: pointer;\n padding: 5px;\n width: 8px;\n height: 8px;\n border: 1px solid #8d8b8b;\n border-radius: 16px; }\n\n.igv-circview-button {\n cursor: pointer;\n padding: 5px;\n color: #444;\n vertical-align: middle;\n text-align: center;\n font-family: \"Open Sans\", sans-serif;\n font-size: 12px;\n border: 1px solid #8d8b8b;\n border-radius: 4px;\n background: #efefef;\n box-shadow: 0 0 5px -1px rgba(0, 0, 0, 0.2); }\n\n.igv-circview-button:hover {\n background: #efefef;\n box-shadow: 0 0 5px -1px rgba(0, 0, 0, 0.6); }\n\n.igv-circview-button:active {\n color: #007bff;\n box-shadow: 0 0 5px -1px rgba(0, 0, 0, 0.6); }\n\n/*# sourceMappingURL=circular-view.css.map */\n'; 47819 const style = document.createElement('style'); 47820 style.setAttribute('type', 'text/css'); 47821 style.innerHTML = css; 47822 document.head.insertBefore(style, document.head.childNodes[document.head.childNodes.length - 1]); 47823 } 47824 47825 if (typeof document !== 'undefined') { 47826 if (!stylesheetExists("circular-view.css")) { 47827 embedCSS$1(); 47828 } 47829 47830 function stylesheetExists(stylesheetName) { 47831 for (let ss of document.styleSheets) { 47832 ss = ss.href ? ss.href.replace(/^.*[\\\/]/, '') : ''; 47833 47834 if (ss === stylesheetName) { 47835 return true; 47836 } 47837 } 47838 47839 return false; 47840 } 47841 } 47842 47843 /** 47844 * The minimum length for a VCF structural variant. VCF records < this length are ignored in the circular view 47845 * @type {number} 47846 */ 47847 47848 const MINIMUM_SV_LENGTH = 1000000; 47849 47850 const shortChrName = chrName => { 47851 return chrName.startsWith("chr") ? chrName.substring(3) : chrName; 47852 }; 47853 47854 const makePairedAlignmentChords = alignments => { 47855 const chords = []; 47856 47857 for (let a of alignments) { 47858 const mate = a.mate; 47859 47860 if (mate && mate.chr && mate.position) { 47861 chords.push({ 47862 uniqueId: a.readName, 47863 refName: shortChrName(a.chr), 47864 start: a.start, 47865 end: a.end, 47866 mate: { 47867 refName: shortChrName(mate.chr), 47868 start: mate.position - 1, 47869 end: mate.position 47870 } 47871 }); 47872 } 47873 } 47874 47875 return chords; 47876 }; 47877 47878 const makeSupplementalAlignmentChords = alignments => { 47879 const chords = []; 47880 47881 for (let a of alignments) { 47882 const sa = a.tags()['SA']; 47883 const supAl = createSupplementaryAlignments(sa); 47884 let n = 0; 47885 47886 for (let s of supAl) { 47887 if (s.start !== a.start) { 47888 chords.push({ 47889 uniqueId: `${a.readName}_${n++}`, 47890 refName: shortChrName(a.chr), 47891 start: a.start, 47892 end: a.end, 47893 mate: { 47894 refName: shortChrName(s.chr), 47895 start: s.start, 47896 end: s.start + s.lenOnRef 47897 } 47898 }); 47899 } 47900 } 47901 } 47902 47903 return chords; 47904 }; 47905 47906 const makeBedPEChords = features => { 47907 return features.map(v => { 47908 // If v is a whole-genome feature, get the true underlying variant. 47909 const f = v._f || v; 47910 return { 47911 uniqueId: `${f.chr1}:${f.start1}-${f.end1}_${f.chr2}:${f.start2}-${f.end2}`, 47912 refName: shortChrName(f.chr1), 47913 start: f.start1, 47914 end: f.end1, 47915 mate: { 47916 refName: shortChrName(f.chr2), 47917 start: f.start2, 47918 end: f.end2 47919 } 47920 }; 47921 }); 47922 }; 47923 47924 const makeVCFChords = features => { 47925 const svFeatures = features.filter(v => { 47926 const f = v._f || v; 47927 const isLargeEnough = f.info && f.info.CHR2 && f.info.END && (f.info.CHR2 !== f.chr || Math.abs(Number.parseInt(f.info.END) - f.pos) > MINIMUM_SV_LENGTH); 47928 return isLargeEnough; 47929 }); 47930 return svFeatures.map(v => { 47931 // If v is a whole-genome feature, get the true underlying variant. 47932 const f = v._f || v; 47933 const pos2 = Number.parseInt(f.info.END); 47934 const start2 = pos2 - 100; 47935 const end2 = pos2 + 100; 47936 return { 47937 uniqueId: `${f.chr}:${f.start}-${f.end}_${f.info.CHR2}:${f.info.END}`, 47938 refName: shortChrName(f.chr), 47939 start: f.start, 47940 end: f.end, 47941 mate: { 47942 refName: shortChrName(f.info.CHR2), 47943 start: start2, 47944 end: end2
47945 } 47946 }; 47947 }); 47948 }; 47949 47950 function makeCircViewChromosomes(genome) { 47951 const regions = []; 47952 const colors = []; 47953 47954 for (let chrName of genome.wgChromosomeNames) { 47955 const chr = genome.getChromosome(chrName); 47956 colors.push(getChrColor(chr.name)); 47957 regions.push({ 47958 name: chr.name, 47959 bpLength: chr.bpLength 47960 }); 47961 } 47962 47963 return regions; 47964 } 47965 47966 function createCircularView(el, browser) { 47967 const circularView = new CircularView(el, { 47968 onChordClick: (feature, chordTrack, pluginManager) => { 47969 const f1 = feature.data; 47970 const f2 = f1.mate; 47971 const flanking = 2000; 47972 const l1 = new Locus({ 47973 chr: browser.genome.getChromosomeName(f1.refName), 47974 start: f1.start, 47975 end: f1.end 47976 }); 47977 const l2 = new Locus({ 47978 chr: browser.genome.getChromosomeName(f2.refName), 47979 start: f2.start, 47980 end: f2.end 47981 }); 47982 let loci; // If there is overlap with current loci 47983 47984 loci = browser.currentLoci().map(str => Locus.fromLocusString(str)); 47985 47986 if (loci.some(locus => locus.contains(l1)) || loci.some(locus => locus.contains(l2))) { 47987 for (let l of [l1, l2]) { 47988 if (!loci.some(locus => { 47989 return locus.contains(l); 47990 })) { 47991 // add flanking 47992 l.start = Math.max(0, l.start - flanking); 47993 l.end += flanking; 47994 loci.push(l); 47995 } 47996 } 47997 } else { 47998 l1.start = Math.max(0, l1.start - flanking); 47999 l1.end += flanking; 48000 l2.start = Math.max(0, l2.start - flanking); 48001 l2.end += flanking; 48002 loci = [l1, l2]; 48003 } 48004 48005 const searchString = loci.map(l => l.getLocusString()).join(" "); 48006 browser.search(searchString); 48007 } 48008 }); 48009 return circularView; 48010 } 48011 48012 /* 48013 * The MIT License (MIT) 48014 * 48015 * Copyright (c) 2014 Broad Institute 48016 * 48017 * Permission is hereby granted, free of charge, to any person obtaining a copy 48018 * of this software and associated documentation files (the "Software"), to deal 48019 * in the Software without restriction, including without limitation the rights 48020 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 48021 * copies of the Software, and to permit persons to whom the Software is 48022 * furnished to do so, subject to the following conditions: 48023 * 48024 * The above copyright notice and this permission notice shall be included in 48025 * all copies or substantial portions of the Software. 48026 * 48027 * 48028 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 48029 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 48030 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 48031 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 48032 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 48033 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 48034 * THE SOFTWARE. 48035 */ 48036 const alignmentStartGap = 5; 48037 const downsampleRowHeight = 5; 48038 const DEFAULT_COVERAGE_TRACK_HEIGHT = 50; 48039 const DEFAULT_TRACK_HEIGHT = 300; 48040 const DEFAULT_ALIGNMENT_COLOR = "rgb(185, 185, 185)"; 48041 const DEFAULT_COVERAGE_COLOR = "rgb(150, 150, 150)"; 48042 const DEFAULT_CONNECTOR_COLOR = "rgb(200, 200, 200)"; 48043 48044 class BAMTrack extends TrackBase { 48045 constructor(config, browser) { 48046 super(config, browser); 48047 } 48048 48049 init(config) { 48050 super.init(config); 48051 this.type = "alignment"; 48052 48053 if (config.alleleFreqThreshold === undefined) { 48054 config.alleleFreqThreshold = 0.2; 48055 } 48056 48057 this.featureSource = new BamSource(config, this.browser); 48058 this.showCoverage = config.showCoverage === undefined ? true : config.showCoverage; 48059 this.showAlignments = config.showAlignments === undefined ? true : config.showAlignments; 48060 this.coverageTrack = new CoverageTrack(config, this); 48061 this.alignmentTrack = new AlignmentTrack(config, this); 48062 this.alignmentTrack.setTop(this.coverageTrack, this.showCoverage); 48063 this.visibilityWindow = config.visibilityWindow || 30000; 48064 this.viewAsPairs = config.viewAsPairs; 48065 this.pairsSupported = config.pairsSupported !== false; 48066 this.showSoftClips = config.showSoftClips; 48067 this.showAllBases = config.showAllBases; 48068 this.showInsertions = false !== config.showInsertions; 48069 this.showMismatches = false !== config.showMismatches; 48070 this.color = config.color; 48071 this.coverageColor = config.coverageColor; 48072 this.minFragmentLength = config.minFragmentLength; // Optional, might be undefined 48073 48074 this.maxFragmentLength = config.maxFragmentLength || 1000; // The sort object can be an array in the case of multi-locus view, however if multiple sort positions 48075 // are present for a given reference frame the last one will take precedence 48076 48077 if (config.sort) { 48078 if (Array.isArray(config.sort)) { 48079 // Legacy support 48080 this.assignSort(config.sort[0]); 48081 } else { 48082 this.assignSort(config.sort); 48083 } 48084 } // Invoke height setter last to allocated to coverage and alignment tracks 48085 48086 48087 this.height = config.height !== undefined ? config.height : DEFAULT_TRACK_HEIGHT; 48088 } 48089 48090 set height(h) { 48091 this._height = h; 48092 48093 if (this.coverageTrack && this.showAlignments) { 48094 this.alignmentTrack.height = this.showCoverage ? h - this.coverageTrack.height : h; 48095 } 48096 } 48097 48098 get height() { 48099 return this._height; 48100 } 48101 48102 sort(options) { 48103 options = this.assignSort(options); 48104 48105 for (let vp of this.trackView.viewports) { 48106 if (vp.containsPosition(options.chr, options.position)) { 48107 const alignmentContainer = vp.getCachedFeatures(); 48108 48109 if (alignmentContainer) { 48110 sortAlignmentRows(options, alignmentContainer); 48111 vp.repaint(); 48112 } 48113 } 48114 } 48115 } 48116 /** 48117 * Fix syntax problems for sort options. 48118 * @param options 48119 */ 48120 48121 48122 assignSort(options) { 48123 // convert old syntax 48124 if (options.locus) { 48125 const range = parseLocusString$1(options.locus); 48126 options.chr = range.chr; 48127 options.position = range.start; 48128 } else { 48129 options.position--; 48130 } 48131 48132 options.direction = options.direction === "ASC" || options.direction === true; // chr aliasing 48133 48134 options.chr = this.browser.genome.getChromosomeName(options.chr); 48135 this.sortObject = options; 48136 return this.sortObject; 48137 } 48138 48139 async getFeatures(chr, bpStart, bpEnd, bpPerPixel, viewport) { 48140 const alignmentContainer = await this.featureSource.getAlignments(chr, bpStart, bpEnd); 48141 48142 if (alignmentContainer.alignments && alignmentContainer.alignments.length > 99) { 48143 if (undefined === this.minFragmentLength) { 48144 this.minFragmentLength = alignmentContainer.pairedEndStats.lowerFragmentLength; 48145 } 48146 48147 if (undefined === this.maxFragmentLength) { 48148 this.maxFragmentLength = alignmentContainer.pairedEndStats.upperFragmentLength; 48149 } 48150 } 48151 48152 const sort = this.sortObject; 48153 48154 if (sort) { 48155 if (sort.chr === chr && sort.position >= bpStart && sort.position <= bpEnd) { 48156 sortAlignmentRows(sort, alignmentContainer); 48157 } 48158 } 48159 48160 return alignmentContainer; 48161 } 48162 /** 48163 * Compute the pixel height required to display all content. This is not the same as the viewport height 48164 * (track.height) which might include a scrollbar. 48165 * 48166 * @param alignmentContainer 48167 * @returns {number} 48168 */ 48169 48170 48171 computePixelHeight(alignmentContainer) { 48172 return (this.showCoverage ? this.coverageTrack.height : 0) + (this.showAlignments ? this.alignmentTrack.computePixelHeight(alignmentContainer) : 0) + 15; 48173 } 48174 48175 draw(options) { 48176 IGVGraphics.fillRect(options.context, 0, options.pixelTop, options.pixelWidth, options.pixelHeight, { 48177 'fillStyle': "rgb(255, 255, 255)" 48178 }); 48179 48180 if (true === this.showCoverage && this.coverageTrack.height > 0) { 48181 this.trackView.axisCanvas.style.display = 'block'; 48182 this.coverageTrack.draw(options); 48183 } else { 48184 this.trackView.axisCanvas.style.display = 'none'; 48185 } 48186 48187 if (true === this.showAlignments) { 48188 this.alignmentTrack.setTop(this.coverageTrack, this.showCoverage); 48189 this.alignmentTrack.draw(options); 48190 } 48191 } 48192 48193 paintAxis(ctx, pixelWidth, pixelHeight) { 48194 this.coverageTrack.paintAxis(ctx, pixelWidth, this.coverageTrack.height); // if (this.browser.isMultiLocusMode()) { 48195 // ctx.clearRect(0, 0, pixelWidth, pixelHeight); 48196 // } else { 48197 // this.coverageTrack.paintAxis(ctx, pixelWidth, this.coverageTrack.height); 48198 // } 48199 } 48200 48201 contextMenuItemList(config) { 48202 return this.alignmentTrack.contextMenuItemList(config); 48203 } 48204 48205 popupData(clickState) { 48206 if (true === this.showCoverage && clickState.y >= this.coverageTrack.top && clickState.y < this.coverageTrack.height) { 48207 return this.coverageTrack.popupData(clickState); 48208 } else { 48209 return this.alignmentTrack.popupData(clickState); 48210 } 48211 } 48212 /** 48213 * Return the features (alignment, coverage, downsampled interval) clicked on. Needed for "oncl
48213ick" event. 48214 * @param clickState 48215 * @param features 48216 */ 48217 48218 48219 clickedFeatures(clickState) { 48220 if (true === this.showCoverage && clickState.y >= this.coverageTrack.top && clickState.y < this.coverageTrack.height) { 48221 return [this.coverageTrack.getClickedObject(clickState)]; 48222 } else { 48223 return [this.alignmentTrack.getClickedObject(clickState)]; 48224 } 48225 } 48226 48227 menuItemList() { 48228 // Start with overage track items 48229 let menuItems = []; 48230 menuItems = menuItems.concat(MenuUtils.numericDataMenuItems(this.trackView)); // Color by items 48231 48232 menuItems.push('<hr/>'); 48233 const $e = $$1('<div class="igv-track-menu-category">'); 48234 $e.text('Color by:'); 48235 menuItems.push({ 48236 name: undefined, 48237 object: $e, 48238 click: undefined, 48239 init: undefined 48240 }); 48241 const colorByMenuItems = [{ 48242 key: 'strand', 48243 label: 'read strand' 48244 }]; 48245 48246 if (this.alignmentTrack.hasPairs) { 48247 colorByMenuItems.push({ 48248 key: 'firstOfPairStrand', 48249 label: 'first-of-pair strand' 48250 }); 48251 colorByMenuItems.push({ 48252 key: 'pairOrientation', 48253 label: 'pair orientation' 48254 }); 48255 colorByMenuItems.push({ 48256 key: 'fragmentLength', 48257 label: 'insert size (TLEN)' 48258 }); 48259 colorByMenuItems.push({ 48260 key: 'unexpectedPair', 48261 label: 'pair orientation & insert size (TLEN)' 48262 }); 48263 } 48264 48265 const tagLabel = 'tag' + (this.alignmentTrack.colorByTag ? ' (' + this.alignmentTrack.colorByTag + ')' : ''); 48266 colorByMenuItems.push({ 48267 key: 'tag', 48268 label: tagLabel 48269 }); 48270 48271 for (let item of colorByMenuItems) { 48272 const selected = this.alignmentTrack.colorBy === item.key; 48273 menuItems.push(this.colorByCB(item, selected)); 48274 } // Show coverage / alignment options 48275 48276 48277 const adjustTrackHeight = () => { 48278 if (!this.autoHeight) { 48279 const h = 15 + (this.showCoverage ? this.coverageTrack.height : 0) + (this.showAlignments ? this.alignmentTrack.height : 0); 48280 this.trackView.setTrackHeight(h); 48281 } 48282 }; 48283 48284 menuItems.push('<hr/>'); 48285 menuItems.push({ 48286 object: $$1(createCheckbox$1("Show Coverage", this.showCoverage)), 48287 click: () => { 48288 this.showCoverage = !this.showCoverage; 48289 adjustTrackHeight(); 48290 this.trackView.checkContentHeight(); 48291 this.trackView.repaintViews(); 48292 } 48293 }); 48294 menuItems.push({ 48295 object: $$1(createCheckbox$1("Show Alignments", this.showAlignments)), 48296 click: () => { 48297 this.showAlignments = !this.showAlignments; 48298 adjustTrackHeight(); 48299 this.trackView.checkContentHeight(); 48300 this.trackView.repaintViews(); 48301 } 48302 }); // Show all bases 48303 48304 menuItems.push('<hr/>'); 48305 menuItems.push({ 48306 object: $$1(createCheckbox$1("Show all bases", this.showAllBases)), 48307 click: () => { 48308 this.showAllBases = !this.showAllBases; 48309 this.config.showAllBases = this.showAllBases; 48310 this.trackView.repaintViews(); 48311 } 48312 }); // Show mismatches 48313 48314 menuItems.push('<hr/>'); 48315 menuItems.push({ 48316 object: $$1(createCheckbox$1("Show mismatches", this.showMismatches)), 48317 click: () => { 48318 this.showMismatches = !this.showMismatches; 48319 this.config.showMismatches = this.showMismatches; 48320 this.trackView.repaintViews(); 48321 } 48322 }); // Insertions 48323 48324 menuItems.push({ 48325 object: $$1(createCheckbox$1("Show insertions", this.showInsertions)), 48326 click: () => { 48327 this.showInsertions = !this.showInsertions; 48328 this.config.showInsertions = this.showInsertions; 48329 this.getCachedAlignmentContainers(); 48330 this.trackView.repaintViews(); 48331 } 48332 }); // Soft clips 48333 48334 menuItems.push({ 48335 object: $$1(createCheckbox$1("Show soft clips", this.showSoftClips)), 48336 click: () => { 48337 this.showSoftClips = !this.showSoftClips; 48338 this.config.showSoftClips = this.showSoftClips; 48339 this.featureSource.setShowSoftClips(this.showSoftClips); 48340 const alignmentContainers = this.getCachedAlignmentContainers(); 48341
48342 for (let ac of alignmentContainers) { 48343 ac.setShowSoftClips(this.showSoftClips); 48344 } 48345 48346 this.trackView.repaintViews(); 48347 } 48348 }); // View as pairs 48349 48350 if (this.pairsSupported && this.alignmentTrack.hasPairs) { 48351 menuItems.push('<hr/>'); 48352 menuItems.push({ 48353 object: $$1(createCheckbox$1("View as pairs", this.viewAsPairs)), 48354 click: () => { 48355 this.viewAsPairs = !this.viewAsPairs; 48356 this.config.viewAsPairs = this.viewAsPairs; 48357 this.featureSource.setViewAsPairs(this.viewAsPairs); 48358 const alignmentContainers = this.getCachedAlignmentContainers(); 48359 48360 for (let ac of alignmentContainers) { 48361 ac.setViewAsPairs(this.viewAsPairs); 48362 } 48363 48364 this.trackView.repaintViews(); 48365 } 48366 }); 48367 } // Experimental JBrowse feature 48368 48369 48370 if (this.browser.circularView && true === this.browser.circularViewVisible && (this.alignmentTrack.hasPairs || this.alignmentTrack.hasSupplemental)) { 48371 menuItems.push('<hr/>'); 48372 48373 if (this.alignmentTrack.hasPairs) { 48374 menuItems.push({ 48375 label: 'Add discordant pairs to circular view', 48376 click: () => { 48377 const maxFragmentLength = this.maxFragmentLength; 48378 const inView = []; 48379 48380 for (let viewport of this.trackView.viewports) { 48381 for (let a of viewport.getCachedFeatures().allAlignments()) { 48382 const referenceFrame = viewport.referenceFrame; 48383 48384 if (a.end >= referenceFrame.start && a.start <= referenceFrame.end && a.mate && a.mate.chr && (a.mate.chr !== a.chr || Math.max(a.fragmentLength) > maxFragmentLength)) { 48385 inView.push(a); 48386 } 48387 } 48388 } 48389 48390 this.browser.circularViewVisible = true; 48391 const chords = makePairedAlignmentChords(inView); 48392 const color = IGVColor.addAlpha(this.color || 'rgb(0,0,255)', 0.02); 48393 this.browser.circularView.addChords(chords, { 48394 track: this.name, 48395 color: color 48396 }); 48397 } 48398 }); 48399 } 48400 48401 if (this.alignmentTrack.hasSupplemental) { 48402 menuItems.push({ 48403 label: 'Add split reads to circular view', 48404 click: () => { 48405 const inView = []; 48406 48407 for (let viewport of this.trackView.viewports) { 48408 for (let a of viewport.getCachedFeatures().allAlignments()) { 48409 const referenceFrame = viewport.referenceFrame; 48410 const sa = a.hasTag('SA'); 48411 48412 if (a.end >= referenceFrame.start && a.start <= referenceFrame.end && sa) { 48413 inView.push(a); 48414 } 48415 } 48416 } 48417 48418 const chords = makeSupplementalAlignmentChords(inView); 48419 const color = IGVColor.addAlpha(this.color || 'rgb(0,0,255)', 0.1); 48420 this.browser.circularView.addChords(chords, { 48421 track: this.name, 48422 color: color 48423 }); 48424 } 48425 }); 48426 } 48427 } // Display mode 48428 48429 48430 menuItems.push('<hr/>'); 48431 const $dml = $$1('<div class="igv-track-menu-category">'); 48432 $dml.text('Display mode:'); 48433 menuItems.push({ 48434 name: undefined, 48435 object: $dml, 48436 click: undefined, 48437 init: undefined 48438 }); 48439 menuItems.push({ 48440 object: $$1(createCheckbox$1("expand", this.alignmentTrack.displayMode === "EXPANDED")), 48441 click: () => { 48442 this.alignmentTrack.displayMode = "EXPANDED"; 48443 this.config.displayMode = "EXPANDED"; 48444 this.trackView.checkContentHeight(); 48445 this.trackView.repaintViews(); 48446 } 48447 }); 48448 menuItems.push({ 48449 object: $$1(createCheckbox$1("squish", this.alignmentTrack.displayMode === "SQUISHED")), 48450 click: () => { 48451 this.alignmentTrack.displayMode = "SQUISHED"; 48452 this.config.displayMode = "SQUISHED"; 48453 this.trackView.checkContentHeight(); 48454 this.trackView.repaintViews(); 48455 } 48456 }); 48457 return menuItems; 48458 } 48459 /** 48460 * Create a "color by" checkbox menu item, optionally initially checked 48461 * @param menuItem 48462 * @param showCheck 48463 * @returns {{init: undefined, name: undefined, click: clickHandler, object: (jQuery|HTMLElement|jQuery.fn.init)}} 48464 */ 48465 48466 48467 colorByCB(menuItem, showCheck) { 48468 const $e = $$1(createCheckbox$1(menuItem.label, showCheck)); 48469 48470 const clickHandler = ev => { 48471 if (menuItem.key !== 'tag') { 48472 if (menuItem.key === this.alignmentTrack.colorBy) { 48473 this.alignmentTrack.colorBy = 'none'; 48474 this.config.colorBy = 'none'; 48475 this.trackView.repaintViews(); 48476 } else { 48477 this.alignmentTrack.colorBy = menuItem.key; 48478 this.config.colorBy = menuItem.key; 48479 this.trackView.repaintViews(); 48480 } 48481 } else { 48482 this.browser.inputDialog.present({ 48483 label: 'Tag Name', 48484 value: this.alignmentTrack.colorByTag ? this.alignmentTrack.colorByTag : '', 48485 callback: tag => { 48486 if (tag) { 48487 this.alignmentTrack.colorBy = 'tag'; 48488 this.alignmentTrack.colorByTag = tag; 48489 48490 if (!this.alignmentTrack.tagColors) { 48491 this.alignmentTrack.tagColors = new PaletteColorTable("Set1"); 48492 } 48493 } else { 48494 this.alignmentTrack.colorBy = 'none'; 48495 this.alignmentTrack.colorByTag = ''; 48496 } 48497 48498 this.trackView.repaintViews(); 48499 } 48500 }, ev); 48501 } 48502 }; 48503 48504 return { 48505 name: undefined, 48506 object: $e, 48507 click: clickHandler, 48508 init: undefined 48509 }; 48510 } 48511 /** 48512 * Called when the track is removed. Do any needed cleanup here 48513 */ 48514 48515 48516 dispose() { 48517 this.trackView = undefined; 48518 } 48519 /** 48520 * Return the current state of the track. Used to create sessions and bookmarks. 48521 * 48522 * @returns {*|{}} 48523 */ 48524 48525 48526 getState() { 48527 const config = super.getState(); 48528 48529 if (this.sortObject) { 48530 config.sort = { 48531 chr: this.sortObject.chr, 48532 position: this.sortObject.position + 1, 48533 option: this.sortObject.option, 48534 direction: this.sortObject.direction ? "ASC" : "DESC" 48535 }; 48536 } 48537 48538 return config; 48539 } 48540 48541 getCachedAlignmentContainers() { 48542 return this.trackView.viewports.map(vp => vp.getCachedFeatures()); 48543 } 48544 48545 get dataRange() { 48546 return this.coverageTrack.dataRange; 48547 } 48548 48549 set dataRange(dataRange) { 48550 this.coverageTrack.dataRange = dataRange; 48551 } 48552 48553 get logScale() { 48554 return this.coverageTrack.logScale; 48555 } 48556 48557 set logScale(logScale) { 48558 this.coverageTrack.logScale = logScale; 48559 } 48560 48561 get autoscale() { 48562 return this.coverageTrack.autoscale; 48563 } 48564 48565 set autoscale(autoscale) { 48566 this.coverageTrack.autoscale = autoscale; 48567 } 48568 48569 } 48570 48571 class CoverageTrack { 48572 constructor(config, parent) { 48573 this.parent = parent; 48574 this.featureSource = parent.featureSource; 48575 this.height = config.coverageTrackHeight !== undefined ? config.coverageTrackHeight : DEFAULT_COVERAGE_TRACK_HEIGHT; 48576 this.paintAxis = paintAxis; 48577 this.top = 0; 48578 this.autoscale = config.autoscale || config.max === undefined; 48579 48580 if (!this.autoscale) { 48581 this.dataRange = { 48582 min: config.min || 0, 48583 max: config.max 48584 }; 48585 } 48586 } 48587 48588 draw(options) { 48589 const pixelTop = options.pixelTop; 48590 pixelTop + options.pixelHeight; 48591 const nucleotideColors = this.parent.browser.nucleotideColors; 48592 48593 if (pixelTop > this.height) { 48594 return; //scrolled out of view 48595 } 48596 48597 const ctx = options.context; 48598 const alignmentContainer = options.features; 48599 const coverageMap = alignmentContainer.coverageMap; 48600 let sequence; 48601 48602 if (coverageMap.refSeq) { 48603 sequence = coverageMap.refSeq.toUpperCase(); 48604 } 48605 48606 const bpPerPixel = options.bpPerPixel; 48607 const bpStart = options.bpStart; 48608 const pixelWidth = options.pixelWidth; 48609 const bpEnd = bpStart + pixelWidth * bpPerPixel + 1;
48609 // paint for all coverage buckets 48610 // If alignment track color is != default, use it 48611 48612 let color; 48613 48614 if (this.parent.coverageColor) { 48615 color = this.parent.coverageColor; 48616 } else if (this.parent.color !== undefined) { 48617 color = IGVColor.darkenLighten(this.parent.color, -35); 48618 } else { 48619 color = DEFAULT_COVERAGE_COLOR; 48620 } 48621 48622 IGVGraphics.setProperties(ctx, { 48623 fillStyle: color, 48624 strokeStyle: color 48625 }); 48626 const w = Math.max(1, Math.ceil(1.0 / bpPerPixel)); 48627 48628 for (let i = 0, len = coverageMap.coverage.length; i < len; i++) { 48629 const bp = coverageMap.bpStart + i; 48630 if (bp < bpStart) continue; 48631 if (bp > bpEnd) break; 48632 const item = coverageMap.coverage[i]; 48633 if (!item) continue; 48634 const h = Math.round(item.total / this.dataRange.max * this.height); 48635 const y = this.height - h; 48636 const x = Math.floor((bp - bpStart) / bpPerPixel); // IGVGraphics.setProperties(ctx, {fillStyle: "rgba(0, 200, 0, 0.25)", strokeStyle: "rgba(0, 200, 0, 0.25)" }); 48637 48638 IGVGraphics.fillRect(ctx, x, y, w, h); 48639 } // coverage mismatch coloring -- don't try to do this in above loop, color bar will be overwritten when w<1 48640 48641 48642 if (sequence) { 48643 for (let i = 0, len = coverageMap.coverage.length; i < len; i++) { 48644 const bp = coverageMap.bpStart + i; 48645 if (bp < bpStart) continue; 48646 if (bp > bpEnd) break; 48647 const item = coverageMap.coverage[i]; 48648 if (!item) continue; 48649 const h = item.total / this.dataRange.max * this.height; 48650 let y = this.height - h; 48651 const x = Math.floor((bp - bpStart) / bpPerPixel); 48652 const refBase = sequence[i]; 48653 48654 if (item.isMismatch(refBase)) { 48655 IGVGraphics.setProperties(ctx, { 48656 fillStyle: nucleotideColors[refBase] 48657 }); 48658 IGVGraphics.fillRect(ctx, x, y, w, h); 48659 let accumulatedHeight = 0.0; 48660 48661 for (let nucleotide of ["A", "C", "T", "G"]) { 48662 const count = item["pos" + nucleotide] + item["neg" + nucleotide]; // non-logoritmic 48663 48664 const hh = count / this.dataRange.max * this.height; 48665 y = this.height - hh - accumulatedHeight; 48666 accumulatedHeight += hh; 48667 IGVGraphics.setProperties(ctx, { 48668 fillStyle: nucleotideColors[nucleotide] 48669 }); 48670 IGVGraphics.fillRect(ctx, x, y, w, hh); 48671 } 48672 } 48673 } 48674 } 48675 } 48676 48677 getClickedObject(clickState) { 48678 let features = clickState.viewport.getCachedFeatures(); 48679 if (!features || features.length === 0) return; 48680 const genomicLocation = Math.floor(clickState.genomicLocation); 48681 const coverageMap = features.coverageMap; 48682 const coverageMapIndex = Math.floor(genomicLocation - coverageMap.bpStart); 48683 return coverageMap.coverage[coverageMapIndex]; 48684 } 48685 48686 popupData(clickState) { 48687 const nameValues = []; 48688 const coverage = this.getClickedObject(clickState); 48689 48690 if (coverage) { 48691 const genomicLocation = Math.floor(clickState.genomicLocation); 48692 const referenceFrame = clickState.viewport.referenceFrame; 48693 nameValues.push(referenceFrame.chr + ":" + numberFormatter$1(1 + genomicLocation)); 48694 nameValues.push({ 48695 name: 'Total Count', 48696 value: coverage.total 48697 }); // A 48698 48699 let tmp = coverage.posA + coverage.negA; 48700 if (tmp > 0) tmp = tmp.toString() + " (" + Math.round(tmp / coverage.total * 100.0) + "%, " + coverage.posA + "+, " + coverage.negA + "- )"; 48701 nameValues.push({ 48702 name: 'A', 48703 value: tmp 48704 }); // C 48705 48706 tmp = coverage.posC + coverage.negC; 48707 if (tmp > 0) tmp = tmp.toString() + " (" + Math.round(tmp / coverage.total * 100.0) + "%, " + coverage.posC + "+, " + coverage.negC + "- )"; 48708 nameValues.push({ 48709 name: 'C', 48710 value: tmp 48711 }); // G 48712 48713 tmp = coverage.posG + coverage.negG; 48714 if (tmp > 0) tmp = tmp.toString() + " (" + Math.round(tmp / coverage.total * 100.0) + "%, " + coverage.posG + "+, " + coverage.negG + "- )"; 48715 nameValues.push({ 48716 name: 'G', 48717 value: tmp 48718 }); // T 48719 48720 tmp = coverage.posT + coverage.negT; 48721 if (tmp > 0) tmp = tmp.toString() + " (" + Math.round(tmp / coverage.total * 100.0) + "%, " + coverage.posT + "+, " + coverage.negT + "- )"; 48722 nameValues.push({ 48723 name: 'T', 48724 value: tmp 48725 }); // N 48726 48727 tmp = coverage.posN + coverage.negN; 48728 if (tmp > 0) tmp = tmp.toString() + " (" + Math.round(tmp / coverage.total * 100.0) + "%, " + coverage.posN + "+, " + coverage.negN + "- )"; 48729 nameValues.push({ 48730 name: 'N', 48731 value: tmp 48732 }); 48733 nameValues.push('<HR/>'); 48734 nameValues.push({ 48735 name: 'DEL', 48736 value: coverage.del.toString() 48737 }); 48738 nameValues.push({ 48739 name: 'INS', 48740 value: coverage.ins.toString() 48741 }); 48742 } 48743 48744 return nameValues; 48745 } 48746 48747 } 48748 48749 class AlignmentTrack { 48750 constructor(config, parent) { 48751 this.parent = parent; 48752 this.browser = parent.browser; 48753 this.featureSource = parent.featureSource; 48754 this.top = 0 === config.coverageTrackHeight ? 0 : config.coverageTrackHeight + 5; 48755 this.displayMode = config.displayMode || "EXPANDED"; 48756 this.alignmentRowHeight = config.alignmentRowHeight || 14; 48757 this.squishedRowHeight = config.squishedRowHeight || 3; 48758 this.negStrandColor = config.negStrandColor || "rgba(150, 150, 230, 0.75)"; 48759 this.posStrandColor = config.posStrandColor || "rgba(230, 150, 150, 0.75)"; 48760 this.insertionColor = config.insertionColor || "rgb(138, 94,
48760161)"; 48761 this.deletionColor = config.deletionColor || "black"; 48762 this.skippedColor = config.skippedColor || "rgb(150, 170, 170)"; 48763 this.pairConnectorColor = config.pairConnectorColor; 48764 this.smallFragmentLengthColor = config.smallFragmentLengthColor || "rgb(0, 0, 150)"; 48765 this.largeFragmentLengthColor = config.largeFragmentLengthColor || "rgb(200, 0, 0)"; 48766 this.pairOrientation = config.pairOrienation || 'fr'; 48767 this.pairColors = {}; 48768 this.pairColors["RL"] = config.rlColor || "rgb(0, 150, 0)"; 48769 this.pairColors["RR"] = config.rrColor || "rgb(20, 50, 200)"; 48770 this.pairColors["LL"] = config.llColor || "rgb(0, 150, 150)"; 48771 this.colorBy = config.colorBy || "pairOrientation"; 48772 this.colorByTag = config.colorByTag ? config.colorByTag.toUpperCase() : undefined; 48773 this.bamColorTag = config.bamColorTag === undefined ? "YC" : config.bamColorTag; 48774 this.hideSmallIndels = config.hideSmallIndels; 48775 this.indelSizeThreshold = config.indelSizeThreshold || 1; 48776 this.hasPairs = false; // Until proven otherwise 48777 48778 this.hasSupplemental = false; 48779 } 48780 48781 setTop(coverageTrack, showCoverage) { 48782 this.top = 0 === coverageTrack.height || false === showCoverage ? 0 : 5 + coverageTrack.height; 48783 } 48784 /** 48785 * Compute the pixel height required to display all content. 48786 * 48787 * @param alignmentContainer 48788 * @returns {number|*} 48789 */ 48790 48791 48792 computePixelHeight(alignmentContainer) { 48793 if (alignmentContainer.packedAlignmentRows) { 48794 const h = alignmentContainer.hasDownsampledIntervals() ? downsampleRowHeight + alignmentStartGap : 0; 48795 const alignmentRowHeight = this.displayMode === "SQUISHED" ? this.squishedRowHeight : this.alignmentRowHeight; 48796 return h + alignmentRowHeight * alignmentContainer.packedAlignmentRows.length + 5; 48797 } else { 48798 return 0; 48799 } 48800 } 48801 48802 draw(options) { 48803 const alignmentContainer = options.features; 48804 const ctx = options.context; 48805 const bpPerPixel = options.bpPerPixel; 48806 const bpStart = options.bpStart; 48807 const pixelWidth = options.pixelWidth; 48808 const bpEnd = bpStart + pixelWidth * bpPerPixel + 1; 48809 const showSoftClips = this.parent.showSoftClips; 48810 const showAllBases = this.parent.showAllBases; 48811 const nucleotideColors = this.browser.nucleotideColors; //alignmentContainer.repack(bpPerPixel, showSoftClips); 48812 48813 const packedAlignmentRows = alignmentContainer.packedAlignmentRows; 48814 ctx.save(); 48815 let referenceSequence = alignmentContainer.sequence; 48816 48817 if (referenceSequence) { 48818 referenceSequence = referenceSequence.toUpperCase(); 48819 } 48820 48821 let alignmentRowYInset = 0; 48822 let pixelTop = options.pixelTop; 48823 48824 if (this.top) { 48825 ctx.translate(0, this.top); 48826 } 48827 48828 const pixelBottom = pixelTop + options.pixelHeight; 48829 48830 if (alignmentContainer.hasDownsampledIntervals()) { 48831 alignmentRowYInset = downsampleRowHeight + alignmentStartGap; 48832 alignmentContainer.downsampledIntervals.forEach(function (interval) { 48833 var xBlockStart = (interval.start - bpStart) / bpPerPixel, 48834 xBlockEnd = (interval.end - bpStart) / bpPerPixel; 48835 48836 if (xBlockEnd - xBlockStart > 5) { 48837 xBlockStart += 1; 48838 xBlockEnd -= 1; 48839 } 48840 48841 IGVGraphics.fillRect(ctx, xBlockStart, 2, xBlockEnd - xBlockStart, downsampleRowHeight - 2, { 48842 fillStyle: "black" 48843 }); 48844 }); 48845 } else { 48846 alignmentRowYInset = 0; 48847 } // Transient variable -- rewritten on every draw, used for click object selection 48848 48849 48850 this.alignmentsYOffset = alignmentRowYInset; 48851 const alignmentRowHeight = this.displayMode === "SQUISHED" ? this.squishedRowHeight : this.alignmentRowHeight; 48852 48853 if (packedAlignmentRows) { 48854 const nRows = packedAlignmentRows.length; 48855 48856 for (let rowIndex = 0; rowIndex < nRows; rowIndex++) { 48857 const alignmentRow = packedAlignmentRows[rowIndex]; 48858 const alignmentY = alignmentRowYInset + alignmentRowHeight * rowIndex; 48859 const alignmentHeight = alignmentRowHeight <= 4 ? al
48859ignmentRowHeight : alignmentRowHeight - 2; 48860 48861 if (alignmentY > pixelBottom) { 48862 break; 48863 } else if (alignmentY + alignmentHeight < pixelTop) { 48864 continue; 48865 } 48866 48867 for (let alignment of alignmentRow.alignments) { 48868 this.hasPairs = this.hasPairs || alignment.isPaired(); 48869 48870 if (this.browser.circularView && true === this.browser.circularViewVisible) { 48871 // This is an expensive check, only do it if needed 48872 this.hasSupplemental = this.hasSupplemental || alignment.hasTag('SA'); 48873 } 48874 48875 if (alignment.start + alignment.lengthOnRef < bpStart) continue; 48876 if (alignment.start > bpEnd) break; 48877 48878 if (true === alignment.hidden) { 48879 continue; 48880 } 48881 48882 if (alignment instanceof PairedAlignment) { 48883 drawPairConnector.call(this, alignment, alignmentY, alignmentHeight); 48884 drawSingleAlignment.call(this, alignment.firstAlignment, alignmentY, alignmentHeight); 48885 48886 if (alignment.secondAlignment) { 48887 drawSingleAlignment.call(this, alignment.secondAlignment, alignmentY, alignmentHeight); 48888 } 48889 } else { 48890 drawSingleAlignment.call(this, alignment, alignmentY, alignmentHeight); 48891 } 48892 } 48893 } 48894 } 48895 48896 ctx.restore(); // alignment is a PairedAlignment 48897 48898 function drawPairConnector(alignment, yRect, alignmentHeight) { 48899 var connectorColor = this.getConnectorColor(alignment.firstAlignment), 48900 xBlockStart = (alignment.connectingStart - bpStart) / bpPerPixel, 48901 xBlockEnd = (alignment.connectingEnd - bpStart) / bpPerPixel, 48902 yStrokedLine = yRect + alignmentHeight / 2; 48903 48904 if (alignment.connectingEnd < bpStart || alignment.connectingStart > bpEnd) { 48905 return; 48906 } 48907 48908 if (alignment.mq <= 0) { 48909 connectorColor = IGVColor.addAlpha(connectorColor, 0.15); 48910 } 48911 48912 IGVGraphics.setProperties(ctx, { 48913 fillStyle: connectorColor, 48914 strokeStyle: connectorColor 48915 }); 48916 IGVGraphics.strokeLine(ctx, xBlockStart, yStrokedLine, xBlockEnd, yStrokedLine); 48917 } 48918 48919 function drawSingleAlignment(alignment, yRect, alignmentHeight) { 48920 if (alignment.start + alignment.lengthOnRef < bpStart || alignment.start > bpEnd) { 48921 return; 48922 } 48923 48924 const blocks = showSoftClips ? alignment.blocks : alignment.blocks.filter(b => 'S' !== b.type); 48925 let alignmentColor = this.getAlignmentColor(alignment); 48926 const outlineColor = alignmentColor; 48927 48928 if (alignment.mq <= 0) { 48929 alignmentColor = IGVColor.addAlpha(alignmentColor, 0.15); 48930 } 48931 48932 IGVGraphics.setProperties(ctx, { 48933 fillStyle: alignmentColor, 48934 strokeStyle: outlineColor 48935 }); 48936 48937 for (let b = 0; b < blocks.length; b++) { 48938 // Can't use forEach here -- we need ability to break 48939 const block = blocks[b]; // Somewhat complex test, neccessary to insure gaps are drawn. 48940 // If this is not the last block, and the next block starts before the orign (off screen to left) then skip. 48941 48942 if (b !== blocks.length - 1 && blocks[b + 1].start < bpStart) continue; 48943 drawBlock.call(this, block, b); 48944 48945 if (block.start + block.len > bpEnd) { 48946 // Do this after drawBlock to insure gaps are drawn 48947 break; 48948 } 48949 } 48950 48951 if (alignment.insertions && this.parent.showInsertions) { 48952 let lastXBlockStart = -1; 48953 48954 for (let insertionBlock of alignment.insertions) { 48955 if (this.hideSmallIndels && insertionBlock.len <= this.indelSizeThreshold) { 48956 continue; 48957 } 48958 48959 if (insertionBlock.start < bpStart) { 48960 continue; 48961 } 48962 48963 if (insertionBlock.start > bpEnd) { 48964 break; 48965 } 48966 48967 const refOffset = insertionBlock.start - bpStart; 48968 const xBlockStart = refOffset / bpPerPixel - 1; 48969 48970 if (xBlockStart - lastXBlockStart > 2) { 48971 const widthBlock = 3; 48972 IGVGraphics.fillRect(ctx, xBlockStart, yRect - 1, widthBlock, alignmentHeight + 2, { 48973 fillStyle: this.insertionColor 48974 }); 48975 lastXBlockStart = xBlockStart; 48976 } 48977 } 48978 } 48979 48980 if (alignment.gaps) { 48981 const yStrokedLine = yRect + alignmentHeight / 2; 48982 48983 for (let gap of alignment.gaps) { 48984 const sPixel = (gap.start - bpStart) / bpPerPixel; 48985 const ePixel = (gap.start + gap.len - bpStart) / bpPerPixel; 48986 const color = "D" === gap.type ? this.deletionColor : this.skippedColor; 48987 IGVGraphics.strokeLine(ctx, sPixel, yStrokedLine, ePixel, yStrokedLine, { 48988 strokeStyle: color 48989 }); 48990 } 48991 } 48992 48993 function drawBlock(block, b) { 48994 const offsetBP = block.start - alignmentContainer.start; 48995 const blockStartPixel = (block.start - bpStart) / bpPerPixel; 48996 const blockEndPixel = (block.start + block.len - bpStart) / bpPerPixel; 48997 const blockWidthPixel = Math.max(1, blockEndPixel - blockStartPixel); //const arrowHeadWidthPixel = alignmentRowHeight / 2.0; 48998 48999 const nomPixelWidthOnRef = 100 / bpPerPixel; 49000 const arrowHeadWidthPixel = Math.min(alignmentRowHeight / 2.0, nomPixelWidthOnRef / 6); 49001 const isSoftClip = 'S' === block.type; 49002 const strokeOutline = alignment.mq <= 0 || this.highlightedAlignmentReadNamed === alignment.readName || isSoftClip; 49003 let blockOutlineColor = outlineColor; 49004 if (this.highlightedAlignmentReadNamed === alignment.readName) blockOutlineColor = 'red';else if (isSoftClip) blockOutlineColor = 'rgb(50,50,50)';
49005 const lastBlockPositiveStrand = true === alignment.strand && b === blocks.length - 1; 49006 const lastBlockReverseStrand = false === alignment.strand && b === 0; 49007 const lastBlock = lastBlockPositiveStrand | lastBlockReverseStrand; 49008 49009 if (lastBlock) { 49010 let xListPixel; 49011 let yListPixel; 49012 49013 if (lastBlockPositiveStrand) { 49014 xListPixel = [blockStartPixel, blockEndPixel, blockEndPixel + arrowHeadWidthPixel, blockEndPixel, blockStartPixel, blockStartPixel]; 49015 yListPixel = [yRect, yRect, yRect + alignmentHeight / 2.0, yRect + alignmentHeight, yRect + alignmentHeight, yRect]; 49016 } // Last block on - strand ? 49017 else if (lastBlockReverseStrand) { 49018 xListPixel = [blockEndPixel, blockStartPixel, blockStartPixel - arrowHeadWidthPixel, blockStartPixel, blockEndPixel, blockEndPixel]; 49019 yListPixel = [yRect, yRect, yRect + alignmentHeight / 2.0, yRect + alignmentHeight, yRect + alignmentHeight, yRect]; 49020 } 49021 49022 IGVGraphics.fillPolygon(ctx, xListPixel, yListPixel, { 49023 fillStyle: alignmentColor 49024 }); 49025 49026 if (strokeOutline) { 49027 IGVGraphics.strokePolygon(ctx, xListPixel, yListPixel, { 49028 strokeStyle: blockOutlineColor 49029 }); 49030 } 49031 } // Internal block 49032 else { 49033 IGVGraphics.fillRect(ctx, blockStartPixel, yRect, blockWidthPixel, alignmentHeight, { 49034 fillStyle: alignmentColor 49035 }); 49036 49037 if (strokeOutline) { 49038 ctx.save(); 49039 ctx.strokeStyle = blockOutlineColor; 49040 ctx.strokeRect(blockStartPixel, yRect, blockWidthPixel, alignmentHeight); 49041 ctx.restore(); 49042 } 49043 } // Read base coloring coloring 49044 49045 49046 if (isSoftClip || showAllBases || this.parent.showMismatches && referenceSequence && alignment.seq && alignment.seq !== "*") { 49047 const seq = alignment.seq ? alignment.seq.toUpperCase() : undefined; 49048 const qual = alignment.qual; 49049 const seqOffset = block.seqOffset; 49050 49051 for (let i = 0, len = block.len; i < len; i++) { 49052 if (offsetBP + i < 0) continue; 49053 let readChar = seq ? seq.charAt(seqOffset + i) : ''; 49054 const refChar = referenceSequence.charAt(offsetBP + i); 49055 49056 if (readChar === "=") { 49057 readChar = refChar; 49058 } 49059 49060 if (readChar === "X" || refChar !== readChar || isSoftClip || showAllBases) { 49061 let baseColor; 49062 49063 if (!isSoftClip && qual !== undefined && qual.length > seqOffset + i) { 49064 const readQual = qual[seqOffset + i]; 49065 baseColor = shadedBaseColor(readQual, nucleotideColors[readChar]); 49066 } else { 49067 baseColor = nucleotideColors[readChar]; 49068 } 49069 49070 if (baseColor) { 49071 const xPixel = (block.start + i - bpStart) / bpPerPixel; 49072 const widthPixel = Math.max(1, 1 / bpPerPixel); 49073 renderBlockOrReadChar(ctx, bpPerPixel, { 49074 x: xPixel, 49075 y: yRect, 49076 width: widthPixel, 49077 height: alignmentHeight 49078 }, baseColor, readChar); 49079 } 49080 } 49081 } 49082 } 49083 } 49084 49085 function renderBlockOrReadChar(context, bpp, bbox, color, char) { 49086 var threshold, center; 49087 threshold = 1.0 / 10.0; 49088 49089 if (bpp <= threshold && bbox.height >= 8) { 49090 // render letter 49091 const fontHeight = Math.min(10, bbox.height); 49092 context.font = '' + fontHeight + 'px sans-serif'; 49093 center = bbox.x + bbox.width / 2.0; 49094 IGVGraphics.strokeText(context, char, center - context.measureText(char).width / 2, fontHeight - 1 + bbox.y, { 49095 strokeStyle: color 49096 }); 49097 } else { 49098 // render colored block 49099 IGVGraphics.fillRect(context, bbox.x, bbox.y, bbox.width, bbox.height, { 49100 fillStyle: color 49101 }); 49102 } 49103 } 49104 } 49105 } 49106 49107 popupData(clickState) { 49108 const clickedObject = this.getClickedObject(clickState); 49109 return clickedObject ? clickedObject.popupData(clickState.genomicLocation) : undefined; 49110 } 49111 49112 contextMenuItemList(clickState) { 49113 const viewport = clickState.viewport; 49114 const list = []; 49115 49116 const sortByOption = option => { 49117 const cs = this.parent.sortObject; 49118 const direction = cs && cs.position === Math.floor(clickState.genomicLocation) ? !cs.direction : true; 49119 const newSortObject = { 49120 chr: viewport.referenceFrame.chr, 49121 position: Math.floor(clickState.genomicLocation), 49122 option: option, 49123 direction: direction 49124 }; 49125 this.parent.sortObject = newSortObject; 49126 sortAlignmentRows(newSortObject, viewport.getCachedFeatures()); 49127 viewport.repaint(); 49128 }; 49129 49130 list.push('<b>Sort by...</b>'); 49131 list.push({ 49132 label: ' base', 49133 click: () => sortByOption("BASE") 49134 }); 49135 list.push({ 49136 label: ' read strand', 49137 click: () => sortByOption("STRAND") 49138 }); 49139 list.push({ 49140 label: ' insert size', 49141 click: () => sortByOption("INSERT_SIZE") 49142 }); 49143 list.push({ 49144 label: ' gap size', 49145 click: () => sortByOption("GAP_SIZE") 49146 }); 49147 list.push({ 49148 label: ' chromosome of mate', 49149 click: () => sortByOption("MATE_CHR") 49150 }); 49151 list.push({ 49152 label: ' mapping quality', 49153 click: () => sortByOption("MQ") 49154 }); 49155 list.push({ 49156 label: ' read name', 49157 click: () => sortByOption("READ_NAME") 49158 }); 49159 list.push({ 49160 label: ' tag', 49161 click: () => { 49162 const cs = this.parent.sortObject; 49163 const direction = cs && cs.position === Math.floor(clickState.genomicLocation) ? !cs.direction : true; 49164 const config = { 49165 label: 'Tag Name', 49166 value: this.sortByTag ? this.sortByTag : '', 49167 callback: tag => { 49168 if (tag) { 49169 const newSortObject = { 49170 chr: viewport.referenceFrame.chr, 49171 position: Math.floor(clickState.genomicLocation), 49172 option: "TAG", 49173 tag: tag, 49174 direction: direction 49175 }; 49176 this.sortByTag = tag; 49177 this.parent.sortObject = newSortObject; 49178 sortAlignmentRows(newSortObject, viewport.getCachedFeatures()); 49179 viewport.repaint(); 49180 } 49181 } 49182 }; 49183 this.browser.inputDialog.present(config, clickState.event); 49184 } 49185 }); 49186 list.push('<hr/>'); 49187 const clickedObject = this.getClickedObject(clickState); 49188 49189 if (clickedObject) { 49190 const showSoftClips = this.parent.showSoftClips; 49191 const clickedAlignment = typeof clickedObject.alignmentContaining === 'function' ? clickedObject.alignmentContaining(clickState.genomicLocation, showSoftClips) : clickedObject; 49192 49193 if (clickedAlignment.isPaired() && clickedAlignment.isMateMapped()) { 49194 list.push({ 49195 label: 'View mate in split screen', 49196 click: () => { 49197 if (clickedAlignment.mate) { 49198 const referenceFrame = clickState.viewport.referenceFrame; 49199 49200 if (this.browser.genome.getChromosome(clickedAlignment.mate.chr)) { 49201 this.highlightedAlignmentReadNamed = clickedAlignment.readName; 49202 this.browser.presentMultiLocusPanel(clickedAlignment, referenceFrame); 49203 } else { 49204 Alert.presentAlert(`Reference does not contain chromosome: ${clickedAlignment.mate.chr}`); 49205 } 49206 } 49207 }, 49208 init: undefined 49209 }); 49210 } 49211 49212 list.push({ 49213 label: 'View read sequence', 49214 click: () => { 49215 const alignment = clickedAlignment; 49216 if (!alignment) return;
49217 const seqstring = alignment.seq; //.map(b => String.fromCharCode(b)).join(""); 49218 49219 if (!seqstring || "*" === seqstring) { 49220 Alert.presentAlert("Read sequence: *"); 49221 } else { 49222 Alert.presentAlert(seqstring); 49223 } 49224 } 49225 }); 49226 49227 if (isSecureContext()) { 49228 list.push({ 49229 label: 'Copy read sequence', 49230 click: () => { 49231 const alignment = clickedAlignment; 49232 if (!alignment) return; 49233 const seqstring = alignment.seq; //.map(b => String.fromCharCode(b)).join(""); 49234 49235 navigator.clipboard.writeText(seqstring); 49236 } 49237 }); 49238 } 49239 49240 list.push('<hr/>'); 49241 } // Experimental JBrowse feature 49242 49243 49244 if (this.browser.circularView && true === this.browser.circularViewVisible && (this.hasPairs || this.hasSupplemental)) { 49245 if (this.hasPairs) { 49246 list.push({ 49247 label: 'Add discordant pairs to circular view', 49248 click: () => { 49249 const maxFragmentLength = this.parent.maxFragmentLength; 49250 const { 49251 referenceFrame 49252 } = viewport; 49253 const inView = viewport.getCachedFeatures().allAlignments().filter(a => { 49254 return a.end >= referenceFrame.start && a.start <= referenceFrame.end && a.mate && a.mate.chr && (a.mate.chr !== a.chr || Math.max(a.fragmentLength) > maxFragmentLength); 49255 }); 49256 this.browser.circularViewVisible = true; 49257 const chords = makePairedAlignmentChords(inView); 49258 const color = IGVColor.addAlpha(this.parent.color || 'rgb(0,0,255)', 0.02); 49259 this.browser.circularView.addChords(chords, { 49260 track: this.parent.name, 49261 color: color 49262 }); 49263 } 49264 }); 49265 } 49266 49267 if (this.hasSupplemental) { 49268 list.push({ 49269 label: 'Add split reads to circular view', 49270 click: () => { 49271 const inView = []; 49272 49273 for (let a of viewport.getCachedFeatures().allAlignments()) { 49274 const referenceFrame = viewport.referenceFrame; 49275 const sa = a.hasTag('SA'); 49276 49277 if (a.end >= referenceFrame.start && a.start <= referenceFrame.end && sa) { 49278 inView.push(a); 49279 } 49280 } 49281 49282 const chords = makeSupplementalAlignmentChords(inView); 49283 const color = IGVColor.addAlpha(this.color || 'rgb(0,0,255)', 0.1); 49284 this.browser.circularView.addChords(chords, { 49285 track: this.name, 49286 color: color 49287 }); 49288 } 49289 }); 49290 } 49291 49292 list.push('<hr/>'); 49293 } 49294 49295 return list; 49296 } 49297 49298 getClickedObject(clickState) { 49299 const viewport = clickState.viewport; 49300 const y = clickState.y; 49301 const genomicLocation = clickState.genomicLocation; 49302 const showSoftClips = this.parent.showSoftClips; 49303 let features = viewport.getCachedFeatures(); 49304 if (!features || features.length === 0) return; 49305 let packedAlignmentRows = features.packedAlignmentRows; 49306 let downsampledIntervals = features.downsampledIntervals; 49307 const alignmentRowHeight = this.displayMode === "SQUISHED" ? this.squishedRowHeight : this.alignmentRowHeight; 49308 let packedAlignmentsIndex = Math.floor((y - this.top - this.alignmentsYOffset) / alignmentRowHeight); 49309 49310 if (packedAlignmentsIndex < 0) { 49311 for (let i = 0; i < downsampledIntervals.length; i++) { 49312 if (downsampledIntervals[i].start <= genomicLocation && downsampledIntervals[i].end >= genomicLocation) { 49313 return downsampledIntervals[i]; 49314 } 49315 } 49316 } else if (packedAlignmentsIndex < packedAlignmentRows.length) { 49317 const alignmentRow = packedAlignmentRows[packedAlignmentsIndex]; 49318 const clicked = alignmentRow.alignments.filter(alignment => alignment.containsLocation(genomicLocation, showSoftClips)); 49319 if (clicked.length > 0) return clicked[0]; 49320 } 49321 49322 return undefined; 49323 } 49324 49325 /** 49326 * Return the color for connectors in paired alignment view. If explicitly set return that, otherwise return 49327 * the alignment color, unless the color option can result in split colors (separte color for each mate). 49328 * 49329 * @param alignment 49330 * @returns {string} 49331 */ 49332 getConnectorColor(alignment) { 49333 if (this.pairConnectorColor) { 49334 return this.pairConnectorColor; 49335 } 49336 49337 switch (this.colorBy) { 49338 case "strand": 49339 case "firstOfPairStrand": 49340 case "pairOrientation": 49341 case "tag": 49342 return this.parent.color || DEFAULT_CONNECTOR_COLOR; 49343 49344 default: 49345 return this.getAlignmentColor(alignment); 49346 } 49347 } 49348 49349 getAlignmentColor(alignment) { 49350 let color = this.parent.color || DEFAULT_ALIGNMENT_COLOR; // The default color if nothing else applies 49351 49352 const option = this.colorBy; 49353 49354 switch (option) { 49355 case "strand":
49356 color = alignment.strand ? this.posStrandColor : this.negStrandColor; 49357 break; 49358 49359 case "firstOfPairStrand": 49360 if (alignment instanceof PairedAlignment) { 49361 color = alignment.firstOfPairStrand() ? this.posStrandColor : this.negStrandColor; 49362 } else if (alignment.isPaired()) { 49363 if (alignment.isFirstOfPair()) { 49364 color = alignment.strand ? this.posStrandColor : this.negStrandColor; 49365 } else if (alignment.isSecondOfPair()) { 49366 color = alignment.strand ? this.negStrandColor : this.posStrandColor; 49367 } else { 49368 console.error("ERROR. Paired alignments are either first or second."); 49369 } 49370 } 49371 49372 break; 49373 49374 case "unexpectedPair": 49375 case "pairOrientation": 49376 if (this.pairOrientation && alignment.pairOrientation) { 49377 var oTypes = orientationTypes[this.pairOrientation]; 49378 49379 if (oTypes) { 49380 var pairColor = this.pairColors[oTypes[alignment.pairOrientation]]; 49381 if (pairColor) color = pairColor; 49382 } 49383 } 49384 49385 if ("pairOrientation" === option) { 49386 break; 49387 } 49388 49389 case "fragmentLength": 49390 if (alignment.mate && alignment.isMateMapped() && alignment.mate.chr !== alignment.chr) { 49391 color = getChrColor(alignment.mate.chr); 49392 } else if (this.parent.minFragmentLength && Math.abs(alignment.fragmentLength) < this.parent.minFragmentLength) { 49393 color = this.smallFragmentLengthColor; 49394 } else if (this.parent.maxFragmentLength && Math.abs(alignment.fragmentLength) > this.parent.maxFragmentLength) { 49395 color = this.largeFragmentLengthColor; 49396 } 49397 49398 break; 49399 49400 case "tag": 49401 const tagValue = alignment.tags()[this.colorByTag]; 49402 49403 if (tagValue !== undefined) { 49404 if (this.bamColorTag === this.colorByTag) { 49405 // UCSC style color option 49406 color = "rgb(" + tagValue + ")"; 49407 } else { 49408 if (!this.tagColors) { 49409 this.tagColors = new PaletteColorTable("Set1"); 49410 } 49411 49412 color = this.tagColors.getColor(tagValue); 49413 } 49414 } 49415 49416 break; 49417 49418 default: 49419 color = this.parent.color || DEFAULT_ALIGNMENT_COLOR; 49420 } 49421 49422 return color; 49423 } 49424 49425 } 49426 49427 function sortAlignmentRows(options, alignmentContainer) { 49428 const direction = options.direction; 49429 49430 for (let row of alignmentContainer.packedAlignmentRows) { 49431 row.updateScore(options, alignmentContainer); 49432 } 49433 49434 alignmentContainer.packedAlignmentRows.sort(function (rowA, rowB) { 49435 const i = rowA.score > rowB.score ? 1 : rowA.score < rowB.score ? -1 : 0; 49436 return true === direction ? i : -i; 49437 }); // For debugging 49438 // for(let r of alignmentContainer.packedAlignmentRows) { 49439 // console.log(r.score); 49440 // } 49441 } 49442 49443 function shadedBaseColor(qual, baseColor) { 49444 const minQ = 5; //prefs.getAsInt(PreferenceManager.SAM_BASE_QUALITY_MIN), 49445 49446 const maxQ = 20; //prefs.getAsInt(PreferenceManager.SAM_BASE_QUALITY_MAX); 49447 49448 let alpha; 49449 49450 if (qual < minQ) { 49451 alpha = 0.1; 49452 } else { 49453 alpha = Math.max(0.1, Math.min(1.0, 0.1 + 0.9 * (qual - minQ) / (maxQ - minQ))); 49454 } // Round alpha to nearest 0.1 49455 49456 49457 alpha = Math.round(alpha * 10) / 10.0; 49458 49459 if (alpha < 1) { 49460 baseColor = IGVColor.addAlpha(baseColor, alpha); 49461 } 49462 49463 return baseColor; 49464 } 49465 49466 const orientationTypes = { 49467 "fr": { 49468 "F1R2": "LR", 49469 "F2R1": "LR", 49470 "F1F2": "LL", 49471 "F2F1": "LL", 49472 "R1R2": "RR", 49473 "R2R1": "RR", 49474 "R1F2": "RL", 49475 "R2F1": "RL" 49476 }, 49477 "rf": { 49478 "R1F2": "LR", 49479 "R2F1": "LR", 49480 "R1R2": "LL", 49481 "R2R1": "LL", 49482 "F1F2": "RR", 49483 "F2F1": "RR", 49484 "F1R2": "RL", 49485 "F2R1": "RL" 49486 }, 49487 "ff": { 49488 "F2F1": "LR", 49489 "R1R2": "LR", 49490 "F2R1": "LL", 49491 "R1F2": "LL", 49492 "R2F1": "RR", 49493 "F1R2": "RR", 49494 "R2R1": "RL", 49495 "F1F2": "RL" 49496 } 49497 }; 49498 function getChrColor(chr) { 49499 if (chrColorMap[chr]) { 49500 return chrColorMap[chr]; 49501 } else if (chrColorMap["chr" + chr]) { 49502 const color = chrColorMap["chr" + chr]; 49503 chrColorMap[chr] = color; 49504 return color; 49505 } else { 49506 const color = IGVColor.randomRGB(); 49507 chrColorMap[chr] = color; 49508 return color; 49509 } 49510 } 49511 const chrColorMap = { 49512 "chrX": "rgb(204, 153, 0)", 49513 "chrY": "rgb(153, 204, 0", 49514 "chrUn": "rgb(50, 50, 50)", 49515 "chr1": "rgb(80, 80, 255)", 49516 "chrI": "rgb(139, 155, 187)", 49517 "chr2": "rgb(206, 61, 50)", 49518 "chrII": "rgb(206, 61, 50)", 49519 "chr2a": "rgb(216, 71, 60)", 49520 "chr2b": "rgb(226, 81, 70)", 49521 "chr3": "rgb(116, 155, 88)", 49522 "chrIII": "rgb(116, 155, 88)", 49523 "chr4": "rgb(240, 230, 133)", 49524 "chrIV": "rgb(240, 230, 133)", 49525 "chr5": "rgb(70, 105, 131)", 49526 "chr6": "rgb(186, 99, 56)", 49527 "chr7": "rgb(93, 177, 221)", 49528 "chr8": "rgb(128, 34, 104)", 49529 "chr9": "rgb(107, 215, 107)", 49530 "chr10": "rgb(213, 149, 167)", 49531 "chr11": "rgb(146, 72, 34)", 49532 "chr12": "rgb(131, 123, 141)", 49533 "chr13": "rgb(199, 81, 39)", 49534 "chr14": "rgb(213, 143, 92)", 49535 "chr15": "rgb(122, 101, 165)", 49536 "chr16": "rgb(228, 175, 105)", 49537 "chr17": "rgb(59, 27, 83)", 49538 "chr18": "rgb(205, 222, 183)", 49539 "chr19": "rgb(97, 42, 121)", 49540 "chr20": "rgb(174, 31, 99)", 49541 "chr21": "rgb(231, 199, 111)", 49542 "chr22": "rgb(90, 101, 94)", 49543 "chr23": "rgb(204, 153, 0)", 49544 "chr24": "rgb(153, 204, 0)", 49545 "chr25": "rgb(51, 204, 0)", 49546 "chr26": "rgb(0, 204, 51)", 49547 "chr27": "rgb(0, 204, 153)", 49548 "chr28": "rgb(0, 153, 204)", 49549 "chr29": "rgb(10, 71, 255)", 49550 "chr30": "rgb(71, 117, 255)", 49551 "chr31": "rgb(255, 194, 10)", 49552 "chr32": "rgb(255, 209, 71)", 49553 "chr33": "rgb(153, 0, 51)", 49554 "chr34": "rgb(153, 26, 0)", 49555 "chr35": "rgb(153, 102, 0)", 49556 "chr36": "rgb(128, 153, 0)", 49557 "chr37": "rgb(51, 153, 0)", 49558 "chr38": "rgb(0, 153, 26)", 49559 "chr39": "rgb(0, 153, 102)", 49560 "chr40": "rgb(0, 128, 153)", 49561 "chr41": "rgb(0, 51, 153)", 49562 "chr42": "rgb(26, 0, 153)", 49563 "chr43": "rgb(102, 0, 153)", 49564 "chr44": "rgb(153, 0, 128)", 49565 "chr45": "rgb(214, 0, 71)", 49566 "chr46": "rgb(255, 20, 99)", 49567 "chr47": "rgb(0, 214, 143)", 49568 "chr48": "rgb(20, 255, 177)" 49569 }; 49570 49571 let timer;
49572 let currentViewport = undefined; 49573 const toolTipTimeout = 1e4; 49574 49575 class RulerViewport extends TrackViewport { 49576 constructor(trackView, $viewportColumn, referenceFrame, width) { 49577 super(trackView, $viewportColumn, referenceFrame, width); 49578 } 49579 49580 initializationHelper() { 49581 this.rulerSweeper = new RulerSweeper(this); 49582 this.$multiLocusCloseButton = $$1('<div>', { 49583 class: 'igv-multi-locus-close-button' 49584 }); 49585 this.$viewport.append(this.$multiLocusCloseButton); 49586 this.$multiLocusCloseButton.get(0).appendChild(createIcon$1("times-circle")); 49587 this.$multiLocusCloseButton.click(() => { 49588 this.browser.removeMultiLocusPanel(this.referenceFrame); 49589 }); 49590 this.$rulerLabel = $$1('<div>', { 49591 class: 'igv-multi-locus-ruler-label' 49592 }); 49593 this.$viewport.append(this.$rulerLabel); 49594 this.$rulerLabel.click(async () => { 49595 await this.browser.selectMultiLocusPanel(this.referenceFrame); // const removals = this.browser.referenceFrameList.filter(r => this.referenceFrame !== r) 49596 // for (let referenceFrame of removals) { 49597 // await this.browser.removeMultiLocusPanel(referenceFrame) 49598 // } 49599 }); 49600 this.$tooltip = $$1('<div>', { 49601 class: 'igv-ruler-tooltip' 49602 }); 49603 this.$tooltip.height(this.$viewport.height()); 49604 this.$viewport.append(this.$tooltip); 49605 this.$tooltipContent = $$1('<div>'); 49606 this.$tooltip.append(this.$tooltipContent); 49607 this.attachMouseHandlers(GenomeUtils.isWholeGenomeView(this.referenceFrame.chr)); 49608 this.$tooltip.hide(); 49609 this.dismissLocusLabel(); 49610 } 49611 49612 presentLocusLabel(viewportWidth) { 49613 const createRulerLabelString = () => { 49614 const html = `<div>${this.referenceFrame.getMultiLocusLabel(viewportWidth)}</div>`; 49615 return document.createRange().createContextualFragment(html).firstChild; 49616 }; 49617 49618 this.$rulerLabel.get(0).innerHTML = ''; 49619 this.$rulerLabel.get(0).style.backgroundColor = getChrColor(this.referenceFrame.chr); 49620 this.$rulerLabel.get(0).appendChild(createRulerLabelString()); 49621 this.$rulerLabel.show(); 49622 this.$multiLocusCloseButton.show(); 49623 } // Use in conjuction with .igv-multi-locus-ruler-label-square-dot css class (_dom-misc.scss) 49624 49625 49626 presentLocusLabel_Square_Dot(viewportWidth) { 49627 49628 const createRulerLabelDot = () => { 49629 const html = `<div> 49630 <?xml version="1.0" encoding="UTF-8"?> 49631 <svg width="14px" height="14px" viewBox="0 0 89 89" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> 49632 <g> 49633 <circle id="Oval" fill="${getChrColor(this.referenceFrame.chr)}" cx="44.5" cy="44.5" r="44.5"></circle> 49634 </g> 49635 </svg> 49636 </div>`; 49637 return document.createRange().createContextualFragment(html).firstChild; 49638 }; 49639 49640 const createRulerLabelString = () => { 49641 const html = `<div>${this.referenceFrame.getMultiLocusLabel(viewportWidth)}</div>`; 49642 return document.createRange().createContextualFragment(html).firstChild; 49643 }; 49644 49645 this.$rulerLabel.get(0).innerHTML = ''; 49646 this.$rulerLabel.get(0).appendChild(createRulerLabelDot()); 49647 this.$rulerLabel.get(0).appendChild(createRulerLabelString()); 49648 this.$rulerLabel.show(); 49649 this.$multiLocusCloseButton.show(); 49650 } 49651 49652 dismissLocusLabel() { 49653 this.$rulerLabel.hide(); 49654 this.$multiLocusCloseButton.hide(); 49655 } 49656 49657 attachMouseHandlers(isWholeGenomeView) { 49658 this.namespace = `.ruler_track_viewport_${this.browser.referenceFrameList.indexOf(this.referenceFrame)}`; 49659 this.$viewport.off(this.namespace); // console.log(`Ruler track ${ true === isWholeGenomeView ? 'is' : 'is not' } whole genome.`) 49660 49661 if (true === isWholeGenomeView) { 49662 const index = this.browser.referenceFrameList.indexOf(this.referenceFrame); 49663 const click = `click${this.namespace}`; 49664 this.$viewport.on(click, e => { 49665 const { 49666 x: pixel 49667 } = translateMouseCoordinates$1(e, this.$viewport.get(0)); 49668 const bp = Math.round(this.referenceFrame.start + this.referenceFrame.toBP(pixel)); 49669 let searchString; 49670 const { 49671 chr 49672 } = this.browser.genome.getChromosomeCoordinate(bp); 49673 49674 if (1 === this.browser.referenceFrameList.length) { 49675 searchString = chr; 49676 } else { 49677 let loci = this.browser.referenceFrameList.map(_ref => { 49678 let { 49679 locusSearchString 49680 } = _ref; 49681 return locusSearchString; 49682 }); 49683 loci[index] = chr; 49684 searchString = loci.join(' '); 49685 } 49686 49687 this.browser.search(searchString); 49688 }); 49689 this.$viewport.get(0).style.cursor = 'pointer'; 49690 } else { 49691 this.$viewport.get(0).style.cursor = 'default'; 49692 } 49693 } 49694 49695 mouseMove(event) { 49696 if (true === this.browser.cursorGuideVisible) { 49697 if (undefined === currentViewport) { 49698 currentViewport = this; 49699 this.$tooltip.show(); 49700 } else if (currentViewport.guid !== this.guid) { 49701 currentViewport.$tooltip.hide(); 49702 this.$tooltip.show(); 49703 currentViewport = this; 49704 } else { 49705 this.$tooltip.show(); 49706 } 49707 49708 const isWholeGenome = this.browser.isMultiLocusWholeGenomeView() || GenomeUtils.isWholeGenomeView(this.referenceFrame.chr); 49709 49710 if (isWholeGenome) { 49711 this.$tooltip.hide(); 49712 return; 49713 } 49714 49715 const { 49716 x 49717 } = translateMouseCoordinates$1(event, this.$viewport.get(0)); 49718 const { 49719 start, 49720 bpPerPixel 49721 } = this.referenceFrame; 49722 const bp = Math.round(0.5 + start + Math.max(0, x) * bpPerPixel); 49723 this.$tooltipContent.text(numberFormatter$1(bp)); 49724 const { 49725 width: ww 49726 } = this.$tooltipContent.get(0).getBoundingClientRect(); 49727 const { 49728 width: w 49729 } = this.$viewport.get(0).getBoundingClientRect(); 49730 this.$tooltip.css({ 49731 left: `${IGVMath.clamp(x, 0, w - ww)}px` 49732 }); // hide tooltip when movement stops 49733 49734 clearTimeout(timer); 49735 timer = setTimeout(() => this.$tooltip.hide(), toolTipTimeout); 49736 } 49737 } 49738 49739 startSpinner() {} 49740 49741 stopSpinner() {} 49742 49743 dispose() {
49744 this.rulerSweeper.dispose(); 49745 super.dispose(); 49746 } 49747 49748 } 49749 49750 /* 49751 * The MIT License (MIT) 49752 * 49753 * Copyright (c) 2014 Broad Institute 49754 * 49755 * Permission is hereby granted, free of charge, to any person obtaining a copy 49756 * of this software and associated documentation files (the "Software"), to deal 49757 * in the Software without restriction, including without limitation the rights 49758 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 49759 * copies of the Software, and to permit persons to whom the Software is 49760 * furnished to do so, subject to the following conditions: 49761 * 49762 * The above copyright notice and this permission notice shall be included in 49763 * all copies or substantial portions of the Software. 49764 * 49765 * 49766 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 49767 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 49768 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 49769 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 49770 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 49771 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 49772 * THE SOFTWARE. 49773 */ 49774 49775 class IdeogramViewport extends TrackViewport { 49776 constructor(trackView, viewportColumn, referenceFrame, width) { 49777 super(trackView, viewportColumn, referenceFrame, width); 49778 } 49779 49780 initializationHelper() { 49781 this.$ideogramCanvas = $$1('<canvas>', { 49782 class: 'igv-ideogram-canvas' 49783 }); 49784 this.$ideogramCanvas.insertBefore(this.$canvas); 49785 const canvas = this.$ideogramCanvas.get(0); 49786 this.ideogram_ctx = canvas.getContext('2d'); 49787 this.$canvas.remove(); 49788 this.canvas = undefined; 49789 this.ctx = undefined; 49790 this.addMouseHandlers(); 49791 } 49792 49793 addMouseHandlers() { 49794 this.addViewportClickHandler(this.$viewport.get(0)); 49795 } 49796 49797 removeMouseHandlers() { 49798 this.removeViewportClickHandler(this.$viewport.get(0)); 49799 } 49800 49801 addViewportClickHandler(viewport) { 49802 this.boundClickHandler = clickHandler.bind(this); 49803 viewport.addEventListener('click', this.boundClickHandler); 49804 49805 function clickHandler(event) { 49806 const { 49807 xNormalized, 49808 width 49809 } = translateMouseCoordinates$1(event, this.ideogram_ctx.canvas); 49810 const { 49811 bpLength 49812 } = this.browser.genome.getChromosome(this.referenceFrame.chr); 49813 const locusLength = this.referenceFrame.bpPerPixel * width; 49814 const chrCoveragePercentage = locusLength / bpLength; 49815 let xPercentage = xNormalized; 49816 49817 if (xPercentage - chrCoveragePercentage / 2.0 < 0) { 49818 xPercentage = chrCoveragePercentage / 2.0; 49819 } 49820 49821 if (xPercentage + chrCoveragePercentage / 2.0 > 1.0) { 49822 xPercentage = 1.0 - chrCoveragePercentage / 2.0; 49823 } 49824 49825 const ss = Math.round((xPercentage - chrCoveragePercentage / 2.0) * bpLength); 49826 const ee = Math.round((xPercentage + chrCoveragePercentage / 2.0) * bpLength); 49827 this.referenceFrame.start = ss; 49828 this.referenceFrame.end = ee; 49829 this.referenceFrame.bpPerPixel = (ee - ss) / width; 49830 this.browser.updateViews(this.referenceFrame, this.browser.trackViews, true); 49831 } 49832 } 49833 49834 removeViewportClickHandler(viewport) { 49835 viewport.removeEventListener('click', this.boundClickHandler); 49836 } 49837 49838 setWidth(width) { 49839 this.$viewport.width(width); 49840 } 49841 49842 drawSVGWithContext(context, width, height, id, x, y, yClipOffset) { 49843 context.saveWithTranslationAndClipRect(id, x, y, width, height, yClipOffset); 49844 this.trackView.track.draw({ 49845 context, 49846 referenceFrame: this.referenceFrame, 49847 pixelWidth: width, 49848 pixelHeight: height 49849 }); 49850 context.restore(); 49851 } 49852 49853 async repaint() { 49854 this.draw({ 49855 referenceFrame: this.referenceFrame 49856 }); 49857 } 49858 49859 draw(_ref) { 49860 let { 49861 referenceFrame 49862 } = _ref; 49863 this.$canvas.hide(); 49864 IGVGraphics.configureHighDPICanvas(this.ideogram_ctx, this.$viewport.width(), this.$viewport.height()); 49865 this.trackView.track.draw({ 49866 context: this.ideogram_ctx, 49867 referenceFrame, 49868 pixelWidth: this.$viewport.width(), 49869 pixelHeight: this.$viewport.height() 49870 }); 49871 } 49872 49873 startSpinner() {} 49874 49875 stopSpinner() {} 49876 49877 } 49878 49879 /* 49880 * The MIT License (MIT) 49881 * 49882 * Copyright (c) 2014 Broad Institute 49883 * 49884 * Permission is hereby granted, free of charge, to any person obtaining a copy 49885 * of this software and associated documentation files (the "Software"), to deal 49886 * in the Software without restriction, including without limitation the rights 49887 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 49888 * copies of the Software, and to permit persons to whom the Software is 49889 * furnished to do so, subject to the following conditions: 49890 * 49891 * The above copyright notice and this permission notice shall be included in 49892 * all copies or substantial portions of the Software. 49893 * 49894 * 49895 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 49896 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 49897 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 49898 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 49899 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 49900 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 49901 * THE SOFTWARE. 49902 */ 49903 /** 49904 * Test if the given value is a string or number. Not using typeof as it fails on boxed primitives. 49905 * 49906 * @param value 49907 * @returns boolean 49908 */ 49909 49910 49911 function isSimpleType(value) { 49912 const simpleTypes = new Set(["boolean", "number", "string", "symbol"]); 49913 const valueType = typeof value; 49914 return value !== undefined && (simpleTypes.has(valueType) || value.substring || value.toFixed); 49915 } 49916 49917 function buildOptions(config, options) { 49918 var defaultOptions = { 49919 oauthToken: config.oauthToken, 49920 headers: config.headers, 49921 withCredentials: config.withCredentials, 49922 filename: config.filename 49923 }; 49924 return Object.assign(defaultOptions, options); 49925 } 49926 /** 49927 * isMobile test from http://detectmobilebrowsers.com 49928 * TODO -- improve UI design so this isn't neccessary 49929 * @returns {boolean} 49930 */ 49931 // igv.isMobile = function () { 49932 // 49933 // const a = (navigator.userAgent || navigator.vendor || window.opera); 49934 // return (/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a) || 49935 // /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|
49935sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0, 4))) 49936 // 49937 // } 49938 49939 49940 const doAutoscale = function (features) { 49941 var min, max; 49942 49943 if (features.length > 0) { 49944 min = Number.MAX_VALUE; 49945 max = -Number.MAX_VALUE; 49946 features.forEach(function (f) { 49947 if (!Number.isNaN(f.value)) { 49948 min = Math.min(min, f.value); 49949 max = Math.max(max, f.value); 49950 } 49951 }); // Insure we have a zero baseline 49952 49953 if (max > 0) min = Math.min(0, min); 49954 if (max < 0) max = 0; 49955 } else { 49956 // No features -- default 49957 min = 0; 49958 max = 100; 49959 } 49960 49961 return { 49962 min: min, 49963 max: max 49964 }; 49965 }; 49966 49967 const validateLocusExtent = function (chromosomeLengthBP, extent, minimumBP) { 49968 let ss = extent.start; 49969 let ee = extent.end; 49970 49971 if (undefined === ee) { 49972 ss -= minimumBP / 2; 49973 ee = ss + minimumBP; 49974 49975 if (ee > chromosomeLengthBP) { 49976 ee = chromosomeLengthBP; 49977 ss = ee - minimumBP; 49978 } else if (ss < 0) { 49979 ss = 0; 49980 ee = minimumBP; 49981 } 49982 } else if (ee - ss < minimumBP) { 49983 const center = (ee + ss) / 2; 49984 49985 if (center - minimumBP / 2 < 0) { 49986 ss = 0; 49987 ee = ss + minimumBP; 49988 } else if (center + minimumBP / 2 > chromosomeLengthBP) { 49989 ee = chromosomeLengthBP; 49990 ss = ee - minimumBP; 49991 } else { 49992 ss = center - minimumBP / 2; 49993 ee = ss + minimumBP; 49994 } 49995 } 49996 49997 extent.start = Math.ceil(ss); 49998 extent.end = Math.floor(ee); 49999 }; 50000 /*! 50001 * is-number <https://github.com/jonschlinkert/is-number> 50002 * 50003 * Copyright (c) 2014-present, Jon Schlinkert. 50004 * Released under the MIT License. 50005 */ 50006 50007 50008 const isNumber = function (num) { 50009 if (typeof num === 'number') { 50010 return num - num === 0; 50011 } 50012 50013 if (typeof num === 'string' && num.trim() !== '') { 50014 return Number.isFinite ? Number.isFinite(+num) : isFinite(+num); 50015 } 50016 50017 return false; 50018 }; 50019 50020 async function getFilename(url) { 50021 if (isString$3(url) && url.startsWith("https://drive.google.com")) { 50022 // This will fail if Google API key is not defined 50023 if (getApiKey() === undefined) { 50024 throw Error("Google drive is referenced, but API key is not defined. An API key is required for Google Drive access"); 50025 } 50026 50027 const json = await getDriveFileInfo(url); 50028 return json.originalFileName || json.name; 50029 } else { 50030 return getFilename$1(url); 50031 } 50032 } 50033 50034 function prettyBasePairNumber(raw) { 50035 var denom, units, value, floored; 50036 50037 if (raw > 1e7) { 50038 denom = 1e6; 50039 units = " mb"; 50040 } else if (raw > 1e4) { 50041 denom = 1e3; 50042 units = " kb"; 50043 value = raw / denom; 50044 floored = Math.floor(value); 50045 return numberFormatter$1(floored) + units; 50046 } else { 50047 return numberFormatter$1(raw) + " bp"; 50048 } 50049 50050 value = raw / denom; 50051 floored = Math.floor(value); 50052 return floored.toString() + units; 50053 } 50054 50055 function isDataURL(obj) { 50056 return isString$3(obj) && obj.startsWith("data:"); 50057 } 50058 50059 function createColumn(columnContainer, className) { 50060 const column = div$1({ 50061 class: className 50062 }); 50063 columnContainer.appendChild(column); 50064 } 50065 50066 function insertElementBefore(element, referenceNode) { 50067 referenceNode.parentNode.insertBefore(element, referenceNode); 50068 } 50069 50070 function insertElementAfter(element, referenceNode) { 50071 referenceNode.parentNode.insertBefore(element, referenceNode.nextSibling); 50072 } 50073 50074 function createViewport(trackView, column, referenceFrame, width) { 50075 if ('ruler' === trackView.track.type) { 50076 return new RulerViewport(trackView, column, referenceFrame, width); 50077 } else if ('ideogram' === trackView.track.type) { 50078 return new IdeogramViewport(trackView, column, referenceFrame, width); 50079 } else { 50080 return new TrackViewport(trackView, column, referenceFrame, width); 50081 } 50082 } 50083 /** 50084 * Test to see if page is loaded in a secure context, that is by https or is localhost. 50085 */ 50086 50087 50088 function isSecureContext() { 50089 return window.location.protocol === "https:" || window.location.hostname === "localhost"; 50090 } 50091 50092 const maxFontSize = 10; 50093 const fontConfigureTemplate = { 50094 // font: '2pt sans-serif', 50095 textAlign: 'start', 50096 textBaseline: 'bottom', 50097 strokeStyle: 'black', 50098 fillStyle: 'black' 50099 }; 50100 50101 class SampleNameViewport { 50102 constructor(trackView, column, unused, width) { 50103 this.guid = guid$1(); 50104 this.trackView = trackView; 50105 this.browser = trackView.browser; 50106 this.viewport = div$1({ 50107 class: 'igv-viewport' 50108 }); 50109 column.appendChild(this.viewport); 50110 50111 if (trackView.track.height) { 50112 this.viewport.style.height = `${trackView.track.height}px`; 50113 } 50114 50115 this.canvas = document.createElement('canvas'); 50116 this.viewport.appendChild(this.canvas); 50117 this.ctx = this.canvas.getContext("2d"); 50118 this.trackScrollDelta = 0; 50119 this.contentTop = 0; 50120 this.setWidth(width); 50121 50122 if (false === this.browser.showSampleNames) { 50123 this.hide(); 50124 } 50125 50126 this.addMouseHandlers(); 50127 } 50128 50129 checkCanvas() { 50130 const dpi = window.devicePixelRatio; 50131 const requiredHeight = this.viewport.clientHeight; 50132 const requiredWidth = this.browser.sampleNameViewportWidth; 50133 50134 if (this.canvas.width !== requiredWidth * dpi || this.canvas.height !== requiredHeight * dpi) { 50135 const canvas = this.canvas; 50136 canvas.width = requiredWidth * dpi; 50137 canvas.height = requiredHeight * dpi; 50138 canvas.style.width = `${requiredWidth}px`; 50139 canvas.style.height = `${requiredHeight}px`; 50140 this.ctx = this.canvas.getContext("2d"); 50141 this.ctx.scale(dpi, dpi); 50142 } 50143 } 50144 50145 setTop(contentTop) { 50146 if (typeof this.trackView.track.getSamples === 'function') { 50147 this.contentTop = contentTop; 50148 const samples = this.trackView.track.getSamples(); 50149 this.repaint(samples); 50150 } 50151 } 50152 50153 setWidth(width) { 50154 this.viewport.innerWidth = width; 50155 this.checkCanvas(); 50156 } 50157 50158 show() { 50159 this.viewport.style.display = 'block'; 50160 } 50161 50162 hide() { 50163 this.viewport.style.display = 'none'; 50164 } 50165 50166 async repaint(samples) { 50167 this.checkCanvas(); 50168 this.draw({ 50169 context: this.ctx, 50170 samples 50171 }); 50172 } 50173 50174 draw(_ref) { 50175 let { 50176 context, 50177 samples 50178 } = _ref; 50179 50180 if (!samples || samples.names.length === 0
50181 /* || samples.height < 1*/ 50182 ) { 50183 return; 50184 } 50185 50186 configureFont(context, fontConfigureTemplate, samples.height); 50187 const sampleNameXShim = 4; 50188 context.clearRect(0, 0, context.canvas.width, context.canvas.height); 50189 context.fillStyle = appleCrayonRGB('lead'); 50190 const viewportHeight = this.viewport.getBoundingClientRect().height; 50191 let y = (samples.yOffset || 0) + this.contentTop; // contentTop will always be a negative number (top relative to viewport) 50192 50193 for (let name of samples.names) { 50194 if (y > viewportHeight) { 50195 break; 50196 } 50197 50198 if (y + samples.height > 0) { 50199 const text = name; 50200 const yFont = getYFont(context, text, y, samples.height); 50201 context.fillText(text, sampleNameXShim, yFont); 50202 } 50203 50204 y += samples.height; 50205 } 50206 } 50207 50208 renderSVGContext(context, _ref2) { 50209 let { 50210 deltaX, 50211 deltaY 50212 } = _ref2; 50213 50214 if (typeof this.trackView.track.getSamples === 'function') { 50215 const samples = this.trackView.track.getSamples(); 50216 const yScrollDelta = 0; // This is not relevant, scrolling is handled in "draw" 50217 50218 const { 50219 width, 50220 height 50221 } = this.viewport.getBoundingClientRect(); 50222 const str = (this.trackView.track.name || this.trackView.track.id).replace(/\W/g, ''); 50223 const id = `${str}_sample_names_guid_${guid$1()}`; 50224 context.saveWithTranslationAndClipRect(id, deltaX, deltaY + yScrollDelta, width, height, -yScrollDelta); 50225 this.draw({ 50226 context, 50227 samples 50228 }); 50229 context.restore(); 50230 } 50231 } 50232 50233 addMouseHandlers() { 50234 this.addViewportContextMenuHandler(this.viewport); 50235 } 50236 50237 removeMouseHandlers() { 50238 this.removeViewportContextMenuHandler(this.viewport); 50239 } 50240 50241 addViewportContextMenuHandler(viewport) { 50242 this.boundContextMenuHandler = contextMenuHandler.bind(this); 50243 viewport.addEventListener('contextmenu', this.boundContextMenuHandler); 50244 50245 function contextMenuHandler(event) { 50246 event.preventDefault(); 50247 event.stopPropagation(); 50248 const config = { 50249 label: 'Name Panel Width', 50250 value: this.browser.sampleNameViewportWidth, 50251 callback: newWidth => { 50252 this.browser.sampleNameViewportWidth = parseInt(newWidth); 50253 50254 for (let { 50255 sampleNameViewport 50256 } of this.browser.trackViews) { 50257 sampleNameViewport.setWidth(this.browser.sampleNameViewportWidth); 50258 } 50259 50260 this.browser.resize(); 50261 } 50262 }; 50263 this.browser.inputDialog.present(config, event); 50264 } 50265 } 50266 50267 removeViewportContextMenuHandler(viewport) { 50268 viewport.removeEventListener('contextmenu', this.boundContextMenuHandler); 50269 } 50270 50271 dispose() { 50272 this.removeMouseHandlers(); 50273 this.viewport.remove(); 50274 } 50275 50276 } 50277 50278 function getYFont(context, text, y, height) { 50279 return y + height - getSampleNameYShim(context, text, height); 50280 } 50281 50282 function getSampleNameYShim(context, text, h) { 50283 const { 50284 actualBoundingBoxAscent, 50285 actualBoundingBoxDescent 50286 } = context.measureText(text); 50287 return (h - (actualBoundingBoxAscent + actualBoundingBoxDescent)) / 2; 50288 } 50289 50290 function configureFont(ctx, _ref3, sampleHeight) { 50291 let { 50292 textAlign, 50293 textBaseline, 50294 strokeStyle, 50295 fillStyle 50296 } = _ref3; 50297 const pixels = Math.min(sampleHeight, maxFontSize); 50298 ctx.font = `${pixels}px sans-serif`; 50299 ctx.textAlign = textAlign; 50300 ctx.textBaseline = textBaseline; 50301 ctx.fillStyle = fillStyle; 50302 } 50303 50304 class GenericColorPicker extends GenericContainer { 50305 constructor(_ref) { 50306 let { 50307 parent, 50308 width 50309 } = _ref; 50310 super({ 50311 parent, 50312 width, 50313 border: '1px solid gray' 50314 }); 50315 } 50316 50317 configure(defaultColors, colorHandlers) { 50318 this.colorHandlers = colorHandlers; // active color handler defaults to handler with 'color' as key 50319 50320 this.setActiveColorHandler('color'); 50321 this.createSwatches(defaultColors); 50322 } 50323
50324 setActiveColorHandler(option) { 50325 this.activeColorHandler = this.colorHandlers[option]; 50326 } 50327 50328 createSwatches(defaultColors) { 50329 this.container.querySelectorAll('.igv-ui-color-swatch').forEach(swatch => swatch.remove()); 50330 const hexColorStrings = Object.values(appleCrayonPalette$1); 50331 50332 for (let hexColorString of hexColorStrings) { 50333 const swatch = div$1({ 50334 class: 'igv-ui-color-swatch' 50335 }); 50336 this.container.appendChild(swatch); 50337 this.decorateSwatch(swatch, hexColorString); 50338 } 50339 50340 if (defaultColors) { 50341 for (let hexColorString of defaultColors) { 50342 const swatch = div$1({ 50343 class: 'igv-ui-color-swatch' 50344 }); 50345 this.container.appendChild(swatch); 50346 this.decorateSwatch(swatch, hexColorString); 50347 } 50348 } 50349 } 50350 50351 decorateSwatch(swatch, hexColorString) { 50352 swatch.style.backgroundColor = hexColorString; 50353 swatch.addEventListener('mouseenter', () => swatch.style.borderColor = hexColorString); 50354 swatch.addEventListener('mouseleave', () => swatch.style.borderColor = 'white'); 50355 swatch.addEventListener('click', event => { 50356 event.stopPropagation(); 50357 this.activeColorHandler(hexColorString); 50358 }); 50359 swatch.addEventListener('touchend', event => { 50360 event.stopPropagation(); 50361 this.activeColorHandler(hexColorString); 50362 }); 50363 } 50364 50365 } 50366 50367 /* 50368 * The MIT License (MIT) 50369 * 50370 * Copyright (c) 2014 Broad Institute 50371 * 50372 * Permission is hereby granted, free of charge, to any person obtaining a copy 50373 * of this software and associated documentation files (the "Software"), to deal 50374 * in the Software without restriction, including without limitation the rights 50375 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 50376 * copies of the Software, and to permit persons to whom the Software is 50377 * furnished to do so, subject to the following conditions: 50378 * 50379 * The above copyright notice and this permission notice shall be included in 50380 * all copies or substantial portions of the Software. 50381 * 50382 * 50383 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 50384 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 50385 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 50386 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 50387 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 50388 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 50389 * THE SOFTWARE. 50390 */ 50391 50392 const MenuPopup = function (parent) { 50393 this.popover = div$1({ 50394 class: 'igv-menu-popup' 50395 }); 50396 parent.appendChild(this.popover); 50397 const header = div$1({ 50398 class: 'igv-menu-popup-header' 50399 }); 50400 this.popover.appendChild(header); 50401 attachDialogCloseHandlerWithParent$1(header, () => this.hide()); 50402 this.popoverContent = div$1(); 50403 this.popover.appendChild(this.popoverContent); 50404 makeDraggable$1(this.popover, header); 50405 header.addEventListener('click', e => { 50406 e.stopPropagation(); 50407 e.preventDefault(); // absorb click to prevent it leaking through to parent DOM element 50408 }); 50409 this.hide(); 50410 }; 50411 50412 MenuPopup.prototype.hide = function () { 50413 this.popover.style.display = 'none'; 50414 }; 50415 50416 MenuPopup.prototype.presentMenuList = function (menuList) { 50417 hideAllMenuPopups(); 50418 50419 if (menuList.length > 0) { 50420 this.popoverContent.innerHTML = ''; 50421 menuList = MenuUtils.trackMenuItemListHelper(menuList, this); 50422 50423 for (let item of menuList) { 50424 if (item.init) { 50425 item.init(); 50426 } 50427 50428 let $e = item.object; 50429 50430 if (0 === menuList.indexOf(item)) { 50431 $e.removeClass('igv-track-menu-border-top'); 50432 } 50433 50434 if ($e.hasClass('igv-track-menu-border-top') || $e.hasClass('igv-menu-popup-check-container')) ; else if ($e.is('div')) { 50435 $e.addClass('igv-menu-popup-shim'); 50436 } 50437 50438 this.popoverContent.appendChild($e.get(0)); 50439 } // NOTE: style.display most NOT be 'none' when calculating width. a display = 'none' will always 50440 // yield a width of zero (0). 50441 50442 50443 this.popover.style.display = 'flex'; 50444 const { 50445 width 50446 } = this.popover.getBoundingClientRect(); 50447 this.popover.style.left = `${-width}px`; 50448 this.popover.style.top = `${0}px`; 50449 } 50450 }; 50451 50452 MenuPopup.prototype.presentTrackContextMenu = function (e, menuItems) { 50453 this.popoverContent.innerHTML = ''; 50454 const menuElements = createMenuElements(menuItems, this.popover); 50455 50456 for (let { 50457 el 50458 } of menuElements) { 50459 this.popoverContent.appendChild(el); 50460 } 50461 50462 present(e, this.popover); 50463 }; 50464 50465 MenuPopup.prototype.dispose = function () { 50466 this.popoverContent.innerHTML = ''; 50467 this.popover.innerHTML = '';
50468 Object.keys(this).forEach(function (key) { 50469 this[key] = undefined; 50470 }); 50471 }; 50472 50473 function createMenuElements(itemList, popover) { 50474 return itemList.map(item => { 50475 let el; 50476 50477 if (typeof item === 'string' && '<hr/>' === item) { 50478 el = document.createElement('hr'); 50479 } else if (typeof item === 'string') { 50480 el = div$1({ 50481 class: 'context-menu' 50482 }); 50483 el.innerHTML = item; 50484 } else if (typeof item === 'Node') { 50485 el = item; 50486 } else { 50487 if (typeof item.init === 'function') { 50488 item.init(); 50489 } 50490 50491 if ("checkbox" === item.type) { 50492 el = createCheckbox$1("Show all bases", item.value); 50493 } else if ("color" === item.type) { 50494 const colorPicker = new GenericColorPicker({ 50495 parent: popover.parentElement, 50496 width: 364 50497 }); 50498 colorPicker.configure(undefined, { 50499 color: color => item.click(color) 50500 }); 50501 el = div$1({ 50502 class: 'context-menu' 50503 }); 50504 50505 if (typeof item.label === 'string') { 50506 el.innerHTML = item.label; 50507 } 50508 50509 const clickHandler = e => { 50510 colorPicker.show(); 50511 hide$1(popover); 50512 e.preventDefault(); 50513 e.stopPropagation(); 50514 }; 50515 50516 el.addEventListener('click', clickHandler); 50517 el.addEventListener('touchend', clickHandler); 50518 el.addEventListener('mouseup', function (e) { 50519 e.preventDefault(); 50520 e.stopPropagation(); 50521 }); 50522 } else { 50523 el = div$1({ 50524 class: 'context-menu' 50525 }); 50526 50527 if (typeof item.label === 'string') { 50528 el.innerHTML = item.label; 50529 } 50530 } 50531 50532 if (item.click && "color" !== item.type) { 50533 el.addEventListener('click', handleClick); 50534 el.addEventListener('touchend', handleClick); 50535 el.addEventListener('mouseup', function (e) { 50536 e.preventDefault(); 50537 e.stopPropagation(); 50538 }); // eslint-disable-next-line no-inner-declarations 50539 50540 function handleClick(e) { 50541 item.click(); 50542 hide$1(popover); 50543 e.preventDefault(); 50544 e.stopPropagation(); 50545 } 50546 } 50547 } 50548 50549 return { 50550 el, 50551 init: item.init 50552 }; 50553 }); 50554 } 50555 50556 function present(e, popover) { 50557 // NOTE: style.display most NOT be 'none' when calculating width. a display = 'none' will always 50558 // yield a width of zero (0). 50559 popover.style.display = 'flex'; 50560 const { 50561 x, 50562 y 50563 } = translateMouseCoordinates$1(e, popover.parentNode); 50564 const { 50565 width 50566 } = popover.getBoundingClientRect(); 50567 const xmax = x + width; 50568 const { 50569 width: parentWidth 50570 } = popover.parentNode.getBoundingClientRect(); 50571 popover.style.left = `${xmax > parentWidth ? x - (xmax - parentWidth) : x}px`; 50572 popover.style.top = `${y}px`; 50573 } 50574 50575 const hideAllMenuPopups = () => { 50576 const menus = document.querySelectorAll('.igv-menu-popup'); 50577 50578 for (let i = 0; i < menus.length; i++) { 50579 menus[i].style.display = 'none'; 50580 } 50581 }; 50582 50583 /* 50584 * The MIT License (MIT) 50585 * 50586 * Copyright (c) 2014 Broad Institute 50587 * 50588 * Permission is hereby granted, free of charge, to any person obtaining a copy 50589 * of this software and associated documentation files (the "Software"), to deal 50590 * in the Software without restriction, including without limitation the rights 50591 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 50592 * copies of the Software, and to permit persons to whom the Software is 50593 * furnished to do so, subject to the following conditions: 50594 * 50595 * The above copyright notice and this permission notice shall be included in 50596 * all copies or substantial portions of the Software. 50597 * 50598 * 50599 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 50600 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 50601 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 50602 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 50603 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 50604 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 50605 * THE SOFTWARE. 50606 */ 50607 const scrollbarExclusionTypes = new Set(['ruler', 'sequence', 'ideogram']); 50608 const colorPickerExclusionTypes = new Set(['ruler', 'sequence', 'ideogram']); 50609 50610 class TrackView { 50611 constructor(browser, columnContainer, track) { 50612 this.namespace = `trackview-${guid$1()}`; 50613 this.browser = browser; 50614 this.track = track; 50615 track.trackView = this; 50616 this.addDOMToColumnContainer(browser, columnContainer, browser.referenceFrameList); 50617 } 50618 /** 50619 * Start a spinner for the track on any of its viewports. In practice this is called during initialization 50620 * when there is only one. 50621 */ 50622 50623 50624 startSpinner() { 50625 if (this.viewports && this.viewports.length > 0) { 50626 this.viewports[0].startSpinner(); 50627 } 50628 } 50629 50630 stopSpinner() { 50631 if (this.viewports && this.viewports.length > 0) { 50632 this.viewports[0].stopSpinner(); 50633 } 50634 } 50635 50636 addDOMToColumnContainer(browser, columnContainer, referenceFrameList) { 50637 // Axis 50638 this.axis = this.createAxis(browser, this.track); // Track Viewports 50639 50640 this.viewports = []; 50641 const viewportWidth = browser.calculateViewportWidth(referenceFrameList.length); 50642 const viewportColumns = columnContainer.querySelectorAll('.igv-column'); 50643 50644 for (let i = 0; i < viewportColumns.length; i++) { 50645 const viewport = createViewport(this, viewportColumns[i], referenceFrameList[i], viewportWidth); 50646 this.viewports.push(viewport); 50647 } // SampleName Viewport 50648 50649 50650 this.sampleNameViewport = new SampleNameViewport(this, browser.columnContainer.querySelector('.igv-sample-name-column'), undefined, browser.sampleNameViewportWidth); // Track Scrollbar 50651 50652 this.createTrackScrollbar(browser); // Track Drag 50653 50654 this.createTrackDragHandle(browser); // Track Gear 50655 50656 this.createTrackGearPopup(browser); 50657 } 50658 50659 createAxis(browser, track) { 50660 const axis = div$1(); 50661 browser.columnContainer.querySelector('.igv-axis-column').appendChild(axis); 50662 axis.style.height = `${track.height}px`; 50663 50664 if (typeof track.paintAxis === 'function') { 50665 if (track.dataRange) { 50666 axis.addEventListener('click', () => { 50667 browser.dataRangeDialog.configure(this); 50668 browser.dataRangeDialog.present($$1(browser.columnContainer)); 50669 }); 50670 } 50671 50672 const { 50673 width, 50674 height 50675 } = axis.getBoundingClientRect(); 50676 this.axisCanvas = document.createElement('canvas'); 50677 this.axisCanvas.style.width = `${width}px`; 50678 this.axisCanvas.style.height = `${height}px`; 50679 axis.appendChild(this.axisCanvas); 50680 } 50681 50682 return axis; 50683 } 50684 50685 resizeAxisCanvas(width, height) { 50686 this.axis.style.width = `${width}px`; 50687 this.axis.style.height = `${height}px`; 50688 50689 if (typeof this.track.paintAxis === 'function') { 50690 // Size the canvas in CSS (logical) pixels. The buffer size will be set when painted. 50691 this.axisCanvas.style.width = `${width}px`; 50692 this.axisCanvas.style.height = `${height}px`; 50693 } 50694 } 50695 50696 removeDOMFromColumnContainer() { 50697 // Axis 50698 if (this.boundAxisClickHander) { 50699 this.removeAxisEventListener(this.axis); 50700 } 50701 50702 this.axis.remove(); // Track Viewports 50703 50704 for (let viewport of this.viewports) { 50705 viewport.removeMouseHandlers(); 50706 viewport.$viewport.remove(); 50707 } // SampleName Viewport 50708 50709
50710 this.sampleNameViewport.dispose(); // empty trackScrollbar Column 50711 50712 this.removeTrackScrollMouseHandlers(); 50713 this.outerScroll.remove(); // empty trackDrag Column 50714 50715 this.removeTrackDragMouseHandlers(); 50716 this.dragHandle.remove(); // empty trackGear Column 50717 50718 this.removeTrackGearMouseHandlers(); 50719 this.gearContainer.remove(); 50720 } 50721 50722 renderSVGContext(context, _ref) { 50723 let { 50724 deltaX, 50725 deltaY 50726 } = _ref; 50727 renderSVGAxis(context, this.track, this.axisCanvas, deltaX, deltaY); 50728 const { 50729 width: axisWidth 50730 } = this.axis.getBoundingClientRect(); 50731 const { 50732 y 50733 } = this.viewports[0].$viewport.get(0).getBoundingClientRect(); 50734 let delta = { 50735 deltaX: axisWidth + deltaX, 50736 deltaY: y + deltaY 50737 }; 50738 50739 for (let viewport of this.viewports) { 50740 viewport.renderSVGContext(context, delta); 50741 const { 50742 width 50743 } = viewport.$viewport.get(0).getBoundingClientRect(); 50744 delta.deltaX += width; 50745 } 50746 50747 if (true === this.browser.showSampleNames) { 50748 this.sampleNameViewport.renderSVGContext(context, delta); 50749 } 50750 } 50751 50752 dataRange() { 50753 return this.track.dataRange ? this.track.dataRange : undefined; 50754 } 50755 50756 setDataRange(min, max) { 50757 if (min !== undefined) { 50758 this.track.dataRange.min = min; 50759 } 50760 50761 if (max !== undefined) { 50762 this.track.dataRange.max = max; 50763 } 50764 50765 this.track.autoscale = false; 50766 this.repaintViews(); 50767 } 50768 50769 presentColorPicker(key) { 50770 if (false === colorPickerExclusionTypes.has(this.track.type)) { 50771 const trackColors = []; 50772 const color = this.track.color || this.track.defaultColor; 50773 50774 if (isString$3(color)) { 50775 trackColors.push(color); 50776 } 50777 50778 if (this.track.altColor && isString$3(this.track.altColor)) { 50779 trackColors.push(this.track.altColor); 50780 } 50781 50782 const defaultColors = trackColors.map(c => c.startsWith("#") ? c : c.startsWith("rgb(") ? IGVColor.rgbToHex(c) : IGVColor.colorNameToHex(c)); 50783 const colorHandlers = { 50784 color: color => { 50785 this.track.color = color; 50786 this.repaintViews(); 50787 }, 50788 altColor: color => { 50789 this.track.altColor = color; 50790 this.repaintViews(); 50791 } 50792 }; 50793 this.browser.genericColorPicker.configure(defaultColors, colorHandlers); 50794 this.browser.genericColorPicker.setActiveColorHandler(key); 50795 this.browser.genericColorPicker.show(); 50796 } 50797 } 50798 50799 setTrackHeight(newHeight, force) { 50800 if (!force) { 50801 if (this.track.minHeight) { 50802 newHeight = Math.max(this.track.minHeight, newHeight); 50803 } 50804 50805 if (this.track.maxHeight) { 50806 newHeight = Math.min(this.track.maxHeight, newHeight); 50807 } 50808 } 50809 50810 this.track.height = newHeight; 50811 this.resizeAxisCanvas(this.axis.clientWidth, this.track.height); 50812 50813 if (typeof this.track.paintAxis === 'function') { 50814 this.paintAxis(); 50815 } 50816 50817 for (let { 50818 $viewport 50819 } of this.viewports) { 50820 $viewport.height(newHeight); 50821 } 50822 50823 this.sampleNameViewport.viewport.style.height = `${newHeight}px`; // If the track does not manage its own content height set it here 50824 50825 if (typeof this.track.computePixelHeight !== "function") { 50826 for (let vp of this.viewports) { 50827 vp.setContentHeight(newHeight); 50828 } 50829 } 50830 50831 this.repaintViews(); 50832 50833 if (false === scrollbarExclusionTypes.has(this.track.type)) { 50834 this.updateScrollbar(); 50835 } 50836 50837 this.dragHandle.style.height = `${newHeight}px`; 50838 this.gearContainer.style.height = `${newHeight}px`; 50839 } 50840 50841 updateScrollbar() { 50842 const viewportHeight = this.viewports[0].$viewport.height(); 50843 this.outerScroll.style.height = `${viewportHeight}px`; 50844 const viewportContentHeight = maxViewportContentHeight(this.viewports);
50845 const innerScrollHeight = Math.round(viewportHeight / viewportContentHeight * viewportHeight); 50846 50847 if (viewportContentHeight > viewportHeight) { 50848 this.innerScroll.style.display = 'block'; 50849 this.innerScroll.style.height = `${innerScrollHeight}px`; 50850 } else { 50851 this.innerScroll.style.display = 'none'; 50852 } 50853 } 50854 50855 moveScroller(delta) { 50856 const y = $$1(this.innerScroll).position().top + delta; 50857 const top = Math.min(Math.max(0, y), this.outerScroll.clientHeight - this.innerScroll.clientHeight); 50858 $$1(this.innerScroll).css('top', `${top}px`); 50859 const contentHeight = maxViewportContentHeight(this.viewports); 50860 const contentTop = -Math.round(top * (contentHeight / this.viewports[0].$viewport.height())); 50861 50862 for (let viewport of this.viewports) { 50863 viewport.setTop(contentTop); 50864 } 50865 50866 this.sampleNameViewport.trackScrollDelta = delta; 50867 this.sampleNameViewport.setTop(contentTop); 50868 } 50869 50870 isLoading() { 50871 for (let viewport of this.viewports) { 50872 if (viewport.isLoading()) return true; 50873 } 50874 } 50875 50876 resize(viewportWidth) { 50877 for (let viewport of this.viewports) { 50878 viewport.setWidth(viewportWidth); 50879 } 50880 50881 this.updateViews(true); 50882 } 50883 /** 50884 * Repaint all viewports without loading any new data. Use this for events that change visual aspect of data, 50885 * e.g. color, sort order, etc, but do not change the genomic state. 50886 */ 50887 50888 50889 repaintViews() { 50890 for (let viewport of this.viewports) { 50891 viewport.repaint(); 50892 } 50893 50894 if (typeof this.track.paintAxis === 'function') { 50895 this.paintAxis(); 50896 } // Repaint sample names last 50897 50898 50899 this.repaintSamples(); 50900 } 50901 50902 repaintSamples() { 50903 if (typeof this.track.getSamples === 'function') { 50904 const samples = this.track.getSamples(); 50905 this.sampleNameViewport.repaint(samples); 50906 } 50907 } // track labels 50908 50909 50910 setTrackLabelName(name) { 50911 this.viewports.forEach(viewport => viewport.setTrackLabel(name)); 50912 } 50913 /** 50914 * Update viewports to reflect current genomic state, possibly loading additional data. 50915 */ 50916 50917 50918 async updateViews(force) { 50919 if (!(this.browser && this.browser.referenceFrameList)) return; 50920 const visibleViewports = this.viewports.filter(viewport => viewport.isVisible()); // Shift viewports left/right to current genomic state (pans canvas) 50921 50922 visibleViewports.forEach(viewport => viewport.shift()); 50923 const isDragging = this.browser.dragObject; 50924 50925 if (isDragging) { 50926 return; 50927 } // rpv: viewports whose image (canvas) does not fully cover current genomic range 50928 50929 50930 const reloadableViewports = this.viewportsToReload(force); // Trigger viewport to load features needed to cover current genomic range 50931 // NOTE: these must be loaded synchronously, do not user Promise.all, not all file readers are thread safe 50932 50933 for (let viewport of reloadableViewports) { 50934 await viewport.loadFeatures(); 50935 } // Very special case for variant tracks in multilocus view. The # of rows to allocate to the variant (site) 50936 // section depends on data from all the views. We only need to adjust this however if any data was loaded 50937 // (i.e. reloadableViewports.length > 0) 50938 50939 50940 if (typeof this.track.variantRowCount === 'function' && reloadableViewports.length > 0) { 50941 let maxRow = 0; 50942 50943 for (let viewport of this.viewports) { 50944 if (viewport.tile && viewport.tile.features) { 50945 maxRow = Math.max(maxRow, viewport.tile.features.reduce((a, f) => Math.max(a, f.row || 0), 0)); 50946 } 50947 } 50948 50949 const current = this.track.nVariantRows; 50950 50951 if (current !== maxRow + 1) { 50952 this.track.variantRowCount(maxRow + 1); 50953 50954 for (let viewport of this.viewports) { 50955 viewport.checkContentHeight(); 50956 } 50957 } 50958 } 50959 50960 if (this.disposed) return; // Track was removed during load 50961 50962 if (this.track.autoscale) { 50963 let allFeatures = []; 50964 50965 for (let visibleViewport of visibleViewports) { 50966 const referenceFrame = visibleViewport.referenceFrame; 50967 const start = referenceFrame.start; 50968 const end = start + referenceFrame.toBP($$1(visibleViewport.contentDiv).width()); 50969 50970 if (visibleViewport.tile && visibleViewport.tile.features) { 50971 if (typeof visibleViewport.tile.features.getMax === 'function') { 50972 const max = visibleViewport.tile.features.getMax(start, end); 50973 allFeatures.push({ 50974 value: max 50975 }); 50976 } else { 50977 allFeatures = allFeatures.concat(FeatureUtils.findOverlapping(visibleViewport.tile.features, start, end)); 50978 } 50979 } 50980 } 50981 50982 if (typeof this.track.doAutoscale === 'function') { 50983 this.track.dataRange = this.track.doAutoscale(allFeatures); 50984 } else { 50985 this.track.dataRange = doAutoscale(allFeatures); 50986 } 50987 } // Must repaint all viewports if autoscaling 50988 50989 50990 if (!isDragging && (this.track.autoscale || this.track.autoscaleGroup)) { 50991 for (let visibleViewport of visibleViewports) { 50992 visibleViewport.repaint(); 50993 } 50994 } else { 50995 for (let vp of reloadableViewports) { 50996 vp.repaint(); 50997 } 50998 } 50999 51000 this.adjustTrackHeight(); // Repaint sample names last 51001 51002 this.repaintSamples();
51003 this.updateRulerViewportLabels(); 51004 } 51005 51006 updateRulerViewportLabels() { 51007 const viewportWidth = this.browser.calculateViewportWidth(this.viewports.length); 51008 51009 for (let viewport of this.viewports) { 51010 if ('ruler' === this.track.type) { 51011 if (this.viewports.length > 1) { 51012 viewport.presentLocusLabel(viewportWidth); 51013 } else { 51014 viewport.dismissLocusLabel(); 51015 } 51016 } 51017 } 51018 } 51019 /** 51020 * Return a promise to get all in-view features. Used for group autoscaling. 51021 */ 51022 51023 51024 async getInViewFeatures(force) { 51025 if (!(this.browser && this.browser.referenceFrameList)) { 51026 return []; 51027 } // List of viewports that need reloading 51028 51029 51030 const rpV = this.viewportsToReload(force); 51031 const promises = rpV.map(function (vp) { 51032 return vp.loadFeatures(); 51033 }); 51034 await Promise.all(promises); 51035 let allFeatures = []; 51036 51037 for (let vp of this.viewports) { 51038 if (vp.tile && vp.tile.features) { 51039 const referenceFrame = vp.referenceFrame; 51040 const start = referenceFrame.start; 51041 const end = start + referenceFrame.toBP($$1(vp.contentDiv).width()); 51042 51043 if (typeof vp.tile.features.getMax === 'function') { 51044 const max = vp.tile.features.getMax(start, end); 51045 allFeatures.push({ 51046 value: max 51047 }); 51048 } else { 51049 allFeatures = allFeatures.concat(FeatureUtils.findOverlapping(vp.tile.features, start, end)); 51050 } 51051 } 51052 } 51053 51054 return allFeatures; 51055 } 51056 51057 checkContentHeight() { 51058 for (let viewport of this.viewports) { 51059 viewport.checkContentHeight(); 51060 } 51061 51062 this.adjustTrackHeight(); 51063 } 51064 51065 adjustTrackHeight() { 51066 var maxHeight = maxViewportContentHeight(this.viewports); 51067 51068 if (this.track.autoHeight) { 51069 this.setTrackHeight(maxHeight, false); 51070 } else if (this.track.paintAxis) { 51071 // Avoid duplication, paintAxis is already called in setTrackHeight 51072 this.paintAxis(); 51073 } 51074 51075 if (false === scrollbarExclusionTypes.has(this.track.type)) { 51076 const currentTop = this.viewports[0].getContentTop(); 51077 const heights = this.viewports.map(viewport => viewport.getContentHeight()); 51078 const minContentHeight = Math.min(...heights); 51079 const newTop = Math.min(0, this.viewports[0].$viewport.height() - minContentHeight); 51080 51081 if (currentTop < newTop) { 51082 for (let viewport of this.viewports) { 51083 viewport.$content.css('top', `${newTop}px`); 51084 } 51085 } 51086 51087 this.updateScrollbar(); 51088 } 51089 } 51090 51091 viewportsToReload(force) { 51092 // List of viewports that need reloading 51093 const viewports = this.viewports.filter(viewport => { 51094 if (!viewport.isVisible()) { 51095 return false; 51096 } 51097 51098 if (!viewport.checkZoomIn()) { 51099 return false; 51100 } else { 51101 const referenceFrame = viewport.referenceFrame; 51102 const chr = viewport.referenceFrame.chr; 51103 const start = referenceFrame.start; 51104 const end = start + referenceFrame.toBP($$1(viewport.contentDiv).width()); 51105 const bpPerPixel = referenceFrame.bpPerPixel; 51106 return force || !viewport.tile || viewport.tile.invalidate || !viewport.tile.containsRange(chr, start, end, bpPerPixel); 51107 } 51108 }); 51109 return viewports; 51110 } 51111 51112 createTrackScrollbar(browser) { 51113 const outerScroll = div$1(); 51114 browser.columnContainer.querySelector('.igv-scrollbar-column').appendChild(outerScroll); 51115 outerScroll.style.height = `${this.track.height}px`; 51116 this.outerScroll = outerScroll; 51117 51118 if (false === scrollbarExclusionTypes.has(this.track.type)) { 51119 const innerScroll = div$1(); 51120 outerScroll.appendChild(innerScroll); 51121 this.innerScroll = innerScroll; 51122 this.addTrackScrollMouseHandlers(browser); 51123 } 51124 } 51125 51126 createTrackDragHandle(browser) { 51127 const className = 'ideogram' === this.track.type || 'ruler' === this.track.type ? 'igv-track-drag-shim' : 'igv-track-drag-handle'; 51128 this.dragHandle = div$1({ 51129 class: className 51130 }); 51131 browser.columnContainer.querySelector('.igv-track-drag-column').appendChild(this.dragHandle); 51132 this.dragHandle.style.height = `${this.track.height}px`; 51133 this.addTrackDragMouseHandlers(browser); 51134 } 51135 51136 createTrackGearPopup(browser) { 51137 this.gearContainer = div$1(); 51138 browser.columnContainer.querySelector('.igv-gear-menu-column').appendChild(this.gearContainer); 51139 this.gearContainer.style.height = `${this.track.height}px`; 51140 51141 if (true === this.track.ignoreTrackMenu) ; else { 51142 this.gear = div$1(); 51143 this.gearContainer.appendChild(this.gear); 51144 this.gear.appendChild(createIcon$1('cog')); 51145 this.trackGearPopup = new MenuPopup(this.gear); 51146 this.addTrackGearMouseHandlers(); 51147 } 51148 } 51149 51150 addAxisEventListener(axis) { 51151 this.boundAxisClickHander = axisClickHandler.bind(this); 51152 axis.addEventListener('click', this.boundAxisClickHander); 51153 51154 function axisClickHandler(event) { 51155 this.browser.dataRangeDialog.configure(this); 51156 this.browser.dataRangeDialog.present($$1(this.browser.columnContainer)); 51157 } 51158 } 51159 51160 removeAxisEventListener(axis) { 51161 axis.removeEventListener('click', this.boundAxisClickHander); 51162 } 51163 51164 addTrackScrollMouseHandlers(browser) { 51165 // Mouse Down 51166 this.boundTrackScrollMouseDownHandler = trackScrollMouseDownHandler.bind(this); 51167 this.innerScroll.addEventListener('mousedown', this.boundTrackScrollMouseDownHandler); 51168 51169 function trackScrollMouseDownHandler(event) { 51170 event.stopPropagation(); 51171 const { 51172 y 51173 } = pageCoordinates$1(event); 51174 $$1(this.innerScroll).data('yDown', y.toString()); 51175 this.boundColumnContainerMouseMoveHandler = columnContainerMouseMoveHandler.bind(this); 51176 browser.columnContainer.addEventListener('mousemove', this.boundColumnContainerMouseMoveHandler); 51177 51178 function columnContainerMouseMoveHandler(event) { 51179 event.stopPropagation(); 51180 const { 51181 y 51182 } = pageCoordinates$1(event); 51183 this.moveScroller(y - parseInt($$1(this.innerScroll).data('yDown'))); 51184 $$1(this.innerScroll).data('yDown', y.toString()); 51185 } 51186 } 51187 51188 this.boundColumnContainerMouseUpHandler = columnContainerMouseUpHandler.bind(this); 51189 browser.columnContainer.addEventListener('mouseup', this.boundColumnContainerMouseUpHandler); 51190 51191 function columnContainerMouseUpHandler(event) { 51192 browser.columnContainer.removeEventListener('mousemove', this.boundColumnContainerMouseMoveHandler); 51193 } 51194 } 51195 51196 removeTrackScrollMouseHandlers() { 51197 if (false === scrollbarExclusionTypes.has(this.track.type)) { 51198 this.innerScroll.removeEventListener('mousedown', this.boundTrackScrollMouseDownHandler); 51199 this.browser.columnContainer.removeEventListener('mouseup', this.boundColumnContainerMouseUpHandler); 51200 this.browser.columnContainer.removeEventListener('mousemove', this.boundColumnContainerMouseMoveHandler); 51201 } 51202 } 51203 51204 addTrackDragMouseHandlers(browser) { 51205 if ('ideogram' === this.track.type || 'ruler' === this.track.type) ; else { 51206 let currentDragHandle = undefined; // Mouse Down 51207 51208 this.boundTrackDragMouseDownHandler = trackDragMouseDownHandler.bind(this); 51209 this.dragHandle.addEventListener('mousedown', this.boundTrackDragMouseDownHandler); 51210 51211 function trackDragMouseDownHandler(event) { 51212 event.preventDefault(); 51213 currentDragHandle = event.target; 51214 currentDragHandle.classList.add('igv-track-drag-handle-hover'); 51215 browser.startTrackDrag(this); 51216 } // Mouse Up 51217 51218 51219 this.boundDocumentTrackDragMouseUpHandler = documentTrackDragMouseUpHandler.bind(this); 51220 document.addEventListener('mouseup', this.boundDocumentTrackDragMouseUpHandler); 51221 51222 function documentTrackDragMouseUpHandler(event) { 51223 // console.log(`${ Date.now() } TrackView - documentTrackDragMouseUpHandler - target ${ event.target.nodeName }`) 51224 browser.endTrackDrag(); 51225 51226 if (currentDragHandle && event.target !== currentDragHandle) { 51227 currentDragHandle.classList.remove('igv-track-drag-handle-hover'); 51228 } 51229 51230 currentDragHandle = undefined; 51231 } // Mouse Enter 51232 51233 51234 this.boundTrackDragMouseEnterHandler = trackDragMouseEnterHandler.bind(this); 51235 this.dragHandle.addEventListener('mouseenter', this.boundTrackDragMouseEnterHandler); 51236 51237 function trackDragMouseEnterHandler(event) { 51238 event.preventDefault(); 51239 51240 if (undefined === currentDragHandle) { 51241 event.target.classList.add('igv-track-drag-handle-hover'); 51242 } 51243 51244 browser.updateTrackDrag(this); 51245 } // Mouse Out 51246 51247 51248 this.dragHandle.addEventListener('mouseout', e => { 51249 e.preventDefault(); 51250 51251 if (undefined === currentDragHandle) { 51252 e.target.classList.remove('igv-track-drag-handle-hover'); 51253 } 51254 }); 51255 this.boundTrackDragMouseOutHandler = trackDragMouseOutHandler.bind(this); 51256 this.dragHandle.addEventListener('mouseout', this.boundTrackDragMouseOutHandler); 51257 51258 function trackDragMouseOutHandler(event) { 51259 event.preventDefault(); 51260 51261 if (undefined === currentDragHandle) { 51262 event.target.classList.remove('igv-track-drag-handle-hover'); 51263 } 51264 } 51265 } 51266 } 51267 51268 removeTrackDragMouseHandlers() { 51269 if ('ideogram' === this.track.type || 'ruler' === this.track.type) ; else { 51270 this.dragHandle.removeEventListener('mousedown', this.boundTrackDragMouseDownHandler); 51271 document.removeEventListener('mouseup', this.boundDocumentTrackDragMouseUpHandler); 51272 this.dragHandle.removeEventListener('mouseup', this.boundTrackDragMouseEnterHandler); 51273 this.dragHandle.removeEventListener('mouseout', this.boundTrackDragMouseOutHandler); 51274 } 51275 } 51276 51277 addTrackGearMouseHandlers() { 51278 if (true === this.track.ignoreTrackMenu) ; else { 51279 this.boundTrackGearClickHandler = trackGearClickHandler.bind(this); 51280 this.gear.addEventListener('click', this.boundTrackGearClickHandler); 51281 51282 function trackGearClickHandler(event) { 51283 event.preventDefault(); 51284 event.stopPropagation(); 51285 this.trackGearPopup.presentMenuList(MenuUtils.trackMenuItemList(this)); 51286 } 51287 } 51288 } 51289 51290 removeTrackGearMouseHandlers() { 51291 if (true === this.track.ignoreTrackMenu) ; else { 51292 this.gear.removeEventListener('click', this.boundTrackGearClickHandler); 51293 } 51294 } 51295 /** 51296 * Do any cleanup here 51297 */ 51298 51299 51300 dispose() { 51301 this.removeAxisEventListener(this.axis); 51302 this.axis.remove(); 51303 51304 for (let viewport of this.viewports) {
51305 viewport.dispose(); 51306 } 51307 51308 this.sampleNameViewport.dispose(); 51309 this.removeTrackScrollMouseHandlers(); 51310 this.outerScroll.remove(); 51311 this.removeTrackDragMouseHandlers(); 51312 this.dragHandle.remove(); 51313 this.removeTrackGearMouseHandlers(); 51314 this.gearContainer.remove(); 51315 51316 if (typeof this.track.dispose === "function") { 51317 this.track.dispose(); 51318 } // TODO: Perhaps better done in track/trackBase 51319 51320 51321 const track = this.track; 51322 51323 if (typeof track.dispose === 'function') { 51324 track.dispose(); 51325 } 51326 51327 for (let key of Object.keys(track)) { 51328 track[key] = undefined; 51329 } 51330 51331 for (let key of Object.keys(this)) { 51332 this[key] = undefined; 51333 } 51334 51335 if (this.alert) { 51336 this.alert.container.remove(); // This is quite obviously a hack, need a "dispose" method on AlertDialog 51337 } 51338 51339 this.disposed = true; 51340 } 51341 51342 paintAxis() { 51343 if (typeof this.track.paintAxis === 'function') { 51344 // Set the canvas buffer size, this is the resolution it is drawn at. This is done here in case the browser 51345 // has been drug between screens at different dpi resolutions since the last repaint 51346 const { 51347 width, 51348 height 51349 } = this.axisCanvas.getBoundingClientRect(); 51350 const dpi = window.devicePixelRatio || 1; 51351 this.axisCanvas.height = dpi * height; 51352 this.axisCanvas.width = dpi * width; // Get a scaled context to draw aon 51353 51354 const axisCanvasContext = this.axisCanvas.getContext('2d'); 51355 axisCanvasContext.scale(dpi, dpi); 51356 this.track.paintAxis(axisCanvasContext, width, height); 51357 } 51358 } 51359 51360 } 51361
51362 function renderSVGAxis(context, track, axisCanvas, deltaX, deltaY) { 51363 if (typeof track.paintAxis === 'function') { 51364 const { 51365 y, 51366 width, 51367 height 51368 } = axisCanvas.getBoundingClientRect(); 51369 const str = (track.name || track.id).replace(/\W/g, ''); 51370 const id = `${str}_axis_guid_${guid$1()}`; 51371 context.saveWithTranslationAndClipRect(id, deltaX, y + deltaY, width, height, 0); 51372 track.paintAxis(context, width, height); 51373 context.restore(); 51374 } 51375 } // css - $igv-axis-column-width: 50px; 51376 51377 51378 const igv_axis_column_width = 50; 51379 51380 function maxViewportContentHeight(viewports) { 51381 const heights = viewports.map(viewport => viewport.getContentHeight()); 51382 return Math.max(...heights); 51383 } 51384 51385 /** 51386 * Decoder for bedpe records. 51387 * 51388 * Bedpe format was created by Aaron Quinlan et al as part of the bedtools project. 51389 * The spec is here: https://bedtools.readthedocs.io/en/latest/content/general-usage.html, however there 51390 * are off spec variants, an important one being a 7 column format with score in place of the standard 51391 * name column. 51392 * 51393 * Another common variant is a "hiccups" output file, which is standard bedpe with the exception of a header line 51394 * of the form 51395 * chr1 x1 x2 chr2 y1 y2 name score strand1 strand2 color observed expectedBL expectedDonut expectedH expectedV fdrBL fdrDonut fdrH fdrV 51396 * 51397 * @param tokens 51398 * @param ignore 51399 * @returns {{start1: number, end2: number, end1: number, chr1: *, chr2: *, start2: number}|undefined} 51400 */ 51401 51402 function decodeBedpe(tokens, header) { 51403 if (tokens.length < 6) { 51404 console.log("Skipping line: " + tokens.join(' ')); 51405 return undefined; 51406 } 51407 51408 var feature = { 51409 chr1: tokens[0], 51410 start1: Number.parseInt(tokens[1]), 51411 end1: Number.parseInt(tokens[2]), 51412 chr2: tokens[3], 51413 start2: Number.parseInt(tokens[4]), 51414 end2: Number.parseInt(tokens[5]) 51415 }; 51416 51417 if (isNaN(feature.start1) || isNaN(feature.end1) || isNaN(feature.start2) || isNaN(feature.end2)) { 51418 //throw Error(`Error parsing line: ${tokens.join('\t')}`); 51419 return undefined; 51420 } 51421 51422 if (tokens.length > 6 && tokens[6] !== ".") { 51423 feature.name = tokens[6]; 51424 } 51425 51426 if (tokens.length > 7 && tokens[7] !== ".") { 51427 feature.score = Number(tokens[7]); 51428 } 51429 51430 if (tokens.length > 8 && tokens[8] !== ".") { 51431 feature.strand1 = tokens[8]; 51432 } 51433 51434 if (tokens.length > 9 && tokens[9] !== ".") { 51435 feature.strand2 = tokens[9]; 51436 } // Optional extra columns 51437 51438 51439 if (header) { 51440 const colorColumn = header.colorColumn; 51441 51442 if (colorColumn && colorColumn < tokens.length) { 51443 feature.color = IGVColor.createColorString(tokens[colorColumn]); 51444 } 51445 51446 const thicknessColumn = header.thicknessColumn; 51447 51448 if (thicknessColumn && thicknessColumn < tokens.length) { 51449 feature.thickness = tokens[thicknessColumn]; 51450 } 51451 51452 if (tokens.length > 10 && header.columnNames && header.columnNames.length === tokens.length) { 51453 feature.extras = tokens.slice(10); 51454 } 51455 } // Set total extent of feature 51456 51457 51458 if (feature.chr1 === feature.chr2) { 51459 feature.chr = feature.chr1; 51460 feature.start = Math.min(feature.start1, feature.start2); 51461 feature.end = Math.max(feature.end1, feature.end2); 51462 } 51463 51464 return feature; 51465 } 51466 /** 51467 * Hack for non-standard bedPE formats, where numeric score can be in column 7 (name field from spec) 51468 * @param features 51469 */ 51470 51471 51472 function fixBedPE(features) { 51473 if (features.length == 0) return; // Assume all features have same properties 51474 51475 const firstFeature = features[0]; 51476 51477 if (firstFeature.score === undefined && firstFeature.name !== undefined) { 51478 // Name field (col 7) is sometimes used for score. 51479 for (let f of features) { 51480 if (!(isNumber(f.name) || f.name === '.')) return; 51481 } 51482 51483 for (let f of features) { 51484 f.score = Number(f.name); 51485 delete f.name; 51486 } 51487 } // Make copies of inter-chr features, one for each chromosome 51488 51489 51490 const interChrFeatures = features.filter(f => f.chr1 !== f.chr2); 51491 51492 for (let f1 of interChrFeatures) { 51493 const f2 = Object.assign({}, f1); 51494 f2.dup = true; 51495 features.push(f2); 51496 f1.chr = f1.chr1; 51497 f1.start = f1.start1; 51498 f1.end = f1.end1; 51499 f2.chr = f2.chr2; 51500 f2.start = f2.start2; 51501 f2.end = f2.end2; 51502 } 51503 } 51504 /** 51505 * Special decoder for Hic Domain files. In these files feature1 == feature2, they are really bed records. 51506 * @param tokens 51507 * @param ignore 51508 * @returns {*} 51509 */ 51510 51511 51512 function decodeBedpeDomain(tokens, header) { 51513 if (tokens.length < 8) return undefined; 51514 return { 51515 chr: tokens[0], 51516 start: Number.parseInt(tokens[1]), 51517 end: Number.parseInt(tokens[2]), 51518 color: IGVColor.createColorString(tokens[6]), 51519 value: Number(tokens[7]) 51520 }; 51521 } 51522 51523 /** 51524 * Decode UCSC "interact" files. See https://genome.ucsc.edu/goldenpath/help/interact.html 51525 * 51526 0 string chrom; "Chromosome (or contig, scaffold, etc.). For interchromosomal, use 2 records" 51527 1 uint chromStart; "Start position of lower region. For interchromosomal, set to chromStart of this region" 51528 2 uint chromEnd; "End position of upper region. For interchromosomal, set to chromEnd of this region"
51529 3 string name; "Name of item, for display. Usually 'sourceName/targetName/exp' or empty" 51530 4 uint score; "Score (0-1000)" 51531 5 double value; "Strength of interaction or other data value. Typically basis for score" 51532 6 string exp; "Experiment name (metadata for filtering). Use . if not applicable" 51533 7 string color; "Item color. Specified as r,g,b or hexadecimal #RRGGBB or html color name, as in //www.w3.org/TR/css3-color/#html4. Use 0 and spectrum setting to shade by score" 51534 8 string sourceChrom; "Chromosome of source region (directional) or lower region. For non-directional interchromosomal, chrom of this region." 51535 9 uint sourceStart; "Start position in chromosome of source/lower/this region" 51536 10 uint sourceEnd; "End position in chromosome of source/lower/this region" 51537 11 string sourceName; "Identifier of source/lower/this region" 51538 12 string sourceStrand; "Orientation of source/lower/this region: + or -. Use . if not applicable" 51539 13 string targetChrom; "Chromosome of target region (directional) or upper region. For non-directional interchromosomal, chrom of other region" 51540 14 uint targetStart; "Start position in chromosome of target/upper/this region" 51541 15 uint targetEnd; "End position in chromosome of target/upper/this region" 51542 16 string targetName; "Identifier of target/upper/this region" 51543 17 string targetStrand; "Orientation of target/upper/this region: + or -. Use . if not applicable" 51544 * 51545 * @param tokens 51546 * @param ignore 51547 * @returns {*} 51548 */ 51549 51550 function decodeInteract(tokens, header) { 51551 if (tokens.length < 6) { 51552 console.log("Skipping line: " + tokens.join(' ')); 51553 return undefined; 51554 } 51555 51556 var feature = { 51557 chr: tokens[0], 51558 start: tokens[1], 51559 end: tokens[2], 51560 chr1: tokens[8], 51561 start1: Number.parseInt(tokens[9]), 51562 end1: Number.parseInt(tokens[10]), 51563 chr2: tokens[13], 51564 start2: Number.parseInt(tokens[14]), 51565 end2: Number.parseInt(tokens[15]), 51566 name: tokens[3], 51567 score: Number(tokens[4]), 51568 value: Number(tokens[5]), 51569 color: tokens[7] === '.' ? undefined : tokens[7] === "0" ? "rgb(0,0,0)" : tokens[7] 51570 }; 51571 return feature; 51572 } 51573 51574 /** 51575 * Some interpretations of the sequence ontology needed to assemble GFF transcripts. 51576 * 51577 */ 51578 const transcriptTypes = new Set(['transcript', 'primary_transcript', 'processed_transcript', 'mRNA', 'mrna', 'lnc_RNA', 'miRNA', 'ncRNA', 'rRNA', 'scRNA', 'snRNA', 'snoRNA', 'tRNA']); 51579 const cdsTypes = new Set(['CDS', 'cds']); 51580 const codonTypes = new Set(['start_codon', 'stop_codon']); 51581 const utrTypes = new Set(['5UTR', '3UTR', 'UTR', 'five_prime_UTR', 'three_prime_UTR', "3'-UTR", "5'-UTR"]); 51582 const exonTypes = new Set(['exon', 'coding-exon']); 51583 const transcriptPartTypes = new Set(); 51584 51585 for (let cltn of [cdsTypes, codonTypes, utrTypes, exonTypes]) { 51586 for (let t of cltn) { 51587 transcriptPartTypes.add(t); 51588 } 51589 } 51590 51591 function isExon(type) { 51592 return exonTypes.has(type); 51593 } 51594 51595 function isIntron(type) { 51596 return type.includes("intron"); 51597 } 51598 51599 function isCoding(type) { 51600 return cdsTypes.has(type) || codonTypes.has(type); 51601 } 51602 51603 function isUTR(type) { 51604 return utrTypes.has(type); 51605 } 51606 51607 function isTranscript(type) { 51608 return transcriptTypes.has(type) || type.endsWith("RNA") || type.endsWith("transcript"); 51609 } 51610 51611 function isTranscriptPart(type) { 51612 return transcriptPartTypes.has(type) || type.endsWith("RNA") || isIntron(type); 51613 } 51614 51615 const filterPopupProperties = new Set(["id", "parent", "name"]); 51616 51617 class GFFFeature { 51618 constructor(properties) { 51619 Object.assign(this, properties); 51620 } 51621 51622 popupData(genomicLocation) { 51623 const pd = this.geneObject ? this.geneObject.popupData() : []; 51624 51625 if (this.geneObject) { 51626 pd.push('<hr/>'); 51627 } 51628 51629 if (this.name) { 51630 pd.push({ 51631 name: 'Name', 51632 value: this.name 51633 }); 51634 } 51635 51636 pd.push({ 51637 name: 'Type', 51638 value: this.type 51639 }); 51640 pd.push({ 51641 name: 'Source', 51642 value: this.source 51643 }); 51644 51645 if (this.attributeString) { 51646 const atts = parseAttributeString(this.attributeString, this.delim); 51647 51648 for (let [key, value] of atts) { 51649 if (value !== undefined && value.length > 0 && !filterPopupProperties.has(key.toLowerCase())) { 51650 pd.push({ 51651 name: key + ":", 51652 value: value 51653 }); 51654 } 51655 } 51656 } 51657 51658 pd.push({ 51659 name: 'Location', 51660 value: `${this.chr}:${numberFormatter$1(this.start + 1)}-${numberFormatter$1(this.end)}` 51661 }); 51662 return pd; 51663 } 51664 51665 getAttributeValue(attributeName) { 51666 if (this.hasOwnProperty(attributeName)) { 51667 return this[attributeName]; 51668 } else { 51669 // TODO -- fetch from attribute string and cache 51670 if (!this._attributeCache) { 51671 this._attributeCache = new Map(); 51672 } 51673 51674 if (this._attributeCache.has(attributeName)) { 51675 return this._attributeCache.get(attributeName); 51676 } else { 51677 const atts = parseAttributeString(this.attributeString, this.delim); 51678 let v; 51679 51680 for (let [key, value] of atts) { 51681 if (key === attributeName) { 51682 v = value; 51683 break; 51684 } 51685 } 51686 51687 this._attributeCache.set(attributeName, v); 51688 51689 return v; 51690 } 51691 } 51692 } 51693 51694 } 51695 51696 class GFFTranscript extends GFFFeature { 51697 constructor(feature) { 51698 super(feature); 51699 this.exons = []; 51700 this.parts = []; 51701 } 51702 51703 addExon(feature) { 51704 this.exons.push(feature); // Expand feature -- for transcripts not explicitly represented in the file (gtf) 51705 51706 this.start = Math.min(this.start, feature.start);
51707 this.end = Math.max(this.end, feature.end); 51708 } 51709 51710 addPart(feature) { 51711 this.parts.push(feature); 51712 } 51713 51714 assembleParts() { 51715 if (this.parts.length === 0) return; 51716 this.parts.sort(function (a, b) { 51717 return a.start - b.start; 51718 }); // Create exons, if neccessary 51719 51720 let lastStart = this.parts[0].start; 51721 let lastEnd = this.parts[0].end; 51722 51723 for (let i = 1; i < this.parts.length; i++) { 51724 const part = this.parts[i]; 51725 51726 if (isIntron(part.type)) { 51727 continue; 51728 } 51729 51730 if (part.start <= lastEnd) { 51731 lastEnd = Math.max(lastEnd, part.end); 51732 } else { 51733 let exon = this.findExonContaining({ 51734 start: lastStart, 51735 end: lastEnd 51736 }); 51737 51738 if (!exon) { 51739 this.exons.push({ 51740 start: lastStart, 51741 end: lastEnd, 51742 psuedo: true 51743 }); 51744 } 51745 51746 lastStart = part.start; 51747 lastEnd = part.end; 51748 } 51749 } 51750 51751 let exon = this.findExonContaining({ 51752 start: lastStart, 51753 end: lastEnd 51754 }); 51755 51756 if (!exon) { 51757 this.exons.push({ 51758 start: lastStart, 51759 end: lastEnd, 51760 psuedo: true 51761 }); 51762 this.start = Math.min(this.start, lastStart); 51763 this.end = Math.max(this.end, lastEnd); 51764 } 51765 51766 for (let part of this.parts) { 51767 const type = part.type; 51768 51769 if (isCoding(type)) { 51770 this.addCDS(part); 51771 } else if (isUTR(type)) { 51772 this.addUTR(part); 51773 } 51774 } 51775 } 51776 51777 findExonContaining(_ref) { 51778 let { 51779 start, 51780 end 51781 } = _ref; 51782 51783 for (let exon of this.exons) { 51784 if (exon.end >= end && exon.start <= start) { 51785 return exon; 51786 } 51787 } 51788 51789 return undefined; 51790 } 51791 51792 addCDS(cds) { 51793 let exon; 51794 const exons = this.exons; 51795 51796 for (let e of exons) { 51797 if (e.start <= cds.start && e.end >= cds.end) { 51798 exon = e; 51799 break; 51800 } 51801 } 51802 51803 if (exon) { 51804 exon.cdStart = exon.cdStart ? Math.min(cds.start, exon.cdStart) : cds.start; 51805 exon.cdEnd = exon.cdEnd ? Math.max(cds.end, exon.cdEnd) : cds.end; 51806 } else { 51807 // cds.cdStart = cds.start 51808 // cds.cdEnd = cds.end 51809 // exons.push(cds) 51810 console.error("No exon found spanning " + cds.start + "-" + cds.end); 51811 } // Expand feature -- for transcripts not explicitly represented in the file (gtf files) 51812 // this.start = Math.min(this.start, cds.start); 51813 // this.end = Math.max(this.end, cds.end); 51814 51815 51816 this.cdStart = this.cdStart ? Math.min(cds.start, this.cdStart) : cds.start; 51817 this.cdEnd = this.cdEnd ? Math.max(cds.end, this.cdEnd) : cds.end; 51818 } 51819 51820 addUTR(utr) { 51821 let exon; 51822 const exons = this.exons; // Find exon containing CDS 51823 51824 for (let i = 0; i < exons.length; i++) { 51825 if (exons[i].start <= utr.start && exons[i].end >= utr.end) { 51826 exon = exons[i]; 51827 break; 51828 } 51829 } 51830 51831 if (exon) { 51832 if (utr.start === exon.start && utr.end === exon.end) { 51833 exon.utr = true; 51834 } else { 51835 if (utr.end < exon.end) { 51836 exon.cdStart = utr.end; 51837 } 51838 51839 if (utr.start > exon.start) { 51840 exon.cdEnd = utr.start; 51841 } 51842 } 51843 } else { 51844 // utr.utr = true 51845 // exons.push(utr) 51846 console.error("No exon found spanning " + cds.start + "-" + cds.end); 51847 } // Expand feature -- for transcripts not explicitly represented in the file 51848 // this.start = Math.min(this.start, utr.start); 51849 // this.end = Math.max(this.end, utr.end); 51850 51851 } 51852 51853 finish() { 51854 this.assembleParts(); 51855 var cdStart = this.cdStart; 51856 var cdEnd = this.cdEnd; 51857 this.exons.sort(function (a, b) { 51858 return a.start - b.start; 51859 }); // Search for UTR exons that were not explicitly tagged 51860 51861 if (cdStart) { 51862 this.exons.forEach(function (exon) { 51863 if (exon.end < cdStart || exon.start > cdEnd) exon.utr = true; 51864 }); 51865 } 51866 } 51867 51868 popupData(genomicLocation) { 51869 const pd = super.popupData(genomicLocation); // If clicked over an exon add its attributes 51870 51871 for (let exon of this.exons) { 51872 if (exon.pseudo) continue; // An implicit exon 51873 51874 if (genomicLocation >= exon.start && genomicLocation < exon.end && typeof exon.popupData === 'function') { 51875 pd.push('<hr/>'); 51876 const exonData = exon.popupData(genomicLocation); 51877 51878 for (let att of exonData) { 51879 pd.push(att); 51880 } 51881 } 51882 } 51883 51884 for (let part of this.parts) { 51885 if (genomicLocation >= part.start && genomicLocation < part.end && typeof part.popupData === 'function') { 51886 pd.push('<hr/>'); 51887 const partData = part.popupData(genomicLocation); 51888 51889 for (let att of partData) { 51890 pd.push(att); 51891 } 51892 } 51893 } 51894 51895 return pd; 51896 } 51897 51898 } 51899 51900 function decode(tokens, header) { 51901 const format = header.format; 51902 51903 if (tokens.length < 9) { 51904 return undefined; // Not a valid gff record 51905 } 51906 51907 const delim = 'gff3' === format ? '=' : ' '; 51908 return new GFFFeature({ 51909 source: tokens[1], 51910 type: tokens[2], 51911 chr: tokens[0], 51912 start: parseInt(tokens[3]) - 1, 51913 end: parseInt(tokens[4]), 51914 score: "." === tokens[5] ? 0 : Number(tokens[5]), 51915 strand: tokens[6], 51916 phase: "." === tokens[7] ? 0 : parseInt(tokens[7]), 51917 attributeString: tokens[8], 51918 delim: delim 51919 }); 51920 } 51921 /** 51922 * Decode a single gff record (1 line in file). Aggregations such as gene models are constructed at a higher level. 51923 * ctg123 . mRNA 1050 9000 . + . ID=mRNA00001;Parent=gene00001 51924 * @param tokens 51925 * @param ignore 51926 * @returns {*} 51927 */ 51928 51929 51930 function decodeGFF3(tokens, header) { 51931 const feature = decode(tokens, header); 51932 51933 if (!feature) { 51934 return; 51935 } 51936 51937 const attributes = parseAttributeString(feature.attributeString, feature.delim); // Search for color value as case insenstivie key 51938 51939 for (let [key, value] of attributes) {
51940 const keyLower = key.toLowerCase(); 51941 51942 if ("color" === keyLower || "colour" === keyLower) { 51943 feature.color = IGVColor.createColorString(value); 51944 } else if (key === "ID") { 51945 feature.id = value; 51946 } else if (key === "Parent") { 51947 feature.parent = value; 51948 } 51949 } 51950 51951 return feature; 51952 } 51953 /** 51954 * GTF format example: 51955 NC_000008.11 BestRefSeq gene 127735434 127742951 . + . gene_id "MYC"; transcript_id ""; db_xref "GeneID:4609"; db_xref "HGNC:HGNC:7553"; db_xref "MIM:190080"; description "MYC proto-oncogene, bHLH transcription factor"; gbkey "Gene"; gene "MYC"; gene_biotype "protein_coding"; gene_synonym "bHLHe39"; gene_synonym "c-Myc"; gene_synonym "MRTL"; gene_synonym "MYCC"; 51956 NC_000008.11 BestRefSeq transcript 127735434 127742951 . + . gene_id "MYC"; transcript_id "NM_001354870.1"; db_xref "GeneID:4609"; gbkey "mRNA"; gene "MYC"; product "MYC proto-oncogene, bHLH transcription factor, transcript variant 2"; transcript_biotype "mRNA"; 51957 NC_000008.11 BestRefSeq exon 127735434 127736623 . + . gene_id "MYC"; transcript_id "NM_001354870.1"; db_xref "GeneID:4609"; gene "MYC"; product "MYC proto-oncogene, bHLH transcription factor, transcript variant 2"; transcript_biotype "mRNA"; exon_number "1"; 51958 * 51959 * @param tokens 51960 * @param ignore 51961 * @returns {*} 51962 */ 51963 51964 51965 function decodeGTF(tokens, header) { 51966 const feature = decode(tokens, header); 51967 51968 if (!feature) { 51969 return; 51970 } 51971 51972 const attributes = parseAttributeString(feature.attributeString, feature.delim); // GTF files specify neither ID nor parent fields, but they can be inferred from common conventions 51973 51974 let idField; 51975 let parentField; 51976 51977 switch (feature.type) { 51978 case "gene": 51979 idField = "gene_id"; 51980 break; 51981 51982 case "transcript": 51983 idField = "transcript_id"; 51984 parentField = "gene_id"; 51985 break; 51986 51987 default: 51988 parentField = "transcript_id"; 51989 } 51990 51991 for (let [key, value] of attributes) { 51992 const keyLower = key.toLowerCase(); 51993 51994 if ("color" === keyLower || "colour" === keyLower) { 51995 feature.color = IGVColor.createColorString(value); 51996 } else if (key === idField) { 51997 feature.id = value; 51998 } else if (key === parentField) { 51999 feature.parent = value; 52000 } 52001 } 52002 52003 return feature; 52004 } 52005 /** 52006 * Parse the attribute string, returning an array of key-value pairs. An array is used rather than a map as attribute 52007 * keys are not required to be unique. 52008 * 52009 * @param attributeString 52010 * @param keyValueDelim 52011 * @returns {[]} 52012 */ 52013 52014 52015 function parseAttributeString(attributeString, keyValueDelim) { 52016 // parse 'attributes' string (see column 9 docs in https://github.com/The-Sequence-Ontology/Specifications/blob/master/gff3.md) 52017 var attributes = []; 52018 52019 for (let kv of attributeString.split(';')) { 52020 kv = kv.trim(); 52021 const idx = kv.indexOf(keyValueDelim); 52022 52023 if (idx > 0 && idx < kv.length - 1) { 52024 const key = kv.substring(0, idx); 52025 let value = stripQuotes(decodeURIComponent(kv.substring(idx + 1).trim())); 52026 attributes.push([key, value]); 52027 } 52028 } 52029 52030 return attributes; 52031 } 52032 52033 function stripQuotes(value) { 52034 if (value.startsWith('"') && value.endsWith('"')) { 52035 value = value.substr(1, value.length - 2); 52036 } 52037 52038 return value; 52039 } 52040 52041 /** 52042 * Wrapper class to record a decoding error. 52043 */ 52044 class DecodeError { 52045 constructor(message) { 52046 this.message = message; 52047 } 52048 52049 } 52050 52051 /** 52052 * Decode the UCSC bed format. Only the first 3 columns (chr, start, end) are required. The remaining columns 52053 * must follow standard bed order, but we will tolerate deviations after column 3. 52054 * 52055 * @param tokens 52056 * @param ignore 52057 * @returns decoded feature, or null if this is not a valid record 52058 */ 52059 52060 function decodeBed(tokens, header) { 52061 if (tokens.length < 3) return undefined; 52062 header && header.gffTags; 52063 const chr = tokens[0]; 52064 const start = parseInt(tokens[1]); 52065 const end = tokens.length > 2 ? parseInt(tokens[2]) : start + 1; 52066 52067 if (isNaN(start) || isNaN(end)) { 52068 return new DecodeError(`Unparsable bed record.`); 52069 } 52070 52071 const feature = new UCSCBedFeature({ 52072 chr: chr, 52073 start: start, 52074 end: end, 52075 score: 1000 52076 }); 52077
52078 try { 52079 if (tokens.length > 3) { 52080 // Potentially parse name field as GFF column 9 style streng. 52081 if (tokens[3].indexOf(';') > 0 && tokens[3].indexOf('=') > 0) { 52082 const attributeKVs = parseAttributeString(tokens[3], '='); 52083 feature.attributes = {}; 52084 52085 for (let kv of attributeKVs) { 52086 feature.attributes[kv[0]] = kv[1]; 52087 } 52088 } 52089 52090 if (!feature.name) { 52091 feature.name = tokens[3] === '.' ? '' : tokens[3]; 52092 } 52093 } 52094 52095 if (tokens.length > 4) { 52096 feature.score = tokens[4] === '.' ? 0 : Number(tokens[4]); 52097 52098 if (isNaN(feature.score)) { 52099 return feature; 52100 } 52101 } 52102 52103 if (tokens.length > 5) { 52104 feature.strand = tokens[5]; 52105 52106 if (!(feature.strand === '.' || feature.strand === '+' || feature.strand === '-')) { 52107 return feature; 52108 } 52109 } 52110 52111 if (tokens.length > 6) { 52112 feature.cdStart = parseInt(tokens[6]); 52113 52114 if (isNaN(feature.cdStart)) { 52115 return feature; 52116 } 52117 } 52118 52119 if (tokens.length > 7) { 52120 feature.cdEnd = parseInt(tokens[7]); 52121 52122 if (isNaN(feature.cdEnd)) { 52123 return feature; 52124 } 52125 } 52126 52127 if (tokens.length > 8) { 52128 if (tokens[8] !== "." && tokens[8] !== "0") feature.color = IGVColor.createColorString(tokens[8]); 52129 } 52130 52131 if (tokens.length > 11) { 52132 const exonCount = parseInt(tokens[9]); // Some basic validation 52133 52134 if (exonCount > 1000) { 52135 // unlikely 52136 return feature; 52137 } 52138 52139 const exonSizes = tokens[10].replace(/,$/, '').split(','); 52140 const exonStarts = tokens[11].replace(/,$/, '').split(','); 52141 52142 if (!(exonSizes.length === exonStarts.length && exonCount === exonSizes.length)) { 52143 return feature; 52144 } 52145 52146 const exons = []; 52147 52148 for (let i = 0; i < exonCount; i++) { 52149 const eStart = start + parseInt(exonStarts[i]); 52150 const eEnd = eStart + parseInt(exonSizes[i]); 52151 exons.push({ 52152 start: eStart, 52153 end: eEnd 52154 }); 52155 } 52156 52157 findUTRs(exons, feature.cdStart, feature.cdEnd); 52158 feature.exons = exons; 52159 } // Optional extra columns 52160 52161 52162 if (header) { 52163 let thicknessColumn = header.thicknessColumn; 52164 let colorColumn = header.colorColumn; 52165 52166 if (colorColumn && colorColumn < tokens.length) { 52167 feature.color = IGVColor.createColorString(tokens[colorColumn]); 52168 } 52169 52170 if (thicknessColumn && thicknessColumn < tokens.length) { 52171 feature.thickness = tokens[thicknessColumn]; 52172 } 52173 } 52174 } catch (e) {} 52175 52176 return feature; 52177 } 52178 /** 52179 * Decode a UCSC repeat masker record. 52180 * 52181 * Columns, from UCSC documentation 52182 * 52183 * 0 bin 585 smallint(5) unsigned Indexing field to speed chromosome range queries. 52184 * 1 swScore 1504 int(10) unsigned Smith Waterman alignment score 52185 * 2 milliDiv 13 int(10) unsigned Base mismatches in parts per thousand 52186 * 3 milliDel 4 int(10) unsigned Bases deleted in parts per thousand 52187 * 4 milliIns 13 int(10) unsigned Bases inserted in parts per thousand 52188 * 5 genoName chr1 varchar(255) Genomic sequence name 52189 * 6 genoStart 10000 int(10) unsigned Start in genomic sequence 52190 * 7 genoEnd 10468 int(10) unsigned End in genomic sequence 52191 * 8 genoLeft -249240153 int(11) -#bases after match in genomic sequence 52192 * 9 strand + char(1) Relative orientation + or - 52193 * 10 repName (CCCTAA)n varchar(255) Name of repeat 52194 * 11 repClass Simple_repeat varchar(255) Class of repeat 52195 * 12 repFamily Simple_repeat varchar(255) Family of repeat 52196 * 13 repStart 1 int(11) Start (if strand is +) or -#bases after match (if strand is -) in repeat sequence 52197 * 14 repEnd 463 int(11) End in repeat sequence 52198 * 15 repLeft 0 int(11) -#bases after match (if strand is +) or start (if strand is -) in repeat sequence 52199 * 16 id 1 char(1) First digit of id field in RepeatMasker .out file. Best ignored. 52200 */ 52201 52202 52203 function decodeRepeatMasker(tokens, header) { 52204 if (tokens.length <= 15) return undefined; 52205 const feature = { 52206 swScore: Number.parseInt(tokens[1]), 52207 milliDiv: Number.parseInt(tokens[2]), 52208 milliDel: Number.parseInt(tokens[3]), 52209 milliIns: Number.parseInt(tokens[4]), 52210 chr: tokens[5], 52211 start: Number.parseInt(tokens[6]), 52212 end: Number.parseInt(tokens[7]), 52213 //genoLeft: tokens[8], 52214 strand: tokens[9], 52215 repName: tokens[10], 52216 repClass: tokens[11], 52217 repFamily: tokens[12], 52218 repStart: Number.parseInt(tokens[13]), 52219 repEnd: Number.parseInt(tokens[14]), 52220 repLeft: Number.parseInt(tokens[15]) 52221 }; 52222 return feature; 52223 } 52224 /** 52225 * Decode a UCSC "genePred" record. 52226 * 52227 * @param tokens 52228 * @param ignore 52229 * @returns {*} 52230 */ 52231 52232 52233 function decodeGenePred(tokens, header) { 52234 var shift = header.shift === undefined ? 0 : 1; 52235 if (tokens.length <= 9 + shift) return undefined; 52236 const cdStart = parseInt(tokens[5 + shift]); 52237 const cdEnd = parseInt(tokens[6 + shift]); 52238 var feature = { 52239 name: tokens[0 + shift], 52240 chr: tokens[1 + shift], 52241 strand: tokens[2 + shift], 52242 start: parseInt(tokens[3 + shift]), 52243 end: parseInt(tokens[4 + shift]), 52244 cdStart: cdStart, 52245 cdEnd: cdEnd, 52246 id: tokens[0 + shift] 52247 }, 52248 exonCount = parseInt(tokens[7 + shift]), 52249 exonStarts = tokens[8 + shift].split(','), 52250 exonEnds = tokens[9 + shift].split(','), 52251 exons = []; 52252 52253 for (let i = 0; i < exonCount; i++) { 52254 const start = parseInt(exonStarts[i]); 52255 const end = parseInt(exonEnds[i]); 52256 exons.push({ 52257 start: start, 52258 end: end 52259 }); 52260 } 52261 52262 findUTRs(exons, cdStart, cdEnd); 52263 feature.exons = exons; 52264 return feature; 52265 } 52266 /** 52267 * Decode a UCSC "genePredExt" record. refGene files are in this format. 52268 * 52269 * @param tokens 52270 * @param ignore 52271 * @returns {*} 52272 */ 52273 52274 52275 function decodeGenePredExt(tokens, header) { 52276 var shift = header.shift === undefined ? 0 : 1; 52277 if (tokens.length <= 11 + shift) return undefined; 52278 const cdStart = parseInt(tokens[5 + shift]); 52279 const cdEnd = parseInt(tokens[6 + shift]); 52280 const feature = { 52281 name: tokens[11 + shift], 52282 chr: tokens[1 + shift], 52283 strand: tokens[2 + shift], 52284 start: parseInt(tokens[3 + shift]), 52285 end: parseInt(tokens[4 + shift]), 52286 cdStart: cdStart, 52287 cdEnd: cdEnd, 52288 id: tokens[0 + shift] 52289 }, 52290 exonCount = parseInt(tokens[7 + shift]), 52291 exonStarts = tokens[8 + shift].split(','), 52292 exonEnds = tokens[9 + shift].split(','), 52293 exons = []; 52294 52295 for (let i = 0; i < exonCount; i++) { 52296 const start = parseInt(exonStarts[i]); 52297 const end = parseInt(exonEnds[i]); 52298 exons.push({ 52299 start: start, 52300 end: end 52301 }); 52302 } 52303 52304 findUTRs(exons, cdStart, cdEnd); 52305 feature.exons = exons; 52306 return feature; 52307 } 52308 /** 52309 * Decode a UCSC "refFlat" record 52310 * @param tokens 52311 * @param ignore 52312 * @returns {*} 52313 */ 52314 52315 52316 function decodeReflat(tokens, header) { 52317 var shift = header.shift === undefined ? 0 : 1; 52318 if (tokens.length <= 10 + shift) return undefined; 52319 const cdStart = parseInt(tokens[6 + shift]); 52320 const cdEnd = parseInt(tokens[7 + shift]); 52321 var feature = { 52322 name: tokens[0 + shift], 52323 id: tokens[1 + shift], 52324 chr: tokens[2 + shift], 52325 strand: tokens[3 + shift], 52326 start: parseInt(tokens[4 + shift]), 52327 end: parseInt(tokens[5 + shift]), 52328 cdStart: cdStart, 52329 cdEnd: cdEnd 52330 }, 52331 exonCount = parseInt(tokens[8 + shift]), 52332 exonStarts = tokens[9 + shift].split(','), 52333 exonEnds = tokens[10 + shift].split(','), 52334 exons = []; 52335 52336 for (let i = 0; i < exonCount; i++) { 52337 const start = parseInt(exonStarts[i]); 52338 const end = parseInt(exonEnds[i]); 52339 exons.push({ 52340 start: start, 52341 end: end 52342 }); 52343 } 52344 52345 findUTRs(exons, cdStart, cdEnd); 52346 feature.exons = exons; 52347 return feature; 52348 } 52349 52350 function findUTRs(exons, cdStart, cdEnd) { 52351 for (let exon of exons) { 52352 const end = exon.end; 52353 const start = exon.start; 52354 52355 if (end < cdStart || start > cdEnd) { 52356 exon.utr = true; 52357 } else { 52358 if (cdStart >= start && cdStart <= end) { 52359 exon.cdStart = cdStart; 52360 } 52361 52362 if (cdEnd >= start && cdEnd <= end) { 52363 exon.cdEnd = cdEnd; 52364 } 52365 } 52366 } 52367 } 52368 52369 function decodePeak(tokens, header) { 52370 var tokenCount, chr, start, end, strand, name, score, qValue, signal, pValue; 52371 tokenCount = tokens.length; 52372 52373 if (tokenCount < 9) { 52374 return undefined; 52375 } 52376 52377 chr = tokens[0]; 52378 start = parseInt(tokens[1]); 52379 end = parseInt(tokens[2]); 52380 name = tokens[3]; 52381 score = Number(tokens[4]); 52382 strand = tokens[5].trim(); 52383 signal = Number(tokens[6]); 52384 pValue = Number(tokens[7]); 52385 qValue = Number(tokens[8]); 52386 if (score === 0) score = signal; 52387 return { 52388 chr: chr, 52389 start: start, 52390 end: end, 52391 name: name, 52392 score: score, 52393 strand: strand, 52394 signal: signal, 52395 pValue: pValue, 52396 qValue: qValue 52397 }; 52398 } 52399 52400 function decodeBedGraph(tokens, header) { 52401 var chr, start, end, value; 52402 if (tokens.length <= 3) return undefined; 52403 chr = tokens[0]; 52404 start = parseInt(tokens[1]); 52405 end = parseInt(tokens[2]); 52406 value = Number(tokens[3]); 52407 const feature = { 52408 chr: chr, 52409 start: start, 52410 end: end, 52411 value: value 52412 }; // Optional extra columns 52413 52414 if (header) { 52415 let colorColumn = header.colorColumn; 52416 52417 if (colorColumn && colorColumn < tokens.length) { 52418 feature.color = IGVColor.createColorString(tokens[colorColumn]); 52419 } 52420 } 52421 52422 return feature; 52423 } 52424 52425 function decodeWig(tokens, header) { 52426 const wig = header.wig; 52427 52428 if (wig && wig.format === "fixedStep") { 52429 const ss = wig.index * wig.step + wig.start; 52430 const ee = ss + wig.span; 52431 const value = Number(tokens[0]); 52432 ++wig.index; 52433 return isNaN(value) ? null : { 52434 chr: wig.chrom, 52435 start: ss, 52436 end: ee, 52437 value: value 52438 }; 52439 } else if (wig && wig.format === "variableStep") { 52440 if (tokens.length < 2) return null; 52441 const ss = parseInt(tokens[0], 10) - 1; 52442 const ee = ss + wig.span; 52443 const value = Number(tokens[1]); 52444 return isNaN(value) ? null : { 52445 chr: wig.chrom, 52446 start: ss, 52447 end: ee, 52448 value: value 52449 }; 52450 } else { 52451 return decodeBedGraph(tokens); 52452 } 52453 } 52454 52455 function decodeSNP(tokens, header) { 52456 if (tokens.length < 6) return undefined; 52457 const autoSql = ['bin', 'chr', 'start', 'end', 'name', 'score', 'strand', 'refNCBI', 'refUCSC', 'observed', 'molType', 'class', 'valid', 'avHet', 'avHetSE', 'func', 'locType', 'weight', 'exceptions', 'submitterCount', 'submitters', 'alleleFreqCount', 'alleles', 'alleleNs', 'alleleFreqs', 'bitfields']; 52458 const feature = { 52459 chr: tokens[1], 52460 start: Number.parseInt(tokens[2]), 52461 end: Number.parseInt(tokens[3]), 52462 name: tokens[4], 52463 score: Number.parseInt(tokens[5]) 52464 }; 52465 const n = Math.min(tokens.length, autoSql.length); 52466 52467 for (let i = 6; i < n; i++) { 52468 feature[autoSql[i]] = tokens[i]; 52469 } 52470 52471 return feature; 52472 } 52473 52474 class UCSCBedFeature { 52475 constructor(properties) { 52476 Object.assign(this, properties); 52477 } 52478 52479 getAttributeValue(attributeName) { 52480 if (this.hasOwnProperty(attributeName)) { 52481 return this[attributeName]; 52482 } else if (this.attributes) { 52483 return this.attributes[attributeName]; 52484 } 52485 } 52486 52487 } 52488 52489 function decodeFusionJuncSpan(tokens, header) { 52490 /* 52491 Format: 52492 0 #scaffold 52493 1 fusion_break_name 52494 2 break_left 52495 3 break_right 52496 4 num_junction_reads 52497 5 num_spanning_frags 52498 6 spanning_frag_coords 52499 0 B3GNT1--NPSR1 52500 1 B3GNT1--NPSR1|2203-10182 52501 2 2203 52502 3 10182 52503 4 189 52504 5 1138 52505 6 1860-13757,1798-13819,1391-18127,1443-17174,... 52506 */ 52507 if (tokens.length < 7) return undefined; 52508 var chr = tokens[0]; 52509 var fusion_name = tokens[1]; 52510 var junction_left = parseInt(tokens[2]); 52511 var junction_right = parseInt(tokens[3]); 52512 var num_junction_reads = parseInt(tokens[4]); 52513 var num_spanning_frags = parseInt(tokens[5]); 52514 var spanning_frag_coords_text = tokens[6]; 52515 var feature = { 52516 chr: chr, 52517 name: fusion_name, 52518 junction_left: junction_left, 52519 junction_right: junction_right, 52520 num_junction_reads: num_junction_reads, 52521 num_spanning_frags: num_spanning_frags, 52522 spanning_frag_coords: [], 52523 start: -1, 52524 end: -1 52525 }; // set start and end later based on min/max of span coords 52526 52527 var min_coord = junction_left; 52528 var max_coord = junction_right; 52529 52530 if (num_spanning_frags > 0) { 52531 var coord_pairs = spanning_frag_coords_text.split(','); 52532 52533 for (var i = 0; i < coord_pairs.length; i++) { 52534 var split_coords = coord_pairs[i].split('-'); 52535 var span_left = split_coords[0]; 52536 var span_right = split_coords[1]; 52537 52538 if (span_left < min_coord) { 52539 min_coord = span_left; 52540 } 52541 52542 if (span_right > max_coord) { 52543 max_coord = span_right; 52544 } 52545 52546 feature.spanning_frag_coords.push({ 52547 left: span_left, 52548 right: span_right 52549 }); 52550 } 52551 } 52552 52553 feature.start = min_coord; 52554 feature.end = max_coord; 52555 return feature; 52556 } 52557 52558 function decodeGtexGWAS(tokens, header) { 52559 //chrom chromStart chromEnd Strongest SNP-risk allele Disease/Phe
52559notype P-value Odds ratio or beta PUBMEDID 52560 //1 1247493 1247494 rs12103-A Inflammatory bowel disease 8.00E-13 1.1 23128233 52561 const tokenCount = tokens.length; 52562 52563 if (tokenCount < 7) { 52564 return null; 52565 } 52566 52567 const feature = { 52568 chr: tokens[0], 52569 start: parseInt(tokens[1]) - 1, 52570 end: parseInt(tokens[2]), 52571 'Strongest SNP-risk allele': tokens[3], 52572 'Disease/Phenotype': tokens[4], 52573 'P-value': tokens[5], 52574 'Odds ratio or beta': tokens[6] 52575 }; 52576 52577 if (tokens.length > 6) { 52578 feature['PUBMEDID'] = `<a target = "blank" href = "https://www.ncbi.nlm.nih.gov/pubmed/${tokens[7]}">${tokens[7]}</a>`; 52579 } 52580 52581 return feature; 52582 } 52583 52584 /** 52585 * Decode a custom columnar format. Required columns are 'chr' and 'start' 52586 * 52587 * @param tokens 52588 * @param ignore 52589 * @returns decoded feature, or null if this is not a valid record 52590 */ 52591 function decodeCustom(tokens, header) { 52592 const format = header.customFormat; 52593 if (tokens.length < format.fields.length) return undefined; 52594 const coords = format.coords || 0; 52595 const chr = tokens[format.chr]; 52596 const start = parseInt(tokens[format.start]) - coords; 52597 const end = format.end !== undefined ? parseInt(tokens[format.end]) : start + 1; 52598 const feature = { 52599 chr: chr, 52600 start: start, 52601 end: end 52602 }; 52603 52604 if (format.fields) { 52605 format.fields.forEach(function (field, index) { 52606 if (index !== format.chr && index !== format.start && index !== format.end) { 52607 feature[field] = tokens[index]; 52608 } 52609 }); 52610 } 52611 52612 return feature; 52613 } // function expandFormat(format) { 52614 52615 /** 52616 * Decode a gcnv record, a bed style format encoding copy number variation 52617 * 52618 * @param tokens 52619 * @param header 52620 */ 52621 function decodeGcnv(tokens, header) { 52622 const columnNames = header.columnNames; 52623 52624 if (!columnNames) { 52625 throw Error("Sample names are not defined. Missing column headers?"); 52626 } 52627 52628 const sampleCount = columnNames.length - 3; 52629 const chr = tokens[0]; 52630 const start = parseInt(tokens[1]); 52631 const end = parseInt(tokens[2]); 52632 const values = tokens.slice(3).map(Number); 52633 52634 if (values.length == sampleCount) { 52635 return { 52636 chr: chr, 52637 start: start, 52638 end: end, 52639 values: values 52640 }; 52641 } else { 52642 // TODO Throw error? 52643 console.warn(`${chr}:${start}-${end} row contains ${values.length} sample columns instead of the expected ${sampleCount} columns. Skipping...`); 52644 return undefined; 52645 } 52646 } 52647 52648 /* 52649 * The MIT License (MIT) 52650 * 52651 * Copyright (c) 2014 Broad Institute 52652 * 52653 * Permission is hereby granted, free of charge, to any person obtaining a copy 52654 * of this software and associated documentation files (the "Software"), to deal 52655 * in the Software without restriction, including without limitation the rights 52656 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 52657 * copies of the Software, and to permit persons to whom the Software is 52658 * furnished to do so, subject to the following conditions: 52659 * 52660 * The above copyright notice and this permission notice shall be included in 52661 * all copies or substantial portions of the Software. 52662 * 52663 * 52664 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 52665 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 52666 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 52667 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 52668 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 52669 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 52670 * THE SOFTWARE. 52671 */ 52672 /** 52673 * Parser for column style (tab delimited, etc) text file formats (bed, gff, vcf, etc). 52674 * 52675 * 52676 */ 52677 52678 /** 52679 * Return a parser for the given file format. 52680 */ 52681 52682 class FeatureParser { 52683 constructor(config) { 52684 this.config = config; 52685 this.header = {}; 52686 52687 if (config.nameField) {
52688 this.header.nameField = config.nameField; 52689 } 52690 52691 this.skipRows = 0; // The number of fixed header rows to skip. Override for specific types as needed 52692 52693 if (config.decode) { 52694 this.decode = config.decode; 52695 this.delimiter = config.delimiter || "\t"; 52696 } else if (config.format) { 52697 this.header.format = config.format.toLowerCase(); 52698 this.setDecoder(this.header.format); 52699 } 52700 52701 if (!this.delimiter) { 52702 this.delimiter = "\t"; 52703 } 52704 } 52705 /** 52706 * Parse metadata from the file. A variety of conventions are in use to supply metadata about file contents 52707 * through header lines (e.g. 'track') and # directives. This method unifies metadata as properties of a 52708 * 'header' object. 52709 * 52710 * @param data 52711 * @returns {{}} 52712 */ 52713 52714 52715 async parseHeader(dataWrapper) { 52716 let header = this.header; 52717 let columnNames; 52718 let line; 52719 52720 while ((line = await dataWrapper.nextLine()) !== undefined) { 52721 if (line.startsWith("track") || line.startsWith("#track")) { 52722 let h = parseTrackLine$1(line); 52723 Object.assign(header, h); 52724 } else if (line.startsWith("browser")) ; else if (line.startsWith("#columns")) { 52725 let h = parseColumnsDirective$1(line); 52726 Object.assign(header, h); 52727 } else if (line.startsWith("##gff-version 3")) { 52728 header.format = "gff3"; 52729 } else if (line.startsWith("#gffTags")) { 52730 header.gffTags = true; 52731 } else if (line.startsWith("fixedStep") || line.startsWith("variableStep")) {
52732 // Wig directives -- we are in the data section 52733 break; 52734 } else if (line.startsWith("#")) { 52735 const tokens = line.split(this.delimiter || "\t"); 52736 52737 if (tokens.length > 1) { 52738 columnNames = tokens; // Possible column names 52739 } 52740 } else { 52741 // All directives that could change the format, and thus decoder, should have been read by now. 52742 this.setDecoder(header.format); // If the line can be parsed as a feature assume we are beyond the header, if any 52743 52744 const tokens = line.split(this.delimiter || "\t"); 52745 52746 try { 52747 const tmpHeader = Object.assign({ 52748 columnNames 52749 }, header); 52750 52751 if (this.decode(tokens, tmpHeader)) { 52752 break; 52753 } else { 52754 if (tokens.length > 1) { 52755 columnNames = tokens; // possible column names 52756 } 52757 } 52758 } catch (e) { 52759 // Not a feature 52760 if (tokens.length > 1) { 52761 columnNames = tokens; // possible column names 52762 } 52763 } 52764 } 52765 } 52766 52767 if (columnNames) { 52768 header.columnNames = columnNames; 52769 52770 for (let n = 0; n < columnNames.length; n++) { 52771 if (columnNames[n] === "color" || columnNames[n] === "colour") { 52772 header.colorColumn = n; 52773 } else if (columnNames[n] === "thickness") { 52774 header.thicknessColumn = n; 52775 } 52776 } 52777 } 52778 52779 this.header = header; // Directives might be needed for parsing lines 52780 52781 return header; 52782 } 52783 52784 async parseFeatures(dataWrapper) { 52785 const allFeatures = []; 52786 const decode = this.decode; 52787 const format = this.header.format; 52788 const delimiter = this.delimiter || "\t"; 52789 let i = 0; 52790 let errorCount = 0; 52791 let line; 52792 52793 while ((line = await dataWrapper.nextLine()) !== undefined) { 52794 i++; 52795 if (i <= this.skipRows) continue; 52796 52797 if (!line || line.startsWith("track") || line.startsWith("#") || line.startsWith("browser")) { 52798 continue; 52799 } else if (format === "wig" && line.startsWith("fixedStep")) { 52800 this.header.wig = parseFixedStep(line); 52801 continue; 52802 } else if (format === "wig" && line.startsWith("variableStep")) { 52803 this.header.wig = parseVariableStep(line); 52804 continue; 52805 } 52806 52807 const tokens = line.split(delimiter); 52808 52809 if (tokens.length < 1) { 52810 continue; 52811 } 52812 52813 const feature = decode(tokens, this.header); 52814 52815 if (feature instanceof DecodeError) { 52816 errorCount++; 52817 52818 if (errorCount > 0) { 52819 console.error(`Error parsing line '${line}': ${feature.message}`); 52820 } 52821 52822 continue; 52823 } 52824 52825 if (feature) { 52826 allFeatures.push(feature); 52827 } 52828 } // Special hack for bedPE 52829 52830 52831 if (decode === decodeBedpe) { 52832 fixBedPE(allFeatures); 52833 } 52834 52835 return allFeatures; 52836 } 52837 52838 setDecoder(format) { 52839 switch (format) { 52840 case "narrowpeak": 52841 case "broadpeak": 52842 case "regionpeak": 52843 case "peaks": 52844 this.decode = decodePeak; 52845 this.delimiter = this.config.delimiter || /\s+/; 52846 break; 52847 52848 case "bedgraph": 52849 this.decode = decodeBedGraph; 52850 this.delimiter = /\s+/; 52851 break; 52852 52853 case "wig": 52854 this.decode = decodeWig; 52855 this.delimiter = this.config.delimiter || /\s+/; 52856 break; 52857 52858 case "gff3": 52859 case "gff": 52860 this.decode = decodeGFF3; 52861 this.delimiter = "\t"; 52862 break; 52863 52864 case "gtf": 52865 this.decode = decodeGTF; 52866 this.delimiter = "\t"; 52867 break; 52868 52869 case "fusionjuncspan": 52870 // bhaas, needed for FusionInspector view 52871 this.decode = decodeFusionJuncSpan; 52872 this.delimiter = this.config.delimiter || /\s+/; 52873 break; 52874 52875 case "gtexgwas": 52876 this.skipRows = 1; 52877 this.decode = decodeGtexGWAS; 52878 this.delimiter = "\t"; 52879 break; 52880 52881 case "refflat": 52882 this.decode = decodeReflat; 52883 this.delimiter = this.config.delimiter || /\s+/; 52884 break; 52885 52886 case "genepred": 52887 this.decode = decodeGenePred; 52888 this.delimiter = this.config.delimiter || /\s+/; 52889 break; 52890 52891 case "genepredext": 52892 this.decode = decodeGenePredExt; 52893 this.delimiter = this.config.delimiter || /\s+/; 52894 break; 52895 52896 case "ensgene": 52897 this.decode = decodeGenePred; 52898 this.header.shift = 1; 52899 this.delimiter = this.config.delimiter || /\s+/; 52900 break; 52901 52902 case "refgene": 52903 this.decode = decodeGenePredExt; 52904 this.delimiter = this.config.delimiter || /\s+/; 52905 this.header.shift = 1; 52906 break; 52907 52908 case "bed": 52909 this.decode = decodeBed; 52910 this.delimiter = this.config.delimiter || /\s+/; 52911 break; 52912 52913 case "bedpe": 52914 this.decode = decodeBedpe;
52915 this.delimiter = this.config.delimiter || "\t"; 52916 break; 52917 52918 case "bedpe-domain": 52919 this.decode = decodeBedpeDomain; 52920 this.headerLine = true; 52921 this.delimiter = this.config.delimiter || "\t"; 52922 break; 52923 52924 case "bedpe-loop": 52925 this.decode = decodeBedpe; 52926 this.delimiter = this.config.delimiter || "\t"; 52927 this.header = { 52928 colorColumn: 7 52929 }; 52930 break; 52931 52932 case "interact": 52933 this.decode = decodeInteract; 52934 this.delimiter = this.config.delimiter || /\s+/; 52935 break; 52936 52937 case "snp": 52938 this.decode = decodeSNP; 52939 this.delimiter = "\t"; 52940 break; 52941 52942 case "rmsk": 52943 this.decode = decodeRepeatMasker; 52944 this.delimiter = "\t"; 52945 break; 52946 52947 case "gcnv": 52948 this.decode = decodeGcnv; 52949 this.delimiter = "\t"; 52950 break; 52951 52952 default: 52953 const customFormat = getFormat(format); 52954 52955 if (customFormat !== undefined) { 52956 this.decode = decodeCustom; 52957 this.header.customFormat = customFormat; 52958 this.delimiter = customFormat.delimiter || "\t"; 52959 } else { 52960 this.decode = decodeBed; 52961 this.delimiter = this.config.delimiter || /\s+/; 52962 } 52963 52964 } 52965 } 52966 52967 } 52968 52969 function parseTrackLine$1(line) { 52970 const properties = {}; 52971 const tokens = line.split(/(?:")([^"]+)(?:")|([^\s"]+)(?=\s+|$)/g); // Clean up tokens array 52972 52973 let curr; 52974 const tmp = []; 52975 52976 for (let tk of tokens) { 52977 if (!tk || tk.trim().length === 0) continue; 52978 52979 if (tk.endsWith("=")) { 52980 curr = tk; 52981 } else if (curr) { 52982 tmp.push(curr + tk); 52983 curr = undefined; 52984 } else { 52985 tmp.push(tk); 52986 } 52987 } 52988 52989 for (let str of tmp) { 52990 if (!str) return; 52991 var kv = str.split('=', 2); 52992 52993 if (kv.length === 2) { 52994 const key = kv[0].trim(); 52995 const value = kv[1].trim(); 52996 52997 if (properties.hasOwnProperty(key)) { 52998 let currentValue = properties[key]; 52999 53000 if (Array.isArray(currentValue)) { 53001 currentValue.push(value); 53002 } else { 53003 properties[key] = [currentValue, value]; 53004 } 53005 } else { 53006 properties[key] = value; 53007 } 53008 } 53009 } 53010 53011 if ("interact" == properties["type"]) { 53012 properties["format"] = "interact"; 53013 } else if ("gcnv" === properties["type"]) { 53014 properties["format"] = "gcnv"; 53015 } 53016 53017 return properties; 53018 } 53019 53020 function parseColumnsDirective$1(line) { 53021 let properties = {}; 53022 let t1 = line.split(/\s+/); 53023 53024 if (t1.length === 2) { 53025 let t2 = t1[1].split(";"); 53026 t2.forEach(function (keyValue) { 53027 let t = keyValue.split("="); 53028 53029 if (t[0] === "color") { 53030 properties.colorColumn = Number.parseInt(t[1]) - 1; 53031 } else if (t[0] === "thickness") { 53032 properties.thicknessColumn = Number.parseInt(t[1]) - 1; 53033 } 53034 }); 53035 } 53036 53037 return properties; 53038 } 53039 53040 function parseFixedStep(line) { 53041 const tokens = line.split(/\s+/); 53042 const chrom = tokens[1].split("=")[1]; 53043 const start = parseInt(tokens[2].split("=")[1], 10) - 1; 53044 const step = parseInt(tokens[3].split("=")[1], 10); 53045 const span = tokens.length > 4 ? parseInt(tokens[4].split("=")[1], 10) : 1; 53046 return { 53047 format: "fixedStep", 53048 chrom, 53049 start, 53050 step, 53051 span, 53052 index: 0 53053 }; 53054 } 53055 53056 function parseVariableStep(line) { 53057 const tokens = line.split(/\s+/); 53058 const chrom = tokens[1].split("=")[1]; 53059 const span = tokens.length > 2 ? parseInt(tokens[2].split("=")[1], 10) : 1; 53060 return { 53061 format: "variableStep", 53062 chrom, 53063 span 53064 }; 53065 } 53066 53067 /* 53068 * The MIT License (MIT) 53069 * 53070 * Copyright (c) 2014 Broad Institute 53071 * 53072 * Permission is hereby granted, free of charge, to any person obtaining a copy 53073 * of this software and associated documentation files (the "Software"), to deal 53074 * in the Software without restriction, including without limitation the rights 53075 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 53076 * copies of the Software, and to permit persons to whom the Software is 53077 * furnished to do so, subject to the following conditions: 53078 * 53079 * The above copyright notice and this permission notice shall be included in 53080 * all copies or substantial portions of the Software. 53081 * 53082 * 53083 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 53084 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 53085 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 53086 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 53087 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 53088 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 53089 * THE SOFTWARE. 53090 */ 53091 /** 53092 * Define parser for seg files (.bed, .gff, .vcf, etc). A parser should implement 2 methods 53093 * 53094 * parseHeader(data) - return an object representing a header. Details are format specific 53095 * 53096 * parseFeatures(data) - return a list of features 53097 * 53098 */ 53099 53100 class SegParser { 53101 constructor(type) { 53102 this.type = type || 'seg'; // One of seg, mut, or maf 53103 53104 switch (this.type) { 53105 case 'mut': 53106 this.sampleColumn = 3; 53107 this.chrColumn = 0; 53108 this.startColumn = 1; 53109 this.endColumn = 2; 53110 this.dataColumn = 4; 53111 break; 53112 53113 case 'maf': 53114 this.sampleColumn = 15; 53115 this.chrColumn = 4; 53116 this.startColumn = 5; 53117 this.endColumn = 6; 53118 this.dataColumn = 8; 53119 break; 53120 53121 default: 53122 this.sampleColumn = 0; 53123 this.chrColumn = 1; 53124 this.startColumn = 2; 53125 this.endColumn = 3; 53126 // Data column determined after reading header 53127 } 53128 } 53129 53130 async parseHeader(dataWrapper) { 53131 let line; 53132
53133 while ((line = await dataWrapper.nextLine()) !== undefined) { 53134 if (line.startsWith("#")) ; else { 53135 const tokens = line.split("\t"); 53136 this.header = { 53137 headings: tokens 53138 }; 53139 break; 53140 } 53141 } 53142 53143 return this.header; 53144 } 53145 53146 async parseFeatures(dataWrapper) { 53147 const allFeatures = []; 53148 let extraHeaders; 53149 53150 if (!this.header) { 53151 this.header = await this.parseHeader(dataWrapper); // This will only work for non-indexed files 53152 } 53153 53154 if ('seg' === this.type) { 53155 this.dataColumn = this.header.headings.length - 1; 53156 } 53157 53158 if (this.header.headings.length > 5) { 53159 extraHeaders = this.extractExtraColumns(this.header.headings); 53160 } 53161 53162 const valueColumnName = this.header.headings[this.dataColumn]; 53163 let line; 53164 53165 while ((line = await dataWrapper.nextLine()) !== undefined) { 53166 const tokens = line.split("\t"); 53167 const value = 'seg' === this.type ? Number(tokens[this.dataColumn]) : tokens[this.dataColumn]; 53168 53169 if (tokens.length > this.dataColumn) { 53170 const feature = new SegFeature({ 53171 sample: tokens[this.sampleColumn], 53172 chr: tokens[this.chrColumn], 53173 start: parseInt(tokens[this.startColumn]) - 1, 53174 end: parseInt(tokens[this.endColumn]), 53175 value, 53176 valueColumnName 53177 }); 53178 53179 if (extraHeaders) { 53180 const extraValues = this.extractExtraColumns(tokens); 53181 feature.setAttributes({ 53182 names: extraHeaders, 53183 values: extraValues 53184 }); 53185 } 53186 53187 allFeatures.push(feature); 53188 } 53189 } 53190 53191 return allFeatures; 53192 } 53193 53194 extractExtraColumns(tokens) { 53195 const extras = []; 53196 53197 for (let i = 0; i < tokens.length; i++) { 53198 if (i !== this.chrColumn && i !== this.startColumn && i !== this.endColumn && i !== this.sampleColumn) { 53199 extras.push(tokens[i]); 53200 } 53201 } 53202 53203 return extras; 53204 } 53205 53206 } 53207 53208 class SegFeature { 53209 constructor(_ref) { 53210 let { 53211 sample, 53212 chr, 53213 start, 53214 end, 53215 value, 53216 valueColumnName 53217 } = _ref; 53218 this.sample = sample; 53219 this.chr = chr; 53220 this.start = start; 53221 this.end = end; 53222 this.value = value; 53223 this.valueColumnName = valueColumnName; 53224 } 53225 53226 setAttributes(_ref2) { 53227 let { 53228 names, 53229 values 53230 } = _ref2; 53231 this.attributeNames = names; 53232 this.attributeValues = values; 53233 } 53234 53235 getAttribute(name) { 53236 if (this.attributeNames) { 53237 const idx = this.attributeNames.indexOf(name); 53238 53239 if (idx >= 0) { 53240 return this.attributeValues[idx]; 53241 } 53242 } 53243 53244 return undefined; 53245 } 53246 53247 popupData(type, genomeID) { 53248 const filteredProperties = new Set(['chr', 'start', 'end', 'sample', 'value', 'row', 'color', 'sampleKey', 'uniqueSampleKey', 'sampleId', 'chromosome', 'uniquePatientKey']); 53249 const locationString = this.chr + ":" + numberFormatter$1(this.start + 1) + "-" + numberFormatter$1(this.end); 53250 const pd = [{ 53251 name: "Sample", 53252 value: this.sample 53253 }, { 53254 name: "Location", 53255 value: locationString 53256 }, { 53257 name: this.valueColumnName ? capitalize(this.valueColumnName) : "Value", 53258 value: this.value 53259 }]; // TODO -- the Cravat stuff should probably be in the track (SegTrack) 53260 53261 if ("mut" === type && "hg38" === genomeID) { 53262 const l = this.extractCravatLink(genomeID); 53263 53264 if (l) { 53265 pd.push('<hr/>'); 53266 pd.push({ 53267 html: l 53268 }); 53269 pd.push('<hr/>'); 53270 } 53271 } 53272 53273 if (this.attributeNames && this.attributeNames.length > 0) { 53274 for (let i = 0; i < this.attributeNames.length; i++) { 53275 if (!filteredProperties.has(this.attributeNames[i]) & this.valueColumnName !== this.attributeNames[i]) { 53276 pd.push({ 53277 name: capitalize(this.attributeNames[i]), 53278 value: this.attributeValues[i] 53279 }); 53280 } 53281 } 53282 } 53283 53284 return pd; 53285 } 53286 53287 extractCravatLink(genomeId) { 53288 let ref, alt; 53289 53290 if (this.attributeNames && this.attributeNames.length > 0) { 53291 for (let i = 0; i < this.attributeNames.length; i++) { 53292 if (!ref && "Reference_Allele" === this.attributeNames[i]) { 53293 ref = this.attributeValues[i]; 53294 } 53295 53296 if (!alt && this.attributeNames[i].startsWith("Tumor_Seq_Allele") && this.attributeValues[i] !== ref) { 53297 alt = this.attributeValues[i]; 53298 } 53299 53300 if (ref && alt) { 53301 return TrackBase.getCravatLink(this.chr, this.start + 1, ref, alt, genomeId); 53302 } 53303 } 53304 } 53305 } 53306 53307 } 53308 53309 /* 53310 * The MIT License (MIT) 53311 * 53312 * Copyright (c) 2014 Broad Institute 53313 * 53314 * Permission is hereby granted, free of charge, to any person obtaining a copy 53315 * of this software and associated documentation files (the "Software"), to deal 53316 * in the Software without restriction, including without limitation the rights 53317 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 53318 * copies of the Software, and to permit persons to whom the Software is 53319 * furnished to do so, subject to the following conditions: 53320 * 53321 * The above copyright notice and this permission notice shall be included in 53322 * all copies or substantial portions of the Software. 53323 * 53324 * 53325 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 53326 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 53327 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 53328 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 53329 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 53330 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 53331 * THE SOFTWARE. 53332 */
53333 const knownAltBases = new Set(["A", "C", "T", "G"].map(c => c.charCodeAt(0))); 53334 53335 function createVCFVariant(tokens) { 53336 return new Variant(tokens); 53337 } 53338 53339 class Variant { 53340 constructor(tokens) { 53341 this.chr = tokens[0]; // TODO -- use genome aliases 53342 53343 this.pos = parseInt(tokens[1]); 53344 this.names = tokens[2]; // id in VCF 53345 53346 this.referenceBases = tokens[3]; 53347 this.alternateBases = tokens[4]; 53348 this.quality = tokens[5]; 53349 this.filter = tokens[6]; 53350 this.info = getInfoObject(tokens[7]); 53351 this.init(); 53352 } 53353 53354 init() { 53355 const ref = this.referenceBases; 53356 const altBases = this.alternateBases; 53357 53358 if (this.info) { 53359 if (this.info["VT"]) { 53360 this.type = this.info["VT"]; 53361 } else if (this.info["SVTYPE"]) { 53362 this.type = "SV"; 53363 } else if (this.info["PERIOD"]) { 53364 this.type = "STR"; 53365 } 53366 } 53367 53368 if (this.type === undefined) { 53369 this.type = determineType(ref, altBases); 53370 } 53371 53372 if (this.type === "NONVARIANT") { 53373 this.heterozygosity = 0; 53374 } // Determine start/end coordinates -- these are the coordinates representing the actual variant, 53375 // not the leading or trailing reference 53376 53377 53378 if (this.info["END"]) { 53379 this.start = this.pos - 1; 53380 53381 if (this.info["CHR2"] && this.info["CHR2"] !== this.chr) { 53382 this.end = this.start + 1; 53383 } else { 53384 this.end = Number.parseInt(this.info["END"]); 53385 } 53386 } else { 53387 if (this.type === "NONVARIANT") { 53388 this.start = this.pos - 1; // convert to 0-based coordinate convention 53389 53390 this.end = this.start + ref.length; 53391 } else { 53392 const altTokens = altBases.split(",").filter(token => token.length > 0); 53393 this.alleles = []; 53394 this.start = undefined; 53395 this.end = undefined; 53396 53397 for (let alt of altTokens) { 53398 this.alleles.push(alt); // We don't yet handle SV and other special alt representations 53399 53400 if ("SV" !== this.type && isKnownAlt(alt)) { 53401 let altLength = alt.length; 53402 let lengthOnRef = ref.length; 53403 const lmin = Math.min(altLength, lengthOnRef); // Trim off matching bases. Try first match, then right -> left, then any remaining left -> right 53404 53405 let s = 0; 53406 53407 while (s < lmin && ref.charCodeAt(s) === alt.charCodeAt(s)) { 53408 s++; 53409 altLength--; 53410 lengthOnRef--; 53411 } // right -> left from end 53412 53413 53414 while (altLength > 0 && lengthOnRef > 0) { 53415 const altIdx = s + altLength - 1; 53416 const refIdx = s + lengthOnRef - 1; 53417 53418 if (alt.charCodeAt(altIdx) === ref.charCodeAt(refIdx)) { 53419 altLength--; 53420 lengthOnRef--; 53421 } else { 53422 break; 53423 } 53424 } // if any remaining, left -> right 53425 53426 53427 while (altLength > 0 && lengthOnRef > 0) { 53428 const altIdx = s; 53429 const refIdx = s; 53430 53431 if (alt.charCodeAt(altIdx) === ref.charCodeAt(refIdx)) { 53432 s++; 53433 altLength--; 53434 lengthOnRef--; 53435 } else { 53436 break; 53437 } 53438 } 53439 53440 const alleleStart = this.pos + s - 1; // -1 for zero based coordinates 53441 53442 const alleleEnd = alleleStart + lengthOnRef; 53443 this.start = this.start === undefined ? alleleStart : Math.min(this.start, alleleStart); 53444 this.end = this.end === undefined ? alleleEnd : Math.max(this.end, alleleEnd); 53445 } 53446 } // Default to single base representation @ position for variant types not otherwise handled 53447 53448 53449 if (this.start === undefined) { 53450 this.start = this.pos - 1; 53451 this.end = this.pos; 53452 } 53453 } 53454 } 53455 } 53456 53457 popupData(genomicLocation, genomeId) { 53458 const posString = `${numberFormatter$1(this.pos)}`; 53459 const locString = this.start === this.end ? `${numberFormatter$1(this.start)} | ${numberFormatter$1(this.start + 1)}` : `${numberFormatter$1(this.start + 1)}-${numberFormatter$1(this.end)}`; 53460 const fields = [{ 53461 name: "Chr", 53462 value: this.chr 53463 }, { 53464 name: "Pos", 53465 value: posString 53466 }, { 53467 name: "Loc", 53468 value: locString 53469 }, { 53470 name: "Names", 53471 value: this.names ? this.names : "" 53472 }, { 53473 name: "Ref", 53474 value: this.referenceBases 53475 }, { 53476 name: "Alt", 53477 value: this.alternateBases.replace("<", "<") 53478 }, { 53479 name: "Qual",
53480 value: this.quality 53481 }, { 53482 name: "Filter", 53483 value: this.filter 53484 }]; 53485 53486 if ("SNP" === this.type) { 53487 let ref = this.referenceBases; 53488 53489 if (ref.length === 1) { 53490 let altArray = this.alternateBases.split(","); 53491 53492 for (let alt of altArray) { 53493 if (alt.length === 1) { 53494 let l = TrackBase.getCravatLink(this.chr, this.pos, ref, alt, genomeId); 53495 53496 if (l) { 53497 fields.push('<hr/>'); 53498 fields.push({ 53499 html: l 53500 }); 53501 } 53502 } 53503 } 53504 } 53505 } 53506 53507 if (this.hasOwnProperty("heterozygosity")) { 53508 fields.push({ 53509 name: "Heterozygosity", 53510 value: this.heterozygosity 53511 }); 53512 } 53513 53514 if (this.info) { 53515 fields.push({ 53516 html: '<hr style="border-top: dotted 1px;border-color: #c9c3ba" />' 53517 }); 53518 53519 for (let key of Object.keys(this.info)) { 53520 fields.push({ 53521 name: key, 53522 value: arrayToString(decodeURIComponent(this.info[key])) 53523 }); 53524 } 53525 } 53526 53527 return fields; 53528 } 53529 53530 isRefBlock() { 53531 return "NONVARIANT" === this.type; 53532 } 53533 53534 } 53535 53536 function getInfoObject(infoStr) { 53537 var info = {}; 53538 53539 if (infoStr) { 53540 infoStr.split(';').forEach(function (elem) { 53541 var element = elem.split('='); 53542 info[element[0]] = element[1]; 53543 }); 53544 } 53545 53546 return info; 53547 } 53548 53549 function isKnownAlt(alt) { 53550 for (let i = 0; i < alt.length; i++) { 53551 if (!knownAltBases.has(alt.charCodeAt(i))) { 53552 return false; 53553 } 53554 } 53555 53556 return true; 53557 } 53558 53559 function determineType(ref, altAlleles) { 53560 const refLength = ref.length; 53561 53562 if (altAlleles === undefined) { 53563 return "UNKNOWN"; 53564 } else if (altAlleles.trim().length === 0 || altAlleles === "<NON_REF>" || altAlleles === "<*>" || altAlleles === ".") { 53565 return "NONVARIANT"; 53566 } else { 53567 const alleles = altAlleles.split(","); 53568 const types = alleles.map(function (a) { 53569 if (refLength === 1 && a.length === 1) { 53570 return "SNP"; 53571 } else { 53572 return "<NON_REF>" === a ? "NONVARIANT" : "OTHER"; 53573 } 53574 }); 53575 let type = types[0]; 53576 53577 for (let t of types) { 53578 if (t !== type) { 53579 return "MIXED"; 53580 } 53581 } 53582 53583 return type; 53584 } 53585 } 53586 53587 function arrayToString(value, delim) { 53588 if (delim === undefined) delim = ","; 53589 53590 if (!Array.isArray(value)) { 53591 return value; 53592 } 53593 53594 return value.join(delim); 53595 } 53596 /** 53597 * @deprecated - the GA4GH API has been deprecated. This code no longer maintained. 53598 * @param json 53599 * @returns {Variant} 53600 */ 53601 53602 53603 function createGAVariant(json) { 53604 var variant = new Variant(); 53605 variant.chr = json.referenceName; 53606 variant.start = parseInt(json.start); // Might get overriden below 53607 53608 variant.end = parseInt(json.end); // Might get overriden below 53609 53610 variant.pos = variant.start + 1; // GA4GH is 0 based. 53611 53612 variant.names = arrayToString(json.names, "; "); 53613 variant.referenceBases = json.referenceBases; 53614 variant.alternateBases = arrayToString(json.alternateBases); 53615 variant.quality = json.quality; 53616 variant.filter = arrayToString(json.filter); // Flatten GA4GH attributes array 53617 53618 variant.info = {}; 53619 53620 if (json.info) { 53621 Object.keys(json.info).forEach(function (key) { 53622 var value, 53623 valueArray = json.info[key]; 53624 53625 if (Array.isArray(valueArray)) { 53626 value = valueArray.join(","); 53627 } else { 53628 value = valueArray; 53629 } 53630 53631 variant.info[key] = value; 53632 }); 53633 } // Need to build a hash of calls for fast lookup 53634 // Note from the GA4GH spec on call ID: 53635 // 53636 // The ID of the call set this variant call belongs to. If this field is not present,
53637 // the ordering of the call sets from a SearchCallSetsRequest over this GAVariantSet 53638 // is guaranteed to match the ordering of the calls on this GAVariant. 53639 // The number of results will also be the same. 53640 53641 53642 variant.calls = {}; 53643 var id; 53644 53645 if (json.calls) { 53646 json.calls.forEach(function (call) { 53647 id = call.callSetId; 53648 variant.calls[id] = call; 53649 }); 53650 } 53651 53652 init(variant); 53653 return variant; 53654 } 53655 53656 /* 53657 * The MIT License (MIT) 53658 * 53659 * Copyright (c) 2014 Broad Institute 53660 * 53661 * Permission is hereby granted, free of charge, to any person obtaining a copy 53662 * of this software and associated documentation files (the "Software"), to deal 53663 * in the Software without restriction, including without limitation the rights 53664 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 53665 * copies of the Software, and to permit persons to whom the Software is 53666 * furnished to do so, subject to the following conditions: 53667 * 53668 * The above copyright notice and this permission notice shall be included in 53669 * all copies or substantial portions of the Software. 53670 * 53671 * 53672 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 53673 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 53674 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 53675 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 53676 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 53677 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 53678 * THE SOFTWARE. 53679 */ 53680 /** 53681 * Parser for VCF files. 53682 */ 53683 53684 class VcfParser { 53685 construtor() {} 53686 53687 async parseHeader(dataWrapper, genome) { 53688 const header = {}; 53689 header.chrAliasTable = new Map(); // First line must be file format 53690 53691 let line = await dataWrapper.nextLine(); 53692 53693 if (line.startsWith("##fileformat")) { 53694 header.version = line.substr(13); 53695 } else { 53696 throw new Error("Invalid VCF file: missing fileformat line"); 53697 } 53698 53699 while ((line = await dataWrapper.nextLine()) !== undefined) { 53700 if (line.startsWith("#")) { 53701 let id; 53702 const values = {}; 53703 53704 if (line.startsWith("##")) { 53705 if (line.startsWith("##INFO") || line.startsWith("##FILTER") || line.startsWith("##FORMAT")) { 53706 const ltIdx = line.indexOf("<"); 53707 const gtIdx = line.lastIndexOf(">"); 53708 53709 if (!(ltIdx > 2 && gtIdx > 0)) { 53710 console.log("Malformed VCF header line: " + line); 53711 continue; 53712 } 53713 53714 const type = line.substring(2, ltIdx - 1); 53715 if (!header[type]) header[type] = {}; //##INFO=<ID=AF,Number=A,Type=Float,Description="Allele frequency based on Flow Evaluator observation counts"> 53716 // ##FILTER=<ID=NOCALL,Description="Generic filter. Filtering details stored in FR info tag."> 53717 // ##FORMAT=<ID=AF,Number=A,Type=Float,Description="Allele frequency based on Flow Evaluator observation counts"> 53718 53719 const tokens = splitStringRespectingQuotes(line.substring(ltIdx + 1, gtIdx - 1), ","); 53720 53721 for (let token of tokens) { 53722 var kv = token.split("="); 53723 53724 if (kv.length > 1) { 53725 if (kv[0] === "ID") { 53726 id = kv[1]; 53727 } else { 53728 values[kv[0]] = kv[1]; 53729 } 53730 } 53731 } 53732 53733 if (id) { 53734 header[type][id] = values; 53735 } 53736 } else if (line.startsWith("##contig") && genome) { 53737 const idx1 = line.indexOf("<ID="); 53738 let idx2 = line.indexOf(",", idx1); 53739 53740 if (idx2 == -1) { 53741 idx2 = line.indexOf(">", idx1); 53742 } 53743 53744 const chr = line.substring(idx1 + 4, idx2); 53745 const canonicalChromosome = genome.getChromosomeName(chr); 53746 header.chrAliasTable.set(canonicalChromosome, chr); 53747 } else ; 53748 } else if (line.startsWith("#CHROM")) { 53749 const tokens = line.split("\t"); 53750 53751 if (tokens.length > 8) { 53752 // call set names -- use column index for id 53753 header.callSets = []; 53754 53755 for (let j = 9; j < tokens.length; j++) { 53756 header.callSets.push({ 53757 id: j, 53758 name: tokens[j] 53759 }); 53760 } 53761 } 53762 } 53763 } else { 53764 break; 53765 } 53766 } 53767 53768 this.header = header; // Will need to intrepret genotypes and info field 53769 53770 return header; 53771 } 53772 /** 53773 * Parse data as a collection of Variant objects. 53774 * 53775 * @param data 53776 * @returns {Array} 53777 */ 53778 53779 53780 async parseFeatures(dataWrapper) { 53781 const allFeatures = []; 53782 const callSets = this.header.callSets;
53783 const nExpectedColumns = 8 + (callSets ? callSets.length + 1 : 0); 53784 let line; 53785 53786 while ((line = await dataWrapper.nextLine()) !== undefined) { 53787 if (line && !line.startsWith("#")) { 53788 const tokens = line.split("\t"); 53789 53790 if (tokens.length === nExpectedColumns) { 53791 const variant = createVCFVariant(tokens); 53792 variant.header = this.header; // Keep a pointer to the header to interpret fields for popup text 53793 53794 allFeatures.push(variant); 53795 53796 if (tokens.length > 9) { 53797 // Format 53798 const callFields = extractCallFields(tokens[8].split(":")); 53799 variant.calls = {}; 53800 53801 for (let index = 9; index < tokens.length; index++) { 53802 const token = tokens[index]; 53803 const callSet = callSets[index - 9]; 53804 const call = { 53805 callSetName: callSet.name, 53806 info: {} 53807 }; 53808 variant.calls[callSet.id] = call; 53809 token.split(":").forEach(function (callToken, idx) { 53810 switch (idx) { 53811 case callFields.genotypeIndex: 53812 call.genotype = []; 53813 callToken.split(/[\|\/]/).forEach(function (s) { 53814 call.genotype.push('.' === s ? s : parseInt(s)); 53815 }); 53816 break; 53817 53818 default: 53819 call.info[callFields.fields[idx]] = callToken; 53820 } 53821 }); 53822 } 53823 } 53824 53825 if (variant.info && variant.info.CHR2 && variant.info.END) { 53826 allFeatures.push(svComplement(variant)); 53827 } 53828 } 53829 } 53830 } 53831 53832 return allFeatures; 53833 } 53834 53835 } 53836 53837 function extractCallFields(tokens) { 53838 const callFields = { 53839 genotypeIndex: -1, 53840 fields: tokens 53841 }; 53842 53843 for (let i = 0; i < tokens.length; i++) { 53844 if ("GT" === tokens[i]) { 53845 callFields.genotypeIndex = i; 53846 } 53847 } 53848 53849 return callFields; 53850 } 53851 53852 function svComplement(v) { 53853 const chr2 = v.info.CHR2; 53854 const pos2 = Number.parseInt(v.info.END); 53855 return { 53856 chr: chr2, 53857 start: pos2 - 1, 53858 end: pos2, 53859 _f: v 53860 }; 53861 } 53862 53863 /** 53864 * Parser for IGV desktop GWAS files. See http://software.broadinstitute.org/software/igv/GWAS 53865 */ 53866 class GWASParser { 53867 constructor(config) { 53868 // Defaults - can be overriden by header 53869 this.config = config; 53870 53871 if (config.columns) { 53872 if (config.columns.chromosome === undefined || config.columns.position === undefined || config.columns.value === undefined) { 53873 throw Error("columns property must define chrCol, posCol, and valueCol"); 53874 } 53875 53876 this.posCol = config.columns.position - 1; 53877 this.chrCol = config.columns.chromosome - 1; 53878 this.pvalueCol = config.columns.value - 1; 53879 } else { 53880 // Defaults -- can be overriden in header 53881 this.posCol = 2; 53882 this.chrCol = 1; 53883 this.pvalueCol = 3; 53884 } 53885 } 53886 53887 async parseHeader(dataWrapper) { 53888 const headerLine = await dataWrapper.nextLine(); 53889 return this.parseHeaderLine(headerLine); 53890 } 53891 53892 parseHeaderLine(headerLine) { 53893 this.columns = headerLine.split(/\t/); 53894 53895 if (!this.config.columns) { 53896 for (let i = 0; i < this.columns.length; i++) { 53897 const c = this.columns[i].toLowerCase(); 53898 53899 switch (c) { 53900 case 'chr': 53901 case 'chromosome': 53902 case 'chr_id': 53903 this.chrCol = i; 53904 break; 53905 53906 case 'bp': 53907 case 'pos': 53908 case 'position': 53909 case 'chr_pos': 53910 this.posCol = i; 53911 break; 53912 53913 case 'p': 53914 case 'pval': 53915 case 'pvalue': 53916 case 'p-value': 53917 case 'p.value': 53918 this.valueCol = i; 53919 break; 53920 } 53921 } 53922 } 53923 53924 return this.columns; 53925 } 53926 53927 async parseFeatures(dataWrapper) { 53928 const allFeatures = []; 53929 const headerLine = dataWrapper.nextLine(); 53930 53931 if (!this.columns) { 53932 this.parseHeaderLine(headerLine); 53933 } 53934 53935 let line; 53936
53937 while ((line = dataWrapper.nextLine()) !== undefined) { 53938 const tokens = line.split(/\t/); 53939 53940 if (tokens.length === this.columns.length) { 53941 const chr = tokens[this.chrCol]; 53942 const start = parseInt(tokens[this.posCol]) - 1; 53943 const end = start + 1; 53944 const value = Number(tokens[this.valueCol]); 53945 allFeatures.push(new GWASFeature({ 53946 chr: chr, 53947 start: start, 53948 end: end, 53949 value: value, 53950 line: line, 53951 columns: this.columns 53952 })); 53953 } 53954 } 53955 53956 return allFeatures; 53957 } 53958 53959 } 53960 53961 class GWASFeature { 53962 constructor(_ref) { 53963 let { 53964 chr, 53965 start, 53966 end, 53967 value, 53968 line, 53969 columns 53970 } = _ref; 53971 this.chr = chr; 53972 this.start = start; 53973 this.end = end; 53974 this.value = value; 53975 this.line = line; 53976 this.columns = columns; 53977 } 53978 53979 popupData() { 53980 const tokens = this.line.split(/\t/); 53981 return this.columns.map(function (c, index) { 53982 return { 53983 name: c, 53984 value: tokens[index] 53985 }; 53986 }); 53987 } 53988 53989 getAttribute(attrName) { 53990 const tokens = this.line.split(/\t/); 53991 53992 for (let i = 0; i < this.columns.length; i++) { 53993 if (this.columns[i] === attrName) { 53994 return tokens[i]; 53995 } 53996 } 53997 53998 return undefined; 53999 } 54000 54001 } 54002 54003 /* 54004 * The MIT License (MIT) 54005 * 54006 * Copyright (c) 2014 Broad Institute 54007 * 54008 * Permission is hereby granted, free of charge, to any person obtaining a copy 54009 * of this software and associated documentation files (the "Software"), to deal 54010 * in the Software without restriction, including without limitation the rights 54011 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 54012 * copies of the Software, and to permit persons to whom the Software is 54013 * furnished to do so, subject to the following conditions: 54014 * 54015 * The above copyright notice and this permission notice shall be included in 54016 * all copies or substantial portions of the Software. 54017 * 54018 * 54019 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 54020 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 54021 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 54022 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 54023 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 54024 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 54025 * THE SOFTWARE. 54026 */ 54027 /** 54028 * Define parsers for bed-like files (.bed, .gff, .vcf, etc). A parser should implement 2 methods 54029 * 54030 * parseHeader(data) - return an object representing a header or metadata. Details are format specific 54031 * 54032 * parseFeatures(data) - return an array of features 54033 * 54034 */ 54035 54036 var aedRegexpNoNamespace = new RegExp("([^:]*)\\(([^)]*)\\)"); // name(type) for AED parsing (namespace undefined) 54037 54038 var aedRegexpNamespace = new RegExp("([^:]*):([^(]*)\\(([^)]*)\\)"); // namespace:name(type) for AED parsing 54039 54040 class AEDParser { 54041 constructor(config) { 54042 const decode = config ? config.decode : undefined; 54043 this.nameField = config ? config.nameField : undefined; 54044 this.skipRows = 0; // The number of fixed header rows to skip. Override for specific types as needed 54045 54046 if (decode) { 54047 this.decode = decode; 54048 } else { 54049 this.decode = decodeAed; 54050 } 54051 54052 this.delimiter = "\t"; 54053 } 54054 54055 async parseHeader(dataWrapper) { 54056 let line; 54057 let header; 54058 54059 while (line = await dataWrapper.nextLine()) { 54060 if (line.startsWith("track") || line.startsWith("#") || line.startsWith("browser")) { 54061 if (line.startsWith("track") || line.startsWith("#track")) { 54062 let h = parseTrackLine(line); 54063 54064 if (header) { 54065 Object.assign(header, h); 54066 } else { 54067 header = h; 54068 } 54069 } else if (line.startsWith("#columns")) { 54070 let h = parseColumnsDirective(line); 54071 54072 if (header) { 54073 Object.assign(header, h); 54074 } else { 54075 header = h; 54076 } 54077 } else if (line.startsWith("##gff-version 3")) { 54078 this.format = "gff3";
54079 if (!header) header = {}; 54080 header["format"] = "gff3"; 54081 } 54082 } else { 54083 break; 54084 } 54085 } 54086 54087 this.header = header; // Directives might be needed for parsing lines 54088 54089 return header; 54090 } 54091 54092 async parseFeatures(dataWrapper) { 54093 const allFeatures = []; 54094 const decode = this.decode; 54095 const delimiter = this.delimiter || "\t"; 54096 let i = 0; 54097 let line; 54098 let wig; 54099 54100 while ((line = dataWrapper.nextLine()) !== undefined) { 54101 i++; 54102 54103 if (i <= this.skipRows || line.startsWith("track") || line.startsWith("#") || line.startsWith("browser")) { 54104 continue; 54105 } 54106 54107 let tokens = readTokensAed(); 54108 54109 if (tokens.length < 1) { 54110 continue; 54111 } 54112 54113 if (!this.aed) { 54114 // Store information about the aed header in the parser itself 54115 // This is done only once - on the first row 54116 this.aed = parseAedHeaderRow(tokens); 54117 continue; 54118 } 54119 54120 const feature = decode.call(this, tokens, wig); 54121 54122 if (feature) { 54123 allFeatures.push(feature); 54124 } 54125 } 54126 54127 return allFeatures; // Double quoted strings can contain newlines in AED 54128 // "" is an escape for a ". 54129 // Parse all this, clean it up, split into tokens in a custom way 54130 54131 function readTokensAed() { 54132 var tokens = [], 54133 token = "", 54134 quotedString = false, 54135 n, 54136 c; 54137 54138 while (line || line === '') { 54139 for (n = 0; n < line.length; n++) { 54140 c = line.charAt(n); 54141 54142 if (c === delimiter) { 54143 if (!quotedString) { 54144 tokens.push(token); 54145 token = ""; 54146 } else { 54147 token += c; 54148 } 54149 } else if (c === "\"") { 54150 // Look ahead to the next character 54151 if (n + 1 < line.length && line.charAt(n + 1) === "\"") { 54152 if (quotedString) { 54153 // Turn "" into a single " in the output string 54154 token += "\""; 54155 } // Skip the next double quote 54156 54157 54158 n++; 54159 } else { 54160 // We know the next character is NOT a double quote, flip our state 54161 quotedString = !quotedString; 54162 } 54163 } else { 54164 token += c; 54165 } 54166 } // We are at the end of the line 54167 54168 54169 if (quotedString) { 54170 token += '\n'; // Add newline to the token 54171 54172 line = nextLine(); // Keep going 54173 } else { 54174 // We can end the loop 54175 break; 54176 } 54177 } // Push the last token 54178 54179 54180 tokens.push(token); 54181 return tokens; 54182 } 54183 } 54184 54185 } 54186 54187 function parseAedToken(value) { 54188 // Example: refseq:accessionNumber(aed:String) 54189 // refseq - namespace, will be declared later 54190 // accessionNumber - name of the field 54191 // aed:String - type of the field 54192 // The namespace part may be missing 54193 var match = aedRegexpNamespace.exec(value); 54194 54195 if (match) { 54196 return { 54197 namespace: match[1], 54198 name: match[2], 54199 type: match[3] 54200 }; 54201 } 54202 54203 match = aedRegexpNoNamespace.exec(value); 54204 54205 if (match) { 54206 return { 54207 namespace: '?', 54208 name: match[1], 54209 type: match[2] 54210 }; 54211 } else { 54212 throw new Error("Error parsing the header row of AED file - column not in ns:name(ns:type) format"); 54213 } 54214 } 54215 54216 function parseAedHeaderRow(tokens) { 54217 // First row of AED file defines column names 54218 // Each header item is an aed token - see parseAedToken 54219 var aed, k, token, aedToken; // Initialize aed section to be filled in 54220 54221 aed = { 54222 columns: [// Information about the namespace, name and type of each column 54223 // Example entry: 54224 // { namespace: 'bio', name: 'start', type: 'aed:Integer' } 54225 ], 54226 metadata: {// Metadata about the entire AED file 54227 // Example: 54228 // { 54229 // aed: { 54230 // application: { value: "CHaS Browser 3.3.0.139 (r10838)", type: "aed:String" }, 54231 // created: { value: "2018-01-02T10:20:30.123+01:00", type: "aed:DateTime" }, 54232 // modified: { value: "2018-03-04T11:22:33.456+01:00", type: "aed:DateTime" }, 54233 // } 54234 // affx: { 54235 // ucscGenomeVersion: { value: "hg19", type: "aed:String" } 54236 // }, 54237 // namespace: { 54238 // omim: { value: "http://affymetrix.com/ontology/www.ncbi.nlm.nih.gov/omim/", type: "aed:URI" }, 54239 // affx: { value: "http://affymetrix.com/ontology/", type: "aed:URI" }, 54240 // refseq: { value: "http://affymetrix.com/ontology/www.ncbi.nlm.nih.gov/RefSeq/", type: "aed:URI" } 54241 // } 54242 // } 54243 } 54244 }; 54245 54246 for (k = 0; k < tokens.length; k++) { 54247 token = tokens[k]; 54248 aedToken = parseAedToken(token); 54249 aed.columns.push(aedToken); 54250 } 54251 54252 return aed; 54253 } 54254 54255 function parseTrackLine(line) { 54256 const properties = {}; 54257 const tokens = line.split(/(?:")([^"]+)(?:")|([^\s"]+)(?=\s+|$)/g); // Clean up tokens array 54258 54259 let curr; 54260 const tmp = []; 54261 54262 for (let tk of tokens) { 54263 if (!tk || tk.trim().length === 0) continue; 54264 54265 if (tk.endsWith("=") > 0) { 54266 curr = tk; 54267 } else if (curr) { 54268 tmp.push(curr + tk); 54269 curr = undefined; 54270 } else { 54271 tmp.push(tk); 54272 } 54273 } 54274 54275 for (let str of tmp) { 54276 if (!str) return; 54277 var kv = str.split('=', 2); 54278 54279 if (kv.length === 2) {
54280 const key = kv[0].trim(); 54281 const value = kv[1].trim(); 54282 properties[key] = value; 54283 } 54284 } 54285 54286 return properties; 54287 } 54288 54289 function parseColumnsDirective(line) { 54290 let properties = {}; 54291 let t1 = line.split(/\s+/); 54292 54293 if (t1.length === 2) { 54294 let t2 = t1[1].split(";"); 54295 t2.forEach(function (keyValue) { 54296 let t = keyValue.split("="); 54297 54298 if (t[0] === "color") { 54299 properties.colorColumn = Number.parseInt(t[1]) - 1; 54300 } else if (t[0] === "thickness") { 54301 properties.thicknessColumn = Number.parseInt(t[1]) - 1; 54302 } 54303 }); 54304 } 54305 54306 return properties; 54307 } 54308 /** 54309 * AED file feature. 54310 * 54311 * @param aed link to the AED file object containing file-level metadata and column descriptors 54312 * @param allColumns All columns as parsed from the AED 54313 * 54314 * Other values are parsed one by one 54315 */ 54316 54317 54318 function AedFeature(aed, allColumns) { 54319 var token, 54320 aedColumn, 54321 aedColumns = aed.columns; // Link to AED file (for metadata) 54322 54323 this.aed = aed; // Unparsed columns from AED file 54324 54325 this.allColumns = allColumns; // Prepare space for the parsed values 54326 54327 this.chr = null; 54328 this.start = null; 54329 this.end = null; 54330 this.score = 1000; 54331 this.strand = '.'; 54332 this.cdStart = null; 54333 this.cdEnd = null; 54334 this.name = null; 54335 this.color = null; 54336 54337 for (let i = 0; i < allColumns.length; i++) { 54338 token = allColumns[i]; 54339 54340 if (!token) { 54341 // Skip empty fields 54342 continue; 54343 } 54344 54345 aedColumn = aedColumns[i]; 54346 54347 if (aedColumn.type === 'aed:Integer') { 54348 token = parseInt(token); 54349 } 54350 54351 var arr = []; 54352 54353 if (aedColumn.namespace.length > 0) { 54354 for (let j = 0; j < aedColumn.namespace.length; j++) { 54355 arr.push(aedColumn.namespace.charCodeAt(j)); 54356 } 54357 } 54358 54359 if (aedColumn.namespace.trim() === 'bio') { 54360 if (aedColumn.name === 'sequence') { 54361 this.chr = token; 54362 } else if (aedColumn.name === 'start') { 54363 this.start = token; 54364 } else if (aedColumn.name === 'end') { 54365 this.end = token; 54366 } else if (aedColumn.name === 'cdsMin') { 54367 this.cdStart = token; 54368 } else if (aedColumn.name === 'cdsMax') { 54369 this.cdEnd = token; 54370 } else if (aedColumn.name === 'strand') { 54371 this.strand = token; 54372 } 54373 } else if (aedColumn.namespace === 'aed') { 54374 if (aedColumn.name === 'name') { 54375 this.name = token; 54376 } 54377 } else if (aedColumn.namespace === 'style') { 54378 if (aedColumn.name === 'color') { 54379 this.color = IGVColor.createColorString(token); 54380 } 54381 } 54382 } 54383 } 54384 54385 AedFeature.prototype.popupData = function () { 54386 var data = [], 54387 aed = this.aed; // Just dump everything we have for now 54388 54389 for (var i = 0; i < this.allColumns.length; i++) { 54390 var featureValue = this.allColumns[i]; 54391 var name = aed.columns[i].name; // Skip columns that are not interesting - you know the sequence, and you can see color 54392 54393 if (name !== 'sequence' && name !== 'color') { 54394 if (featureValue) { 54395 data.push({ 54396 name: name, 54397 value: featureValue 54398 }); 54399 } 54400 } 54401 } 54402 54403 return data; 54404 }; 54405 /** 54406 * Decode the AED file format 54407 * @param tokens 54408 * @param ignore 54409 * @returns decoded feature, or null if this is not a valid record 54410 */ 54411 54412 54413 function decodeAed(tokens, ignore) { 54414 var name, 54415 value, 54416 token, 54417 nonEmptyTokens = 0, 54418 aedColumns = this.aed.columns, 54419 aedColumn, 54420 aedKey, 54421 i; // Each aed row must match the exact number of columns or we skip it 54422 54423 if (tokens.length !== aedColumns.length) { 54424 console.log('Corrupted AED file row: ' + tokens.join(',')); 54425 return undefined; 54426 } 54427 54428 for (i = 0; i < tokens.length; i++) { 54429 aedColumn = aedColumns[i]; 54430 token = tokens[i]; 54431 54432 if (token !== '') { 54433 nonEmptyTokens++; 54434 } 54435 54436 if (aedColumn.name === 'name' && aedColumn.namespace === 'aed') { 54437 name = token; 54438 } else if (aedColumn.name === 'value' && aedColumn.namespace === 'aed') { 54439 value = token; 54440 } 54441 } 54442 54443 if (nonEmptyTokens === 2 && name && value) { 54444 // Special row that defines metadata for the entire file 54445 aedKey = parseAedToken(name); // Store in the metadata section 54446 54447 if (!this.aed.metadata[aedKey.namespace]) { 54448 this.aed.metadata[aedKey.namespace] = {}; 54449 } 54450 54451 if (!this.aed.metadata[aedKey.namespace][aedKey.name]) { 54452 this.aed.metadata[aedKey.namespace][aedKey.name] = { 54453 type: aedKey.type, 54454 value: value 54455 }; 54456 } // Ignore this value 54457 54458 54459 return undefined; 54460 } 54461 54462 var feature = new AedFeature(this.aed, tokens); 54463 54464 if (!feature.chr || !feature.start && feature.start !== 0 || !feature.end
54464) { 54465 console.log('Cannot parse feature: ' + tokens.join(',')); 54466 return undefined; 54467 } 54468 54469 return feature; 54470 } 54471 54472 /* 54473 * The MIT License (MIT) 54474 * 54475 * Copyright (c) 2016-2017 The Regents of the University of California 54476 * Author: Jim Robinson 54477 * 54478 * Permission is hereby granted, free of charge, to any person obtaining a copy 54479 * of this software and associated documentation files (the "Software"), to deal 54480 * in the Software without restriction, including without limitation the rights 54481 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 54482 * copies of the Software, and to permit persons to whom the Software is 54483 * furnished to do so, subject to the following conditions: 54484 * 54485 * The above copyright notice and this permission notice shall be included in 54486 * all copies or substantial portions of the Software. 54487 * 54488 * 54489 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 54490 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 54491 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 54492 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 54493 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 54494 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 54495 * THE SOFTWARE. 54496 */ 54497 function getDataWrapper(data) { 54498 if (typeof data == 'string' || data instanceof String) { 54499 return new StringDataWrapper(data); 54500 } else { 54501 return new ByteArrayDataWrapper(data); 54502 } 54503 } // Data might be a string, or an UInt8Array 54504 54505 54506 class StringDataWrapper { 54507 constructor(string) { 54508 this.data = string; 54509 this.ptr = 0; 54510 } 54511 54512 nextLine() { 54513 var start = this.ptr, 54514 idx = this.data.indexOf('\n', start), 54515 data = this.data; 54516 54517 if (idx > 0) { 54518 this.ptr = idx + 1; // Advance pointer for next line 54519 54520 if (idx > start && data.charAt(idx - 1) === '\r') { 54521 // Trim CR manually in CR/LF sequence 54522 return data.substring(start, idx - 1); 54523 } 54524 54525 return data.substring(start, idx); 54526 } else { 54527 var length = data.length; 54528 this.ptr = length; // Return undefined only at the very end of the data 54529 54530 return start >= length ? undefined : data.substring(start); 54531 } 54532 } 54533 54534 } 54535 54536 class ByteArrayDataWrapper { 54537 constructor(array) { 54538 this.data = array; 54539 this.length = this.data.length; 54540 this.ptr = 0; 54541 } 54542 54543 nextLine() { 54544 var c, result; 54545 result = ""; 54546 if (this.ptr >= this.length) return undefined; 54547 54548 for (var i = this.ptr; i < this.length; i++) { 54549 c = String.fromCharCode(this.data[i]); 54550 if (c === '\r') continue; 54551 if (c === '\n') break; 54552 result = result + c; 54553 } 54554 54555 this.ptr = i + 1; 54556 return result; 54557 } 54558 54559 } 54560 54561 class BGZipLineReader { 54562 constructor(config) { 54563 this.config = config; 54564 this.filePtr = 0; 54565 this.bufferPtr = 0; 54566 this.buffer; 54567 } 54568 54569 async nextLine() { 54570 let result = undefined; 54571 54572 try { 54573 while (true) { 54574 const length = this.buffer ? this.buffer.length : 0; 54575 54576 while (this.bufferPtr < length) { 54577 const c = String.fromCharCode(this.buffer[this.bufferPtr++]); 54578 if (c === '\r') continue; 54579 54580 if (c === '\n') { 54581 return result; 54582 } 54583 54584 result = result ? result + c : c; 54585 } 54586 54587 if (this.eof) { 54588 return result; 54589 } else { 54590 await this.readNextBlock(); 54591 } 54592 } 54593 } catch (e) { 54594 console.warn(e); 54595 this.eof = true; 54596 return result; 54597 } 54598 } 54599 54600 async readNextBlock() { 54601 const bsizeOptions = buildOptions(this.config, { 54602 range: { 54603 start: this.filePtr, 54604 size: 26 54605 } 54606 }); 54607 const abuffer = await igvxhr.loadArrayBuffer(this.config.url, bsizeOptions); 54608 const bufferSize = bgzBlockSize(abuffer); //console.log(`next block ${this.filePtr} ${bufferSize}`); 54609 54610 if (bufferSize === 0) { 54611 this.eof = true; 54612 this.buffer = undefined; 54613 } else { 54614 const options = buildOptions(this.config, { 54615 range: { 54616 start: this.filePtr, 54617 size: bufferSize 54618 } 54619 }); 54620 const data = await igvxhr.loadArrayBuffer(this.config.url, options); 54621 54622 if (data.byteLength < bufferSize) { 54623 this.eof = true; // Assumption 54624 } 54625 54626 this.buffer = unbgzf(data); 54627 this.bufferPtr = 0; 54628 this.filePtr += data.byteLength; //data.byteLength; 54629 } 54630 } 54631 54632 } 54633 54634 /* 54635 * The MIT License (MIT) 54636 * 54637 * Copyright (c) 2014 Broad Institute 54638 * 54639 * Permission is hereby granted, free of charge, to any person obtaining a copy 54640 * of this software and associated documentation files (the "Software"), to deal 54641 * in the Software without restriction, including without limitation the rights 54642 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 54643 * copies of the Software, and to permit persons to whom the Software is 54644 * furnished to do so, subject to the following conditions: 54645 * 54646 * The above copyright notice and this permission notice shall be included in 54647 * all copies or substantial portions of the Software. 54648 * 54649 * 54650 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 54651 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 54652 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 54653 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 54654 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 54655 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 54656 * THE SOFTWARE. 54657 */ 54658 /** 54659 * Reader for "bed like" files (tab delimited files with 1 feature per line: bed, gff, vcf, etc) 54660 * 54661 * @param config 54662 * @constructor 54663 */ 54664 54665 class FeatureFileReader { 54666 constructor(config, genome) { 54667 var uriParts; 54668 this.config = config || {}; 54669 this.genome = genome; 54670 this.indexURL = config.indexURL; 54671 this.indexed = config.indexed; 54672 54673 if (isFile(this.config.url)) { 54674 this.filename = this.config.url.name; 54675 } else if (isDataURL(this.config.url)) { 54676 this.indexed = false; // by definition 54677 54678 this.dataURI = config.url; 54679 } else { 54680 uriParts = parseUri(this.config.url); 54681 this.filename = config.filename || uriParts.file; 54682 } 54683 54684 this.parser = this.getParser(this.config); 54685 54686 if (this.config.format === "vcf" && !this.config.indexURL) { 54687 console.warn("Warning: index file not specified. The entire vcf file will be loaded."); 54688 } 54689 } 54690 54691 async defaultVisibilityWindow() { 54692 if (this.config.indexURL) { 54693 const index = await this.getIndex(); 54694 54695 if (index && index.lastBlockPosition) { 54696 let gl = 0; 54697 const s = 10000; 54698 54699 for (let c of index.chromosomeNames) { 54700 const chromosome = this.genome.getChromosome(c); 54701 54702 if (chromosome) { 54703 gl += chromosome.bpLength; 54704 } 54705 } 54706 54707 return Math.round(gl / index.lastBlockPosition * s); 54708 } 54709 } 54710 } 54711 /** 54712 * Return a promise to load features for the genomic interval 54713 * @param chr 54714 * @param start 54715 * @param end 54716 */ 54717 54718 54719 async readFeatures(chr, start, end) { 54720 const index = await this.getIndex(); 54721 54722 if (index) { 54723 this.indexed = true; 54724 return this.loadFeaturesWithIndex(chr, start, end); 54725 } else if (this.dataURI) { 54726 this.indexed = false;
54727 return this.loadFeaturesFromDataURI(); 54728 } else { 54729 this.indexed = false; 54730 return this.loadFeaturesNoIndex(); 54731 } 54732 } 54733 54734 async readHeader() { 54735 if (this.dataURI) { 54736 await this.loadFeaturesFromDataURI(this.dataURI); 54737 return this.header; 54738 } else { 54739 if (this.config.indexURL) { 54740 const index = await this.getIndex(); 54741 54742 if (!index) { 54743 // Note - it should be impossible to get here 54744 throw new Error("Unable to load index: " + this.config.indexURL); 54745 } 54746 54747 let dataWrapper; 54748 54749 if (index.tabix) { 54750 dataWrapper = new BGZipLineReader(this.config); 54751 } else { 54752 // Tribble 54753 const maxSize = Object.values(index.chrIndex).flatMap(chr => chr.blocks).map(block => block.max).reduce((previous, current) => Math.min(previous, current), Number.MAX_SAFE_INTEGER); 54754 const options = buildOptions(this.config, { 54755 bgz: index.tabix, 54756 range: { 54757 start: 0, 54758 size: maxSize 54759 } 54760 }); 54761 const data = await igvxhr.loadString(this.config.url, options); 54762 dataWrapper = getDataWrapper(data); 54763 } 54764 54765 this.header = await this.parser.parseHeader(dataWrapper); // Cache header, might be needed to parse features 54766 54767 return this.header; 54768 } else { 54769 // If this is a non-indexed file we will load all features in advance 54770 const options = buildOptions(this.config); 54771 const data = await igvxhr.loadString(this.config.url, options); 54772 let dataWrapper = getDataWrapper(data); 54773 this.header = await this.parser.parseHeader(dataWrapper); // Reset data wrapper and parse features 54774 54775 dataWrapper = getDataWrapper(data); 54776 this.features = await this.parser.parseFeatures(dataWrapper); // cache features 54777 54778 return this.header; 54779 } 54780 } 54781 } 54782 54783 getParser(config) { 54784 switch (config.format) { 54785 case "vcf": 54786 return new VcfParser(config); 54787 54788 case "seg": 54789 return new SegParser("seg"); 54790 54791 case "mut": 54792 return new SegParser("mut"); 54793 54794 case "maf": 54795 return new SegParser("maf"); 54796 54797 case "gwas": 54798 return new GWASParser(config); 54799 54800 case "aed": 54801 return new AEDParser(config); 54802 54803 default: 54804 return new FeatureParser(config); 54805 } 54806 } 54807 54808 async loadFeaturesNoIndex() { 54809 if (this.features) { 54810 // An optimization hack for non-indexed files, features are temporarily cached when header is read. 54811 const tmp = this.features; 54812 delete this.features; 54813 return tmp; 54814 } else { 54815 const options = buildOptions(this.config); // Add oauth token, if any 54816 54817 const data = await igvxhr.loadString(this.config.url, options); 54818 54819 if (!this.header) { 54820 const dataWrapper = getDataWrapper(data); 54821 this.header = await this.parser.parseHeader(dataWrapper); 54822 } 54823 54824 const dataWrapper = getDataWrapper(data); 54825 const features = await this.parser.parseFeatures(dataWrapper); // <= PARSING DONE HERE 54826 54827 return features; 54828 } 54829 } 54830 54831 async loadFeaturesWithIndex(chr, start, end) { 54832 //console.log("Using index" 54833 const config = this.config; 54834 const parser = this.parser; 54835 const tabix = this.index.tabix; 54836 const refId = tabix ? this.index.sequenceIndexMap[chr] : chr; 54837 54838 if (refId === undefined) { 54839 return []; 54840 } 54841 54842 const genome = this.genome; 54843 const blocks = this.index.blocksForRange(refId, start, end); 54844 54845 if (!blocks || blocks.length === 0) { 54846 return []; 54847 } else { 54848 const allFeatures = []; 54849 54850 for (let block of blocks) { 54851 const startPos = block.minv.block; 54852 const startOffset = block.minv.offset; 54853 const endOffset = block.maxv.offset; 54854 let endPos; 54855 54856 if (tabix) { 54857 let lastBlockSize = 0; 54858 54859 if (endOffset > 0) { 54860 const bsizeOptions = buildOptions(config, { 54861 range: { 54862 start: block.maxv.block, 54863 size: 26 54864 } 54865 }); 54866 const abuffer = await igvxhr.loadArrayBuffer(config.url, bsizeOptions); 54867 lastBlockSize = bgzBlockSize(abuffer); 54868 } 54869 54870 endPos = block.maxv.block + lastBlockSize; 54871 } else { 54872 endPos = block.maxv.block; 54873 } 54874 54875 const options = buildOptions(config, { 54876 range: { 54877 start: startPos, 54878 size: endPos - startPos + 1 54879 } 54880 }); 54881 let inflated; 54882 54883 if (tabix) { 54884 const data = await igvxhr.loadArrayBuffer(config.url, options); 54885 inflated = unbgzf(data); 54886 } else { 54887 inflated = await igvxhr.loadString(config.url, options); 54888 } 54889 54890 const slicedData = startOffset ? inflated.slice(startOffset) : inflated; 54891 const dataWrapper = getDataWrapper(slicedData); 54892 let slicedFeatures = await parser.parseFeatures(dataWrapper); // Filter psuedo-features (e.g. created mates for VCF SV records) 54893 54894 slicedFeatures = slicedFeatures.filter(f => f._f === undefined); // Filter features not in requested range. 54895 54896 let inInterval = false;
54897 54898 for (let i = 0; i < slicedFeatures.length; i++) { 54899 const f = slicedFeatures[i]; 54900 const canonicalChromosome = genome ? genome.getChromosomeName(f.chr) : f.chr; 54901 54902 if (canonicalChromosome !== chr) { 54903 if (allFeatures.length === 0) { 54904 continue; //adjacent chr to the left 54905 } else { 54906 break; //adjacent chr to the right 54907 } 54908 } 54909 54910 if (f.start > end) { 54911 allFeatures.push(f); // First feature beyond interval 54912 54913 break; 54914 } 54915 54916 if (f.end >= start && f.start <= end) { 54917 if (!inInterval) { 54918 inInterval = true; 54919 54920 if (i > 0) { 54921 allFeatures.push(slicedFeatures[i - 1]); 54922 } 54923 } 54924 54925 allFeatures.push(f); 54926 } 54927 } 54928 } 54929 54930 allFeatures.sort(function (a, b) { 54931 return a.start - b.start; 54932 }); 54933 return allFeatures; 54934 } 54935 } 54936 54937 async getIndex() { 54938 if (this.index) { 54939 return this.index; 54940 } else if (this.config.indexURL) { 54941 this.index = await this.loadIndex(); 54942 return this.index; 54943 } 54944 } 54945 /** 54946 * Return a Promise for the async loaded index 54947 */ 54948 54949 54950 async loadIndex() { 54951 const indexURL = this.config.indexURL; 54952 return loadIndex(indexURL, this.config, this.genome); 54953 } 54954 54955 async loadFeaturesFromDataURI() { 54956 if (this.features) { 54957 // An optimization hack for non-indexed files, features are temporarily cached when header is read. 54958 const tmp = this.features; 54959 delete this.features; 54960 return tmp; 54961 } else { 54962 const plain = decodeDataURI$1(this.dataURI); 54963 let dataWrapper = getDataWrapper(plain); 54964 this.header = await this.parser.parseHeader(dataWrapper); 54965 54966 if (this.header instanceof String && this.header.startsWith("##gff-version 3")) { 54967 this.format = 'gff3'; 54968 } 54969 54970 dataWrapper = getDataWrapper(plain); 54971 this.features = await this.parser.parseFeatures(dataWrapper); 54972 return this.features; 54973 } 54974 } 54975 54976 } 54977 54978 /* 54979 * The MIT License (MIT) 54980 * 54981 * Copyright (c) 2016 University of California San Diego 54982 * Author: Jim Robinson 54983 * 54984 * Permission is hereby granted, free of charge, to any person obtaining a copy 54985 * of this software and associated documentation files (the "Software"), to deal 54986 * in the Software without restriction, including without limitation the rights 54987 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 54988 * copies of the Software, and to permit persons to whom the Software is 54989 * furnished to do so, subject to the following conditions: 54990 * 54991 * The above copyright notice and this permission notice shall be included in 54992 * all copies or substantial portions of the Software. 54993 * 54994 * 54995 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 54996 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 54997 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 54998 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 54999 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 55000 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 55001 * THE SOFTWARE. 55002 */ 55003 const isString$1 = isString$3; 55004 55005 class CustomServiceReader { 55006 constructor(config) { 55007 this.config = config; 55008 } 55009 55010 async readFeatures(chr, start, end) { 55011 let url; 55012 55013 if (typeof this.config.url === 'function') { 55014 url = this.config.url({ 55015 chr, 55016 start, 55017 end 55018 }); 55019 } else { 55020 url = this.config.url.replace("$CHR", chr).replace("$START", start).replace("$END", end); 55021 } 55022 55023 let config = Object.assign({}, this.config); 55024 55025 if (this.config.body !== undefined) { 55026 if (typeof this.config.body === 'function') { 55027 config.body = this.config.body({ 55028 chr, 55029 start, 55030 end 55031 }); 55032 } else { 55033 config.body = this.config.body.replace("$CHR", chr).replace("$START", start).replace("$END", end); 55034 } 55035 } 55036 55037 let features; 55038 const data = await igvxhr.load(url, config); 55039 55040 if (data) { 55041 if (typeof this.config.parser === "function") { 55042 features = this.config.parser(data); 55043 } else if (isString$1(data)) { 55044 features = JSON.parse(data); 55045 } else { 55046 features = data; 55047 } 55048 } 55049 55050 if (this.config.mappings) { 55051 let mappingKeys = Object.keys(this.config.mappings); 55052 55053 for (let f of features) { 55054 for (let key of mappingKeys) { 55055 f[key] = f[this.config.mappings[key]]; 55056 } 55057 } 55058 } 55059 55060 return features; 55061 } 55062 55063 } 55064 55065 /* 55066 * The MIT License (MIT) 55067 * 55068 * Copyright (c) 2016-2017 The Regents of the University of California 55069 * Author: Jim Robinson 55070 * 55071 * Permission is hereby granted, free of charge, to any person obtaining a copy 55072 * of this software and associated documentation files (the "Software"), to deal 55073 * in the Software without restriction, including without limitation the rights 55074 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 55075 * copies of the Software, and to permit persons to whom the Software is 55076 * furnished to do so, subject to the following conditions: 55077 * 55078 * The above copyright notice and this permission notice shall be included in 55079 * all copies or substantial portions of the Software. 55080 * 55081 * 55082 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 55083 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 55084 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 55085 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 55086 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 55087 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 55088 * THE SOFTWARE. 55089 */ 55090 55091 const UCSCServiceReader = function (config, genome) { 55092 this.config = config; 55093 this.genome = genome; 55094 this.expandQueryInterval = false;
55095 }; 55096 55097 UCSCServiceReader.prototype.readFeatures = function (chr, start, end) { 55098 const s = Math.max(0, Math.floor(start)); 55099 let e = Math.ceil(end); 55100 55101 if (this.genome) { 55102 const c = this.genome.getChromosome(chr); 55103 55104 if (c && e > c.bpLength) { 55105 e = c.bpLength; 55106 } 55107 } 55108 55109 const url = this.config.url + '?db=' + this.config.db + '&table=' + this.config.tableName + '&chr=' + chr + '&start=' + s + '&end=' + e; 55110 return igvxhr.loadJson(url, this.config).then(function (data) { 55111 if (data) { 55112 data.forEach(function (sample) { 55113 if (sample.hasOwnProperty('exonStarts') && sample.hasOwnProperty('exonEnds') && sample.hasOwnProperty('exonCount') && sample.hasOwnProperty('cdsStart') && sample.hasOwnProperty('cdsEnd')) { 55114 addExons(sample); 55115 } 55116 }); 55117 return data; 55118 } else { 55119 return null; 55120 } 55121 }); 55122 }; 55123 55124 function addExons(sample) { 55125 var exonCount, exonStarts, exonEnds, exons, eStart, eEnd; 55126 exonCount = sample['exonCount']; 55127 exonStarts = sample['exonStarts'].split(','); 55128 exonEnds = sample['exonEnds'].split(','); 55129 exons = []; 55130 55131 for (var i = 0; i < exonCount; i++) { 55132 eStart = parseInt(exonStarts[i]); 55133 eEnd = parseInt(exonEnds[i]); 55134 var exon = { 55135 start: eStart, 55136 end: eEnd 55137 }; 55138 if (sample.cdsStart > eEnd || sample.cdsEnd < sample.cdsStart) exon.utr = true; // Entire exon is UTR 55139 55140 if (sample.cdsStart >= eStart && sample.cdsStart <= eEnd) exon.cdStart = sample.cdsStart; 55141 if (sample.cdsEnd >= eStart && sample.cdsEnd <= eEnd) exon.cdEnd = sample.cdsEnd; 55142 exons.push(exon); 55143 } 55144 55145 sample.exons = exons; 55146 } 55147 55148 /* 55149 * The MIT License (MIT) 55150 * 55151 * Copyright (c) 2021 University of California San Diego 55152 * Author: Jim Robinson 55153 * 55154 * Permission is hereby granted, free of charge, to any person obtaining a copy 55155 * of this software and associated documentation files (the "Software"), to deal 55156 * in the Software without restriction, including without limitation the rights 55157 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 55158 * copies of the Software, and to permit persons to whom the Software is 55159 * furnished to do so, subject to the following conditions: 55160 * 55161 * The above copyright notice and this permission notice shall be included in 55162 * all copies or substantial portions of the Software. 55163 * 55164 * 55165 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 55166 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 55167 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 55168 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 55169 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 55170 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 55171 * THE SOFTWARE. 55172 */ 55173 const gffNameFields = ["Name", "gene_name", "gene", "gene_id", "alias", "locus", "name"]; 55174 55175 class GFFHelper { 55176 constructor(options) { 55177 this.format = options.format; 55178 this.nameField = options.nameField; 55179 this.filterTypes = options.filterTypes === undefined ? new Set(['chromosome']) : new Set(options.filterTypes); 55180 } 55181 55182 combineFeatures(features, genomicInterval) { 55183 let combinedFeatures; 55184 const filterTypes = this.filterTypes; 55185 features = features.filter(f => filterTypes === undefined || !filterTypes.has(f.type)); 55186 55187 if ("gff3" === this.format) { 55188 const tmp = this.combineFeaturesById(features); 55189 combinedFeatures = this.combineFeaturesByType(tmp); 55190 } else { 55191 combinedFeatures = this.combineFeaturesByType(features); 55192 } 55193 55194 combinedFeatures.sort(function (a, b) { 55195 return a.start - b.start; 55196 }); 55197 this.numberExons(combinedFeatures, genomicInterval); 55198 this.nameFeatures(combinedFeatures); 55199 return combinedFeatures; 55200 } 55201 /** 55202 * Combine multiple non-transcript model features with the same ID on the same chromosome into a single feature. 55203 * Features that are part of the transcript model (e.g. exon, mRNA, etc) are combined later. 55204 * 55205 * @param features 55206 * @returns {[]} 55207 */ 55208 55209 55210 combineFeaturesById(features) { 55211 const chrIdMap = new Map(); 55212 const combinedFeatures = []; 55213 55214 for (let f of features) { 55215 if (isTranscriptPart(f.type) || isTranscript(f.type) || !f.id) { 55216 combinedFeatures.push(f); 55217 } else { 55218 let idMap = chrIdMap.get(f.chr); 55219 55220 if (!idMap) { 55221 idMap = new Map(); 55222 chrIdMap.set(f.chr, idMap); 55223 } 55224 55225 let featureArray = idMap.get(f.id); 55226 55227 if (featureArray) { 55228 featureArray.push(f); 55229 } else { 55230 idMap.set(f.id, [f]); 55231 } 55232 } 55233 } 55234 55235 for (let idMap of chrIdMap.values()) { 55236 for (let featureArray of idMap.values()) { 55237 if (featureArray.length > 1) { 55238 // Use the first feature as prototypical (for column 9 attributes), and adjust start/end 55239 // Parts are represented as "exons", as that is how they are presented visually 55240 const cf = featureArray[0]; 55241 cf.exons = []; 55242 55243 for (let f of featureArray) {
55244 cf.start = Math.min(cf.start, f.start); 55245 cf.end = Math.max(cf.end, f.end); 55246 cf.exons.push({ 55247 start: f.start, 55248 end: f.end 55249 }); 55250 } 55251 55252 combinedFeatures.push(cf); 55253 } else { 55254 combinedFeatures.push(featureArray[0]); 55255 } 55256 } 55257 } 55258 55259 return combinedFeatures; 55260 } 55261 55262 combineFeaturesByType(features) { 55263 // Build dictionary of genes 55264 const genes = features.filter(f => "gene" === f.type || f.type.endsWith("_gene")); 55265 const geneMap = Object.create(null); 55266 55267 for (let g of genes) { 55268 geneMap[g.id] = g; 55269 } // 1. Build dictionary of transcripts 55270 55271 55272 const transcripts = Object.create(null); 55273 const combinedFeatures = []; 55274 const consumedFeatures = new Set(); 55275 const filterTypes = this.filterTypes; 55276 features = features.filter(f => filterTypes === undefined || !filterTypes.has(f.type)); 55277 55278 for (let f of features) { 55279 if (f.type === "biological_region") { 55280 console.log(); 55281 } 55282 55283 if (isTranscript(f.type)) { 55284 const transcriptId = f.id; // getAttribute(f.attributeString, "transcript_id", /\s+/); 55285 55286 if (undefined !== transcriptId) { 55287 const gffTranscript = new GFFTranscript(f); 55288 transcripts[transcriptId] = gffTranscript; 55289 combinedFeatures.push(gffTranscript); 55290 consumedFeatures.add(f); 55291 const g = geneMap[f.parent]; 55292 55293 if (g) { 55294 gffTranscript.geneObject = g; 55295 consumedFeatures.add(g); 55296 } 55297 } 55298 } 55299 } // Add exons and transcript parts 55300 55301 55302 for (let f of features) { 55303 if (isTranscriptPart(f.type)) { 55304 const parents = getParents(f); 55305 55306 if (parents) { 55307 for (let id of parents) { 55308 let transcript = transcripts[id]; 55309 55310 if (!transcript && this.format === "gtf") { 55311 // GTF does not require explicit transcript record, start one with this feature. 55312 const psuedoTranscript = Object.assign({}, f); 55313 psuedoTranscript.type = "transcript"; 55314 transcript = new GFFTranscript(psuedoTranscript); 55315 transcripts[id] = transcript; 55316 combinedFeatures.push(transcript); 55317 } 55318 55319 if (transcript !== undefined) { 55320 if (isExon(f.type)) { 55321 if (parents.length > 1) { 55322 // Make a copy as exon can be modified differently by CDS, etc, for each transcript 55323 const e2 = new GFFFeature(f); 55324 transcript.addExon(e2); 55325 } else { 55326 transcript.addExon(f); 55327 } 55328 } else { 55329 transcript.addPart(f); 55330 } 55331 55332 consumedFeatures.add(f); 55333 } 55334 } 55335 } 55336 } 55337 }
55337 // Finish transcripts 55338 55339 55340 combinedFeatures.forEach(function (f) { 55341 if (typeof f.finish === "function") { 55342 f.finish(); 55343 } 55344 }); // Add other features 55345 55346 const others = features.filter(f => !consumedFeatures.has(f)); 55347 55348 for (let f of others) { 55349 combinedFeatures.push(f); 55350 } 55351 55352 return combinedFeatures; 55353 55354 function getParents(f) { 55355 if (f.parent && f.parent.trim() !== "") { 55356 return f.parent.trim().split(","); 55357 } else { 55358 return null; 55359 } 55360 } 55361 } 55362 55363 numberExons(features, genomicInterval) { 55364 for (let f of features) { 55365 if (f.exons && (!genomicInterval || f.end <= genomicInterval.end && f.start > genomicInterval.start)) { 55366 for (let i = 0; i < f.exons.length; i++) { 55367 const exon = f.exons[i]; 55368 exon.number = f.strand === "-" ? f.exons.length - i : i + 1; 55369 } 55370 } 55371 } 55372 } 55373 55374 nameFeatures(features) { 55375 // Find name (label) property 55376 for (let f of features) { 55377 if (f.attributeString) { 55378 const delim = 'gff3' === this.format ? '=' : ' '; 55379 const attributes = parseAttributeString(f.attributeString, delim); 55380 const attributesMap = new Map(attributes); 55381 55382 if (this.nameField) { 55383 f.name = attributesMap.get(this.nameField); 55384 } else { 55385 for (let nameField of gffNameFields) { 55386 if (attributesMap.has(nameField)) { 55387 f.name = attributesMap.get(nameField); 55388 break; 55389 } 55390 } 55391 } 55392 } 55393 } 55394 } 55395 55396 } 55397 55398 /* 55399 * The MIT License (MIT) 55400 * 55401 * Copyright (c) 2015 UC San Diego 55402 * 55403 * Permission is hereby granted, free of charge, to any person obtaining a copy 55404 * of this software and associated documentation files (the "Software"), to deal 55405 * in the Software without restriction, including without limitation the rights 55406 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 55407 * copies of the Software, and to permit persons to whom the Software is 55408 * furnished to do so, subject to the following conditions: 55409 * 55410 * The above copyright notice and this permission notice shall be included in 55411 * all copies or substantial portions of the Software. 55412 * 55413 * 55414 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 55415 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 55416 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 55417 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 55418 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 55419 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 55420 * THE SOFTWARE. 55421 */ 55422 55423 const GtexReader = function (config) { 55424 this.config = config; 55425 this.url = config.url; 55426 this.tissueId = config.tissueSiteDetailId; 55427 this.indexed = true; 55428 this.datasetId = config.datasetId || "gtex_v8"; 55429 }; 55430 55431 GtexReader.prototype.readFeatures = async function (chr, bpStart, bpEnd) { 55432 let self = this, 55433 queryChr = chr.startsWith("chr") ? chr : "chr" + chr, 55434 queryStart = Math.floor(bpStart), 55435 queryEnd = Math.ceil(bpEnd), 55436 datasetId = this.datasetId, 55437 queryURL = this.url + "?chromosome=" + queryChr + "&start=" + queryStart + "&end=" + queryEnd + "&tissueSiteDetailId=" + this.tissueId + "&datasetId=" + datasetId; 55438 const json = await igvxhr.loadJson(queryURL, { 55439 withCredentials: self.config.withCredentials 55440 }); 55441 55442 if (json && json.singleTissueEqtl) { 55443 //variants = json.variants; 55444 //variants.sort(function (a, b) { 55445 // return a.POS - b.POS; 55446 //}); 55447 //source.cache = new FeatureCache(chr, queryStart, queryEnd, variants); 55448 json.singleTissueEqtl.forEach(function (eqtl) { 55449 eqtl.chr = eqtl.chromosome; 55450 eqtl.position = eqtl.pos; 55451 eqtl.start = eqtl.pos - 1; 55452 eqtl.end = eqtl.start + 1; 55453 eqtl.snp = eqtl.snpId; 55454 eqtl.geneName = eqtl.geneSymbol; 55455 eqtl.geneId = eqtl.gencodeId; 55456 }); 55457 return json.singleTissueEqtl; 55458 } else { 55459 return undefined; 55460 } 55461 }; 55462 55463 /* 55464 * The MIT License (MIT) 55465 * 55466 * Copyright (c) 2014 Broad Institute 55467 * 55468 * Permission is hereby granted, free of charge, to any person obtaining a copy 55469 * of this software and associated documentation files (the "Software"), to deal 55470 * in the Software without restriction, including without limitation the rights 55471 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 55472 * copies of the Software, and to permit persons to whom the Software is 55473 * furnished to do so, subject to the following conditions: 55474 * 55475 * The above copyright notice and this permission notice shall be included in 55476 * all copies or substantial portions of the Software. 55477 * 55478 * 55479 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 55480 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 55481 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 55482 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 55483 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 55484 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 55485 * THE SOFTWARE. 55486 */ 55487 // http://immvar.broadinstitute.org:3000/load_data?chromosome=&start=&end=&categories= 55488 55489 const ImmVarReader = function (config) { 55490 this.config = config; 55491 this.url = config.url; 55492 this.cellConditionId = config.cellConditionId; 55493 this.valueThreshold = config.valueThreshold ? config.valueThreshold : 5E-2; 55494 }; 55495 55496 ImmVarReader.prototype.readFeatures = function (queryChr, queryStart, queryEnd) { 55497 var self = this, 55498 queryURL = this.url + "?chromosome=" + queryChr + "&start=" + queryStart + "&end=" + queryEnd + "&cell_condition_id=" + this.cellConditionId; 55499 return new Promise(function (fulfill, reject) { 55500 igvxhr.loadJson(queryURL, { 55501 withCredentials: self.config.withCredentials 55502 }).then(function (json) { 55503 if (json) { 55504 //variants = json.variants; 55505 //variants.sort(function (a, b) { 55506 // return a.POS - b.POS; 55507 //}); 55508 //source.cache = new FeatureCache(chr, queryStart, queryEnd, variants);
55509 json.eqtls.forEach(function (eqtl) { 55510 eqtl.chr = eqtl.chromosome; 55511 eqtl.start = eqtl.position; 55512 eqtl.end = eqtl.position + 1; 55513 }); 55514 fulfill(json.eqtls); 55515 } else { 55516 fulfill(null); 55517 } 55518 }).catch(function (error) { 55519 reject(error); 55520 }); 55521 }); 55522 }; 55523 55524 /* 55525 * The MIT License (MIT) 55526 * 55527 * Copyright (c) 2014 Broad Institute 55528 * 55529 * Permission is hereby granted, free of charge, to any person obtaining a copy 55530 * of this software and associated documentation files (the "Software"), to deal 55531 * in the Software without restriction, including without limitation the rights 55532 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 55533 * copies of the Software, and to permit persons to whom the Software is 55534 * furnished to do so, subject to the following conditions: 55535 * 55536 * The above copyright notice and this permission notice shall be included in 55537 * all copies or substantial portions of the Software. 55538 * 55539 * 55540 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 55541 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 55542 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 55543 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 55544 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 55545 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 55546 * THE SOFTWARE. 55547 */ 55548 55549 const Ga4ghVariantReader = function (config, genome) { 55550 this.config = config; 55551 this.genome = genome; 55552 this.url = config.url; 55553 this.variantSetId = config.variantSetId; 55554 this.callSetIds = config.callSetIds; 55555 this.includeCalls = config.includeCalls === undefined ? true : config.includeCalls; 55556 }; // Simulate a VCF file header 55557 55558 55559 Ga4ghVariantReader.prototype.readHeader = function () { 55560 var self = this; 55561 55562 if (self.header) { 55563 return Promise.resolve(self.header); 55564 } else { 55565 self.header = {}; 55566 55567 if (self.includeCalls === false) { 55568 return Promise.resolve(self.header); 55569 } else { 55570 var readURL = self.url + "/callsets/search"; 55571 return ga4ghSearch({ 55572 url: readURL, 55573 fields: "nextPageToken,callSets(id,name)", 55574 body: { 55575 "variantSetIds": Array.isArray(self.variantSetId) ? self.variantSetId : [self.variantSetId], 55576 "pageSize": "10000" 55577 }, 55578 decode: function (json) { 55579 // If specific callSetIds are specified filter to those 55580 if (self.callSetIds) { 55581 var callSets = [], 55582 csIdSet = new Set(); 55583 self.callSetIds.forEach(function (csid) { 55584 csIdSet.add(csid); 55585 }); 55586 json.callSets.forEach(function (cs) { 55587 if (csIdSet.has(cs.id)) { 55588 callSets.push(cs); 55589 } 55590 }); 55591 return callSets; 55592 } else { 55593 return json.callSets; 55594 } 55595 } 55596 }).then(function (callSets) { 55597 self.header.callSets = callSets; 55598 return self.header; 55599 }); 55600 } 55601 } 55602 }; 55603 55604 Ga4ghVariantReader.prototype.readFeatures = function (chr, bpStart, bpEnd) { 55605 const self = this; 55606 const genome = this.genome; 55607 return self.readHeader().then(function (header) { 55608 return getChrAliasTable(); 55609 }).then(function (chrAliasTable) { 55610 var queryChr = chrAliasTable.hasOwnProperty(chr) ? chrAliasTable[chr] : chr, 55611 readURL = self.url + "/variants/search"; 55612 return ga4ghSearch({ 55613 url: readURL, 55614 fields: self.includeCalls ? undefined : "nextPageToken,variants(id,variantSetId,names,referenceName,start,end,referenceBases,alternateBases,quality,filter,info)", 55615 body: { 55616 "variantSetIds": Array.isArray(self.variantSetId) ? self.variantSetId : [self.variantSetId], 55617 "callSetIds": self.callSetIds ? self.callSetIds : undefined, 55618 "referenceName": queryChr, 55619 "start": bpStart.toString(), 55620 "end": bpEnd.toString(), 55621 "pageSize": "10000" 55622 }, 55623 decode: function (json) { 55624 var v; 55625 var variants = [];
55626 json.variants.forEach(function (json) { 55627 v = createGAVariant(json); 55628 55629 if (!v.isRefBlock()) { 55630 variants.push(v); 55631 } 55632 }); 55633 return variants; 55634 } 55635 }); 55636 }); 55637 55638 function getChrAliasTable() { 55639 return new Promise(function (fulfill, reject) { 55640 if (self.chrAliasTable) { 55641 fulfill(self.chrAliasTable); 55642 } else { 55643 self.readMetadata().then(function (json) { 55644 self.metadata = json.metadata; 55645 self.chrAliasTable = {}; 55646 55647 if (json.referenceBounds && genome) { 55648 json.referenceBounds.forEach(function (rb) { 55649 var refName = rb.referenceName, 55650 alias = genome.getChromosomeName(refName); 55651 self.chrAliasTable[alias] = refName; 55652 }); 55653 } 55654 55655 fulfill(self.chrAliasTable); 55656 }); 55657 } 55658 }); 55659 } 55660 }; 55661 55662 Ga4ghVariantReader.prototype.readMetadata = function () { 55663 return ga4ghGet({ 55664 url: this.url, 55665 entity: "variantsets", 55666 entityId: this.variantSetId 55667 }); 55668 }; 55669 55670 class CivicReader { 55671 constructor(config) { 55672 this.config = config; 55673 } 55674 55675 async readFeatures(chr, start, end) { 55676 const json = await igvxhr.loadJson(this.config.url + "/variants/?count=50000"); 55677 const records = json.records; 55678 const features = []; 55679 55680 for (let record of records) { 55681 if (record.coordinates) { 55682 record.id; 55683 const coordinates = record.coordinates; 55684 55685 if (coordinates.chromosome) { 55686 features.push(new CivicVariant(coordinates.chromosome, coordinates.start - 1, // UCSC 0 convention 55687 coordinates.stop, record)); 55688 } 55689 55690 if (coordinates.chromosome2) { 55691 features.push(new CivicVariant(coordinates.chromosome2, coordinates.start2 - 1, // UCSC 0 convention 55692 coordinates.stop2, record)); 55693 } 55694 } 55695 } 55696 55697 return features; 55698 } 55699 55700 } 55701 55702 class CivicVariant { 55703 constructor(chr, start, end, record) { 55704 this.chr = chr; 55705 this.start = start; 55706 this.end = end; 55707 this.id = record.id; 55708 this.entrezName = record.entrez_name; 55709 this.name = record.name; 55710 this.actionabilityScore = record.civic_actionability_score; 55711 55712 if (record.coordinates.reference_bases) { 55713 this.refBases = record.coordinates.reference_bases; 55714 } 55715 55716 if (record.coordinates.variant_bases) { 55717 this.altBases = record.coordinates.variant_bases; 55718 } 55719 55720 if (record.variant_types) { 55721 this.variant_types = record.variant_types; 55722 } 55723 55724 this.locationString = this.chr + ":" + numberFormatter$1(this.start + 1) + "-" + numberFormatter$1(this.end); // Color based on actionability score 55725 55726 if (this.actionabilityScore !== undefined) { 55727 let alpha; 55728 55729 if (this.actionabilityScore <= 10) { 55730 alpha = 0.2; 55731 } else { 55732 const v = Math.min(30, this.actionabilityScore); 55733 alpha = 0.2 + 0.8 * Math.log10((v - 10) / 2); 55734 } 55735 55736 this.alpha = alpha; 55737 } 55738 } 55739 55740 popupData() { 55741 const link = createLink("CIViC", "https://civicdb.org/links/variants/" + this.id); 55742 this.refBases !== this.altBases && this.refBases && this.refBases.length === 1 && this.altBases && this.altBases.length === 1; 55743 const pd = [link]; 55744 pd.push({ 55745 name: "Entrez", 55746 value: createLink(this.entrezName, "https://ghr.nlm.nih.gov/gene/" + this.entrezName) 55747 }); 55748 pd.push({ 55749 name: "Name", 55750 value: this.name 55751 }); 55752 55753 if (this.variant_types && this.variant_types.length > 0) { 55754 const name = this.variant_types.length === 1 ? "Type" : "Types"; 55755 let typeString; 55756 55757 for (let vt of this.variant_types) { 55758 if (!typeString) typeString = vt.display_name;else typeString += ", " + vt.display_name; 55759 } 55760 55761 pd.push({ 55762 name: name, 55763 value: typeString 55764 }); 55765 } 55766 55767 pd.push({ 55768 name: "Actionability", 55769 value: this.actionabilityScore 55770 }); 55771 pd.push({ 55772 name: "Location", 55773 value: this.locationString 55774 }); 55775 return pd; 55776 55777 function createLink(text, href) { 55778 return "<a target='_blank' " + "href='" + href + "'>
55778" + text + "</a>"; 55779 } 55780 } 55781 55782 } 55783 55784 // Assigns a row # to each feature. If the feature does not fit in any row and #rows == maxRows no 55785 // row number is assigned. 55786 function pack(featureList, maxRows) { 55787 maxRows = maxRows || Number.MAX_SAFE_INTEGER; 55788 const rows = []; 55789 featureList.sort(function (a, b) { 55790 return a.start - b.start; 55791 }); 55792 rows.push(-1000); 55793 55794 for (let feature of featureList) { 55795 let r = 0; 55796 const len = Math.min(rows.length, maxRows); 55797 55798 for (r = 0; r < len; r++) { 55799 if (feature.start > rows[r]) { 55800 feature.row = r; 55801 rows[r] = feature.end; 55802 break; 55803 } 55804 } 55805 55806 feature.row = r; 55807 rows[r] = feature.end; 55808 } 55809 } 55810 55811 /* 55812 * The MIT License (MIT) 55813 * 55814 * Copyright (c) 2016-2017 The Regents of the University of California 55815 * Author: Jim Robinson 55816 * 55817 * Permission is hereby granted, free of charge, to any person obtaining a copy 55818 * of this software and associated documentation files (the "Software"), to deal 55819 * in the Software without restriction, including without limitation the rights 55820 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 55821 * copies of the Software, and to permit persons to whom the Software is 55822 * furnished to do so, subject to the following conditions: 55823 * 55824 * The above copyright notice and this permission notice shall be included in 55825 * all copies or substantial portions of the Software. 55826 * 55827 * 55828 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 55829 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 55830 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 55831 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 55832 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 55833 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 55834 * THE SOFTWARE. 55835 */ 55836 55837 class HtsgetVariantReader extends HtsgetReader { 55838 constructor(config, genome) { 55839 super(config, genome); 55840 this.parser = new VcfParser(); 55841 } 55842 55843 async readHeader() { 55844 if (!this.header) { 55845 const data = await this.readHeaderData(); 55846 const dataWrapper = getDataWrapper(data); 55847 this.header = await this.parser.parseHeader(dataWrapper, this.genome); 55848 this.chrAliasTable = this.header.chrAliasTable; 55849 } 55850 55851 return this.header; 55852 } 55853 55854 async readFeatures(chr, start, end) { 55855 if (this.config.format && this.config.format.toUpperCase() !== "VCF") { 55856 throw Error(`htsget format ${this.config.format} is not supported`); 55857 } 55858 55859 if (!this.chrAliasTable) { 55860 await this.readHeader(); 55861 } 55862 55863 let queryChr = this.chrAliasTable.has(chr) ? this.chrAliasTable.get(chr) : chr; 55864 const data = await this.readData(queryChr, start, end); 55865 const dataWrapper = getDataWrapper(data); 55866 return this.parser.parseFeatures(dataWrapper); // return dataWrapper; 55867 } 55868 55869 } 55870 55871 /* 55872 * The MIT License (MIT) 55873 * 55874 * Copyright (c) 2014-2015 Broad Institute 55875 * 55876 * Permission is hereby granted, free of charge, to any person obtaining a copy 55877 * of this software and associated documentation files (the "Software"), to deal 55878 * in the Software without restriction, including without limitation the rights 55879 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 55880 * copies of the Software, and to permit persons to whom the Software is 55881 * furnished to do so, subject to the following conditions: 55882 * 55883 * The above copyright notice and this permission notice shall be included in 55884 * all copies or substantial portions of the Software. 55885 * 55886 * 55887 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 55888 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 55889 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 55890 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 55891 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 55892 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 55893 * THE SOFTWARE. 55894 */ 55895 /** 55896 * feature source for "bed like" files (tab or whitespace delimited files with 1 feature per line: bed, gff, vcf, etc) 55897 * 55898 * @param config 55899 * @constructor 55900 */ 55901 55902 class TextFeatureSource { 55903 constructor(config, genome) { 55904 this.config = config || {}; 55905 this.genome = genome; 55906 this.sourceType = config.sourceType === undefined ? "file" : config.sourceType; 55907 const queryableFormats = new Set(["bigwig", "bw", "bigbed", "bb", "tdf"]); 55908 55909 if (config.features && Array.isArray(config.features)) { 55910 // Explicit array of features 55911 let features = fixFeatures(config.features, genome); 55912 packFeatures(features); 55913 55914 if (config.mappings) { 55915 mapProperties(features, config.mappings); 55916 } 55917 55918 this.queryable = false;
55919 this.featureCache = new FeatureCache(features, genome); 55920 } else if (config.reader) { 55921 // Explicit reader implementation 55922 this.reader = config.reader; 55923 this.queryable = config.queryable !== false; 55924 } else if (config.sourceType === "ga4gh") { 55925 this.reader = new Ga4ghVariantReader(config, genome); 55926 this.queryable = true; 55927 } else if (config.sourceType === "immvar") { 55928 this.reader = new ImmVarReader(config); 55929 this.queryable = true; 55930 } else if (config.type === "eqtl" && config.sourceType === "gtex-ws") { 55931 this.reader = new GtexReader(config); 55932 this.queryable = true; 55933 } else if ("htsget" === config.sourceType) { 55934 this.reader = new HtsgetVariantReader(config, genome); 55935 } else if (config.sourceType === 'ucscservice') { 55936 this.reader = new UCSCServiceReader(config.source); 55937 this.queryable = true; 55938 } else if (config.sourceType === 'custom') { 55939 this.reader = new CustomServiceReader(config.source); 55940 this.queryable = false !== config.source.queryable; 55941 } else if ("civic-ws" === config.sourceType) { 55942 this.reader = new CivicReader(config); 55943 this.queryable = false; 55944 } else { 55945 // File of some type (i.e. not a webservice) 55946 this.reader = new FeatureFileReader(config, genome); 55947 55948 if (config.queryable !== undefined) { 55949 this.queryable = config.queryable; 55950 } else if (queryableFormats.has(config.format) || this.reader.indexed) { 55951 this.queryable = true; 55952 } else ; 55953 } 55954 } 55955 55956 async defaultVisibilityWindow() { 55957 if (this.reader && typeof this.reader.defaultVisibilityWindow === 'function') { 55958 return this.reader.defaultVisibilityWindow(); 55959 } 55960 } 55961 55962 async trackType() { 55963 const header = await this.getHeader(); 55964 55965 if (header) { 55966 return header.type; 55967 } else { 55968 return undefined; // Convention for unknown or unspecified 55969 } 55970 } 55971 55972 async getHeader() { 55973 if (!this.header) { 55974 if (this.reader && typeof this.reader.readHeader === "function") { 55975 const header = await this.reader.readHeader(); 55976 55977 if (header) { 55978 this.header = header; 55979 55980 if (header.format) { 55981 this.config.format = header.format; 55982 } 55983 } else { 55984 this.header = {}; 55985 } 55986 } else { 55987 this.header = {}; 55988 } 55989 } 55990 55991 return this.header; 55992 } 55993 /** 55994 * Required function for all data source objects. Fetches features for the 55995 * range requested. 55996 * 55997 * This function is quite complex due to the variety of reader types backing it, some indexed, some queryable, 55998 * some not. The whole scheme could use a refactoring. 55999 * 56000 * @param chr 56001 * @param start 56002 * @param end 56003 * @param bpPerPixel 56004 */ 56005 56006 56007 async getFeatures(_ref) { 56008 let { 56009 chr, 56010 start, 56011 end, 56012 bpPerPixel, 56013 visibilityWindow 56014 } = _ref; 56015 const genome = this.genome; 56016 const queryChr = genome ? genome.getChromosomeName(chr) : chr; 56017 const isWholeGenome = "all" === queryChr.toLowerCase(); // Various conditions that can create a feature load 56018 // * view is "whole genome" but no features are loaded 56019 // * cache is disabled 56020 // * cache does not contain requested range 56021 56022 if (isWholeGenome && !this.getWGFeatures || this.config.disableCache || !this.featureCache || !this.featureCache.containsRange(new GenomicInterval(queryChr, start, end))) { 56023 await this.loadFeatures(queryChr, start, end, visibilityWindow); 56024 } 56025 56026 if (isWholeGenome) { 56027 if (!this.wgFeatures) { 56028 if (this.queryable) { 56029 // queryable sources don't support whole genome view 56030 this.wgFeatures = []; 56031 } else { 56032 this.wgFeatures = this.getWGFeatures(this.featureCache.getAllFeatures()); 56033 } 56034 } 56035 56036 return this.wgFeatures; 56037 } else { 56038 return this.featureCache.queryFeatures(queryChr, start, end); 56039 } 56040 } // TODO -- experimental, will only work for non-indexed sources 56041 56042 56043 getAllFeatures() { 56044 if (this.queryable) { 56045 // queryable sources don't support all features 56046 return []; 56047 } else { 56048 return this.getWGFeatures(this.featureCache.getAllFeatures()); 56049 } 56050 } 56051 56052 async loadFeatures(queryChr, start, end, visibilityWindow) { 56053 const reader = this.reader; 56054 let intervalStart = start; 56055 let intervalEnd = end; // Use visibility window to potentially expand query interval. 56056 // This can save re-queries as we zoom out. Visibility window <= 0 is a special case 56057 // indicating whole chromosome should be read at once. 56058 56059 if ((!visibilityWindow || visibilityWindow <= 0) && this.config.expandQuery !== false) { 56060 // Whole chromosome 56061 const chromosome = this.genome ? this.genome.getChromosome(queryChr) : undefined; 56062 intervalStart = 0; 56063 intervalEnd = Math.max(chromosome ? chromosome.bpLength : Number.MAX_SAFE_INTEGER, end); 56064 } else if (visibilityWindow > end - start && this.config.expandQuery !== false) { 56065 const expansionWindow = Math.min(4.1 * (end - start), visibilityWindow); 56066 intervalStart = Math.max(0, (start + end) / 2 - expansionWindow); 56067 intervalEnd = start + expansionWindow; 56068 } 56069 56070 let features = await reader.readFeatures(queryChr, intervalStart, intervalEnd); 56071 56072 if (this.queryable === undefined) { 56073 this.queryable = reader.indexed; 56074 } 56075 56076 const genomicInterval = this.queryable ? new GenomicInterval(queryChr, intervalStart, intervalEnd) : undefined; 56077 56078 if (features) { 56079 if (this.config.assembleGFF !== false && ("gtf" === this.config.format || "gff3" === this.config.format || "gff" === this.config.format)) { 56080 features = new GFFHelper(this.config).combineFeatures(features, genomicInterval); 56081 } // Assign overlapping features to rows 56082 56083 56084 if (this.config.format !== "wig" && this.config.type !== "junctions") { 56085 const maxRows = this.config.maxRows || Number.MAX_SAFE_INTEGER; 56086 packFeatures(features, maxRows); 56087 } // Note - replacing previous cache with new one. genomicInterval is optional (might be undefined => includes all features) 56088 56089 56090 this.featureCache = new FeatureCache(features, this.genome, genomicInterval); // If track is marked "searchable"< cache features by name -- use this with caution, memory intensive 56091 56092 if (this.config.searchable || this.config.searchableFields) { 56093 this.addFeaturesToDB(features); 56094 } 56095 } else { 56096 this.featureCache = new FeatureCache([], genomicInterval); // Empty cache 56097 } 56098 } 56099 56100 addFeaturesToDB(featureList) { 56101 for (let feature of featureList) { 56102 if (feature.name) { 56103 this.genome.featureDB[feature.name.toUpperCase()] = feature; 56104 } 56105 56106 if (feature.gene && feature.gene.name) { 56107 this.genome.featureDB[feature.gene.name.toUpperCase()] = feature; 56108 } 56109 56110 if (this.config.searchableFields) { 56111 for (let f of this.config.searchableFields) { 56112 const value = feature.getAttributeValue(f); 56113 56114 if (value) { 56115 if (value.indexOf(" ") > 0) { 56116 this.genome.featureDB[value.replaceAll(" ", "+").toUpperCase()] = feature; 56117 this.genome.featureDB[value.replaceAll(" ", "%20").toUpperCase()] = feature; 56118 } else { 56119 this.genome.featureDB[value.toUpperCase()] = feature; 56120 } 56121 } 56122 } 56123 } 56124 } 56125 } // TODO -- filter by pixel size 56126 56127 56128 getWGFeatures(allFeatures) { 56129 const genome = this.genome; 56130 const wgChromosomeNames = new Set(genome.wgChromosomeNames); 56131 const wgFeatures = []; 56132 56133 for (let c of genome.wgChromosomeNames) { 56134 const features = allFeatures[c]; 56135 56136 if (features) { 56137 for (let f of features) { 56138 let queryChr = genome.getChromosomeName(f.chr); 56139 56140 if (wgChromosomeNames.has(queryChr)) { 56141 const wg = Object.assign({}, f); 56142 wg.chr = "all"; 56143 wg.start = genome.getGenomeCoordinate(f.chr, f.start); 56144 wg.end = genome.getGenomeCoordinate(f.chr, f.end); 56145 wg._f = f; // Don't draw exons in whole genome view 56146 56147 if (wg["exons"]) delete wg["exons"]; 56148 wgFeatures.push(wg); 56149 } 56150 } 56151 } 56152 } 56153 56154 wgFeatures.sort(function (a, b) { 56155 return a.start - b.start; 56156 }); 56157 return wgFeatures; 56158 } 56159 56160 } 56161 56162 function packFeatures(features, maxRows) { 56163 maxRows = maxRows || 1000; 56164 56165 if (features == null || features.length === 0) { 56166 return; 56167 } // Segregate by chromosome 56168 56169 56170 const chrFeatureMap = {}; 56171 const chrs = []; 56172 56173 for (let feature of features) { 56174 const chr = feature.chr; 56175 let flist = chrFeatureMap[chr]; 56176 56177 if (!flist) { 56178 flist = []; 56179 chrFeatureMap[chr] = flist; 56180 chrs.push(chr); 56181 } 56182 56183 flist.push(feature); 56184 }
56184 // Loop through chrosomosomes and pack features; 56185 56186 56187 for (let chr of chrs) { 56188 pack(chrFeatureMap[chr], maxRows); 56189 } 56190 } 56191 /** 56192 * This function is used to apply properties normally added during parsing to features supplied directly in the 56193 * config as an array of objects. At the moment the only application is bedpe type features. 56194 * @param features 56195 */ 56196 56197 56198 function fixFeatures(features, genome) { 56199 if (!features || features.length === 0) return []; 56200 const isBedPE = features[0].chr === undefined && features[0].chr1 !== undefined; 56201 56202 if (isBedPE) { 56203 const interChrFeatures = []; 56204 56205 for (let feature of features) { 56206 if (genome) { 56207 feature.chr1 = genome.getChromosomeName(feature.chr1); 56208 feature.chr2 = genome.getChromosomeName(feature.chr2); 56209 } // Set total extent of feature 56210 56211 56212 if (feature.chr1 === feature.chr2) { 56213 feature.chr = feature.chr1; 56214 feature.start = Math.min(feature.start1, feature.start2); 56215 feature.end = Math.max(feature.end1, feature.end2); 56216 } else { 56217 interChrFeatures.push(feature); 56218 } 56219 } // Make copies of inter-chr features, one for each chromosome 56220 56221 56222 for (let f1 of interChrFeatures) { 56223 const f2 = Object.assign({ 56224 dup: true 56225 }, f1); 56226 features.push(f2); 56227 f1.chr = f1.chr1; 56228 f1.start = f1.start1; 56229 f1.end = f1.end1; 56230 f2.chr = f2.chr2; 56231 f2.start = f2.start2; 56232 f2.end = f2.end2; 56233 } 56234 } else if (genome) { 56235 for (let feature of features) { 56236 feature.chr = genome.getChromosomeName(feature.chr); 56237 } 56238 } 56239 56240 return features; 56241 } 56242 56243 function mapProperties(features, mappings) { 56244 let mappingKeys = Object.keys(mappings); 56245 features.forEach(function (f) { 56246 mappingKeys.forEach(function (key) { 56247 f[key] = f[mappings[key]]; 56248 }); 56249 }); 56250 } 56251 56252 class BufferedReader { 56253 constructor(config, contentLength, bufferSize) { 56254 this.path = config.url; 56255 this.bufferSize = bufferSize ? bufferSize : 512000; 56256 this.range = { 56257 start: -1, 56258 size: -1 56259 }; 56260 this.config = config; 56261 } 56262 /** 56263 * 56264 * @param requestedRange - byte rangeas {start, size} 56265 * @param fulfill - function to receive result 56266 * @param asUint8 - optional flag to return result as an UInt8Array 56267 */ 56268 56269 56270 async dataViewForRange(requestedRange, asUint8) { 56271 const hasData = this.data && this.range.start <= requestedRange.start && this.range.start + this.range.size >= requestedRange.start + requestedRange.size; 56272 56273 if (!hasData) { 56274 let bufferSize; // If requested range size is specified, potentially expand buffer size 56275 56276 if (requestedRange.size) { 56277 bufferSize = Math.max(this.bufferSize, requestedRange.size); 56278 } else { 56279 bufferSize = this.bufferSize; 56280 } 56281 56282 const loadRange = { 56283 start: requestedRange.start, 56284 size: bufferSize 56285 }; 56286 const arrayBuffer = await igvxhr.loadArrayBuffer(this.path, buildOptions(this.config, { 56287 range: loadRange 56288 })); 56289 this.data = arrayBuffer; 56290 this.range = loadRange; 56291 } 56292 56293 const len = this.data.byteLength; 56294 const bufferStart = requestedRange.start - this.range.start; 56295 return asUint8 ? new Uint8Array(this.data, bufferStart, len - bufferStart) : new DataView(this.data, bufferStart, len - bufferStart); 56296 } 56297 56298 } 56299 56300 //table chromatinInteract 56301 56302 function getDecoder(definedFieldCount, fieldCount, autoSql) { 56303 if (autoSql && 'chromatinInteract' === autoSql.table) { 56304 return decodeInteract; 56305 } else { 56306 const standardFieldCount = definedFieldCount - 3; 56307 return function (feature, tokens) { 56308 if (standardFieldCount > 0) { 56309 feature.name = tokens[0]; 56310 } 56311 56312 if (standardFieldCount > 1) { 56313 feature.score = Number(tokens[1]); 56314 } 56315 56316 if (standardFieldCount > 2) { 56317 feature.strand = tokens[2]; 56318 } 56319 56320 if (standardFieldCount > 3) { 56321 feature.cdStart = parseInt(tokens[3]); 56322 } 56323 56324 if (standardFieldCount > 4) { 56325 feature.cdEnd = parseInt(tokens[4]); 56326 } 56327 56328 if (standardFieldCount > 5) { 56329 if (tokens[5] !== "." && tokens[5] !== "0" && tokens[5] !== "-1") { 56330 const c = IGVColor.createColorString(tokens[5]); 56331 feature.color = c.startsWith("rgb") ? c : undefined; 56332 } 56333 } 56334 56335 if (standardFieldCount > 8) { 56336 const exonCount = parseInt(tokens[6]); 56337 const exonSizes = tokens[7].split(','); 56338 const exonStarts = tokens[8].split(','); 56339 const exons = []; 56340 56341 for (let i = 0; i < exonCount; i++) { 56342 const eStart = feature.start + parseInt(exonStarts[i]); 56343 const eEnd = eStart + parseInt(exonSizes[i]); 56344 exons.push({ 56345 start: eStart, 56346 end: eEnd 56347 }); 56348 } 56349 56350 feature.exons = exons; 56351 } 56352 56353 if (autoSql) { 56354 // TODO -- these should be equal, validate? fieldCount-definedFieldCount, as.fields.length, tokens.length-3 56355 const extraStart = definedFieldCount; 56356 56357 for (let i = extraStart; i < fieldCount; i++) { 56358 if (i < autoSql.fields.length) { 56359 const name = autoSql.fields[i].name; 56360 const value = tokens[i - 3]; 56361 feature[name] = value; 56362 } 56363 } 56364 } 56365 }; 56366 } 56367 56368 function decodeInteract(feature, tokens) { 56369 feature.chr1 = tokens[5]; 56370 feature.start1 = Number.parseInt(tokens[6]); 56371 feature.end1 = Number.parseInt(tokens[7]); 56372 feature.chr2 = tokens[10]; 56373 feature.start2 = Number.parseInt(tokens[11]); 56374 feature.end2 = Number.parseInt(tokens[12]); 56375 feature.name = tokens[0]; 56376 feature.score = Number(tokens[1]); 56377 feature.value = Number(tokens[2]); 56378 feature.color = tokens[4] === '.' ? undefined : tokens[4] === "0" ? "rgb(0,0,0)" : tokens[4]; 56379 return feature; 56380 } 56381 } 56382 56383 function scoreShade(score, color) {
56384 const alpha = Math.min(1, 0.11 + 0.89 * (score / 779)); 56385 return alpha.toString(); 56386 } 56387 56388 function parseAutoSQL(str) { 56389 let table; 56390 const fields = []; 56391 let startDecoding = false; 56392 const lines = str.trim().split(/\s*[\r\n]+\s*/g); 56393 56394 for (let line of lines) { 56395 if (line.startsWith('table')) { 56396 table = line.split(/\s+/)[1].trim(); 56397 } else if (line.startsWith('(')) { 56398 startDecoding = true; 56399 } else if (line.startsWith(')')) ; else if (startDecoding) { 56400 if (line.length > 0) { 56401 const idx = line.indexOf(';'); 56402 const tokens = line.substr(0, idx).split(/\s+/); 56403 const description = line.substr(idx + 1).replace(/"/g, '').trim(); 56404 fields.push({ 56405 type: tokens[0], 56406 name: tokens[1], 56407 description: description 56408 }); 56409 } 56410 } 56411 } 56412 56413 return { 56414 table: table, 56415 fields: fields 56416 }; 56417 } 56418 56419 let BIGWIG_MAGIC_LTH = 0x888FFC26; // BigWig Magic Low to High 56420 56421 let BIGWIG_MAGIC_HTL = 0x26FC8F66; // BigWig Magic High to Low 56422 56423 let BIGBED_MAGIC_LTH = 0x8789F2EB; // BigBed Magic Low to High 56424 56425 let BIGBED_MAGIC_HTL = 0xEBF28987; // BigBed Magic High to Low 56426 56427 let BBFILE_HEADER_SIZE = 64; 56428 let RPTREE_HEADER_SIZE = 48; 56429 let RPTREE_NODE_LEAF_ITEM_SIZE = 32; // leaf item size 56430 56431 let RPTREE_NODE_CHILD_ITEM_SIZE = 24; // child item size 56432 56433 let BUFFER_SIZE = 512000; // buffer 56434 56435 class BWReader { 56436 constructor(config, genome) { 56437 this.path = config.url; 56438 this.genome = genome; 56439 this.rpTreeCache = {}; 56440 this.config = config; 56441 this.loader = isDataURL(this.path) ? new DataBuffer(this.path) : igvxhr; 56442 } 56443 56444 async readWGFeatures(bpPerPixel, windowFunction) { 56445 await this.loadHeader(); 56446 const chrIdx1 = 0; 56447 const chrIdx2 = this.chromTree.idToChrom.length - 1; 56448 const chr1 = this.chromTree.idToChrom[chrIdx1]; 56449 const chr2 = this.chromTree.idToChrom[chrIdx2]; 56450 return this.readFeatures(chr1, 0, chr2, Number.MAX_VALUE, bpPerPixel, windowFunction); 56451 } 56452 56453 async readFeatures(chr1, bpStart, chr2, bpEnd, bpPerPixel, windowFunction) { 56454 await this.loadHeader(); 56455 const chrIdx1 = this.chromTree.chromToID[chr1]; 56456 const chrIdx2 = this.chromTree.chromToID[chr2]; 56457 56458 if (chrIdx1 === undefined || chrIdx2 === undefined) { 56459 return []; 56460 } 56461 56462 let treeOffset; 56463 let decodeFunction; 56464 56465 if (this.type === "bigwig") { 56466 // Select a biwig "zoom level" appropriate for the current resolution. 56467 const zoomLevelHeaders = await this.getZoomHeaders(); 56468 let zoomLevelHeader = bpPerPixel ? zoomLevelForScale$1(bpPerPixel, zoomLevelHeaders) : undefined; 56469 56470 if (zoomLevelHeader) { 56471 treeOffset = zoomLevelHeader.indexOffset; 56472 decodeFunction = decodeZoomData; 56473 } else { 56474 treeOffset = this.header.fullIndexOffset; 56475 decodeFunction = decodeWigData; 56476 } 56477 } else { 56478 // bigbed, zoom data is not currently used in igv for bed type features 56479 treeOffset = this.header.fullIndexOffset; 56480 decodeFunction = getBedDataDecoder.call(this); 56481 } // Load the R Tree and fine leaf items 56482 56483 56484 const rpTree = await this.loadRPTree(treeOffset); 56485 const leafItems = await rpTree.findLeafItemsOverlapping(chrIdx1, bpStart, chrIdx2, bpEnd); 56486 56487 if (!leafItems || leafItems.length === 0) { 56488 return []; 56489 } else { 56490 // Consolidate leaf items and get all data at once 56491 let start = Number.MAX_VALUE; 56492 let end = 0; 56493 56494 for (let item of leafItems) { 56495 start = Math.min(start, item.dataOffset); 56496 end = Math.max(end, item.dataOffset + item.dataSize); 56497 } 56498 56499 const size = end - start; 56500 const arrayBuffer = await this.loader.loadArrayBuffer(this.config.url, buildOptions(this.config, { 56501 range: { 56502 start: start, 56503 size: size 56504 } 56505 })); // Parse data and return features 56506 56507 const allFeatures = []; 56508 56509 for (let item of leafItems) { 56510 const uint8Array = new Uint8Array(arrayBuffer, item.dataOffset - start, item.dataSize); 56511 let plain; 56512 const isCompressed = this.header.uncompressBuffSize > 0; 56513 56514 if (isCompressed) { 56515 plain = inflate(uint8Array); 56516 } else { 56517 plain = uint8Array; 56518 } 56519 56520 decodeFunction.call(this, new DataView(plain.buffer), chrIdx1, bpStart, chrIdx2, bpEnd, allFeatures, this.chromTree.idToChrom, windowFunction); 56521 } 56522 56523 allFeatures.sort(function (a, b) { 56524 return a.start - b.start; 56525 }); 56526 return allFeatures; 56527 } 56528 } 56529 56530 async getZoomHeaders() { 56531 if (this.zoomLevelHeaders) { 56532 return this.zoomLevelHeaders; 56533 } else { 56534 await this.loadHeader(); 56535 return this.zoomLevelHeaders; 56536 } 56537 } 56538 56539 async loadHeader() { 56540 if (this.header) { 56541 return this.header; 56542 } else { 56543 let data = await this.loader.loadArrayBuffer(this.path, buildOptions(this.config, { 56544 range: { 56545 start: 0, 56546 size: BBFILE_HEADER_SIZE 56547 } 56548 })); 56549 let header; // Assume low-to-high unless proven otherwise 56550 56551 this.littleEndian = true; 56552 let binaryParser = new BinaryParser(new DataView(data)); 56553 let magic = binaryParser.getUInt(); 56554 56555 if (magic === BIGWIG_MAGIC_LTH) { 56556 this.type = "bigwig"; 56557 } else if (magic === BIGBED_MAGIC_LTH) { 56558 this.type = "bigbed"; 56559 } else { 56560 //Try big endian order 56561 this.littleEndian = false;
56562 binaryParser.littleEndian = false; 56563 binaryParser.position = 0; 56564 let magic = binaryParser.getUInt(); 56565 56566 if (magic === BIGWIG_MAGIC_HTL) { 56567 this.type = "bigwig"; 56568 } else if (magic === BIGBED_MAGIC_HTL) { 56569 this.type = "bigbed"; 56570 } else ; 56571 } // Table 5 "Common header for bigwig and bigbed files" 56572 56573 56574 header = { 56575 bwVersion: binaryParser.getUShort(), 56576 nZoomLevels: binaryParser.getUShort(), 56577 chromTreeOffset: binaryParser.getLong(), 56578 fullDataOffset: binaryParser.getLong(), 56579 fullIndexOffset: binaryParser.getLong(), 56580 fieldCount: binaryParser.getUShort(), 56581 definedFieldCount: binaryParser.getUShort(), 56582 autoSqlOffset: binaryParser.getLong(), 56583 totalSummaryOffset: binaryParser.getLong(), 56584 uncompressBuffSize: binaryParser.getInt(), 56585 extensionOffset: binaryParser.getLong() 56586 }; /////////// 56587 56588 const startOffset = BBFILE_HEADER_SIZE; 56589 let range = { 56590 start: startOffset, 56591 size: header.fullDataOffset - startOffset + 5 56592 }; 56593 data = await this.loader.loadArrayBuffer(this.path, buildOptions(this.config, { 56594 range: range 56595 })); 56596 const nZooms = header.nZoomLevels; 56597 binaryParser = new BinaryParser(new DataView(data)); 56598 this.zoomLevelHeaders = []; 56599 this.firstZoomDataOffset = Number.MAX_SAFE_INTEGER; 56600 56601 for (let i = 1; i <= nZooms; i++) { 56602 const zoomNumber = nZooms - i; 56603 const zlh = new ZoomLevelHeader(zoomNumber, binaryParser); 56604 this.firstZoomDataOffset = Math.min(zlh.dataOffset, this.firstZoomDataOffset); 56605 this.zoomLevelHeaders[zoomNumber] = zlh; 56606 } // Autosql 56607 56608 56609 if (header.autoSqlOffset > 0) { 56610 binaryParser.position = header.autoSqlOffset - startOffset; 56611 const autoSqlString = binaryParser.getString(); 56612 56613 if (autoSqlString) { 56614 this.autoSql = parseAutoSQL(autoSqlString); 56615 } 56616 } // Total summary 56617 56618 56619 if (header.totalSummaryOffset > 0) { 56620 binaryParser.position = header.totalSummaryOffset - startOffset; 56621 this.totalSummary = new BWTotalSummary(binaryParser); 56622 } // Chrom data index 56623 56624 56625 if (header.chromTreeOffset > 0) { 56626 binaryParser.position = header.chromTreeOffset - startOffset; 56627 this.chromTree = new BPTree(binaryParser, startOffset, this.genome); 56628 } else { 56629 // TODO -- this is an error, not expected 56630 throw "BigWig chromosome tree offset <= 0"; 56631 } //Finally total data count 56632 56633 56634 binaryParser.position = header.fullDataOffset - startOffset; 56635 header.dataCount = binaryParser.getInt(); /////////// 56636 56637 this.setDefaultVisibilityWindow(header); 56638 this.header = header; 56639 return this.header; 56640 } 56641 } 56642 56643 async loadRPTree(offset) { 56644 let rpTree = this.rpTreeCache[offset]; 56645 56646 if (rpTree) { 56647 return rpTree; 56648 } else { 56649 rpTree = new RPTree(offset, this.config, this.littleEndian, this.loader); 56650 await rpTree.load(); 56651 this.rpTreeCache[offset] = rpTree; 56652 return rpTree; 56653 } 56654 } 56655 56656 async getType() { 56657 await this.loadHeader(); 56658 return this.type; 56659 } 56660 56661 async getTrackType() { 56662 await this.loadHeader(); 56663 56664 if (this.type === "bigwig") { 56665 return "wig"; 56666 } else { 56667 return this.autoSql && this.autoSql.table === "chromatinInteract" ? "interact" : "annotation"; 56668 } 56669 } 56670 56671 setDefaultVisibilityWindow(header) { 56672 if (this.type === "bigwig") { 56673 this.visibilityWindow = -1; 56674 } else { 56675 // bigbed 56676 let genomeSize = this.genome ? this.genome.getGenomeLength() : 3088286401; // Estimate window size to return ~ 1,000 features, assuming even distribution across the genome 56677 56678 this.visibilityWindow = header.dataCount < 1000 ? -1 : 1000 * (genomeSize / header.dataCount); 56679 } 56680 } 56681 56682 } 56683 56684 class ZoomLevelHeader { 56685 constructor(index, byteBuffer) { 56686 this.index = index; 56687 this.reductionLevel = byteBuffer.getInt(); 56688 this.reserved = byteBuffer.getInt(); 56689 this.dataOffset = byteBuffer.getLong(); 56690 this.indexOffset = byteBuffer.getLong(); 56691 } 56692 56693 } 56694 56695 class RPTree { 56696 constructor(fileOffset, config, littleEndian, loader) { 56697 this.config = config; 56698 this.loader = loader;
56699 this.fileOffset = fileOffset; // File offset to beginning of tree 56700 56701 this.path = config.url; 56702 this.littleEndian = littleEndian; 56703 } 56704 56705 async load() { 56706 const rootNodeOffset = this.fileOffset + RPTREE_HEADER_SIZE; 56707 const bufferedReader = isDataURL(this.path) ? this.loader : new BufferedReader(this.config, BUFFER_SIZE); 56708 this.rootNode = await this.readNode(rootNodeOffset, bufferedReader); 56709 return this; 56710 } 56711 56712 async readNode(filePosition, bufferedReader) { 56713 let dataView = await bufferedReader.dataViewForRange({ 56714 start: filePosition, 56715 size: 4 56716 }, false); 56717 let binaryParser = new BinaryParser(dataView, this.littleEndian); 56718 const type = binaryParser.getByte(); 56719 const isLeaf = type === 1; 56720 binaryParser.getByte(); 56721 const count = binaryParser.getUShort(); 56722 filePosition += 4; 56723 let bytesRequired = count * (isLeaf ? RPTREE_NODE_LEAF_ITEM_SIZE : RPTREE_NODE_CHILD_ITEM_SIZE); 56724 let range2 = { 56725 start: filePosition, 56726 size: bytesRequired 56727 }; 56728 dataView = await bufferedReader.dataViewForRange(range2, false); 56729 const items = new Array(count); 56730 binaryParser = new BinaryParser(dataView); 56731 56732 if (isLeaf) { 56733 for (let i = 0; i < count; i++) { 56734 let item = { 56735 isLeaf: true, 56736 startChrom: binaryParser.getInt(), 56737 startBase: binaryParser.getInt(), 56738 endChrom: binaryParser.getInt(), 56739 endBase: binaryParser.getInt(), 56740 dataOffset: binaryParser.getLong(), 56741 dataSize: binaryParser.getLong() 56742 }; 56743 items[i] = item; 56744 } 56745 56746 return new RPTreeNode(items); 56747 } else { 56748 // non-leaf 56749 for (let i = 0; i < count; i++) { 56750 let item = { 56751 isLeaf: false, 56752 startChrom: binaryParser.getInt(), 56753 startBase: binaryParser.getInt(), 56754 endChrom: binaryParser.getInt(), 56755 endBase: binaryParser.getInt(), 56756 childOffset: binaryParser.getLong() 56757 }; 56758 items[i] = item; 56759 } 56760 56761 return new RPTreeNode(items); 56762 } 56763 } 56764 56765 async findLeafItemsOverlapping(chrIdx1, startBase, chrIdx2, endBase) { 56766 let self = this; 56767 return new Promise(function (fulfill, reject) { 56768 let leafItems = [], 56769 processing = new Set(), 56770 bufferedReader = isDataURL(self.path) ? self.loader : new BufferedReader(self.config, BUFFER_SIZE); 56771 processing.add(0); // Zero represents the root node 56772 56773 findLeafItems(self.rootNode, 0); 56774 56775 function findLeafItems(node, nodeId) { 56776 if (overlaps(node, chrIdx1, startBase, chrIdx2, endBase)) { 56777 let items = node.items; 56778 items.forEach(function (item) { 56779 if (overlaps(item, chrIdx1, startBase, chrIdx2, endBase)) { 56780 if (item.isLeaf) { 56781 leafItems.push(item); 56782 } else { 56783 if (item.childNode) { 56784 findLeafItems(item.childNode); 56785 } else { 56786 processing.add(item.childOffset); // Represent node to-be-loaded by its file position 56787 56788 self.readNode(item.childOffset, bufferedReader).then(function (node) { 56789 item.childNode = node; 56790 findLeafItems(node, item.childOffset); 56791 }).catch(reject); 56792 } 56793 } 56794 } 56795 }); 56796 } 56797 56798 if (nodeId !== undefined) processing.delete(nodeId); // Wait until all nodes are processed 56799 56800 if (processing.size === 0) { 56801 fulfill(leafItems); 56802 } 56803 } 56804 }); 56805 } 56806 56807 } 56808 56809 class RPTreeNode { 56810 constructor(items) { 56811 this.items = items; 56812 let minChromId = Number.MAX_SAFE_INTEGER, 56813 maxChromId = 0, 56814 minStartBase = Number.MAX_SAFE_INTEGER, 56815 maxEndBase = 0, 56816 i, 56817 item; 56818 56819 for (i = 0; i < items.length; i++) { 56820 item = items[i]; 56821 minChromId = Math.min(minChromId, item.startChrom);
56822 maxChromId = Math.max(maxChromId, item.endChrom); 56823 minStartBase = Math.min(minStartBase, item.startBase); 56824 maxEndBase = Math.max(maxEndBase, item.endBase); 56825 } 56826 56827 this.startChrom = minChromId; 56828 this.endChrom = maxChromId; 56829 this.startBase = minStartBase; 56830 this.endBase = maxEndBase; 56831 } 56832 56833 } 56834 56835 class BPTree { 56836 constructor(binaryParser, startOffset, genome) { 56837 let magic = binaryParser.getInt(); 56838 let blockSize = binaryParser.getInt(); 56839 let keySize = binaryParser.getInt(); 56840 let valSize = binaryParser.getInt(); 56841 let itemCount = binaryParser.getLong(); 56842 let reserved = binaryParser.getLong(); 56843 let chromToId = {}; 56844 let idToChrom = []; 56845 this.header = { 56846 magic: magic, 56847 blockSize: blockSize, 56848 keySize: keySize, 56849 valSize: valSize, 56850 itemCount: itemCount, 56851 reserved: reserved 56852 }; 56853 this.chromToID = chromToId; 56854 this.idToChrom = idToChrom; // Recursively walk tree to populate dictionary 56855 56856 readTreeNode(binaryParser, -1); 56857 56858 function readTreeNode(byteBuffer, offset) { 56859 if (offset >= 0) byteBuffer.position = offset; 56860 let type = byteBuffer.getByte(); 56861 byteBuffer.getByte(); 56862 let count = byteBuffer.getUShort(), 56863 i, 56864 key, 56865 chromId, 56866 childOffset, 56867 bufferOffset, 56868 currOffset; 56869 56870 if (type === 1) { 56871 for (i = 0; i < count; i++) { 56872 key = byteBuffer.getFixedLengthTrimmedString(keySize); 56873 chromId = byteBuffer.getInt(); 56874 byteBuffer.getInt(); 56875 if (genome) key = genome.getChromosomeName(key); // Translate to canonical chr name 56876 56877 chromToId[key] = chromId; 56878 idToChrom[chromId] = key; 56879 } 56880 } else { 56881 // non-leaf 56882 for (i = 0; i < count; i++) { 56883 key = byteBuffer.getFixedLengthTrimmedString(keySize); 56884 childOffset = byteBuffer.getLong(); 56885 bufferOffset = childOffset - startOffset; 56886 currOffset = byteBuffer.position; 56887 readTreeNode(byteBuffer, bufferOffset); 56888 byteBuffer.position = currOffset; 56889 } 56890 } 56891 } 56892 } 56893 56894 } 56895 /** 56896 * Return true if {chrIdx1:startBase-chrIdx2:endBase} overlaps item's interval 56897 * @returns {boolean} 56898 */ 56899 56900 56901 function overlaps(item, chrIdx1, startBase, chrIdx2, endBase) { 56902 if (!item) { 56903 console.log("null item for " + chrIdx1 + " " + startBase + " " + endBase); 56904 return false; 56905 } 56906 56907 return (chrIdx2 > item.startChrom || chrIdx2 === item.startChrom && endBase >= item.startBase) && (chrIdx1 < item.endChrom || chrIdx1 === item.endChrom && startBase <= item.endBase); 56908 } 56909 56910 class BWTotalSummary { 56911 constructor(byteBuffer) { 56912 if (byteBuffer) { 56913 this.basesCovered = byteBuffer.getLong(); 56914 this.minVal = byteBuffer.getDouble(); 56915 this.maxVal = byteBuffer.getDouble(); 56916 this.sumData = byteBuffer.getDouble(); 56917 this.sumSquares = byteBuffer.getDouble(); 56918 computeStats.call(this); 56919 } else { 56920 this.basesCovered = 0; 56921 this.minVal = 0; 56922 this.maxVal = 0; 56923 this.sumData = 0; 56924 this.sumSquares = 0; 56925 this.mean = 0; 56926 this.stddev = 0; 56927 } 56928 } 56929 56930 } 56931 56932 function computeStats() { 56933 let n = this.basesCovered; 56934 56935 if (n > 0) { 56936 this.mean = this.sumData / n; 56937 this.stddev = Math.sqrt(this.sumSquares / (n - 1)); 56938 let min = this.minVal < 0 ? this.mean - 2 * this.stddev : 0, 56939 max = this.maxVal > 0 ? this.mean + 2 * this.stddev : 0; 56940 this.defaultRange = { 56941 min: min, 56942 max: max 56943 }; 56944 } 56945 } 56946 56947 function zoomLevelForScale$1(bpPerPixel, zoomLevelHeaders) { 56948 let level; 56949 56950 for (let i = 0; i < zoomLevelHeaders.length; i++) { 56951 const zl = zoomLevelHeaders[i]; 56952 56953 if (zl.reductionLevel < bpPerPixel) { 56954 level = zl; 56955 break; 56956 } 56957 } 56958 56959 return level; 56960 } 56961 56962 function decodeWigData(data, chrIdx1, bpStart, chrIdx2, bpEnd, featureArray, chrDict) { 56963 const binaryParser = new BinaryParser(data); 56964 const chromId = binaryParser.getInt(); 56965 let chromStart = binaryParser.getInt(); 56966 let chromEnd = binaryParser.getInt(); 56967 const itemStep = binaryParser.getInt(); 56968 const itemSpan = binaryParser.getInt(); 56969 const type = binaryParser.getByte(); 56970 binaryParser.getByte(); 56971 let itemCount = binaryParser.getUShort(); 56972 56973 if (chromId >= chrIdx1 && chromId <= chrIdx2) { 56974 while (itemCount-- > 0) { 56975 let value; 56976 56977 switch (type) { 56978 case 1: 56979 chromStart = binaryParser.getInt(); 56980 chromEnd = binaryParser.getInt(); 56981 value = binaryParser.getFloat(); 56982 break; 56983 56984 case 2: 56985 chromStart = binaryParser.getInt(); 56986 value = binaryParser.getFloat(); 56987 chromEnd = chromStart + itemSpan; 56988 break; 56989 56990 case 3: 56991 // Fixed step 56992 value = binaryParser.getFloat(); 56993 chromEnd = chromStart + itemSpan; 56994 chromStart += itemStep; 56995 break; 56996 } 56997 56998 if (chromId < chrIdx1 || chromId === chrIdx1 && chromEnd < bpStart) continue;else if (chromId > chrIdx2 || chromId === chrIdx2 && chromStart >= bpEnd) break; 56999 57000 if (Number.isFinite(value)) { 57001 const chr = chrDict[chromId]; 57002 featureArray.push({ 57003 chr: chr, 57004 start: chromStart, 57005 end: chromEnd, 57006 value: value 57007 }); 57008 } 57009 } 57010 } 57011 } 57012 57013 function getBedDataDecoder() { 57014 const minSize = 3 * 4 + 1; // Minimum # of bytes required for a bed record 57015 57016 const decoder = getDecoder(this.header.definedFieldCount, this.header.fieldCount, this.autoSql); 57017 return function (data, chrIdx1, bpStart, chrIdx2, bpEnd, featureArray, chrDict) { 57018 const binaryParser = new BinaryParser(data); 57019 57020 while (binaryParser.remLength() >= minSize) { 57021 const chromId = binaryParser.getInt(); 57022 const chr = chrDict[chromId]; 57023 const chromStart = binaryParser.getInt(); 57024 const chromEnd = binaryParser.getInt(); 57025 const rest = binaryParser.getString(); 57026 if (chromId < chrIdx1 || chromId === chrIdx1 && chromEnd < bpStart) continue;else if (chromId > chrIdx2 || chromId === chrIdx2 && chromStart >= bpEnd) break; 57027 57028 if (chromEnd > 0) { 57029 const feature = { 57030 chr: chr, 57031 start: chromStart, 57032 end: chromEnd 57033 }; 57034 featureArray.push(feature); 57035 const tokens = rest.split("\t"); 57036 decoder(feature, tokens); 57037 } 57038 } 57039 }; 57040 } 57041 57042 function decodeZoomData(data, chrIdx1, bpStart, chrIdx2, bpEnd, featureArray, chrDict, windowFunction) { 57043 const binaryParser = new BinaryParser(data); 57044 const minSize = 8 * 4; // Minimum # of bytes required for a zoom record 57045 57046 while (binaryParser.remLength() >= minSize) { 57047 const chromId = binaryParser.getInt(); 57048 const chr = chrDict[chromId]; 57049 const chromStart = binaryParser.getInt(); 57050 const chromEnd = binaryParser.getInt(); 57051 const validCount = binaryParser.getInt(); 57052 const minVal = binaryParser.getFloat(); 57053 const maxVal = binaryParser.getFloat(); 57054 const sumData = binaryParser.getFloat(); 57055 binaryParser.getFloat(); 57056 let value; 57057 57058 switch (windowFunction) { 57059 case "min": 57060 value = minVal; 57061 break; 57062 57063 case "max": 57064 value = maxVal; 57065 break; 57066 57067 default: 57068 value = validCount === 0 ? 0 : sumData / validCount; 57069 } 57070 57071 if (chromId < chrIdx1 || chromId === chrIdx1 && chromEnd < bpStart) continue;else if (chromId > chrIdx2 || chromId === chrIdx2 && chromStart >= bpEnd) break; 57072 57073 if (Number.isFinite(value)) { 57074 featureArray.push({ 57075 chr: chr, 57076 start: chromStart, 57077 end: chromEnd, 57078 value: value 57079 }); 57080 } 57081 } 57082 } 57083 57084 class DataBuffer { 57085 constructor(dataURI) { 57086 this.data = decodeDataURI$1(dataURI).buffer; 57087 } 57088 /** 57089 * igvxhr interface 57090 * @param ignore 57091 * @param options 57092 * @returns {any} 57093 */ 57094 57095 57096 loadArrayBuffer(ignore, options) { 57097 const range = options.range; 57098 return range ? this.data.slice(range.start, range.start + range.size) : this.data; 57099 } 57100 /** 57101 * BufferedReader interface 57102 * 57103 * @param requestedRange - byte rangeas {start, size} 57104 * @param fulfill - function to receive result 57105 * @param asUint8 - optional flag to return result as an UInt8Array 57106 */ 57107 57108 57109 async dataViewForRange(requestedRange, asUint8) { 57110 const len = Math.min(this.data.byteLength - requestedRange.start, requestedRange.size); 57111 return asUint8 ? new Uint8Array(this.data, requestedRange.start, len) : new DataView(this.data, requestedRange.start, len); 57112 } 57113 57114 } 57115 57116 /* 57117 * The MIT License (MIT) 57118 * 57119 * Copyright (c) 2014 Broad Institute 57120 * 57121 * Permission is hereby granted, free of charge, to any person obtaining a copy 57122 * of this software and associated documentation files (the "Software"), to deal 57123 * in the Software without restriction, including without limitation the rights 57124 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 57125 * copies of the Software, and to permit persons to whom the Software is 57126 * furnished to do so, subject to the following conditions: 57127 * 57128 * The above copyright notice and this permission notice shall be included in 57129 * all copies or substantial portions of the Software. 57130 * 57131 * 57132 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 57133 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 57134 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 57135 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 57136 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 57137 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 57138 * THE SOFTWARE. 57139 */ 57140 57141 class BWSource { 57142 constructor(config, genome) { 57143 this.reader = new BWReader(config, genome); 57144 this.genome = genome; 57145 this.format = config.format || "bigwig"; 57146 this.wgValues = {}; 57147 } 57148 57149 async getFeatures(_ref) { 57150 let { 57151 chr, 57152 start, 57153 end, 57154 bpPerPixel, 57155 windowFunction 57156 } = _ref; 57157 const features = chr.toLowerCase() === "all" ? await this.getWGValues(windowFunction) : await this.reader.readFeatures(chr, start, chr, end, bpPerPixel, windowFunction); 57158 const isBigWig = this.reader.type === "bigwig"; 57159 57160 if (!isBigWig) { 57161 pack(features); 57162 } 57163 57164 return features; 57165 } 57166 57167 async getHeader() { 57168 return this.reader.loadHeader(); 57169 } 57170 57171 getDefaultRange() { 57172 if (this.reader.totalSummary !== undefined) { 57173 return this.reader.totalSummary.defaultRange; 57174 } else { 57175 return undefined; 57176 } 57177 } 57178 57179 async defaultVisibilityWindow() { 57180 return this.reader.defaultVisibilityWindow; 57181 } 57182 57183 async getWGValues(windowFunction) { 57184 const nominalScreenWidth = 1000; // This doesn't need to be precise 57185 57186 const genome = this.genome; 57187 57188 if (this.wgValues[windowFunction]) { 57189 return this.wgValues[windowFunction]; 57190 } else { 57191 const bpPerPixel = genome.getGenomeLength() / nominalScreenWidth; 57192 const features = await this.reader.readWGFeatures(bpPerPixel, windowFunction); 57193 let wgValues = []; 57194 57195 for (let f of features) { 57196 const chr = f.chr; 57197 const offset = genome.getCumulativeOffset(chr); 57198 const wgFeature = Object.assign({}, f); 57199 wgFeature.chr = "all"; 57200 wgFeature.start = offset + f.start; 57201 wgFeature.end = offset + f.end; 57202 wgValues.push(wgFeature); 57203 } 57204 57205 this.wgValues[windowFunction] = wgValues; 57206 return wgValues; 57207 } 57208 } 57209 57210 supportsWholeGenome() { 57211 return this.reader.type === "bigwig" || this.defaultVisibilityWindow() <= 0; 57212 } 57213 57214 async trackType() { 57215 return this.reader.getTrackType(); 57216 } 57217 57218 } 57219 57220 /* 57221 * The MIT License (MIT) 57222 * 57223 * Copyright (c) 2016 University of California San Diego 57224 * Author: Jim Robinson 57225 * 57226 * Permission is hereby granted, free of charge, to any person obtaining a copy 57227 * of this software and associated documentation files (the "Software"), to deal 57228 * in the Software without restriction, including without limitation the rights 57229 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 57230 * copies of the Software, and to permit persons to whom the Software is 57231 * furnished to do so, subject to the following conditions: 57232 * 57233 * The above copyright notice and this permission notice shall be included in 57234 * all copies or substantial portions of the Software. 57235 * 57236 * 57237 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 57238 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 57239 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 57240 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 57241 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 57242 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 57243 * THE SOFTWARE. 57244 */ 57245 const GZIP_FLAG = 0x1; 57246
57247 class TDFReader { 57248 constructor(config, genome) { 57249 this.config = config; 57250 this.genome = genome; 57251 this.path = config.url; 57252 this.groupCache = {}; 57253 this.datasetCache = {}; 57254 } 57255 57256 async readHeader() { 57257 if (this.magic !== undefined) { 57258 return this; // Already read 57259 } 57260 57261 let data = await igvxhr.loadArrayBuffer(this.path, buildOptions(this.config, { 57262 range: { 57263 start: 0, 57264 size: 64000 57265 } 57266 })); 57267 let binaryParser = new BinaryParser(new DataView(data)); 57268 this.magic = binaryParser.getInt(); 57269 this.version = binaryParser.getInt(); 57270 this.indexPos = binaryParser.getLong(); 57271 this.indexSize = binaryParser.getInt(); 57272 binaryParser.getInt(); 57273 57274 if (this.version >= 2) { 57275 let nWindowFunctions = binaryParser.getInt(); 57276 this.windowFunctions = []; 57277 57278 while (nWindowFunctions-- > 0) { 57279 this.windowFunctions.push(binaryParser.getString()); 57280 } 57281 } 57282 57283 this.trackType = binaryParser.getString(); 57284 this.trackLine = binaryParser.getString(); 57285 let nTracks = binaryParser.getInt(); 57286 this.trackNames = []; 57287 57288 while (nTracks-- > 0) { 57289 this.trackNames.push(binaryParser.getString()); 57290 } 57291 57292 this.genomeID = binaryParser.getString(); 57293 this.flags = binaryParser.getInt(); 57294 this.compressed = (this.flags & GZIP_FLAG) !== 0; // Now read index 57295 57296 data = await igvxhr.loadArrayBuffer(this.path, buildOptions(this.config, { 57297 range: { 57298 start: this.indexPos, 57299 size: this.indexSize 57300 } 57301 })); 57302 binaryParser = new BinaryParser(new DataView(data)); 57303 this.datasetIndex = {}; 57304 let nEntries = binaryParser.getInt(); 57305 57306 while (nEntries-- > 0) { 57307 const name = binaryParser.getString(); 57308 const pos = binaryParser.getLong(); 57309 const size = binaryParser.getInt(); 57310 this.datasetIndex[name] = { 57311 position: pos, 57312 size: size 57313 }; 57314 } 57315 57316 this.groupIndex = {}; 57317 nEntries = binaryParser.getInt(); 57318 57319 while (nEntries-- > 0) { 57320 const name = binaryParser.getString(); 57321 const pos = binaryParser.getLong(); 57322 const size = binaryParser.getInt(); 57323 this.groupIndex[name] = { 57324 position: pos, 57325 size: size 57326 }; 57327 } 57328 57329 return this; 57330 } 57331 57332 async readDataset(chr, windowFunction, zoom) { 57333 const key = chr + "_" + windowFunction + "_" + zoom; 57334 57335 if (this.datasetCache[key]) { 57336 return this.datasetCache[key]; 57337 } else { 57338 await this.readHeader(); 57339 const wf = this.version < 2 ? "" : "/" + windowFunction; 57340 const zoomString = chr.toLowerCase() === "all" || zoom === undefined ? "0" : zoom.toString(); 57341 let dsName; 57342 57343 if (windowFunction === "raw") { 57344 dsName = "/" + chr + "/raw"; 57345 } else { 57346 dsName = "/" + chr + "/z" + zoomString + wf; 57347 } 57348 57349 const indexEntry = this.datasetIndex[dsName]; 57350 57351 if (indexEntry === undefined) { 57352 return undefined; 57353 } 57354 57355 const data = await igvxhr.loadArrayBuffer(this.path, buildOptions(this.config, { 57356 range: { 57357 start: indexEntry.position, 57358 size: indexEntry.size 57359 } 57360 })); 57361 57362 if (!data) { 57363 return undefined; 57364 } 57365 57366 const binaryParser = new BinaryParser(new DataView(data)); 57367 let nAttributes = binaryParser.getInt(); 57368 const attributes = {}; 57369 57370 while (nAttributes-- > 0) { 57371 attributes[binaryParser.getString()] = binaryParser.getString(); 57372 } 57373 57374 const dataType = binaryParser.getString(); 57375 const tileWidth = binaryParser.getFloat(); 57376 let nTiles = binaryParser.getInt(); 57377 const tiles = []; 57378 57379 while (nTiles-- > 0) { 57380 tiles.push({ 57381 position: binaryParser.getLong(), 57382 size: binaryParser.getInt() 57383 }); 57384 } 57385 57386 const dataset = { 57387 name: dsName, 57388 attributes: attributes, 57389 dataType: dataType, 57390 tileWidth: tileWidth, 57391 tiles: tiles 57392 }; 57393 this.datasetCache[key] = dataset; 57394 return dataset; 57395 } 57396 } 57397 57398 async readRootGroup() { 57399 const genome = this.genome; 57400 const rootGroup = this.groupCache["/"]; 57401 57402 if (rootGroup) { 57403 return rootGroup; 57404 } else { 57405 const group = await this.readGroup("/"); 57406 const names = group["chromosomes"]; 57407 const maxZoomString = group["maxZoom"]; // Now parse out interesting attributes. 57408 57409 if (maxZoomString) { 57410 this.maxZoom = Number(maxZoomString); 57411 } 57412
57413 const totalCountString = group["totalCount"]; 57414 57415 if (totalCountString) { 57416 group.totalCount = Number(totalCountString); 57417 } // Chromosome names 57418 57419 57420 const chrAliasTable = {}; 57421 57422 if (names) { 57423 names.split(",").forEach(function (chr) { 57424 const canonicalName = genome.getChromosomeName(chr); 57425 chrAliasTable[canonicalName] = chr; 57426 }); 57427 } 57428 57429 this.chrAliasTable = chrAliasTable; 57430 this.groupCache["/"] = group; 57431 return group; 57432 } 57433 } 57434 57435 async readGroup(name) { 57436 const group = this.groupCache[name]; 57437 57438 if (group) { 57439 return group; 57440 } else { 57441 await this.readHeader(); 57442 const indexEntry = this.groupIndex[name]; 57443 57444 if (indexEntry === undefined) { 57445 return undefined; 57446 } 57447 57448 const data = await igvxhr.loadArrayBuffer(this.path, buildOptions(this.config, { 57449 range: { 57450 start: indexEntry.position, 57451 size: indexEntry.size 57452 } 57453 })); 57454 57455 if (!data) { 57456 return undefined; 57457 } 57458 57459 const binaryParser = new BinaryParser(new DataView(data)); 57460 const group = { 57461 name: name 57462 }; 57463 let nAttributes = binaryParser.getInt(); 57464 57465 while (nAttributes-- > 0) { 57466 const key = binaryParser.getString(); 57467 const value = binaryParser.getString(); 57468 group[key] = value; 57469 } 57470 57471 this.groupCache[name] = group; 57472 return group; 57473 } 57474 } 57475 57476 async readTiles(tileIndeces, nTracks) { 57477 tileIndeces.sort(function (a, b) { 57478 return a.position - b.position; 57479 }); 57480 tileIndeces = tileIndeces.filter(function (idx) { 57481 return idx.size > 0; 57482 }); 57483 57484 if (tileIndeces.length === 0) { 57485 return Promise.resolve([]); 57486 } 57487 57488 const firstEntry = tileIndeces[0]; 57489 const lastEntry = tileIndeces[tileIndeces.length - 1]; 57490 const position = firstEntry.position; 57491 const size = lastEntry.position + lastEntry.size - position; 57492 const data = await igvxhr.loadArrayBuffer(this.path, buildOptions(this.config, { 57493 range: { 57494 start: position, 57495 size: size 57496 } 57497 })); 57498 const tiles = []; // Loop through and decode tiles 57499 57500 for (let indexEntry of tileIndeces) { 57501 const start = indexEntry.position - position; 57502 const size = indexEntry.size; 57503 57504 if (size > 0) { 57505 let tileData; 57506 57507 if (this.compressed) { 57508 const plain = inflate(data.slice(start, start + size)); 57509 tileData = plain.buffer; 57510 } else { 57511 tileData = data.slice(start, start + size); 57512 } 57513 57514 const binaryParser = new BinaryParser(new DataView(tileData)); 57515 const type = binaryParser.getString(); 57516 let tile; 57517 57518 switch (type) { 57519 case "fixedStep": 57520 tile = createFixedStep(binaryParser, nTracks); 57521 break; 57522 57523 case "variableStep": 57524 tile = createVariableStep(binaryParser, nTracks); 57525 break; 57526 57527 case "bed": 57528 case "bedWithName": 57529 tile = createBed(binaryParser, nTracks, type); 57530 break; 57531 57532 default: 57533 throw "Unknown tile type: " + type; 57534 } 57535 57536 tiles.push(tile); 57537 } 57538 } 57539 57540 return tiles; 57541 } 57542 57543 async readTile(indexEntry, nTracks) { 57544 let data = await igvxhr.loadArrayBuffer(this.path, buildOptions(this.config, { 57545 range: { 57546 start: indexEntry.position, 57547 size: indexEntry.size 57548 } 57549 })); 57550 57551 if (this.compressed) { 57552 const plain = inflate(data); 57553 data = plain.buffer; 57554 } 57555 57556 const binaryParser = new BinaryParser(new DataView(data)); 57557 const type = binaryParser.getString(); 57558 57559 switch (type) { 57560 case "fixedStep": 57561 return createFixedStep(binaryParser, nTracks); 57562 57563 case "variableStep": 57564 return createVariableStep(binaryParser, nTracks); 57565 57566 case "bed": 57567 case "bedWithName": 57568 return createBed(binaryParser, nTracks, type); 57569 57570 default: 57571 throw "Unknown tile type: " + type; 57572 } 57573 } 57574 57575 } 57576 57577 function createFixedStep(binaryParser, nTracks) { 57578 const nPositions = binaryParser.getInt(); 57579 const start = binaryParser.getInt(); 57580 const span = binaryParser.getFloat(); 57581 const data = []; 57582 let nt = nTracks; 57583 57584 while (nt-- > 0) { 57585 let np = nPositions; 57586 const dtrack = []; 57587 57588 while (np-- > 0) { 57589 dtrack.push(binaryParser.getFloat()); 57590 } 57591 57592 data.push(dtrack); 57593 } 57594 57595 return { 57596 type: "fixedStep", 57597 start: start, 57598 span: span, 57599 data: data, 57600 nTracks: nTracks, 57601 nPositions: nPositions 57602 }; 57603 } 57604 57605 function createVariableStep(binaryParser, nTracks) { 57606 const tileStart = binaryParser.getInt(); 57607 const span = binaryParser.getFloat(); 57608 const nPositions = binaryParser.getInt(); 57609 const start = []; 57610 let np = nPositions; 57611 57612 while (np-- > 0) { 57613 start.push(binaryParser.getInt()); 57614 } 57615 57616 binaryParser.getInt(); // # of samples, ignored but should === nTracks 57617 57618 const data = []; 57619 let nt = nTracks; 57620 57621 while (nt-- > 0) { 57622 np = nPositions; 57623 const dtrack = []; 57624 57625 while (np-- > 0) { 57626 dtrack.push(binaryParser.getFloat()); 57627 } 57628 57629 data.push(dtrack); 57630 } 57631 57632 return { 57633 type: "variableStep", 57634 tileStart: tileStart, 57635 span: span, 57636 start: start, 57637 data: data, 57638 nTracks: nTracks, 57639 nPositions: nPositions 57640 }; 57641 } 57642 57643 function createBed(binaryParser, nTracks, type) { 57644 const nPositions = binaryParser.getInt(); 57645 let n = nPositions; 57646 const start = []; 57647 57648 while (n-- > 0) { 57649 start.push(binaryParser.getInt()); 57650 } 57651 57652 n = nPositions; 57653 const end = []; 57654 57655 while (n-- > 0) { 57656 end.push(binaryParser.getInt()); 57657 } 57658 57659 binaryParser.getInt(); // # of samples, ignored but should === nTracks 57660 57661 const data = []; 57662 let nt = nTracks; 57663 57664 while (nt-- > 0) { 57665 let np = nPositions; 57666 const dtrack = []; 57667 57668 while (np-- > 0) { 57669 dtrack.push(binaryParser.getFloat()); 57670 } 57671 57672 data.push(dtrack); 57673 } 57674 57675 if (type === "bedWithName") { 57676 n = nPositions; 57677 const name = []; 57678 57679 while (n-- > 0) { 57680 name.push(binaryParser.getString()); 57681 } 57682 } 57683 57684 return { 57685 type: type, 57686 start: start, 57687 end: end, 57688 data: data, 57689 nTracks: nTracks, 57690 nPositions: nPositions 57691 }; 57692 } 57693 57694 /* 57695 * The MIT License (MIT) 57696 * 57697 * Copyright (c) 2016 University of California San Diego 57698 * Author: Jim Robinson 57699 * 57700 * Permission is hereby granted, free of charge, to any person obtaining a copy 57701 * of this software and associated documentation files (the "Software"), to deal 57702 * in the Software without restriction, including without limitation the rights 57703 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 57704 * copies of the Software, and to permit persons to whom the Software is 57705 * furnished to do so, subject to the following conditions: 57706 * 57707 * The above copyright notice and this permission notice shall be included in 57708 * all copies or substantial portions of the Software. 57709 * 57710 * 57711 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 57712 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 57713 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 57714 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 57715 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 57716 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 57717 * THE SOFTWARE. 57718 */ 57719 57720 class TDFSource { 57721 constructor(config, genome) { 57722 this.genome = genome;
57723 this.windowFunction = config.windowFunction || "mean"; 57724 this.reader = new TDFReader(config, genome); 57725 } 57726 57727 async getFeatures(_ref) { 57728 let { 57729 chr, 57730 start, 57731 end, 57732 bpPerPixel 57733 } = _ref; 57734 57735 if (chr.toLowerCase() === "all") { 57736 const wgFeatures = []; 57737 const genome = this.genome; 57738 const chrNames = this.genome.wgChromosomeNames; 57739 57740 if (chrNames) { 57741 for (let c of genome.wgChromosomeNames) { 57742 const len = genome.getChromosome(c).bpLength; 57743 bpPerPixel = len / 1000; 57744 const chrFeatures = await this._getFeatures(c, 0, len, bpPerPixel); 57745 57746 if (chrFeatures) { 57747 for (let f of chrFeatures) { 57748 const wg = Object.assign({}, f); 57749 wg.chr = "all"; 57750 wg.start = genome.getGenomeCoordinate(f.chr, f.start); 57751 wg.end = genome.getGenomeCoordinate(f.chr, f.end); 57752 wg._f = f; 57753 wgFeatures.push(wg); 57754 } 57755 } 57756 } 57757 } 57758 57759 return wgFeatures; 57760 } else { 57761 return this._getFeatures(chr, start, end, bpPerPixel); 57762 } 57763 } 57764 57765 async _getFeatures(chr, start, end, bpPerPixel) { 57766 const genomicInterval = new GenomicInterval(chr, start, end); 57767 const genome = this.genome; 57768 57769 if (!this.rootGroup) { 57770 this.rootGroup = await this.reader.readRootGroup(); 57771 57772 if (!this.normalizationFactor) { 57773 const totalCount = this.rootGroup.totalCount; 57774 57775 if (totalCount) { 57776 this.normalizationFactor = 1.0e6 / totalCount; 57777 } 57778 } 57779 } 57780 57781 genomicInterval.bpPerPixel = bpPerPixel; 57782 const zoom = zoomLevelForScale(chr, bpPerPixel, genome); 57783 let queryChr = this.reader.chrAliasTable[chr]; 57784 let maxZoom = this.reader.maxZoom; 57785 if (queryChr === undefined) queryChr = chr; 57786 if (maxZoom === undefined) maxZoom = -1; 57787 const wf = zoom > maxZoom ? "raw" : this.windowFunction; 57788 const dataset = await this.reader.readDataset(queryChr, wf, zoom); 57789 57790 if (dataset == null) { 57791 return []; 57792 } 57793 57794 const tileWidth = dataset.tileWidth; 57795 const startTile = Math.floor(start / tileWidth); 57796 const endTile = Math.floor(end / tileWidth); 57797 const NTRACKS = 1; // TODO read this 57798 57799 const tiles = await this.reader.readTiles(dataset.tiles.slice(startTile, endTile + 1), NTRACKS); 57800 const features = []; 57801 57802 for (let tile of tiles) { 57803 switch (tile.type) { 57804 case "bed": 57805 decodeBedTile(tile, chr, start, end, bpPerPixel, features); 57806 break; 57807 57808 case "variableStep": 57809 decodeVaryTile(tile, chr, start, end, bpPerPixel, features); 57810 break; 57811 57812 case "fixedStep": 57813 decodeFixedTile(tile, chr, start, end, bpPerPixel, features); 57814 break; 57815 57816 default: 57817 throw "Unknown tile type: " + tile.type; 57818 } 57819 } 57820 57821 features.sort(function (a, b) { 57822 return a.start - b.start; 57823 }); 57824 return features; 57825 } 57826 57827 supportsWholeGenome() { 57828 return true; 57829 } 57830 57831 } 57832 57833 function decodeBedTile(tile, chr, bpStart, bpEnd, bpPerPixel, features) { 57834 const nPositions = tile.nPositions; 57835 const starts = tile.start; 57836 const ends = tile.end; 57837 const data = tile.data[0]; // Single track for now 57838 57839 for (let i = 0; i < nPositions; i++) { 57840 const s = starts[i]; 57841 const e = ends[i]; 57842 if (e < bpStart) continue; 57843 if (s > bpEnd) break; 57844 features.push({ 57845 chr: chr, 57846 start: s, 57847 end: e, 57848 value: data[i] 57849 }); 57850 } 57851 } 57852 57853 function decodeVaryTile(tile, chr, bpStart, bpEnd, bpPerPixel, features) { 57854 const nPositions = tile.nPositions; 57855 const starts = tile.start; 57856 const span = tile.span; 57857 const data = tile.data[0]; // Single track for now 57858 57859 for (let i = 0; i < nPositions; i++) { 57860 const s = starts[i]; 57861 const e = s + span; 57862 if (e < bpStart) continue; 57863 if (s > bpEnd) break; 57864 features.push({ 57865 chr: chr, 57866 start: s, 57867 end: e, 57868 value: data[i] 57869 }); 57870 } 57871 } 57872 57873 function decodeFixedTile(tile, chr, bpStart, bpEnd, bpPerPixel, features) { 57874 const nPositions = tile.nPositions; 57875 let s = tile.start; 57876 const span = tile.span; 57877 const data = tile.data[0]; // Single track for now 57878 57879 for (let i = 0; i < nPositions; i++) { 57880 const e = s + span; 57881 if (s > bpEnd) break; 57882 57883 if (e >= bpStart) { 57884 if (!Number.isNaN(data[i])) { 57885 features.push({ 57886 chr: chr, 57887 start: s, 57888 end: e, 57889 value: data[i] 57890 }); 57891 } 57892 } 57893 57894 s = e; 57895 } 57896 } 57897 57898 var log2 = Math.log(2); 57899 57900 function zoomLevelForScale(chr, bpPerPixel, genome) { 57901 // Convert bpPerPixel to IGV "zoom" level. This is a bit convoluted, IGV computes zoom levels assuming 57902 // display in a 700 pixel window. The fully zoomed out view of a chromosome is zoom level "0". 57903 // Zoom level 1 is magnified 2X, and so forth 57904 var chrSize = genome.getChromosome(chr).bpLength;
57905 return Math.ceil(Math.log(Math.max(0, chrSize / (bpPerPixel * 700))) / log2); 57906 } 57907 57908 /* 57909 * The MIT License (MIT) 57910 * 57911 * Copyright (c) 2014-2015 Broad Institute 57912 * 57913 * Permission is hereby granted, free of charge, to any person obtaining a copy 57914 * of this software and associated documentation files (the "Software"), to deal 57915 * in the Software without restriction, including without limitation the rights 57916 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 57917 * copies of the Software, and to permit persons to whom the Software is 57918 * furnished to do so, subject to the following conditions: 57919 * 57920 * The above copyright notice and this permission notice shall be included in 57921 * all copies or substantial portions of the Software. 57922 * 57923 * 57924 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 57925 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 57926 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 57927 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 57928 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 57929 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 57930 * THE SOFTWARE. 57931 */ 57932 57933 function FeatureSource(config, genome) { 57934 const format = config.format ? config.format.toLowerCase() : undefined; 57935 57936 if ('bigwig' === format || 'bigbed' === format || 'bb' === format) { 57937 return new BWSource(config, genome); 57938 } else if ("tdf" === format) { 57939 return new TDFSource(config, genome); 57940 } else { 57941 return new TextFeatureSource(config, genome); 57942 } 57943 } 57944 57945 const pairs = [['A', 'T'], ['G', 'C'], ['Y', 'R'], ['W', 'S'], ['K', 'M'], ['D', 'H'], ['B', 'V']]; 57946 const complements = new Map(); 57947 57948 for (let p of pairs) { 57949 const p1 = p[0]; 57950 const p2 = p[1]; 57951 complements.set(p1, p2); 57952 complements.set(p2, p1); 57953 complements.set(p1.toLowerCase(), p2.toLowerCase()); 57954 complements.set(p2.toLowerCase(), p1.toLowerCase()); 57955 } 57956 57957 function reverseComplementSequence(sequence) { 57958 let comp = ''; 57959 let idx = sequence.length; 57960 57961 while (idx-- > 0) { 57962 const base = sequence[idx]; 57963 comp += complements.has(base) ? complements.get(base) : base; 57964 } 57965 57966 return comp; 57967 } 57968 57969 const GtexUtils = { 57970 getTissueInfo: function (datasetId, baseURL) { 57971 datasetId = datasetId || 'gtex_v8'; 57972 baseURL = baseURL || 'https://gtexportal.org/rest/v1'; 57973 let url = baseURL + '/dataset/tissueInfo?datasetId=' + datasetId; 57974 return igvxhr.loadJson(url, {}); 57975 }, 57976 //https://gtexportal.org/rest/v1/association/singleTissueEqtlByLocation?chromosome=7&start=98358766&end=101523798&tissueName=Liver&datasetId=gtex_v7 57977 //https://gtexportal.org/rest/v1/association/singleTissueEqtlByLocation?chromosome=7&start=98358766&end=101523798&tissueSiteDetailId=Liver&datasetId=gtex_v8 57978 trackConfiguration: function (tissueSummary, baseURL) { 57979 baseURL = baseURL || 'https://gtexportal.org/rest/v1'; 57980 return { 57981 type: "eqtl", 57982 sourceType: "gtex-ws", 57983 url: baseURL + '/association/singleTissueEqtlByLocation', 57984 tissueSiteDetailId: tissueSummary.tissueSiteDetailId, 57985 name: tissueSummary.tissueSiteDetailId.split('_').join(' '), 57986 visibilityWindow: 250000 57987 }; 57988 } 57989 }; 57990 57991 /** 57992 * @param feature 57993 * @param bpStart genomic location of the left edge of the current canvas 57994 * @param xScale scale in base-pairs per pixel 57995 * @returns {{px: number, px1: number, pw: number, h: number, py: number}} 57996 */ 57997 57998 function calculateFeatureCoordinates(feature, bpStart, xScale) { 57999 let px = (feature.start - bpStart) / xScale; 58000 let px1 = (feature.end - bpStart) / xScale; //px = Math.round((feature.start - bpStart) / xScale), 58001 //px1 = Math.round((feature.end - bpStart) / xScale), 58002 58003 let pw = px1 - px; 58004 58005 if (pw < 3) { 58006 pw = 3; 58007 px -= 1.5; 58008 } 58009 58010 return { 58011 px: px, 58012 px1: px1, 58013 pw: pw 58014 }; 58015 } 58016 /** 58017 * 58018 * @param feature 58019 * @param bpStart genomic location of the left edge of the current canvas 58020 * @param xScale scale in base-pairs per pixel 58021 * @param pixelHeight pixel height of the current canvas 58022 * @param ctx the canvas 2d context 58023 * @param options genomic state 58024 */ 58025 58026 function renderFeature(feature, bpStart, xScale, pixelHeight, ctx, options) {
58027 try { 58028 ctx.save(); // Set ctx color to a known valid color. If getColorForFeature returns an invalid color string it is ignored, and 58029 // this default will be used. 58030 58031 ctx.fillStyle = this.defaultColor; 58032 ctx.strokeStyle = this.defaultColor; 58033 const color = getColorForFeature.call(this, feature); 58034 ctx.fillStyle = color; 58035 ctx.strokeStyle = color; 58036 let h; 58037 let py; 58038 58039 if (this.displayMode === "SQUISHED" && feature.row !== undefined) { 58040 h = this.featureHeight / 2; 58041 py = this.margin + this.squishedRowHeight * feature.row; 58042 } else if (this.displayMode === "EXPANDED" && feature.row !== undefined) { 58043 h = this.featureHeight; 58044 py = this.margin + this.expandedRowHeight * feature.row; 58045 } else { 58046 // collapsed 58047 h = this.featureHeight; 58048 py = this.margin; 58049 } 58050 58051 const pixelWidth = options.pixelWidth; 58052 const cy = py + h / 2; 58053 const h2 = h / 2; 58054 const py2 = cy - h2 / 2; 58055 const exonCount = feature.exons ? feature.exons.length : 0; 58056 const coord = calculateFeatureCoordinates(feature, bpStart, xScale); 58057 const step = this.arrowSpacing; 58058 const direction = feature.strand === '+' ? 1 : feature.strand === '-' ? -1 : 0; 58059 58060 if (exonCount === 0) { 58061 // single-exon transcript 58062 const xLeft = Math.max(0, coord.px); 58063 const xRight = Math.min(pixelWidth, coord.px1); 58064 const width = Math.max(coord.pw, xRight - xLeft); 58065 ctx.fillRect(xLeft, py, width, h); // Arrows 58066 // Do not draw if strand is not +/- 58067 58068 if (direction !== 0) { 58069 ctx.fillStyle = "white"; 58070 ctx.strokeStyle = "white"; 58071 58072 for (let x = xLeft + step / 2; x < xRight; x += step) { 58073 // draw arrowheads along central line indicating transcribed orientation 58074 IGVGraphics.strokeLine(ctx, x - direction * 2, cy - 2, x, cy); 58075 IGVGraphics.strokeLine(ctx, x - direction * 2, cy + 2, x, cy); 58076 } 58077 58078 ctx.fillStyle = color; 58079 ctx.strokeStyle = color; 58080 } 58081 } else { 58082 // multi-exon transcript 58083 IGVGraphics.strokeLine(ctx, coord.px + 1, cy, coord.px1 - 1, cy); // center line for introns 58084 58085 const xLeft = Math.max(0, coord.px) + step / 2; 58086 const xRight = Math.min(pixelWidth, coord.px1); 58087 58088 for (let x = xLeft; x < xRight; x += step) { 58089 // draw arrowheads along central line indicating transcribed orientation 58090 IGVGraphics.strokeLine(ctx, x - direction * 2, cy - 2, x, cy); 58091 IGVGraphics.strokeLine(ctx, x - direction * 2, cy + 2, x, cy); 58092 } 58093 58094 for (let e = 0; e < exonCount; e++) { 58095 // draw the exons 58096 const exon = feature.exons[e]; 58097 let ePx = Math.round((exon.start - bpStart) / xScale); 58098 let ePx1 = Math.round((exon.end - bpStart) / xScale); 58099 let ePw = Math.max(1, ePx1 - ePx); 58100 let ePxU; 58101 58102 if (ePx + ePw < 0) { 58103 continue; // Off the left edge 58104 } 58105 58106 if (ePx > pixelWidth) { 58107 break; // Off the right edge 58108 } 58109 58110 if (exon.utr) { 58111 ctx.fillRect(ePx, py2, ePw, h2); // Entire exon is UTR 58112 } else { 58113 if (exon.cdStart) { 58114 ePxU = Math.round((exon.cdStart - bpStart) / xScale); 58115 ctx.fillRect(ePx, py2, ePxU - ePx, h2); // start is UTR 58116 58117 ePw -= ePxU - ePx; 58118 ePx = ePxU; 58119 } 58120 58121 if (exon.cdEnd) { 58122 ePxU = Math.round((exon.cdEnd - bpStart) / xScale); 58123 ctx.fillRect(ePxU, py2, ePx1 - ePxU, h2); // start is UTR 58124 58125 ePw -= ePx1 - ePxU; 58126 ePx1 = ePxU; 58127 } 58128 58129 ePw = Math.max(ePw, 1); 58130 ctx.fillRect(ePx, py, ePw, h); // Arrows 58131 58132 if (ePw > step + 5 && direction !== 0) { 58133 ctx.fillStyle = "white"; 58134 ctx.strokeStyle = "white"; 58135 58136 for (let x = ePx + step / 2; x < ePx1; x += step) { 58137 // draw arrowheads along central line indicating transcribed orientation 58138 IGVGraphics.strokeLine(ctx, x - direction * 2, cy - 2, x, cy); 58139 IGVGraphics.strokeLine(ctx, x - direction * 2, cy + 2, x, cy); 58140 } 58141 58142 ctx.fillStyle = color; 58143 ctx.strokeStyle = color; 58144 } 58145 } 58146 } 58147 } 58148 58149 if (options.drawLabel && this.displayMode !== "SQUISHED") { 58150 renderFeatureLabel.call(this, ctx, feature, coord.px, coord.px1, py, options.referenceFrame, options); 58151 } 58152 } finally {
58153 ctx.restore(); 58154 } 58155 } 58156 /** 58157 * @param ctx the canvas 2d context 58158 * @param feature 58159 * @param featureX feature start x-coordinate 58160 * @param featureX1 feature end x-coordinate 58161 * @param featureY feature y-coordinate 58162 * @param windowX visible window start x-coordinate 58163 * @param windowX1 visible window end x-coordinate 58164 * @param referenceFrame genomic state 58165 * @param options options 58166 */ 58167 58168 function renderFeatureLabel(ctx, feature, featureX, featureX1, featureY, referenceFrame, options) { 58169 try { 58170 ctx.save(); 58171 let name = feature.name; 58172 if (name === undefined && feature.gene) name = feature.gene.name; 58173 if (name === undefined) name = feature.id || feature.ID; 58174 if (!name || name === '.') return; 58175 let pixelXOffset = options.pixelXOffset || 0; 58176 const t1 = Math.max(featureX, -pixelXOffset); 58177 const t2 = Math.min(featureX1, -pixelXOffset + options.viewportWidth); 58178 const centerX = (t1 + t2) / 2; 58179 let transform; 58180 58181 if (this.displayMode === "COLLAPSED" && this.labelDisplayMode === "SLANT") { 58182 transform = { 58183 rotate: { 58184 angle: 45 58185 } 58186 }; 58187 } 58188 58189 const labelY = getFeatureLabelY(featureY, transform); 58190 let color = getColorForFeature.call(this, feature); 58191 let geneColor; 58192 let gtexSelection = false; 58193 58194 if (referenceFrame.selection && GtexUtils.gtexLoaded) { 58195 // TODO -- for gtex, figure out a better way to do this 58196 gtexSelection = true; 58197 geneColor = referenceFrame.selection.colorForGene(name); 58198 } 58199 58200 const geneFontStyle = { 58201 textAlign: "SLANT" === this.labelDisplayMode ? undefined : 'center', 58202 fillStyle: geneColor || color, 58203 strokeStyle: geneColor || color 58204 }; 58205 const textBox = ctx.measureText(name); 58206 const xleft = centerX - textBox.width / 2; 58207 const xright = centerX + textBox.width / 2; 58208 58209 if (options.labelAllFeatures || xleft > options.rowLastX[feature.row] || gtexSelection) { 58210 options.rowLastX[feature.row] = xright; 58211 IGVGraphics.fillText(ctx, name, centerX, labelY, geneFontStyle, transform); 58212 } 58213 } finally { 58214 ctx.restore(); 58215 } 58216 } 58217 58218 function getFeatureLabelY(featureY, transform) { 58219 return transform ? featureY + 20 : featureY + 25; 58220 } 58221 /** 58222 * Return color for feature. Called in the context of a FeatureTrack instance. 58223 * @param feature 58224 * @returns {string} 58225 */ 58226 58227 58228 function getColorForFeature(feature) { 58229 let color; 58230 58231 if (this.altColor && "-" === feature.strand) { 58232 color = typeof this.altColor === "function" ? this.altColor(feature) : this.altColor; 58233 } else if (this.color) { 58234 color = typeof this.color === "function" ? this.color(feature) : this.color; // Explicit setting via menu, or possibly track line if !config.color 58235 } else if (this.colorBy) { 58236 const value = feature.getAttributeValue ? feature.getAttributeValue(this.colorBy) : feature[this.colorBy]; 58237 color = this.colorTable.getColor(value); 58238 } else if (feature.color) { 58239 color = feature.color; // Explicit color for feature 58240 } else { 58241 color = this.defaultColor; // Track default 58242 } 58243 58244 if (feature.alpha && feature.alpha !== 1) { 58245 color = IGVColor.addAlpha(color, feature.alpha); 58246 } else if (this.useScore && feature.score && !Number.isNaN(feature.score)) { 58247 // UCSC useScore option, for scores between 0-1000. See https://genome.ucsc.edu/goldenPath/help/customTrack.html#TRACK 58248 const min = this.config.min ? this.config.min : 0; //getViewLimitMin(track); 58249 58250 const max = this.config.max ? this.config.max : 1000; //getViewLimitMax(track); 58251 58252 const alpha = getAlpha(min, max, feature.score); 58253 feature.alpha = alpha; // Avoid computing again 58254 58255 color = IGVColor.addAlpha(color, alpha); 58256 } 58257 58258 function getAlpha(min, max, score) { 58259 const binWidth = (max - min) / 9; 58260 const binNumber = Math.floor((score - min) / binWidth); 58261 return Math.min(1.0, 0.2 + binNumber * 0.8 / 9); 58262 } 58263 58264 return color; 58265 } 58266 58267 // SNP constants 58268 const codingNonSynonSet = new Set(['nonsense', 'missense', 'stop-loss', 'frameshift', 'cds-indel']); 58269 const codingSynonSet = new Set(['coding-synon']); 58270 const spliceSiteSet = new Set(['splice-3', 'splice-5']); 58271 const untranslatedSet = new Set(['untranslated-5', 'untranslated-3']); 58272 /**
58273 * Renderer for a UCSC snp track 58274 * 58275 * @param snp 58276 * @param bpStart genomic location of the left edge of the current canvas 58277 * @param xScale scale in base-pairs per pixel 58278 * @param pixelHeight pixel height of the current canvas 58279 * @param ctx the canvas 2d context 58280 */ 58281 58282 function renderSnp(snp, bpStart, xScale, pixelHeight, ctx) { 58283 var coord = calculateFeatureCoordinates(snp, bpStart, xScale), 58284 py = this.margin, 58285 h, 58286 colorArrLength = this.snpColors.length, 58287 colorPriority; 58288 h = this.displayMode === "squished" ? this.squishedRowHeight : this.expandedRowHeight; 58289 58290 switch (this.colorBy) { 58291 case 'function': 58292 colorPriority = colorByFunc(snp.func); 58293 break; 58294 58295 case 'class': 58296 colorPriority = colorByClass(snp['class']); 58297 } 58298 58299 ctx.fillStyle = this.snpColors[colorPriority]; 58300 ctx.fillRect(coord.px, py, coord.pw, h); // Coloring functions, convert a value to a priority 58301 58302 function colorByFunc(theFunc) { 58303 var priorities; 58304 var funcArray = theFunc.split(','); // possible func values 58305 58306 priorities = funcArray.map(function (func) { 58307 if (codingNonSynonSet.has(func) || spliceSiteSet.has(func)) { 58308 return colorArrLength - 1; 58309 } else if (codingSynonSet.has(func)) { 58310 return colorArrLength - 2; 58311 } else if (untranslatedSet.has(func)) { 58312 return colorArrLength - 3; 58313 } else { 58314 // locusSet.has(func) || intronSet.has(func) 58315 return 0; 58316 } 58317 }); 58318 return priorities.reduce(function (a, b) { 58319 return Math.max(a, b); 58320 }); 58321 } 58322 58323 function colorByClass(cls) { 58324 if (cls === 'deletion') { 58325 return colorArrLength - 1; 58326 } else if (cls === 'mnp') { 58327 return colorArrLength - 2; 58328 } else if (cls === 'microsatellite' || cls === 'named') { 58329 return colorArrLength - 3; 58330 } else { 58331 // cls === 'single' || cls === 'in-del' || cls === 'insertion' 58332 return 0; 58333 } 58334 } 58335 } 58336 58337 /** 58338 * 58339 * @param feature 58340 * @param bpStart genomic location of the left edge of the current canvas 58341 * @param xScale scale in base-pairs per pixel 58342 * @param pixelHeight pixel height of the current canvas 58343 * @param ctx the canvas 2d context 58344 */ 58345 function renderFusionJuncSpan(feature, bpStart, xScale, pixelHeight, ctx) { 58346 const rowHeight = this.displayMode === "EXPANDED" ? this.expandedRowHeight : this.squishedRowHeight; 58347 let py = this.margin; 58348 58349 if (this.displayMode !== "COLLAPSED" && feature.row !== undefined) { 58350 py += feature.row * rowHeight; 58351 } 58352 58353 const cy = py + 0.5 * rowHeight; 58354 const topY = cy - 0.5 * rowHeight; 58355 const bottomY = cy + 0.5 * rowHeight; // draw the junction arc 58356 58357 const junctionLeftPx = Math.round((feature.junction_left - bpStart) / xScale); 58358 const junctionRightPx = Math.round((feature.junction_right - bpStart) / xScale); 58359 ctx.beginPath(); 58360 ctx.moveTo(junctionLeftPx, cy); 58361 ctx.bezierCurveTo(junctionLeftPx, topY, junctionRightPx, topY, junctionRightPx, cy); 58362 ctx.lineWidth = 1 + Math.log(feature.num_junction_reads) / Math.log(2); 58363 ctx.strokeStyle = 'blue'; 58364 ctx.stroke(); // draw the spanning arcs 58365 58366 const spanningCoords = feature.spanning_frag_coords; 58367 58368 for (let i = 0; i < spanningCoords.length; i++) { 58369 const spanningInfo = spanningCoords[i]; 58370 const spanLeftPx = Math.round((spanningInfo.left - bpStart) / xScale); 58371 const spanRightPx = Math.round((spanningInfo.right - bpStart) / xScale); 58372 ctx.beginPath(); 58373 ctx.moveTo(spanLeftPx, cy); 58374 ctx.bezierCurveTo(spanLeftPx, bottomY, spanRightPx, bottomY, spanRightPx, cy); 58375 ctx.lineWidth = 1; 58376 ctx.strokeStyle = 'purple'; 58377 ctx.stroke(); 58378 } 58379 } 58380 58381 /* 58382 * The MIT License (MIT) 58383 * 58384 * Copyright (c) 2014 Broad Institute 58385 * 58386 * Permission is hereby granted, free of charge, to any person obtaining a copy 58387 * of this software and associated documentation files (the "Software"), to deal 58388 * in the Software without restriction, including without limitation the rights 58389 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 58390 * copies of the Software, and to permit persons to whom the Software is 58391 * furnished to do so, subject to the following conditions: 58392 * 58393 * The above copyright notice and this permission notice shall be included in 58394 * all copies or substantial portions of the Software. 58395 * 58396 * 58397 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 58398 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 58399 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 58400 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 58401 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 58402 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 58403 * THE SOFTWARE. 58404 */ 58405 58406 class FeatureTrack extends TrackBase { 58407 constructor(config, browser) { 58408 super(config, browser); 58409 } 58410 58411 init(config) { 58412 super.init(config); 58413 this.type = config.type || "annotation"; // Set maxRows -- protects against pathological feature packing cases (# of rows of overlapping feaures) 58414 58415 this.maxRows = config.maxRows === undefined ? 1000 : config.maxRows; 58416 this.displayMode = config.displayMode || "EXPANDED"; // COLLAPSED | EXPANDED | SQUISHED 58417 58418 this.labelDisplayMode = config.labelDisplayMode; 58419 58420 if (config._featureSource) { 58421 this.featureSource = config._featureSource; 58422 delete config._featureSource; 58423 } else { 58424 this.featureSource = config.featureSource ? config.featureSource : FeatureSource(config, this.browser.genome); 58425 } // Set default heights 58426 58427 58428 this.autoHeight = config.autoHeight; 58429 this.margin = config.margin === undefined ? 10 : config.margin; 58430 this.featureHeight = config.featureHeight || 14; 58431 58432 if ("FusionJuncSpan" === config.type) { 58433 this.render = config.render || renderFusionJuncSpan; 58434 this.squishedRowHeight = config.squishedRowHeight || 50; 58435 this.expandedRowHeight = config.expandedRowHeight || 50; 58436 this.height = config.height || this.margin + 2 * this.expandedRowHeight; 58437 } else if ('snp' === config.type) { 58438 this.render = config.render || renderSnp; // colors ordered based on priority least to greatest 58439 58440 this.snpColors = ['rgb(0,0,0)', 'rgb(0,0,255)', 'rgb(0,255,0)', 'rgb(255,0,0)']; 58441 this.colorBy = 'function'; 58442 this.expandedRowHeight = config.expandedRowHeight || 10; 58443 this.squishedRowHeight = config.squishedRowHeight || 5; 58444 this.height = config.height || 30; 58445 } else { 58446 this.render = config.render || renderFeature; 58447 this.arrowSpacing = 30; // adjust label positions to make sure they're always visible 58448 58449 monitorTrackDrag(this); 58450 this.squishedRowHeight = config.squishedRowHeight || 15; 58451 this.expandedRowHeight = config.expandedRowHeight || 30; 58452 this.height = config.height || this.margin + 2 * this.expandedRowHeight; // Set colorBy fields considering legacy options for backward compatibility 58453 58454 if (config.colorBy) { 58455 if (config.colorBy.field) { 58456 config.colorTable = config.colorBy.pallete || config.colorBy.palette; 58457 config.colorBy = config.colorBy.field; 58458 } 58459 58460 this.colorBy = config.colorBy; // Can be undefined => default 58461 58462 if (config.colorTable) { 58463 this.colorTable = new ColorTable(config.colorTable); 58464 } else { 58465 this.colorTable = new PaletteColorTable("Set1"); 58466 } 58467 } 58468 } //UCSC useScore option 58469 58470 58471 this.useScore = config.useScore; 58472 } 58473 58474 async postInit() { 58475 if (typeof this.featureSource.getHeader === "function") { 58476 this.header = await this.featureSource.getHeader(); 58477 } // Set properties from track line 58478 58479 58480 if (this.header) { 58481 this.setTrackProperties(this.header); 58482 } 58483 58484 if (this.visibilityWindow === undefined && typeof this.featureSource.defaultVisibilityWindow === 'function') { 58485 this.visibilityWindow = await this.featureSource.defaultVisibilityWindow(); 58486 } 58487 58488 return this; 58489 } 58490 58491 supportsWholeGenome() { 58492 return (this.config.indexed === false || !this.config.indexURL) && this.config.supp
58492ortsWholeGenome !== false; 58493 } 58494 58495 async getFeatures(chr, start, end, bpPerPixel) { 58496 const visibilityWindow = this.visibilityWindow; 58497 return this.featureSource.getFeatures({ 58498 chr, 58499 start, 58500 end, 58501 bpPerPixel, 58502 visibilityWindow 58503 }); 58504 } 58505 58506 /** 58507 * The required height in pixels required for the track content. This is not the visible track height, which 58508 * can be smaller (with a scrollbar) or larger. 58509 * 58510 * @param features 58511 * @returns {*} 58512 */ 58513 computePixelHeight(features) { 58514 if (this.displayMode === "COLLAPSED") { 58515 return this.margin + this.expandedRowHeight; 58516 } else { 58517 let maxRow = 0; 58518 58519 if (features && typeof features.forEach === "function") { 58520 for (let feature of features) { 58521 if (feature.row && feature.row > maxRow) { 58522 maxRow = feature.row; 58523 } 58524 } 58525 } 58526 58527 const height = this.margin + (maxRow + 1) * ("SQUISHED" === this.displayMode ? this.squishedRowHeight : this.expandedRowHeight); 58528 return height; 58529 } 58530 } 58531 58532 draw(options) { 58533 const featureList = options.features; 58534 const ctx = options.context; 58535 const bpPerPixel = options.bpPerPixel; 58536 const bpStart = options.bpStart; 58537 const pixelWidth = options.pixelWidth; 58538 const pixelHeight = options.pixelHeight; 58539 const bpEnd = bpStart + pixelWidth * bpPerPixel + 1; 58540 58541 if (!this.config.isMergedTrack) { 58542 IGVGraphics.fillRect(ctx, 0, options.pixelTop, pixelWidth, pixelHeight, { 58543 'fillStyle': "rgb(255, 255, 255)" 58544 }); 58545 } 58546 58547 if (featureList) { 58548 const rowFeatureCount = []; 58549 options.rowLastX = []; 58550 58551 for (let feature of featureList) { 58552 const row = feature.row || 0; 58553 58554 if (rowFeatureCount[row] === undefined) { 58555 rowFeatureCount[row] = 1; 58556 } else { 58557 rowFeatureCount[row]++; 58558 } 58559 58560 options.rowLastX[row] = -Number.MAX_SAFE_INTEGER; 58561 } 58562 58563 let lastPxEnd = []; 58564 58565 for (let feature of featureList) { 58566 if (feature.end < bpStart) continue; 58567 if (feature.start > bpEnd) break; 58568 const row = this.displayMode === 'COLLAPSED' ? 0 : feature.row; 58569 const featureDensity = pixelWidth / rowFeatureCount[row]; 58570 options.drawLabel = options.labelAllFeatures || featureDensity > 10; 58571 const pxEnd = Math.ceil((feature.end - bpStart) / bpPerPixel); 58572 const last = lastPxEnd[row]; 58573 58574 if (!last || pxEnd > last) { 58575 this.render.call(this, feature, bpStart, bpPerPixel, pixelHeight, ctx, options); // Ensure a visible gap between features 58576 58577 const pxStart = Math.floor((feature.start - bpStart) / bpPerPixel); 58578 58579 if (last && pxStart - last <= 0) { 58580 ctx.globalAlpha = 0.5; 58581 IGVGraphics.strokeLine(ctx, pxStart, 0, pxStart, pixelHeight, { 58582 'strokeStyle': "rgb(255, 255, 255)" 58583 }); 58584 ctx.globalAlpha = 1.0; 58585 } 58586 58587 lastPxEnd[row] = pxEnd; 58588 } 58589 } 58590 } else { 58591 console.log("No feature list"); 58592 } 58593 } 58594 58595 clickedFeatures(clickState, features) { 58596 const y = clickState.y - this.margin; 58597 const allFeatures = super.clickedFeatures(clickState, features); 58598 let row; 58599 58600 switch (this.displayMode) { 58601 case 'SQUISHED': 58602 row = Math.floor(y / this.squishedRowHeight); 58603 break; 58604 58605 case 'EXPANDED': 58606 row = Math.floor(y / this.expandedRowHeight); 58607 break; 58608 58609 default: 58610 row = undefined; 58611 } 58612 58613 return allFeatures.filter(function (feature) { 58614 return row === undefined || feature.row === undefined || row === feature.row; 58615 }); 58616 } 58617 /** 58618 * Return "popup data" for feature @ genomic location. Data is an array of key-value pairs 58619 */ 58620 58621 58622 popupData(clickState, features) { 58623 features = this.clickedFeatures(clickState, features); 58624 const genomicLocation = clickState.genomicLocation; 58625 const data = []; 58626 58627 for (let feature of features) { 58628 // Whole genome hack, whole-genome psuedo features store the "real" feature in an _f field 58629 const f = feature._f || feature; 58630 const featureData = typeof f.popupData === "function" ? f.popupData(genomicLocation) : this.extractPopupData(f); 58631 58632 if (featureData) { 58633 if (data.length > 0) { 58634 data.push("<hr/><hr/>"); 58635 } // If we have an infoURL, find the name property and create the link. We do this at this level 58636 // to catch name properties in both custom popupData functions and the generic extractPopupData function 58637 58638 58639 const infoURL = this.infoURL || this.config.infoURL; 58640 58641 for (let fd of featureData) { 58642 data.push(fd); 58643 58644 if (infoURL) { 58645 if (fd.name && fd.name.toLowerCase() === "name" && fd.value && isString$3(fd.value) && !fd.value.startsWith("<")) { 58646 const url = this.infoURL || this.config.infoURL; 58647 const href = url.replace("$$", feature.name); 58648 data.push({ 58649 name: "Info", 58650 value: `<a target="_blank" href=${href}>${fd.value}</a>` 58651 }); 58652 } 58653 } 58654 } //Array.prototype.push.apply(data, featureData); 58655 // If we have clicked over an exon number it. 58656 // Disabled for GFF and GTF files if the visibility window is < the feature length since we don't know if we have all exons 58657 58658 58659 const isGFF = "gff" === this.config.format || "gff3" === this.config.format || "gtf" === this.config.format; 58660 58661 if (f.exons) { 58662 for (let i = 0; i < f.exons.length; i++) { 58663 const exon = f.exons[i]; 58664 58665 if (genomicLocation >= exon.start && genomicLocation <= exon.end) { 58666 const exonNumber = isGFF ? exon.number : f.strand === "-" ? f.exons.length - i : i + 1; 58667 58668 if (exonNumber) { 58669 data.push('<hr/>'); 58670 data.push({ 58671 name: "Exon Number", 58672 value: exonNumber 58673 }); 58674 } 58675 58676 break; 58677 } 58678 } 58679 } 58680 } 58681 } 58682 58683 return data; 58684 } 58685 58686 menuItemList() { 58687 const menuItems = []; 58688
58689 if (this.render === renderSnp) { 58690 menuItems.push('<hr/>'); 58691 58692 for (let colorScheme of ["function", "class"]) { 58693 menuItems.push({ 58694 object: $$1(createCheckbox$1('Color by ' + colorScheme, colorScheme === this.colorBy)), 58695 click: () => { 58696 this.colorBy = colorScheme; 58697 this.trackView.repaintViews(); 58698 } 58699 }); 58700 } 58701 } 58702 58703 menuItems.push('<hr/>'); 58704 58705 for (let displayMode of ["COLLAPSED", "SQUISHED", "EXPANDED"]) { 58706 const lut = { 58707 "COLLAPSED": "Collapse", 58708 "SQUISHED": "Squish", 58709 "EXPANDED": "Expand" 58710 }; 58711 menuItems.push({ 58712 object: $$1(createCheckbox$1(lut[displayMode], displayMode === this.displayMode)), 58713 click: () => { 58714 this.displayMode = displayMode; 58715 this.config.displayMode = displayMode; 58716 this.trackView.checkContentHeight(); 58717 this.trackView.repaintViews(); 58718 } 58719 }); 58720 } 58721 58722 return menuItems; 58723 } 58724 58725 contextMenuItemList(clickState) { 58726 if (isSecureContext()) { 58727 const features = this.clickedFeatures(clickState); 58728 58729 if (features.length > 1) { 58730 features.sort((a, b) => a.end - a.start - (b.end - b.start)); 58731 } 58732 58733 const f = features[0]; // The longest feature 58734 58735 if (f.end - f.start <= 1000000) { 58736 return [{ 58737 label: 'Copy feature sequence', 58738 click: async () => { 58739 let seq = await this.browser.genome.getSequence(f.chr, f.start, f.end); 58740 58741 if (f.strand === '-') { 58742 seq = reverseComplementSequence(seq); 58743 } 58744 58745 navigator.clipboard.writeText(seq); 58746 } 58747 }, '<hr/>']; 58748 } 58749 } // Either not a secure context (i.e. http: protocol), or feature is too long 58750 58751 58752 return undefined; 58753 } 58754 58755 description() { 58756 // if('snp' === this.type) { 58757 if (renderSnp === this.render) { 58758 let desc = "<html>" + this.name + '<hr/>'; 58759 desc += '<em>Color By Function:</em><br>'; 58760 desc += '<span style="color:red">Red</span>: Coding-Non-Synonymous, Splice Site<br>'; 58761 desc += '<span style="color:green">Green</span>: Coding-Synonymous<br>'; 58762 desc += '<span style="color:blue">Blue</span>: Untranslated<br>'; 58763 desc += '<span style="color:black">Black</span>: Intron, Locus, Unknown<br><br>'; 58764 desc += '<em>Color By Class:</em><br>'; 58765 desc += '<span style="color:red">Red</span>: Deletion<br>'; 58766 desc += '<span style="color:green">Green</span>: MNP<br>'; 58767 desc += '<span style="color:blue">Blue</span>: Microsatellite, Named<br>'; 58768 desc += '<span style="color:black">Black</span>: Indel, Insertion, SNP'; 58769 desc += "</html>"; 58770 return desc; 58771 } else { 58772 return this.name; 58773 } 58774 } 58775 58776 /** 58777 * Called when the track is removed. Do any needed cleanup here 58778 */ 58779 dispose() { 58780 this.trackView = undefined; 58781 } 58782 58783 } 58784 /** 58785 * Monitors track drag events, updates label position to ensure that they're always visible. 58786 * @param track 58787 */ 58788 58789 58790 function monitorTrackDrag(track) { 58791 if (track.browser.on) { 58792 track.browser.on('trackdragend', onDragEnd); 58793 track.browser.on('trackremoved', unSubscribe); 58794 } 58795 58796 function onDragEnd() { 58797 if (track.trackView && track.displayMode !== "SQUISHED") { 58798 track.trackView.repaintViews(); // TODO -- refine this to the viewport that was dragged after DOM refactor 58799 } 58800 } 58801 58802 function unSubscribe(removedTrack) { 58803 if (track.browser.un && track === removedTrack) { 58804 track.browser.un('trackdragend', onDragEnd); 58805 track.browser.un('trackremoved', unSubscribe); 58806 } 58807 } 58808 } 58809 58810 /* 58811 * The MIT License (MIT) 58812 * 58813 * Copyright (c) 2014 Broad Institute 58814 * 58815 * Permission is hereby granted, free of charge, to any person obtaining a copy 58816 * of this software and associated documentation files (the "Software"), to deal 58817 * in the Software without restriction, including without limitation the rights 58818 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 58819 * copies of the Software, and to permit persons to whom the Software is 58820 * furnished to do so, subject to the following conditions: 58821 * 58822 * The above copyright notice and this permission notice shall be included in 58823 * all copies or substantial portions of the Software. 58824 * 58825 * 58826 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 58827 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 58828 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 58829 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 58830 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 58831 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 58832 * THE SOFTWARE. 58833 */ 58834 const DEFAULT_COLOR = "rgb(150,150,150)"; 58835 58836 class WigTrack extends TrackBase { 58837 constructor(config, browser) { 58838 super(config, browser); 58839 } 58840 58841 init(config) { 58842 super.init(config); 58843 this.type = "wig"; 58844 this.height = config.height || 50; 58845 this.featureType = 'numeric'; 58846 this.paintAxis = paintAxis; 58847 const format = config.format ? config.format.toLowerCase() : config.format; 58848 58849 if ("bigwig" === format) { 58850 this.featureSource = new BWSource(config, this.browser.genome); 58851 } else if ("tdf" === format) { 58852 this.featureSource = new TDFSource(config, this.browser.genome); 58853 } else { 58854 this.featureSource = FeatureSource(config, this.browser.genome); 58855 } 58856 58857 this.autoscale = config.autoscale || config.max === undefined; 58858 58859 if (!this.autoscale) { 58860 this.dataRange = { 58861 min: config.min || 0, 58862 max: config.max 58863 }; 58864 } 58865
58866 this.windowFunction = config.windowFunction || "mean"; 58867 this.graphType = config.graphType || "bar"; 58868 this.normalize = config.normalize; // boolean, for use with "TDF" files 58869 58870 this.scaleFactor = config.scaleFactor; // optional scale factor, ignored if normalize === true; 58871 } 58872 58873 async postInit() { 58874 const header = await this.getHeader(); 58875 if (header) this.setTrackProperties(header); 58876 } 58877 58878 async getFeatures(chr, start, end, bpPerPixel) { 58879 const features = await this.featureSource.getFeatures({ 58880 chr, 58881 start, 58882 end, 58883 bpPerPixel, 58884 windowFunction: this.windowFunction 58885 }); 58886 58887 if (this.normalize && this.featureSource.normalizationFactor) { 58888 const scaleFactor = this.featureSource.normalizationFactor; 58889 58890 for (let f of features) { 58891 f.value *= scaleFactor; 58892 } 58893 } 58894 58895 if (this.scaleFactor) { 58896 const scaleFactor = this.scaleFactor; 58897 58898 for (let f of features) { 58899 f.value *= scaleFactor; 58900 } 58901 } 58902 58903 return features; 58904 } 58905 58906 menuItemList() { 58907 return MenuUtils.numericDataMenuItems(this.trackView); 58908 } 58909 58910 async getHeader() { 58911 if (typeof this.featureSource.getHeader === "function") { 58912 this.header = await this.featureSource.getHeader(); 58913 } 58914 58915 return this.header; 58916 } 58917 58918 draw(options) { 58919 const features = options.features; 58920 const ctx = options.context; 58921 const bpPerPixel = options.bpPerPixel; 58922 const bpStart = options.bpStart; 58923 const pixelWidth = options.pixelWidth; 58924 const pixelHeight = options.pixelHeight; 58925 const bpEnd = bpStart + pixelWidth * bpPerPixel + 1; 58926 let lastPixelEnd = -1; 58927 let lastValue = -1; 58928 let lastNegValue = 1; 58929 const posColor = this.color || DEFAULT_COLOR; 58930 let baselineColor; 58931 58932 if (typeof posColor === "string" && posColor.startsWith("rgb(")) { 58933 baselineColor = IGVColor.addAlpha(posColor, 0.1); 58934 } 58935 58936 const yScale = yValue => { 58937 return (this.dataRange.max - yValue) / (this.dataRange.max - this.dataRange.min) * pixelHeight; 58938 }; 58939 58940 if (features && features.length > 0) { 58941 if (this.dataRange.min === undefined) this.dataRange.min = 0;
58941 // Max can be less than min if config.min is set but max left to autoscale. If that's the case there is 58942 // nothing to paint. 58943 58944 if (this.dataRange.max > this.dataRange.min) { 58945 const y0 = this.dataRange.min == 0 ? pixelHeight : yScale(0); 58946 58947 for (let f of features) { 58948 if (f.end < bpStart) continue; 58949 if (f.start > bpEnd) break; 58950 const x = Math.floor((f.start - bpStart) / bpPerPixel); 58951 if (isNaN(x)) continue; 58952 let y = yScale(f.value); 58953 const rectEnd = Math.ceil((f.end - bpStart) / bpPerPixel); 58954 const width = Math.max(1, rectEnd - x); 58955 let c = f.value < 0 && this.altColor ? this.altColor : posColor; 58956 const color = typeof c === "function" ? c(f.value) : c; 58957 58958 if (this.graphType === "points") { 58959 const pointSize = this.config.pointSize || 3; 58960 const px = x + width / 2; 58961 IGVGraphics.fillCircle(ctx, px, y, pointSize / 2, { 58962 "fillStyle": color, 58963 "strokeStyle": color 58964 }); 58965 } else { 58966 let height = y - y0; 58967 58968 if (Math.abs(height) < 1) { 58969 height = height < 0 ? -1 : 1; 58970 } 58971 58972 const pixelEnd = x + width; 58973 58974 if (pixelEnd > lastPixelEnd || f.value >= 0 && f.value > lastValue || f.value < 0 && f.value < lastNegValue) { 58975 IGVGraphics.fillRect(ctx, x, y0, width, height, { 58976 fillStyle: color 58977 }); 58978 } 58979 58980 lastValue = f.value; 58981 lastPixelEnd = pixelEnd; 58982 } 58983 } // If the track includes negative values draw a baseline 58984 58985 58986 if (this.dataRange.min < 0) { 58987 const basepx = this.dataRange.max / (this.dataRange.max - this.dataRange.min) * options.pixelHeight; 58988 IGVGraphics.strokeLine(ctx, 0, basepx, options.pixelWidth, basepx, { 58989 strokeStyle: baselineColor 58990 }); 58991 } 58992 } 58993 } // Draw guidelines 58994 58995 58996 if (this.config.hasOwnProperty('guideLines')) { 58997 for (let line of this.config.guideLines) { 58998 if (line.hasOwnProperty('color') && line.hasOwnProperty('y') && line.hasOwnProperty('dotted')) { 58999 let y = yScale(line.y); 59000 let props = { 59001 'strokeStyle': line['color'], 59002 'strokeWidth': 2 59003 }; 59004 if (line['dotted']) IGVGraphics.dashedLine(options.context, 0, y, options.pixelWidth, y, 5, props);else IGVGraphics.strokeLine(options.context, 0, y, options.pixelWidth, y, props); 59005 } 59006 } 59007 } 59008 } 59009 59010 popupData(clickState, features) { 59011 // We use the featureCache property rather than method to avoid async load. If the 59012 // feature is not already loaded this won't work, but the user wouldn't be mousing over it either. 59013 features = this.clickedFeatures(clickState, features); 59014 59015 if (features && features.length > 0) { 59016 const genomicLocation = clickState.genomicLocation; 59017 const popupData = []; // Sort features based on distance from click 59018 59019 features.sort(function (a, b) { 59020 const distA = Math.abs((a.start + a.end) / 2 - genomicLocation); 59021 const distB = Math.abs((b.start + b.end) / 2 - genomicLocation); 59022 return distA - distB; 59023 }); // Display closest 10 59024 59025 const displayFeatures = features.length > 10 ? features.slice(0, 10) : features; // Resort in ascending order 59026 59027 displayFeatures.sort(function (a, b) { 59028 return a.start - b.start; 59029 }); 59030 59031 for (let selectedFeature of displayFeatures) { 59032 if (selectedFeature) { 59033 if (popupData.length > 0) { 59034 popupData.push('<hr/>'); 59035 } 59036 59037 let posString = selectedFeature.end - selectedFeature.start === 1 ? numberFormatter$1(selectedFeature.start + 1) : numberFormatter$1(selectedFeature.start + 1) + "-" + numberFormatter$1(selectedFeature.end
59037); 59038 popupData.push({ 59039 name: "Position:", 59040 value: posString 59041 }); 59042 popupData.push({ 59043 name: "Value: ", 59044 value: numberFormatter$1(selectedFeature.value) 59045 }); 59046 } 59047 } 59048 59049 if (displayFeatures.length < features.length) { 59050 popupData.push("<hr/>..."); 59051 } 59052 59053 return popupData; 59054 } else { 59055 return []; 59056 } 59057 } 59058 59059 supportsWholeGenome() { 59060 return !this.config.indexURL && this.config.supportsWholeGenome !== false; 59061 } 59062 /** 59063 * Called when the track is removed. Do any needed cleanup here 59064 */ 59065 59066 59067 dispose() { 59068 this.trackView = undefined; 59069 } 59070 59071 } 59072 59073 /** 59074 * 59075 * @param cs - object containing 59076 * 1) array of threshold values defining bin boundaries in ascending order 59077 * 2) array of colors for bins (length == thresholds.length + 1) 59078 * @constructor 59079 */ 59080 function BinnedColorScale(cs) { 59081 this.thresholds = cs.thresholds; 59082 this.colors = cs.colors; 59083 } 59084 59085 BinnedColorScale.prototype.getColor = function (value) { 59086 for (let threshold of this.thresholds) { 59087 if (value < threshold) { 59088 return this.colors[this.thresholds.indexOf(threshold)]; 59089 } 59090 } 59091 59092 return this.colors[this.colors.length - 1]; 59093 }; 59094 /** 59095 * 59096 * @param scale - object with the following properties 59097 * low 59098 * lowR 59099 * lowG 59100 * lowB 59101 * high 59102 * highR 59103 * highG 59104 * highB 59105 * 59106 * @constructor 59107 */ 59108 59109 59110 function GradientColorScale(scale) { 59111 this.scale = scale; 59112 this.lowColor = "rgb(" + scale.lowR + "," + scale.lowG + "," + scale.lowB + ")"; 59113 this.highColor = "rgb(" + scale.highR + "," + scale.highG + "," + scale.highB + ")"; 59114 this.diff = scale.high - scale.low; 59115 } 59116 59117 GradientColorScale.prototype.getColor = function (value) { 59118 var scale = this.scale, 59119 r, 59120 g, 59121 b, 59122 frac; 59123 if (value <= scale.low) return this.lowColor;else if (value >= scale.high) return this.highColor; 59124 frac = (value - scale.low) / this.diff; 59125 r = Math.floor(scale.lowR + frac * (scale.highR - scale.lowR)); 59126 g = Math.floor(scale.lowG + frac * (scale.highG - scale.lowG)); 59127 b = Math.floor(scale.lowB + frac * (scale.highB - scale.lowB)); 59128 return "rgb(" + r + "," + g + "," + b + ")"; 59129 }; 59130 59131 class ConstantColorScale { 59132 constructor(color) { 59133 this.color = color; 59134 } 59135 59136 getColor() { 59137 return this.color; 59138 } 59139 59140 } 59141 59142 /* 59143 * The MIT License (MIT) 59144 * 59145 * Copyright (c) 2014 Broad Institute 59146 * 59147 * Permission is hereby granted, free of charge, to any person obtaining a copy 59148 * of this software and associated documentation files (the "Software"), to deal 59149 * in the Software without restriction, including without limitation the rights 59150 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 59151 * copies of the Software, and to permit persons to whom the Software is 59152 * furnished to do so, subject to the following conditions: 59153 * 59154 * The above copyright notice and this permission notice shall be included in 59155 * all copies or substantial portions of the Software. 59156 * 59157 * 59158 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 59159 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 59160 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 59161 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 59162 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 59163 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 59164 * THE SOFTWARE. 59165 */ 59166 59167 class SegTrack extends TrackBase { 59168 constructor(config, browser) { 59169 super(config, browser); 59170 } 59171 59172 init(config) { 59173 super.init(config); 59174 this.type = config.type || "seg";
59175 if (this.type === 'maf') this.type = 'mut'; 59176 this.isLog = config.isLog; 59177 this.displayMode = config.displayMode || "EXPANDED"; // EXPANDED | SQUISHED 59178 59179 this.height = config.height || 300; 59180 this.maxHeight = config.maxHeight || 500; 59181 this.squishedRowHeight = config.sampleSquishHeight || config.squishedRowHeight || 2; 59182 this.expandedRowHeight = config.sampleExpandHeight || config.expandedRowHeight || 13; 59183 this.sampleHeight = this.squishedRowHeight; // Initial value, will get overwritten when rendered 59184 59185 if (config.color) { 59186 this.color = config.color; 59187 } else { 59188 // Color scales for "seg" (copy number) tracks. 59189 this.posColorScale = config.posColorScale || new GradientColorScale({ 59190 low: 0.1, 59191 lowR: 255, 59192 lowG: 255, 59193 lowB: 255, 59194 high: 1.5, 59195 highR: 255, 59196 highG: 0, 59197 highB: 0 59198 }); 59199 this.negColorScale = config.negColorScale || new GradientColorScale({ 59200 low: -1.5, 59201 lowR: 0, 59202 lowG: 0, 59203 lowB: 255, 59204 high: -0.1, 59205 highR: 255, 59206 highG: 255, 59207 highB: 255 59208 }); // Default color table for mutation (mut and maf) tracks 59209 59210 if (this.type === "mut") { 59211 this.colorTable = new ColorTable(config.colorTable || MUT_COLORS); 59212 } 59213 } 59214 59215 this.sampleKeys = []; 59216 this.sampleNames = new Map(); 59217 59218 if (config.samples) { 59219 // Explicit setting, keys == names 59220 for (let s of config.samples) { 59221 this.sampleKeys.push(s); 59222 this.sampleNames.set(s, s); 59223 } 59224 59225 this.explicitSamples = true; 59226 } // this.featureSource = config.sourceType === "bigquery" ? 59227 // new igv.BigQueryFeatureSource(this.config) : 59228 59229 59230 this.featureSource = FeatureSource(this.config, this.browser.genome); 59231 this.initialSort = config.sort; 59232 } 59233 59234 async postInit() { 59235 if (typeof this.featureSource.getHeader === "function") { 59236 this.header = await this.featureSource.getHeader(); 59237 } // Set properties from track line 59238 59239 59240 if (this.header) { 59241 this.setTrackProperties(this.header); 59242 } 59243 } 59244 59245 menuItemList() { 59246 const menuItems = []; 59247 const lut = { 59248 "SQUISHED": "Squish", 59249 "EXPANDED": "Expand", 59250 "FILL": "Fill" 59251 }; 59252 menuItems.push('<hr/>'); 59253 menuItems.push("DisplayMode:"); 59254 const displayOptions = this.type === 'seg' ? ["SQUISHED", "EXPANDED", "FILL"] : ["SQUISHED", "EXPANDED"]; 59255 59256 for (let displayMode of displayOptions) { 59257 const checkBox = createCheckbox$1(lut[displayMode], displayMode === this.displayMode); 59258 menuItems.push({ 59259 object: $$1(checkBox), 59260 click: () => { 59261 this.displayMode = displayMode; 59262 this.config.displayMode = displayMode; 59263 this.trackView.checkContentHeight(); 59264 this.trackView.repaintViews(); 59265 this.trackView.moveScroller(this.trackView.sampleNameViewport.trackScrollDelta); 59266 } 59267 }); 59268 } 59269 59270 return menuItems; 59271 } 59272 59273 hasSamples() { 59274 return true; // SEG, MUT, and MAF tracks have samples by definition 59275 } 59276 59277 getSamples() { 59278 return { 59279 names: this.sampleKeys.map(key => this.sampleNames.get(key)), 59280 height: this.sampleHeight, 59281 yOffset: 0 59282 }; 59283 } 59284 59285 async getFeatures(chr, start, end) { 59286 const features = await this.featureSource.getFeatures({ 59287 chr, 59288 start, 59289 end 59290 }); 59291 59292 if (this.initialSort) { 59293 const sort = this.initialSort; 59294 this.sortSamples(sort.chr, sort.start, sort.end, sort.direction, features); 59295 this.initialSort = undefined; // Sample order is sorted, 59296 } 59297 59298 return features; 59299 } 59300 59301 draw(_ref) { 59302 let { 59303 context, 59304 renderSVG, 59305 pixelTop, 59306 pixelWidth, 59307 pixelHeight, 59308 features, 59309 bpPerPixel, 59310 bpStart 59311 } = _ref; 59312 IGVGraphics.fillRect(context, 0, 0, pixelWidth, pixelHeight, { 59313 'fillStyle': "rgb(255, 255, 255)" 59314 }); 59315 59316 if (features && features.length > 0) { 59317 this.checkForLog(features); // New segments could conceivably add new samples 59318 59319 this.updateSampleKeys(features); // Create a map for fast id -> row lookup 59320 59321 const samples = {}; 59322 this.sampleKeys.forEach(function (id, index) { 59323 samples[id] = index; 59324 }); 59325 let border; 59326 59327 switch (this.displayMode) { 59328 case "FILL": 59329 this.sampleHeight = pixelHeight / this.sampleKeys.length; 59330 border = 0; 59331 break; 59332 59333 case "SQUISHED": 59334 this.sampleHeight = this.squishedRowHeight; 59335 border = 0; 59336 break; 59337 59338 default: 59339 // EXPANDED 59340 this.sampleHeight = this.expandedRowHeight; 59341 border = 1; 59342 } 59343 59344 const rowHeight = this.sampleHeight; // this.featureMap = new Map() 59345 59346 for (let segment of features) { 59347 segment.pixelRect = undefined; // !important, reset this in case segment is not drawn 59348 } 59349 59350 const pixelBottom = pixelTop + pixelHeight; 59351 const bpEnd = bpStart + pixelWidth * bpPerPixel + 1; 59352 const xScale = bpPerPixel; 59353 this.sampleYStart = undefined; 59354 59355 for (let f of features) { 59356 if (f.end < bpStart) continue; 59357 if (f.start > bpEnd) break; 59358 const sampleKey = f.sampleKey || f.sample; 59359 f.row = samples[sampleKey]; 59360 const y = f.row * rowHeight + border; 59361 59362 if (undefined === this.sampleYStart) { 59363 this.sampleYStart = y; 59364 } 59365 59366 const bottom = y + rowHeight; 59367 59368 if (bottom < pixelTop || y > pixelBottom) { 59369 continue; 59370 } 59371 59372 const segmentStart = Math.max(f.start, bpStart); // const segmentStart = segment.start; 59373 59374 let x = Math.round((segmentStart - bpStart) / xScale); 59375 const segmentEnd = Math.min(f.end, bpEnd); // const segmentEnd = segment.end; 59376 59377 const x1 = Math.round((segmentEnd - bpStart) / xScale); 59378 let w = Math.max(1, x1 - x); 59379 let color; 59380 59381 if (this.color) { 59382 if (typeof this.color === "function") { 59383 color = this.color(f); 59384 } else { 59385 color = this.color; 59386 } 59387 } else if (this.colorTable) { 59388 color = this.colorTable.getColor(f.value.toLowerCase()); 59389 } 59390 59391 let h; 59392 59393 if ("mut" === this.type) { 59394 h = rowHeight - 2 * border; 59395 59396 if (w < 3) { 59397 w = 3; 59398 x -= 1; 59399 } 59400 } else { 59401 // Assume seg track 59402 let value = f.value; 59403 59404 if (!this.isLog) { 59405 value = IGVMath.log2(value / 2); 59406 } 59407 59408 if (value < -0.1) { 59409 color = this.negColorScale.getColor(value); 59410 } else if (value > 0.1) { 59411 color = this.posColorScale.getColor(value); 59412 } else { 59413 color = "white"; 59414 } 59415 59416 let sh = rowHeight; 59417 59418 if (rowHeight < 0.25) { 59419 const f = 0.1 + 2 * Math.abs(value); 59420 sh = Math.min(1, f * rowHeight); 59421 } 59422 59423 h = sh - 2 * border; 59424 } 59425 59426 f.pixelRect = { 59427 x, 59428 y, 59429 w, 59430 h 59431 }; // Use for diagnostic rendering 59432 // context.fillStyle = randomRGB(180, 240) 59433 // context.fillStyle = randomGrey(200, 255) 59434 59435 context.fillStyle = color; 59436 context.fillRect(x, y, w, h); 59437 } 59438 } 59439 } 59440 59441 checkForLog(features) { 59442 if (this.isLog === undefined) { 59443 this.isLog = false;
59444 59445 for (let feature of features) { 59446 if (feature.value < 0) { 59447 this.isLog = true; 59448 return; 59449 } 59450 } 59451 } 59452 } 59453 /** 59454 * Optional method to compute pixel height to accomodate the list of features. The implementation below 59455 * has side effects (modifiying the samples hash). This is unfortunate, but harmless. 59456 * 59457 * Note displayMode "FILL" is handled by the viewport 59458 * 59459 * @param features 59460 * @returns {number} 59461 */ 59462 59463 59464 computePixelHeight(features) { 59465 if (!features) return 0; 59466 const sampleHeight = "SQUISHED" === this.displayMode ? this.squishedRowHeight : this.expandedRowHeight; 59467 this.updateSampleKeys(features); 59468 return this.sampleKeys.length * sampleHeight; 59469 } 59470 /** 59471 * Sort samples by the average value over the genomic range in the direction indicated (1 = ascending, -1 descending) 59472 */ 59473 59474 59475 async sortSamples(chr, start, end, direction, featureList) { 59476 if (!featureList) { 59477 featureList = await this.featureSource.getFeatures({ 59478 chr, 59479 start, 59480 end 59481 }); 59482 } 59483 59484 if (!featureList) return; 59485 this.updateSampleKeys(featureList); 59486 const scores = {}; 59487 const d2 = direction === "ASC" ? 1 : -1; 59488 59489 const sortSeg = () => { 59490 // Compute weighted average score for each sample 59491 const bpLength = end - start + 1; 59492 59493 for (let segment of featureList) { 59494 if (segment.end < start) continue; 59495 if (segment.start > end) break; 59496 const min = Math.max(start, segment.start); 59497 const max = Math.min(end, segment.end); 59498 const f = (max - min) / bpLength; 59499 const sampleKey = segment.sampleKey || segment.sample; 59500 const s = scores[sampleKey] || 0; 59501 scores[sampleKey] = s + f * segment.value; 59502 } // Now sort sample names by score 59503 59504 59505 this.sampleKeys.sort(function (a, b) { 59506 let s1 = scores[a]; 59507 let s2 = scores[b]; 59508 if (!s1) s1 = d2 * Number.MAX_VALUE; 59509 if (!s2) s2 = d2 * Number.MAX_VALUE; 59510 if (s1 === s2) return 0;else if (s1 > s2) return d2;else return d2 * -1; 59511 }); 59512 }; 59513 59514 const sortMut = () => { 59515 // Compute weighted average score for each sample 59516 for (let segment of featureList) { 59517 if (segment.end < start) continue; 59518 if (segment.start > end) break; 59519 const sampleKey = segment.sampleKey || segment.sample; 59520 59521 if (!scores.hasOwnProperty(sampleKey) || segment.value.localeCompare(scores[sampleKey]) > 0) { 59522 scores[sampleKey] = segment.value; 59523 } 59524 } // Now sort sample names by score 59525 59526 59527 this.sampleKeys.sort(function (a, b) { 59528 let sa = scores[a] || ""; 59529 let sb = scores[b] || ""; 59530 return d2 * sa.localeCompare(sb); 59531 }); 59532 }; 59533 59534 if ("mut" === this.type) { 59535 sortMut(); 59536 } else { 59537 sortSeg(); 59538 } 59539 59540 this.trackView.repaintViews(); 59541 } 59542 59543 clickedFeatures(clickState, features) { 59544 const allFeatures = super.clickedFeatures(clickState, features); 59545 const y = clickState.y; 59546 return allFeatures.filter(function (feature) { 59547 const rect = feature.pixelRect; 59548 return rect && y >= rect.y && y <= rect.y + rect.h; 59549 }); 59550 } 59551 59552 popupData(clickState, featureList) { 59553 featureList = this.clickedFeatures(clickState); 59554 const items = []; 59555 59556 for (let feature of featureList) { 59557 // Double line divider between features 59558 if (items.length > 0) { 59559 items.push('<hr/>'); 59560 items.push('<hr/>'); 59561 } // hack for whole genome features, which save the original feature as "_f" 59562 59563 59564 const f = feature._f || feature; 59565 const data = typeof f.popupData === 'function' ? f.popupData(this.type, this.browser.genome.id) : this.extractPopupData(f); 59566 Array.prototype.push.apply(items, data); 59567 } 59568 59569 return items; 59570 } 59571 59572 contextMenuItemList(clickState) { 59573 const referenceFrame = clickState.viewport.referenceFrame; 59574 const genomicLocation = clickState.genomicLocation; // Define a region 5 "pixels" wide in genomic coordinates 59575 59576 const sortDirection = this.config.sort ? this.config.sort.direction === "ASC" ? "DESC" : "ASC" : // Toggle from previous sort 59577 "DESC"; 59578 const bpWidth = referenceFrame.toBP(2.5); 59579 59580 const sortHandler = sort => { 59581 const viewport = clickState.viewport; 59582 const features = viewport.getCachedFeatures(); 59583 this.sortSamples(sort.chr, sort.start, sort.end, sort.direction, features); 59584 }; 59585
59586 const sortLabel = this.type === 'seg' ? 'Sort by value' : 'Sort by type'; 59587 return [{ 59588 label: sortLabel, 59589 click: e => { 59590 const sort = { 59591 direction: sortDirection, 59592 chr: clickState.viewport.referenceFrame.chr, 59593 start: genomicLocation - bpWidth, 59594 end: genomicLocation + bpWidth 59595 }; 59596 sortHandler(sort); 59597 this.config.sort = sort; 59598 } 59599 }]; 59600 } 59601 59602 supportsWholeGenome() { 59603 return (this.config.indexed === false || !this.config.indexURL) && this.config.supportsWholeGenome !== false; 59604 } 59605 59606 updateSampleKeys(featureList) { 59607 if (this.explicitSamples) return; 59608 59609 for (let feature of featureList) { 59610 const sampleKey = feature.sampleKey || feature.sample; 59611 59612 if (!this.sampleNames.has(sampleKey)) { 59613 this.sampleNames.set(sampleKey, feature.sample); 59614 this.sampleKeys.push(sampleKey); 59615 } 59616 } 59617 } 59618 59619 } // Mut and MAF file default color table 59620 59621 59622 const MUT_COLORS = { 59623 "indel": "rgb(0,200,0)", 59624 "targeted region": "rgb(236,155,43)", 59625 "truncating": "rgb( 150,0,0)", 59626 "non-coding transcript": "rgb(0,0,150)", 59627 // Colors from https://www.nature.com/articles/nature11404 59628 "synonymous": "rgb(109,165,95)", 59629 "silent": "rgb(109,135,80)", 59630 "missense_mutation": "rgb(72,130,187)", 59631 "missense": "rgb(72,130,187)", 59632 "splice site": "rgb(143,83,155)", 59633 "splice_region": "rgb(143,83,155)", 59634 "nonsense": "rgb(216, 57,81)", 59635 "nonsense_mutation": "rgb(216, 57,81)", 59636 "frame_shift_del": "rgb(226,135,65)", 59637 "frame_shift_ins": "rgb(226,135,65)", 59638 "in_frame_del": "rgb(247,235,94)", 59639 "in_frame_ins": "rgb(247,235,94)", 59640 "*other*": "rgb(159,91,50)" // 59641 // 3'Flank 59642 // 3'UTR 59643 // 5'Flank 59644 // 5'UTR 59645 // Frame_Shift_Del 59646 // Frame_Shift_Ins 59647 // IGR 59648 // In_Frame_Del 59649 // In_Frame_Ins 59650 // Intron 59651 // Missense_Mutation 59652 // Nonsense_Mutation 59653 // Nonstop_Mutation 59654 // RNA 59655 // Silent 59656 // Splice_Region 59657 // Splice_Site 59658 // Translation_Start_Site 59659 // Variant_Classification 59660 59661 }; 59662 59663 /* 59664 * The MIT License (MIT) 59665 * 59666 * Copyright (c) 2016-2017 The Regents of the University of California 59667 * Author: Jim Robinson 59668 * 59669 * Permission is hereby granted, free of charge, to any person obtaining a copy 59670 * of this software and associated documentation files (the "Software"), to deal 59671 * in the Software without restriction, including without limitation the rights 59672 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 59673 * copies of the Software, and to permit persons to whom the Software is 59674 * furnished to do so, subject to the following conditions: 59675 * 59676 * The above copyright notice and this permission notice shall be included in 59677 * all copies or substantial portions of the Software. 59678 * 59679 * 59680 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 59681 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 59682 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 59683 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 59684 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 59685 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 59686 * THE SOFTWARE. 59687 */ 59688 59689 class MergedTrack extends TrackBase { 59690 constructor(config, browser) { 59691 super(config, browser); 59692 } 59693 59694 init(config) { 59695 if (!config.tracks) { 59696 throw Error("Error: no tracks defined for merged track" + config); 59697 } 59698 59699 super.init(config); 59700 } 59701 59702 get height() { 59703 return this._height; 59704 } 59705 59706 set height(h) { 59707 this._height = h; 59708 59709 if (this.tracks) { 59710 for (let t of this.tracks) { 59711 t.height = h; 59712 t.config.height = h; 59713 } 59714 } 59715 } 59716 59717 async postInit() { 59718 this.tracks = []; 59719 const p = []; 59720 59721 for (let tconf of this.config.tracks) { 59722 tconf.isMergedTrack = true; 59723 const t = await this.browser.createTrack(tconf); 59724 59725 if (t) { 59726 t.autoscale = false; // Scaling done from merged track 59727 59728 this.tracks.push(t); 59729 } else { 59730 console.warn("Could not create track " + tconf); 59731 } 59732 59733 if (typeof t.postInit === 'function') { 59734 p.push(t.postInit()); 59735 } 59736 } 59737 59738 this.height = this.config.height || 100; 59739 return Promise.all(p); 59740 } 59741 59742 async getFeatures(chr, bpStart, bpEnd, bpPerPixel) { 59743 const promises = this.tracks.map(t => t.getFeatures(chr, bpStart, bpEnd, bpPerPixel)); 59744 return Promise.all(promises); 59745 } 59746 59747 draw(options) { 59748 var i, len, mergedFeatures, trackOptions, dataRange; 59749 mergedFeatures = options.features; // Array of feature arrays, 1 for each track 59750 59751 dataRange = autoscale(options.referenceFrame.chr, mergedFeatures); //IGVGraphics.fillRect(options.context, 0, options.pixelTop, options.pixelWidth, options.pixelHeight, {'fillStyle': "rgb(255, 255, 255)"}); 59752 59753 for (i = 0, len = this.tracks.length; i < len; i++) { 59754 trackOptions = Object.assign({}, options); 59755 trackOptions.features = mergedFeatures[i]; 59756 this.tracks[i].dataRange = dataRange; 59757 this.tracks[i].draw(trackOptions); 59758 } 59759 } 59760 59761 paintAxis(ctx, pixelWidth, pixelHeight) { 59762 var i, len, autoscale, track; 59763 autoscale = true; // Hardcoded for now 59764 59765 for (i = 0, len = this.tracks.length; i < len; i++) { 59766 track = this.tracks[i]; 59767 59768 if (typeof track.paintAxis === 'function') { 59769 track.paintAxis(ctx, pixelWidth, pixelHeight); 59770 if (autoscale) break; 59771 } 59772 } 59773 } 59774 59775 popupData(clickState, features) { 59776 const featuresArray = features || clickState.viewport.getCachedFeatures(); 59777 59778 if (featuresArray && featuresArray.length === this.tracks.length) { 59779 // Array of feature arrays, 1 for each track 59780 const popupData = []; 59781 59782 for (let i = 0; i < this.tracks.length; i++) { 59783 if (i > 0) popupData.push('<hr/>'); 59784 popupData.push(`<div style=background-color:rgb(245,245,245);border-bottom-style:dashed;border-bottom-width:1px;padding-bottom:5px;padding-top:10px;font-weight:bold;font-size:larger >${this.tracks[i].name}</div>`); 59785 const trackPopupData = this.tracks[i].popupData(clickState, featuresArray[i]); 59786 popupData.push(...trackPopupData); 59787 } 59788 59789 return popupData; 59790 } 59791 } 59792 59793 supportsWholeGenome() { 59794 const b = this.tracks.every(track => track.supportsWholeGenome()); 59795 return b; 59796 } 59797 59798 } 59799 59800 function autoscale(chr, featureArrays) { 59801 var min = 0, 59802 max = -Number.MAX_VALUE; 59803 // if (chr === 'all') { 59804 // allValues = []; 59805 // featureArrays.forEach(function (features) {
59806 // features.forEach(function (f) { 59807 // if (!Number.isNaN(f.value)) { 59808 // allValues.push(f.value); 59809 // } 59810 // }); 59811 // }); 59812 // 59813 // min = Math.min(0, IGVMath.percentile(allValues, .1)); 59814 // max = IGVMath.percentile(allValues, 99.9); 59815 // 59816 // } 59817 // else { 59818 59819 featureArrays.forEach(function (features, i) { 59820 features.forEach(function (f) { 59821 if (typeof f.value !== 'undefined' && !Number.isNaN(f.value)) { 59822 min = Math.min(min, f.value); 59823 max = Math.max(max, f.value); 59824 } 59825 }); 59826 }); // } 59827 59828 return { 59829 min: min, 59830 max: max 59831 }; 59832 } 59833 59834 /* 59835 * The MIT License (MIT) 59836 * 59837 * Copyright (c) 2016-2018 The Regents of the University of California 59838 * Author: Jim Robinson 59839 * 59840 * Permission is hereby granted, free of charge, to any person obtaining a copy 59841 * of this software and associated documentation files (the "Software"), to deal 59842 * in the Software without restriction, including without limitation the rights 59843 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 59844 * copies of the Software, and to permit persons to whom the Software is 59845 * furnished to do so, subject to the following conditions: 59846 * 59847 * The above copyright notice and this permission notice shall be included in 59848 * all copies or substantial portions of the Software. 59849 * 59850 * 59851 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 59852 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 59853 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 59854 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 59855 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 59856 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 59857 * THE SOFTWARE. 59858 */ 59859 59860 class InteractionTrack extends TrackBase { 59861 constructor(config, browser) { 59862 super(config, browser); 59863 } 59864 59865 init(config) { 59866 super.init(config); 59867 this.theta = config.theta || Math.PI / 4; 59868 this.sinTheta = Math.sin(this.theta); 59869 this.cosTheta = Math.cos(this.theta); 59870 this.height = config.height || 250; 59871 this.arcType = config.arcType || "nested"; // nested | proportional 59872 59873 this.arcOrientation = config.arcOrientation === undefined ? true : config.arcOrientation; // true for up, false for down 59874 59875 this.showBlocks = config.showBlocks === undefined ? true : config.showBlocks; 59876 this.blockHeight = config.blockHeight || 3; 59877 this.thickness = config.thickness || 1; 59878 this.color = config.color || "rgb(180,25,137)"; 59879 this.alpha = config.alpha || 0.15; 59880 59881 if (config.valueColumn) { 59882 this.valueColumn = config.valueColumn; 59883 this.hasValue = true; 59884 } else if (config.useScore) { 59885 this.hasValue = true; 59886 this.valueColumn = "score"; 59887 } 59888 59889 this.logScale = config.logScale !== false; // i.e. defaul to true (undefined => true) 59890 59891 if (config.max) { 59892 this.dataRange = { 59893 min: config.min || 0, 59894 max: config.max 59895 }; 59896 this.autoscale = false; 59897 } else { 59898 this.autoscale = true; 59899 } // Create the FeatureSource and override the default whole genome method 59900 59901 59902 this.featureSource = FeatureSource(config, this.browser.genome); 59903 this.featureSource.getWGFeatures = getWGFeatures; 59904 } 59905 59906 async postInit() { 59907 if (typeof this.featureSource.getHeader === "function") { 59908 this.header = await this.featureSource.getHeader(); 59909 } // Set properties from track line 59910 59911 59912 if (this.header) { 59913 this.setTrackProperties(this.header); 59914 } 59915 59916 if (this.visibilityWindow === undefined && typeof this.featureSource.defaultVisibilityWindow === 'function') { 59917 this.visibilityWindow = await this.featureSource.defaultVisibilityWindow(); 59918 this.featureSource.visibilityWindow = this.visibilityWindow; // <- this looks odd 59919 } 59920 59921 return this; 59922 } 59923 59924 supportsWholeGenome() { 59925 return true; 59926 } 59927 59928 async getFeatures(chr, start, end) { 59929 const visibilityWindow = this.visibilityWindow; 59930 const features = await this.featureSource.getFeatures({ 59931 chr, 59932 start, 59933 end, 59934 visibilityWindow 59935 }); // Check for score or value 59936 59937 if (this.hasValue === undefined && features && features.length > 0) { 59938 this.hasValue = features[0].score !== undefined; 59939 } 59940 59941 return features; 59942 } 59943 59944 draw(options) { 59945 if (this.arcType === "proportional") { 59946 this.drawProportional(options); 59947 } else { 59948 this.drawNested(options); 59949 } 59950 } 59951 59952 drawNested(options) { 59953 const ctx = options.context; 59954 const pixelWidth = options.pixelWidth; 59955 const pixelHeight = options.pixelHeight; 59956 const viewportWidth = options.viewportWidth; 59957 const bpPerPixel = options.bpPerPixel; 59958 const bpStart = options.bpStart; 59959 const xScale = bpPerPixel; 59960 IGVGraphics.fillRect(ctx, 0, options.pixelTop, pixelWidth, pixelHeight, { 59961 'fillStyle': "rgb(255, 255, 255)" 59962 }); 59963 const featureList = options.features; 59964 59965 if (featureList) { 59966 // Autoscale theta 59967 autoscaleNested.call(this); 59968 const y = this.arcOrientation ? options.pixelHeight : 0; 59969 const direction = this.arcOrientation; 59970 ctx.font = "8px sans-serif"; 59971 ctx.textAlign = "center"; 59972 59973 for (let feature of featureList) { 59974 let color = feature.color || this.color; 59975 59976 if (color && this.config.useScore) { 59977 color = getAlphaColor(color, scoreShade(feature.score)); 59978 } 59979 59980 ctx.lineWidth = feature.thickness || this.thickness || 1; 59981 59982 if (feature.chr1 === feature.chr2 || feature.chr === 'all') { 59983 const { 59984 m1, 59985 m2 59986 } = getMidpoints(feature, this.browser.genome); 59987 let pixelStart = Math.round((m1 - bpStart) / xScale); 59988 let pixelEnd = Math.round((m2 - bpStart) / xScale); 59989 if (pixelEnd < 0 || pixelStart > pixelWidth) continue; 59990 let w = pixelEnd - pixelStart; 59991 59992 if (w < 3) { 59993 w = 3; 59994 pixelStart--; 59995 } 59996 59997 const a = w / 2; 59998 const r = a / this.sinTheta; 59999 const b = this.cosTheta * r; 60000 const xc = pixelStart + a; 60001 let yc, startAngle, endAngle; 60002 60003 if (direction) { 60004 // UP 60005 yc = this.height + b; 60006 startAngle = Math.PI + Math.PI / 2 - this.theta; 60007 endAngle = Math.PI + Math.PI / 2 + this.theta; 60008 } else { 60009 // DOWN 60010 yc = -b; 60011 startAngle = Math.PI / 2 - this.theta; 60012 endAngle = Math.PI / 2 + this.theta; 60013 } 60014 60015 if (this.showBlocks && feature.chr !== 'all') { 60016 const s1 = (feature.start1 - bpStart) / xScale; 60017 const e1 = (feature.end1 - bpStart) / xScale; 60018 const s2 = (feature.start2 - bpStart) / xScale; 60019 const e2 = (feature.end2 - bpStart) / xScale; 60020 const hb = this.arcOrientation ? -this.blockHeight : this.blockHeight; 60021 ctx.fillRect(s1, y, e1 - s1, hb); 60022 ctx.fillRect(s2, y, e2 - s2, hb); 60023 } // Alpha shade (de-emphasize) arcs that extend beyond viewport, unless alpha shading is used for score. 60024 60025 60026 if (color && !this.config.useScore && w > viewportWidth) { 60027 color = getAlphaColor(color, this.alpha); 60028 } 60029 60030 ctx.strokeStyle = color; 60031 ctx.fillStyle = color; 60032 ctx.beginPath(); 60033 ctx.arc(xc, yc, r, startAngle, endAngle, false); 60034 ctx.stroke(); 60035 feature.drawState = { 60036 xc, 60037 yc, 60038 r 60039 }; 60040 } else { 60041 let pixelStart = Math.round((feature.start - bpStart) / xScale); 60042 let pixelEnd = Math.round((feature.end - bpStart) / xScale); 60043 if (pixelEnd < 0 || pixelStart > pixelWidth) continue; 60044 let w = pixelEnd - pixelStart; 60045 60046 if (w < 3) { 60047 w = 3; 60048 pixelStart--; 60049 } 60050 60051 const otherChr = feature.chr === feature.chr1 ? feature.chr2 : feature.chr1; 60052 ctx.strokeStyle = color; 60053 ctx.fillStyle = color; 60054 60055 if (direction) { 60056 // UP 60057 ctx.fillRect(pixelStart, this.height / 2, w, this.height / 2); 60058 ctx.fillText(otherChr, pixelStart + w / 2, this.height / 2 - 5); 60059 feature.drawState = { 60060 x: pixelStart, 60061 y: this.height / 2, 60062 w: w, 60063 h: this.height / 2 60064 }; 60065 } else { 60066 ctx.fillRect(pixelStart, 0, w, this.height / 2); 60067 ctx.fillText(otherChr, pixelStart + w / 2, this.height / 2 + 13); 60068 feature.drawState = { 60069 x: pixelStart, 60070 y: 0, 60071 w: w, 60072 h: this.height / 2 60073 }; 60074 } 60075 } 60076 } 60077 } 60078 60079 function autoscaleNested() { 60080 let max = 0; 60081 60082 for (let feature of featureList) { 60083 let pixelStart = (feature.start - bpStart) / xScale; 60084 let pixelEnd = (feature.end - bpStart) / xScale; 60085 60086 if (pixelEnd >= 0 && pixelStart <= pixelWidth) { 60087 max = Math.max(max, pixelEnd - pixelStart); 60088 } 60089 } 60090 60091 let a = Math.min(viewportWidth, max) / 2; 60092 60093 if (max > 0) { 60094 let coa = (pixelHeight - 10) / a; 60095 this.theta = estimateTheta(coa); 60096 this.sinTheta = Math.sin(this.theta); 60097 this.cosTheta = Math.cos(this.theta); 60098 } 60099 } 60100 } 60101 60102 drawProportional(options) { 60103 const ctx = options.context; 60104 const pixelWidth = options.pixelWidth; 60105 const pixelHeight = options.pixelHeight; 60106 const bpPerPixel = options.bpPerPixel; 60107 const bpStart = options.bpStart; 60108 const xScale = bpPerPixel; // SVG output for proportional arcs are currently not supported because "ellipse" is not implemented 60109 // if(typeof ctx.ellipse !== 'function') { 60110 // Alert.presentAlert("SVG output of proportional arcs is currently not supported.") 60111 // return; 60112 // } 60113 60114 IGVGraphics.fillRect(ctx, 0, options.pixelTop, pixelWidth, pixelHeight, { 60115 'fillStyle': "rgb(255, 255, 255)" 60116 }); 60117 const featureList = options.features; 60118 60119 if (featureList && featureList.length > 0) { 60120 const yScale = this.logScale ? options.pixelHeight / Math.log10(this.dataRange.max + 1) : options.pixelHeight / (this.dataRange.max - this.dataRange.min); 60121 const y = this.arcOrientation ? options.pixelHeight : 0; 60122 60123 for (let feature of featureList) { 60124 const value = this.valueColumn ? feature[this.valueColumn] : feature.score; 60125 if (value === undefined || Number.isNaN(value)) continue; 60126 const radiusY = this.logScale ? Math.log10(value + 1) * yScale : value * yScale; 60127 60128 if (feature.chr1 === feature.chr2 || feature.chr === 'all') { 60129 const { 60130 m1, 60131 m2 60132 } = getMidpoints(feature, this.browser.genome); 60133 let pixelStart = (m1 - bpStart) / xScale; 60134 let pixelEnd = (m2 - bpStart) / xScale; 60135 let w = pixelEnd - pixelStart; 60136 60137 if (w < 3) { 60138 w = 3; 60139 pixelStart--; 60140 } 60141 60142 if (pixelEnd < 0 || pixelStart > pixelWidth || value < this.dataRange.min) continue; 60143 const radiusX = w / 2; 60144 const xc = pixelStart + w / 2; 60145 const counterClockwise = this.arcOrientation ? true : false;
60146 const color = feature.color || this.color; 60147 ctx.strokeStyle = color; 60148 ctx.lineWidth = feature.thickness || this.thickness || 1; 60149 60150 if (true === ctx.isSVG) { 60151 ctx.strokeEllipse(xc, y, radiusX, radiusY, 0, 0, Math.PI, counterClockwise); 60152 } else { 60153 ctx.beginPath(); 60154 ctx.ellipse(xc, y, radiusX, radiusY, 0, 0, Math.PI, counterClockwise); 60155 ctx.stroke(); 60156 } 60157 60158 if (this.showBlocks && feature.chr !== 'all') { 60159 ctx.fillStyle = color; 60160 const s1 = (feature.start1 - bpStart) / xScale; 60161 const e1 = (feature.end1 - bpStart) / xScale; 60162 const s2 = (feature.start2 - bpStart) / xScale; 60163 const e2 = (feature.end2 - bpStart) / xScale; 60164 const hb = this.arcOrientation ? -this.blockHeight : this.blockHeight; 60165 ctx.fillRect(s1, y, e1 - s1, hb); 60166 ctx.fillRect(s2, y, e2 - s2, hb); 60167 } 60168 60169 if (this.alpha) { 60170 ctx.fillStyle = getAlphaColor(color, this.alpha); 60171 60172 if (true === ctx.isSVG) { 60173 ctx.fillEllipse(xc, y, radiusX, radiusY, 0, 0, Math.PI, counterClockwise); 60174 } else { 60175 ctx.fill(); 60176 } 60177 } 60178 60179 feature.drawState = { 60180 xc, 60181 yc: y, 60182 radiusX, 60183 radiusY 60184 }; 60185 } else { 60186 let pixelStart = Math.round((feature.start - bpStart) / xScale); 60187 let pixelEnd = Math.round((feature.end - bpStart) / xScale); 60188 if (pixelEnd < 0 || pixelStart > pixelWidth || value < this.dataRange.min) continue; 60189 const h = Math.min(radiusY, this.height - 13); // Leave room for text 60190 60191 let w = pixelEnd - pixelStart; 60192 60193 if (w < 3) { 60194 w = 3; 60195 pixelStart--; 60196 } 60197 60198 const otherChr = feature.chr === feature.chr1 ? feature.chr2 : feature.chr1; 60199 ctx.font = "8px sans-serif"; 60200 ctx.textAlign = "center"; 60201 60202 if (this.arcOrientation) { 60203 // UP 60204 const y = this.height - h; 60205 ctx.fillRect(pixelStart, y, w, h); 60206 ctx.fillText(otherChr, pixelStart + w / 2, y - 5); 60207 feature.drawState = { 60208 x: pixelStart, 60209 y, 60210 w, 60211 h 60212 }; 60213 } else { 60214 ctx.fillRect(pixelStart, 0, w, h); 60215 ctx.fillText(otherChr, pixelStart + w / 2, h + 13); 60216 feature.drawState = { 60217 x: pixelStart, 60218 y: 0, 60219 w, 60220 h 60221 }; 60222 } 60223 } 60224 } 60225 } 60226 } 60227 60228 menuItemList() { 60229 let items = [{ 60230 name: "Set track color", 60231 click: () => { 60232 this.trackView.presentColorPicker(); 60233 } 60234 }, '<hr/>']; 60235 60236 if (this.hasValue) { 60237 const lut = { 60238 "nested": "Nested Arcs", 60239 "proportional": "Proportional Arcs" 60240 }; 60241 60242 for (let arcType of ["nested", "proportional"]) { 60243 items.push({ 60244 object: $$1(createCheckbox$1(lut[arcType], arcType === this.arcType)), 60245 click: () => { 60246 this.arcType = arcType; 60247 this.trackView.repaintViews(); 60248 } 60249 }); 60250 } 60251 } 60252 60253 items.push({ 60254 object: $$1(createCheckbox$1("Show Blocks", this.showBlocks)), 60255 click: () => { 60256 this.showBlocks = !this.showBlocks; 60257 this.trackView.repaintViews(); 60258 } 60259 }); 60260 items.push({ 60261 name: "Toggle arc direction", 60262 click: () => { 60263 this.arcOrientation = !this.arcOrientation; 60264 this.trackView.repaintViews(); 60265 } 60266 }); 60267 60268 if (this.arcType === "proportional") { 60269 items.push("<HR>"); 60270 items = items.concat(MenuUtils.numericDataMenuItems(this.trackView)); 60271 } 60272
60273 if (this.browser.circularView && true === this.browser.circularViewVisible) { 60274 items.push({ 60275 label: 'Add interactions to circular view', 60276 click: () => { 60277 const inView = []; 60278 60279 for (let viewport of this.trackView.viewports) { 60280 const refFrame = viewport.referenceFrame; 60281 60282 for (let f of viewport.getCachedFeatures()) { 60283 if (f.end >= refFrame.start && f.start <= refFrame.end) { 60284 inView.push(f); 60285 } 60286 } 60287 } 60288 60289 const chords = makeBedPEChords(inView); 60290 const color = IGVColor.addAlpha(this.color, 0.5); 60291 this.browser.circularView.addChords(chords, { 60292 track: this.name, 60293 color: color 60294 }); 60295 } 60296 }); 60297 } 60298 60299 return items; 60300 } 60301 60302 contextMenuItemList(clickState) { 60303 // Experimental JBrowse feature 60304 if (this.browser.circularView && true === this.browser.circularViewVisible) { 60305 const viewport = clickState.viewport; 60306 const list = []; 60307 list.push({ 60308 label: 'Add interactions to circular view', 60309 click: () => { 60310 const refFrame = viewport.referenceFrame; 60311 const inView = "all" === refFrame.chr ? this.featureSource.getAllFeatures() : this.featureSource.featureCache.queryFeatures(refFrame.chr, refFrame.start, refFrame.end); 60312 this.browser.circularViewVisible = true; 60313 const chords = makeBedPEChords(inView); 60314 const color = IGVColor.addAlpha(this.color, 0.5); 60315 this.browser.circularView.addChords(chords, { 60316 track: this.name, 60317 color: color 60318 }); 60319 } 60320 }); 60321 list.push('<hr/>'); 60322 return list; 60323 } 60324 } 60325 60326 doAutoscale(features) { 60327 // if ("proportional" === this.arcType) { 60328 let max = 0; 60329 60330 if (features) { 60331 for (let f of features) { 60332 const v = this.valueColumn ? f[this.valueColumn] : f.score; 60333 60334 if (!Number.isNaN(v)) { 60335 max = Math.max(max, v); 60336 } 60337 } 60338 } 60339 60340 return { 60341 min: 0, 60342 max: max 60343 }; // } 60344 } 60345 60346 popupData(clickState, features) { 60347 features = this.clickedFeatures(clickState); 60348 const data = []; 60349 60350 for (let feature of features) { 60351 const f = feature._ || feature; // For "whole genome" features, which keeps a pointer to the original 60352 60353 data.push({ 60354 name: "Region 1", 60355 value: positionString(f.chr1, f.start1, f.end1, f.strand1) 60356 }); 60357 data.push({ 60358 name: "Region 2", 60359 value: positionString(f.chr2, f.start2, f.end2, f.strand2) 60360 }); 60361 60362 if (f.name) { 60363 data.push({ 60364 name: "Name", 60365 value: f.name 60366 }); 60367 } 60368 60369 if (f.value !== undefined) { 60370 data.push({ 60371 name: "Value", 60372 value: f.value 60373 }); 60374 } 60375 60376 if (f.score !== undefined) { 60377 data.push({ 60378 name: "Score", 60379 value: f.score 60380 }); 60381 } 60382 60383 if (f.extras && this.header && this.header.columnNames) { 60384 const columnNames = this.header.columnNames; 60385 60386 for (let i = 10; i < columnNames.length; i++) { 60387 if (columnNames[i] === 'info') { 60388 extractInfoColumn(data, f.extras[i - 10]); 60389 } else { 60390 data.push({ 60391 name: columnNames[i], 60392 value: f.extras[i - 10] 60393 }); 60394 } 60395 } 60396 } // For now just return the top hit 60397 60398 60399 break; //if (data.length > 0) { 60400 // data.push("<HR>"); 60401 // } 60402 } 60403 60404 return data; 60405 } 60406 60407 clickedFeatures(clickState, features) { 60408 // We use the cached features rather than method to avoid async load. If the 60409 // feature is not already loaded this won't work, but the user wouldn't be mousing over it either. 60410 const featureList = features || clickState.viewport.getCachedFeatures(); 60411 const candidates = []; 60412 60413 if (featureList) { 60414 const proportional = this.arcType === "proportional"; 60415 60416 for (let feature of featureList) { 60417 if (!feature.drawState) continue; 60418 60419 if (feature.chr1 === feature.chr2 || feature.chr === 'all') { 60420 if (proportional) { 60421 //(x-xc)^2/radiusX^2 + (y-yc)^2/radiusY^2 <= 1 60422 const { 60423 xc, 60424 yc, 60425 radiusX, 60426 radiusY 60427 } = feature.drawState; 60428 const dx = clickState.canvasX - xc; 60429 const dy = clickState.canvasY - yc; 60430 const score = dx / radiusX * (dx / radiusX) + dy / radiusY * (dy / radiusY); 60431 60432 if (score <= 1) { 60433 candidates.push({ 60434 score: 1 / score, 60435 feature 60436 }); 60437 } 60438 } else { 60439 const { 60440 xc, 60441 yc, 60442 r 60443 } = feature.drawState; 60444 const dx = clickState.canvasX - xc; 60445 const dy = clickState.canvasY - yc; 60446 const score = Math.abs(Math.sqrt(dx * dx + dy * dy) - r); 60447 60448 if (score < 5) { 60449 candidates.push({ 60450 score, 60451 feature 60452 }); 60453 } 60454 } 60455 } else { 60456 const { 60457 x, 60458 y, 60459 w, 60460 h 60461 } = feature.drawState; 60462 const tolerance = 5; 60463 60464 if (clickState.canvasX >= x - tolerance && clickState.canvasX <= x + w + tolerance && clickState.canvasY >= y && clickState.canvasY <= y + h) { 60465 const score = -Math.abs(clickState.canvasX - (x + w / 2)); 60466 candidates.push({ 60467 score, 60468 feature 60469 }); 60470 break; 60471 } 60472 } 60473 } 60474 } 60475 60476 if (candidates.length > 1) { 60477 candidates.sort((a, b) => a.score - b.score); 60478 } 60479 60480 return candidates.map(c => c.feature); 60481 } 60482 60483 } 60484 60485 function getMidpoints(feature, genome) { 60486 let m1 = (feature.start1 + feature.end1) / 2; 60487 let m2 = (feature.start2 + feature.end2) / 2; 60488 60489 if (feature.chr === 'all') { 60490 m1 = genome.getGenomeCoordinate(feature.chr1, m1); 60491 m2 = genome.getGenomeCoordinate(feature.chr2, m2); 60492 } 60493 60494 if (m1 > m2) { 60495 const tmp = m1; 60496 m1 = m2; 60497 m2 = tmp; 60498 } 60499 60500 return { 60501 m1, 60502 m2 60503 }; 60504 } 60505 60506 function positionString(chr, start, end, strand) { 60507 return strand && strand !== '.' ? `${chr}:${numberFormatter$1(start + 1)}-${numberFormatter$1(end)} (${strand})` : `${chr}:${numberFormatter$1(start + 1)}-${numberFormatter$1(end)}`; 60508 } 60509 /** 60510 * Estimate theta given the ratio of track height to 1/2 the feature width (coa). This relationship is a
60510pproximately linear. 60511 */ 60512 60513 60514 function estimateTheta(x) { 60515 let coa = [0.01570925532366355, 0.15838444032453644, 0.3249196962329063, 0.5095254494944288, 0.7265425280053609, 0.9999999999999999]; 60516 let theta = [0.031415926535897934, 0.3141592653589793, 0.6283185307179586, 0.9424777960769379, 1.2566370614359172, 1.5707963267948966]; 60517 let idx; 60518 60519 for (idx = 0; idx < coa.length; idx++) { 60520 if (coa[idx] > x) { 60521 break; 60522 } 60523 } 60524 60525 let left = idx === 0 ? 0 : coa[idx - 1]; 60526 let right = idx < coa.length ? coa[idx] : 1; 60527 let r = (x - left) / (right - left); 60528 let thetaLeft = idx === 0 ? 0 : theta[idx - 1]; 60529 let thetaRight = idx < theta.length ? theta[idx] : Math.PI / 2; 60530 return thetaLeft + r * (thetaRight - thetaLeft); 60531 } 60532 60533 const colorAlphaCache = new Map(); 60534 60535 function getAlphaColor(color, alpha) { 60536 const key = `${color}_${alpha}`; 60537 let c = colorAlphaCache.get(key); 60538 60539 if (!c) { 60540 c = IGVColor.addAlpha(color, alpha); 60541 colorAlphaCache.set(key, c); 60542 } 60543 60544 return c; 60545 } 60546 /** 60547 * Called in the context of FeatureSource 60548 * @param allFeatures 60549 * @returns {[]} 60550 */ 60551 60552 60553 function getWGFeatures(allFeatures) { 60554 const genome = this.genome; 60555 const wgFeatures = []; 60556 60557 for (let c of genome.wgChromosomeNames) { 60558 const chrFeatures = allFeatures[c]; 60559 60560 if (chrFeatures) { 60561 for (let f of chrFeatures) { 60562 if (!f.dup) { 60563 const wg = Object.assign({}, f); 60564 wg.chr = "all"; 60565 wg.start = genome.getGenomeCoordinate(f.chr1, f.start1); 60566 wg.end = genome.getGenomeCoordinate(f.chr2, f.end2); 60567 wgFeatures.push(wg); 60568 } 60569 } 60570 } 60571 } 60572 60573 return wgFeatures; 60574 } 60575 /** 60576 * Extract a gff style info column for popup text. This convention used by 10X for bedpe files 60577 * ALLELIC_FRAC=0.0375670840787;BLACK1=.;BLACK2=.;... 60578 * @param data 60579 * @param str 60580 */ 60581 60582 60583 function extractInfoColumn(data, str) { 60584 const kvs = str.split(';'); 60585 60586 for (let t of kvs) { 60587 const kv = t.split('='); 60588 60589 if (kv.length === 2) { 60590 data.push({ 60591 name: kv[0], 60592 value: kv[1] 60593 }); 60594 } 60595 } 60596 } 60597 60598 /* 60599 * The MIT License (MIT) 60600 * 60601 * Copyright (c) 2016 University of California San Diego 60602 * Author: Jim Robinson 60603 * 60604 * Permission is hereby granted, free of charge, to any person obtaining a copy 60605 * of this software and associated documentation files (the "Software"), to deal 60606 * in the Software without restriction, including without limitation the rights 60607 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 60608 * copies of the Software, and to permit persons to whom the Software is 60609 * furnished to do so, subject to the following conditions: 60610 * 60611 * The above copyright notice and this permission notice shall be included in 60612 * all copies or substantial portions of the Software. 60613 * 60614 * 60615 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 60616 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 60617 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 60618 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 60619 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 60620 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 60621 * THE SOFTWARE. 60622 */ 60623 const isString = isString$3; 60624 const DEFAULT_VISIBILITY_WINDOW = 1000000; 60625 const TOP_MARGIN = 10; 60626 60627 class VariantTrack extends TrackBase { 60628 constructor(config, browser) { 60629 super(config, browser); 60630 } 60631 60632 init(config) { 60633 super.init(config); 60634 this.visibilityWindow = config.visibilityWindow; 60635 this.displayMode = config.displayMode || "EXPANDED"; // COLLAPSED | EXPANDED | SQUISHED 60636 60637 this.labelDisplayMode = config.labelDisplayMode; 60638 this.expandedVariantHeight = config.expandedVariantHeight || config.variantHeight || 10; 60639 this.squishedVariantHeight = config.squishedVariantHeight || 2; 60640 this.squishedCallHeight = config.squishedCallHeight || 1; 60641 this.expandedCallHeight = config.expandedCallHeight || 10; 60642 this.expandedVGap = config.expandedVGap !== undefined ? config.expandedVGap : 2; 60643 this.squishedVGap = config.squishedVGap !== undefined ? config.squishedVGap : 1; 60644 this.expandedGroupGap = config.expandedGroupGap || 10; 60645 this.squishedGroupGap = config.squishedGroupGap || 5; 60646 this.featureHeight = config.featureHeight || 14; 60647 this.visibilityWindow = config.visibilityWindow; 60648 this.featureSource = FeatureSource(config, this.browser.genome); 60649 this.noGenotypeColor = config.noGenotypeColor || "rgb(200,180,180)"; 60650 this.noCallColor = config.noCallColor || "rgb(225, 225, 225)"; 60651 this.nonRefColor = config.nonRefColor || "rgb(200, 200, 215)"; 60652 this.mixedColor = config.mixedColor || "rgb(200, 220, 200)"; 60653 this.homrefColor = config.homrefColor || "rgb(200, 200, 200)"; 60654 this.homvarColor = config.homvarColor || "rgb(17,248,254)"; 60655 this.hetvarColor = config.hetvarColor || "rgb(34,12,253)"; 60656 this.sortDirection = "ASC"; 60657 this.type = config.type || "variant"; 60658 this.colorBy = config.colorBy; // Can be undefined => default 60659 60660 this._initColorBy = config.colorBy; 60661 60662 if (config.colorTable) { 60663 this.colorTables = new Map(); 60664 this.colorTables.set(config.colorBy, new ColorTable(config.colorTable)); 60665 } 60666 60667 this._color = config.color; 60668 this.showGenotypes = config.showGenotypes === undefined ? true : config.showGenotypes; // The number of variant rows are computed dynamically, but start with "1" by default 60669 60670 this.variantRowCount(1); 60671 } 60672 60673 async postInit() { 60674 this.header = await this.getHeader(); // cricital, don't remove' 60675 60676 if (undefined === this.visibilityWindow && this.config.indexed !== false) { 60677 const fn = isFile(this.config.url) ? this.config.url.name : this.config.url; 60678 60679 if (isString(fn) && fn.toLowerCase().includes("gnomad")) { 60680 this.visibilityWindow = 1000; // these are known to be very dense 60681 } else if (typeof this.featureSource.defaultVisibilityWindow === 'function') { 60682 this.visibilityWindow = await this.featureSource.defaultVisibilityWindow(); 60683 } else { 60684 this.visibilityWindow = DEFAULT_VISIBILITY_WINDOW; 60685 } 60686 } 60687 60688 return this; 60689 } 60690 60691 supportsWholeGenome() { 60692 return this.config.indexed === false || this.config.supp
60692ortsWholeGenome === true; 60693 } 60694 60695 get color() { 60696 return this._color; 60697 } 60698 60699 set color(c) { 60700 this._color = c; 60701 this.colorBy = undefined; 60702 } 60703 60704 async getHeader() { 60705 if (!this.header) { 60706 if (typeof this.featureSource.getHeader === "function") { 60707 const header = await this.featureSource.getHeader(); 60708 60709 if (header) { 60710 this.callSets = header.callSets || []; 60711 } 60712 60713 this.header = header; 60714 } 60715 60716 this.sampleNames = this.callSets ? this.callSets.map(cs => cs.name) : []; 60717 } 60718 60719 return this.header; 60720 } 60721 60722 getCallsetsLength() { 60723 return this.callSets ? this.callSets.length : 0; 60724 } 60725 60726 async getFeatures(chr, start, end, bpPerPixel) { 60727 if (this.header === undefined) { 60728 this.header = await this.getHeader(); 60729 } 60730 60731 return this.featureSource.getFeatures({ 60732 chr, 60733 start, 60734 end, 60735 bpPerPixel, 60736 visibilityWindow: this.visibilityWindow 60737 }); 60738 } 60739 60740 hasSamples() { 60741 return this.getCallsetsLength() > 0; 60742 } 60743 60744 getSamples() { 60745 return { 60746 yOffset: this.sampleYOffset, 60747 names: this.sampleNames, 60748 height: this.sampleHeight 60749 }; 60750 } 60751 /** 60752 * The required height in pixels required for the track content. This is not the visible track height, which 60753 * can be smaller (with a scrollbar) or larger. 60754 * 60755 * @param features 60756 * @returns {*} 60757 */ 60758 60759 60760 computePixelHeight(features) { 60761 if (!features || features.length == 0) return TOP_MARGIN; 60762 const nVariantRows = this.displayMode === "COLLAPSED" ? 1 : this.nVariantRows; 60763 const vGap = this.displayMode === "SQUISHED" ? this.squishedVGap : this.expandedVGap; 60764 const variantHeight = this.displayMode === "SQUISHED" ? this.squishedVariantHeight : this.expandedVariantHeight; 60765 const callHeight = this.displayMode === "SQUISHED" ? this.squishedCallHeight : this.expandedCallHeight; 60766 const nCalls = this.showGenotypes === false ? 0 : this.getCallsetsLength() * nVariantRows; 60767 const h = TOP_MARGIN + nVariantRows * (variantHeight + vGap); 60768 return h + vGap + (nCalls + 1) * (callHeight + vGap); 60769 } 60770 60771 variantRowCount(count) { 60772 this.nVariantRows = count; 60773 } 60774 60775 draw(_ref) { 60776 let { 60777 context, 60778 pixelWidth, 60779 pixelHeight, 60780 bpPerPixel, 60781 bpStart, 60782 pixelTop, 60783 features 60784 } = _ref; 60785 IGVGraphics.fillRect(context, 0, pixelTop, pixelWidth, pixelHeight, { 60786 'fillStyle': "rgb(255, 255, 255)" 60787 }); 60788 const vGap = "SQUISHED" === this.displayMode ? this.squishedVGap : this.expandedVGap; 60789 const rc = "COLLAPSED" === this.displayMode ? 1 : this.nVariantRows; 60790 const variantHeight = "SQUISHED" === this.displayMode ? this.squishedVariantHeight : this.expandedVariantHeight; 60791 this.variantBandHeight = TOP_MARGIN + rc * (variantHeight + vGap); 60792 const callSets = this.callSets; 60793 const nCalls = this.getCallsetsLength(); 60794 60795 if (callSets && nCalls > 0 && this.showGenotypes !== false) { 60796 IGVGraphics.strokeLine(context, 0, this.variantBandHeight, pixelWidth, this.variantBandHeight, { 60797 strokeStyle: 'rgb(224,224,224) ' 60798 }); 60799 } 60800 60801 if (features) { 60802 const callHeight = "SQUISHED" === this.displayMode ? this.squishedCallHeight : this.expandedCallHeight; 60803 const vGap = "SQUISHED" === this.displayMode ? this.squishedVGap : this.expandedVGap; 60804 const bpEnd = bpStart + pixelWidth * bpPerPixel + 1; // Loop through variants. A variant == a row in a VCF file 60805 60806 for (let variant of features) { 60807 if (variant.end < bpStart) continue; 60808 if (variant.start > bpEnd) break; 60809 const variantHeight = "SQUISHED" === this.displayMode ? this.squishedVariantHeight : this.expandedVariantHeight; 60810 const y = TOP_MARGIN + ("COLLAPSED" === this.displayMode ? 0 : variant.row * (variantHeight + vGap)); 60811 const h = variantHeight; // Compute pixel width. Minimum width is 3 pixels, if > 5 pixels create gap between variants 60812 60813 let x = Math.round((variant.start - bpStart) / bpPerPixel); 60814 let x1 = Math.round((variant.end - bpStart) / bpPerPixel); 60815 let w = Math.max(1, x1 - x); 60816 60817 if (w < 3) { 60818 w = 3; 60819 x -= 1; 60820 } else if (w > 5) { 60821 x += 1; 60822 w -= 2; 60823 } 60824 60825 context.fillStyle = this.getVariantColor(variant); 60826 context.fillRect(x, y, w, h); 60827 variant.pixelRect = { 60828 x, 60829 y, 60830 w, 60831 h 60832 }; // Loop though the calls for this variant. There will potentially be a call for each sample. 60833 60834 if (nCalls > 0 && this.showGenotypes !== false) { 60835 const nVariantRows = "COLLAPSED" === this.displayMode ? 1 : this.nVariantRows; 60836 this.sampleYOffset = this.variantBandHeight + vGap; 60837 this.sampleHeight = nVariantRows * (callHeight + vGap); // For each sample, there is a call for each variant at this position 60838 60839 let sampleNumber = 0; 60840 60841 for (let callSet of callSets) { 60842 const call = variant.calls[callSet.id]; 60843 60844 if (call) {
60845 const row = "COLLAPSED" === this.displayMode ? 0 : variant.row; 60846 const py = this.sampleYOffset + sampleNumber * this.sampleHeight + row * (callHeight + vGap); 60847 let allVar = true; // until proven otherwise 60848 60849 let allRef = true; 60850 let noCall = false; 60851 60852 if (call.genotype) { 60853 for (let g of call.genotype) { 60854 if ('.' === g) { 60855 noCall = true; 60856 break; 60857 } else { 60858 if (g !== 0) allRef = false; 60859 if (g === 0) allVar = false; 60860 } 60861 } 60862 } 60863 60864 if (!call.genotype) { 60865 context.fillStyle = this.noGenotypeColor; 60866 } else if (noCall) { 60867 context.fillStyle = this.noCallColor; 60868 } else if (allRef) { 60869 context.fillStyle = this.homrefColor; 60870 } else if (allVar) { 60871 context.fillStyle = this.homvarColor; 60872 } else { 60873 context.fillStyle = this.hetvarColor; 60874 } 60875 60876 context.fillRect(x, py, w, callHeight); 60877 callSet.pixelRect = { 60878 x, 60879 y: py, 60880 w, 60881 h: callHeight 60882 }; 60883 } 60884 60885 sampleNumber++; 60886 } 60887 } 60888 } 60889 } else { 60890 console.log("No feature list"); 60891 } 60892 } 60893 60894 getVariantColor(variant) { 60895 const v = variant._f || variant; 60896 let variantColor; 60897 60898 if (this.colorBy) { 60899 const value = v.info[this.colorBy]; 60900 variantColor = this.getVariantColorTable(this.colorBy).getColor(value); 60901 60902 if (!variantColor) { 60903 variantColor = "gray"; 60904 } 60905 } else if (this._color) { 60906 variantColor = typeof this._color === "function" ? this._color(v) : this._color; 60907 } else if ("NONVARIANT" === v.type) { 60908 variantColor = this.nonRefColor; 60909 } else if ("MIXED" === v.type) { 60910 variantColor = this.mixedColor; 60911 } else { 60912 variantColor = this.defaultColor; 60913 } 60914 60915 return variantColor; 60916 } 60917 60918 clickedFeatures(clickState, features) { 60919 let featureList = super.clickedFeatures(clickState, features); 60920 const vGap = this.displayMode === 'EXPANDED' ? this.expandedVGap : this.squishedVGap; 60921 const callHeight = vGap + ("SQUISHED" === this.displayMode ? this.squishedCallHeight : this.expandedCallHeight); // Find the variant row (i.e. row assigned during feature packing) 60922 60923 const yOffset = clickState.y; 60924 60925 if (yOffset <= this.variantBandHeight) { 60926 // Variant 60927 const variantHeight = "SQUISHED" === this.displayMode ? this.squishedVariantHeight : this.expandedVariantHeight; 60928 const variantRow = Math.floor((yOffset - TOP_MARGIN) / (variantHeight + vGap)); 60929 featureList = featureList.filter(f => f.row === variantRow); 60930 } else if (this.callSets) { 60931 const callSets = this.callSets; 60932 const sampleY = yOffset - this.variantBandHeight; 60933 const sampleRow = Math.floor(sampleY / this.sampleHeight); 60934 60935 if (sampleRow >= 0 && sampleRow < callSets.length) { 60936 const variantRow = Math.floor((sampleY - sampleRow * this.sampleHeight) / callHeight); 60937 const variants = featureList.filter(f => f.row === variantRow); 60938 const cs = callSets[sampleRow]; 60939 featureList = variants.map(v => { 60940 const call = v.calls[cs.id]; 60941 expandGenotype(call, v); 60942 return call; 60943 }); 60944 } 60945 } 60946 60947 return featureList; 60948 } 60949 /** 60950 * Return "popup data" for feature @ genomic location. Data is an array of key-value pairs 60951 */ 60952 60953 60954 popupData(clickState, features) { 60955 const featureList = this.clickedFeatures(clickState, features); 60956 const genomicLocation = clickState.genomicLocation; 60957 const genomeID = this.browser.genome.id; 60958 const sampleInformation = this.browser.sampleInformation; 60959 let popupData = []; 60960 60961 for (let v of featureList) { 60962 const f = v._f || v; // Get real variant from psuedo-variant, e.g. whole genome or SV mate 60963 60964 if (popupData.length > 0) { 60965 popupData.push({ 60966 html: '<hr style="border-top-width:2px ;border-color: #c9c3ba" />' 60967 }); 60968 } 60969 60970 if (typeof f.popupData === 'function') { 60971 const v = f.popupData(genomicLocation, genomeID);
60972 Array.prototype.push.apply(popupData, v); 60973 } else { 60974 // Assume this is a call (genotype) 60975 const call = f; 60976 60977 if (call.callSetName !== undefined) { 60978 popupData.push({ 60979 name: 'Name', 60980 value: call.callSetName 60981 }); 60982 } 60983 60984 if (call.genotypeName) { 60985 popupData.push({ 60986 name: 'Genotype', 60987 value: call.genotypeName 60988 }); 60989 } 60990 60991 if (call.phaseset !== undefined) { 60992 popupData.push({ 60993 name: 'Phase set', 60994 value: call.phaseset 60995 }); 60996 } 60997 60998 if (call.genotypeLikelihood !== undefined) { 60999 popupData.push({ 61000 name: 'genotypeLikelihood', 61001 value: call.genotypeLikelihood.toString() 61002 }); 61003 } 61004 61005 if (sampleInformation) { 61006 var attr = sampleInformation.getAttributes(call.callSetName); 61007 61008 if (attr) { 61009 Object.keys(attr).forEach(function (attrName) { 61010 var displayText = attrName.replace(/([A-Z])/g, " $1"); 61011 displayText = displayText.charAt(0).toUpperCase() + displayText.slice(1); 61012 popupData.push({ 61013 name: displayText, 61014 value: attr[attrName] 61015 }); 61016 }); 61017 } 61018 } 61019 61020 var infoKeys = Object.keys(call.info); 61021 61022 if (infoKeys.length) { 61023 popupData.push('<hr/>'); 61024 } 61025 61026 infoKeys.forEach(function (key) { 61027 popupData.push({ 61028 name: key, 61029 value: decodeURIComponent(call.info[key]) 61030 }); 61031 }); 61032 } 61033 } 61034 61035 return popupData; 61036 } // VariantTrack.prototype.contextMenuItemList = function (clickState) { 61037 // 61038 // const self = this; 61039 // const menuItems = []; 61040 // 61041 // const featureList = this.clickedFeatures(clickState); 61042 // 61043 // if (this.callSets && featureList && featureList.length > 0) { 61044 // 61045 // featureList.forEach(function (variant) { 61046 // 61047 // if ('str' === variant.type) { 61048 // 61049 // menuItems.push({ 61050 // label: 'Sort by allele length', 61051 // click: function () { 61052 // sortCallSetsByAlleleLength(self.callSets, variant, self.sortDirection); 61053 // self.sortDirection = (self.sortDirection === "ASC") ? "DESC" : "ASC"; 61054 // self.trackView.repaintViews(); 61055 // } 61056 // }); 61057 // 61058 // } 61059 // 61060 // }); 61061 // } 61062 // 61063 // 61064 // function sortCallSetsByAlleleLength(callSets, variant, direction) { 61065 // var d = (direction === "DESC") ? 1 : -1; 61066 // Object.keys(callSets).forEach(function (property) { 61067 // callSets[property].sort(function (a, b) { 61068 // var aNan = isNaN(variant.calls[a.id].genotype[0]); 61069 // var bNan = isNaN(variant.calls[b.id].genotype[0]); 61070 // if (aNan && bNan) { 61071 // return 0; 61072 // } else if (aNan) { 61073 // return 1; 61074 // } else if (bNan) { 61075 // return -1; 61076 // } else { 61077 // var a0 = getAlleleString(variant.calls[a.id], variant, 0); 61078 // var a1 = getAlleleString(variant.calls[a.id], variant, 1); 61079 // var b0 = getAlleleString(variant.calls[b.id], variant, 0); 61080 // var b1 = getAlleleString(variant.calls[b.id], variant, 1); 61081 // var result = Math.max(b0.length, b1.length) - Math.max(a0.length, a1.length); 61082 // if (result === 0) { 61083 // result = Math.min(b0.length, b1.length) - Math.min(a0.length, a1.length); 61084 // } 61085 // return d * result; 61086 // } 61087 // }); 61088 // }); 61089 // } 61090 // 61091 // 61092 // return menuItems; 61093 // 61094 // }; 61095 61096 61097 menuItemList() { 61098 const menuItems = []; // color-by INFO attribute 61099 61100 if (this.header.INFO) { 61101 //Code below will present checkboxes for all info fields of type "String". Wait until this is requested 61102 //const stringInfoKeys = Object.keys(this.header.INFO).filter(key => "String" === this.header.INFO[key].Type); 61103 // For now stick to explicit info fields (well, exactly 1 for starters) 61104 if (this.header.INFO) { 61105 //const stringInfoKeys = Object.keys(this.header.INFO).filter(key => this.header.INFO[key].Type === "String") 61106 const stringInfoKeys = this.header.INFO.SVTYPE ? ['SVTYPE'] : []; 61107 61108 if (this._initColorBy && this._initColorBy !== 'SVTYPE') {
61109 stringInfoKeys.push(this._initColorBy); 61110 } 61111 61112 if (stringInfoKeys.length > 0) { 61113 menuItems.push('<hr/>'); 61114 const $e = $$1('<div class="igv-track-menu-category igv-track-menu-border-top">'); 61115 $e.text('Color by:'); 61116 menuItems.push({ 61117 name: undefined, 61118 object: $e, 61119 click: undefined, 61120 init: undefined 61121 }); 61122 stringInfoKeys.sort(); 61123 61124 for (let item of stringInfoKeys) { 61125 const selected = this.colorBy === item; 61126 const label = item ? item : 'None'; 61127 menuItems.push(this.colorByCB({ 61128 key: item, 61129 label: label 61130 }, selected)); 61131 } 61132 61133 menuItems.push(this.colorByCB({ 61134 key: undefined, 61135 label: 'None' 61136 }, this.colorBy === undefined)); 61137 menuItems.push('<hr/>'); 61138 } 61139 } 61140 } 61141 61142 if (this.getCallsetsLength() > 0) { 61143 menuItems.push({ 61144 object: $$1('<div class="igv-track-menu-border-top">') 61145 }); 61146 menuItems.push({ 61147 object: $$1(createCheckbox$1("Show Genotypes", this.showGenotypes)), 61148 click: () => { 61149 this.showGenotypes = !this.showGenotypes; //adjustTrackHeight(); 61150 61151 this.trackView.checkContentHeight(); 61152 this.trackView.repaintViews(); 61153 } 61154 }); 61155 } 61156 61157 menuItems.push({ 61158 object: $$1('<div class="igv-track-menu-border-top">') 61159 }); 61160 61161 for (let displayMode of ["COLLAPSED", "SQUISHED", "EXPANDED"]) { 61162 var lut = { 61163 "COLLAPSED": "Collapse", 61164 "SQUISHED": "Squish", 61165 "EXPANDED": "Expand" 61166 }; 61167 menuItems.push({ 61168 object: $$1(createCheckbox$1(lut[displayMode], displayMode === this.displayMode)), 61169 click: () => { 61170 this.displayMode = displayMode; 61171 this.trackView.checkContentHeight(); 61172 this.trackView.repaintViews(); 61173 } 61174 }); 61175 } // Experimental JBrowse circular view integration 61176 61177 61178 if (this.browser.circularView && true === this.browser.circularViewVisible) { 61179 menuItems.push('<hr>'); 61180 menuItems.push({ 61181 label: 'Add SVs to circular view', 61182 click: () => { 61183 const inView = []; 61184 61185 for (let viewport of this.trackView.viewports) { 61186 const refFrame = viewport.referenceFrame; 61187 61188 for (let f of viewport.getCachedFeatures()) { 61189 if (f.end >= refFrame.start && f.start <= refFrame.end) { 61190 inView.push(f); 61191 } 61192 } 61193 } 61194 61195 const chords = makeVCFChords(inView); 61196 const color = IGVColor.addAlpha(this._color || this.defaultColor, 0.5); 61197 this.browser.circularView.addChords(chords, { 61198 track: this.name, 61199 color: color 61200 }); 61201 } 61202 }); 61203 } 61204 61205 return menuItems; 61206 } 61207 61208 contextMenuItemList(clickState) { 61209 // Experimental JBrowse circular view integration 61210 if (this.browser.circularView && true === this.browser.circularViewVisible) { 61211 const viewport = clickState.viewport; 61212 const list = []; 61213 list.push({ 61214 label: 'Add SVs to Circular View', 61215 click: () => { 61216 const refFrame = viewport.referenceFrame; 61217 const inView = "all" === refFrame.chr ? this.featureSource.getAllFeatures() : this.featureSource.featureCache.queryFeatures(refFrame.chr, refFrame.start, refFrame.end); 61218 const chords = makeVCFChords(inView); 61219 const color = IGVColor.addAlpha(this._color || this.defaultColor, 0.5); 61220 this.browser.circularView.addChords(chords, { 61221 track: this.name, 61222 color: color 61223 }); 61224 } 61225 }); 61226 list.push('<hr/>'); 61227 return list; 61228 } 61229 } 61230 /** 61231 * Create a "color by" checkbox menu item, optionally initially checked 61232 * @param menuItem 61233 * @param showCheck 61234 * @returns {{init: undefined, name: undefined, click: clickHandler, object: (jQuery|HTMLElement|jQuery.fn.init)}} 61235 */ 61236 61237 61238 colorByCB(menuItem, showCheck) { 61239 const $e = $$1(createCheckbox$1(menuItem.label, showCheck)); 61240 61241 const clickHandler = () => { 61242 if (menuItem.key === this.colorBy) { 61243 this.colorBy = undefined; 61244 delete this.config.colorBy; 61245 this.trackView.repaintViews(); 61246 } else { 61247 this.colorBy = menuItem.key; 61248 this.config.colorBy = menuItem.key; 61249 this.trackView.repaintViews(); 61250 } 61251 }; 61252 61253 return { 61254 name: undefined, 61255 object: $e, 61256 click: clickHandler, 61257 init: undefined 61258 }; 61259 } 61260 61261 getState() { 61262 const config = super.getState(); 61263 61264 if (this._color && typeof this._color !== "function") { 61265 config.color = this._color; 61266 } 61267 61268 return config; 61269 } 61270 61271 getVariantColorTable(key) { 61272 if (!this.colorTables) { 61273 this.colorTables = new Map(); 61274 } 61275 61276 if (!this.colorTables.has(key)) { 61277 let tbl; 61278 61279 switch (key) { 61280 case "SVTYPE": 61281 tbl = SV_COLOR_TABLE; 61282 break; 61283 61284 default: 61285 tbl = new PaletteColorTable("Set1"); 61286 } 61287 61288 this.colorTables.set(key, tbl); 61289 } 61290 61291 return this.colorTables.get(key); 61292 } 61293 61294 } 61295 61296 function expandGenotype(call, variant) { 61297 if (call.genotype) { 61298 let gt = ''; 61299 61300 if (variant.alternateBases === ".") { 61301 gt = "No Call"; 61302 } else { 61303 const altArray = variant.alternateBases.split(","); 61304 61305 for (let allele of call.genotype) { 61306 if (gt.length > 0) { 61307 gt += "|"; 61308 } 61309 61310 if ('.' === allele) { 61311 gt += '.'; 61312 } else if (allele === 0) { 61313 gt += variant.referenceBases; 61314 } else { 61315 let alt = altArray[allele - 1].replace("<", "<"); 61316 gt += alt; 61317 } 61318 } 61319 } 61320 61321 call.genotypeName = gt; 61322 } 61323 } 61324 61325 const SV_COLOR_TABLE = new ColorTable({ 61326 'DEL': '#ff2101', 61327 'INS': '#001888', 61328 'DUP': '#028401', 61329 'INV': '#008688', 61330 'CNV': '#8931ff', 61331 'BND': '#891100', 61332 '*': '#002eff' 61333 }); 61334 61335 /* 61336 * The MIT License (MIT) 61337 * 61338 * Copyright (c) 2014 Broad Institute 61339 * 61340 * Permission is hereby granted, free of charge, to any person obtaining a copy 61341 * of this software and associated documentation files (the "Software"), to deal 61342 * in the Software without restriction, including without limitation the rights 61343 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 61344 * copies of the Software, and to permit persons to whom the Software is 61345 * furnished to do so, subject to the following conditions: 61346 * 61347 * The above copyright notice and this permission notice shall be included in 61348 * all copies or substantial portions of the Software. 61349 * 61350 * 61351 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 61352 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 61353 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 61354 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 61355 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 61356 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 61357 * THE SOFTWARE. 61358 */ 61359 61360 class EqtlTrack extends TrackBase { 61361 constructor(config, browser) { 61362 super(config, browser); 61363 } 61364 61365 init(config) { 61366 super.init(config); 61367 this.name = config.name; 61368 this.pValueField = config.pValueField || "pValue"; 61369 this.geneField = config.geneField || "geneSymbol"; 61370 this.snpField = config.snpField || "snp"; 61371 const min = config.minLogP || config.min; 61372 const max = config.maxLogP || config.max; 61373 this.dataRange = { 61374 min: min || 3.5, 61375 max: max || 25 61376 }; 61377 61378 if (!max) { 61379 this.autoscale = true; 61380 } else { 61381 this.autoscale = config.autoscale; 61382 } 61383 61384 this.autoscalePercentile = config.autoscalePercentile === undefined ? 98 : config.autoscalePercentile; 61385 this.background = config.background; // No default 61386 61387 this.divider = config.divider || "rgb(225,225,225)"; 61388 this.dotSize = config.dotSize || 2; 61389 this.height = config.height || 100; 61390 this.autoHeight = false;
61391 this.disableButtons = config.disableButtons; // Limit visibility window to 2 mb, gtex server gets flaky beyond that 61392 61393 this.visibilityWindow = config.visibilityWindow === undefined ? 2000000 : config.visibilityWindow >= 0 ? Math.min(2000000, config.visibilityWindow) : 2000000; 61394 this.featureSource = FeatureSource(config, this.browser.genome); 61395 GtexUtils.gtexLoaded = true; 61396 } 61397 61398 paintAxis(ctx, pixelWidth, pixelHeight) { 61399 const yScale = (this.dataRange.max - this.dataRange.min) / pixelHeight; 61400 const font = { 61401 'font': 'normal 10px Arial', 61402 'textAlign': 'right', 61403 'strokeStyle': "black" 61404 }; 61405 IGVGraphics.fillRect(ctx, 0, 0, pixelWidth, pixelHeight, { 61406 'fillStyle': "rgb(255, 255, 255)" 61407 }); // Determine a tick spacing such that there is at least 10 pixels between ticks 61408 61409 const n = Math.ceil((this.dataRange.max - this.dataRange.min) * 10 / pixelHeight); 61410 61411 for (let p = 4; p <= this.dataRange.max; p += n) { 61412 // TODO: Dashes may not actually line up with correct scale. Ask Jim about this 61413 const ref = 0.85 * pixelWidth; 61414 const x1 = ref - 5; 61415 const x2 = ref; 61416 const y = pixelHeight - (p - this.dataRange.min) / yScale; 61417 IGVGraphics.strokeLine(ctx, x1, y, x2, y, font); // Offset dashes up by 2 pixel 61418 61419 if (y > 8) { 61420 IGVGraphics.fillText(ctx, p, x1 - 1, y + 2, font); 61421 } // Offset numbers down by 2 pixels; 61422 61423 } 61424 61425 font['textAlign'] = 'center'; 61426 IGVGraphics.fillText(ctx, "-log10(pvalue)", pixelWidth / 4, pixelHeight / 2, font, { 61427 rotate: { 61428 angle: -90 61429 } 61430 }); 61431 } 61432 61433 async getFeatures(chr, start, end) { 61434 const pValueField = this.pValueField; 61435 const visibilityWindow = this.visibilityWindow; 61436 const features = await this.featureSource.getFeatures({ 61437 chr, 61438 start, 61439 end, 61440 visibilityWindow 61441 }); 61442 features.forEach(function (f) { 61443 f.value = f[pValueField]; 61444 }); 61445 return features; 61446 } 61447 61448 draw(options) { 61449 const ctx = options.context; 61450 const pixelWidth = options.pixelWidth; 61451 const pixelHeight = options.pixelHeight; 61452 61453 if (this.background) { 61454 IGVGraphics.fillRect(ctx, 0, 0, pixelWidth, pixelHeight, { 61455 'fillStyle': this.background 61456 }); 61457 } 61458 61459 IGVGraphics.strokeLine(ctx, 0, pixelHeight - 1, pixelWidth, pixelHeight - 1, { 61460 'strokeStyle': this.divider 61461 }); 61462 61463 const drawEqtls = drawSelected => { 61464 const radius = drawSelected ? 2 * this.dotSize : this.dotSize; 61465 const bpStart = options.bpStart; 61466 const yScale = (this.dataRange.max - this.dataRange.min) / pixelHeight; 61467 const selection = options.referenceFrame.selection; 61468 61469 for (let eqtl of options.features) { 61470 const px = (eqtl.start - bpStart + 0.5) / options.bpPerPixel; 61471 if (px < 0) continue;else if (px > pixelWidth) break; 61472 const snp = eqtl.snp.toUpperCase(); 61473 const geneName = eqtl[this.geneField].toUpperCase(); 61474 const isSelected = selection && (selection.snp === snp || selection.gene === geneName); 61475 61476 if (!drawSelected || isSelected) { 61477 // Add eqtl's gene to the selection if this is the selected snp. 61478 // TODO -- this should not be done here in the rendering code. 61479 if (selection && selection.snp === snp) { 61480 selection.addGene(geneName); 61481 } 61482 61483 var mLogP = -Math.log(eqtl[this.pValueField]) / Math.LN10; 61484 61485 if (mLogP >= this.dataRange.min) { 61486 let capped; 61487 61488 if (mLogP > this.dataRange.max) { 61489 mLogP = this.dataRange.max; 61490 capped = true; 61491 } else { 61492 capped = false; 61493 } 61494 61495 const py = Math.max(0 + radius, pixelHeight - Math.round((mLogP - this.dataRange.min) / yScale)); 61496 eqtl.px = px; 61497 eqtl.py = py;
61498 eqtl.radius = radius; 61499 let color; 61500 61501 if (drawSelected && selection) { 61502 color = selection.colorForGene(geneName); 61503 IGVGraphics.setProperties(ctx, { 61504 fillStyle: color, 61505 strokeStyle: "black" 61506 }); 61507 } else { 61508 color = capped ? "rgb(150, 150, 150)" : "rgb(180, 180, 180)"; 61509 IGVGraphics.setProperties(ctx, { 61510 fillStyle: color, 61511 strokeStyle: color 61512 }); 61513 } 61514 61515 IGVGraphics.fillCircle(ctx, px, py, radius); 61516 IGVGraphics.strokeCircle(ctx, px, py, radius); 61517 } 61518 } 61519 } 61520 }; // Draw in two passes, with "selected" eqtls drawn last 61521 61522 61523 drawEqtls(false); 61524 drawEqtls(true); 61525 } 61526 /** 61527 * Return "popup data" for feature @ genomic location. Data is an array of key-value pairs 61528 */ 61529 61530 61531 popupData(clickState) { 61532 let features = clickState.viewport.getCachedFeatures(); 61533 if (!features || features.length === 0) return []; 61534 const tolerance = 3; 61535 const tissue = this.name; 61536 const popupData = []; 61537 61538 for (let feature of features) { 61539 // Hit test --use square vs circle for efficiency (no sqrt) 61540 if (Math.abs(feature.px - clickState.canvasX) < feature.radius + tolerance && Math.abs(feature.py - clickState.canvasY) < feature.radius + tolerance) { 61541 if (popupData.length > 0) { 61542 popupData.push('<hr/>'); 61543 } 61544 61545 popupData.push({ 61546 name: "snp id", 61547 value: feature.snp 61548 }, { 61549 name: "gene id", 61550 value: feature.geneId 61551 }, { 61552 name: "gene name", 61553 value: feature.geneName 61554 }, { 61555 name: "p value", 61556 value: feature.pValue 61557 }, { 61558 name: "tissue", 61559 value: tissue 61560 }); 61561 } 61562 } 61563 61564 return popupData; 61565 } 61566 61567 menuItemList() { 61568 return MenuUtils.numericDataMenuItems(this.trackView); 61569 } 61570 61571 doAutoscale(featureList) { 61572 if (featureList.length > 0) { 61573 var values = featureList.map(function (eqtl) { 61574 return -Math.log(eqtl.value) / Math.LN10; 61575 }); 61576 this.dataRange.max = IGVMath.percentile(values, this.autoscalePercentile); 61577 } else { 61578 // No features -- default 61579 const max = this.config.maxLogP || this.config.max; 61580 this.dataRange.max = max || 25; 61581 } 61582 61583 return this.dataRange; 61584 } 61585 61586 } 61587 61588 /** 61589 * Colors used for coding omosomes 61590 */ 61591 const Colors = { 61592 "X": "rgb(204, 153, 0)", 61593 "Y": "rgb(153, 204, 0)", 61594 "Un": "darkGray)", 61595 "1": "rgb(80, 80, 255)", 61596 //"1": Color.red); 61597 "I": "rgb(139, 155, 187)", 61598 "2": "rgb(206, 61, 50)", 61599 "II": "rgb(206, 61, 50)", 61600 "2a": "rgb(210, 65, 55)", 61601 "2b": "rgb(215, 70, 60)", 61602 "3": "rgb(116, 155, 88)", 61603 "III": "rgb(116, 155, 88)", 61604 "4": "rgb(240, 230, 133)", 61605 "IV": "rgb(240, 230, 133)", 61606 "5": "rgb(70, 105, 131)", 61607 "6": "rgb(186, 99, 56)", 61608 "7": "rgb(93, 177, 221)", 61609 "8": "rgb(128, 34, 104)", 61610 "9": "rgb(107, 215, 107)", 61611 "10": "rgb(213, 149, 167)", 61612 "11": "rgb(146, 72, 34)", 61613 "12": "rgb(131, 123, 141)", 61614 "13": "rgb(199, 81, 39)", 61615 "14": "rgb(213, 143, 92)", 61616 "15": "rgb(122, 101, 165)", 61617 "16": "rgb(228, 175, 105)", 61618 "17": "rgb(59, 27, 83)", 61619 "18": "rgb(205, 222, 183)", 61620 "19": "rgb(97, 42, 121)", 61621 "20": "rgb(174, 31, 99)", 61622 "21": "rgb(231, 199, 111)", 61623 "22": "rgb(90, 101, 94)", 61624 "23": "rgb(204, 153, 0)", 61625 "24": "rgb(153, 204, 0)", 61626 "25": "rgb(51, 204, 0)", 61627 "26": "rgb(0, 204, 51)", 61628 "27": "rgb(0, 204, 153)", 61629 "28": "rgb(0, 153, 204)", 61630 "29": "rgb(10, 71, 255)", 61631 "30": "rgb(71, 117, 255)", 61632 "31": "rgb(255, 194, 10)", 61633 "32": "rgb(255, 209, 71)", 61634 "33": "rgb(153, 0, 51)", 61635 "34": "rgb(153, 26, 0)", 61636 "35": "rgb(153, 102, 0)", 61637 "36": "rgb(128, 153, 0)", 61638 "37": "rgb(51, 153, 0)", 61639 "38": "rgb(0, 153, 26)", 61640 "39": "rgb(0, 153, 102)", 61641 "40": "rgb(0, 128, 153)", 61642 "41": "rgb(0, 51, 153)",
61643 "42": "rgb(26, 0, 153)", 61644 "43": "rgb(102, 0, 153)", 61645 "44": "rgb(153, 0, 128)", 61646 "45": "rgb(214, 0, 71)", 61647 "46": "rgb(255, 20, 99)", 61648 "47": "rgb(0, 214, 143)", 61649 "48": "rgb(20, 255, 177)" 61650 }; // aliasing 61651 61652 for (let key of Object.keys(Colors)) { 61653 const altName = "chr" + key; 61654 Colors[altName] = Colors[key]; 61655 } 61656 61657 /* 61658 * The MIT License (MIT) 61659 * 61660 * Copyright (c) 2014 Broad Institute 61661 * 61662 * Permission is hereby granted, free of charge, to any person obtaining a copy 61663 * of this software and associated documentation files (the "Software"), to deal 61664 * in the Software without restriction, including without limitation the rights 61665 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 61666 * copies of the Software, and to permit persons to whom the Software is 61667 * furnished to do so, subject to the following conditions: 61668 * 61669 * The above copyright notice and this permission notice shall be included in 61670 * all copies or substantial portions of the Software. 61671 * 61672 * 61673 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 61674 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 61675 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 61676 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 61677 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 61678 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 61679 * THE SOFTWARE. 61680 */ 61681 const DEFAULT_POPOVER_WINDOW = 100000000; //const type = "gwas"; 61682 61683 class GWASTrack extends TrackBase { 61684 constructor(config, browser) { 61685 super(config, browser); 61686 } 61687 61688 init(config) { 61689 super.init(config); 61690 this.useChrColors = config.useChrColors === undefined ? true : config.useChrColors; 61691 this.trait = config.trait; 61692 this.posteriorProbability = config.posteriorProbability; 61693 this.valueProperty = "bed" === config.format ? "score" : "value"; 61694 this.height = config.height || 100; // The preferred height 61695 61696 this.autoscale = config.autoscale; 61697 this.autoscalePercentile = config.autoscalePercentile === undefined ? 98 : config.autoscalePercentile; 61698 this.background = config.background; // No default 61699 61700 this.divider = config.divider || "rgb(225,225,225)"; 61701 this.dotSize = config.dotSize || 3; 61702 this.popoverWindow = config.popoverWindow === undefined ? DEFAULT_POPOVER_WINDOW : config.popoverWindow; 61703 this.description = config.description; // might be null 61704 61705 this.colorScales = config.color ? new ConstantColorScale(config.color) : { 61706 "*": new BinnedColorScale(config.colorScale || { 61707 thresholds: [5e-8, 5e-4, 0.5], 61708 colors: ["rgb(255,50,50)", "rgb(251,100,100)", "rgb(251,170,170)", "rgb(227,238,249)"] 61709 }) 61710 }; 61711 this.featureSource = FeatureSource(config, this.browser.genome); 61712 } 61713 61714 async postInit() { 61715 if (typeof this.featureSource.getHeader === "function") { 61716 this.header = await this.featureSource.getHeader(); 61717 } // Set properties from track line 61718 61719 61720 if (this.header) { 61721 this.setTrackProperties(this.header); // setTrackProperties defined in TrackBase 61722 } // Set initial range if specfied, unless autoscale == true 61723 61724 61725 if (!this.autoscale) { 61726 if (this.posteriorProbability) { 61727 this.dataRange = { 61728 min: this.config.min === undefined ? 0 : this.config.min, 61729 max: this.config.max === undefined ? 1 : this.config.max 61730 }; 61731 } else { 61732 this.dataRange = { 61733 min: this.config.min === undefined ? 0 : this.config.min, 61734 max: this.config.max === undefined ? 25 : this.config.max 61735 }; 61736 } 61737 } 61738 61739 return this; 61740 } 61741 61742 supportsWholeGenome() { 61743 return true; 61744 } 61745 61746 async getFeatures(chr, start, end) { 61747 const visibilityWindow = this.visibilityWindow; 61748 return this.featureSource.getFeatures({ 61749 chr, 61750 start, 61751 end, 61752 visibilityWindow 61753 }); 61754 } 61755 61756 draw(options) { 61757 const featureList = options.features; 61758 const ctx = options.context; 61759 const pixelWidth = options.pixelWidth; 61760 const pixelHeight = options.pixelHeight; 61761 61762 if (this.background) { 61763 IGVGraphics.fillRect(ctx, 0, 0, pixelWidth, pixelHeight, { 61764 'fillStyle': this.background 61765 }); 61766 } 61767 61768 IGVGraphics.strokeLine(ctx, 0, pixelHeight - 1, pixelWidth, pixelHeight - 1, { 61769 'strokeStyle': this.divider 61770 }); 61771 61772 if (featureList) { 61773 const bpPerPixel = options.bpPerPixel; 61774 const bpStart = options.bpStart; 61775 const bpEnd = bpStart + pixelWidth * bpPerPixel + 1; 61776 61777 for (let variant of featureList) { 61778 const pos = variant.start; 61779 if (pos < bpStart) continue; 61780 if (pos > bpEnd) break; 61781 const colorScale = this.getColorScale(variant._f ? variant._f.chr : variant.chr); 61782 let color; 61783 let val; 61784 61785 if (this.posteriorProbability) { 61786 val = variant[this.valueProperty]; 61787 color = colorScale.getColor(val); 61788 } else { 61789 const pvalue = variant[this.valueProperty]; 61790 if (!pvalue) continue; 61791 val = -Math.log10(pvalue); 61792 color = colorScale.getColor(val); 61793 } 61794 61795 const yScale = (this.dataRange.max - this.dataRange.min) / pixelHeight; 61796 const px = Math.round((pos - bpStart) / bpPerPixel); 61797 const py = Math.max(this.dotSize, pixelHeight - Math.round((val - this.dataRange.min) / yScale)); 61798 61799 if (color) { 61800 IGVGraphics.setProperties(ctx, { 61801 fillStyle: color, 61802 strokeStyle: "black" 61803 }); 61804 } 61805 61806 IGVGraphics.fillCircle(ctx, px, py, this.dotSize); 61807 variant.px = px; 61808 variant.py = py; 61809 } 61810 } 61811 } 61812 61813 getColorScale(chr) { 61814 if (this.useChrColors) { 61815 let cs = this.colorScales[chr]; 61816 61817 if (!cs) { 61818 const color = Colors[chr] || randomColor(); 61819 cs = new ConstantColorScale(color); 61820 this.colorScales[chr] = cs; 61821 } 61822 61823 return cs; 61824 } else { 61825 return this.colorScales("*"); 61826 } 61827 } 61828 61829 paintAxis(ctx, pixelWidth, pixelHeight) { 61830 IGVGraphics.fillRect(ctx, 0, 0, pixelWidth, pixelHeight, { 61831 'fillStyle': "rgb(255, 255, 255)" 61832 }); 61833 var font = { 61834 'font': 'normal 10px Arial', 61835 'textAlign': 'right', 61836 'strokeStyle': "black" 61837 }; 61838 const yScale = (this.dataRange.max - this.dataRange.min) / pixelHeight; 61839 61840 if (this.posteriorProbability) { 61841 const n = 0.1; 61842 61843 for (let p = this.dataRange.min; p < this.dataRange.max; p += n) { 61844 const yp = pixelHeight - Math.round((p - this.dataRange.min) / yScale); 61845 IGVGraphics.strokeLine(ctx, 45, yp - 2, 50, yp - 2, font); // Offset dashes up by 2 pixel 61846 61847 IGVGraphics.fillText(ctx, p.toFixed(1), 44, yp + 2, font); // Offset numbers down by 2 pixels; 61848 } 61849 } else { 61850 const n = Math.ceil((this.dataRange.max - this.dataRange.min) * 10 / pixelHeight); 61851 61852 for (let p = this.dataRange.min; p < this.dataRange.max; p += n) { 61853 const yp = pixelHeight - Math.round((p - this.dataRange.min) / yScale); 61854 IGVGraphics.strokeLine(ctx, 45, yp, 50, yp, font); // Offset dashes up by 2 pixel 61855 61856 IGVGraphics.fillText(ctx, Math.floor(p), 44, yp + 4, font); // Offset numbers down by 2 pixels; 61857 } 61858 } 61859 61860 font['textAlign'] = 'center'; 61861 61862 if (this.posteriorProbability) { 61863 IGVGraphics.fillText(ctx, "PPA", pixelWidth / 2, pixelHeight / 2, font, { 61864 rotate: { 61865 angle: -90 61866 } 61867 }); 61868 } else { 61869 IGVGraphics.fillText(ctx, "-log10(pvalue)", pixelWidth / 2, pixelHeight / 2, font, { 61870 rotate: { 61871 angle: -90 61872 } 61873 }); 61874 } 61875 } 61876 61877 popupData(clickState) { 61878 let data = []; 61879 const track = clickState.viewport.trackView.track; 61880 const features = clickState.viewport.getCachedFeatures(); 61881 61882 if (features) { 61883 let count = 0; 61884 61885 for (let f of features) { 61886 const xDelta = Math.abs(clickState.canvasX - f.px); 61887 const yDelta = Math.abs(clickState.canvasY - f.py); 61888 const value = f[this.valueProperty]; 61889 61890 if (xDelta < this.dotSize && yDelta < this.dotSize) { 61891 if (count > 0) { 61892 data.push("<HR/>"); 61893 } 61894 61895 if (count == 5) { 61896 data.push("..."); 61897 break; 61898 } 61899 61900 if (typeof f.popupData === 'function') { 61901 data = data.concat(f.popupData()); 61902 } else { 61903 const chr = f.realChr || f.chr; 61904 const pos = (f.realStart || f.start) + 1; 61905 data.push({ 61906 name: 'chromosome', 61907 value: chr 61908 }); 61909 data.push({ 61910 name: 'position', 61911 value: pos 61912 }); 61913 data.push({ 61914 name: 'name', 61915 value: f.name 61916 }); 61917 61918 if (track.posteriorProbability) { 61919 data.push({ 61920 name: 'posterior probability', 61921 value: value 61922 }); 61923 } else { 61924 data.push({ 61925 name: 'pValue', 61926 value: value 61927 }); 61928 } 61929 } 61930 61931 count++; 61932 } 61933 } 61934 } 61935 61936 return data; 61937 } 61938 61939 menuItemList() {
61940 return MenuUtils.numericDataMenuItems(this.trackView); 61941 } 61942 61943 doAutoscale(featureList) { 61944 if (featureList.length > 0) { 61945 // posterior probabilities are treated without modification, but we need to take a negative logarithm of P values 61946 const valueProperty = this.valueProperty; 61947 const posterior = this.posteriorProbability; 61948 const features = featureList.map(function (feature) { 61949 const v = feature[valueProperty]; 61950 return { 61951 value: posterior ? v : -Math.log(v) / Math.LN10 61952 }; 61953 }); 61954 this.dataRange = doAutoscale(features); 61955 } else { 61956 // No features -- pick something reasonable for PPAs and p-values 61957 if (this.posteriorProbability) { 61958 this.dataRange.min = this.config.min || 0; 61959 this.dataRange.max = this.config.max || 1; 61960 } else { 61961 this.dataRange.max = this.config.max || 25; 61962 this.dataRange.min = this.config.min || 0; 61963 } 61964 } 61965 61966 return this.dataRange; 61967 } 61968 61969 } 61970 61971 const X_PIXEL_DIFF_THRESHOLD = 1; 61972 61973 class GCNVTrack extends TrackBase { 61974 constructor(config, browser) { 61975 super(config, browser); 61976 } 61977 61978 init(config) { 61979 super.init(config); 61980 this.autoscale = config.autoscale || config.max === undefined; 61981 this.dataRange = { 61982 min: config.min || 0, 61983 max: config.max 61984 }; 61985 this.windowFunction = config.windowFunction || "mean"; 61986 this.paintAxis = paintAxis; 61987 this.graphType = config.graphType || "bar"; //hack to avoid creating feature source multiple times. If config.type is not set the file must be read 61988 //to determine type, which results in creation of a feature source. 61989 61990 if (config._featureSource) { 61991 this.featureSource = config._featureSource; 61992 delete config._featureSource; 61993 } else { 61994 this.featureSource = FeatureSource(this.config, this.browser.genome); 61995 } // Visibility window hardcoded to -1 (== whole chromosome). Draw method needs feature beyond current view, 61996 // when/if this is resolved visibilityWindow can be used. 61997 61998 61999 this.visibilityWindow = -1; 62000 this.featureSource.visibilityWindow = this.visibilityWindow; 62001 } 62002 62003 async postInit() { 62004 if (typeof this.featureSource.getHeader === "function") { 62005 this.header = await this.featureSource.getHeader(); 62006 this.sampleNames = this.header.columnNames.slice(3); // Set generic properties from track line 62007 62008 this.setTrackProperties(this.header); // setTrackProperties defined in TrackBase 62009 // set option to highlight sample track line on click 62010 62011 if (this.header.hasOwnProperty("clickToHighlight")) { 62012 let colour = this.header["clickToHighlight"]; 62013 this.config.clickToHighlight = colour; 62014 this.config.samplesClickedToHighlight = {}; 62015 } // Special track line properties 62016 62017 62018 if (this.header.hasOwnProperty("highlight")) { 62019 this.config.highlightSamples = {}; 62020 let v = this.header["highlight"]; 62021 if (!Array.isArray(v)) v = [v]; 62022 62023 for (let h of v) { 62024 const tokens = h.split(";"); 62025 62026 if (tokens.length === 2) { 62027 this.config.highlightSamples[tokens[0]] = tokens[1]; 62028 } 62029 } 62030 } 62031 } 62032 } 62033 62034 menuItemList() { 62035 return MenuUtils.numericDataMenuItems(this.trackView); 62036 } 62037 62038 async getFeatures(chr, start, end) { 62039 const chrFeatures = await this.featureSource.getFeatures({ 62040 chr, 62041 start: 0, 62042 end: Number.MAX_SAFE_INTEGER, 62043 visibilityWindow: this.visibilityWindow 62044 }); 62045 let prevIndex = undefined; 62046 let nextIndex = undefined; 62047 62048 for (let i = 1; i < chrFeatures.length - 1; i++) { 62049 if (prevIndex === undefined && chrFeatures[i].end > start) { 62050 prevIndex = i - 1; 62051 } 62052 62053 if (nextIndex === undefined && chrFeatures[i].start > end) { 62054 nextIndex = i + 1; 62055 break; 62056 } 62057 } 62058 62059 if (prevIndex === undefined) prevIndex = 0; 62060 if (nextIndex === undefined) nextIndex = chrFeatures.length; 62061 return chrFeatures.slice(prevIndex, nextIndex); 62062 } 62063 62064 draw(options) { 62065 const { 62066 features, 62067 context, 62068 bpPerPixel, 62069 bpStart, 62070 pixelWidth, 62071 pixelHeight 62072 } = options; ///let baselineColor; 62073 //if (typeof self.color === "string" && self.color.startsWith("rgb(")) {
62074 // baselineColor = IGVColor.addAlpha(self.color, 0.1); 62075 //} 62076 62077 const yScale = yValue => { 62078 return (this.dataRange.max - yValue) / (this.dataRange.max - this.dataRange.min) * pixelHeight; 62079 }; 62080 62081 const getX = function (bpPosition) { 62082 let x = Math.floor((bpPosition - bpStart) / bpPerPixel); 62083 if (isNaN(x)) console.warn('isNaN(x). feature start ' + numberFormatter$1(bpPosition) + ' bp start ' + numberFormatter$1(bpStart)); 62084 return x; 62085 }; 62086 62087 const drawGuideLines = options => { 62088 if (this.config.hasOwnProperty('guideLines')) { 62089 for (let line of this.config.guideLines) { 62090 if (line.hasOwnProperty('color') && line.hasOwnProperty('y') && line.hasOwnProperty('dotted')) { 62091 let y = yScale(line.y); 62092 let props = { 62093 'strokeStyle': line['color'], 62094 'strokeWidth': 2 62095 }; 62096 if (line['dotted']) IGVGraphics.dashedLine(options.context, 0, y, options.pixelWidth, y, 5, props);else IGVGraphics.strokeLine(options.context, 0, y, options.pixelWidth, y, props); 62097 } 62098 } 62099 } 62100 }; 62101 62102 if (features && features.length > 0) { 62103 if (this.dataRange.min === undefined) this.dataRange.min = 0;
62103 // Max can be less than min if config.min is set but max left to autoscale. If that's the case there is 62104 // nothing to paint. 62105 62106 if (this.dataRange.max > this.dataRange.min) { 62107 const highlightSamples = this.config.highlightSamples; 62108 const onlyHandleClicksForHighlightedSamples = this.config.onlyHandleClicksForHighlightedSamples; 62109 const clickToHighlight = this.config.clickToHighlight; 62110 let previousEnd = -1; 62111 let previousValues = {}; 62112 let highlightConnectorLines = []; 62113 let highlightFeatureLines = []; // clickDetectorCache allows fast retrieval of whether a mouse click hits a rendered line segment 62114 // by storing lists of rendered line segments, keyed by their right x coordinate in canvas pixel space. 62115 // this cache is regenerated on every draw. 62116 62117 this.clickDetectorCache = {}; 62118 62119 for (let feature of features) { 62120 const x1 = getX(feature.start); 62121 const x2 = getX(feature.end); 62122 const previousX = previousEnd >= 0 ? getX(previousEnd) : x1; 62123 if (isNaN(x1) || isNaN(x2)) continue; // if ((x1 - previousX < X_PIXEL_DIFF_THRESHOLD) && (x2 - x1 < X_PIXEL_DIFF_THRESHOLD)) continue; 62124 62125 this.clickDetectorCache[x1] = []; 62126 this.clickDetectorCache[x2] = []; 62127 62128 for (let i = 0; i < feature.values.length; i++) { 62129 const sampleName = this.sampleNames[i]; 62130 const value = feature.values[i]; 62131 const y = yScale(value); 62132 62133 if (x1 - previousX >= X_PIXEL_DIFF_THRESHOLD) { 62134 const previousValue = previousValues[sampleName]; 62135 const previousY = yScale(previousValue); 62136 const highlightColor = highlightSamples && highlightSamples[sampleName]; 62137 62138 if (highlightColor) { 62139 highlightConnectorLines.push([previousX, previousY, x1, y, highlightColor]); 62140 } else if (clickToHighlight && sampleName in this.config.samplesClickedToHighlight) { 62141 highlightConnectorLines.push([previousX, previousY, x1, y, this.config.samplesClickedToHighlight[sampleName]]); 62142 } else { 62143 IGVGraphics.strokeLine(context, previousX, previousY, x1, y, { 62144 strokeStyle: '#D9D9D9' 62145 }); 62146 } 62147 62148 if (!onlyHandleClicksForHighlightedSamples || sampleName in highlightSamples) { 62149 this.clickDetectorCache[x1].push([previousX, previousY, x1, y, sampleName, highlightColor || 'gray']); 62150 } 62151 } 62152 62153 if (x2 - x1 >= X_PIXEL_DIFF_THRESHOLD) { 62154 const highlightColor = highlightSamples && highlightSamples[sampleName]; 62155 62156 if (highlightColor) { 62157 highlightFeatureLines.push([x1, y, x2, y, highlightColor]); 62158 } else if (clickToHighlight && sampleName in this.config.samplesClickedToHighlight) { 62159 highlightFeatureLines.push([x1, y, x2, y, this.config.samplesClickedToHighlight[sampleName]]); 62160 } else { 62161 IGVGraphics.strokeLine(context, x1, y, x2, y, { 62162 strokeStyle: 'gray' 62163 }); 62164 } 62165 62166 if (!onlyHandleClicksForHighlightedSamples || sampleName in highlightSamples) { 62167 this.clickDetectorCache[x2].push([x1, y, x2, y, sampleName, highlightColor || 'gray']); 62168 } 62169 } 62170 62171 previousValues[sampleName] = value; //IGVGraphics.fillCircle(ctx, px, y, pointSize / 2, {"fillStyle": color, "strokeStyle": color}); 62172 //IGVGraphics.fillRect(ctx, x, y, width, height, {fillStyle: color}); 62173 } 62174 62175 previousEnd = feature.end; 62176 } 62177 62178 for (let f of highlightConnectorLines) { 62179 IGVGraphics.strokeLine(context, f[0], f[1], f[2], f[3], { 62180 strokeStyle: f[4], 62181 lineWidth: 1.3 62182 }); 62183 } 62184 62185 for (let f of highlightFeatureLines) { 62186 IGVGraphics.strokeLine(context, f[0], f[1], f[2], f[3], {
62187 strokeStyle: f[4], 62188 lineWidth: 2 62189 }); 62190 } 62191 /* 62192 // If the track includes negative values draw a baseline 62193 if (this.dataRange.min < 0) { 62194 const basepx = (self.dataRange.max / (this.dataRange.max - this.dataRange.min)) * options.pixelHeight; 62195 IGVGraphics.strokeLine(context, 0, basepx, options.pixelWidth, basepx, {strokeStyle: baselineColor}); 62196 } 62197 */ 62198 62199 } 62200 } 62201 62202 drawGuideLines(options); 62203 } 62204 62205 doAutoscale(features) { 62206 let min, max; 62207 62208 if (features.length > 0) { 62209 min = Number.MAX_VALUE; 62210 max = -Number.MAX_VALUE; 62211 features.forEach(function (feature) { 62212 min = Math.min(min, ...feature.values); 62213 max = Math.max(max, ...feature.values); 62214 }); 62215 min -= 0.01; 62216 max += 0.01; 62217 } else { 62218 // No features -- default 62219 min = 0; 62220 max = 100; 62221 } 62222 62223 return { 62224 min: min, 62225 max: max 62226 }; 62227 } 62228 62229 clickedFeatures(clickState) { 62230 //console.warn('click', clickState.canvasX, clickState.canvasY, clickState) 62231 const BOUNDING_BOX_PADDING = 10; 62232 const MIN_DISTANCE_TO_SEGMENT = 5; 62233 const clickX = clickState.canvasX; 62234 const clickY = clickState.canvasY; 62235 let key = null; 62236 62237 for (key of Object.keys(this.clickDetectorCache)) { 62238 key = parseInt(key); 62239 62240 if (key >= clickX) { 62241 break; 62242 } 62243 } 62244 62245 if (key) { 62246 let closestDistanceSoFar = Number.MAX_VALUE; 62247 let closestResult = []; 62248 const segments = this.clickDetectorCache[key]; 62249 62250 for (let segment of segments) { 62251 const x1 = segment[0]; 62252 const x2 = segment[2]; 62253 if (clickX < x1 || clickX > x2) return []; 62254 const y1 = segment[1]; 62255 const y2 = segment[3]; 62256 if (clickY < Math.min(y1, y2) - BOUNDING_BOX_PADDING || clickY > Math.max(y1, y2) + BOUNDING_BOX_PADDING) continue; 62257 const distance = distanceToLine(clickX, clickY, x1, y1, x2, y2); 62258 62259 if (distance < closestDistanceSoFar) { 62260 closestResult = [{ 62261 'name': segment[4], 62262 'color': segment[5] 62263 }]; 62264 closestDistanceSoFar = distance; //console.warn('closest:', 'name', segment[4], 'color', segment[5], distance); 62265 } 62266 } 62267 62268 if (closestDistanceSoFar < MIN_DISTANCE_TO_SEGMENT) { 62269 // clickToHighlight set, add sample to dict of clicked lines 62270 if (this.config.clickToHighlight) { 62271 if (closestResult[0]['name'] in this.config.samplesClickedToHighlight) { 62272 // clicked sample already highlighted => remove if clicked again 62273 delete this.config.samplesClickedToHighlight[closestResult[0]['name']]; 62274 } else if (this.config.clickToHighlight === 'any') { 62275 var colourList = ['red', 'darkblue', 'green', 'teal', 'olivedrab', 'orange', 'maroon', 'purple', 'blue', 'gold']; 62276 var colour = colourList[Math.floor(Math.random() * (colourList.length + 1))]; 62277 this.config.samplesClickedToHighlight[closestResult[0]['name']] = colour; 62278 } else { 62279 this.config.samplesClickedToHighlight[closestResult[0]['name']] = this.config.clickToHighlight; 62280 } 62281 62282 this.trackView.repaintViews(); // prompt redraw to change colour of clicked sample 62283 } 62284 62285 return closestResult; 62286 } 62287 } 62288 62289 return []; 62290 } 62291 62292 popupData(clickState, featureList) { 62293 featureList = this.clickedFeatures(clickState, featureList); 62294 const items = []; 62295 featureList.forEach(function (f) { 62296 for (let property of Object.keys(f)) { 62297 if (isSimpleType(f[property])) { 62298 items.push({ 62299 name: property, 62300 value: f[property] 62301 }); 62302 } 62303 } 62304 }); 62305 return items; 62306 } 62307 62308 supportsWholeGenome() { 62309 return false;
62310 } 62311 62312 } 62313 62314 function distanceToLine(x, y, ax, ay, bx, by) { 62315 /* 62316 Finds distance between point (x, y) and line defined by points (ax, ay) (bx, by) 62317 based on http://mathworld.wolfram.com/Point-LineDistance2-Dimensional.html 62318 */ 62319 const bx_minus_ax = bx - ax; 62320 const by_minus_ay = by - ay; 62321 const v = Math.abs(bx_minus_ax * (ay - y) - (ax - x) * by_minus_ay); 62322 const r = Math.sqrt(bx_minus_ax * bx_minus_ax + by_minus_ay * by_minus_ay); 62323 const distance = r > 0 ? v / r : 0; //console.warn('Check if', x, y, 'is within', ax, ay, bx, by, '. Distance from line: ', distance); 62324 62325 return distance; 62326 } 62327 62328 /* 62329 * The MIT License (MIT) 62330 * 62331 * Copyright (c) 2014 Broad Institute 62332 * 62333 * Permission is hereby granted, free of charge, to any person obtaining a copy 62334 * of this software and associated documentation files (the "Software"), to deal 62335 * in the Software without restriction, including without limitation the rights 62336 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 62337 * copies of the Software, and to permit persons to whom the Software is 62338 * furnished to do so, subject to the following conditions: 62339 * 62340 * The above copyright notice and this permission notice shall be included in 62341 * all copies or substantial portions of the Software. 62342 * 62343 * 62344 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 62345 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 62346 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 62347 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 62348 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 62349 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 62350 * THE SOFTWARE. 62351 */ 62352 62353 class RnaStructTrack extends TrackBase { 62354 constructor(config, browser) { 62355 super(config, browser); // Set defaults 62356 62357 if (!config.height) { 62358 this.height = 300; 62359 } 62360 62361 this.arcOrientation = false; 62362 this.theta = Math.PI / 2; 62363 62364 if ("bp" === config.format) { 62365 this.featureSource = new RNAFeatureSource(config, browser.genome); 62366 } else { 62367 this.featureSource = new TextFeatureSource(config, browser.genome); 62368 } 62369 } 62370 62371 async getFeatures(chr, start, end) { 62372 const visibilityWindow = this.visibilityWindow; 62373 return this.featureSource.getFeatures({ 62374 chr, 62375 start, 62376 end, 62377 visibilityWindow 62378 }); 62379 } 62380 62381 draw(options) { 62382 const ctx = options.context; 62383 const theta = Math.PI / 2; 62384 const pixelWidth = options.pixelWidth; 62385 const pixelHeight = options.pixelHeight; 62386 options.viewportWidth; 62387 const bpPerPixel = options.bpPerPixel; 62388 const bpStart = options.bpStart; 62389 const xScale = bpPerPixel; 62390 const orienation = this.arcOrientation; 62391 IGVGraphics.fillRect(ctx, 0, options.pixelTop, pixelWidth, pixelHeight, { 62392 'fillStyle': "rgb(255, 255, 255)" 62393 }); 62394 const featureList = options.features; 62395 62396 if (featureList) { 62397 // Sort by score -- draw lowest scored features first 62398 sortByScore(featureList, 1); 62399 62400 for (let feature of featureList) { 62401 if (feature.startLeft) { 62402 let sl = Math.round((feature.startLeft - bpStart) / xScale); 62403 let sr = Math.round((feature.startRight - bpStart) / xScale); 62404 let el = Math.round((feature.endLeft - bpStart) / xScale); 62405 let er = Math.round((feature.endRight - bpStart) / xScale); 62406 ctx.fillStyle = feature.color; 62407 ctx.strokeStyle = feature.color; 62408 ctx.beginPath(); // First arc 62409 62410 let x1 = (sl + er) / 2; 62411 let r1 = (er - sl) / 2; 62412 let y1 = this.height; 62413 let sa = Math.PI + (Math.PI / 2 - theta); 62414 let ea = 2 * Math.PI - (Math.PI / 2 - theta); 62415 62416 if (orienation) { 62417 y1 = 0; 62418 ctx.arc(x1, y1, r1, ea, sa); 62419 ctx.lineTo(er, y1); 62420 } else { 62421 ctx.arc(x1, y1, r1, sa, ea); 62422 ctx.lineTo(el, y1); 62423 } // Second arc 62424 62425 62426 const x2 = (sr + el) / 2; 62427 const r2 = (el - sr) / 2; 62428 const y2 = y1; // Only for theta == pi/2 62429 62430 if (orienation) { 62431 ctx.arc(x2, y2, r2, sa, ea, true); 62432 ctx.lineTo(el, y2); 62433 } else { 62434 ctx.arc(x2, y2, r2, ea, sa, true); 62435 ctx.lineTo(sl, y2); 62436 } 62437 62438 ctx.stroke(); 62439 ctx.fill(); 62440 feature.drawState = { 62441 x1: x1, 62442 y1: y1, 62443 r1: r1, 62444 x2: x2, 62445 y2: y2, 62446 r2: r2, 62447 sa: sa, 62448 ea: ea 62449 }; 62450 } else { 62451 let s = Math.round((feature.start - bpStart) / xScale); 62452 let e = Math.round((feature.end - bpStart) / xScale); 62453 ctx.strokeStyle = feature.color; 62454 ctx.beginPath(); // First arc 62455 62456 let x = (s + e) / 2; 62457 let r = (e - s) / 2; 62458 let y = this.height; 62459 let sa = Math.PI + (Math.PI / 2 - theta); 62460 let ea = 2 * Math.PI - (Math.PI / 2 - theta); 62461 62462 if (orienation) { 62463 y = 0; 62464 ctx.arc(x, y, r, ea, sa); 62465 } else { 62466 ctx.arc(x, y, r, sa, ea); 62467 } 62468 62469 ctx.stroke(); 62470 feature.drawState = { 62471 x1: x, 62472 y1: y, 62473 r1: r, 62474 sa: sa, 62475 ea: ea 62476 }; 62477 } 62478 } 62479 } 62480 } 62481 62482 clickedFeatures(clickState, features) { 62483 features = super.clickedFeatures(clickState, features); 62484 const clicked = []; // Sort by score in descending order (opposite order than drawn) 62485 62486 sortByScore(features, -1); 62487 62488 for (let f of features) { 62489 const ds = f.drawState;
62489 // Distance from arc radius, or outer arc for type ".bp" 62490 62491 const dx1 = clickState.canvasX - ds.x1; 62492 const dy1 = clickState.canvasY - ds.y1; 62493 const d1 = Math.sqrt(dx1 * dx1 + dy1 * dy1); 62494 const outerLim = ds.r1 + 3; 62495 let d2; 62496 let innerLim; 62497 62498 if (ds.x2 === undefined) { 62499 d2 = d1; 62500 innerLim = ds.r1 - 3; 62501 } else { 62502 const dx2 = clickState.canvasX - ds.x2; 62503 const dy2 = clickState.canvasY - ds.y2; 62504 d2 = Math.sqrt(dx2 * dx2 + dy2 * dy2); 62505 innerLim = ds.r2 - 3; 62506 } // Between outer and inner arcs, with some tolerance 62507 62508 62509 if (d1 < outerLim && d2 > innerLim) { 62510 clicked.push(f); 62511 break; 62512 } 62513 } 62514 62515 return clicked; 62516 } 62517 62518 popupData(clickState, features) { 62519 // We use the featureCache property rather than method to avoid async load. If the 62520 // feature is not already loaded this won't work, but the user wouldn't be mousing over it either. 62521 features = this.clickedFeatures(clickState, features); 62522 62523 if (features && features.length > 0) { 62524 return TrackBase.extractPopupData(features[0], this.getGenomeId()); 62525 } 62526 } 62527 62528 menuItemList() { 62529 var self = this; 62530 return [{ 62531 name: "Toggle arc direction", 62532 click: function () { 62533 self.arcOrientation = !self.arcOrientation; 62534 self.trackView.repaintViews(); 62535 } 62536 }]; 62537 } 62538 62539 } 62540 62541 function sortByScore(featureList, direction) { 62542 featureList.sort(function (a, b) { 62543 const s1 = a.score === undefined ? -Number.MAX_VALUE : a.score; 62544 const s2 = b.score === undefined ? -Number.MAX_VALUE : b.score; 62545 const d = direction === undefined ? 1 : direction; 62546 return d * (s1 - s2); 62547 }); 62548 } 62549 62550 class RNAFeatureSource { 62551 constructor(config, genome) { 62552 this.config = config; 62553 this.genome = genome; 62554 } 62555 62556 async getFeatures(_ref) { 62557 let { 62558 chr, 62559 start, 62560 end, 62561 bpPerPixel, 62562 visibilityWindow 62563 } = _ref; 62564 const genome = this.genome; 62565 62566 if (!this.featureCache) { 62567 const options = buildOptions(this.config); 62568 const data = await igvxhr.loadString(this.config.url, options); 62569 this.featureCache = new FeatureCache(parseBP(data), genome); 62570 return this.featureCache.queryFeatures(chr, start, end); 62571 } else { 62572 return this.featureCache.queryFeatures(chr, start, end); 62573 } 62574 62575 function parseBP(data) { 62576 if (!data) return null; 62577 const dataWrapper = getDataWrapper(data); 62578 let header = true; 62579 let line; 62580 const colors = []; 62581 const descriptors = []; 62582 const features = []; 62583 62584 while ((line = dataWrapper.nextLine()) !== undefined) { 62585 const tokens = line.split('\t'); 62586 62587 if (header && line.startsWith("color:")) { 62588 const color = "rgb(" + tokens[1] + "," + tokens[2] + "," + tokens[3] + ")"; 62589 colors.push(color); 62590 62591 if (tokens.length > 4) { 62592 descriptors.push(tokens[4]); 62593 } // TODO - use label 62594 62595 } else { 62596 header = false;
62597 const chr = tokens[0]; 62598 const startLeftNuc = Number.parseInt(tokens[1]) - 1; 62599 const startRightNuc = Number.parseInt(tokens[2]) - 1; 62600 const endLeftNuc = Number.parseInt(tokens[3]); 62601 const endRightNuc = Number.parseInt(tokens[4]); 62602 var colorIdx = Number.parseInt(tokens[5]); 62603 const color = colors[colorIdx]; 62604 let feature; 62605 62606 if (startLeftNuc <= endRightNuc) { 62607 feature = { 62608 chr: chr, 62609 startLeft: Math.min(startLeftNuc, startRightNuc), 62610 startRight: Math.max(startLeftNuc, startRightNuc), 62611 endLeft: Math.min(endLeftNuc, endRightNuc), 62612 endRight: Math.max(endLeftNuc, endRightNuc), 62613 color: color, 62614 score: colorIdx 62615 }; 62616 } else { 62617 feature = { 62618 chr: chr, 62619 startLeft: Math.min(endLeftNuc, endRightNuc), 62620 startRight: Math.max(endLeftNuc, endRightNuc), 62621 endLeft: Math.min(startLeftNuc, startRightNuc), 62622 endRight: Math.max(startLeftNuc, startRightNuc), 62623 color: color, 62624 score: colorIdx 62625 }; 62626 } 62627 62628 feature.start = feature.startLeft; 62629 feature.end = feature.endRight; 62630 62631 if (descriptors.length > colorIdx) { 62632 feature.description = descriptors[colorIdx]; 62633 } 62634 62635 features.push(feature); 62636 } 62637 } 62638 62639 return features; 62640 } 62641 } 62642 62643 } 62644 62645 /* 62646 * The MIT License (MIT) 62647 * 62648 * Copyright (c) 2014 Broad Institute 62649 * 62650 * Permission is hereby granted, free of charge, to any person obtaining a copy 62651 * of this software and associated documentation files (the "Software"), to deal 62652 * in the Software without restriction, including without limitation the rights 62653 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 62654 * copies of the Software, and to permit persons to whom the Software is 62655 * furnished to do so, subject to the following conditions: 62656 * 62657 * The above copyright notice and this permission notice shall be included in 62658 * all copies or substantial portions of the Software. 62659 * 62660 * 62661 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 62662 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 62663 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 62664 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 62665 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 62666 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 62667 * THE SOFTWARE. 62668 */ 62669 62670 class IdeogramTrack { 62671 constructor(browser) { 62672 this.browser = browser; 62673 this.type = 'ideogram'; 62674 this.id = this.type; 62675 this.height = 16; 62676 this.order = Number.MIN_SAFE_INTEGER; 62677 this.disableButtons = true; 62678 this.ignoreTrackMenu = true; 62679 } 62680 62681 async getFeatures(chr, start, end) { 62682 return []; 62683 } 62684 62685 computePixelHeight(ignore) { 62686 return this.height; 62687 } 62688 62689 draw(_ref) { 62690 let { 62691 context, 62692 referenceFrame, 62693 pixelWidth, 62694 pixelHeight 62695 } = _ref; 62696 const chr = referenceFrame.chr; 62697 const chromosome = referenceFrame.genome.getChromosome(chr); 62698 62699 if (undefined === chromosome || pixelWidth <= 0 || pixelHeight <= 0 || 'all' === chr.toLowerCase()) { 62700 return; 62701 } 62702 62703 const stainColors = []; 62704 drawIdeogram({ 62705 ctx: context, 62706 chr, 62707 referenceFrame, 62708 genome: referenceFrame.genome, 62709 width: pixelWidth, 62710 height: pixelHeight, 62711 stainColors 62712 }); 62713 const widthBP = Math.round(referenceFrame.bpPerPixel * pixelWidth); 62714 const xBP = referenceFrame.start; // Total chromosome length can be > chromosome.bpLength for partial fastas. 62715 62716 let chrLength = chromosome.bpLength; 62717 const cytobands = referenceFrame.genome.getCytobands(chr); 62718 62719 if (cytobands && cytobands.length > 0 && cytobands[cytobands.length - 1].end) { 62720 chrLength = Math.max(chrLength, cytobands[cytobands.length - 1].end); 62721 chromosome.bpLength = chrLength; // Correct bp length, bit of a hack 62722 } 62723 62724 if (widthBP < chrLength) { 62725 const percentWidth = widthBP / chrLength; 62726 const percentX = xBP / chrLength; 62727 let x = Math.floor(percentX * pixelWidth); 62728 let ww = Math.floor(percentWidth * pixelWidth); 62729 x = Math.max(0, x); 62730 x = Math.min(pixelWidth - ww, x); // Push current context 62731 62732 context.save(); // Draw red box 62733 62734 context.strokeStyle = "red"; 62735 context.lineWidth = ww < 2 ? 1 : 2; 62736 const xx = x + context.lineWidth / 2; 62737 ww = ww < 2 ? 1 : ww - context.lineWidth; 62738 const yy = context.lineWidth / 2;
62739 const hh = pixelHeight - context.lineWidth; 62740 context.strokeRect(xx, yy, ww, hh); // Pop current context 62741 62742 context.restore(); 62743 } 62744 } 62745 62746 dispose() { 62747 this.trackView = undefined; 62748 } 62749 62750 } 62751 62752 function drawIdeogram(_ref2) { 62753 let { 62754 ctx, 62755 chr, 62756 referenceFrame, 62757 genome, 62758 width, 62759 height, 62760 stainColors 62761 } = _ref2; 62762 const shim = 1; 62763 const shim2 = 0.5 * shim; 62764 const ideogramTop = 0; 62765 62766 if (undefined === genome) { 62767 return; 62768 } 62769 62770 IGVGraphics.fillRect(ctx, 0, 0, width, height, { 62771 fillStyle: IGVColor.greyScale(255) 62772 }); 62773 const cytobands = genome.getCytobands(chr); 62774 62775 if (cytobands) { 62776 const center = ideogramTop + height / 2; 62777 const xC = []; 62778 const yC = []; 62779 62780 if (0 === cytobands.length) { 62781 return; 62782 } // Get chrLength from the cytobands -- chromsome.bpLength might not work for igv-reports fasta files, which 62783 // contain only a portion of the chromosome sequence 62784 // *DOESNT WORK* const chrLength = referenceFrame.genome.getChromosome(chr).bpLength; 62785 62786 62787 const chrLength = cytobands[cytobands.length - 1].end; 62788 const scale = width / chrLength; // round rect clipping path 62789 62790 ctx.beginPath(); 62791 IGVGraphics.roundRect(ctx, shim2, shim2 + ideogramTop, width - 2 * shim2, height - 2 * shim2, (height - 2 * shim2) / 2, 0, 1); 62792 ctx.clip(); 62793 62794 for (let i = 0; i < cytobands.length; i++) { 62795 const cytoband = cytobands[i]; 62796 const start = scale * cytoband.start; 62797 const end = scale * cytoband.end; 62798 62799 if (cytoband.type === 'c') { 62800 if (cytoband.name.charAt(0) === 'p') { 62801 xC[0] = start; 62802 yC[0] = height + ideogramTop; 62803 xC[1] = start; 62804 yC[1] = ideogramTop; 62805 xC[2] = end; 62806 yC[2] = center; 62807 } else { 62808 xC[0] = end; 62809 yC[0] = height + ideogramTop; 62810 xC[1] = end; 62811 yC[1] = ideogramTop; 62812 xC[2] = start; 62813 yC[2] = center; 62814 } 62815 62816 ctx.fillStyle = "rgb(150, 0, 0)"; 62817 ctx.strokeStyle = "rgb(150, 0, 0)"; 62818 IGVGraphics.polygon(ctx, xC, yC, 1, 0); 62819 } else { 62820 ctx.fillStyle = getCytobandColor(stainColors, cytoband); 62821 IGVGraphics.fillRect(ctx, start, shim + ideogramTop, end - start, height - 2 * shim); 62822 } 62823 } 62824 } // round rect border 62825 62826 62827 ctx.strokeStyle = IGVColor.greyScale(41); 62828 IGVGraphics.roundRect(ctx, shim2, shim2 + ideogramTop, width - 2 * shim2, height - 2 * shim2, (height - 2 * shim2) / 2, 0, 1); 62829 } 62830 62831 function getCytobandColor(colors, data) { 62832 if (data.type === 'c') { 62833 // centermere: "acen" 62834 return "rgb(150, 10, 10)"; 62835 } else { 62836 var stain = data.stain; // + 4; 62837 62838 var shade = 230; 62839 62840 if (data.type === 'p') { 62841 shade = Math.floor(230 - stain / 100.0 * 230); 62842 } 62843 62844 var c = colors[shade]; 62845 62846 if (!c) { 62847 c = "rgb(" + shade + "," + shade + "," + shade + ")"; 62848 colors[shade] = c; 62849 } 62850 62851 return c; 62852 } 62853 } 62854 62855 /* 62856 * The MIT License (MIT) 62857 * 62858 * Copyright (c) 2014 Broad Institute 62859 * 62860 * Permission is hereby granted, free of charge, to any person obtaining a copy 62861 * of this software and associated documentation files (the "Software"), to deal 62862 * in the Software without restriction, including without limitation the rights 62863 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 62864 * copies of the Software, and to permit persons to whom the Software is 62865 * furnished to do so, subject to the following conditions: 62866 * 62867 * The above copyright notice and this permission notice shall be included in 62868 * all copies or substantial portions of the Software. 62869 * 62870 * 62871 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 62872 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 62873 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 62874 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 62875 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 62876 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 62877 * THE SOFTWARE. 62878 */ 62879 let JUNCTION_MOTIF_PALETTE = new PaletteColorTable("Dark2"); // Lock in color-to-motif mapping so it's independent of data loading order. This list may not include all possible
62880 // motif values as this varies depending on the RNA-seq pipeline. The current list is based on STAR v2.4 docs. 62881 62882 const someMotifValues = ['GT/AG', 'CT/AC', 'GC/AG', 'CT/GC', 'AT/AC', 'GT/AT', 'non-canonical']; 62883 someMotifValues.forEach(motif => { 62884 JUNCTION_MOTIF_PALETTE.getColor(motif); 62885 }); // rendering context with values that only need to be computed once per render, rather than for each splice junction 62886 62887 const junctionRenderingContext = {}; 62888 62889 class SpliceJunctionTrack extends TrackBase { 62890 constructor(config, browser) { 62891 super(config, browser); 62892 } 62893 62894 init(config) { 62895 super.init(config); 62896 this.type = config.type || 'junctions'; 62897 62898 if (config._featureSource) { 62899 this.featureSource = config._featureSource; 62900 delete config._featureSource; 62901 } else { 62902 this.featureSource = config.featureSource ? config.featureSource : FeatureSource(config, this.browser.genome); 62903 } 62904 62905 this.margin = config.margin === undefined ? 10 : config.margin; 62906 62907 if (!this.height) { 62908 this.height = 100; 62909 } //set defaults 62910 62911 62912 if (config.colorByNumReadsThreshold === undefined) { 62913 config.colorByNumReadsThreshold = 5; 62914 } 62915 } 62916 62917 async postInit() { 62918 if (typeof this.featureSource.getHeader === "function") { 62919 this.header = await this.featureSource.getHeader(); 62920 } // Set properties from track line 62921 62922 62923 if (this.header) { 62924 this.setTrackProperties(this.header); 62925 } 62926 62927 if (this.visibilityWindow === undefined && typeof this.featureSource.defaultVisibilityWindow === 'function') { 62928 this.visibilityWindow = await this.featureSource.defaultVisibilityWindow(); 62929 } 62930 62931 return this; 62932 } 62933 62934 supportsWholeGenome() { 62935 return false; 62936 } 62937 62938 async getFeatures(chr, start, end, bpPerPixel) { 62939 const visibilityWindow = this.visibilityWindow; 62940 return this.featureSource.getFeatures({ 62941 chr, 62942 start, 62943 end, 62944 bpPerPixel, 62945 visibilityWindow 62946 }); 62947 } 62948 62949 /** 62950 * The required height in pixels required for the track content. This is not the visible track height, which 62951 * can be smaller (with a scrollbar) or larger. 62952 * 62953 * @param features 62954 * @returns {*} 62955 */ 62956 computePixelHeight(features) { 62957 return this.height; 62958 } 62959 62960 draw(options) { 62961 const featureList = options.features; 62962 const ctx = options.context; 62963 const bpPerPixel = options.bpPerPixel; 62964 const bpStart = options.bpStart; 62965 const pixelWidth = options.pixelWidth; 62966 const pixelHeight = options.pixelHeight; 62967 const bpEnd = bpStart + pixelWidth * bpPerPixel + 1; 62968 62969 if (!this.config.isMergedTrack) { 62970 IGVGraphics.fillRect(ctx, 0, options.pixelTop, pixelWidth, pixelHeight, { 62971 'fillStyle': "rgb(255, 255, 255)" 62972 }); 62973 } 62974 62975 if (featureList) { 62976 junctionRenderingContext.referenceFrame = options.viewport.referenceFrame; 62977 junctionRenderingContext.referenceFrameStart = junctionRenderingContext.referenceFrame.start; 62978 junctionRenderingContext.referenceFrameEnd = junctionRenderingContext.referenceFrameStart + junctionRenderingContext.referenceFrame.toBP($$1(options.viewport.contentDiv).width()); // For a given viewport, records where features that are < 2px in width have been rendered already. 62979 // This prevents wasteful rendering of multiple such features onto the same pixels. 62980 62981 junctionRenderingContext.featureZoomOutTracker = {}; 62982 62983 for (let feature of featureList) { 62984 if (feature.end < bpStart) continue; 62985 if (feature.start > bpEnd) break; 62986 this.renderJunction(feature, bpStart, bpPerPixel, pixelHeight, ctx); 62987 } 62988 } else { 62989 console.log("No feature list"); 62990 } 62991 } 62992 62993 /** 62994 * 62995 * @param feature 62996 * @param bpStart genomic location of the left edge of the current canvas 62997 * @param xScale scale in base-pairs per pixel 62998 * @param pixelHeight pixel height of the current canvas 62999 * @param ctx the canvas 2d context 63000 */ 63001 renderJunction(feature, bpStart, xScale, pixelHeight, ctx) { 63002 // cache whether this junction is rendered or filtered out. Use later to exclude non-rendered junctions from click detection. 63003 feature.isVisible = false;
63004 const junctionLeftPx = Math.round((feature.start - bpStart) / xScale); 63005 const junctionRightPx = Math.round((feature.end - bpStart) / xScale); 63006 const junctionMiddlePx = (junctionLeftPx + junctionRightPx) / 2; 63007 63008 if (junctionRightPx - junctionLeftPx <= 3) { 63009 if (junctionMiddlePx in junctionRenderingContext.featureZoomOutTracker) { 63010 return; 63011 } 63012 63013 junctionRenderingContext.featureZoomOutTracker[junctionMiddlePx] = true; 63014 } // TODO: cache filter and pixel calculations by doing them earlier when features are initially parsed? 63015 63016 63017 if (this.config.hideAnnotatedJunctions && feature.attributes.annotated_junction === "true") { 63018 return; 63019 } 63020 63021 if (this.config.hideUnannotatedJunctions && feature.attributes.annotated_junction === "false") { 63022 return; 63023 } 63024 63025 if (this.config.hideMotifs && this.config.hideMotifs.includes(feature.attributes.motif)) { 63026 return; 63027 } 63028 63029 if (this.config.hideStrand === feature.strand) { 63030 return; 63031 } // check if splice junction is inside viewport 63032 63033 63034 if (this.config.minJunctionEndsVisible) { 63035 let numJunctionEndsVisible = 0; 63036 63037 if (feature.start >= junctionRenderingContext.referenceFrameStart && feature.start <= junctionRenderingContext.referenceFrameEnd) { 63038 numJunctionEndsVisible += 1; 63039 } 63040 63041 if (feature.end >= junctionRenderingContext.referenceFrameStart && feature.end <= junctionRenderingContext.referenceFrameEnd) { 63042 numJunctionEndsVisible += 1; 63043 } 63044 63045 if (numJunctionEndsVisible < this.config.minJunctionEndsVisible) { 63046 return; 63047 } 63048 } 63049 63050 let uniquelyMappedReadCount; 63051 let multiMappedReadCount; 63052 let totalReadCount; 63053 63054 if (feature.attributes.uniquely_mapped) { 63055 uniquelyMappedReadCount = parseInt(feature.attributes.uniquely_mapped); 63056 63057 if (uniquelyMappedReadCount < this.config.minUniquelyMappedReads) { 63058 return; 63059 } 63060 63061 multiMappedReadCount = parseInt(feature.attributes.multi_mapped); 63062 totalReadCount = uniquelyMappedReadCount + multiMappedReadCount; 63063 63064 if (totalReadCount < this.config.minTotalReads) { 63065 return; 63066 } 63067 63068 if (totalReadCount > 0 && multiMappedReadCount / totalReadCount > this.config.maxFractionMultiMappedReads) { 63069 return; 63070 } 63071 63072 if (feature.attributes.maximum_spliced_alignment_overhang && parseInt(feature.attributes.maximum_spliced_alignment_overhang) < this.config.minSplicedAlignmentOverhang) { 63073 return; 63074 } 63075 } 63076 63077 let numSamplesWithThisJunction; 63078 63079 if (feature.attributes.num_samples_with_this_junction) { 63080 numSamplesWithThisJunction = parseInt(feature.attributes.num_samples_with_this_junction); 63081 63082 if (this.config.minSamplesWithThisJunction && numSamplesWithThisJunction < this.config.minSamplesWithThisJunction) { 63083 return; 63084 } 63085 63086 if (this.config.maxSamplesWithThisJunction && numSamplesWithThisJunction > this.config.maxSamplesWithThisJunction) { 63087 return; 63088 } 63089 63090 if (feature.attributes.num_samples_total) { 63091 feature.attributes.percent_samples_with_this_junction = 100 * numSamplesWithThisJunction / Number(feature.attributes.num_samples_total); 63092 63093 if (this.config.minPercentSamplesWithThisJunction) { 63094 if (feature.attributes.percent_samples_with_this_junction < this.config.minPercentSamplesWithThisJunction || feature.attributes.percent_samples_with_this_junction > this.config.maxPercentSamplesWithThisJunction) { 63095 return; 63096 } 63097 } 63098 } 63099 } 63100 63101 const py = this.margin; 63102 const rowHeight = this.height; 63103 const cy = py + 0.5 * rowHeight; 63104 let topY = py; 63105 const bottomY = py + rowHeight; 63106 const bezierBottomY = bottomY - 10; // draw the junction arc 63107 63108 const bezierControlLeftPx = (junctionLeftPx + junctionMiddlePx) / 2; 63109 const bezierControlRightPx = (junctionMiddlePx + junctionRightPx) / 2; 63110 let lineWidth = 1; 63111 63112 if (feature.attributes.line_width) { 63113 lineWidth = Number(feature.attributes.line_width); 63114 } else { 63115 if (this.config.thicknessBasedOn === undefined || this.config.thicknessBasedOn === 'numUniqueReads') { 63116 lineWidth = uniquelyMappedReadCount; 63117 } else if (this.config.thicknessBasedOn === 'numReads') { 63118 lineWidth = totalReadCount; 63119 } else if (this.config.thicknessBasedOn === 'numSamplesWithThisJunction') { 63120 if (numSamplesWithThisJunction !== undefined) { 63121 lineWidth = numSamplesWithThisJunction; 63122 } 63123 } 63124 63125 lineWidth = 1 + Math.log(lineWidth + 1) / Math.log(12); 63126 } 63127 63128 let bounceHeight; 63129 63130 if (this.config.bounceHeightBasedOn === undefined || this.config.bounceHeightBasedOn === 'random') { 63131 // randomly but deterministically stagger topY coordinates to reduce overlap
63132 bounceHeight = (feature.start + feature.end) % 7; 63133 } else if (this.config.bounceHeightBasedOn === 'distance') { 63134 bounceHeight = 6 * (feature.end - feature.start) / (junctionRenderingContext.referenceFrameEnd - junctionRenderingContext.referenceFrameStart); 63135 } else if (this.config.bounceHeightBasedOn === 'thickness') { 63136 bounceHeight = 2 * lineWidth; 63137 } 63138 63139 topY += rowHeight * Math.max(7 - bounceHeight, 0) / 10; 63140 let color; 63141 63142 if (feature.attributes.color) { 63143 color = feature.attributes.color; // Explicit setting 63144 } else if (this.config.colorBy === undefined || this.config.colorBy === 'numUniqueReads') { 63145 color = uniquelyMappedReadCount > this.config.colorByNumReadsThreshold ? 'blue' : '#AAAAAA'; // color gradient? 63146 } else if (this.config.colorBy === 'numReads') { 63147 color = totalReadCount > this.config.colorByNumReadsThreshold ? 'blue' : '#AAAAAA'; 63148 } else if (this.config.colorBy === 'isAnnotatedJunction') { 63149 color = feature.attributes.annotated_junction === "true" ? '#b0b0ec' : 'orange'; 63150 } else if (this.config.colorBy === 'strand') { 63151 color = feature.strand === "+" ? '#b0b0ec' : '#ecb0b0'; 63152 } else if (this.config.colorBy === 'motif') { 63153 color = JUNCTION_MOTIF_PALETTE.getColor(feature.attributes.motif); 63154 } else { 63155 color = '#AAAAAA'; 63156 } 63157 63158 let label = ""; 63159 63160 if (feature.attributes.label) { 63161 label = feature.attributes.label.replace(/_/g, " "); 63162 } else if (this.config.labelWith === undefined || this.config.labelWith === 'uniqueReadCount') { 63163 //default label 63164 label = uniquelyMappedReadCount; 63165 } else if (this.config.labelWith === 'totalReadCount') { 63166 label = totalReadCount; 63167 } else if (this.config.labelWith === 'numSamplesWithThisJunction') { 63168 if (numSamplesWithThisJunction !== undefined) { 63169 label = numSamplesWithThisJunction; 63170 } 63171 } else if (this.config.labelWith === 'percentSamplesWithThisJunction') { 63172 if (feature.attributes.percent_samples_with_this_junction !== undefined) { 63173 label = feature.attributes.percent_samples_with_this_junction.toFixed(0) + '%'; 63174 } 63175 } else if (this.config.labelWith === 'motif') { 63176 if (feature.attributes.motif !== undefined) { 63177 label += feature.attributes.motif; 63178 } 63179 } 63180 63181 if (this.config.labelWithInParen === 'uniqueReadCount') { 63182 label += ' (' + uniquelyMappedReadCount + ')'; 63183 } else if (this.config.labelWithInParen === 'totalReadCount') { 63184 label += ' (' + totalReadCount + ')'; 63185 } else if (this.config.labelWithInParen === 'multiMappedReadCount') { 63186 if (multiMappedReadCount > 0) { 63187 label += ' (+' + multiMappedReadCount + ')'; 63188 } 63189 } else if (this.config.labelWithInParen === 'numSamplesWithThisJunction') { 63190 if (numSamplesWithThisJunction !== undefined) { 63191 label += ' (' + numSamplesWithThisJunction + ')'; 63192 } 63193 } else if (this.config.labelWithInParen === 'percentSamplesWithThisJunction') { 63194 if (feature.attributes.percent_samples_with_this_junction !== undefined) { 63195 label += ' (' + feature.attributes.percent_samples_with_this_junction.toFixed(0) + '%)'; 63196 } 63197 } else if (this.config.labelWithInParen === 'motif') { 63198 if (feature.attributes.motif !== undefined) { 63199 label += ` ${feature.attributes.motif}`; 63200 } 63201 } // data source: STAR splice junctions (eg. SJ.out.tab file converted to bed). 63202 // .bed "name" field used to store unique + multi-mapped read counts, so: 63203 // feature.score: unique spanning read counts 63204 // feature.name: unique + multi-mapped spanning read counts 63205 //example feature: { chr: "chr17", start: 39662344, end: 39662803, name: "59", row: 0, score: 38, strand: "+"} 63206 63207 63208 feature.isVisible = true; 63209 ctx.beginPath(); 63210 ctx.moveTo(junctionLeftPx, bezierBottomY); 63211 ctx.bezierCurveTo(bezierControlLeftPx, topY, bezierControlRightPx, topY, junctionRightPx, bezierBottomY); 63212 ctx.lineWidth = lineWidth; 63213 ctx.strokeStyle = color; 63214 ctx.stroke(); 63215 63216 const drawArrowhead = (ctx, x, y, size) => { 63217 //TODO draw better arrow heads: https://stackoverflow.com/questions/21052972/curved-thick-arrows-on-canvas 63218 ctx.beginPath(); 63219 ctx.moveTo(x, y); 63220 ctx.lineTo(x - size / 2, y - size); 63221 ctx.lineTo(x + size / 2, y - size); 63222 ctx.lineTo(x, y); 63223 ctx.closePath(); 63224 ctx.fill(); 63225 }; 63226 63227 if (feature.attributes.left_shape || feature.attributes.right_shape) { 63228 ctx.fillStyle = color; 63229 const arrowSize = ctx.lineWidth > 2 ? 10 : 7; 63230 63231 if (feature.attributes.left_shape) { 63232 drawArrowhead(ctx, junctionLeftPx, bezierBottomY, arrowSize); 63233 } 63234 63235 if (feature.attributes.right_shape) { 63236 drawArrowhead(ctx, junctionRightPx, bezierBottomY, arrowSize); 63237 } 63238 } 63239 63240 ctx.fillText(label, junctionMiddlePx - ctx.measureText(label).width / 2, (7 * topY + cy) / 8); 63241 } 63242 63243 clickedFeatures(clickState, features) { 63244 const allFeatures = super.clickedFeatures(clickState, features); 63245 return allFeatures.filter(function (feature) { 63246 return feature.isVisible && feature.attributes; 63247 }); 63248 } 63249 /** 63250 * Return "popup data" for feature @ genomic location. Data is an array of key-value pairs 63251 */ 63252 63253 63254 popupData(clickState, features) { 63255 features = this.clickedFeatures(clickState, features); 63256 const genomicLocation = clickState.genomicLocation; 63257 const data = []; 63258 63259 for (let feature of features) { 63260 const featureData = typeof feature.popupData === "function" ? feature.popupData(genomicLocation) : this.extractPopupData(feature._f || feature, this.getGenomeId()); 63261 63262 if (featureData) { 63263 if (data.length > 0) { 63264 data.push("<hr/><hr/>"); 63265 } 63266 63267 Array.prototype.push.apply(data, featureData); 63268 } 63269 } 63270 63271 return data; 63272 } 63273 63274 description() { 63275 return this.name; 63276 } 63277 /** 63278 * Called when the track is removed. Do any needed cleanup here 63279 */ 63280 63281 63282 dispose() { 63283 this.trackView = undefined; 63284 } 63285 63286 } 63287 63288 const trackFunctions = new Map([['ideogram', (config, browser) => new IdeogramTrack(config, browser)], ['sequence', (config, browser) => new SequenceTrack(config, browser)], ['feature', (config, browser) => new FeatureTrack(config, browser)], ['seg', (config, browser) => new SegTrack(config, browser)], ['mut', (config, browser) => new SegTrack(config, browser)], ['maf', (config, browser) => new SegTrack(config, browser)], ['wig', (config, browser) => new WigTrack(config, browser)], ['merged', (config, browser) => new MergedTrack(config, browser)], ['alignment', (config, browser) => new BAMTrack(config, browser)], ['interaction', (config, browser) => new InteractionTrack(config, browser)], ['interact', (config, browser) => new InteractionTrack(config, browser)], ['variant', (config, browser) => new VariantTrack(config, browser)], ['eqtl', (config, browser) => new EqtlTrack(config, browser)], ['gwas', (config, browser) => new GWASTrack(config, browser)], ['arc', (config, browser) => new RnaStructTrack(config, browser)], ['gcnv', (config, browser) => new GCNVTrack(config, browser)], ['junction', (config, browser) => new SpliceJunctionTrack(config, browser)]]); 63289 /** 63290 * Add a track constructor the the factory lookup table. 63291 * 63292 * @param type 63293 * @param track 63294 */ 63295 63296 const addTrackCreatorFunction = function (type, track) { 63297 trackFunctions.set(type, track); 63298 }; 63299 63300 const getTrack = function (type, config, browser) { 63301 let trackKey; 63302 63303 switch (type) { 63304 case "annotation": 63305 case "genes": 63306 case "fusionjuncspan": 63307 case "snp": 63308 trackKey = "feature"; 63309 break; 63310 63311 case 'seg': 63312 case 'maf': 63313 case 'mut': 63314 trackKey = 'seg'; 63315 break; 63316 63317 case 'junctions': 63318 case 'splicejunctions': 63319 trackKey = 'junction'; 63320 break; 63321 63322 default: 63323 trackKey = type; 63324 } 63325 63326 return trackFunctions.has(trackKey) ? trackFunctions.get(trackKey)(config, browser) : undefined; 63327 }; 63328 63329 var TrackFactory = { 63330 tracks: trackFunctions, 63331 addTrack: addTrackCreatorFunction, 63332 getTrack 63333 }; 63334 63335 /* 63336 * The MIT License (MIT) 63337 * 63338 * Copyright (c) 2016-2017 The Regents of the University of California 63339 * Author: Jim Robinson 63340 * 63341 * Permission is hereby granted, free of charge, to any person obtaining a copy 63342 * of this software and associated documentation files (the "Software"), to deal 63343 * in the Software without restriction, including without limitation the rights 63344 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 63345 * copies of the Software, and to permit persons to whom the Software is 63346 * furnished to do so, subject to the following conditions: 63347 * 63348 * The above copyright notice and this permission notice shall be included in 63349 * all copies or substantial portions of the Software. 63350 * 63351 * 63352 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 63353 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 63354 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 63355 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 63356 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 63357 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 63358 * THE SOFTWARE. 63359 */ 63360 var defaultHighlightColor = "rgba(68, 134, 247, 0.25)"; 63361 63362 class ROI { 63363 constructor(config, genome) { 63364 this.config = config; 63365 this.name = config.name; 63366 this.roiSource = FeatureSource(config, genome); 63367 this.color = config.color || defaultHighlightColor; 63368 } 63369 63370 async getFeatures(chr, start, end) { 63371 return this.roiSource.getFeatures({ 63372 chr, 63373 start, 63374 end 63375 }); 63376 } 63377 63378 draw(drawConfiguration) { 63379 var endBP, region, coord, regions; 63380 regions = drawConfiguration.features; 63381 63382 if (!regions) { 63383 return; 63384 } 63385 63386 endBP = drawConfiguration.bpStart + (drawConfiguration.pixelWidth * drawConfiguration.bpPerPixel + 1); 63387 63388 for (var i = 0, len = regions.length; i < len; i++) { 63389 region = regions[i]; 63390 63391 if (region.end < drawConfiguration.bpStart) { 63392 continue; 63393 } 63394 63395 if (region.start > endBP) { 63396 break; 63397 } 63398 63399 coord = coordinates(region, drawConfiguration.bpStart, drawConfiguration.bpPerPixel); 63400 IGVGraphics.fillRect(drawConfiguration.context, coord.x, drawConfiguration.pixelTop, coord.width, drawConfiguration.pixelHeight, { 63401 fillStyle: this.color 63402 }); 63403 } 63404 } 63405 63406 } 63407 63408 function coordinates(region, startBP, bpp) { 63409 var ss, ee, width; 63410 ss = Math.round((region.start - startBP) / bpp); 63411 ee = Math.round((region.end - startBP) / bpp); 63412 width = ee - ss; 63413 63414 if (width < 3) { 63415 width = 3; 63416 ss -= 1; 63417 } 63418 63419 return { 63420 x: ss, 63421 width: width 63422 }; 63423 } 63424 63425 /* 63426 * The MIT License (MIT) 63427 * 63428 * Copyright (c) 2016-2017 The Regents of the University of California 63429 * Author: Jim Robinson 63430 * 63431 * Permission is hereby granted, free of charge, to any person obtaining a copy 63432 * of this software and associated documentation files (the "Software"), to deal 63433 * in the Software without restriction, including without limitation the rights 63434 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 63435 * copies of the Software, and to permit persons to whom the Software is 63436 * furnished to do so, subject to the following conditions: 63437 * 63438 * The above copyright notice and this permission notice shall be included in 63439 * all copies or substantial portions of the Software. 63440 * 63441 * 63442 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 63443 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 63444 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 63445 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 63446 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 63447 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 63448 * THE SOFTWARE. 63449 */ 63450 63451 /** 63452 * Minimal support for the legacy IGV desktop session format. 63453 */ 63454 class XMLSession {
63455 constructor(xmlString, knownGenomes) { 63456 const parser = new DOMParser(); 63457 const xmlDoc = parser.parseFromString(xmlString, "text/xml"); 63458 this.processRootNode(xmlDoc, knownGenomes); 63459 const resourceElements = xmlDoc.getElementsByTagName("Resource"); 63460 const trackElements = xmlDoc.getElementsByTagName("Track"); 63461 const hasTrackElements = trackElements && trackElements.length > 0; 63462 const tracks = []; 63463 this.tracks = tracks; 63464 const resourceMap = new Map(); 63465 Array.from(resourceElements).forEach(function (r, idx) { 63466 var config = { 63467 url: r.getAttribute("path"), 63468 indexURL: r.getAttribute("index"), 63469 order: idx 63470 }; 63471 resourceMap.set(config.url, config); 63472 63473 if (!hasTrackElements) { 63474 tracks.push(config); 63475 } 63476 }); // Check for optional Track section 63477 63478 if (hasTrackElements) { 63479 Array.from(trackElements).forEach(function (track) { 63480 const subtracks = track.getElementsByTagName("Track"); 63481 63482 if (subtracks && subtracks.length > 0) { 63483 const mergedTrack = { 63484 type: 'merged', 63485 tracks: [] 63486 }; 63487 extractTrackAttributes(track, mergedTrack); 63488 tracks.push(mergedTrack);
63489 Array.from(subtracks).forEach(function (t) { 63490 t.processed = true; 63491 const id = t.getAttribute("id"); 63492 const config = resourceMap.get(id); 63493 63494 if (config) { 63495 mergedTrack.tracks.push(config); 63496 extractTrackAttributes(t, config); 63497 config.autoscale = false; 63498 mergedTrack.height = config.height; // Add alpha for merged track colors. Alpha is not recorded by IGV desktop in XML session 63499 //const color = t.getAttribute("color"); 63500 //if (color) { 63501 // config.color = "rgba(" + color + ",0.5)"; 63502 //} 63503 } 63504 }); 63505 } else if (!track.processed) { 63506 const id = track.getAttribute("id"); 63507 const res = resourceMap.get(id); 63508 63509 if (res) { 63510 tracks.push(res); 63511 extractTrackAttributes(track, res); 63512 } 63513 } 63514 }); 63515 } 63516 } 63517 63518 processRootNode(xmlDoc, knownGenomes) { 63519 const elements = xmlDoc.getElementsByTagName("Session"); 63520 63521 if (!elements || elements.length === 0) ; 63522 63523 const session = elements.item(0); 63524 const genome = session.getAttribute("genome"); 63525 const locus = session.getAttribute("locus"); 63526 const ucscID = session.getAttribute("ucscID"); 63527 63528 if (knownGenomes && knownGenomes.hasOwnProperty(genome)) { 63529 this.genome = genome; 63530 } else { 63531 this.reference = { 63532 fastaURL: genome 63533 }; 63534 63535 if (ucscID) { 63536 this.reference.id = ucscID; 63537 } 63538 } 63539 63540 if (locus) { 63541 this.locus = locus; 63542 } 63543 } 63544 63545 } 63546 63547 function extractTrackAttributes(track, config) { 63548 config.name = track.getAttribute("name"); 63549 const color = track.getAttribute("color"); 63550 63551 if (color) { 63552 config.color = "rgb(" + color + ")"; 63553 } 63554 63555 const altColor = track.getAttribute("altColor"); 63556 63557 if (color) { 63558 config.altColor = "rgb(" + altColor + ")"; 63559 } 63560 63561 const height = track.getAttribute("height"); 63562 63563 if (height) { 63564 config.height = parseInt(height); 63565 } 63566 63567 const autoScale = track.getAttribute("autoScale"); 63568 63569 if (autoScale) { 63570 config.autoscale = autoScale === "true"; 63571 } 63572 63573 const autoscaleGroup = track.getAttribute("autoscaleGroup"); 63574 63575 if (autoscaleGroup) { 63576 config.autoscaleGroup = autoscaleGroup; 63577 } 63578 63579 const windowFunction = track.getAttribute("windowFunction"); 63580 63581 if (windowFunction) { 63582 config.windowFunction = windowFunction; 63583 } 63584 63585 const visWindow = track.getAttribute("visibilityWindow") || track.getAttribute("featureVisibilityWindow"); 63586 63587 if (visWindow) { 63588 config.visibilityWindow = visWindow; 63589 } 63590 63591 const indexed = track.getAttribute("indexed"); 63592 63593 if (indexed) { 63594 config.indexed = indexed === "true"; 63595 } 63596 63597 const normalize = track.getAttribute("normalize"); 63598 63599 if (normalize) { 63600 config.normalize = normalize === "true"; 63601 } 63602 63603 const dataRangeCltn = track.getElementsByTagName("DataRange"); 63604 63605 if (dataRangeCltn.length > 0) { 63606 const dataRange = dataRangeCltn.item(0); 63607 config.min = Number(dataRange.getAttribute("minimum")); 63608 config.max = Number(dataRange.getAttribute("maximum")); 63609 config.logScale = dataRange.getAttribute("type") === "LOG"; 63610 } 63611 } 63612 63613 /* 63614 * The MIT License (MIT) 63615 * 63616 * Copyright (c) 2014-2015 Broad Institute 63617 * 63618 * Permission is hereby granted, free of charge, to any person obtaining a copy 63619 * of this software and associated documentation files (the "Software"), to deal 63620 * in the Software without restriction, including without limitation the rights 63621 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 63622 * copies of the Software, and to permit persons to whom the Software is 63623 * furnished to do so, subject to the following conditions: 63624 * 63625 * The above copyright notice and this permission notice shall be included in 63626 * all copies or substantial portions of the Software. 63627 * 63628 * 63629 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 63630 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 63631 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 63632 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 63633 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 63634 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 63635 * THE SOFTWARE. 63636 */ 63637 const splitLines = splitLines$5; 63638 63639 class SampleInformation { 63640 constructor() { 63641 this.attributes = {}; 63642 this.plinkLoaded = false;
63643 } 63644 63645 async loadPlinkFile(url, config) { 63646 if (!config) config = {}; 63647 var options = buildOptions(config); // Add oauth token, if any 63648 63649 const data = await igvxhr.loadString(url, options); 63650 var lines = splitLines(data); 63651 63652 for (let line of lines) { 63653 var line_arr = line.split(' '); 63654 this.attributes[line_arr[1]] = { 63655 familyId: line_arr[0], 63656 fatherId: line_arr[2], 63657 motherId: line_arr[3], 63658 sex: line_arr[4], 63659 phenotype: line_arr[5] 63660 }; 63661 } 63662 63663 this.plinkLoaded = true; 63664 return this; 63665 } 63666 /** 63667 * Return the attributes for the given sample as a map-like object (key-value pairs) 63668 * @param sample 63669 */ 63670 63671 63672 getAttributes(sample) { 63673 return this.attributes[sample]; 63674 } 63675 63676 getAttributeNames() { 63677 if (this.hasAttributes()) { 63678 return Object.keys(this.attributes[Object.keys(this.attributes)[0]]); 63679 } else return []; 63680 } 63681 63682 hasAttributes() { 63683 return Object.keys(this.attributes).length > 0; 63684 } 63685 63686 } 63687 63688 function loadPlinkFile(url, config) { 63689 const si = new SampleInformation(); 63690 return si.loadPlinkFile(url, config); 63691 } 63692 63693 /* 63694 * The MIT License (MIT) 63695 * 63696 * Copyright (c) 2014 Broad Institute 63697 * 63698 * Permission is hereby granted, free of charge, to any person obtaining a copy 63699 * of this software and associated documentation files (the "Software"), to deal 63700 * in the Software without restriction, including without limitation the rights 63701 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 63702 * copies of the Software, and to permit persons to whom the Software is 63703 * furnished to do so, subject to the following conditions: 63704 * 63705 * The above copyright notice and this permission notice shall be included in 63706 * all copies or substantial portions of the Software. 63707 * 63708 * 63709 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 63710 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 63711 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 63712 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 63713 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 63714 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 63715 * THE SOFTWARE. 63716 */ 63717 class GtexSelection { 63718 constructor(gene, snp) { 63719 this.geneColors = {}; 63720 this.gene = null; 63721 this.snp = null; 63722 this.genesCount = 0; 63723 63724 if (gene) { 63725 this.gene = gene.toUpperCase(); 63726 this.geneColors[this.gene] = brewer[this.genesCount++]; 63727 } 63728 63729 if (snp) { 63730 this.snp = snp.toUpperCase(); 63731 } 63732 } 63733 63734 addGene(geneName) { 63735 if (!this.geneColors[geneName.toUpperCase()]) { 63736 this.geneColors[geneName.toUpperCase()] = brewer[this.genesCount++]; 63737 } 63738 } 63739 63740 colorForGene(geneName) { 63741 return this.geneColors[geneName.toUpperCase()]; 63742 } 63743 63744 } 63745 63746 var brewer = []; // Set +! 63747 63748 brewer.push("rgb(228,26,28)"); 63749 brewer.push("rgb(55,126,184)"); 63750 brewer.push("rgb(77,175,74)"); 63751 brewer.push("rgb(166,86,40)"); 63752 brewer.push("rgb(152,78,163)"); 63753 brewer.push("rgb(255,127,0)"); 63754 brewer.push("rgb(247,129,191)"); 63755 brewer.push("rgb(153,153,153)"); 63756 brewer.push("rgb(255,255,51)"); // #Set 2 63757 63758 brewer.push("rgb(102, 194, 165"); 63759 brewer.push("rgb(252, 141, 98"); 63760 brewer.push("rgb(141, 160, 203"); 63761 brewer.push("rgb(231, 138, 195"); 63762 brewer.push("rgb(166, 216, 84"); 63763 brewer.push("rgb(255, 217, 47"); 63764 brewer.push("rgb(229, 196, 148"); 63765 brewer.push("rgb(179, 179, 179"); //#Set 3 63766 63767 brewer.push("rgb( 141, 211, 199"); 63768 brewer.push("rgb(255, 255, 179"); 63769 brewer.push("rgb(190, 186, 218"); 63770 brewer.push("rgb(251, 128, 114"); 63771 brewer.push("rgb(128, 177, 211"); 63772 brewer.push("rgb(253, 180, 98"); 63773 brewer.push("rgb(179, 222, 105");
63774 brewer.push("rgb(252, 205, 229"); 63775 brewer.push("rgb(217, 217, 217"); 63776 brewer.push("rgb(188, 128, 189"); 63777 brewer.push("rgb(204, 235, 197"); 63778 brewer.push("rgb(255, 237, 111"); 63779 63780 /* 63781 * The MIT License (MIT) 63782 * 63783 * Copyright (c) 2014 Broad Institute 63784 * 63785 * Permission is hereby granted, free of charge, to any person obtaining a copy 63786 * of this software and associated documentation files (the "Software"), to deal 63787 * in the Software without restriction, including without limitation the rights 63788 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 63789 * copies of the Software, and to permit persons to whom the Software is 63790 * furnished to do so, subject to the following conditions: 63791 * 63792 * The above copyright notice and this permission notice shall be included in 63793 * all copies or substantial portions of the Software. 63794 * 63795 * 63796 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 63797 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 63798 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 63799 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 63800 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 63801 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 63802 * THE SOFTWARE. 63803 */ 63804 63805 class ReferenceFrame { 63806 constructor(genome, chr, start, end, bpPerPixel) { 63807 this.genome = genome; 63808 this.chr = chr; 63809 this.start = start; // TODO WARNING THIS IS NOT UPDATED !!! 63810 63811 this.end = end; 63812 this.bpPerPixel = bpPerPixel; 63813 this.id = guid$1(); 63814 } 63815 63816 calculateEnd(pixels) { 63817 return this.start + this.bpPerPixel * pixels; 63818 } 63819 63820 calculateBPP(end, pixels) { 63821 return (end - this.start) / pixels; 63822 } 63823 63824 set(json) { 63825 this.chr = json.chr; 63826 this.start = json.start; 63827 this.bpPerPixel = json.bpPerPixel; 63828 } 63829 63830 toPixels(bp) { 63831 return bp / this.bpPerPixel; 63832 } 63833 63834 toBP(pixels) { 63835 return this.bpPerPixel * pixels; 63836 } 63837 /** 63838 * Shift frame by stated pixels. Return true if view changed, false if not. 63839 * @param pixels 63840 * @param viewportWidth 63841 */ 63842 63843 63844 shiftPixels(pixels, viewportWidth) { 63845 const currentStart = this.start; 63846 const deltaBP = pixels * this.bpPerPixel; 63847 this.start += deltaBP; 63848 this.clampStart(viewportWidth); 63849 this.end += deltaBP; 63850 const { 63851 bpLength 63852 } = this.genome.getChromosome(this.chr); 63853 this.end = Math.min(bpLength, this.end); 63854 return currentStart !== this.start; 63855 } 63856 63857 clampStart(viewportWidth) { 63858 // clamp left 63859 const min = this.genome.getChromosome(this.chr).bpStart || 0; 63860 this.start = Math.max(min, this.start); // clamp right 63861 63862 if (viewportWidth) { 63863 const { 63864 bpLength 63865 } = this.genome.getChromosome(this.chr); 63866 const maxStart = bpLength - viewportWidth * this.bpPerPixel; 63867 63868 if (this.start > maxStart) { 63869 this.start = maxStart; 63870 } 63871 } 63872 } 63873 63874 async zoomWithScaleFactor(browser, scaleFactor, viewportWidth, centerBPOrUndefined) { 63875 const centerBP = undefined === centerBPOrUndefined ? this.start + this.toBP(viewportWidth / 2.0) : centerBPOrUndefined; // save initial start and bpp 63876 63877 const { 63878 start, 63879 bpPerPixel 63880 } = this.start; 63881 const { 63882 bpLength 63883 } = this.getChromosome(); 63884 const bppThreshold = scaleFactor < 1.0 ? browser.minimumBases() / viewportWidth : bpLength / viewportWidth; // update bpp 63885 63886 if (scaleFactor < 1.0) { 63887 this.bpPerPixel = Math.max(this.bpPerPixel * scaleFactor, bppThreshold); 63888 } else { 63889 this.bpPerPixel = Math.min(this.bpPerPixel * scaleFactor, bppThreshold); 63890 } // update start and end 63891 63892 63893 const widthBP = this.bpPerPixel * viewportWidth; 63894 this.start = centerBP - 0.5 * widthBP; 63895 this.clampStart(viewportWidth); 63896 this.end = this.start + widthBP; 63897 const viewChanged = start !== this.start || bpPerPixel !== this.bpPerPixel; 63898 63899 if (viewChanged) { 63900 await browser.updateViews(this); 63901 } 63902 } 63903 63904 getChromosome() { 63905 return this.genome.getChromosome(this.chr); 63906 } 63907 63908 getMultiLocusLabel(pixels) { 63909 const margin = ' '; 63910 const space = '     '; 63911 const ss = Math.floor(this.start) + 1; 63912 const ee = Math.round(this.start + this.bpPerPixel * pixels); 63913 return `${margin}${this.chr}${space}${prettyBasePairNumber(ee - ss)}${margin}`; 63914 } 63915 63916 getPresentationLocusComponents(pixels) { 63917 if ('all' === this.chr) { 63918 return { 63919 chr: this.chr 63920 }; 63921 } else { 63922 const ss = numberFormatter$1(Math.floor(this.start) + 1); 63923 const ee = numberFormatter$1(Math.round(this.start + this.bpPerPixel * pixels)); 63924 return { 63925 chr: this.chr, 63926 start: ss, 63927 end: ee 63928 }; 63929 } 63930 } 63931 63932 getLocusString() { 63933 if ('all' === this.chr) { 63934 return 'all'; 63935 } else { 63936 const ss = numberFormatter$1(Math.floor(this.start) + 1); 63937 const ee = numberFormatter$1(Math.round(this.end)); 63938 return `${this.chr}:${ss}-${ee}`; 63939 } 63940 } 63941 63942 description(blurb) { 63943 console.log(` ${blurb || ''} referenceFrame - ${this.chr} bpp ${this.bpPerPixel.toFixed(3)} start ${numberFormatter$1(Math.round(this.start))} end ${numberFormatter$1(Math.round(this.end))} `); 63944 } 63945 63946 } 63947 63948 function createReferenceFrameList(loci, genome, browserFlanking, minimumBases, viewportWidth) { 63949 return loci.map(locus => { 63950 // If a flanking region is defined, and the search object is a symbol ("gene") type, adjust start and end 63951 if (browserFlanking && locus.gene) { 63952 locus.start = Math.max(0, locus.start - browserFlanking); 63953 locus.end += browserFlanking; 63954 } // Validate the range. This potentionally modifies start & end of locus. 63955 63956 63957 const chromosome = genome.getChromosome(locus.chr); 63958 validateLocusExtent(chromosome.bpLength, locus, minimumBases);
63959 const referenceFrame = new ReferenceFrame(genome, locus.chr, locus.start, locus.end, (locus.end - locus.start) / viewportWidth); 63960 referenceFrame.locusSearchString = locus.locusSearchString; // GTEX hack 63961 63962 if (locus.gene || locus.snp) { 63963 referenceFrame.selection = new GtexSelection(locus.gene, locus.snp); 63964 } 63965 63966 return referenceFrame; 63967 }); 63968 } 63969 63970 function adjustReferenceFrame(scaleFactor, referenceFrame, viewportWidth, alignmentStart, alignmentLength) { 63971 referenceFrame.bpPerPixel *= scaleFactor; 63972 const alignmentEE = alignmentStart + alignmentLength; 63973 const alignmentCC = (alignmentStart + alignmentEE) / 2; 63974 referenceFrame.start = alignmentCC - referenceFrame.bpPerPixel * (viewportWidth / 2); 63975 referenceFrame.end = referenceFrame.start + referenceFrame.bpPerPixel * viewportWidth; 63976 referenceFrame.locusSearchString = referenceFrame.getLocusString(); 63977 } 63978 63979 function createReferenceFrameWithAlignment(genome, chromosomeName, bpp, viewportWidth, alignmentStart, alignmentLength) { 63980 const alignmentEE = alignmentStart + alignmentLength; 63981 const alignmentCC = (alignmentStart + alignmentEE) / 2; 63982 const ss = alignmentCC - bpp * (viewportWidth / 2); 63983 const ee = ss + bpp * viewportWidth; 63984 return new ReferenceFrame(genome, chromosomeName, ss, ee, bpp); 63985 } 63986 63987 const defaultNucleotideColors = { 63988 "A": "rgb( 0, 200, 0)", 63989 "C": "rgb( 0,0,200)", 63990 "T": "rgb(255,0,0)", 63991 "G": "rgb(209,113, 5)", 63992 "N": "rgb(80,80,80)" 63993 }; 63994 63995 const DEFAULT_SEARCH_CONFIG = { 63996 timeout: 5000, 63997 type: "plain", 63998 // Legacy plain text support -- deprecated 63999 url: 'https://igv.org/genomes/locus.php?genome=$GENOME$&name=$FEATURE$', 64000 coords: 0, 64001 chromosomeField: "chromosome", 64002 startField: "start", 64003 endField: "end", 64004 geneField: "gene", 64005 snpField: "snp" 64006 }; 64007 /** 64008 * Return an object representing the locus of the given string. Object is of the form 64009 * { 64010 * chr, 64011 * start, 64012 * end, 64013 * locusSearchString, 64014 * gene, 64015 * snp 64016 * } 64017 * @param browser 64018 * @param string 64019 * @returns {Promise<*>} 64020 */ 64021 64022 async function search(browser, string) { 64023 if (undefined === string || '' === string.trim()) { 64024 return; 64025 } 64026 64027 if (string && string.trim().toLowerCase() === "all" || string === "*") { 64028 string = "all"; 64029 } 64030 64031 const loci = string.split(' '); 64032 let searchConfig = browser.searchConfig || DEFAULT_SEARCH_CONFIG; 64033 let list = []; 64034 64035 const searchLocus = async locus => { 64036 let locusObject = parseLocusString(browser, locus); 64037 64038 if (!locusObject) { 64039 const feature = browser.genome.featureDB[locus.toUpperCase()]; 64040 64041 if (feature) { 64042 locusObject = { 64043 chr: feature.chr, 64044 start: feature.start, 64045 end: feature.end, 64046 gene: feature.name, 64047 locusSearchString: string 64048 }; 64049 } 64050 } 64051 64052 if (!locusObject && browser.config && false !== browser.config.search) { 64053 try { 64054 locusObject = await searchWebService(browser, locus, searchConfig); 64055 } catch (error) { 64056 console.error(error); 64057 throw Error("Search service currently unavailable."); 64058 } 64059 } 64060 64061 return locusObject; 64062 }; 64063 64064 for (let locus of loci) { 64065 const locusObject = await searchLocus(locus); 64066 64067 if (locusObject) { 64068 locusObject.locusSearchString = locus; 64069 list.push(locusObject); 64070 } 64071 } // If nothing is found, consider possibility that loci name itself has spaces 64072 64073 64074 if (list.length === 0) { 64075 const locusObject = await searchLocus(string); 64076 64077 if (locusObject) { 64078 locusObject.locusSearchString = string; 64079 list.push(locusObject); 64080 } 64081 } 64082 64083 return 0 === list.length ? undefined : list; 64084 } 64085 64086 function parseLocusString(browser, locus) { 64087 const a = locus.split(':'); 64088 const chr = a[0]; 64089 64090 if ('all' === chr && browser.genome.getChromosome(chr)) { 64091 return { 64092 chr, 64093 start: 0, 64094 end: browser.genome.getChromosome(chr).bpLength 64095 }; 64096 } else if (undefined === browser.genome.getChromosome(chr)) { 64097 return undefined; 64098 } else { 64099 const queryChr = browser.genome.getChromosomeName(chr); 64100 const extent = { 64101 chr: queryChr, 64102 start: 0, 64103 end: browser.genome.getChromosome(chr).bpLength 64104 }; 64105 64106 if (a.length > 1) { 64107 const b = a[1].split('-'); 64108 64109 if (b.length > 2) { 64110 return undefined; 64111 } else { 64112 let numeric; 64113 numeric = b[0].replace(/,/g, ''); 64114 64115 if (isNaN(numeric)) { 64116 return undefined; 64117 } 64118 64119 extent.start = parseInt(numeric, 10) - 1; 64120 extent.end = extent.start + 1; 64121 64122 if (1 === b.length) { 64123 extent.start -= 20; 64124 extent.end += 20; 64125 } 64126 64127 if (2 === b.length) { 64128 numeric = b[1].replace(/,/g, ''); 64129 64130 if (isNaN(numeric)) { 64131 return undefined; 64132 } else { 64133 extent.end = parseInt(numeric, 10); 64134 } 64135 } 64136 } 64137 } 64138 64139 return extent; 64140 } 64141 } 64142 64143 async function searchWebService(browser, locus, searchConfig) { 64144 let path = searchConfig.url.replace("$FEATURE$", locus.toUpperCase()); 64145 64146 if (path.indexOf("$GENOME$") > -1) { 64147 path = path.replace("$GENOME$", browser.genome.id ? browser.genome.id : "hg19"); 64148 } 64149 64150 const options = searchConfig.timeout ? { 64151 timeout: searchConfig.timeout 64152 } : undefined; 64153 const result = await igvxhr.loadString(path, options); 64154 const locusObject = processSearchResult(browser, result, searchConfig); 64155 64156 if (locusObject) { 64157 locusObject.locusSearchString = locus; 64158 } 64159 64160 return locusObject; 64161 } 64162 64163 function processSearchResult(browser, result, searchConfig) { 64164 let results; 64165 64166 if ('plain' === searchConfig.type) { 64167 results = parseSearchResults(browser, result); 64168 } else { 64169 results = JSON.parse(result); 64170 } 64171 64172 if (searchConfig.resultsField) { 64173 results = results[searchConfig.resultsField]; 64174 } 64175 64176 if (!results || 0 === results.length) { 64177 return undefined; 64178 } else { 64179 const chromosomeField = searchConfig.chromosomeField || "chromosome"; 64180 const startField = searchConfig.startField || "start"; 64181 const endField = searchConfig.endField || "end"; 64182 const coords = searchConfig.coords || 1; 64183 let result; 64184 64185 if (Array.isArray(results)) { 64186 // Ignoring all but first result for now 64187 // TODO -- present all and let user select if results.length > 1 64188 result = results[0]; 64189 } else { 64190 // When processing search results from Ensembl REST API 64191 // Example: https://rest.ensembl.org/lookup/symbol/macaca_fascicularis/BRCA2?content-type=application/json 64192 result = results; 64193 } 64194 64195 if (!(result.hasOwnProperty(chromosomeField) && result.hasOwnProperty(startField))) { 64196 console.error("Search service results must include chromosome and start fields: " + result); 64197 } 64198 64199 const chrResult = result[chromosomeField]; 64200 const chromosome = browser.genome.getChromosome(chrResult); 64201 64202 if (!chromosome) { 64203 return undefined; 64204 } 64205 64206 const chr = chromosome.name; 64207 let start = result[startField] - coords; 64208 let end = result[endField]; 64209 64210 if (undefined === end) { 64211 end = start + 1; 64212 } 64213 64214 const locusObject = { 64215 chr, 64216 start, 64217 end 64218 }; // Some GTEX hacks 64219 64220 const type = result.type ? result.type : "gene"; 64221 64222 if (searchConfig.geneField && type === "gene") { 64223 locusObject.gene = result[searchConfig.geneField]; 64224 } 64225 64226 if (searchConfig.snpField && type === "snp") { 64227 locusObject.snp = result[searchConfig.snpField]; 64228 } 64229 64230 return locusObject; 64231 } 64232 } 64233 /** 64234 * Parse the igv line-oriented (non json) search results. 64235 * Example 64236 * EGFR chr7:55,086,724-55,275,031 refseq 64237 * 64238 */ 64239 64240 64241 function parseSearchResults(browser, data) { 64242 const linesTrimmed = []; 64243 const results = []; 64244 const lines = splitLines$5(data);
64245 lines.forEach(function (item) { 64246 if ("" === item) ; else { 64247 linesTrimmed.push(item); 64248 } 64249 }); 64250 linesTrimmed.forEach(function (line) { 64251 var tokens = line.split("\t"), 64252 source, 64253 locusTokens, 64254 rangeTokens, 64255 obj; 64256 64257 if (tokens.length >= 3) { 64258 locusTokens = tokens[1].split(":"); 64259 rangeTokens = locusTokens[1].split("-"); 64260 source = tokens[2].trim(); 64261 obj = { 64262 gene: tokens[0], 64263 chromosome: browser.genome.getChromosomeName(locusTokens[0].trim()), 64264 start: parseInt(rangeTokens[0].replace(/,/g, '')), 64265 end: parseInt(rangeTokens[1].replace(/,/g, '')), 64266 type: "gtex" === source ? "snp" : "gene" 64267 }; 64268 results.push(obj); 64269 } 64270 }); 64271 return results; 64272 } // Export some functions for unit testing 64273 64274 /* 64275 * The MIT License (MIT) 64276 * 64277 * Copyright (c) 2014 Broad Institute 64278 * 64279 * Permission is hereby granted, free of charge, to any person obtaining a copy 64280 * of this software and associated documentation files (the "Software"), to deal 64281 * in the Software without restriction, including without limitation the rights 64282 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 64283 * copies of the Software, and to permit persons to whom the Software is 64284 * furnished to do so, subject to the following conditions: 64285 * 64286 * The above copyright notice and this permission notice shall be included in 64287 * all copies or substantial portions of the Software. 64288 * 64289 * 64290 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 64291 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 64292 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 64293 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 64294 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 64295 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 64296 * THE SOFTWARE. 64297 */ 64298 64299 class NavbarManager { 64300 constructor(browser) { 64301 this.browser = browser; 64302 } 64303 64304 navbarDidResize(width, isWholeGenomeView) { 64305 this.updateNavbar(this.createResponsiveClassSchedule(width, isWholeGenomeView)); 64306 } 64307 64308 updateNavbar(responsiveClassSchedule) { 64309 this.browser.$toggle_button_container.removeClass(); 64310 this.browser.$toggle_button_container.addClass(responsiveClassSchedule.$toggle_button_container); 64311 $$1(this.browser.zoomWidget.zoomContainer).removeClass(); 64312 $$1(this.browser.zoomWidget.zoomContainer).addClass(responsiveClassSchedule.zoomContainer); 64313 } 64314 64315 createResponsiveClassSchedule(navbarWidth, isWholeGenomeView) { 64316 let candidates = {}; 64317 64318 if (isWholeGenomeView) { 64319 this.browser.windowSizePanel.hide(); 64320 } else { 64321 this.browser.windowSizePanel.show(); 64322 } 64323 64324 if (navbarWidth > 990) { 64325 candidates.$toggle_button_container = 'igv-navbar-toggle-button-container'; 64326 candidates.zoomContainer = 'igv-zoom-widget'; 64327 } else if (navbarWidth > 860) { 64328 candidates.$toggle_button_container = 'igv-navbar-toggle-button-container'; 64329 candidates.zoomContainer = 'igv-zoom-widget-900'; 64330 } else if (navbarWidth > 540) { 64331 candidates.$toggle_button_container = 'igv-navbar-toggle-button-container-750'; 64332 candidates.zoomContainer = 'igv-zoom-widget-900'; 64333 } else { 64334 candidates.$toggle_button_container = 'igv-navbar-toggle-button-container-750'; 64335 candidates.zoomContainer = 'igv-zoom-widget-900'; 64336 this.browser.windowSizePanel.hide(); 64337 } 64338 64339 if (isWholeGenomeView) { 64340 candidates['zoomContainer'] = 'igv-zoom-widget-hidden'; 64341 } 64342 64343 return candidates; 64344 } 64345 64346 } 64347 64348 /* 64349 * The MIT License (MIT) 64350 * 64351 * Copyright (c) 2016-2017 The Regents of the University of California 64352 * Author: Jim Robinson 64353 * 64354 * Permission is hereby granted, free of charge, to any person obtaining a copy 64355 * of this software and associated documentation files (the "Software"), to deal 64356 * in the Software without restriction, including without limitation the rights 64357 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 64358 * copies of the Software, and to permit persons to whom the Software is 64359 * furnished to do so, subject to the following conditions: 64360 * 64361 * The above copyright notice and this permission notice shall be included in 64362 * all copies or substantial portions of the Software. 64363 * 64364 * 64365 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 64366 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 64367 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 64368 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 64369 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 64370 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 64371 * THE SOFTWARE. 64372 */ 64373 64374 const ChromosomeSelectWidget = function (browser, parent) { 64375 this.container = div$1({ 64376 class: 'igv-chromosome-select-widget-container' 64377 }); 64378 parent.appendChild(this.container); 64379 this.select = document.createElement('select'); 64380 this.select.setAttribute('name', 'chromosome-select-widget'); 64381 this.container.appendChild(this.select); 64382 this.select.addEventListener('change', () => { 64383 this.select.blur(); 64384 64385 if (this.select.value !== '') { 64386 browser.search(this.select.value); 64387 } 64388 }); 64389 this.showAllChromosomes = browser.config.showAllChromosomes !== false; // i.e. default to true 64390 }; 64391 64392 ChromosomeSelectWidget.prototype.show = function () { 64393 this.container.style.display = 'flex'; 64394 }; 64395 64396 ChromosomeSelectWidget.prototype.hide = function () { 64397 this.container.style.display = 'none'; 64398 }; 64399 64400 ChromosomeSelectWidget.prototype.update = function (genome) { 64401 const list = this.showAllChromosomes ? genome.chromosomeNames.slice() : genome.wgChromosomeNames.slice(); // console.log(`${ this.showAllChromosomes ? 'Do' : 'Do not'} show all chromosomes. List ${ list }`) 64402 64403 if (genome.showWholeGenomeView()) { 64404 list.unshift('all'); 64405 list.unshift(''); 64406 } 64407 64408 this.select.innerHTML = ''; 64409 64410 for (let name of list) { 64411 const option = document.createElement('option'); 64412 option.setAttribute('value', name); 64413 option.innerText = name; 64414 this.select.appendChild(option); 64415 } 64416 }; 64417 64418 /* 64419 * The MIT License (MIT) 64420 * 64421 * Copyright (c) 2014 Broad Institute 64422 * 64423 * Permission is hereby granted, free of charge, to any person obtaining a copy 64424 * of this software and associated documentation files (the "Software"), to deal 64425 * in the Software without restriction, including without limitation the rights 64426 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 64427 * copies of the Software, and to permit persons to whom the Software is 64428 * furnished to do so, subject to the following conditions: 64429 * 64430 * The above copyright notice and this permission notice shall be included in 64431 * all copies or substantial portions of the Software. 64432 * 64433 * 64434 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 64435 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 64436 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 64437 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 64438 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 64439 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 64440 * THE SOFTWARE. 64441 */ 64442 64443 class WindowSizePanel { 64444 constructor(parent, browser) { 64445 this.container = div$1({ 64446 class: 'igv-windowsize-panel-container' 64447 }); 64448 parent.appendChild(this.container); 64449 browser.on('locuschange', referenceFrameList => { 64450 this.updatePanel(referenceFrameList); 64451 }); 64452 this.browser = browser; 64453 } 64454 64455 show() { 64456 this.container.style.display = 'block'; 64457 } 64458 64459 hide() { 64460 this.container.style.display = 'none'; 64461 } 64462 64463 updatePanel(referenceFrameList) { 64464 const width = this.browser.calculateViewportWidth(this.browser.referenceFrameList.length); 64465 this.container.innerText = 1 === referenceFrameList.length ? prettyBasePairNumber(Math.round(width * referenceFrameList[0].bpPerPixel)) : ''; 64466 } 64467 64468 } 64469 64470 /* 64471 * The MIT License (MIT) 64472 * 64473 * Copyright (c) 2016 University of California San Diego 64474 * Author: Jim Robinson 64475 * 64476 * Permission is hereby granted, free of charge, to any person obtaining a copy 64477 * of this software and associated documentation files (the "Software"), to deal 64478 * in the Software without restriction, including without limitation the rights 64479 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 64480 * copies of the Software, and to permit persons to whom the Software is 64481 * furnished to do so, subject to the following conditions: 64482 * 64483 * The above copyright notice and this permission notice shall be included in 64484 * all copies or substantial portions of the Software. 64485 * 64486 * 64487 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 64488 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 64489 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 64490 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 64491 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 64492 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 64493 * THE SOFTWARE. 64494 */ 64495 64496 class CursorGuide { 64497 constructor(columnContainer, browser) { 64498 this.browser = browser; 64499 this.columnContainer = columnContainer; 64500 this.horizontalGuide = div$1({ 64501 class: 'igv-cursor-guide-horizontal' 64502 }); 64503 columnContainer.appendChild(this.horizontalGuide); 64504 this.verticalGuide = div$1({ 64505 class: 'igv-cursor-guide-vertical' 64506 }); 64507 columnContainer.appendChild(this.verticalGuide); 64508 this.addMouseHandler(browser); 64509 this.setVisibility(browser.config.showCursorTrackingGuide); 64510 } 64511 64512 addMouseHandler(browser) { 64513 this.boundMouseMoveHandler = mouseMoveHandler.bind(this); 64514 this.columnContainer.addEventListener('mousemove', this.boundMouseMoveHandler); 64515 64516 function mouseMoveHandler(event) { 64517 const { 64518 x, 64519 y 64520 } = translateMouseCoordinates$1(event, this.columnContainer); 64521 this.horizontalGuide.style.top = `${y}px`; 64522 const target = document.elementFromPoint(event.clientX, event.clientY); 64523 let viewport = undefined; 64524 64525 if (target.parentElement.classList.contains('igv-viewport-content')) { 64526 viewport = target.parentElement.parentElement; 64527 } else if (target.parentElement.classList.contains('igv-viewport') && target.classList.contains('igv-viewport-content')) { 64528 viewport = target.parentElement; 64529 } 64530 64531 if (viewport && browser.getRulerTrackView()) { 64532 this.verticalGuide.style.left = `${x}px`; 64533 const columns = browser.root.querySelectorAll('.igv-column'); 64534 let index = undefined; 64535 const viewportParent = viewport.parentElement; 64536 64537 for (let i = 0; i < columns.length; i++) { 64538 if (undefined === index && viewportParent === columns[i]) { 64539 index = i; 64540 } 64541 } 64542 64543 const rulerViewport = browser.getRulerTrackView().viewports[index]; 64544 const result = rulerViewport.mouseMove(event); 64545 64546 if (result) { 64547 const { 64548 start, 64549 bp, 64550 end 64551 } = result; 64552 const interpolant = (bp - start) / (end - start); 64553 64554 if (this.customMouseHandler) { 64555 this.customMouseHandler({ 64556 start, 64557 bp, 64558 end, 64559 interpolant 64560 }); 64561 } 64562 } 64563 } 64564 } 64565 } 64566 64567 removeMouseHandler() { 64568 this.columnContainer.removeEventListener('mousemove', this.boundMouseMoveHandler); 64569 } 64570 64571 setVisibility(showCursorTrackingGuide) { 64572 if (true === showCursorTrackingGuide) { 64573 this.show(); 64574 } else { 64575 this.hide(); 64576 } 64577 } 64578 64579 show() { 64580 this.verticalGuide.style.display = 'block'; 64581 this.horizontalGuide.style.display = 'block'; 64582 } 64583 64584 hide() { 64585 this.verticalGuide.style.display = 'none'; 64586 this.horizontalGuide.style.display = 'none'; 64587 64588 if (this.browser.getRulerTrackView()) { 64589 for (let viewport of this.browser.getRulerTrackView().viewports) { 64590 viewport.$tooltip.hide(); 64591 } 64592 } 64593 } 64594 64595 } 64596 64597 /* 64598 * The MIT License (MIT) 64599 * 64600 * Copyright (c) 2016 University of California San Diego 64601 * Author: Jim Robinson 64602 * 64603 * Permission is hereby granted, free of charge, to any person obtaining a copy 64604 * of this software and associated documentation files (the "Software"), to deal 64605 * in the Software without restriction, including without limitation the rights 64606 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 64607 * copies of the Software, and to permit persons to whom the Software is 64608 * furnished to do so, subject to the following conditions: 64609 * 64610 * The above copyright notice and this permission notice shall be included in 64611 * all copies or substantial portions of the Software. 64612 * 64613 * 64614 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 64615 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 64616 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 64617 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 64618 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 64619 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 64620 * THE SOFTWARE. 64621 */ 64622 64623 class CursorGuideButton { 64624 constructor(browser, parent) { 64625 this.browser = browser; 64626 this.button = div$1({ 64627 class: 'igv-navbar-button' 64628 }); 64629 parent.appendChild(this.button); 64630 this.button.textContent = 'cursor guide'; 64631 this.button.addEventListener('click', () => { 64632 browser.cursorGuideVisible = !browser.cursorGuideVisible; 64633 browser.setCursorGuideVisibility(browser.cursorGuideVisible); 64634 this.setButtonState(browser.cursorGuideVisible); 64635 }); 64636 this.setButtonState(browser.cursorGuideVisible); 64637 64638 if (browser.config.showCursorTrackingGuideButton) { 64639 this.show(); 64640 } else { 64641 this.hide(); 64642 } 64643 } 64644 64645 setButtonState(cursorGuideVisible) { 64646 if (true === cursorGuideVisible) { 64647 this.button.classList.add('igv-navbar-button-clicked'); 64648 } else { 64649 this.button.classList.remove('igv-navbar-button-clicked'); 64650 } 64651 } 64652 64653 show() { 64654 this.button.style.display = 'block'; 64655 this.setButtonState(this.browser.cursorGuideVisible); 64656 } 64657 64658 hide() { 64659 this.button.style.display = 'none'; 64660 } 64661 64662 } 64663 64664 class CenterLineButton { 64665 constructor(browser, parent) { 64666 this.browser = browser; 64667 this.button = div$1({ 64668 class: 'igv-navbar-button' 64669 }); 64670 parent.appendChild(this.button); 64671 this.button.textContent = 'center line'; 64672 this.button.addEventListener('click', () => { 64673 browser.isCenterLineVisible = !browser.isCenterLineVisible; 64674 browser.setCenterLineVisibility(browser.isCenterLineVisible); 64675
64675 this.setButtonState(browser.isCenterLineVisible); 64676 }); 64677 this.setButtonState(browser.isCenterLineVisible); 64678 64679 if (browser.config.showCenterGuideButton) { 64680 this.show(); 64681 } else { 64682 this.hide(); 64683 } 64684 } 64685 64686 setButtonState(isCenterLineVisible) { 64687 if (true === isCenterLineVisible) { 64688 this.button.classList.add('igv-navbar-button-clicked'); 64689 } else { 64690 this.button.classList.remove('igv-navbar-button-clicked'); 64691 } 64692 } 64693 64694 show() { 64695 this.isVisible = true; 64696 this.button.style.display = 'block'; 64697 this.setButtonState(this.browser.isCenterLineVisible); 64698 } 64699 64700 hide() { 64701 this.isVisible = false; 64702 this.button.style.display = 'none'; 64703 } 64704 64705 } 64706 64707 /* 64708 * The MIT License (MIT) 64709 * 64710 * Copyright (c) 2016 University of California San Diego 64711 * Author: Jim Robinson 64712 * 64713 * Permission is hereby granted, free of charge, to any person obtaining a copy 64714 * of this software and associated documentation files (the "Software"), to deal 64715 * in the Software without restriction, including without limitation the rights 64716 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 64717 * copies of the Software, and to permit persons to whom the Software is 64718 * furnished to do so, subject to the following conditions: 64719 * 64720 * The above copyright notice and this permission notice shall be included in 64721 * all copies or substantial portions of the Software. 64722 * 64723 * 64724 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 64725 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 64726 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 64727 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 64728 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 64729 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 64730 * THE SOFTWARE. 64731 */ 64732 64733 const TrackLabelControl = function (parent, browser) { 64734 this.button = div$1({ 64735 class: 'igv-navbar-button' 64736 }); 64737 parent.appendChild(this.button); 64738 this.button.textContent = 'track labels'; 64739 this.button.addEventListener('click', () => { 64740 browser.trackLabelsVisible = !browser.trackLabelsVisible; 64741 this.setState(browser.trackLabelsVisible); 64742 browser.setTrackLabelVisibility(browser.trackLabelsVisible); 64743 }); 64744 this.browser = browser; 64745 this.setVisibility(browser.config.showTrackLabelButton); 64746 this.setState(browser.trackLabelsVisible); 64747 }; 64748 64749 TrackLabelControl.prototype.setVisibility = function (showTrackLabelButton) { 64750 if (true === showTrackLabelButton) { 64751 this.show(); 64752 } else { 64753 this.hide(); 64754 } 64755 }; 64756 64757 TrackLabelControl.prototype.setState = function (trackLabelsVisible) { 64758 if (true === trackLabelsVisible) { 64759 this.button.classList.add('igv-navbar-button-clicked'); 64760 } else { 64761 this.button.classList.remove('igv-navbar-button-clicked'); 64762 } 64763 }; 64764 64765 TrackLabelControl.prototype.show = function () { 64766 this.button.style.display = 'block'; 64767 this.setState(this.browser.trackLabelsVisible); 64768 }; 64769 64770 TrackLabelControl.prototype.hide = function () { 64771 this.button.style.display = 'none'; 64772 }; 64773 64774 /* 64775 * The MIT License (MIT) 64776 * 64777 * Copyright (c) 2016 University of California San Diego 64778 * Author: Jim Robinson 64779 * 64780 * Permission is hereby granted, free of charge, to any person obtaining a copy 64781 * of this software and associated documentation files (the "Software"), to deal 64782 * in the Software without restriction, including without limitation the rights 64783 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 64784 * copies of the Software, and to permit persons to whom the Software is 64785 * furnished to do so, subject to the following conditions: 64786 * 64787 * The above copyright notice and this permission notice shall be included in 64788 * all copies or substantial portions of the Software. 64789 * 64790 * 64791 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 64792 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 64793 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 64794 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 64795 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 64796 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 64797 * THE SOFTWARE. 64798 */ 64799 64800 class SampleNameControl { 64801 constructor(parent, browser) { 64802 this.button = div$1({ 64803 class: 'igv-navbar-button' 64804 }); 64805 parent.appendChild(this.button); 64806 this.button.innerText = 'Sample Names'; 64807 this.setState(browser.showSampleNames); 64808 this.setVisibility(browser.showSampleNameButton); 64809 this.button.addEventListener('click', () => { 64810 browser.showSampleNames = !browser.showSampleNames; 64811 this.setState(browser.showSampleNames); 64812 64813 for (let { 64814 sampleNameViewport 64815 } of browser.trackViews) { 64816 if (false === browser.showSampleNames) { 64817 sampleNameViewport.hide(); 64818 } else { 64819 sampleNameViewport.show(); 64820 } 64821 } 64822 64823 browser.resize(); 64824 }); 64825 } 64826 64827 setVisibility(showSampleNameButton) { 64828 if (true === showSampleNameButton) { 64829 this.show(); 64830 } else { 64831 this.hide(); 64832 } 64833 } 64834 64835 setState(showSampleNames) { 64836 if (true === showSampleNames) { 64837 this.button.classList.add('igv-navbar-button-clicked'); 64838 } else { 64839 this.button.classList.remove('igv-navbar-button-clicked'); 64840 } 64841 } 64842 64843 hide() { 64844 this.button.style.display = 'none'; 64845 } 64846 64847 show() { 64848 this.button.style.display = 'block'; 64849 } 64850 64851 } 64852 64853 /* 64854 * The MIT License (MIT) 64855 * 64856 * Copyright (c) 2016 University of California San Diego 64857 * Author: Jim Robinson 64858 * 64859 * Permission is hereby granted, free of charge, to any person obtaining a copy 64860 * of this software and associated documentation files (the "Software"), to deal 64861 * in the Software without restriction, including without limitation the rights 64862 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 64863 * copies of the Software, and to permit persons to whom the Software is 64864 * furnished to do so, subject to the following conditions: 64865 * 64866 * The above copyright notice and this permission notice shall be included in 64867 * all copies or substantial portions of the Software. 64868 * 64869 * 64870 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 64871 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 64872 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 64873 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 64874 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 64875 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 64876 * THE SOFTWARE. 64877 */ 64878 const sliderMin = 0; 64879 let sliderMax = 23; 64880 let sliderValueRaw = 0; 64881 64882 const ZoomWidget = function (browser, parent) { 64883 this.browser = browser; 64884 this.zoomContainer = div$1({ 64885 class: 'igv-zoom-widget' 64886 }); 64887 parent.appendChild(this.zoomContainer); // zoom out 64888 64889 this.zoomOutButton = div$1(); 64890 this.zoomContainer.appendChild(this.zoomOutButton); 64891 this.zoomOutButton.appendChild(createIcon$1('minus-circle')); 64892 this.zoomOutButton.addEventListener('click', () => { 64893 // browser.zoomWithScaleFactor(2.0) 64894 browser.zoomOut(); 64895 }); // Range slider 64896 64897 const el = div$1(); 64898 this.zoomContainer.appendChild(el); 64899 this.slider = document.createElement('input'); 64900 this.slider.type = 'range'; 64901 this.slider.min = `${sliderMin}`; 64902 this.slider.max = `${sliderMax}`; 64903 el.appendChild(this.slider); 64904 this.slider.addEventListener('change', e => { 64905 e.preventDefault(); 64906 e.stopPropagation(); 64907 const referenceFrame = browser.referenceFrameList[0]; 64908 const { 64909 bpLength 64910 } = referenceFrame.genome.getChromosome(referenceFrame.chr); 64911 const { 64912 end, 64913 start 64914 } = referenceFrame; 64915 const extent = end - start; // bpLength/(end - start) 64916 64917 const scaleFactor = Math.pow(2, e.target.valueAsNumber); // (end - start) = bpLength/scaleFactor 64918 64919 const zoomedExtent = bpLength / scaleFactor; // console.log(`zoom-widget - slider ${ e.target.value } scaleFactor ${ scaleFactor } extent-zoomed ${ StringUtils.numberFormatter(Math.round(zoomedExtent)) }`) 64920 64921 browser.zoomWithScaleFactor(zoomedExtent / extent); 64922 }); // zoom in 64923 64924 this.zoomInButton = div$1(); 64925 this.zoomContainer.appendChild(this.zoomInButton); 64926 this.zoomInButton.appendChild(createIcon$1('plus-circle')); 64927 this.zoomInButton.addEventListener('click', () => { 64928 // browser.zoomWithScaleFactor(0.5) 64929 browser.zoomIn(); 64930 }); 64931 browser.on('locuschange', referenceFrameList => { 64932 if (this.browser.isMultiLocusMode()) { 64933 this.disable(); 64934 } else { 64935 this.enable(); 64936 this.update(referenceFrameList); 64937 } 64938 }); 64939 }; 64940 64941 ZoomWidget.prototype.update = function (referenceFrameList) { 64942 const referenceFrame = referenceFrameList[0]; 64943 const { 64944 bpLength 64945 } = referenceFrame.genome.getChromosome(referenceFrame.chr); 64946 const { 64947 start, 64948 end 64949 } = referenceFrame; 64950 sliderMax = Math.ceil(Math.log2(bpLength / this.browser.minimumBases())); 64951 this.slider.max = `${sliderMax}`; 64952 const scaleFactor = bpLength / (end - start); 64953 sliderValueRaw = Math.log2(scaleFactor);
64954 this.slider.value = `${Math.round(sliderValueRaw)}`; 64955 // console.log(`${ Date.now() } update - slider ${ this.slider.value } scaleFactor ${ Math.round(scaleFactor) } extent ${ StringUtils.numberFormatter(Math.round(extent)) }`) 64956 // console.log(`update - sliderMin ${ sliderMin } sliderValue ${ this.slider.value } sliderMax ${ sliderMax } scaleFactor ${ scaleFactor.toFixed(3) } derived-scaleFactor ${ derivedScalefactor.toFixed(3) }`) 64957 }; 64958 64959 ZoomWidget.prototype.enable = function () { 64960 // this.zoomInButton.style.color = appleCrayonPalette[ 'steel' ]; 64961 // this.zoomInButton.style.pointerEvents = 'auto'; 64962 // 64963 // this.zoomOutButton.style.color = appleCrayonPalette[ 'steel' ]; 64964 // this.zoomOutButton.style.pointerEvents = 'auto'; 64965 this.slider.disabled = false; 64966 }; 64967 64968 ZoomWidget.prototype.disable = function () { 64969 // this.zoomInButton.style.color = appleCrayonPalette[ 'silver' ]; 64970 // this.zoomInButton.style.pointerEvents = 'none'; 64971 // 64972 // this.zoomOutButton.style.color = appleCrayonPalette[ 'silver' ]; 64973 // this.zoomOutButton.style.pointerEvents = 'none'; 64974 this.slider.disabled = true; 64975 }; 64976 64977 ZoomWidget.prototype.hide = function () { 64978 this.zoomContainer.style.display = 'none'; 64979 }; 64980 64981 ZoomWidget.prototype.show = function () { 64982 this.zoomContainer.style.display = 'block'; 64983 }; 64984 64985 ZoomWidget.prototype.hideSlider = function () { 64986 this.slider.style.display = 'none'; 64987 }; 64988 64989 ZoomWidget.prototype.showSlider = function () { 64990 this.slider.style.display = 'block'; 64991 }; 64992 64993 /* 64994 * The MIT License (MIT) 64995 * 64996 * Copyright (c) 2016 University of California San Diego 64997 * Author: Jim Robinson 64998 * 64999 * Permission is hereby granted, free of charge, to any person obtaining a copy 65000 * of this software and associated documentation files (the "Software"), to deal 65001 * in the Software without restriction, including without limitation the rights 65002 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 65003 * copies of the Software, and to permit persons to whom the Software is 65004 * furnished to do so, subject to the following conditions: 65005 * 65006 * The above copyright notice and this permission notice shall be included in 65007 * all copies or substantial portions of the Software. 65008 * 65009 * 65010 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 65011 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 65012 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 65013 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 65014 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 65015 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 65016 * THE SOFTWARE. 65017 */ 65018 65019 const SVGSaveControl = function (parent, browser) { 65020 const button = div$1({ 65021 class: 'igv-navbar-button' 65022 }); 65023 parent.append(button); 65024 button.textContent = 'Save SVG'; 65025 button.addEventListener('click', () => browser.saveSVGtoFile({})); 65026 }; 65027 65028 const viewportColumnManager = { 65029 createColumns: (columnContainer, count) => { 65030 for (let i = 0; i < count; i++) { 65031 if (0 === i) { 65032 createColumn(columnContainer, 'igv-column'); 65033 } else { 65034 columnContainer.appendChild(div$1({ 65035 class: 'igv-column-shim' 65036 })); 65037 createColumn(columnContainer, 'igv-column'); 65038 } 65039 } 65040 }, 65041 removeColumnAtIndex: (i, column) => { 65042 const shim = 0 === i ? column.nextElementSibling : column.previousElementSibling; 65043 column.remove(); 65044 shim.remove(); 65045 }, 65046 insertAfter: referenceElement => { 65047 const shim = div$1({ 65048 class: 'igv-column-shim' 65049 }); 65050 insertElementAfter(shim, referenceElement); 65051 const column = div$1({ 65052 class: 'igv-column' 65053 }); 65054 insertElementAfter(column, shim); 65055 return column; 65056 }, 65057 insertBefore: (referenceElement, count) => { 65058 for (let i = 0; i < count; i++) { 65059 const column = div$1({ 65060 class: 'igv-column' 65061 }); 65062 insertElementBefore(column, referenceElement); 65063 65064 if (count > 1 && i > 0) { 65065 const columnShim = div$1({ 65066 class: 'igv-column-shim' 65067 }); 65068 insertElementBefore(columnShim, column); 65069 } 65070 } 65071 } 65072 }; 65073 65074 /* 65075 * The MIT License (MIT) 65076 * 65077 * Copyright (c) 2016 University of California San Diego 65078 * Author: Jim Robinson 65079 * 65080 * Permission is hereby granted, free of charge, to any person obtaining a copy 65081 * of this software and associated documentation files (the "Software"), to deal 65082 * in the Software without restriction, including without limitation the rights 65083 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 65084 * copies of the Software, and to permit persons to whom the Software is 65085 * furnished to do so, subject to the following conditions: 65086 * 65087 * The above copyright notice and this permission notice shall be included in 65088 * all copies or substantial portions of the Software. 65089 * 65090 * 65091 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 65092 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 65093 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 65094 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 65095 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 65096 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 65097 * THE SOFTWARE. 65098 */ 65099 65100 class ViewportCenterLine { 65101 constructor(browser, referenceFrame, column) { 65102 this.browser = browser; 65103 this.referenceFrame = referenceFrame; 65104 this.column = column; 65105 this.container = div$1({ 65106 class: 'igv-center-line' 65107 }); 65108 column.appendChild(this.container); 65109 65110 if (browser.isCenterLineVisible) { 65111 this.show(); 65112 } else { 65113 this.hide(); 65114 } 65115 } 65116 65117 repaint() { 65118 const left = Math.floor(this.browser.calculateViewportWidth(this.browser.referenceFrameList.length) / 2); 65119 65120 if (this.referenceFrame) { 65121 const ppb = 1.0 / this.referenceFrame.bpPerPixel; 65122 65123 if (ppb > 1) { 65124 this.container.style.left = `${left}px`; 65125 this.container.style.width = `${Math.floor(this.referenceFrame.toPixels(1))}px`; 65126 this.container.classList.remove('igv-center-line-thin'); 65127 this.container.classList.add('igv-center-line-wide'); 65128 } else { 65129 this.container.style.left = `${left}px`; 65130 this.container.style.width = '1px'; 65131 this.container.classList.remove('igv-center-line-wide'); 65132 this.container.classList.add('igv-center-line-thin'); 65133 } 65134 } 65135 } 65136 65137 show() { 65138 this.isVisible = true; 65139 this.container.style.display = 'block'; 65140 this.repaint(); 65141 } 65142 65143 hide() { 65144 this.isVisible = false;
65145 this.container.style.display = 'none'; 65146 } 65147 65148 resize() { 65149 this.repaint(); 65150 } 65151 65152 } 65153 65154 /* 65155 * The MIT License (MIT) 65156 * 65157 * Copyright (c) 2014 Broad Institute 65158 * 65159 * Permission is hereby granted, free of charge, to any person obtaining a copy 65160 * of this software and associated documentation files (the "Software"), to deal 65161 * in the Software without restriction, including without limitation the rights 65162 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 65163 * copies of the Software, and to permit persons to whom the Software is 65164 * furnished to do so, subject to the following conditions: 65165 * 65166 * The above copyright notice and this permission notice shall be included in 65167 * all copies or substantial portions of the Software. 65168 * 65169 * 65170 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 65171 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 65172 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 65173 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 65174 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 65175 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 65176 * THE SOFTWARE. 65177 */ 65178 const numberFormatter = numberFormatter$1; 65179 65180 class RulerTrack { 65181 constructor(browser) { 65182 this.browser = browser; 65183 this.height = 40; 65184 this.name = ""; 65185 this.id = "ruler"; 65186 this.disableButtons = true; 65187 this.ignoreTrackMenu = true; 65188 this.order = Number.MIN_SAFE_INTEGER * 1e-2; 65189 this.removable = false; 65190 this.type = 'ruler'; 65191 } 65192 65193 async getFeatures(chr, start, end) { 65194 return []; 65195 } 65196 65197 computePixelHeight(ignore) { 65198 return this.height; 65199 } 65200 65201 draw(_ref) { 65202 let { 65203 context, 65204 referenceFrame, 65205 pixelWidth, 65206 pixelHeight, 65207 bpPerPixel, 65208 bpStart 65209 } = _ref; 65210 65211 if (GenomeUtils.isWholeGenomeView(referenceFrame.chr)) { 65212 this.drawWholeGenome({ 65213 context, 65214 pixelWidth, 65215 pixelHeight, 65216 bpPerPixel 65217 }); 65218 } else { 65219 this.doDraw({ 65220 context, 65221 referenceFrame, 65222 pixelWidth, 65223 pixelHeight, 65224 bpStart 65225 }); 65226 } 65227 } 65228 65229 drawWholeGenome(_ref2) { 65230 let { 65231 context, 65232 pixelWidth, 65233 pixelHeight, 65234 bpPerPixel 65235 } = _ref2; 65236 context.save(); 65237 IGVGraphics.fillRect(context, 0, 0, pixelWidth, pixelHeight, { 65238 'fillStyle': 'white' 65239 }); 65240 65241 for (let name of this.browser.genome.wgChromosomeNames) { 65242 let xBP = this.browser.genome.getCumulativeOffset(name); 65243 let wBP = this.browser.genome.getChromosome(name).bpLength; 65244 let x = Math.round(xBP / bpPerPixel); 65245 let w = Math.round(wBP / bpPerPixel); 65246 this.renderChromosomeRect(context, x, 0, w, pixelHeight, name); 65247 } 65248 65249 context.restore(); 65250 } 65251 65252 doDraw(_ref3) { 65253 let { 65254 context, 65255 referenceFrame, 65256 pixelWidth, 65257 pixelHeight, 65258 bpStart 65259 } = _ref3; 65260 context.clearRect(0, 0, pixelWidth, pixelHeight); 65261 const tickHeight = 6; 65262 const shim = 2; 65263 const bpLength = Math.floor(referenceFrame.toBP(pixelWidth)); 65264 const tick = findSpacing(bpLength, context.isSVG); 65265 let nTick = Math.floor(bpStart / tick.majorTick) - 1; 65266 const { 65267 tickDelta, 65268 labelLength 65269 } = calculateDeltas(context, referenceFrame, bpStart, nTick, tick); 65270 this.browser.referenceFrameList.indexOf(referenceFrame); // console.log(`ruler(${ index }) label-length ${ labelLength > tickDelta ? 'clobbers' : 'less than' } tick-delta ${ StringUtils.numberFormatter(tickDelta)} `) 65271 65272 let xTick; 65273 let bp; 65274 let accumulatedTickDelta = tickDelta; 65275 const labelLengthShim = 0.25 * labelLength; 65276 65277 do { 65278 bp = Math.floor(nTick * tick.majorTick); 65279 const rulerLabel = `${numberFormatter$1(Math.floor(bp / tick.unitMultiplier))} ${tick.majorUnit}`; 65280 xTick = Math.round(referenceFrame.toPixels(bp - 1 - bpStart + 0.5)); 65281 const xLabel = Math.round(xTick - context.measureText(rulerLabel).width / 2); 65282 65283 if (xLabel > 0 && labelLengthShim + labelLength <= accumulatedTickDelta) { 65284 IGVGraphics.fillText(context, rulerLabel, xLabel, this.height - tickHeight / 0.75); 65285 accumulatedTickDelta = 0; 65286 } 65287 65288 if (xTick > 0) { 65289 IGVGraphics.strokeLine(context, xTick, this.height - tickHeight, xTick, this.height - shim); 65290 } 65291 65292 bp = Math.floor((1 + nTick) * tick.majorTick); 65293 let pixel = Math.round(referenceFrame.toPixels(bp - 1 - bpStart + 0.5)); 65294 let delta = (pixel - xTick) / 2; 65295 let xx = xTick + delta; 65296 65297 if (xx > 0) { 65298 IGVGraphics.strokeLine(context, xx, this.height - tickHeight, xx, this.height - shim); 65299 } 65300 65301 ++nTick; 65302 accumulatedTickDelta += tickDelta; 65303 } while (xTick < pixelWidth); 65304 65305 IGVGraphics.strokeLine(context, 0, this.height - shim, pixelWidth, this.height - shim); 65306 } 65307 65308 renderChromosomeRect(ctx, x, y, w, h, name) { 65309 ctx.textAlign = 'center'; 65310 ctx.textBaseline = 'middle'; 65311 ctx.font = '12px sans-serif'; 65312 IGVGraphics.strokeLine(ctx, x + w, y, x + w, y + h, { 65313 strokeStyle: IGVColor.greyScale(191) 65314 }); 65315 const shortName = name.startsWith("chr") ? name.substring(3) : name; 65316 65317 if (w > ctx.measureText(shortName).width) { 65318 IGVGraphics.fillText(ctx, shortName, x + w / 2, y + h / 2, { 65319 fillStyle: IGVColor.greyScale(68) 65320 }); 65321 } 65322 } 65323 65324 supportsWholeGenome() { 65325 return true; 65326 } 65327 65328 dispose() {// do stuff 65329 } 65330 65331 } 65332 65333 function findSpacing(bpLength, isSVG) { 65334 if (bpLength < 10) { 65335 return new Tick(1, 'bp', 1); 65336 } 65337 65338 const nZeroes = Math.floor(Math.log10(bpLength)); 65339 let majorUnit = 'bp'; 65340 let unitMultiplier = 1; 65341 65342 if (nZeroes > 9) { 65343 majorUnit = 'gb'; 65344 unitMultiplier = 1e9; 65345 } else if (nZeroes > 6) { 65346 majorUnit = 'mb'; 65347 unitMultiplier = 1e6; 65348 } else if (nZeroes > 3) { 65349 majorUnit = 'kb'; 65350 unitMultiplier = 1e3; 65351 } 65352 65353 const denom = Math.pow(10, nZeroes - 1); 65354 const nMajorTicks = bpLength / denom; // const threshold = 25 65355 65356 const threshold = 3 * 25; 65357 const belowThresholdTick = Math.pow(10, nZeroes - 1); 65358 const aboveThresholdTick = Math.pow(10, nZeroes) / 2; // console.log(`zeros ${ nZeroes } tick-threshold ${ threshold }
65358 ticks ${ nMajorTicks } belowTick ${ StringUtils.numberFormatter(belowThresholdTick) } aboveTick ${ StringUtils.numberFormatter(aboveThresholdTick) }`) 65359 65360 const majorTick = nMajorTicks < threshold && isSVG !== true ? belowThresholdTick : aboveThresholdTick; 65361 return new Tick(majorTick, majorUnit, unitMultiplier); 65362 } 65363 65364 function calculateDeltas(context, referenceFrame, bpStart, nTick, tick) { 65365 const tickDelta = getX(referenceFrame, getBP(1 + nTick, tick), bpStart) - getX(referenceFrame, getBP(nTick, tick), bpStart); 65366 const label = `${numberFormatter$1(Math.floor(getBP(nTick, tick) / tick.unitMultiplier))} ${tick.majorUnit}`; 65367 const labelLength = Math.floor(context.measureText(label).width); 65368 return { 65369 tickDelta, 65370 labelLength 65371 }; 65372 65373 function getBP(nTick, tick) { 65374 return Math.floor(nTick * tick.majorTick); 65375 } 65376 65377 function getX(referenceFrame, bp, bpStart) { 65378 return Math.round(referenceFrame.toPixels(bp - 1 - bpStart + 0.5)); 65379 } 65380 } 65381 65382 class Tick { 65383 constructor(majorTick, majorUnit, unitMultiplier) { 65384 this.majorTick = majorTick; 65385 this.minorTick = majorTick / 10.0; 65386 this.majorUnit = majorUnit; 65387 this.unitMultiplier = unitMultiplier; 65388 } 65389 65390 description(blurb) { 65391 console.log((blurb || '') + ' tick ' + numberFormatter(this.majorTick) + ' label width ' + numberFormatter(this.labelWidthBP) + ' multiplier ' + this.unitMultiplier); 65392 } 65393 65394 } 65395 65396 /* 65397 * The MIT License (MIT) 65398 * 65399 * Copyright (c) 2016 University of California San Diego 65400 * Author: Jim Robinson 65401 * 65402 * Permission is hereby granted, free of charge, to any person obtaining a copy 65403 * of this software and associated documentation files (the "Software"), to deal 65404 * in the Software without restriction, including without limitation the rights 65405 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 65406 * copies of the Software, and to permit persons to whom the Software is 65407 * furnished to do so, subject to the following conditions: 65408 * 65409 * The above copyright notice and this permission notice shall be included in 65410 * all copies or substantial portions of the Software. 65411 * 65412 * 65413 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 65414 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 65415 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 65416 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 65417 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 65418 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 65419 * THE SOFTWARE. 65420 */ 65421 65422 const CircularViewControl = function (parent, browser) { 65423 this.button = div$1({ 65424 class: 'igv-navbar-button' 65425 }); 65426 parent.appendChild(this.button); 65427 this.button.textContent = 'circular view'; 65428 this.button.addEventListener('click', () => {
65429 browser.circularViewVisible = !browser.circularViewVisible; //this.setState(browser.circularViewVisible) 65430 }); 65431 this.browser = browser; 65432 this.setVisibility(browser.config.showCircularViewButton); 65433 this.setState(browser.circularViewVisible); 65434 }; 65435 65436 CircularViewControl.prototype.setVisibility = function (showCircularViewButton) { 65437 if (true === showCircularViewButton) { 65438 this.show(); 65439 } else { 65440 this.hide(); 65441 } 65442 }; 65443 65444 CircularViewControl.prototype.setState = function (circularViewVisible) { 65445 if (true === circularViewVisible) { 65446 this.button.classList.add('igv-navbar-button-clicked'); 65447 } else { 65448 this.button.classList.remove('igv-navbar-button-clicked'); 65449 } 65450 }; 65451 65452 CircularViewControl.prototype.show = function () { 65453 this.button.style.display = 'block'; 65454 this.setState(this.browser.circularViewVisible); 65455 }; 65456 65457 CircularViewControl.prototype.hide = function () { 65458 this.button.style.display = 'none'; 65459 }; 65460 65461 /* 65462 * The MIT License (MIT) 65463 * 65464 * Copyright (c) 2014 Broad Institute 65465 * 65466 * Permission is hereby granted, free of charge, to any person obtaining a copy 65467 * of this software and associated documentation files (the "Software"), to deal 65468 * in the Software without restriction, including without limitation the rights 65469 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 65470 * copies of the Software, and to permit persons to whom the Software is 65471 * furnished to do so, subject to the following conditions: 65472 * 65473 * The above copyright notice and this permission notice shall be included in 65474 * all copies or substantial portions of the Software. 65475 * 65476 * 65477 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 65478 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 65479 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 65480 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 65481 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 65482 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 65483 * THE SOFTWARE. 65484 */ 65485 65486 const igv_scrollbar_outer_width = 14; // css - $igv-track-drag-column-width: 12px; 65487 65488 const igv_track_manipulation_handle_width = 12; // css - $igv-track-gear-menu-column-width: 28px; 65489 65490 const igv_track_gear_menu_column_width = 28; // $igv-column-shim-width: 1px; 65491 // $igv-column-shim-margin: 2px; 65492 65493 const column_multi_locus_shim_width = 2 + 1 + 2; 65494 const defaultSampleNameViewportWidth = 200; 65495 65496 class Browser { 65497 constructor(config, parentDiv) { 65498 this.config = config; 65499 this.guid = guid$1(); 65500 this.namespace = '.browser_' + this.guid; 65501 this.parent = parentDiv; 65502 this.root = div$1({ 65503 class: 'igv-container' 65504 }); 65505 parentDiv.appendChild(this.root); 65506 Alert.init(this.root); 65507 this.columnContainer = div$1({ 65508 class: 'igv-column-container' 65509 }); 65510 this.root.appendChild(this.columnContainer); 65511 this.menuPopup = new MenuPopup(this.columnContainer); 65512 this.initialize(config); 65513 this.trackViews = []; 65514 this.constants = { 65515 dragThreshold: 3, 65516 scrollThreshold: 5, 65517 defaultColor: "rgb(0,0,150)", 65518 doubleClickDelay: config.doubleClickDelay || 500 65519 }; // Map of event name -> [ handlerFn, ... ] 65520 65521 this.eventHandlers = {}; 65522 this.addMouseHandlers(); 65523 this.setControls(config); 65524 } 65525 65526 initialize(config) { 65527 if (config.gtex) { 65528 GtexUtils.gtexLoaded = true; 65529 } 65530 65531 this.flanking = config.flanking; 65532 this.crossDomainProxy = config.crossDomainProxy; 65533 this.formats = config.formats; 65534 this.trackDefaults = config.trackDefaults; 65535 this.nucleotideColors = config.nucleotideColors || defaultNucleotideColors; 65536 65537 for (let key of Object.keys(this.nucleotideColors)) { 65538 this.nucleotideColors[key.toLowerCase()] = this.nucleotideColors[key]; 65539 } 65540 65541 this.trackLabelsVisible = config.showTrackLabels; 65542 this.isCenterLineVisible = config.showCenterGuide; 65543 this.cursorGuideVisible = config.showCursorTrackingGuide; 65544 this.showSampleNames = config.showSampleNames; 65545 this.showSampleNameButton = config.showSampleNameButton; 65546 this.sampleNameViewportWidth = config.sampleNameViewportWidth || defaultSampleNameViewportWidth; 65547 65548 if (config.search) { 65549 this.searchConfig = { 65550 type: "json", 65551 url: config.search.url, 65552 coords: config.search.coords === undefined ? 1 : config.search.coords, 65553 chromosomeField: config.search.chromosomeField || "chromosome", 65554 startField: config.search.startField || "start", 65555 endField: config.search.endField || "end", 65556 geneField: config.search.geneField || "gene", 65557 snpField: config.search.snpField || "snp", 65558 resultsField: config.search.resultsField 65559 }; 65560 } 65561 } 65562 65563 setControls(config) { 65564 const $navBar = this.createStandardControls(config); 65565 $navBar.insertBefore($$1(this.columnContainer)); 65566 this.$navigation = $navBar; 65567 65568 if (false === config.showControls) { 65569 $navBar.hide(); 65570 } 65571 } 65572 65573 createStandardControls(config) { 65574 this.navbarManager = new NavbarManager(this); 65575 const $navBar = $$1('<div>', { 65576 class: 'igv-navbar' 65577 }); 65578 this.$navigation = $navBar; 65579 const $navbarLeftContainer = $$1('<div>', { 65580 class: 'igv-navbar-left-container' 65581 }); 65582 $navBar.append($navbarLeftContainer); // IGV logo 65583 65584 const $logo = $$1('<div>', { 65585 class: 'igv-logo' 65586 }); 65587 $navbarLeftContainer.append($logo); 65588 const logoSvg = logo(); 65589 logoSvg.css("width", "34px"); 65590 logoSvg.css("height", "32px"); 65591 $logo.append(logoSvg); 65592 this.$current_genome = $$1('<div>', { 65593 class: 'igv-current-genome' 65594 }); 65595 $navbarLeftContainer.append(this.$current_genome); 65596 this.$current_genome.text(''); 65597 const $genomicLocation = $$1('<div>', { 65598 class: 'igv-navbar-genomic-location' 65599 }); 65600 $navbarLeftContainer.append($genomicLocation); // chromosome select widget 65601 65602 this.chromosomeSelectWidget = new ChromosomeSelectWidget(this, $genomicLocation.get(0)); 65603 65604 if (undefined === config.showChromosomeWidget) { 65605 config.showChromosomeWidget = true; // Default to true 65606 } 65607 65608 if (true === config.showChromosomeWidget) { 65609 this.chromosomeSelectWidget.show(); 65610 } else { 65611 this.chromosomeSelectWidget.hide(); 65612 } 65613 65614 const $locusSizeGroup = $$1('<div>', { 65615 class: 'igv-locus-size-group' 65616 }); 65617 $genomicLocation.append($locusSizeGroup); 65618 const $searchContainer = $$1('<div>', { 65619 class: 'igv-search-container' 65620 }); 65621 $locusSizeGroup.append($searchContainer); // browser.$searchInput = $('<input type="text" placeholder="Locus Search">'); 65622 65623 this.$searchInput = $$1('<input>', { 65624 class: 'igv-search-input', 65625 type: 'text', 65626 placeholder: 'Locus Search' 65627 }); 65628 $searchContainer.append(this.$searchInput); 65629 this.$searchInput.change(() => this.doSearch(this.$searchInput.val())); 65630 const searchIconContainer = div$1({ 65631 class: 'igv-search-icon-container' 65632 }); 65633 $searchContainer.append($$1(searchIconContainer)); 65634 searchIconContainer.appendChild(createIcon$1("search")); 65635 searchIconContainer.addEventListener('click', () => this.doSearch(this.$searchInput.val())); 65636 this.windowSizePanel = new WindowSizePanel($locusSizeGroup.get(0), this); 65637 const $navbarRightContainer = $$1('<div>', { 65638 class: 'igv-navbar-right-container' 65639 }); 65640 $navBar.append($navbarRightContainer); 65641 const $toggle_button_container = $$1('<div class="igv-navbar-toggle-button-container">'); 65642 $navbarRightContainer.append($toggle_button_container); 65643 this.$toggle_button_container = $toggle_button_container; 65644 this.cursorGuide = new CursorGuide(this.columnContainer, this); 65645 this.cursorGuideButton = new CursorGuideButton(this, $toggle_button_container.get(0)); 65646 this.centerLineButton = new CenterLineButton(this, $toggle_button_container.get(0)); 65647 this.setTrackLabelVisibility(config.showTrackLabels); 65648 this.trackLabelControl = new TrackLabelControl($toggle_button_container.get(0), this); 65649 this.sampleNameControl = new SampleNameControl($toggle_button_container.get(0), this); 65650 65651 if (true === config.showSVGButton) { 65652 this.svgSaveControl = new SVGSaveControl($toggle_button_container.get(0), this); 65653 } 65654 65655 this.zoomWidget = new ZoomWidget(this, $navbarRightContainer.get(0)); 65656 65657 if (false === config.showNavigation) { 65658 this.$navigation.hide(); 65659 } 65660 65661 this.inputDialog = new InputDialog(this.root); 65662 this.inputDialog.container.id = `igv-input-dialog-${guid$1()}`; 65663 this.dataRangeDialog = new DataRangeDialog($$1(this.root)); 65664 this.dataRangeDialog.$container.get(0).id = `igv-data-range-dialog-${guid$1()}`; 65665 this.genericColorPicker = new GenericColorPicker({ 65666 parent: this.columnContainer, 65667 width: 432 65668 }); 65669 this.genericColorPicker.container.id = `igv-track-color-picker-${guid$1()}`; 65670 return $navBar; 65671 } 65672 65673 getSampleNameViewportWidth() { 65674 return false === this.showSampleNames ? 0 : this.sampleNameViewportWidth; 65675 } 65676 65677 isMultiLocusMode() { 65678 return this.referenceFrameList && this.referenceFrameList.length > 1; 65679 } 65680 65681 addTrackToFactory(name, track) { 65682 TrackFactory.addTrack(name, track); 65683 } 65684 65685 isMultiLocusWholeGenomeView() { 65686 if (undefined === this.referenceFrameList || 1 === this.referenceFrameList.length) { 65687 return false;
65688 } 65689 65690 for (let referenceFrame of this.referenceFrameList) { 65691 if ('all' === referenceFrame.chr.toLowerCase()) { 65692 return true; 65693 } 65694 } 65695 65696 return false; 65697 } 65698 65699 /** 65700 * Render browse display as SVG 65701 * @returns {string} 65702 */ 65703 toSVG() { 65704 let { 65705 x, 65706 y, 65707 width, 65708 height 65709 } = this.columnContainer.getBoundingClientRect(); 65710 const h_render = 8000; 65711 let context = new ctx({ 65712 width, 65713 height: h_render, 65714 backdropColor: 'white', 65715 multiLocusGap: 0, 65716 viewbox: { 65717 x: 0, 65718 y: 0, 65719 width, 65720 height: h_render 65721 } 65722 }); 65723 65724 for (let trackView of this.trackViews) { 65725 trackView.renderSVGContext(context, { 65726 deltaX: 0, 65727 deltaY: -y 65728 }); 65729 } // reset height to trim away unneeded svg canvas real estate. Yes, a bit of a hack. 65730 65731 65732 context.setHeight(height); 65733 return context.getSerializedSvg(true); 65734 } 65735 65736 renderSVG($container) { 65737 const svg = this.toSVG(); 65738 $container.empty(); 65739 $container.append(svg); 65740 return svg; 65741 } 65742 65743 saveSVGtoFile(config) { 65744 let svg = this.toSVG(); 65745 65746 if (config.$container) { 65747 config.$container.empty(); 65748 config.$container.append(svg); 65749 } 65750 65751 const path = config.filename || 'igvjs.svg'; 65752 const data = URL.createObjectURL(new Blob([svg], { 65753 type: "application/octet-stream" 65754 })); 65755 download(path, data); 65756 } 65757 /** 65758 * Initialize a session from an object, json, or by loading from a file. 65759 * 65760 * TODO Really should be split into at least 2 functions, load from file and load from object/json 65761 * 65762 * @param options 65763 * @returns {*} 65764 */ 65765 65766 65767 async loadSession(options) { 65768 this.roi = []; 65769 let session; 65770 65771 if (options.url || options.file) { 65772 session = await loadSessionFile(options); 65773 } else { 65774 session = options; 65775 } 65776 65777 return this.loadSessionObject(session); 65778 65779 async function loadSessionFile(options) { 65780 const urlOrFile = options.url || options.file; 65781 65782 if (options.url && (options.url.startsWith("blob:") || options.url.startsWith("data:"))) { 65783 const json = Browser.uncompressSession(options.url); 65784 return JSON.parse(json); 65785 } else { 65786 let filename = options.filename; 65787 65788 if (!filename) { 65789 filename = options.url ? await getFilename(options.url) : options.file.name; 65790 } 65791 65792 if (filename.endsWith(".xml")) { 65793 const knownGenomes = GenomeUtils.KNOWN_GENOMES; 65794 const string = await igvxhr.loadString(urlOrFile); 65795 return new XMLSession(string, knownGenomes); 65796 } else if (filename.endsWith(".json")) { 65797 return igvxhr.loadJson(urlOrFile); 65798 } else { 65799 return undefined; 65800 } 65801 } 65802 } 65803 } 65804 /** 65805 * Note: public API function 65806 * @param session 65807 * @returns {Promise<void>} 65808 */ 65809 65810 65811 async loadSessionObject(session) { 65812 // prepare to load a new session, discarding DOM and state 65813 this.cleanHouseForSession(); 65814 this.showSampleNames = session.showSampleNames || false; 65815 this.sampleNameControl.setState(this.showSampleNames === true); 65816 65817 if (session.sampleNameViewportWidth) { 65818 this.sampleNameViewportWidth = session.sampleNameViewportWidth; 65819 } // axis column 65820 65821 65822 createColumn(this.columnContainer, 'igv-axis-column'); // SampleName column 65823 65824 createColumn(this.columnContainer, 'igv-sample-name-column'); // Track scrollbar column 65825 65826 createColumn(this.columnContainer, 'igv-scrollbar-column'); // Track drag/reorder column 65827 65828 createColumn(this.columnContainer, 'igv-track-drag-column'); // Track gear column 65829 65830 createColumn(this.columnContainer, 'igv-gear-menu-column'); 65831 const genomeConfig = await GenomeUtils.expandReference(session.reference || session.genome); 65832 await this.loadReference(genomeConfig, session.locus); 65833 this.centerLineList = this.createCenterLineList(this.columnContainer); // Create ideogram and ruler track. Really this belongs in browser initialization, but creation is 65834 // deferred because ideogram and ruler are treated as "tracks", and tracks require a reference frame 65835 65836 if (false !== session.showIdeogram) { 65837 this.trackViews.push(new TrackView(this, this.columnContainer, new IdeogramTrack(this))); 65838 } 65839 65840 if (false !== session.showRuler) { 65841 this.trackViews.push(new TrackView(this, this.columnContainer, new RulerTrack(this))); 65842 } // Restore gtex selections. 65843 65844 65845 if (session.gtexSelections) { 65846 for (let referenceFrame of this.referenceFrameList) { 65847 for (let s of Object.keys(session.gtexSelections)) { 65848 const gene = session.gtexSelections[s].gene; 65849 const snp = session.gtexSelections[s].snp; 65850 referenceFrame.selection = new GtexSelection(gene, snp); 65851 } 65852 } 65853 } 65854 65855 if (session.roi) { 65856 this.roi = []; 65857 65858 for (let r of session.roi) { 65859 this.roi.push(new ROI(r, this.genome)); 65860 } 65861 } // Tracks. Start with genome tracks, if any, then append session tracks 65862 65863 65864 const genomeTracks = genomeConfig.tracks || []; 65865 const trackConfigurations = session.tracks ? genomeTracks.concat(session.tracks) : genomeTracks; // Insure that we always have a sequence track 65866 65867 const pushSequenceTrack = trackConfigurations.filter(track => track.type === 'sequence').length === 0; 65868 65869 if (pushSequenceTrack 65870 /*&& false !== this.config.showSequence*/ 65871 ) { 65872 trackConfigurations.push({ 65873 type: "sequence", 65874 order: defaultSequenceTrackOrder 65875 }); 65876 } // Maintain track order unless explicitly set 65877 65878 65879 let trackOrder = 1; 65880 65881 for (let t of trackConfigurations) { 65882 if (undefined === t.order) { 65883 t.order = trackOrder++; 65884 } 65885 } 65886 65887 await this.loadTrackList(trackConfigurations); 65888 this.updateUIWithReferenceFrameList(); 65889 } 65890 65891 createCenterLineList(columnContainer) { 65892 const centerLines = columnContainer.querySelectorAll('.igv-center-line'); 65893 65894 for (let i = 0; i < centerLines.length; i++) { 65895 centerLines[i].remove(); 65896 } 65897 65898 const centerLineList = []; 65899 const viewportColumns = columnContainer.querySelectorAll('.igv-column'); 65900 65901 for (let i = 0; i < viewportColumns.length; i++) { 65902 centerLineList.push(new ViewportCenterLine(this, this.referenceFrameList[i], viewportColumns[i])); 65903 } 65904 65905 return centerLineList; 65906 } 65907 /** 65908 * Load a reference genome object. This includes the fasta, and optional cytoband, but no tracks. This method 65909 * is used by loadGenome and loadSession. 65910 * 65911 * @param genomeConfig 65912 * @param initialLocus 65913 */ 65914 65915 65916 async loadReference(genomeConfig, initialLocus) { 65917 const genome = await GenomeUtils.loadGenome(genomeConfig); 65918 const genomeChange = undefined === this.genome || this.genome.id !== genome.id; 65919 this.genome = genome; 65920 this.updateNavbarDOMWithGenome(genome); 65921 65922 if (genomeChange) { 65923 this.removeAllTracks(); 65924 } 65925 65926 let locus = getInitialLocus(initialLocus, genome); 65927 const locusFound = await this.search(locus, true); 65928 65929 if (!locusFound) { 65930 console.log("Initial locus not found: " + locus); 65931 locus = genome.getHomeChromosomeName(); 65932 const locusFound = await this.search(locus, true); 65933 65934 if (!locusFound) { 65935 throw new Error("Cannot set initial locus"); 65936 } 65937 } 65938 65939 if (genomeChange && this.circularView) { 65940 this.circularView.setAssembly({ 65941 name: this.genome.id, 65942 id: this.genome.id, 65943 chromosomes: makeCircViewChromosomes(this.genome) 65944 }); 65945 } 65946 } 65947 65948 cleanHouseForSession() { 65949 for (let trackView of this.trackViews) { 65950 // empty axis column, viewport columns, sampleName column, scroll column, drag column, gear column 65951 trackView.removeDOMFromColumnContainer(); 65952 } // discard all columns 65953 65954 65955 const elements = this.columnContainer.querySelectorAll('.igv-axis-column, .igv-column-shim, .igv-column, .igv-sample-name-column, .igv-scrollbar-column, .igv-track-drag-column, .igv-gear-menu-column');
65956 elements.forEach(column => column.remove()); 65957 this.trackViews = []; 65958 65959 if (this.circularView) { 65960 this.circularView.clearChords(); 65961 } 65962 } 65963 65964 updateNavbarDOMWithGenome(genome) { 65965 this.$current_genome.text(genome.id || ''); 65966 this.$current_genome.attr('title', genome.id || ''); 65967 this.chromosomeSelectWidget.update(genome); 65968 } 65969 /** 65970 * Load a genome, defined by a string ID or a json-like configuration object. This includes a fasta reference 65971 * as well as optional cytoband and annotation tracks. 65972 * 65973 * @param idOrConfig 65974 * @returns genome 65975 */ 65976 65977 65978 async loadGenome(idOrConfig) { 65979 const genomeConfig = await GenomeUtils.expandReference(idOrConfig); 65980 await this.loadReference(genomeConfig, undefined); 65981 const tracks = genomeConfig.tracks || []; // Insure that we always have a sequence track 65982 65983 const pushSequenceTrack = tracks.filter(track => track.type === 'sequence').length === 0; 65984 65985 if (pushSequenceTrack) { 65986 tracks.push({ 65987 type: "sequence", 65988 order: defaultSequenceTrackOrder 65989 }); 65990 } 65991 65992 await this.loadTrackList(tracks); 65993 await this.updateViews(); 65994 return this.genome; 65995 } 65996 /** 65997 * Called after a session load, search, pan (horizontal drag), or resize 65998 * 65999 * @param referenceFrameList 66000 */ 66001 66002 66003 updateUIWithReferenceFrameList() { 66004 const referenceFrameList = this.referenceFrameList; 66005 this.updateLocusSearchWidget(); 66006 const isWGV = this.isMultiLocusWholeGenomeView() || GenomeUtils.isWholeGenomeView(referenceFrameList[0].chr); 66007 this.navbarManager.navbarDidResize(this.$navigation.width(), isWGV); 66008 toggleTrackLabels(this.trackViews, this.trackLabelsVisible); 66009 this.setCenterLineAndCenterLineButtonVisibility(!GenomeUtils.isWholeGenomeView(referenceFrameList[0].chr)); 66010 } 66011 66012 setTrackLabelVisibility(isVisible) { 66013 toggleTrackLabels(this.trackViews, isVisible); 66014 } // cursor guide 66015 66016 66017 setCursorGuideVisibility(cursorGuideVisible) { 66018 if (cursorGuideVisible) { 66019 this.cursorGuide.show(); 66020 } else { 66021 this.cursorGuide.hide(); 66022 } 66023 } 66024 66025 setCustomCursorGuideMouseHandler(mouseHandler) { 66026 this.cursorGuide.customMouseHandler = mouseHandler; 66027 } // center line 66028 66029 66030 setCenterLineVisibility(isCenterLineVisible) { 66031 for (let centerLine of this.centerLineList) { 66032 if (true === isCenterLineVisible) { 66033 centerLine.show(); 66034 centerLine.repaint(); 66035 } else { 66036 centerLine.hide(); 66037 } 66038 } 66039 } 66040 66041 setCenterLineAndCenterLineButtonVisibility(isCenterLineVisible) { 66042 for (let centerLine of this.centerLineList) { 66043 const isShown = isCenterLineVisible && centerLine.isVisible; 66044 isShown ? centerLine.show() : centerLine.container.style.display = 'none'; 66045 } 66046 66047 const isShown = isCenterLineVisible && this.centerLineButton.isVisible; 66048 isShown ? this.centerLineButton.show() : this.centerLineButton.button.style.display = 'none'; 66049 } 66050 66051 async loadTrackList(configList) { 66052 try { 66053 const promises = []; 66054 66055 for (let config of configList) { 66056 promises.push(this.loadTrack(config, false)); 66057 } 66058 66059 const loadedTracks = await Promise.all(promises); 66060 const groupAutoscaleViews = this.trackViews.filter(function (trackView) { 66061 return trackView.track.autoscaleGroup; 66062 }); 66063 66064 if (groupAutoscaleViews.length > 0) { 66065 this.updateViews(groupAutoscaleViews); 66066 } 66067 66068 return loadedTracks; 66069 } finally { 66070 await this.resize(); 66071 } 66072 } 66073 66074 async loadROI(config) { 66075 if (!this.roi) { 66076 this.roi = []; 66077 } 66078 66079 if (Array.isArray(config)) { 66080 for (let c of config) { 66081 this.roi.push(new ROI(c, this.genome)); 66082 } 66083 } else { 66084 this.roi.push(new ROI(config, this.genome)); 66085 } 66086 66087 await this.updateViews(true); 66088 } 66089 66090 removeROI(roiToRemove) { 66091 for (let i = 0; i < this.roi.length; i++) { 66092 if (this.roi[i].name === roiToRemove.name) { 66093 this.roi.splice(i, 1); 66094 break; 66095 } 66096 } 66097 66098 for (let tv of this.trackViews) { 66099 tv.updateViews(true); 66100 } 66101 } 66102 66103 clearROIs() { 66104 this.roi = []; 66105 66106 for (let tv of this.trackViews) { 66107 tv.updateViews(true); 66108 } 66109 } 66110 66111 getRulerTrackView() { 66112 const list = this.trackViews.filter(_ref => { 66113 let { 66114 track 66115 } = _ref; 66116 return 'ruler' === track.id; 66117 }); 66118 return list.length > 0 ? list[0] : undefined; 66119 } 66120 /** 66121 * Return a promise to load a track. 66122 * 66123 * Each track is associated with the following DOM elements 66124 * 66125 * leftHandGutter - div on the left for track controls and legend 66126 * contentDiv - a div element wrapping all the track content. Height can be > viewportDiv height 66127 * viewportDiv - a div element through which the track is viewed. This might have a vertical scrollbar 66128 * canvas - canvas element upon which the track is drawn. Child of contentDiv 66129 * 66130 * The width of all elements should be equal. Height of the viewportDiv is controlled by the user, but never 66131 * greater than the contentDiv height. Height of contentDiv and canvas are equal, and governed by the data 66132 * loaded. 66133 * 66134 * 66135 * @param config 66136 * @param doResize - undefined by default 66137 * @returns {*} 66138 */ 66139 66140 66141 async loadTrack(config, doResize) { 66142 // config might be json 66143 if (isString$3(config)) { 66144 config = JSON.parse(config); 66145 } 66146 66147 try { 66148 const newTrack = await this.createTrack(config); 66149 66150 if (undefined === newTrack) { 66151 Alert.presentAlert(new Error(`Unknown file type: ${config.url || config}`), undefined); 66152 return newTrack; 66153 } // Set order field of track here. Otherwise track order might get shuffled during asynchronous load 66154 66155 66156 if (undefined === newTrack.order) { 66157 newTrack.order = this.trackViews.length; 66158 } 66159 66160 const trackView = new TrackView(this, this.columnContainer, newTrack); 66161 this.trackViews.push(trackView); 66162 toggleTrackLabels(this.trackViews, this.trackLabelsVisible); 66163 this.reorderTracks(); 66164 this.fireEvent('trackorderchanged', [this.getTrackOrder()]); 66165 66166 if (typeof newTrack.postInit === 'function') { 66167 try { 66168 trackView.startSpinner(); 66169 await newTrack.postInit(); 66170 } finally { 66171 trackView.stopSpinner(); 66172 } 66173 } 66174 66175 if (!newTrack.autoscaleGroup) { 66176 // Group autoscale will get updated later (as a group) 66177 if (config.sync) { 66178 await trackView.updateViews(); 66179 } else { 66180 trackView.updateViews(); 66181 } 66182 } 66183 66184 if (typeof newTrack.hasSamples === 'function' && newTrack.hasSamples()) { 66185 if (this.config.showSampleNameButton !== false) { 66186 this.sampleNameControl.show(); // If not explicitly set 66187 } 66188 } 66189 66190 return newTrack; 66191 } catch (error) { 66192 const httpMessages = { 66193 "401": "Access unauthorized", 66194 "403": "Access forbidden", 66195 "404": "Not found" 66196 }; 66197 console.error(error); 66198 let msg = error.message || error.error || error.toString(); 66199 66200 if (httpMessages.hasOwnProperty(msg)) { 66201 msg = httpMessages[msg]; 66202 } 66203 66204 msg += ": " + config.url; 66205 Alert.presentAlert(new Error(msg), undefined); 66206 } finally {
66207 // TODO: If loadTrack() is called individually - not via loadTrackList() - call this.resize() 66208 if (false === doResize) ; else { 66209 await this.resize(); 66210 } 66211 } 66212 } 66213 /** 66214 * Create a Track object. 66215 * @param config 66216 * @returns {Promise<*>} 66217 */ 66218 66219 66220 async createTrack(config) { 66221 // Resolve function and promise urls 66222 let url = await resolveURL(config.url); 66223 66224 if (isString$3(url)) { 66225 url = url.trim(); 66226 } 66227 66228 if (url) { 66229 if (config.format) { 66230 config.format = config.format.toLowerCase(); 66231 } else { 66232 let filename = config.filename; 66233 66234 if (!filename) { 66235 filename = await getFilename(url); 66236 } 66237 66238 config.format = inferFileFormat(filename); 66239 66240 if (!config.format && (config.sourceType === undefined || config.sourceType === "htsget")) { 66241 // Check for htsget URL. This is a longshot 66242 await HtsgetReader.inferFormat(config); 66243 } 66244 } 66245 } 66246 66247 let type = config.type ? config.type.toLowerCase() : undefined; 66248 66249 if (!type) { 66250 type = inferTrackType(config); 66251 66252 if ("bedtype" === type) { 66253 // Bed files must be read to determine track type 66254 const featureSource = FeatureSource(config, this.genome); 66255 config._featureSource = featureSource; // This is a temp variable, bit of a hack 66256 66257 const trackType = await featureSource.trackType(); 66258 66259 if (trackType) { 66260 type = trackType; 66261 } else { 66262 type = "annotation"; 66263 } 66264 } // Record in config to make type persistent in session 66265 66266 66267 config.type = type; 66268 } // Set defaults if specified 66269 66270 66271 if (this.trackDefaults && type) { 66272 const settings = this.trackDefaults[type]; 66273 66274 if (settings) { 66275 for (let property in settings) { 66276 if (settings.hasOwnProperty(property) && config[property] === undefined) { 66277 config[property] = settings[property]; 66278 } 66279 } 66280 } 66281 } 66282 66283 const track = TrackFactory.getTrack(type, config, this); 66284 66285 if (track && config.roi) { 66286 track.roi = []; 66287 66288 for (let r of config.roi) { 66289 track.roi.push(new ROI(r, this.genome)); 66290 } 66291 } 66292 66293 return track; 66294 } 66295 66296 reorderTracks() { 66297 this.trackViews.sort(function (a, b) { 66298 const firstSortOrder = tv => { 66299 return 'ideogram' === tv.track.id ? 1 : 'ruler' === tv.track.id ? 2 : 3; 66300 }; 66301 66302 const aOrder1 = firstSortOrder(a); 66303 const bOrder1 = firstSortOrder(b); 66304 66305 if (aOrder1 === bOrder1) { 66306 const aOrder2 = a.track.order || 0; 66307 const bOrder2 = b.track.order || 0; 66308 return aOrder2 - bOrder2; 66309 } else { 66310 return aOrder1 - bOrder1; 66311 } 66312 }); // discard current track order 66313 66314 for (let { 66315 axis, 66316 viewports, 66317 sampleNameViewport, 66318 outerScroll, 66319 dragHandle, 66320 gearContainer 66321 } of this.trackViews) { 66322 axis.remove(); 66323 66324 for (let { 66325 $viewport 66326 } of viewports) { 66327 $viewport.detach(); 66328 } 66329 66330 sampleNameViewport.viewport.remove(); 66331 outerScroll.remove(); 66332 dragHandle.remove(); 66333 gearContainer.remove(); 66334 } // Reattach the divs to the dom in the correct order 66335 66336 66337 const viewportColumns = this.columnContainer.querySelectorAll('.igv-column'); 66338 66339 for (let { 66340 axis, 66341 viewports, 66342 sampleNameViewport, 66343 outerScroll, 66344 dragHandle, 66345 gearContainer 66346 } of this.trackViews) { 66347 this.columnContainer.querySelector('.igv-axis-column').appendChild(axis); 66348 66349 for (let i = 0; i < viewportColumns.length; i++) { 66350 const { 66351 $viewport 66352 } = viewports[i]; 66353 viewportColumns[i].appendChild($viewport.get(0)); 66354 } 66355 66356 this.columnContainer.querySelector('.igv-sample-name-column').appendChild(sampleNameViewport.viewport); 66357 this.columnContainer.querySelector('.igv-scrollbar-column').appendChild(outerScroll); 66358 this.columnContainer.querySelector('.igv-track-drag-column').appendChild(dragHandle); 66359 this.columnContainer.querySelector('.igv-gear-menu-column').appendChild(gearContainer); 66360 } 66361 } 66362 66363 getTrackOrder() { 66364 return this.trackViews.filter(tv => tv.track && tv.track.name).map(tv => tv.track.name); 66365 } 66366 66367 removeTrackByName(name) { 66368 const copy = this.trackViews.slice(); 66369 66370 for (let trackView of copy) { 66371 if (name === trackView.track.name) { 66372 this.removeTrack(trackView.track); 66373 } 66374 } 66375 } 66376 66377 removeTrack(track) { 66378 this.trackViews.splice(this.trackViews.indexOf(track.trackView), 1); 66379 this.fireEvent('trackremoved', [track]); 66380 this.fireEvent('trackorderchanged', [this.getTrackOrder()]); 66381 track.trackView.dispose(); 66382 } 66383 /** 66384 * API function 66385 */ 66386 66387 66388 removeAllTracks() { 66389 const remainingTrackViews = []; 66390 66391 for (let trackView of this.trackViews) { 66392 if (trackView.track.id !== 'ruler' && trackView.track.id !== 'ideogram') { 66393 this.fireEvent('trackremoved', [trackView.track]); 66394 trackView.dispose(); 66395 } else { 66396 remainingTrackViews.push(trackView); 66397 } 66398 } 66399 66400 this.trackViews = remainingTrackViews; 66401 } 66402 /** 66403 * 66404 * @param property 66405 * @param value 66406 * @returns {Array} tracks with given property value. e.g. findTracks("type", "annotation") 66407 */ 66408 66409 66410 findTracks(property, value) { 66411 let f = typeof property === 'function' ? trackView => property(trackView.track) : trackView => value === trackView.track[property]; 66412 return this.trackViews.filter(f).map(tv => tv.track); 66413 } 66414 /** 66415 * Set the track height globally for all tracks. (Note: Its not clear why this is useful). 66416 * @param newHeight 66417 */ 66418 66419 66420 setTrackHeight(newHeight) { 66421 this.trackHeight = newHeight; 66422 this.trackViews.forEach(function (trackView) { 66423 trackView.setTrackHeight(newHeight); 66424 }); 66425 } 66426 66427 async visibilityChange() { 66428 const status = this.referenceFrameList.find(referenceFrame => referenceFrame.bpPerPixel < 0); 66429 66430 if (status) { 66431 const viewportWidth = this.calculateViewportWidth(this.referenceFrameList.length); 66432 66433 for (let referenceFrame of this.referenceFrameList) { 66434 referenceFrame.bpPerPixel = (referenceFrame.end - referenceFrame.start) / viewportWidth; 66435 } 66436 } 66437 66438 if (this.referenceFrameList) { 66439 const isWGV = this.isMultiLocusWholeGenomeView() || GenomeUtils.isWholeGenomeView(this.referenceFrameList[0].chr); 66440 this.navbarManager.navbarDidResize(this.$navigation.width(), isWGV); 66441 } 66442 66443 await this.resize(); 66444 } 66445 66446 async resize() { 66447 const viewportWidth = this.calculateViewportWidth(this.referenceFrameList.length); 66448 66449 for (let referenceFrame of this.referenceFrameList) { 66450 const index = this.referenceFrameList.indexOf(referenceFrame); 66451 const { 66452 chr, 66453 genome 66454 } = referenceFrame; 66455 const { 66456 bpLength 66457 } = genome.getChromosome(referenceFrame.chr); 66458 const viewportWidthBP = referenceFrame.toBP(viewportWidth); // viewportWidthBP > bpLength occurs when locus is full chromosome and user widens browser 66459 66460 if (GenomeUtils.isWholeGenomeView(chr) || viewportWidthBP > bpLength) { 66461 // console.log(`${ Date.now() }
66461 Recalc referenceFrame(${ index }) bpp. viewport ${ StringUtils.numberFormatter(viewportWidthBP) } > ${ StringUtils.numberFormatter(bpLength) }.`) 66462 referenceFrame.bpPerPixel = bpLength / viewportWidth; 66463 } else { 66464 // console.log(`${ Date.now() } Recalc referenceFrame(${ index }) end.`) 66465 referenceFrame.end = referenceFrame.start + referenceFrame.toBP(viewportWidth); 66466 } 66467 66468 for (let { 66469 viewports 66470 } of this.trackViews) { 66471 viewports[index].setWidth(viewportWidth); 66472 } 66473 } 66474 66475 await this.updateViews(true); 66476 this.updateUIWithReferenceFrameList(); 66477 } 66478 66479 async updateViews(force) { 66480 const trackViews = this.trackViews; 66481 this.updateLocusSearchWidget(); 66482 66483 for (let centerGuide of this.centerLineList) { 66484 centerGuide.repaint(); 66485 } // Don't autoscale while dragging. 66486 66487 66488 if (this.dragObject) { 66489 for (let trackView of trackViews) { 66490 await trackView.updateViews(force); 66491 } 66492 } else { 66493 // Group autoscale 66494 const groupAutoscaleTracks = {}; 66495 const otherTracks = []; 66496 66497 for (let trackView of trackViews) { 66498 const group = trackView.track.autoscaleGroup; 66499 66500 if (group) { 66501 var l = groupAutoscaleTracks[group]; 66502 66503 if (!l) { 66504 l = []; 66505 groupAutoscaleTracks[group] = l; 66506 } 66507 66508 l.push(trackView); 66509 } else { 66510 otherTracks.push(trackView); 66511 } 66512 } 66513 66514 if (Object.entries(groupAutoscaleTracks).length > 0) { 66515 const keys = Object.keys(groupAutoscaleTracks); 66516 66517 for (let group of keys) { 66518 const groupTrackViews = groupAutoscaleTracks[group]; 66519 const promises = []; 66520 66521 for (let trackView of groupTrackViews) { 66522 promises.push(trackView.getInViewFeatures()); 66523 } 66524 66525 const featureArray = await Promise.all(promises); 66526 var allFeatures = [], 66527 dataRange; 66528 66529 for (let features of featureArray) { 66530 allFeatures = allFeatures.concat(features); 66531 } 66532 66533 dataRange = doAutoscale(allFeatures); 66534 const p = []; 66535 66536 for (let trackView of groupTrackViews) { 66537 trackView.track.dataRange = dataRange; 66538 trackView.track.autoscale = false; 66539 p.push(trackView.updateViews(force)); 66540 } 66541 66542 await Promise.all(p); 66543 } 66544 } 66545 66546 await Promise.all(otherTracks.map(tv => tv.updateViews(force))); // for (let trackView of otherTracks) { 66547 // await trackView.updateViews(force); 66548 // } 66549 } 66550 } 66551 66552 updateLocusSearchWidget() { 66553 const referenceFrameList = this.referenceFrameList; // Update end position of reference frames based on pixel widths. This is hacky, but its been done here 66554 // for a long time, although indirectly. 66555 66556 const width = this.calculateViewportWidth(this.referenceFrameList.length); 66557 66558 for (let referenceFrame of referenceFrameList) { 66559 referenceFrame.end = referenceFrame.start + referenceFrame.bpPerPixel * width; 66560 } 66561 66562 this.chromosomeSelectWidget.select.value = referenceFrameList.length === 1 ? this.referenceFrameList[0].chr : ''; 66563 const loc = this.referenceFrameList.map(rf => rf.getLocusString()).join(' '); //const loc = this.referenceFrameList.length === 1 ? this.referenceFrameList[0].getLocusString() : ''; 66564 66565 this.$searchInput.val(loc); 66566 this.fireEvent('locuschange', [this.referenceFrameList]); 66567 } 66568 66569 calculateViewportWidth(columnCount) { 66570 let { 66571 width 66572 } = this.columnContainer.getBoundingClientRect(); 66573 const sampleNameViewportWidth = this.getSampleNameViewportWidth(); 66574 width -= igv_axis_column_width + sampleNameViewportWidth + igv_scrollbar_outer_width + igv_track_manipulation_handle_width + igv_track_gear_menu_column_width; 66575 width -= column_multi_locus_shim_width * (columnCount - 1); 66576 return Math.floor(width / columnCount); 66577 } 66578 66579 getCenterLineXOffset() { 66580 let { 66581 width: columnContainerWidth 66582 } = this.columnContainer.getBoundingClientRect(); 66583 columnContainerWidth -= igv_axis_column_width + this.get
66583SampleNameViewportWidth() + igv_scrollbar_outer_width + igv_track_manipulation_handle_width + igv_track_gear_menu_column_width; 66584 return Math.floor(columnContainerWidth / 2 + igv_axis_column_width); 66585 } 66586 66587 minimumBases() { 66588 return this.config.minimumBases; 66589 } // Zoom in by a factor of 2, keeping the same center location 66590 66591 66592 zoomIn() { 66593 this.zoomWithScaleFactor(0.5); 66594 } 66595 66596 // Zoom out by a factor of 2, keeping the same center location if possible 66597 zoomOut() { 66598 this.zoomWithScaleFactor(2.0); 66599 } 66600 66601 async zoomWithScaleFactor(scaleFactor, centerBPOrUndefined, referenceFrameOrUndefined) { 66602 const viewportWidth = this.calculateViewportWidth(this.referenceFrameList.length); 66603 let referenceFrames = referenceFrameOrUndefined ? [referenceFrameOrUndefined] : this.referenceFrameList; 66604 66605 for (let referenceFrame of referenceFrames) { 66606 referenceFrame.zoomWithScaleFactor(this, scaleFactor, viewportWidth, centerBPOrUndefined); 66607 } 66608 } 66609 66610 async presentMultiLocusPanel(alignment, referenceFrameLeft) { 66611 // account for reduced viewport width as a result of adding right mate pair panel 66612 const viewportWidth = this.calculateViewportWidth(1 + this.referenceFrameList.length); 66613 const scaleFactor = this.calculateViewportWidth(this.referenceFrameList.length) / this.calculateViewportWidth(1 + this.referenceFrameList.length); 66614 adjustReferenceFrame(scaleFactor, referenceFrameLeft, viewportWidth, alignment.start, alignment.lengthOnRef); // create right mate pair reference frame 66615 66616 const mateChrName = this.genome.getChromosomeName(alignment.mate.chr); 66617 const referenceFrameRight = createReferenceFrameWithAlignment(this.genome, mateChrName, referenceFrameLeft.bpPerPixel, viewportWidth, alignment.mate.position, alignment.lengthOnRef); // add right mate panel beside left mate panel 66618 66619 const indexLeft = this.referenceFrameList.indexOf(referenceFrameLeft); 66620 const indexRight = 1 + this.referenceFrameList.indexOf(referenceFrameLeft); 66621 const { 66622 $viewport 66623 } = this.trackViews[0].viewports[indexLeft]; 66624 const viewportColumn = viewportColumnManager.insertAfter($viewport.get(0).parentElement); 66625 66626 if (indexRight === this.referenceFrameList.length) { 66627 this.referenceFrameList.push(referenceFrameRight); 66628 66629 for (let trackView of this.trackViews) { 66630 const viewport = createViewport(trackView, viewportColumn, referenceFrameRight); 66631 trackView.viewports.push(viewport); 66632 } 66633 } else { 66634 this.referenceFrameList.splice(indexRight, 0, referenceFrameRight); 66635 66636 for (let trackView of this.trackViews) { 66637 const viewport = createViewport(trackView, viewportColumn, referenceFrameRight); 66638 trackView.viewports.splice(indexRight, 0, viewport); 66639 } 66640 } 66641 66642 this.centerLineList = this.createCenterLineList(this.columnContainer); 66643 await this.resize(); 66644 } 66645 66646 async removeMultiLocusPanel(referenceFrame) { 66647 // find the $column corresponding to this referenceFrame and remove it 66648 const index = this.referenceFrameList.indexOf(referenceFrame); 66649 const { 66650 $viewport 66651 } = this.trackViews[0].viewports[index]; 66652 viewportColumnManager.removeColumnAtIndex(index, $viewport.parent().get(0)); 66653 66654 for (let { 66655 viewports 66656 } of this.trackViews) { 66657 viewports[index].dispose(); 66658 viewports.splice(index, 1); 66659 } 66660 66661 this.referenceFrameList.splice(index, 1); 66662 66663 if (1 === this.referenceFrameList.length && this.getRulerTrackView()) { 66664 for (let rulerViewport of this.getRulerTrackView().viewports) { 66665 rulerViewport.dismissLocusLabel(); 66666 } 66667 } 66668 66669 const scaleFactor = this.calculateViewportWidth(1 + this.referenceFrameList.length) / this.calculateViewportWidth(this.referenceFrameList.length); 66670 await this.rescaleForMultiLocus(scaleFactor); 66671 } 66672 66673 async selectMultiLocusPanel(referenceFrame) { 66674 const referenceFrameIndex = this.referenceFrameList.indexOf(referenceFrame);
66674 // Remove columns for unselected panels 66675 66676 this.columnContainer.querySelectorAll('.igv-column').forEach((column, c) => { 66677 if (c === referenceFrameIndex) ; else { 66678 column.remove(); 66679 } 66680 }); // Remove all column shims 66681 66682 this.columnContainer.querySelectorAll('.igv-column-shim').forEach(shim => shim.remove()); // Discard viewports 66683 66684 for (let trackView of this.trackViews) { 66685 const retain = trackView.viewports[referenceFrameIndex]; 66686 trackView.viewports.filter((viewport, i) => i !== referenceFrameIndex).forEach(viewport => viewport.dispose()); 66687 trackView.viewports = [retain]; 66688 } 66689 66690 const viewportWidth = this.calculateViewportWidth(1); 66691 referenceFrame.bpPerPixel = (referenceFrame.end - referenceFrame.start) / viewportWidth; 66692 this.referenceFrameList = [referenceFrame]; 66693 this.trackViews.forEach(_ref2 => { 66694 let { 66695 viewports 66696 } = _ref2; 66697 return viewports.forEach(viewport => viewport.setWidth(viewportWidth)); 66698 }); 66699 this.centerLineList = this.createCenterLineList(this.columnContainer); 66700 this.updateUIWithReferenceFrameList(); 66701 await this.updateViews(true); 66702 } 66703 66704 async selectMultiLocusPanel(referenceFrame) { 66705 const referenceFrameIndex = this.referenceFrameList.indexOf(referenceFrame); // Remove columns for unselected panels 66706 66707 this.columnContainer.querySelectorAll('.igv-column').forEach((column, c) => { 66708 if (c === referenceFrameIndex) ; else { 66709 column.remove(); 66710 } 66711 }); // Remove all column shims 66712 66713 this.columnContainer.querySelectorAll('.igv-column-shim').forEach(shim => shim.remove()); // Discard viewports 66714 66715 for (let trackView of this.trackViews) { 66716 const retain = trackView.viewports[referenceFrameIndex]; 66717 trackView.viewports.filter((viewport, i) => i !== referenceFrameIndex).forEach(viewport => viewport.dispose()); 66718 trackView.viewports = [retain]; 66719 } 66720 66721 const viewportWidth = this.calculateViewportWidth(1); 66722 referenceFrame.bpPerPixel = (referenceFrame.end - referenceFrame.start) / viewportWidth; 66723 this.referenceFrameList = [referenceFrame]; 66724 this.trackViews.forEach(_ref3 => { 66725 let { 66726 viewports 66727 } = _ref3; 66728 return viewports.forEach(viewport => viewport.setWidth(viewportWidth)); 66729 }); 66730 this.centerLineList = this.createCenterLineList(this.columnContainer); 66731 this.updateUIWithReferenceFrameList(); 66732 await this.updateViews(true); 66733 } 66734 66735 async rescaleForMultiLocus(scaleFactor) { 66736 const viewportWidth = this.calculateViewportWidth(this.referenceFrameList.length); 66737 66738 for (let referenceFrame of this.referenceFrameList) { 66739 referenceFrame.bpPerPixel *= scaleFactor; 66740 } 66741 66742 for (let { 66743 viewports 66744 } of this.trackViews) { 66745 for (let viewport of viewports) { 66746 viewport.setWidth(viewportWidth); 66747 } 66748 } 66749 66750 this.centerLineList = this.createCenterLineList(this.columnContainer); 66751 this.updateUIWithReferenceFrameList(); 66752 await this.updateViews(true); 66753 } 66754 /** 66755 * @deprecated This is a deprecated method with no known usages. To be removed in a future release. 66756 */ 66757 66758 66759 async goto(chr, start, end) { 66760 await this.search(chr + ":" + start + "-" + end); 66761 } 66762 /** 66763 * Search for the locus string -- this function is called from various igv.js GUI elements, and is not part of the 66764 * API. Wraps ```search``` and presents an error dialog if false. 66765 * 66766 * @param string 66767 * @param init 66768 * @returns {Promise<void>} 66769 */ 66770 66771 66772 async doSearch(string, init) { 66773 const success = await this.search(string, init); 66774 66775 if (!success) { 66776 Alert.presentAlert(new Error(`Unrecognized locus: <b> ${string} </b>`)); 66777 } 66778 66779 return success; 66780 } 66781 /** 66782 * Search for the locus string 66783 * NOTE: This is part of the API 66784 * @param string 66785 * @param init true if called during browser initialization 66786 * @returns {Promise<boolean>} true if found, false if not 66787 */ 66788 66789 66790 async search(string, init) { 66791 const loci = await search(this, string); 66792 66793 if (loci && loci.length > 0) { 66794 // create reference frame list based on search loci 66795 this.referenceFrameList = createReferenceFrameList(loci, this.genome, this.flanking, this.minimumBases(), this.calculateViewportWidth(loci.length)); // discard viewport DOM elements 66796 66797 for (let trackView of this.trackViews) { 66798 // empty axis column, viewport columns, sampleName column, scroll column, drag column, gear column 66799 trackView.removeDOMFromColumnContainer(); 66800 } // discard ONLY viewport columns 66801 66802 66803 this.columnContainer.querySelectorAll('.igv-column-shim, .igv-column').forEach(el => el.remove()); // Insert viewport columns preceding the sample-name column 66804 66805 viewportColumnManager.insertBefore(this.columnContainer.querySelector('.igv-sample-name-column'), this.referenceFrameList.length); 66806 this.centerLineList = this.createCenterLineList(this.columnContainer); // Populate the columns 66807 66808 for (let trackView of this.trackViews) { 66809 trackView.addDOMToColumnContainer(this, this.columnContainer, this.referenceFrameList); 66810 } 66811 66812 this.updateUIWithReferenceFrameList(); 66813 66814 if (!init) { 66815 await this.updateViews(); 66816 } 66817 66818 return true; 66819 } else { 66820 return false;
66821 } 66822 } 66823 66824 async loadSampleInformation(url) { 66825 var name = url; 66826 66827 if (isFile(url)) { 66828 name = url.name; 66829 } 66830 66831 var ext = name.substr(name.lastIndexOf('.') + 1); 66832 66833 if (ext === 'fam') { 66834 this.sampleInformation = await loadPlinkFile(url); 66835 } 66836 } 66837 66838 // EVENTS 66839 on(eventName, fn) { 66840 if (!this.eventHandlers[eventName]) { 66841 this.eventHandlers[eventName] = []; 66842 } 66843 66844 this.eventHandlers[eventName].push(fn); 66845 } 66846 66847 /** 66848 * @deprecated use off() 66849 * @param eventName 66850 * @param fn 66851 */ 66852 un(eventName, fn) { 66853 this.off(eventName, fn); 66854 } 66855 66856 off(eventName, fn) { 66857 if (!eventName) { 66858 this.eventHandlers = {}; // Remove all event handlers 66859 } else if (!fn) { 66860 this.eventHandlers[eventName] = []; // Remove all eventhandlers matching name 66861 } else { 66862 // Remove specific event handler 66863 const handlers = this.eventHandlers[eventName]; 66864 66865 if (!handlers || handlers.length === 0) { 66866 console.warn("No handlers to remove for event: " + eventName); 66867 } else { 66868 const callbackIndex = handlers.indexOf(fn); 66869 66870 if (callbackIndex !== -1) { 66871 this.eventHandlers[eventName].splice(callbackIndex, 1); 66872 } 66873 } 66874 } 66875 } 66876 66877 fireEvent(eventName, args, thisObj) { 66878 const handlers = this.eventHandlers[eventName]; 66879 66880 if (undefined === handlers || handlers.length === 0) { 66881 return undefined; 66882 } 66883 66884 const scope = thisObj || window; 66885 const results = handlers.map(function (event) { 66886 return event.apply(scope, args); 66887 }); 66888 return results[0]; 66889 } 66890 66891 dispose() { 66892 this.removeMouseHandlers(); 66893 66894 for (let trackView of this.trackViews) { 66895 trackView.dispose(); 66896 } 66897 } 66898 66899 toJSON() { 66900 const json = { 66901 "version": version$1() 66902 }; 66903 66904 if (this.showSampleNames !== undefined) { 66905 json['showSampleNames'] = this.showSampleNames; 66906 } 66907 66908 if (this.sampleNameViewportWidth !== defaultSampleNameViewportWidth) { 66909 json['sampleNameViewportWidth'] = this.sampleNameViewportWidth; 66910 } 66911 66912 json["reference"] = this.genome.toJSON(); 66913 66914 if (isFilePath(json.reference.fastaURL)) { 66915 throw new Error(`Error. Sessions cannot include local file references ${json.reference.fastaURL.name}.`); 66916 } else if (isFilePath(json.reference.indexURL)) { 66917 throw new Error(`Error. Sessions cannot include local file references ${json.reference.indexURL.name}.`); 66918 } // Build locus array (multi-locus view). Use the first track to extract the loci, any track could be used. 66919 66920 66921 const locus = []; 66922 const gtexSelections = {}; 66923 let anyTrackView = this.trackViews[0]; 66924 66925 for (let { 66926 referenceFrame 66927 } of anyTrackView.viewports) { 66928 const locusString = referenceFrame.getLocusString(); 66929 locus.push(locusString); 66930 66931 if (referenceFrame.selection) { 66932 const selection = { 66933 gene: referenceFrame.selection.gene, 66934 snp: referenceFrame.selection.snp 66935 }; 66936 gtexSelections[locusString] = selection; 66937 } 66938 } 66939 66940 json["locus"] = locus.length === 1 ? locus[0] : locus; 66941 const gtexKeys = Object.getOwnPropertyNames(gtexSelections); 66942 66943 if (gtexKeys.length > 0) { 66944 json["gtexSelections"] = gtexSelections; 66945 } 66946 66947 const trackJson = []; 66948 const errors = []; 66949 66950 for (let { 66951 track 66952 } of this.trackViews) { 66953 try { 66954 let config; 66955 66956 if (typeof track.getState === "function") { 66957 config = track.getState(); 66958 } else { 66959 config = track.config; 66960 } 66961 66962 if (config) { 66963 // null backpointer to browser 66964 if (config.browser) { 66965 delete config.browser; 66966 } 66967 66968 config.order = track.order; //order++; 66969 66970 trackJson.push(config); 66971 } 66972 } catch (e) { 66973 errors.push(e); 66974 } 66975 } 66976 66977 if (errors.length > 0) { 66978 let n = 1; 66979 let message = 'Errors encountered saving session:'; 66980 66981 for (let e of errors) { 66982 message += ` (${n++}) ${e.toString()}.`; 66983 } 66984 66985 throw Error(message); 66986 } 66987 66988 const locaTrackFiles = trackJson.filter(track => { 66989 track.url && isFile(track.url); 66990 }); 66991 66992 if (locaTrackFiles.length > 0) { 66993 throw new Error(`Error. Sessions cannot include local file references.`); 66994 } 66995 66996 json["tracks"] = trackJson; 66997 return json; // This is an object, not a json string 66998 } 66999 67000 compressedSession() { 67001 const json = JSON.stringify(this.toJSON()); 67002 return compressString(json); 67003 } 67004 67005 sessionURL() { 67006 const path = window.location.href.slice(); 67007 const idx = path.indexOf("?"); 67008 const surl = (idx > 0 ? path.substring(0, idx) : path) + "?sessionURL=blob:" + this.compressedSession(); 67009 return surl; 67010 } 67011 67012 currentLoci() { 67013 const loci = []; 67014 const anyTrackView = this.trackViews[0]; 67015 67016 for (let { 67017 referenceFrame 67018 } of anyTrackView.viewports) { 67019 const locusString = referenceFrame.getLocusString(); 67020 loci.push(locusString); 67021 } 67022 67023 return loci; 67024 } 67025 /** 67026 * Record a mouse click on a specific viewport. This might be the start of a drag operation. Dragging
67027 * (panning) is handled here so that the mouse can move out of a specific viewport (e.g. stray into another 67028 * track) without halting the drag. 67029 * 67030 * @param e 67031 * @param viewport 67032 */ 67033 67034 67035 mouseDownOnViewport(e, viewport) { 67036 var coords; 67037 coords = pageCoordinates$1(e); 67038 this.vpMouseDown = { 67039 viewport, 67040 lastMouseX: coords.x, 67041 mouseDownX: coords.x, 67042 lastMouseY: coords.y, 67043 mouseDownY: coords.y, 67044 referenceFrame: viewport.referenceFrame 67045 }; 67046 } 67047 67048 cancelTrackPan() { 67049 const dragObject = this.dragObject; 67050 this.dragObject = undefined; 67051 this.isScrolling = false; 67052 this.vpMouseDown = undefined; 67053 67054 if (dragObject && dragObject.viewport.referenceFrame.start !== dragObject.start) { 67055 this.updateViews(); 67056 this.fireEvent('trackdragend'); 67057 } 67058 } 67059 67060 startTrackDrag(trackView) { 67061 this.dragTrack = trackView; 67062 } 67063 67064 updateTrackDrag(dragDestination) { 67065 if (dragDestination && this.dragTrack) { 67066 const dragged = this.dragTrack; 67067 const indexDestination = this.trackViews.indexOf(dragDestination); 67068 const indexDragged = this.trackViews.indexOf(dragged); 67069 const trackViews = this.trackViews; 67070 trackViews[indexDestination] = dragged; 67071 trackViews[indexDragged] = dragDestination; 67072 const newOrder = this.trackViews[indexDestination].track.order; 67073 this.trackViews[indexDragged].track.order = newOrder; 67074 const nTracks = trackViews.length; 67075 let lastOrder = newOrder; 67076 67077 if (indexDestination < indexDragged) { 67078 // Displace tracks below 67079 for (let i = indexDestination + 1; i < nTracks; i++) { 67080 const track = trackViews[i].track; 67081 67082 if (track.order <= lastOrder) { 67083 track.order = Math.min(Number.MAX_SAFE_INTEGER, lastOrder + 1); 67084 lastOrder = track.order; 67085 } else { 67086 break; 67087 } 67088 } 67089 } else { 67090 // Displace tracks above. First track (index 0) is "ruler" 67091 for (let i = indexDestination - 1; i > 0; i--) { 67092 const track = trackViews[i].track; 67093 67094 if (track.order >= lastOrder) { 67095 track.order = Math.max(-Number.MAX_SAFE_INTEGER, lastOrder - 1); 67096 lastOrder = track.order; 67097 } else { 67098 break; 67099 } 67100 } 67101 } 67102 67103 this.reorderTracks(); 67104 } 67105 } 67106 67107 endTrackDrag() { 67108 if (this.dragTrack) { 67109 // this.dragTrack.$trackDragScrim.hide(); 67110 this.dragTrack = undefined; 67111 this.fireEvent('trackorderchanged', [this.getTrackOrder()]); 67112 } else { 67113 this.dragTrack = undefined; 67114 } 67115 } 67116 /** 67117 * Mouse handlers to support drag (pan) 67118 */ 67119 67120 67121 addMouseHandlers() { 67122 this.addWindowResizeHandler(); 67123 this.addRootMouseUpHandler(); 67124 this.addRootMouseLeaveHandler(); 67125 this.addColumnContainerEventHandlers(); 67126 } 67127 67128 removeMouseHandlers() { 67129 this.removeWindowResizeHandler(); 67130 this.removeRootMouseUpHandler(); 67131 this.removeRootMouseLeaveHandler(); 67132 this.removeColumnContainerEventHandlers(); 67133 } 67134 67135 addWindowResizeHandler() { 67136 this.boundWindowResizeHandler = windowResizeHandler.bind(this); 67137 window.addEventListener('resize', this.boundWindowResizeHandler); 67138 67139 function windowResizeHandler() { 67140 this.resize(); 67141 } 67142 } 67143 67144 removeWindowResizeHandler() { 67145 window.removeEventListener('resize', this.boundWindowResizeHandler); 67146 } 67147 67148 addRootMouseUpHandler() { 67149 this.boundRootMouseUpHandler = mouseUpOrLeave.bind(this); 67150 this.root.addEventListener('mouseup', this.boundRootMouseUpHandler); 67151 } 67152 67153 removeRootMouseUpHandler() { 67154 this.root.removeEventListener('mouseup', this.boundRootMouseUpHandler); 67155 } 67156 67157 addRootMouseLeaveHandler() { 67158 this.boundRootMouseLeaveHandler = mouseUpOrLeave.bind(this); 67159 this.root.addEventListener('mouseleave', this.boundRootMouseLeaveHandler); 67160 } 67161 67162 removeRootMouseLeaveHandler() { 67163 this.root.removeEventListener('mouseleave', this.boundRootMouseLeaveHandler); 67164 } 67165 67166 addColumnContainerEventHandlers() { 67167 this.boundColumnContainerMouseMoveHandler = handleMouseMove.bind(this); 67168 this.boundColumnContainerTouchMoveHandler = handleMouseMove.bind(this); 67169 this.boundColumnContainerMouseLeaveHandler = mouseUpOrLeave.bind(this); 67170 this.boundColumnContainerMouseUpHandler = mouseUpOrLeave.bind(this); 67171 this.boundColumnContainerTouchEndHandler = mouseUpOrLeave.bind(this); 67172 this.columnContainer.addEventListener('mousemove', this.boundColumnContainerMouseMoveHandler); 67173 this.columnContainer.addEventListener('touchmove', this.boundColumnContainerTouchMoveHandler); 67174 this.columnContainer.addEventListener('mouseleave', this.boundColumnContainerMouseLeaveHandler); 67175 this.columnContainer.addEventListener('mouseup', this.boundColumnContainerMouseUpHandler); 67176 this.columnContainer.addEventListener('touchend', this.boundColumnContainerTouchEndHandler); 67177 } 67178 67179 removeColumnContainerEventHandlers() { 67180 this.columnContainer.removeEventListener('mousemove', this.boundColumnContainerMouseMoveHandler); 67181 this.columnContainer.removeEventListener('touchmove', this.boundColumnContainerTouchMoveHandler); 67182 this.columnContainer.removeEventListener('mouseleave', this.boundColumnContainerMouseLeaveHandler); 67183 this.columnContainer.removeEventListener('mouseup', this.boundColumnContainerMouseUpHandler); 67184 this.columnContainer.removeEventListener('touchend', this.boundColumnContainerTouchEndHandler); 67185 } 67186 67187 async getDriveFileInfo(googleDriveURL) { 67188 const id = getGoogleDriveFileID(googleDriveURL); 67189 const endPoint = "https://www.googleapis.com/drive/v3/files/" + id + "?supportsTeamDrives=true"; 67190 return igvxhr.loadJson(endPoint, buildOptions({})); 67191 } 67192
67193 static uncompressSession(url) { 67194 let bytes; 67195 67196 if (url.indexOf('/gzip;base64') > 0) { 67197 //Proper dataURI 67198 bytes = decodeDataURI$1(url); 67199 let json = ''; 67200 67201 for (let b of bytes) { 67202 json += String.fromCharCode(b); 67203 } 67204 67205 return json; 67206 } else { 67207 let enc = url.substring(5); 67208 return uncompressString(enc); 67209 } 67210 } 67211 67212 createCircularView(container, show) { 67213 this.circularView = createCircularView(container, this); 67214 this.circularViewControl = new CircularViewControl(this.$toggle_button_container.get(0), this); 67215 this.circularView.setAssembly({ 67216 name: this.genome.id, 67217 id: this.genome.id, 67218 chromosomes: makeCircViewChromosomes(this.genome) 67219 }); 67220 this.circularViewVisible = show === true; 67221 } 67222 67223 get circularViewVisible() { 67224 return this.circularView !== undefined && this.circularView.visible; 67225 } 67226 67227 set circularViewVisible(isVisible) { 67228 if (this.circularView) { 67229 this.circularView.visible = isVisible; 67230 this.circularViewControl.setState(isVisible); 67231 } 67232 } 67233 67234 } 67235 67236 function handleMouseMove(e) { 67237 e.preventDefault(); 67238 const { 67239 x, 67240 y 67241 } = pageCoordinates$1(e); 67242 67243 if (this.vpMouseDown) { 67244 const { 67245 viewport, 67246 referenceFrame 67247 } = this.vpMouseDown; // Determine direction, true == horizontal 67248 67249 const horizontal = Math.abs(x - this.vpMouseDown.mouseDownX) > Math.abs(y - this.vpMouseDown.mouseDownY); 67250 67251 if (!this.dragObject && !this.isScrolling) { 67252 if (horizontal) { 67253 if (this.vpMouseDown.mouseDownX && Math.abs(x - this.vpMouseDown.mouseDownX) > this.constants.dragThreshold) { 67254 this.dragObject = { 67255 viewport, 67256 start: referenceFrame.start 67257 }; 67258 } 67259 } else { 67260 if (this.vpMouseDown.mouseDownY && Math.abs(y - this.vpMouseDown.mouseDownY) > this.constants.scrollThreshold) { 67261 this.isScrolling = true; 67262 const viewportHeight = viewport.$viewport.height(); 67263 const contentHeight = maxViewportContentHeight(viewport.trackView.viewports); 67264 this.vpMouseDown.r = viewportHeight / contentHeight; 67265 } 67266 } 67267 } 67268 67269 if (this.dragObject) { 67270 const viewChanged = referenceFrame.shiftPixels(this.vpMouseDown.lastMouseX - x, viewport.$viewport.width()); 67271 67272 if (viewChanged) { 67273 this.updateViews(); 67274 } 67275 67276 this.fireEvent('trackdrag'); 67277 } 67278 67279 if (this.isScrolling) { 67280 const delta = this.vpMouseDown.r * (this.vpMouseDown.lastMouseY - y); 67281 viewport.trackView.moveScroller(delta); 67282 } 67283 67284 this.vpMouseDown.lastMouseX = x; 67285 this.vpMouseDown.lastMouseY = y; 67286 } 67287 } 67288 67289 function mouseUpOrLeave(e) { 67290 this.cancelTrackPan(); 67291 this.endTrackDrag(); 67292 } 67293 67294 function getInitialLocus(locus, genome) { 67295 if (locus) { 67296 return Array.isArray(locus) ? locus.join(' ') : locus; 67297 } else { 67298 return genome.getHomeChromosomeName(); 67299 } 67300 } 67301 67302 function logo() { 67303 return $$1('<svg width="690px" height="324px" viewBox="0 0 690 324" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">' + '<title>IGV</title>' + '<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">' + '<g id="IGV" fill="#666666">' + '<polygon id="Path" points="379.54574 8.00169252 455.581247 8.00169252 515.564813 188.87244 532.884012 253.529506 537.108207 253.529506 554.849825 188.87244 614.833392 8.00169252 689.60164 8.00169252 582.729511 320.722144 486.840288 320.722144"></polygon>' + '<path d="M261.482414,323.793286 C207.975678,323.793286 168.339046,310.552102 142.571329,284.069337 C116.803612,257.586572 103.919946,217.158702 103.919946,162.784513 C103.919946,108.410325 117.437235,67.8415913 144.472217,41.0770945 C171.507199,14.3125977 212.903894,0.930550071 268.663545,0.930550071 C283.025879,0.930550071 298.232828,1.84616386 3
6730314.284849,3.6774189 C330.33687,5.50867394 344.839793,7.97378798 357.794056,11.072835 L357.794056,68.968378 C339.48912,65.869331 323.578145,63.5450806 310.060654,61.9955571 C296.543163,60.4460336 284.574731,59.6712835 274.154998,59.6712835 C255.850062,59.6712835 240.502308,61.4320792 228.111274,64.9537236 C215.720241,68.4753679 205.793482,74.2507779 198.330701,82.2801269 C190.867919,90.309476 185.587729,100.87425 182.48997,113.974767 C179.392212,127.075284 177.843356,143.345037 177.843356,162.784513 C177.843356,181.942258 179.251407,198.000716 182.067551,210.960367 C184.883695,223.920018 189.671068,234.41436 196.429813,242.443709 C203.188559,250.473058 212.059279,256.178037 223.042241,259.558815 C234.025202,262.939594 247.683295,264.629958 264.01693,264.629958 C268.241146,264.629958 273.098922,264.489094 278.590403,264.207362 C284.081883,263.925631 289.643684,263.50304 295.275972,262.939577 L295.275972,159.826347 L361.595831,159.826347 L361.595831,308.579859 C344.698967,313.087564 327.239137,316.750019 309.215815,319.567334 C291.192494,322.38465 275.281519,323.793286 261.482414,323.793286 L261.482414,323.793286 L261.482414,323.793286 Z" id="Path"></path>;' + '<polygon id="Path" points="0.81355666 5.00169252 73.0472883 5.00169252 73.0472883 317.722144 0.81355666 317.722144"></polygon>' + '</g> </g> </svg>'); 67304 } 67305 67306 function toggleTrackLabels(trackViews, isVisible) { 67307 for (let { 67308 viewports 67309 } of trackViews) { 67310 for (let viewport of viewports) { 67311 if (viewport.$trackLabel) { 67312 if (0 === viewports.indexOf(viewport) && true === isVisible) { 67313 viewport.$trackLabel.show(); 67314 } else { 67315 viewport.$trackLabel.hide(); 67316 } 67317 } 67318 } 67319 } 67320 } 67321 67322 /* 67323 * The MIT License (MIT) 67324 * 67325 * Copyright (c) 2014 Broad Institute 67326 * 67327 * Permission is hereby granted, free of charge, to any person obtaining a copy 67328 * of this software and associated documentation files (the "Software"), to deal 67329 * in the Software without restriction, including without limitation the rights 67330 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 67331 * copies of the Software, and to permit persons to whom the Software is 67332 * furnished to do so, subject to the following conditions: 67333 * 67334 * The above copyright notice and this permission notice shall be included in 67335 * all copies or substantial portions of the Software. 67336 * 67337 * 67338 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 67339 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 67340 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 67341 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 67342 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 67343 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 67344 * THE SOFTWARE. 67345 */ 67346 let allBrowsers = []; 67347 /** 67348 * Create an igv.browser instance. This object defines the public API for interacting with the genome browser. 67349 * 67350 * @param parentDiv - DOM tree root 67351 * @param config - configuration options. 67352 * 67353 */ 67354 67355 async function createBrowser(parentDiv, config) { 67356 if (undefined === config) config = {}; // Initialize pre-defined genomes. The genome list is shared among all browser instances 67357 67358 if (!GenomeUtils.KNOWN_GENOMES) { 67359 await GenomeUtils.initializeGenomes(config); 67360 } 67361 67362 setDefaults(config); 67363 67364 if (config.queryParametersSupported !== false) { 67365 extractQuery(config); 67366 } 67367 67368 if (config.apiKey) { 67369 igvxhr.setApiKey(config.apiKey); 67370 } 67371 67372 if (config.oauthToken) { 67373 oauth.setToken(config.oauthToken); 67374 } 67375 67376 if (config.clientId && !isInitialized()) { 67377 await init$1({ 67378 clientId: config.clientId, 67379 apiKey: config.apiKey, 67380 scope: 'https://www.googleapis.com/auth/userinfo.profile' 67381 }); 67382 } // Create browser 67383 67384 67385 const browser = new Browser(config, parentDiv); 67386 allBrowsers.push(browser); // Load initial session 67387 67388 if (config.sessionURL) { 67389 await browser.loadSession({ 67390 url: config.sessionURL 67391 }); 67392 } else { 67393 await browser.loadSessionObject(config); 67394 } 67395 67396 const isWGV = browser.isMultiLocusWholeGenomeView() || GenomeUtils.isWholeGenomeView(browser.referenceFrameList[0].chr); 67397 browser.navbarManager.navbarDidResize(browser.$navigation.width(), isWGV); 67398 return browser; 67399 } 67400 67401 function removeBrowser(browser) {
67402 browser.dispose(); 67403 browser.root.remove(); 67404 allBrowsers = allBrowsers.filter(item => item !== browser); 67405 } 67406 67407 function removeAllBrowsers() { 67408 for (let browser of allBrowsers) { 67409 browser.dispose(); 67410 browser.root.remove(); 67411 } 67412 67413 allBrowsers = []; 67414 } 67415 /** 67416 * This function provided so clients can inform igv of a visibility change, typically when an igv instance is 67417 * made visible from a tab, accordion, or similar widget. 67418 */ 67419 67420 67421 async function visibilityChange() { 67422 for (let browser of allBrowsers) { 67423 await browser.visibilityChange(); 67424 } 67425 } 67426 67427 function setDefaults(config) { 67428 if (undefined === config.promisified) { 67429 config.promisified = false; 67430 } 67431 67432 if (undefined === config.minimumBases) { 67433 config.minimumBases = 40; 67434 } 67435 67436 if (undefined === config.showIdeogram) { 67437 config.showIdeogram = true; 67438 } 67439 67440 if (undefined === config.showCircularView) { 67441 config.showCircularView = false; 67442 } 67443 67444 if (undefined === config.showCircularViewButton) { 67445 config.showCircularViewButton = false; 67446 } 67447 67448 if (undefined === config.showTrackLabelButton) { 67449 config.showTrackLabelButton = true; 67450 } 67451 67452 if (undefined === config.showTrackLabels) { 67453 config.showTrackLabels = true; 67454 } 67455 67456 if (undefined === config.showCursorTrackingGuideButton) { 67457 config.showCursorTrackingGuideButton = true; 67458 } 67459 67460 if (undefined === config.showCursorTrackingGuide) { 67461 config.showCursorTrackingGuide = false; 67462 } 67463 67464 if (undefined === config.showCenterGuideButton) { 67465 config.showCenterGuideButton = true; 67466 } 67467 67468 if (undefined === config.showCenterGuide) { 67469 config.showCenterGuide = false; 67470 } 67471 67472 if (undefined === config.showSampleNames) { 67473 config.showSampleNames = false; 67474 } 67475 67476 if (undefined === config.showSVGButton) { 67477 config.showSVGButton = true; 67478 } 67479 67480 if (config.showControls === undefined) { 67481 config.showControls = true; 67482 } 67483 67484 if (config.showNavigation === undefined) { 67485 config.showNavigation = true; 67486 } 67487 67488 if (config.showRuler === undefined) { 67489 config.showRuler = true; 67490 } 67491 67492 if (config.flanking === undefined) { 67493 config.flanking = 1000; 67494 } 67495 67496 if (config.pairsSupported === undefined) { 67497 config.pairsSupported = true; 67498 } 67499 67500 if (!config.tracks) { 67501 config.tracks = []; 67502 } 67503 } 67504 67505 function extractQuery(config) { 67506 var i1, i2, i, j, s, query, tokens, uri, key, value; 67507 uri = window.location.href; 67508 query = {}; 67509 i1 = uri.indexOf("?"); 67510 i2 = uri.lastIndexOf("#"); 67511 let files; 67512 let indexURLs; 67513 let names; 67514 67515 if (i1 >= 0) { 67516 if (i2 < 0) i2 = uri.length; 67517 67518 for (i = i1 + 1; i < i2;) { 67519 j = uri.indexOf("&", i); 67520 if (j < 0) j = i2; 67521 s = uri.substring(i, j); 67522 tokens = s.split("=", 2); 67523 67524 if (tokens.length === 2) { 67525 key = tokens[0]; 67526 value = decodeURIComponent(tokens[1]); 67527 67528 if ('file' === key) { 67529 // IGV desktop style file parameter 67530 files = value.split(','); 67531 } else if ('index' === key) { 67532 // IGV desktop style index parameter 67533 indexURLs = value.split(','); 67534 } else if ('name' === key) { 67535 // IGV desktop style index parameter 67536 names = value.split(','); 67537 } else if ('genome' === key && (value.startsWith("https://") || value.startsWith("http://")) && !value.endsWith(".json")) { 67538 // IGV desktop compatibility -- assuming url to fasta 67539 config['reference'] = { 67540 fastaURL: value, 67541 indexURL: value + ".fai" 67542 }; 67543 } else { 67544 config[key] = value; 67545 } 67546 67547 i = j + 1; 67548 } 67549 } 67550 } 67551 67552 if (files) { 67553 if (!config.tracks) config.tracks = []; 67554 67555 for (let i = 0; i < files.length; i++) { 67556 if (files[i].endsWith(".xml") || files[i].endsWith(".json")) { 67557 config.sessionURL = files[i]; 67558 break; 67559 } 67560 67561 const trackConfig = { 67562 url: files[i] 67563 }; 67564 67565 if (indexURLs && indexURLs.length > i) { 67566 trackConfig.indexURL = indexURLs[i]; 67567 } 67568 67569 if (names && names.length > i) { 67570 trackConfig.name = names[i]; 67571 } 67572 67573 config.tracks.push(trackConfig); 67574 } 67575 } 67576 67577 return query; 67578 } 67579 67580 async function createTrack(config, browser) { 67581 return await Browser.prototype.createTrack.call(browser, config); 67582 } 67583 67584 function embedCSS() { 67585 var css = '.igv-navbar {\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: space-between;\n align-items: center;\n box-sizing: border-box;\n width: 100%;\n color: #444;\n font-size: 12px;\n font-family: \"Open Sans\", sans-serif;\n font-weight: 400;\n line-height: 32px;\n padding-left: 8px;\n padding-right: 8px;\n margin-top: 2px;\n margin-bottom: 6px;\n height: 32px;\n border-style: solid;\n border-radius: 3px;\n border-width: thin;\n border-color: #bfbfbf;\n background-color: #f3f3f3; }\n .igv-navbar .igv-navbar-left-container {\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: space-between;
67585\n align-items: center;\n height: 32px;\n line-height: 32px; }\n .igv-navbar .igv-navbar-left-container .igv-logo {\n width: 34px;\n height: 32px;\n margin-right: 8px; }\n .igv-navbar .igv-navbar-left-container .igv-current-genome {\n height: 32px;\n margin-left: 4px;\n margin-right: 4px;\n user-select: none;\n line-height: 32px;\n vertical-align: middle;\n text-align: center; }\n .igv-navbar .igv-navbar-left-container .igv-navbar-genomic-location {\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: space-between;\n align-items: center;\n height: 100%; }\n .igv-navbar .igv-navbar-left-container .igv-navbar-genomic-location .igv-chromosome-select-widget-container {\n display: flex;\n flex-flow: column;\n flex-wrap: nowrap;\n justify-content: space-around;\n align-items: center;\n height: 100%;\n width: 125px;\n margin-right: 4px; }\n .igv-navbar .igv-navbar-left-container .igv-navbar-genomic-location .igv-chromosome-select-widget-container select {\n display: block;\n cursor: pointer;\n width: 100px;\n height: 75%;\n outline: none;\n font-size: 12px;\n font-family: \"Open Sans\", sans-serif;\n font-weight: 400; }\n .igv-navbar .igv-navbar-left-container .igv-navbar-genomic-location .igv-locus-size-group {\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: space-between;\n align-items: center;\n margin-left: 8px;\n height: 22px; }\n .igv-navbar .igv-navbar-left-container .igv-navbar-genomic-location .igv-locus-size-group .igv-search-container {\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: center;\n width: 210px;\n height: 22px;\n line-height: 22px; }\n .igv-navbar .igv-navbar-left-container .igv-navbar-genomic-location .igv-locus-size-group .igv-search-container input.igv-search-input {\n cursor: text;\n width: 85%;\n height: 22px;\n line-height: 22px;\n font-size: 12px;\n font-family: \"Open Sans\", sans-serif;\n font-weight: 400;\n text-align: left;\n padding-left: 8px;\n margin-right: 8px;\n outline: none;\n border-style: solid;\n border-radius: 3px;\n border-width: thin;\n border-color: #bfbfbf;\n background-color: white; }\n .igv-navbar .igv-navbar-left-container .igv-navbar-genomic-location .igv-locus-size-group .igv-search-container .igv-search-icon-container {\n cursor: pointer;\n height: 16px;\n width: 16px; }\n .igv-navbar .igv-navbar-left-container .igv-navbar-genomic-location .igv-locus-size-group .igv-windowsize-panel-container {\n margin-left: 4px;\n user-select: none; }\n .igv-navbar .igv-navbar-right-container {\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: space-between;\n align-items: center;\n height: 32px;\n line-height: 32px; }\n .igv-navbar .igv-navbar-right-container .igv-navbar-toggle-button-container {\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: space-between;\n align-items: center;\n height: 100%; }\n .igv-navbar .igv-navbar-right-container .igv-navbar-toggle-button-container div {\n margin-left: 0;\n margin-right: 4px; }\n .igv-navbar .igv-navbar-right-container .igv-navbar-toggle-button-container div:last-child {\n margin-left: 0;\n margin-right: 0; }\n .igv-navbar .igv-navbar-right-container .igv-navbar-toggle-button-container-750 {\n display: none; }\n .igv-navbar .igv-navbar-right-container .igv-zoom-widget {\n color: #737373;\n font-size: 18px;\n height: 32px;\n line-height: 32px;\n margin-left: 8px;\n user-select: none;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: flex-end;\n align-items: center; }\n .igv-navbar .igv-navbar-right-container .igv-zoom-widget div {\n cursor: pointer;\n margin-left: unset;\n margin-right: unset; }\n .igv-navbar .igv-navbar-right-container .igv-zoom-widget div:first-child {\n height: 24px;\n width: 24px;\n margin-left: unset;\n margin-right: 8px; }\n .igv-navbar .igv-navbar-right-container .igv-zoom-widget div:last-child {\n height: 24px;\n width: 24px;\n margin-left: 8px;\n margin-right: unset; }\n .igv-navbar .igv-navbar-right-container .igv-zoom-widget div:nth-child(even) {\n display: block;\n height: fit-content; }\n .igv-navbar .igv-navbar-right-container .igv-zoom-widget input {\n display: block;\n width: 125px; }\n .igv-navbar .igv-navbar-right-container .igv-zoom-widget svg {\n display: block; }\n .igv-navbar .igv-navbar-right-container .igv-zoom-widget-900 {\n color: #737373;\n font-size: 18px;\n height: 32px;\n line-height: 32px;\n margin-left: 8px;\n user-select: none;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: flex-end;\n align-items: center; }\n .igv-navbar .igv-navbar-right-container .igv-zoom-widget-900 div {\n cursor: pointer;\n margin-left: unset;\n margin-right: unset; }\n .igv-navbar .igv-navbar-right-container .igv-zoom-widget-900 div:first-child {\n height: 24px;\n width: 24px;\n margin-left: unset;\n margin-right: 8px; }\n .igv-navbar .igv-navbar-right-container .igv-zoom-widget-900 div:last-child {\n height: 24px;\n width: 24px;\n margin-left: 8px;\n margin-right: unset; }\n .igv-navbar .igv-navbar-right-container .igv-zoom-widget-900 div:nth-child(even) {\n width: 0;\n height: 0;\n display: none; }\n .igv-navbar .igv-navbar-right-container .igv-zoom-widget-900 input {\n width: 0;\n height: 0;\n display: none; }\n .igv-navbar .igv-navbar-right-container .igv-zoom-widget-900 svg {\n display: block; }\n .igv-navbar .igv-navbar-right-container .igv-zoom-widget-hidden {\n display: none; }\n\n.igv-navbar-button {\n display: block;\n box-sizing: unset;\n padding-left: 6px;\n padding-right: 6px;\n height: 18px;\n text-transform: capitalize;\n user-select: none;\n line-height: 18px;\n text-align: center;\n vertical-align: middle;\n font-family: \"Open Sans\", sans-serif;\n font-size: 11px;\n font-weight: 200;\n color: #737373;\n background-color: #f3f3f3;\n border-color: #737373;\n border-style: solid;\n border-width: thin;\n border-radius: 6px; }\n\n.igv-navbar-button-clicked {\n color: white;\n background-color: #737373; }
67585\n\n.igv-navbar-button:hover {\n cursor: pointer; }\n\n.igv-zoom-in-notice-container {\n z-index: 1024;\n position: absolute;\n top: 8px;\n left: 50%;\n transform: translate(-50%, 0%);\n display: flex;\n flex-direction: row;\n flex-wrap: nowrap;\n justify-content: center;\n align-items: center;\n background-color: white; }\n .igv-zoom-in-notice-container > div {\n padding-left: 4px;\n padding-right: 4px;\n padding-top: 2px;\n padding-bottom: 2px;\n width: 100%;\n height: 100%;\n font-family: \"Open Sans\", sans-serif;\n font-size: 14px;\n font-weight: 400;\n color: #3f3f3f; }\n\n.igv-zoom-in-notice {\n position: absolute;\n top: 10px;\n left: 50%; }\n .igv-zoom-in-notice div {\n position: relative;\n left: -50%;\n font-family: \"Open Sans\", sans-serif;\n font-size: medium;\n font-weight: 400;\n color: #3f3f3f;\n background-color: rgba(255, 255, 255, 0.51);\n z-index: 64; }\n\n.igv-container-spinner {\n position: absolute;\n top: 90%;\n left: 50%;\n transform: translate(-50%, -50%);\n z-index: 1024;\n width: 24px;\n height: 24px;\n pointer-events: none;\n color: #737373; }\n\n.igv-multi-locus-close-button {\n position: absolute;\n top: 2px;\n right: 0;\n padding-left: 2px;\n padding-right: 2px;\n width: 14px;\n height: 14px;\n color: #666666;\n background-color: white;\n z-index: 1000; }\n .igv-multi-locus-close-button > svg {\n vertical-align: top; }\n\n.igv-multi-locus-close-button:hover {\n cursor: pointer;\n color: #434343; }\n\n.igv-multi-locus-ruler-label {\n z-index: 64;\n position: absolute;\n top: 2px;\n left: 0;\n width: 100%;\n height: 14px;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: center;\n align-items: center; }\n .igv-multi-locus-ruler-label div {\n font-family: \"Open Sans\", sans-serif;\n font-size: 14px;\n font-weight: 400;\n color: #101010;\n background-color: white; }\n\n.igv-multi-locus-ruler-label-square-dot {\n z-index: 64;\n position: absolute;\n left: 50%;\n top: 5%;\n transform: translate(-50%, 0%);\n background-color: white;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: center; }\n .igv-multi-locus-ruler-label-square-dot > div:first-child {\n width: 14px;\n height: 14px; }\n .igv-multi-locus-ruler-label-square-dot > div:last-child {\n margin-left: 16px;\n font-family: \"Open Sans\", sans-serif;\n font-size: 14px;\n font-weight: 400;\n color: #101010; }\n\n.igv-multi-locus-ruler-label:hover {\n cursor: pointer; }\n\n.igv-ruler-sweeper {\n display: none;\n pointer-events: none;\n position: absolute;\n top: 0;\n left: 0;\n width: 0;\n height: 100%;\n z-index: 99999;\n background-color: rgba(68, 134, 247, 0.25); }\n\n.igv-ruler-tooltip {\n pointer-events: none;\n z-index: 128;\n position: absolute;\n top: 0;\n left: 0;\n width: 1px;\n height: 32px;\n background-color: transparent;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: center; }\n .igv-ruler-tooltip > div {\n pointer-events: none;\n width: 128px;\n height: auto;\n padding: 1px;\n color: #373737;\n font-size: 10px;\n font-family: \"Open Sans\", sans-serif;\n font-weight: 400;\n background-color: white;\n border-style: solid;\n border-width: thin;\n border-color: #373737; }\n\n.igv-track-label {\n position: absolute;\n left: 8px;\n top: 8px;\n width: auto;\n height: auto;\n max-width: 200px;\n padding-left: 4px;\n padding-right: 4px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n font-family: \"Open Sans\", sans-serif;\n font-size: small;\n font-weight: 400;\n text-align: center;\n user-select: none;\n -moz-user-select: none;\n -webkit-user-select: none;\n border-color: #444;\n border-radius: 2px;\n border-style: solid;\n border-width: thin;\n background-color: white;\n z-index: 128;\n cursor: pointer; }\n\n.igv-track-label:hover,\n.igv-track-label:focus,\n.igv-track-label:active {\n background-color: #e8e8e8; }\n\n.igv-center-line {\n display: none;\n pointer-events: none;\n position: absolute;\n top: 0;\n bottom: 0;\n transform: translateX(-50%);\n z-index: 8;\n user-select: none;\n -moz-user-select: none;\n -webkit-user-select: none;\n border-left-style: dashed;\n border-left-width: thin;\n border-right-style: dashed;\n border-right-width: thin; }\n\n.igv-center-line-wide {\n background-color: rgba(0, 0, 0, 0);\n border-left-color: rgba(127, 127, 127, 0.51);\n border-right-color: rgba(127, 127, 127, 0.51); }\n\n.igv-center-line-thin {\n background-color: rgba(0, 0, 0, 0);\n border-left-color: rgba(127, 127, 127, 0.51);\n border-right-color: rgba(0, 0, 0, 0); }\n\n.igv-cursor-guide-horizontal {\n display: none;\n pointer-events: none;\n user-select: none;\n -moz-user-select: none;\n -webkit-user-select: none;\n position: absolute;\n left: 0;\n right: 0;\n top: 50%;\n height: 1px;\n z-index: 1;\n margin-left: 50px;\n margin-right: 54px;\n border-top-style: dotted;\n border-top-width: thin;\n border-top-color: rgba(127, 127, 127, 0.76); }\n\n.igv-cursor-guide-vertical {\n pointer-events: none;\n user-select: none;\n -moz-user-select: none;\n -webkit-user-select: none;\n position: absolute;\n top: 0;\n bottom: 0;\n left: 50%;\n width: 1px;\n z-index: 1;\n border-left-style: dotted;\n border-left-width: thin;\n border-left-color: rgba(127, 127, 127, 0.76);\n display: none; }\n\n.igv-user-feedback {\n position: fixed;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 512px;\n height: 360px;\n z-index: 2048;\n background-color: white;\n border-color: #a2a2a2;\n border-style: solid;\n border-width: thin;\n font-family: \"Open Sans\", sans-serif;\n font-size: medium;\n font-weight: 400;\n color: #444;\n display: flex;\n flex-direction: column;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: center; }\n .igv-user-feedback div:first-child {\n position: relative;\n height: 24px;\n width: 100%;\n background-color: white;\n border-bottom-color: #a2a2a2;\n border-bottom-style: solid;\n border-bottom-width: thin; }\n .igv-user-feedback div:first-child div {\n position: absolute;\n top: 2px;\n width: 16px;\n height: 16px;\n background-color: transparent; }\n .igv-user-feedback div:first-child div:first-child {\n left: 8px; }\n .igv-user-feedback div:first-child div:last-child {\n cursor: pointer;\n right: 8px; }\n .igv-user-feedback div:last-child {\n width: 100%;\n height: calc(100% - 24px);\n border-width: 0; }\n .igv-user-feedback div:last-child div {\n width: auto;\n height: auto;\n margin: 8px; }\n\n.igv-generic-dialog-container {\n position: absolute;\n top: 0;\n left: 0;\n width: 300px;\n height: 200px;\n border-color: #7F7F7F;\n border-radius: 4px;\n border-style: solid;\n border-width: thin;\n font-family: \"Open Sans\", sans-serif;\n font-size: medium;\n font-weight: 400;\n z-index: 2048;\n background-color: white;\n display: flex;\n flex-flow: column;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: center; }\n .igv-generic-dialog-container .igv-generic-dialog-header {\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: flex-end;
67585\n align-items: center;\n width: 100%;\n height: 24px;\n cursor: move;\n border-top-left-radius: 4px;\n border-top-right-radius: 4px;\n border-bottom-color: #7F7F7F;\n border-bottom-style: solid;\n border-bottom-width: thin;\n background-color: #eee; }\n .igv-generic-dialog-container .igv-generic-dialog-header div {\n margin-right: 4px;\n margin-bottom: 2px;\n height: 12px;\n width: 12px;\n color: #7F7F7F; }\n .igv-generic-dialog-container .igv-generic-dialog-header div:hover {\n cursor: pointer;\n color: #444; }\n .igv-generic-dialog-container .igv-generic-dialog-one-liner {\n color: #373737;\n width: 95%;\n height: 24px;\n line-height: 24px;\n text-align: left;\n margin-top: 8px;\n padding-left: 8px;\n overflow-wrap: break-word;\n background-color: white; }\n .igv-generic-dialog-container .igv-generic-dialog-label-input {\n margin-top: 8px;\n width: 95%;\n height: 24px;\n color: #373737;\n line-height: 24px;\n padding-left: 8px;\n background-color: white;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: center; }\n .igv-generic-dialog-container .igv-generic-dialog-label-input div {\n width: 30%;\n height: 100%;\n font-size: 16px;\n text-align: right;\n padding-right: 8px;\n background-color: white; }\n .igv-generic-dialog-container .igv-generic-dialog-label-input input {\n display: block;\n height: 100%;\n width: 100%;\n padding-left: 4px;\n font-family: \"Open Sans\", sans-serif;\n font-weight: 400;\n color: #373737;\n text-align: left;\n outline: none;\n border-style: solid;\n border-width: thin;\n border-color: #7F7F7F;\n background-color: white; }\n .igv-generic-dialog-container .igv-generic-dialog-label-input input {\n width: 50%;\n font-size: 16px; }\n .igv-generic-dialog-container .igv-generic-dialog-input {\n margin-top: 8px;\n width: calc(100% - 16px);\n height: 24px;\n color: #373737;\n line-height: 24px;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: space-around;\n align-items: center; }\n .igv-generic-dialog-container .igv-generic-dialog-input input {\n display: block;\n height: 100%;\n width: 100%;\n padding-left: 4px;\n font-family: \"Open Sans\", sans-serif;\n font-weight: 400;\n color: #373737;\n text-align: left;\n outline: none;\n border-style: solid;\n border-width: thin;\n border-color: #7F7F7F;\n background-color: white; }\n .igv-generic-dialog-container .igv-generic-dialog-input input {\n font-size: 16px; }\n .igv-generic-dialog-container .igv-generic-dialog-ok-cancel {\n width: 100%;\n height: 28px;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: space-around;\n align-items: center; }\n .igv-generic-dialog-container .igv-generic-dialog-ok-cancel div {\n margin-top: 32px;\n color: white;\n font-family: \"Open Sans\", sans-serif;\n font-size: 14px;\n font-weight: 400;\n width: 75px;\n height: 28px;\n line-height: 28px;\n text-align: center;\n border-color: transparent;\n border-style: solid;\n border-width: thin;\n border-radius: 2px; }\n .igv-generic-dialog-container .igv-generic-dialog-ok-cancel div:first-child {\n margin-left: 32px;\n margin-right: 0;\n background-color: #5ea4e0; }\n .igv-generic-dialog-container .igv-generic-dialog-ok-cancel div:last-child {\n margin-left: 0;\n margin-right: 32px;\n background-color: #c4c4c4; }\n .igv-generic-dialog-container .igv-generic-dialog-ok-cancel div:first-child:hover {\n cursor: pointer;\n background-color: #3b5c7f; }\n .igv-generic-dialog-container .igv-generic-dialog-ok-cancel div:last-child:hover {\n cursor: pointer;\n background-color: #7f7f7f; }\n .igv-generic-dialog-container .igv-generic-dialog-ok {\n width: 100%;\n height: 36px;\n margin-top: 32px;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: space-around;
67585\n align-items: center; }\n .igv-generic-dialog-container .igv-generic-dialog-ok div {\n width: 98px;\n height: 36px;\n line-height: 36px;\n text-align: center;\n color: white;\n font-family: \"Open Sans\", sans-serif;\n font-size: medium;\n font-weight: 400;\n border-color: white;\n border-style: solid;\n border-width: thin;\n border-radius: 4px;\n background-color: #2B81AF; }\n .igv-generic-dialog-container .igv-generic-dialog-ok div:hover {\n cursor: pointer;\n background-color: #25597f; }\n\n.igv-generic-container {\n position: absolute;\n top: 0;\n left: 0;\n z-index: 2048;\n background-color: white;\n cursor: pointer;\n display: flex;\n flex-direction: row;\n flex-wrap: wrap;\n justify-content: flex-start;\n align-items: center; }\n .igv-generic-container div:first-child {\n cursor: move;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: flex-end;\n align-items: center;\n height: 24px;\n width: 100%;\n background-color: #dddddd; }\n .igv-generic-container div:first-child i {\n display: block;\n color: #5f5f5f;\n cursor: pointer;\n width: 14px;\n height: 14px;\n margin-right: 8px;\n margin-bottom: 4px; }\n\n.igv-menu-popup {\n position: absolute;\n top: 0;\n left: 0;\n width: max-content;\n z-index: 4096;\n cursor: pointer;\n font-family: \"Open Sans\", sans-serif;\n font-size: small;\n font-weight: 400;\n color: #4b4b4b;\n background: white;\n border-radius: 4px;\n border-color: #7F7F7F;\n border-style: solid;\n border-width: thin;\n display: flex;\n flex-flow: column;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: flex-end;\n text-align: left; }\n .igv-menu-popup > div:not(:first-child) {\n width: 100%; }\n .igv-menu-popup > div:not(:first-child) > div {\n background: white; }\n .igv-menu-popup > div:not(:first-child) > div.context-menu {\n padding-left: 4px;\n padding-right: 4px; }\n .igv-menu-popup > div:not(:first-child) > div:last-child {\n border-bottom-left-radius: 4px;\n border-bottom-right-radius: 4px;\n border-bottom-color: transparent;\n border-bottom-style: solid;\n border-bottom-width: thin; }\n .igv-menu-popup > div:not(:first-child) > div:hover {\n background: #efefef; }\n\n.igv-menu-popup-shim {\n padding-left: 8px;\n padding-right: 8px; }\n\n.igv-menu-popup-header {\n position: relative;\n width: 100%;\n height: 24px;\n cursor: move;\n border-top-color: transparent;\n border-top-left-radius: 4px;\n border-top-right-radius: 4px;\n border-bottom-color: #7F7F7F;\n border-bottom-style: solid;\n border-bottom-width: thin;\n background-color: #eee;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: flex-end;\n align-items: center; }\n .igv-menu-popup-header div {\n margin-right: 4px;\n height: 12px;\n width: 12px;\n color: #7F7F7F; }\n .igv-menu-popup-header div:hover {\n cursor: pointer;\n color: #444; }\n\n.igv-menu-popup-check-container {\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: center;\n width: 100%;\n height: 20px;\n background-color: transparent; }\n .igv-menu-popup-check-container div {\n padding-top: 2px;\n padding-left: 8px; }\n .igv-menu-popup-check-container div:first-child {\n position: relative;\n width: 12px;\n height: 12px; }\n .igv-menu-popup-check-container div:first-child svg {\n position: absolute;\n width: 12px;\n height: 12px; }\n\n.igv-user-feedback {\n position: fixed;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 512px;\n height: 360px;\n z-index: 2048;\n background-color: white;\n border-color: #a2a2a2;\n border-style: solid;\n border-width: thin;\n font-family: \"Open Sans\", sans-serif;\n font-size: medium;\n font-weight: 400;\n color: #444;\n display: flex;\n flex-direction: column;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: center; }\n .igv-user-feedback div:first-child {\n position: relative;\n height: 24px;\n width: 100%;\n background-color: white;\n border-bottom-color: #a2a2a2;\n border-bottom-style: solid;\n border-bottom-width: thin; }\n .igv-user-feedback div:first-child div {\n position: absolute;\n top: 2px;\n width: 16px;\n height: 16px;\n background-color: transparent; }\n .igv-user-feedback div:first-child div:first-child {\n left: 8px; }\n .igv-user-feedback div:first-child div:last-child {\n cursor: pointer;\n right: 8px; }\n .igv-user-feedback div:last-child {\n width: 100%;\n height: calc(100% - 24px);\n border-width: 0; }\n .igv-user-feedback div:last-child div {\n width: auto;\n height: auto;\n margin: 8px; }\n\n.igv-loading-spinner-container {\n z-index: 1024;\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 32px;\n height: 32px;\n display: flex;\n flex-direction: row;\n flex-wrap: nowrap;\n justify-content: center;\n align-items: center; }\n .igv-loading-spinner-container > div {\n box-sizing: border-box;\n width: 100%;\n height: 100%;\n border-radius: 50%;\n border: 4px solid rgba(128, 128, 128, 0.5);\n border-top-color: white;\n animation: spin 1s ease-in-out infinite;\n -webkit-animation: spin 1s ease-in-out infinite; }\n\n@keyframes spin {\n to {\n -webkit-transform: rotate(360deg);\n transform: rotate(360deg); } }\n@-webkit-keyframes spin {\n to {\n -webkit-transform: rotate(360deg);\n transform: rotate(360deg); } }\n.igv-container {\n position: relative;\n display: flex;\n flex-direction: column;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: flex-start;\n padding-top: 4px;\n user-select: none;\n -webkit-user-select: none;\n -ms-user-select: none; }\n\n.igv-viewport {\n position: relative;\n margin-top: 5px;\n overflow-x: hidden;\n overflow-y: hidden; }\n\n.igv-viewport-content {\n position: relative;\n width: 100%; }\n .igv-viewport-content > canvas {\n position: relative;\n display: block; }\n\n.igv-column-container {\n position: relative;\n display: flex;\n flex-direction: row;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: stretch;\n width: 100%; }\n\n.igv-column-shim {\n width: 1px;\n margin-left: 2px;\n margin-right: 2px;\n background-color: #545453; }\n\n.igv-column {\n position: relative;\n display: flex;\n flex-direction: column;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: flex-start;\n box-sizing: border-box;\n height: 100%; }\n\n.igv-axis-column {\n display: flex;\n flex-direction: column;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: flex-start;\n box-sizing: border-box;\n height: 100%;\n width: 50px; }\n .igv-axis-column > div {\n margin-top: 5px;\n width: 100%; }\n\n.igv-sample-name-column {\n display: flex;\n flex-direction: column;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: flex-start;\n box-sizing: border-box;\n height: 100%; }\n\n.igv-scrollbar-column {\n display: flex;\n flex-direction: column;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: flex-start;\n box-sizing: border-box;\n height: 100%;\n width: 14px; }\n .igv-scrollbar-column > div {\n position: relative;\n margin-top: 5px;\n width: 14px; }\n .igv-scrollbar-column > div > div {\n cursor: pointer;\n position: absolute;\n top: 0;\n left: 2px;\n width: 8px;\n border-width: 1px;\n border-style: solid;\n border-color: #c4c4c4;\n border-top-left-radius: 4px;\n border-top-right-radius: 4px;\n border-bottom-left-radius: 4px;\n border-bottom-right-radius: 4px; }\n .igv-scrollbar-column > div > div:hover {\n background-color: #c4c4c4; }\n\n.igv-track-drag-column {\n display: flex;\n flex-direction: column;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: flex-start;\n box-sizing: border-box;\n height: 100%;\n width: 12px;\n background-color: white; }\n .igv-track-drag-column > .igv-track-drag-handle {\n z-index: 512;\n position: relative;\n cursor: pointer;\n margin-top: 5px;\n width: 100%;\n border-style: solid;\n border-width: 0;\n border-top-right-radius: 6px;\n border-bottom-right-radius: 6px;\n background-color: #c4c4c4; }\n .igv-track-drag-column .igv-track-drag-handle-hover {\n background-color: #787878; }\n .igv-track-drag-column > .igv-track-drag-shim {\n position: relative;\n margin-top: 5px;\n width: 100%;\n border-style: solid;\n border-width: 0; }\n\n.igv-gear-menu-column {\n display: flex;\n flex-direction: column;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: flex-start;\n box-sizing: border-box;\n height: 100%;\n width: 28px; }\n .igv-gear-menu-column > div {\n display: flex;\n flex-direction: column;\n flex-wrap: nowrap;\n justify-content: flex-start;
67585\n align-items: center;\n margin-top: 5px;\n width: 100%;\n background: white; }\n .igv-gear-menu-column > div > div {\n position: relative;\n margin-top: 4px;\n width: 16px;\n height: 16px;\n color: #7F7F7F; }\n .igv-gear-menu-column > div > div:hover {\n cursor: pointer;\n color: #444; }\n\n/*# sourceMappingURL=dom.css.map */\n'; 67586 var style = document.createElement('style'); 67587 style.setAttribute('type', 'text/css'); 67588 style.innerHTML = css; 67589 document.head.insertBefore(style, document.head.childNodes[document.head.childNodes.length - 1]); 67590 } 67591 67592 // Defines the top-level API for the igv module 67593 const setApiKey = igvxhr.setApiKey; 67594 embedCSS(); 67595 67596 function setGoogleOauthToken(accessToken) { 67597 return oauth.setToken(accessToken); 67598 } 67599 67600 function setOauthToken(accessToken, host) { 67601 return oauth.setToken(accessToken, host); 67602 } 67603 67604 var index = { 67605 IGVGraphics, 67606 MenuUtils, 67607 DataRangeDialog, 67608 createTrack, 67609 createBrowser, 67610 removeBrowser, 67611 removeAllBrowsers, 67612 visibilityChange, 67613 setGoogleOauthToken, 67614 setOauthToken, 67615 oauth, 67616 version: version$1, 67617 setApiKey, 67618 doAutoscale, 67619 TrackView 67620 }; 67621 67622 return index; 67623 67624}));</script>
67624 67625 <div id="myDiv" style="padding-top: 50px;padding-bottom: 20px; height: auto"> 67626</div> 67627
67628<script type="module"> 67629 67630 document.addEventListener("DOMContentLoaded", function () { 67631 var div = document.getElementById("myDiv"); 67632 var options = { 67633 reference: { 67634 id: "ce11", 67635 fastaURL: "//storage.googleapis.com/elegansvariation.org/browser_tracks/c_elegans.PRJNA13758.WS245.genomic.fa" 67636 }, 67637 locus: "II:6710150-6712932", 67638 showNavigation: true, 67639 showKaryo: false, 67640 tracks: [ 67641 { 67642 name: "Genes", 67643 displayMode: "EXPANDED", 67644 order: 2, 67645 url: "https://s3.eu-central-1.amazonaws.com/wormbuilder.dev/tracks/wormTracks/Genes_WS282.bed", 67646 indexed: false, 67647 searchable: true, 67648 visibilityWindow: 250000, 67649 color: "#2471A3", 67650 altColor: "#C0392B" 67651 }, 67652 { 67653 name: "Alphafold confidence score", 67654 order: 1, 67655 type: "wig", 67656 format: "bigWig", 67657 url: "https://s3.eu-central-1.amazonaws.com/wormbuilder.dev/tracks/wormTracks/AF_confidence.bigwig", 67658 visibilityWindow: 5000, 67659 min: 0, 67660 max: 100 67661 }, 67662 { 67663 name: "Transcripts", 67664 displayMode: "EXPANDED", 67665 order: 3, 67666 url: "//s3.eu-central-1.amazonaws.com/wormbuilder.dev/tracks/wormTracks/c_elegans.WS282.WormBase.gff3", 67667 indexURL: "https://s3.eu-central-1.amazonaws.com/wormbuilder.dev/tracks/wormTracks/c_elegans.WS282.WormBase.gff3.idx", 67668 searchable: true, 67669 visibilityWindow: 250000, 67670 height: 200, 67671 color: "#2471A3", 67672 altColor: "#C0392B" 67673 }, 67674 { 67675 name: "Library", 67676 order: 4, 67677 url: "https://s3.eu-central-1.amazonaws.com/wormbuilder.dev/tracks/wormTracks/crRNAlib.v4.bed", 67678 indexURL: "https://s3.eu-central-1.amazonaws.com/wormbuilder.dev/tracks/wormTracks/crRNAlib.v4.bed.idx", 67679 displayMode: "SQUISHED", 67680 visibilityWindow: 100000, 67681 autoHeight: true, 67682 searchable: false 67683 } 67684 ] 67685 }; 67686 67687 igv.createBrowser(div, options) 67688 67689 .then(function (browser) { 67690 67691 67692 browser.on('trackclick', function (track, popoverData) { 67693 var symbol = null; 67694 popoverData.forEach(function (nameValue) { 67695 if (nameValue.name && nameValue.name.toLowerCase() === 'name') { 67696 symbol = nameValue.value; 67697 Shiny.onInputChange("jsValue", symbol); 67698 } 67699 }); 67700 67701 // Prevent default pop-over behavior 67702 return false; 67703 67704 67705 }); 67706 67707 // Function to keep track of where the user is 67708 //browser.on('locuschange', function (referenceFrame) { 67709 // Shiny.onInputChange("locationIGV", referenceFrame.label); 67710 //Shiny.onInputChange("locationIGV", 'Hola'); 67711 //}); 67712 67713 browser.on('locuschange', function (referenceFrameList) { 67714 let loc = referenceFrameList.map(rf => rf.getLocusString()).join('%20'); 67715 Shiny.onInputChange("locationIGV", loc); 67716 }); 67717 67718 }); 67719 67720 }); 67721</script>
67721 67722 <hr/> 67723
67723<script> 67724 Shiny.addCustomMessageHandler('gene-coordinates', function(coordinates) { 67725 igv.browser.search(coordinates); 67726 }); 67727 </script>
67727 67728 <div id="genebrowsearch" class="shiny-html-output"></div> 67729 <pre id="igv_id" class="shiny-text-output noplaceholder"></pre> 67730 <pre id="ErrorMessageBrowser" class="shiny-text-output noplaceholder"></pre> 67731 <pre id="SimpleFragmentBrowser" class="shiny-text-output noplaceholder"></pre> 67732 <button id="userigvlocation" type="button" class="btn btn-default action-button">Display guide sequences seen in browser</button> 67733 <button id="userigvbasket" type="button" class="btn btn-default action-button">Send guide sequences seen in browser to basket</button> 67734 <hr/> 67735 <div id="SelPiTabBrowser" style="width:100%; height:auto; " class="datatables html-widget html-widget-output"></div> 67736 </div> 67737 </div> 67738 <div class="tab-pane" data-value="Basket" id="tab-3862-3"> 67739 <div class="row"> 67740 <h3>Download oligos in bulk</h3> 67741 <div id="BigBasket" style="width:100%; height:auto; " class="datatables html-widget html-widget-output"></div> 67742 <div id="DownloadBasket" class="shiny-html-output"></div> 67743 </div> 67744 </div> 67745 <div class="tab-pane" data-value="Downloads" id="tab-3862-4"> 67746 <div class="row"> 67747 <h3>Tracks</h3> 67748 <br>Bed track with protospacers (ce11/WS282) 67749 <p align="justify"> 67750 <a href="https://s3.eu-central-1.amazonaws.com/wormbuilder.dev/tracks/wormTracks/crRNAlib.v4.bed">Download (45.5 MB)</a><br></p> 67751 <br>BigWig track with AlphaFold confidence scores (ce11/WS282) 67752 <p align="justify"> 67753 <a href="https://s3.eu-central-1.amazonaws.com/wormbuilder.dev/tracks/wormTracks/AF_confidence.bigwig">Download (145 MB)</a><br></p> 67754 </div> 67755 </div> 67756 <div class="tab-pane" data-value="About" id="tab-3862-5"> 67757 <div class="row"> 67758 <h3><i>C. elegans</i> CRISPR-Cas9 library DB</h3> 67759 <p align="justify"> 67760 This website is generated via custom modified css/html code running in R via the shiny library. 67761 <br>All the templates, libraries, and programs used to produce this site are under the MIT and GNU licenses. 67762 <br>The R scripts and files to render this site can be found <a href="https://github.com/AmhedVargas/CRISPR_library_track">here</a></p> 67763 This website was designed by <a href="https://scholar.google.com/citations?user=WokAqF8AAAAJ&hl=en&authuser=1">Mohammed Al-Johani</a> (<a href="https://www.linkedin.com/in/mohammedaljohani/">LinkedIn</a>), <a href="https://www.researchgate.net/profile/Amhed_Vargas_Velazquez">Amhed Missael Vargas Velazquez</a> (<a href="https://github.com/AmhedVargas">Github</a>), and 67764 <a href="https://www.kaust.edu.sa/en/study/faculty/christian-jensen">Christian Froekjaer-Jensen</a> from the Laboratory of Synthetic Genome Biology<br> 67765 <h3>The Laboratory of Synthetic Genome Biology</h3> 67766 <p align="justify"> 67767 The Laboratory of Synthetic Genome Biology is located in building 2 - level 3 (Ibn Al-Haytham â Above Spine) at King Abdullah University of Science and Technology (KAUST). 67768 <br><i>Contact info</i>:<br>Christian-Froekjaer Jensen, Ph.D. 67769 <br>Associate Professor of Bioscience 67770 <br><a href="https://wormbuilder.org/laboratory-of-synthetic-genome-biology/">Laboratory of Synthetic Genome Biology</a> 67771 <br>Email: <a href="mailto:[email protected]">[email protected]</a> 67772 </p> 67773 </div> 67774 </div> 67775 </div> 67776 </div> 67777 <hr/> 67778 <a href="https://www.kaust.edu.sa/en/study/faculty/christian-jensen">Froekjaer-Jensen Lab @KAUST</a><br> 67779 <a href="http://www.wormbuilder.org/">Wormbuilder</a><br> 67780 <a href="mailto:[email protected]">Contact us!</a> 67781 </div> 67782</body> 67783</html>
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.