{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "## Example of loading a map and track from local files.\n", "\n", "**Note: To use update the 2 \"url\" fields to local file paths**" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "pip install git+https://github.com/igvteam/juicebox-notebook.git" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Load a map and track in the intial config" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'/Users/dat/JuiceboxDevelopment/juicebox-notebook/examples'" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pwd" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "pycharm": { "name": "#%%\n" } }, "outputs": [ { "data": { "application/javascript": [ "\n", " const link = document.createElement(\"link\")\n", " link.type = \"text/css\"\n", " link.rel = \"stylesheet\"\n", " link.href = \"https://cdn.jsdelivr.net/npm/juicebox.js@2.2.0/dist/css/juicebox.css\"\n", " document.getElementsByTagName(\"head\")[0].appendChild(link)\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", " const link = document.createElement(\"link\")\n", " link.type = \"text/css\"\n", " link.rel = \"stylesheet\"\n", " link.href = \"https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css\"\n", " document.getElementsByTagName(\"head\")[0].appendChild(link)\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "(function (global, factory) {window.juicebox = factory()}) (this, (function () { 'use strict';\n", "\n", " function div$1(options) {\n", " return create$1(\"div\", options);\n", " }\n", "\n", " function create$1(tag, options) {\n", " const elem = document.createElement(tag);\n", "\n", " if (options) {\n", " if (options.class) {\n", " elem.classList.add(options.class);\n", " }\n", "\n", " if (options.id) {\n", " elem.id = options.id;\n", " }\n", "\n", " if (options.style) {\n", " applyStyle$1(elem, options.style);\n", " }\n", " }\n", "\n", " return elem;\n", " }\n", "\n", " function hide$1(elem) {\n", " const cssStyle = getComputedStyle(elem);\n", "\n", " if (cssStyle.display !== \"none\") {\n", " elem._initialDisplay = cssStyle.display;\n", " }\n", "\n", " elem.style.display = \"none\";\n", " }\n", "\n", " function offset$1(elem) {\n", " // Return zeros for disconnected and hidden (display: none) elements (gh-2310)\n", " // Support: IE <=11 only\n", " // Running getBoundingClientRect on a\n", " // disconnected node in IE throws an error\n", " if (!elem.getClientRects().length) {\n", " return {\n", " top: 0,\n", " left: 0\n", " };\n", " } // Get document-relative position by adding viewport scroll to viewport-relative gBCR\n", "\n", "\n", " const rect = elem.getBoundingClientRect();\n", " const win = elem.ownerDocument.defaultView;\n", " return {\n", " top: rect.top + win.pageYOffset,\n", " left: rect.left + win.pageXOffset\n", " };\n", " }\n", "\n", " function applyStyle$1(elem, style) {\n", " for (let key of Object.keys(style)) {\n", " elem.style[key] = style[key];\n", " }\n", " }\n", "\n", " function guid() {\n", " return (\"0000\" + (Math.random() * Math.pow(36, 4) << 0).toString(36)).slice(-4);\n", " }\n", "\n", " let getMouseXY = (domElement, {\n", " clientX,\n", " clientY\n", " }) => {\n", " // DOMRect object with eight properties: left, top, right, bottom, x, y, width, height\n", " const {\n", " left,\n", " top,\n", " width,\n", " height\n", " } = domElement.getBoundingClientRect();\n", " const x = clientX - left;\n", " const y = clientY - top;\n", " return {\n", " x,\n", " y,\n", " xNormalized: x / width,\n", " yNormalized: y / height,\n", " width,\n", " height\n", " };\n", " };\n", " /**\n", " * Translate the mouse coordinates for the event to the coordinates for the given target element\n", " * @param event\n", " * @param domElement\n", " * @returns {{x: number, y: number}}\n", " */\n", "\n", "\n", " function translateMouseCoordinates(event, domElement) {\n", " const {\n", " clientX,\n", " clientY\n", " } = event;\n", " return getMouseXY(domElement, {\n", " clientX,\n", " clientY\n", " });\n", " }\n", "\n", " function createCheckbox$1(name, initialState) {\n", " const container = div$1({\n", " class: 'igv-ui-trackgear-popover-check-container'\n", " });\n", " const svg = iconMarkup$2('check', true === initialState ? '#444' : 'transparent');\n", " svg.style.borderColor = 'gray';\n", " svg.style.borderWidth = '1px';\n", " svg.style.borderStyle = 'solid';\n", " container.appendChild(svg);\n", " let label = div$1(); //{ class: 'igv-some-label-class' });\n", "\n", " label.textContent = name;\n", " container.appendChild(label);\n", " return container;\n", " }\n", "\n", " function createIcon$2(name, color) {\n", " return iconMarkup$2(name, color);\n", " }\n", "\n", " function iconMarkup$2(name, color) {\n", " color = color || \"currentColor\";\n", " let icon = icons$2[name];\n", "\n", " if (!icon) {\n", " console.error(`No icon named: ${name}`);\n", " icon = icons$2[\"question\"];\n", " }\n", "\n", " const svg = document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\");\n", " svg.setAttributeNS(null, 'viewBox', '0 0 ' + icon[0] + ' ' + icon[1]);\n", " const path = document.createElementNS(\"http://www.w3.org/2000/svg\", \"path\");\n", " path.setAttributeNS(null, 'fill', color);\n", " path.setAttributeNS(null, 'd', icon[4]);\n", " svg.appendChild(path);\n", " return svg;\n", " }\n", "\n", " const icons$2 = {\n", " \"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\"],\n", " \"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\"],\n", " \"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\"],\n", " \"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-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\"],\n", " \"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\"],\n", " \"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\"],\n", " \"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\"],\n", " \"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\"],\n", " \"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\"],\n", " \"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\"],\n", " \"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\"],\n", " \"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\"],\n", " \"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\"],\n", " \"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\"],\n", " \"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\"],\n", " \"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\"],\n", " \"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\"],\n", " \"square-full\": [512, 512, [], \"f45c\", \"M512 512H0V0h512v512z\"],\n", " \"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\"],\n", " \"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\"],\n", " \"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\"]\n", " };\n", "\n", " function attachDialogCloseHandlerWithParent$1(parent, closeHandler) {\n", " var container = document.createElement(\"div\");\n", " parent.appendChild(container);\n", " container.appendChild(createIcon$2(\"times\"));\n", " container.addEventListener('click', function (e) {\n", " e.preventDefault();\n", " e.stopPropagation();\n", " closeHandler();\n", " });\n", " }\n", "\n", " /**\n", " * @fileoverview Zlib namespace. Zlib の仕様に準拠した圧縮は Zlib.Deflate で実装\n", " * されている. これは Inflate との共存を考慮している為.\n", " */\n", " const ZLIB_STREAM_RAW_INFLATE_BUFFER_SIZE$2 = 65000;\n", " var Zlib$2 = {\n", " Huffman: {},\n", " Util: {},\n", " CRC32: {}\n", " };\n", " /**\n", " * Compression Method\n", " * @enum {number}\n", " */\n", "\n", " Zlib$2.CompressionMethod = {\n", " DEFLATE: 8,\n", " RESERVED: 15\n", " };\n", " /**\n", " * @param {Object=} opt_params options.\n", " * @constructor\n", " */\n", "\n", " Zlib$2.Zip = function (opt_params) {\n", " opt_params = opt_params || {};\n", " /** @type {Array.<{\n", " * buffer: !(Array.|Uint8Array),\n", " * option: Object,\n", " * compressed: boolean,\n", " * encrypted: boolean,\n", " * size: number,\n", " * crc32: number\n", " * }>} */\n", "\n", " this.files = [];\n", " /** @type {(Array.|Uint8Array)} */\n", "\n", " this.comment = opt_params['comment'];\n", " /** @type {(Array.|Uint8Array)} */\n", "\n", " this.password;\n", " };\n", " /**\n", " * @enum {number}\n", " */\n", "\n", "\n", " Zlib$2.Zip.CompressionMethod = {\n", " STORE: 0,\n", " DEFLATE: 8\n", " };\n", " /**\n", " * @enum {number}\n", " */\n", "\n", " Zlib$2.Zip.OperatingSystem = {\n", " MSDOS: 0,\n", " UNIX: 3,\n", " MACINTOSH: 7\n", " };\n", " /**\n", " * @enum {number}\n", " */\n", "\n", " Zlib$2.Zip.Flags = {\n", " ENCRYPT: 0x0001,\n", " DESCRIPTOR: 0x0008,\n", " UTF8: 0x0800\n", " };\n", " /**\n", " * @type {Array.}\n", " * @const\n", " */\n", "\n", " Zlib$2.Zip.FileHeaderSignature = [0x50, 0x4b, 0x01, 0x02];\n", " /**\n", " * @type {Array.}\n", " * @const\n", " */\n", "\n", " Zlib$2.Zip.LocalFileHeaderSignature = [0x50, 0x4b, 0x03, 0x04];\n", " /**\n", " * @type {Array.}\n", " * @const\n", " */\n", "\n", " Zlib$2.Zip.CentralDirectorySignature = [0x50, 0x4b, 0x05, 0x06];\n", " /**\n", " * @param {Array.|Uint8Array} input\n", " * @param {Object=} opt_params options.\n", " */\n", "\n", " Zlib$2.Zip.prototype.addFile = function (input, opt_params) {\n", " opt_params = opt_params || {};\n", " /** @type {string} */\n", "\n", " opt_params['filename'];\n", " /** @type {boolean} */\n", "\n", " var compressed;\n", " /** @type {number} */\n", "\n", " var size = input.length;\n", " /** @type {number} */\n", "\n", " var crc32 = 0;\n", "\n", " if (input instanceof Array) {\n", " input = new Uint8Array(input);\n", " } // default\n", "\n", "\n", " if (typeof opt_params['compressionMethod'] !== 'number') {\n", " opt_params['compressionMethod'] = Zlib$2.Zip.CompressionMethod.DEFLATE;\n", " } // その場で圧縮する場合\n", "\n", "\n", " if (opt_params['compress']) {\n", " switch (opt_params['compressionMethod']) {\n", " case Zlib$2.Zip.CompressionMethod.STORE:\n", " break;\n", "\n", " case Zlib$2.Zip.CompressionMethod.DEFLATE:\n", " crc32 = Zlib$2.CRC32.calc(input);\n", " input = this.deflateWithOption(input, opt_params);\n", " compressed = true;\n", " break;\n", "\n", " default:\n", " throw new Error('unknown compression method:' + opt_params['compressionMethod']);\n", " }\n", " }\n", "\n", " this.files.push({\n", " buffer: input,\n", " option: opt_params,\n", " compressed: compressed,\n", " encrypted: false,\n", " size: size,\n", " crc32: crc32\n", " });\n", " };\n", " /**\n", " * @param {(Array.|Uint8Array)} password\n", " */\n", "\n", "\n", " Zlib$2.Zip.prototype.setPassword = function (password) {\n", " this.password = password;\n", " };\n", "\n", " Zlib$2.Zip.prototype.compress = function () {\n", " /** @type {Array.<{\n", " * buffer: !(Array.|Uint8Array),\n", " * option: Object,\n", " * compressed: boolean,\n", " * encrypted: boolean,\n", " * size: number,\n", " * crc32: number\n", " * }>} */\n", " var files = this.files;\n", " /** @type {{\n", " * buffer: !(Array.|Uint8Array),\n", " * option: Object,\n", " * compressed: boolean,\n", " * encrypted: boolean,\n", " * size: number,\n", " * crc32: number\n", " * }} */\n", "\n", " var file;\n", " /** @type {!(Array.|Uint8Array)} */\n", "\n", " var output;\n", " /** @type {number} */\n", "\n", " var op1;\n", " /** @type {number} */\n", "\n", " var op2;\n", " /** @type {number} */\n", "\n", " var op3;\n", " /** @type {number} */\n", "\n", " var localFileSize = 0;\n", " /** @type {number} */\n", "\n", " var centralDirectorySize = 0;\n", " /** @type {number} */\n", "\n", " var endOfCentralDirectorySize;\n", " /** @type {number} */\n", "\n", " var offset;\n", " /** @type {number} */\n", "\n", " var needVersion;\n", " /** @type {number} */\n", "\n", " var flags;\n", " /** @type {Zlib.Zip.CompressionMethod} */\n", "\n", " var compressionMethod;\n", " /** @type {Date} */\n", "\n", " var date;\n", " /** @type {number} */\n", "\n", " var crc32;\n", " /** @type {number} */\n", "\n", " var size;\n", " /** @type {number} */\n", "\n", " var plainSize;\n", " /** @type {number} */\n", "\n", " var filenameLength;\n", " /** @type {number} */\n", "\n", " var extraFieldLength;\n", " /** @type {number} */\n", "\n", " var commentLength;\n", " /** @type {(Array.|Uint8Array)} */\n", "\n", " var filename;\n", " /** @type {(Array.|Uint8Array)} */\n", "\n", " var extraField;\n", " /** @type {(Array.|Uint8Array)} */\n", "\n", " var comment;\n", " /** @type {(Array.|Uint8Array)} */\n", "\n", " var buffer;\n", " /** @type {*} */\n", "\n", " var tmp;\n", " /** @type {Array.|Uint32Array|Object} */\n", "\n", " var key;\n", " /** @type {number} */\n", "\n", " var i;\n", " /** @type {number} */\n", "\n", " var il;\n", " /** @type {number} */\n", "\n", " var j;\n", " /** @type {number} */\n", "\n", " var jl; // ファイルの圧縮\n", "\n", " for (i = 0, il = files.length; i < il; ++i) {\n", " file = files[i];\n", " filenameLength = file.option['filename'] ? file.option['filename'].length : 0;\n", " extraFieldLength = file.option['extraField'] ? file.option['extraField'].length : 0;\n", " commentLength = file.option['comment'] ? file.option['comment'].length : 0; // 圧縮されていなかったら圧縮\n", "\n", " if (!file.compressed) {\n", " // 圧縮前に CRC32 の計算をしておく\n", " file.crc32 = Zlib$2.CRC32.calc(file.buffer);\n", "\n", " switch (file.option['compressionMethod']) {\n", " case Zlib$2.Zip.CompressionMethod.STORE:\n", " break;\n", "\n", " case Zlib$2.Zip.CompressionMethod.DEFLATE:\n", " file.buffer = this.deflateWithOption(file.buffer, file.option);\n", " file.compressed = true;\n", " break;\n", "\n", " default:\n", " throw new Error('unknown compression method:' + file.option['compressionMethod']);\n", " }\n", " } // encryption\n", "\n", "\n", " if (file.option['password'] !== void 0 || this.password !== void 0) {\n", " // init encryption\n", " key = this.createEncryptionKey(file.option['password'] || this.password); // add header\n", "\n", " buffer = file.buffer;\n", "\n", " {\n", " tmp = new Uint8Array(buffer.length + 12);\n", " tmp.set(buffer, 12);\n", " buffer = tmp;\n", " }\n", "\n", " for (j = 0; j < 12; ++j) {\n", " buffer[j] = this.encode(key, i === 11 ? file.crc32 & 0xff : Math.random() * 256 | 0);\n", " } // data encryption\n", "\n", "\n", " for (jl = buffer.length; j < jl; ++j) {\n", " buffer[j] = this.encode(key, buffer[j]);\n", " }\n", "\n", " file.buffer = buffer;\n", " } // 必要バッファサイズの計算\n", "\n", "\n", " localFileSize += // local file header\n", " 30 + filenameLength + // file data\n", " file.buffer.length;\n", " centralDirectorySize += // file header\n", " 46 + filenameLength + commentLength;\n", " } // end of central directory\n", "\n", "\n", " endOfCentralDirectorySize = 22 + (this.comment ? this.comment.length : 0);\n", " output = new (Uint8Array )(localFileSize + centralDirectorySize + endOfCentralDirectorySize);\n", " op1 = 0;\n", " op2 = localFileSize;\n", " op3 = op2 + centralDirectorySize; // ファイルの圧縮\n", "\n", " for (i = 0, il = files.length; i < il; ++i) {\n", " file = files[i];\n", " filenameLength = file.option['filename'] ? file.option['filename'].length : 0;\n", " extraFieldLength = 0; // TODO\n", "\n", " commentLength = file.option['comment'] ? file.option['comment'].length : 0; //-------------------------------------------------------------------------\n", " // local file header & file header\n", " //-------------------------------------------------------------------------\n", "\n", " offset = op1; // signature\n", " // local file header\n", "\n", " output[op1++] = Zlib$2.Zip.LocalFileHeaderSignature[0];\n", " output[op1++] = Zlib$2.Zip.LocalFileHeaderSignature[1];\n", " output[op1++] = Zlib$2.Zip.LocalFileHeaderSignature[2];\n", " output[op1++] = Zlib$2.Zip.LocalFileHeaderSignature[3]; // file header\n", "\n", " output[op2++] = Zlib$2.Zip.FileHeaderSignature[0];\n", " output[op2++] = Zlib$2.Zip.FileHeaderSignature[1];\n", " output[op2++] = Zlib$2.Zip.FileHeaderSignature[2];\n", " output[op2++] = Zlib$2.Zip.FileHeaderSignature[3]; // compressor info\n", "\n", " needVersion = 20;\n", " output[op2++] = needVersion & 0xff;\n", " output[op2++] =\n", " /** @type {Zlib.Zip.OperatingSystem} */\n", " file.option['os'] || Zlib$2.Zip.OperatingSystem.MSDOS; // need version\n", "\n", " output[op1++] = output[op2++] = needVersion & 0xff;\n", " output[op1++] = output[op2++] = needVersion >> 8 & 0xff; // general purpose bit flag\n", "\n", " flags = 0;\n", "\n", " if (file.option['password'] || this.password) {\n", " flags |= Zlib$2.Zip.Flags.ENCRYPT;\n", " }\n", "\n", " output[op1++] = output[op2++] = flags & 0xff;\n", " output[op1++] = output[op2++] = flags >> 8 & 0xff; // compression method\n", "\n", " compressionMethod =\n", " /** @type {Zlib.Zip.CompressionMethod} */\n", " file.option['compressionMethod'];\n", " output[op1++] = output[op2++] = compressionMethod & 0xff;\n", " output[op1++] = output[op2++] = compressionMethod >> 8 & 0xff; // date\n", "\n", " date =\n", " /** @type {(Date|undefined)} */\n", " file.option['date'] || new Date();\n", " output[op1++] = output[op2++] = (date.getMinutes() & 0x7) << 5 | (date.getSeconds() / 2 | 0);\n", " output[op1++] = output[op2++] = date.getHours() << 3 | date.getMinutes() >> 3; //\n", "\n", " output[op1++] = output[op2++] = (date.getMonth() + 1 & 0x7) << 5 | date.getDate();\n", " output[op1++] = output[op2++] = (date.getFullYear() - 1980 & 0x7f) << 1 | date.getMonth() + 1 >> 3; // CRC-32\n", "\n", " crc32 = file.crc32;\n", " output[op1++] = output[op2++] = crc32 & 0xff;\n", " output[op1++] = output[op2++] = crc32 >> 8 & 0xff;\n", " output[op1++] = output[op2++] = crc32 >> 16 & 0xff;\n", " output[op1++] = output[op2++] = crc32 >> 24 & 0xff; // compressed size\n", "\n", " size = file.buffer.length;\n", " output[op1++] = output[op2++] = size & 0xff;\n", " output[op1++] = output[op2++] = size >> 8 & 0xff;\n", " output[op1++] = output[op2++] = size >> 16 & 0xff;\n", " output[op1++] = output[op2++] = size >> 24 & 0xff; // uncompressed size\n", "\n", " plainSize = file.size;\n", " output[op1++] = output[op2++] = plainSize & 0xff;\n", " output[op1++] = output[op2++] = plainSize >> 8 & 0xff;\n", " output[op1++] = output[op2++] = plainSize >> 16 & 0xff;\n", " output[op1++] = output[op2++] = plainSize >> 24 & 0xff; // filename length\n", "\n", " output[op1++] = output[op2++] = filenameLength & 0xff;\n", " output[op1++] = output[op2++] = filenameLength >> 8 & 0xff; // extra field length\n", "\n", " output[op1++] = output[op2++] = extraFieldLength & 0xff;\n", " output[op1++] = output[op2++] = extraFieldLength >> 8 & 0xff; // file comment length\n", "\n", " output[op2++] = commentLength & 0xff;\n", " output[op2++] = commentLength >> 8 & 0xff; // disk number start\n", "\n", " output[op2++] = 0;\n", " output[op2++] = 0; // internal file attributes\n", "\n", " output[op2++] = 0;\n", " output[op2++] = 0; // external file attributes\n", "\n", " output[op2++] = 0;\n", " output[op2++] = 0;\n", " output[op2++] = 0;\n", " output[op2++] = 0; // relative offset of local header\n", "\n", " output[op2++] = offset & 0xff;\n", " output[op2++] = offset >> 8 & 0xff;\n", " output[op2++] = offset >> 16 & 0xff;\n", " output[op2++] = offset >> 24 & 0xff; // filename\n", "\n", " filename = file.option['filename'];\n", "\n", " if (filename) {\n", " {\n", " output.set(filename, op1);\n", " output.set(filename, op2);\n", " op1 += filenameLength;\n", " op2 += filenameLength;\n", " }\n", " } // extra field\n", "\n", "\n", " extraField = file.option['extraField'];\n", "\n", " if (extraField) {\n", " {\n", " output.set(extraField, op1);\n", " output.set(extraField, op2);\n", " op1 += extraFieldLength;\n", " op2 += extraFieldLength;\n", " }\n", " } // comment\n", "\n", "\n", " comment = file.option['comment'];\n", "\n", " if (comment) {\n", " {\n", " output.set(comment, op2);\n", " op2 += commentLength;\n", " }\n", " } //-------------------------------------------------------------------------\n", " // file data\n", " //-------------------------------------------------------------------------\n", "\n", "\n", " {\n", " output.set(file.buffer, op1);\n", " op1 += file.buffer.length;\n", " }\n", " } //-------------------------------------------------------------------------\n", " // end of central directory\n", " //-------------------------------------------------------------------------\n", " // signature\n", "\n", "\n", " output[op3++] = Zlib$2.Zip.CentralDirectorySignature[0];\n", " output[op3++] = Zlib$2.Zip.CentralDirectorySignature[1];\n", " output[op3++] = Zlib$2.Zip.CentralDirectorySignature[2];\n", " output[op3++] = Zlib$2.Zip.CentralDirectorySignature[3]; // number of this disk\n", "\n", " output[op3++] = 0;\n", " output[op3++] = 0; // number of the disk with the start of the central directory\n", "\n", " output[op3++] = 0;\n", " output[op3++] = 0; // total number of entries in the central directory on this disk\n", "\n", " output[op3++] = il & 0xff;\n", " output[op3++] = il >> 8 & 0xff; // total number of entries in the central directory\n", "\n", " output[op3++] = il & 0xff;\n", " output[op3++] = il >> 8 & 0xff; // size of the central directory\n", "\n", " output[op3++] = centralDirectorySize & 0xff;\n", " output[op3++] = centralDirectorySize >> 8 & 0xff;\n", " output[op3++] = centralDirectorySize >> 16 & 0xff;\n", " output[op3++] = centralDirectorySize >> 24 & 0xff; // offset of start of central directory with respect to the starting disk number\n", "\n", " output[op3++] = localFileSize & 0xff;\n", " output[op3++] = localFileSize >> 8 & 0xff;\n", " output[op3++] = localFileSize >> 16 & 0xff;\n", " output[op3++] = localFileSize >> 24 & 0xff; // .ZIP file comment length\n", "\n", " commentLength = this.comment ? this.comment.length : 0;\n", " output[op3++] = commentLength & 0xff;\n", " output[op3++] = commentLength >> 8 & 0xff; // .ZIP file comment\n", "\n", " if (this.comment) {\n", " {\n", " output.set(this.comment, op3);\n", " op3 += commentLength;\n", " }\n", " }\n", "\n", " return output;\n", " };\n", " /**\n", " * @param {!(Array.|Uint8Array)} input\n", " * @param {Object=} opt_params options.\n", " * @return {!(Array.|Uint8Array)}\n", " */\n", "\n", "\n", " Zlib$2.Zip.prototype.deflateWithOption = function (input, opt_params) {\n", " /** @type {Zlib.RawDeflate} */\n", " var deflator = new Zlib$2.RawDeflate(input, opt_params['deflateOption']);\n", " return deflator.compress();\n", " };\n", " /**\n", " * @param {(Array.|Uint32Array)} key\n", " * @return {number}\n", " */\n", "\n", "\n", " Zlib$2.Zip.prototype.getByte = function (key) {\n", " /** @type {number} */\n", " var tmp = key[2] & 0xffff | 2;\n", " return tmp * (tmp ^ 1) >> 8 & 0xff;\n", " };\n", " /**\n", " * @param {(Array.|Uint32Array|Object)} key\n", " * @param {number} n\n", " * @return {number}\n", " */\n", "\n", "\n", " Zlib$2.Zip.prototype.encode = function (key, n) {\n", " /** @type {number} */\n", " var tmp = this.getByte(\n", " /** @type {(Array.|Uint32Array)} */\n", " key);\n", " this.updateKeys(\n", " /** @type {(Array.|Uint32Array)} */\n", " key, n);\n", " return tmp ^ n;\n", " };\n", " /**\n", " * @param {(Array.|Uint32Array)} key\n", " * @param {number} n\n", " */\n", "\n", "\n", " Zlib$2.Zip.prototype.updateKeys = function (key, n) {\n", " key[0] = Zlib$2.CRC32.single(key[0], n);\n", " key[1] = (((key[1] + (key[0] & 0xff)) * 20173 >>> 0) * 6681 >>> 0) + 1 >>> 0;\n", " key[2] = Zlib$2.CRC32.single(key[2], key[1] >>> 24);\n", " };\n", " /**\n", " * @param {(Array.|Uint8Array)} password\n", " * @return {!(Array.|Uint32Array|Object)}\n", " */\n", "\n", "\n", " Zlib$2.Zip.prototype.createEncryptionKey = function (password) {\n", " /** @type {!(Array.|Uint32Array)} */\n", " var key = [305419896, 591751049, 878082192];\n", " /** @type {number} */\n", "\n", " var i;\n", " /** @type {number} */\n", "\n", " var il;\n", "\n", " {\n", " key = new Uint32Array(key);\n", " }\n", "\n", " for (i = 0, il = password.length; i < il; ++i) {\n", " this.updateKeys(key, password[i] & 0xff);\n", " }\n", "\n", " return key;\n", " };\n", " /**\n", " * build huffman table from length list.\n", " * @param {!(Array.|Uint8Array)} lengths length list.\n", " * @return {!Array} huffman table.\n", " */\n", "\n", "\n", " Zlib$2.Huffman.buildHuffmanTable = function (lengths) {\n", " /** @type {number} length list size. */\n", " var listSize = lengths.length;\n", " /** @type {number} max code length for table size. */\n", "\n", " var maxCodeLength = 0;\n", " /** @type {number} min code length for table size. */\n", "\n", " var minCodeLength = Number.POSITIVE_INFINITY;\n", " /** @type {number} table size. */\n", "\n", " var size;\n", " /** @type {!(Array|Uint8Array)} huffman code table. */\n", "\n", " var table;\n", " /** @type {number} bit length. */\n", "\n", " var bitLength;\n", " /** @type {number} huffman code. */\n", "\n", " var code;\n", " /**\n", " * サイズが 2^maxlength 個のテーブルを埋めるためのスキップ長.\n", " * @type {number} skip length for table filling.\n", " */\n", "\n", " var skip;\n", " /** @type {number} reversed code. */\n", "\n", " var reversed;\n", " /** @type {number} reverse temp. */\n", "\n", " var rtemp;\n", " /** @type {number} loop counter. */\n", "\n", " var i;\n", " /** @type {number} loop limit. */\n", "\n", " var il;\n", " /** @type {number} loop counter. */\n", "\n", " var j;\n", " /** @type {number} table value. */\n", "\n", " var value; // Math.max は遅いので最長の値は for-loop で取得する\n", "\n", " for (i = 0, il = listSize; i < il; ++i) {\n", " if (lengths[i] > maxCodeLength) {\n", " maxCodeLength = lengths[i];\n", " }\n", "\n", " if (lengths[i] < minCodeLength) {\n", " minCodeLength = lengths[i];\n", " }\n", " }\n", "\n", " size = 1 << maxCodeLength;\n", " table = new (Uint32Array )(size); // ビット長の短い順からハフマン符号を割り当てる\n", "\n", " for (bitLength = 1, code = 0, skip = 2; bitLength <= maxCodeLength;) {\n", " for (i = 0; i < listSize; ++i) {\n", " if (lengths[i] === bitLength) {\n", " // ビットオーダーが逆になるためビット長分並びを反転する\n", " for (reversed = 0, rtemp = code, j = 0; j < bitLength; ++j) {\n", " reversed = reversed << 1 | rtemp & 1;\n", " rtemp >>= 1;\n", " } // 最大ビット長をもとにテーブルを作るため、\n", " // 最大ビット長以外では 0 / 1 どちらでも良い箇所ができる\n", " // そのどちらでも良い場所は同じ値で埋めることで\n", " // 本来のビット長以上のビット数取得しても問題が起こらないようにする\n", "\n", "\n", " value = bitLength << 16 | i;\n", "\n", " for (j = reversed; j < size; j += skip) {\n", " table[j] = value;\n", " }\n", "\n", " ++code;\n", " }\n", " } // 次のビット長へ\n", "\n", "\n", " ++bitLength;\n", " code <<= 1;\n", " skip <<= 1;\n", " }\n", "\n", " return [table, maxCodeLength, minCodeLength];\n", " }; //-----------------------------------------------------------------------------\n", "\n", " /** @define {number} buffer block size. */\n", "\n", "\n", " var ZLIB_RAW_INFLATE_BUFFER_SIZE$2 = 0x8000; // [ 0x8000 >= ZLIB_BUFFER_BLOCK_SIZE ]\n", " //-----------------------------------------------------------------------------\n", "\n", " var buildHuffmanTable$2 = Zlib$2.Huffman.buildHuffmanTable;\n", " /**\n", " * @constructor\n", " * @param {!(Uint8Array|Array.)} input input buffer.\n", " * @param {Object} opt_params option parameter.\n", " *\n", " * opt_params は以下のプロパティを指定する事ができます。\n", " * - index: input buffer の deflate コンテナの開始位置.\n", " * - blockSize: バッファのブロックサイズ.\n", " * - bufferType: Zlib.RawInflate.BufferType の値によってバッファの管理方法を指定する.\n", " * - resize: 確保したバッファが実際の大きさより大きかった場合に切り詰める.\n", " */\n", "\n", " Zlib$2.RawInflate = function (input, opt_params) {\n", " /** @type {!(Array.|Uint8Array)} inflated buffer */\n", " this.buffer;\n", " /** @type {!Array.<(Array.|Uint8Array)>} */\n", "\n", " this.blocks = [];\n", " /** @type {number} block size. */\n", "\n", " this.bufferSize = ZLIB_RAW_INFLATE_BUFFER_SIZE$2;\n", " /** @type {!number} total output buffer pointer. */\n", "\n", " this.totalpos = 0;\n", " /** @type {!number} input buffer pointer. */\n", "\n", " this.ip = 0;\n", " /** @type {!number} bit stream reader buffer. */\n", "\n", " this.bitsbuf = 0;\n", " /** @type {!number} bit stream reader buffer size. */\n", "\n", " this.bitsbuflen = 0;\n", " /** @type {!(Array.|Uint8Array)} input buffer. */\n", "\n", " this.input = new Uint8Array(input) ;\n", " /** @type {!(Uint8Array|Array.)} output buffer. */\n", "\n", " this.output;\n", " /** @type {!number} output buffer pointer. */\n", "\n", " this.op;\n", " /** @type {boolean} is final block flag. */\n", "\n", " this.bfinal = false;\n", " /** @type {Zlib.RawInflate.BufferType} buffer management. */\n", "\n", " this.bufferType = Zlib$2.RawInflate.BufferType.ADAPTIVE;\n", " /** @type {boolean} resize flag for memory size optimization. */\n", "\n", " this.resize = false; // option parameters\n", "\n", " if (opt_params || !(opt_params = {})) {\n", " if (opt_params['index']) {\n", " this.ip = opt_params['index'];\n", " }\n", "\n", " if (opt_params['bufferSize']) {\n", " this.bufferSize = opt_params['bufferSize'];\n", " }\n", "\n", " if (opt_params['bufferType']) {\n", " this.bufferType = opt_params['bufferType'];\n", " }\n", "\n", " if (opt_params['resize']) {\n", " this.resize = opt_params['resize'];\n", " }\n", " } // initialize\n", "\n", "\n", " switch (this.bufferType) {\n", " case Zlib$2.RawInflate.BufferType.BLOCK:\n", " this.op = Zlib$2.RawInflate.MaxBackwardLength;\n", " this.output = new (Uint8Array )(Zlib$2.RawInflate.MaxBackwardLength + this.bufferSize + Zlib$2.RawInflate.MaxCopyLength);\n", " break;\n", "\n", " case Zlib$2.RawInflate.BufferType.ADAPTIVE:\n", " this.op = 0;\n", " this.output = new (Uint8Array )(this.bufferSize);\n", " break;\n", "\n", " default:\n", " throw new Error('invalid inflate mode');\n", " }\n", " };\n", " /**\n", " * @enum {number}\n", " */\n", "\n", "\n", " Zlib$2.RawInflate.BufferType = {\n", " BLOCK: 0,\n", " ADAPTIVE: 1\n", " };\n", " /**\n", " * decompress.\n", " * @return {!(Uint8Array|Array.)} inflated buffer.\n", " */\n", "\n", " Zlib$2.RawInflate.prototype.decompress = function () {\n", " while (!this.bfinal) {\n", " this.parseBlock();\n", " }\n", "\n", " switch (this.bufferType) {\n", " case Zlib$2.RawInflate.BufferType.BLOCK:\n", " return this.concatBufferBlock();\n", "\n", " case Zlib$2.RawInflate.BufferType.ADAPTIVE:\n", " return this.concatBufferDynamic();\n", "\n", " default:\n", " throw new Error('invalid inflate mode');\n", " }\n", " };\n", " /**\n", " * @const\n", " * @type {number} max backward length for LZ77.\n", " */\n", "\n", "\n", " Zlib$2.RawInflate.MaxBackwardLength = 32768;\n", " /**\n", " * @const\n", " * @type {number} max copy length for LZ77.\n", " */\n", "\n", " Zlib$2.RawInflate.MaxCopyLength = 258;\n", " /**\n", " * huffman order\n", " * @const\n", " * @type {!(Array.|Uint8Array)}\n", " */\n", "\n", " Zlib$2.RawInflate.Order = function (table) {\n", " return new Uint16Array(table) ;\n", " }([16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]);\n", " /**\n", " * huffman length code table.\n", " * @const\n", " * @type {!(Array.|Uint16Array)}\n", " */\n", "\n", "\n", " Zlib$2.RawInflate.LengthCodeTable = function (table) {\n", " return new Uint16Array(table) ;\n", " }([0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000d, 0x000f, 0x0011, 0x0013, 0x0017, 0x001b, 0x001f, 0x0023, 0x002b, 0x0033, 0x003b, 0x0043, 0x0053, 0x0063, 0x0073, 0x0083, 0x00a3, 0x00c3, 0x00e3, 0x0102, 0x0102, 0x0102]);\n", " /**\n", " * huffman length extra-bits table.\n", " * @const\n", " * @type {!(Array.|Uint8Array)}\n", " */\n", "\n", "\n", " Zlib$2.RawInflate.LengthExtraTable = function (table) {\n", " return new Uint8Array(table) ;\n", " }([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, 0, 0]);\n", " /**\n", " * huffman dist code table.\n", " * @const\n", " * @type {!(Array.|Uint16Array)}\n", " */\n", "\n", "\n", " Zlib$2.RawInflate.DistCodeTable = function (table) {\n", " return new Uint16Array(table) ;\n", " }([0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0007, 0x0009, 0x000d, 0x0011, 0x0019, 0x0021, 0x0031, 0x0041, 0x0061, 0x0081, 0x00c1, 0x0101, 0x0181, 0x0201, 0x0301, 0x0401, 0x0601, 0x0801, 0x0c01, 0x1001, 0x1801, 0x2001, 0x3001, 0x4001, 0x6001]);\n", " /**\n", " * huffman dist extra-bits table.\n", " * @const\n", " * @type {!(Array.|Uint8Array)}\n", " */\n", "\n", "\n", " Zlib$2.RawInflate.DistExtraTable = function (table) {\n", " return new Uint8Array(table) ;\n", " }([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]);\n", " /**\n", " * fixed huffman length code table\n", " * @const\n", " * @type {!Array}\n", " */\n", "\n", "\n", " Zlib$2.RawInflate.FixedLiteralLengthTable = function (table) {\n", " return table;\n", " }(function () {\n", " var lengths = new (Uint8Array )(288);\n", " var i, il;\n", "\n", " for (i = 0, il = lengths.length; i < il; ++i) {\n", " lengths[i] = i <= 143 ? 8 : i <= 255 ? 9 : i <= 279 ? 7 : 8;\n", " }\n", "\n", " return buildHuffmanTable$2(lengths);\n", " }());\n", " /**\n", " * fixed huffman distance code table\n", " * @const\n", " * @type {!Array}\n", " */\n", "\n", "\n", " Zlib$2.RawInflate.FixedDistanceTable = function (table) {\n", " return table;\n", " }(function () {\n", " var lengths = new (Uint8Array )(30);\n", " var i, il;\n", "\n", " for (i = 0, il = lengths.length; i < il; ++i) {\n", " lengths[i] = 5;\n", " }\n", "\n", " return buildHuffmanTable$2(lengths);\n", " }());\n", " /**\n", " * parse deflated block.\n", " */\n", "\n", "\n", " Zlib$2.RawInflate.prototype.parseBlock = function () {\n", " /** @type {number} header */\n", " var hdr = this.readBits(3); // BFINAL\n", "\n", " if (hdr & 0x1) {\n", " this.bfinal = true;\n", " } // BTYPE\n", "\n", "\n", " hdr >>>= 1;\n", "\n", " switch (hdr) {\n", " // uncompressed\n", " case 0:\n", " this.parseUncompressedBlock();\n", " break;\n", " // fixed huffman\n", "\n", " case 1:\n", " this.parseFixedHuffmanBlock();\n", " break;\n", " // dynamic huffman\n", "\n", " case 2:\n", " this.parseDynamicHuffmanBlock();\n", " break;\n", " // reserved or other\n", "\n", " default:\n", " throw new Error('unknown BTYPE: ' + hdr);\n", " }\n", " };\n", " /**\n", " * read inflate bits\n", " * @param {number} length bits length.\n", " * @return {number} read bits.\n", " */\n", "\n", "\n", " Zlib$2.RawInflate.prototype.readBits = function (length) {\n", " var bitsbuf = this.bitsbuf;\n", " var bitsbuflen = this.bitsbuflen;\n", " var input = this.input;\n", " var ip = this.ip;\n", " /** @type {number} */\n", "\n", " var inputLength = input.length;\n", " /** @type {number} input and output byte. */\n", "\n", " var octet; // input byte\n", "\n", " if (ip + (length - bitsbuflen + 7 >> 3) >= inputLength) {\n", " throw new Error('input buffer is broken');\n", " } // not enough buffer\n", "\n", "\n", " while (bitsbuflen < length) {\n", " bitsbuf |= input[ip++] << bitsbuflen;\n", " bitsbuflen += 8;\n", " } // output byte\n", "\n", "\n", " octet = bitsbuf &\n", " /* MASK */\n", " (1 << length) - 1;\n", " bitsbuf >>>= length;\n", " bitsbuflen -= length;\n", " this.bitsbuf = bitsbuf;\n", " this.bitsbuflen = bitsbuflen;\n", " this.ip = ip;\n", " return octet;\n", " };\n", " /**\n", " * read huffman code using table\n", " * @param {!(Array.|Uint8Array|Uint16Array)} table huffman code table.\n", " * @return {number} huffman code.\n", " */\n", "\n", "\n", " Zlib$2.RawInflate.prototype.readCodeByTable = function (table) {\n", " var bitsbuf = this.bitsbuf;\n", " var bitsbuflen = this.bitsbuflen;\n", " var input = this.input;\n", " var ip = this.ip;\n", " /** @type {number} */\n", "\n", " var inputLength = input.length;\n", " /** @type {!(Array.|Uint8Array)} huffman code table */\n", "\n", " var codeTable = table[0];\n", " /** @type {number} */\n", "\n", " var maxCodeLength = table[1];\n", " /** @type {number} code length & code (16bit, 16bit) */\n", "\n", " var codeWithLength;\n", " /** @type {number} code bits length */\n", "\n", " var codeLength; // not enough buffer\n", "\n", " while (bitsbuflen < maxCodeLength) {\n", " if (ip >= inputLength) {\n", " break;\n", " }\n", "\n", " bitsbuf |= input[ip++] << bitsbuflen;\n", " bitsbuflen += 8;\n", " } // read max length\n", "\n", "\n", " codeWithLength = codeTable[bitsbuf & (1 << maxCodeLength) - 1];\n", " codeLength = codeWithLength >>> 16;\n", "\n", " if (codeLength > bitsbuflen) {\n", " throw new Error('invalid code length: ' + codeLength);\n", " }\n", "\n", " this.bitsbuf = bitsbuf >> codeLength;\n", " this.bitsbuflen = bitsbuflen - codeLength;\n", " this.ip = ip;\n", " return codeWithLength & 0xffff;\n", " };\n", " /**\n", " * parse uncompressed block.\n", " */\n", "\n", "\n", " Zlib$2.RawInflate.prototype.parseUncompressedBlock = function () {\n", " var input = this.input;\n", " var ip = this.ip;\n", " var output = this.output;\n", " var op = this.op;\n", " /** @type {number} */\n", "\n", " var inputLength = input.length;\n", " /** @type {number} block length */\n", "\n", " var len;\n", " /** @type {number} number for check block length */\n", "\n", " var nlen;\n", " /** @type {number} output buffer length */\n", "\n", " var olength = output.length;\n", " /** @type {number} copy counter */\n", "\n", " var preCopy; // skip buffered header bits\n", "\n", " this.bitsbuf = 0;\n", " this.bitsbuflen = 0; // len\n", "\n", " if (ip + 1 >= inputLength) {\n", " throw new Error('invalid uncompressed block header: LEN');\n", " }\n", "\n", " len = input[ip++] | input[ip++] << 8; // nlen\n", "\n", " if (ip + 1 >= inputLength) {\n", " throw new Error('invalid uncompressed block header: NLEN');\n", " }\n", "\n", " nlen = input[ip++] | input[ip++] << 8; // check len & nlen\n", "\n", " if (len === ~nlen) {\n", " throw new Error('invalid uncompressed block header: length verify');\n", " } // check size\n", "\n", "\n", " if (ip + len > input.length) {\n", " throw new Error('input buffer is broken');\n", " } // expand buffer\n", "\n", "\n", " switch (this.bufferType) {\n", " case Zlib$2.RawInflate.BufferType.BLOCK:\n", " // pre copy\n", " while (op + len > output.length) {\n", " preCopy = olength - op;\n", " len -= preCopy;\n", "\n", " {\n", " output.set(input.subarray(ip, ip + preCopy), op);\n", " op += preCopy;\n", " ip += preCopy;\n", " }\n", "\n", " this.op = op;\n", " output = this.expandBufferBlock();\n", " op = this.op;\n", " }\n", "\n", " break;\n", "\n", " case Zlib$2.RawInflate.BufferType.ADAPTIVE:\n", " while (op + len > output.length) {\n", " output = this.expandBufferAdaptive({\n", " fixRatio: 2\n", " });\n", " }\n", "\n", " break;\n", "\n", " default:\n", " throw new Error('invalid inflate mode');\n", " } // copy\n", "\n", "\n", " {\n", " output.set(input.subarray(ip, ip + len), op);\n", " op += len;\n", " ip += len;\n", " }\n", "\n", " this.ip = ip;\n", " this.op = op;\n", " this.output = output;\n", " };\n", " /**\n", " * parse fixed huffman block.\n", " */\n", "\n", "\n", " Zlib$2.RawInflate.prototype.parseFixedHuffmanBlock = function () {\n", " switch (this.bufferType) {\n", " case Zlib$2.RawInflate.BufferType.ADAPTIVE:\n", " this.decodeHuffmanAdaptive(Zlib$2.RawInflate.FixedLiteralLengthTable, Zlib$2.RawInflate.FixedDistanceTable);\n", " break;\n", "\n", " case Zlib$2.RawInflate.BufferType.BLOCK:\n", " this.decodeHuffmanBlock(Zlib$2.RawInflate.FixedLiteralLengthTable, Zlib$2.RawInflate.FixedDistanceTable);\n", " break;\n", "\n", " default:\n", " throw new Error('invalid inflate mode');\n", " }\n", " };\n", " /**\n", " * parse dynamic huffman block.\n", " */\n", "\n", "\n", " Zlib$2.RawInflate.prototype.parseDynamicHuffmanBlock = function () {\n", " /** @type {number} number of literal and length codes. */\n", " var hlit = this.readBits(5) + 257;\n", " /** @type {number} number of distance codes. */\n", "\n", " var hdist = this.readBits(5) + 1;\n", " /** @type {number} number of code lengths. */\n", "\n", " var hclen = this.readBits(4) + 4;\n", " /** @type {!(Uint8Array|Array.)} code lengths. */\n", "\n", " var codeLengths = new (Uint8Array )(Zlib$2.RawInflate.Order.length);\n", " /** @type {!Array} code lengths table. */\n", "\n", " var codeLengthsTable;\n", " /** @type {!(Uint8Array|Array.)} literal and length code table. */\n", "\n", " var litlenTable;\n", " /** @type {!(Uint8Array|Array.)} distance code table. */\n", "\n", " var distTable;\n", " /** @type {!(Uint8Array|Array.)} code length table. */\n", "\n", " var lengthTable;\n", " /** @type {number} */\n", "\n", " var code;\n", " /** @type {number} */\n", "\n", " var prev;\n", " /** @type {number} */\n", "\n", " var repeat;\n", " /** @type {number} loop counter. */\n", "\n", " var i;\n", " /** @type {number} loop limit. */\n", "\n", " var il; // decode code lengths\n", "\n", " for (i = 0; i < hclen; ++i) {\n", " codeLengths[Zlib$2.RawInflate.Order[i]] = this.readBits(3);\n", " }\n", "\n", "\n", " codeLengthsTable = buildHuffmanTable$2(codeLengths);\n", " lengthTable = new (Uint8Array )(hlit + hdist);\n", "\n", " for (i = 0, il = hlit + hdist; i < il;) {\n", " code = this.readCodeByTable(codeLengthsTable);\n", "\n", " switch (code) {\n", " case 16:\n", " repeat = 3 + this.readBits(2);\n", "\n", " while (repeat--) {\n", " lengthTable[i++] = prev;\n", " }\n", "\n", " break;\n", "\n", " case 17:\n", " repeat = 3 + this.readBits(3);\n", "\n", " while (repeat--) {\n", " lengthTable[i++] = 0;\n", " }\n", "\n", " prev = 0;\n", " break;\n", "\n", " case 18:\n", " repeat = 11 + this.readBits(7);\n", "\n", " while (repeat--) {\n", " lengthTable[i++] = 0;\n", " }\n", "\n", " prev = 0;\n", " break;\n", "\n", " default:\n", " lengthTable[i++] = code;\n", " prev = code;\n", " break;\n", " }\n", " }\n", "\n", " litlenTable = buildHuffmanTable$2(lengthTable.subarray(0, hlit)) ;\n", " distTable = buildHuffmanTable$2(lengthTable.subarray(hlit)) ;\n", "\n", " switch (this.bufferType) {\n", " case Zlib$2.RawInflate.BufferType.ADAPTIVE:\n", " this.decodeHuffmanAdaptive(litlenTable, distTable);\n", " break;\n", "\n", " case Zlib$2.RawInflate.BufferType.BLOCK:\n", " this.decodeHuffmanBlock(litlenTable, distTable);\n", " break;\n", "\n", " default:\n", " throw new Error('invalid inflate mode');\n", " }\n", " };\n", " /**\n", " * decode huffman code\n", " * @param {!(Array.|Uint16Array)} litlen literal and length code table.\n", " * @param {!(Array.|Uint8Array)} dist distination code table.\n", " */\n", "\n", "\n", " Zlib$2.RawInflate.prototype.decodeHuffmanBlock = function (litlen, dist) {\n", " var output = this.output;\n", " var op = this.op;\n", " this.currentLitlenTable = litlen;\n", " /** @type {number} output position limit. */\n", "\n", " var olength = output.length - Zlib$2.RawInflate.MaxCopyLength;\n", " /** @type {number} huffman code. */\n", "\n", " var code;\n", " /** @type {number} table index. */\n", "\n", " var ti;\n", " /** @type {number} huffman code distination. */\n", "\n", " var codeDist;\n", " /** @type {number} huffman code length. */\n", "\n", " var codeLength;\n", " var lengthCodeTable = Zlib$2.RawInflate.LengthCodeTable;\n", " var lengthExtraTable = Zlib$2.RawInflate.LengthExtraTable;\n", " var distCodeTable = Zlib$2.RawInflate.DistCodeTable;\n", " var distExtraTable = Zlib$2.RawInflate.DistExtraTable;\n", "\n", " while ((code = this.readCodeByTable(litlen)) !== 256) {\n", " // literal\n", " if (code < 256) {\n", " if (op >= olength) {\n", " this.op = op;\n", " output = this.expandBufferBlock();\n", " op = this.op;\n", " }\n", "\n", " output[op++] = code;\n", " continue;\n", " } // length code\n", "\n", "\n", " ti = code - 257;\n", " codeLength = lengthCodeTable[ti];\n", "\n", " if (lengthExtraTable[ti] > 0) {\n", " codeLength += this.readBits(lengthExtraTable[ti]);\n", " } // dist code\n", "\n", "\n", " code = this.readCodeByTable(dist);\n", " codeDist = distCodeTable[code];\n", "\n", " if (distExtraTable[code] > 0) {\n", " codeDist += this.readBits(distExtraTable[code]);\n", " } // lz77 decode\n", "\n", "\n", " if (op >= olength) {\n", " this.op = op;\n", " output = this.expandBufferBlock();\n", " op = this.op;\n", " }\n", "\n", " while (codeLength--) {\n", " output[op] = output[op++ - codeDist];\n", " }\n", " }\n", "\n", " while (this.bitsbuflen >= 8) {\n", " this.bitsbuflen -= 8;\n", " this.ip--;\n", " }\n", "\n", " this.op = op;\n", " };\n", " /**\n", " * decode huffman code (adaptive)\n", " * @param {!(Array.|Uint16Array)} litlen literal and length code table.\n", " * @param {!(Array.|Uint8Array)} dist distination code table.\n", " */\n", "\n", "\n", " Zlib$2.RawInflate.prototype.decodeHuffmanAdaptive = function (litlen, dist) {\n", " var output = this.output;\n", " var op = this.op;\n", " this.currentLitlenTable = litlen;\n", " /** @type {number} output position limit. */\n", "\n", " var olength = output.length;\n", " /** @type {number} huffman code. */\n", "\n", " var code;\n", " /** @type {number} table index. */\n", "\n", " var ti;\n", " /** @type {number} huffman code distination. */\n", "\n", " var codeDist;\n", " /** @type {number} huffman code length. */\n", "\n", " var codeLength;\n", " var lengthCodeTable = Zlib$2.RawInflate.LengthCodeTable;\n", " var lengthExtraTable = Zlib$2.RawInflate.LengthExtraTable;\n", " var distCodeTable = Zlib$2.RawInflate.DistCodeTable;\n", " var distExtraTable = Zlib$2.RawInflate.DistExtraTable;\n", "\n", " while ((code = this.readCodeByTable(litlen)) !== 256) {\n", " // literal\n", " if (code < 256) {\n", " if (op >= olength) {\n", " output = this.expandBufferAdaptive();\n", " olength = output.length;\n", " }\n", "\n", " output[op++] = code;\n", " continue;\n", " } // length code\n", "\n", "\n", " ti = code - 257;\n", " codeLength = lengthCodeTable[ti];\n", "\n", " if (lengthExtraTable[ti] > 0) {\n", " codeLength += this.readBits(lengthExtraTable[ti]);\n", " } // dist code\n", "\n", "\n", " code = this.readCodeByTable(dist);\n", " codeDist = distCodeTable[code];\n", "\n", " if (distExtraTable[code] > 0) {\n", " codeDist += this.readBits(distExtraTable[code]);\n", " } // lz77 decode\n", "\n", "\n", " if (op + codeLength > olength) {\n", " output = this.expandBufferAdaptive();\n", " olength = output.length;\n", " }\n", "\n", " while (codeLength--) {\n", " output[op] = output[op++ - codeDist];\n", " }\n", " }\n", "\n", " while (this.bitsbuflen >= 8) {\n", " this.bitsbuflen -= 8;\n", " this.ip--;\n", " }\n", "\n", " this.op = op;\n", " };\n", " /**\n", " * expand output buffer.\n", " * @param {Object=} opt_param option parameters.\n", " * @return {!(Array.|Uint8Array)} output buffer.\n", " */\n", "\n", "\n", " Zlib$2.RawInflate.prototype.expandBufferBlock = function (opt_param) {\n", " /** @type {!(Array.|Uint8Array)} store buffer. */\n", " var buffer = new (Uint8Array )(this.op - Zlib$2.RawInflate.MaxBackwardLength);\n", " /** @type {number} backward base point */\n", "\n", " var backward = this.op - Zlib$2.RawInflate.MaxBackwardLength;\n", " var output = this.output; // copy to output buffer\n", "\n", " {\n", " buffer.set(output.subarray(Zlib$2.RawInflate.MaxBackwardLength, buffer.length));\n", " }\n", "\n", " this.blocks.push(buffer);\n", " this.totalpos += buffer.length; // copy to backward buffer\n", "\n", " {\n", " output.set(output.subarray(backward, backward + Zlib$2.RawInflate.MaxBackwardLength));\n", " }\n", "\n", " this.op = Zlib$2.RawInflate.MaxBackwardLength;\n", " return output;\n", " };\n", " /**\n", " * expand output buffer. (adaptive)\n", " * @param {Object=} opt_param option parameters.\n", " * @return {!(Array.|Uint8Array)} output buffer pointer.\n", " */\n", "\n", "\n", " Zlib$2.RawInflate.prototype.expandBufferAdaptive = function (opt_param) {\n", " /** @type {!(Array.|Uint8Array)} store buffer. */\n", " var buffer;\n", " /** @type {number} expantion ratio. */\n", "\n", " var ratio = this.input.length / this.ip + 1 | 0;\n", " /** @type {number} maximum number of huffman code. */\n", "\n", " var maxHuffCode;\n", " /** @type {number} new output buffer size. */\n", "\n", " var newSize;\n", " /** @type {number} max inflate size. */\n", "\n", " var maxInflateSize;\n", " var input = this.input;\n", " var output = this.output;\n", "\n", " if (opt_param) {\n", " if (typeof opt_param.fixRatio === 'number') {\n", " ratio = opt_param.fixRatio;\n", " }\n", "\n", " if (typeof opt_param.addRatio === 'number') {\n", " ratio += opt_param.addRatio;\n", " }\n", " } // calculate new buffer size\n", "\n", "\n", " if (ratio < 2) {\n", " maxHuffCode = (input.length - this.ip) / this.currentLitlenTable[2];\n", " maxInflateSize = maxHuffCode / 2 * 258 | 0;\n", " newSize = maxInflateSize < output.length ? output.length + maxInflateSize : output.length << 1;\n", " } else {\n", " newSize = output.length * ratio;\n", " } // buffer expantion\n", "\n", "\n", " {\n", " buffer = new Uint8Array(newSize);\n", " buffer.set(output);\n", " }\n", "\n", " this.output = buffer;\n", " return this.output;\n", " };\n", " /**\n", " * concat output buffer.\n", " * @return {!(Array.|Uint8Array)} output buffer.\n", " */\n", "\n", "\n", " Zlib$2.RawInflate.prototype.concatBufferBlock = function () {\n", " /** @type {number} buffer pointer. */\n", " var pos = 0;\n", " /** @type {number} buffer pointer. */\n", "\n", " var limit = this.totalpos + (this.op - Zlib$2.RawInflate.MaxBackwardLength);\n", " /** @type {!(Array.|Uint8Array)} output block array. */\n", "\n", " var output = this.output;\n", " /** @type {!Array} blocks array. */\n", "\n", " var blocks = this.blocks;\n", " /** @type {!(Array.|Uint8Array)} output block array. */\n", "\n", " var block;\n", " /** @type {!(Array.|Uint8Array)} output buffer. */\n", "\n", " var buffer = new (Uint8Array )(limit);\n", " /** @type {number} loop counter. */\n", "\n", " var i;\n", " /** @type {number} loop limiter. */\n", "\n", " var il;\n", " /** @type {number} loop counter. */\n", "\n", " var j;\n", " /** @type {number} loop limiter. */\n", "\n", " var jl; // single buffer\n", "\n", " if (blocks.length === 0) {\n", " return this.output.subarray(Zlib$2.RawInflate.MaxBackwardLength, this.op) ;\n", " } // copy to buffer\n", "\n", "\n", " for (i = 0, il = blocks.length; i < il; ++i) {\n", " block = blocks[i];\n", "\n", " for (j = 0, jl = block.length; j < jl; ++j) {\n", " buffer[pos++] = block[j];\n", " }\n", " } // current buffer\n", "\n", "\n", " for (i = Zlib$2.RawInflate.MaxBackwardLength, il = this.op; i < il; ++i) {\n", " buffer[pos++] = output[i];\n", " }\n", "\n", " this.blocks = [];\n", " this.buffer = buffer;\n", " return this.buffer;\n", " };\n", " /**\n", " * concat output buffer. (dynamic)\n", " * @return {!(Array.|Uint8Array)} output buffer.\n", " */\n", "\n", "\n", " Zlib$2.RawInflate.prototype.concatBufferDynamic = function () {\n", " /** @type {Array.|Uint8Array} output buffer. */\n", " var buffer;\n", " var op = this.op;\n", "\n", " {\n", " if (this.resize) {\n", " buffer = new Uint8Array(op);\n", " buffer.set(this.output.subarray(0, op));\n", " } else {\n", " buffer = this.output.subarray(0, op);\n", " }\n", " }\n", "\n", " this.buffer = buffer;\n", " return this.buffer;\n", " };\n", "\n", " var buildHuffmanTable$2 = Zlib$2.Huffman.buildHuffmanTable;\n", " /**\n", " * @param {!(Uint8Array|Array.)} input input buffer.\n", " * @param {number} ip input buffer pointer.\n", " * @param {number=} opt_buffersize buffer block size.\n", " * @constructor\n", " */\n", "\n", " Zlib$2.RawInflateStream = function (input, ip, opt_buffersize) {\n", " /** @type {!Array.<(Array|Uint8Array)>} */\n", " this.blocks = [];\n", " /** @type {number} block size. */\n", "\n", " this.bufferSize = opt_buffersize ? opt_buffersize : ZLIB_STREAM_RAW_INFLATE_BUFFER_SIZE$2;\n", " /** @type {!number} total output buffer pointer. */\n", "\n", " this.totalpos = 0;\n", " /** @type {!number} input buffer pointer. */\n", "\n", " this.ip = ip === void 0 ? 0 : ip;\n", " /** @type {!number} bit stream reader buffer. */\n", "\n", " this.bitsbuf = 0;\n", " /** @type {!number} bit stream reader buffer size. */\n", "\n", " this.bitsbuflen = 0;\n", " /** @type {!(Array|Uint8Array)} input buffer. */\n", "\n", " this.input = new Uint8Array(input) ;\n", " /** @type {!(Uint8Array|Array)} output buffer. */\n", "\n", " this.output = new (Uint8Array )(this.bufferSize);\n", " /** @type {!number} output buffer pointer. */\n", "\n", " this.op = 0;\n", " /** @type {boolean} is final block flag. */\n", "\n", " this.bfinal = false;\n", " /** @type {number} uncompressed block length. */\n", "\n", " this.blockLength;\n", " /** @type {boolean} resize flag for memory size optimization. */\n", "\n", " this.resize = false;\n", " /** @type {Array} */\n", "\n", " this.litlenTable;\n", " /** @type {Array} */\n", "\n", " this.distTable;\n", " /** @type {number} */\n", "\n", " this.sp = 0; // stream pointer\n", "\n", " /** @type {Zlib.RawInflateStream.Status} */\n", "\n", " this.status = Zlib$2.RawInflateStream.Status.INITIALIZED; //\n", " // backup\n", " //\n", "\n", " /** @type {!number} */\n", "\n", " this.ip_;\n", " /** @type {!number} */\n", "\n", " this.bitsbuflen_;\n", " /** @type {!number} */\n", "\n", " this.bitsbuf_;\n", " };\n", " /**\n", " * @enum {number}\n", " */\n", "\n", "\n", " Zlib$2.RawInflateStream.BlockType = {\n", " UNCOMPRESSED: 0,\n", " FIXED: 1,\n", " DYNAMIC: 2\n", " };\n", " /**\n", " * @enum {number}\n", " */\n", "\n", " Zlib$2.RawInflateStream.Status = {\n", " INITIALIZED: 0,\n", " BLOCK_HEADER_START: 1,\n", " BLOCK_HEADER_END: 2,\n", " BLOCK_BODY_START: 3,\n", " BLOCK_BODY_END: 4,\n", " DECODE_BLOCK_START: 5,\n", " DECODE_BLOCK_END: 6\n", " };\n", " /**\n", " * decompress.\n", " * @return {!(Uint8Array|Array)} inflated buffer.\n", " */\n", "\n", " Zlib$2.RawInflateStream.prototype.decompress = function (newInput, ip) {\n", " /** @type {boolean} */\n", " var stop = false;\n", "\n", " if (newInput !== void 0) {\n", " this.input = newInput;\n", " }\n", "\n", " if (ip !== void 0) {\n", " this.ip = ip;\n", " } // decompress\n", "\n", "\n", " while (!stop) {\n", " switch (this.status) {\n", " // block header\n", " case Zlib$2.RawInflateStream.Status.INITIALIZED:\n", " case Zlib$2.RawInflateStream.Status.BLOCK_HEADER_START:\n", " if (this.readBlockHeader() < 0) {\n", " stop = true;\n", " }\n", "\n", " break;\n", " // block body\n", "\n", " case Zlib$2.RawInflateStream.Status.BLOCK_HEADER_END:\n", " /* FALLTHROUGH */\n", "\n", " case Zlib$2.RawInflateStream.Status.BLOCK_BODY_START:\n", " switch (this.currentBlockType) {\n", " case Zlib$2.RawInflateStream.BlockType.UNCOMPRESSED:\n", " if (this.readUncompressedBlockHeader() < 0) {\n", " stop = true;\n", " }\n", "\n", " break;\n", "\n", " case Zlib$2.RawInflateStream.BlockType.FIXED:\n", " if (this.parseFixedHuffmanBlock() < 0) {\n", " stop = true;\n", " }\n", "\n", " break;\n", "\n", " case Zlib$2.RawInflateStream.BlockType.DYNAMIC:\n", " if (this.parseDynamicHuffmanBlock() < 0) {\n", " stop = true;\n", " }\n", "\n", " break;\n", " }\n", "\n", " break;\n", " // decode data\n", "\n", " case Zlib$2.RawInflateStream.Status.BLOCK_BODY_END:\n", " case Zlib$2.RawInflateStream.Status.DECODE_BLOCK_START:\n", " switch (this.currentBlockType) {\n", " case Zlib$2.RawInflateStream.BlockType.UNCOMPRESSED:\n", " if (this.parseUncompressedBlock() < 0) {\n", " stop = true;\n", " }\n", "\n", " break;\n", "\n", " case Zlib$2.RawInflateStream.BlockType.FIXED:\n", " /* FALLTHROUGH */\n", "\n", " case Zlib$2.RawInflateStream.BlockType.DYNAMIC:\n", " if (this.decodeHuffman() < 0) {\n", " stop = true;\n", " }\n", "\n", " break;\n", " }\n", "\n", " break;\n", "\n", " case Zlib$2.RawInflateStream.Status.DECODE_BLOCK_END:\n", " if (this.bfinal) {\n", " stop = true;\n", " } else {\n", " this.status = Zlib$2.RawInflateStream.Status.INITIALIZED;\n", " }\n", "\n", " break;\n", " }\n", " }\n", "\n", " return this.concatBuffer();\n", " };\n", " /**\n", " * @const\n", " * @type {number} max backward length for LZ77.\n", " */\n", "\n", "\n", " Zlib$2.RawInflateStream.MaxBackwardLength = 32768;\n", " /**\n", " * @const\n", " * @type {number} max copy length for LZ77.\n", " */\n", "\n", " Zlib$2.RawInflateStream.MaxCopyLength = 258;\n", " /**\n", " * huffman order\n", " * @const\n", " * @type {!(Array.|Uint8Array)}\n", " */\n", "\n", " Zlib$2.RawInflateStream.Order = function (table) {\n", " return new Uint16Array(table) ;\n", " }([16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]);\n", " /**\n", " * huffman length code table.\n", " * @const\n", " * @type {!(Array.|Uint16Array)}\n", " */\n", "\n", "\n", " Zlib$2.RawInflateStream.LengthCodeTable = function (table) {\n", " return new Uint16Array(table) ;\n", " }([0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000d, 0x000f, 0x0011, 0x0013, 0x0017, 0x001b, 0x001f, 0x0023, 0x002b, 0x0033, 0x003b, 0x0043, 0x0053, 0x0063, 0x0073, 0x0083, 0x00a3, 0x00c3, 0x00e3, 0x0102, 0x0102, 0x0102]);\n", " /**\n", " * huffman length extra-bits table.\n", " * @const\n", " * @type {!(Array.|Uint8Array)}\n", " */\n", "\n", "\n", " Zlib$2.RawInflateStream.LengthExtraTable = function (table) {\n", " return new Uint8Array(table) ;\n", " }([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, 0, 0]);\n", " /**\n", " * huffman dist code table.\n", " * @const\n", " * @type {!(Array.|Uint16Array)}\n", " */\n", "\n", "\n", " Zlib$2.RawInflateStream.DistCodeTable = function (table) {\n", " return new Uint16Array(table) ;\n", " }([0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0007, 0x0009, 0x000d, 0x0011, 0x0019, 0x0021, 0x0031, 0x0041, 0x0061, 0x0081, 0x00c1, 0x0101, 0x0181, 0x0201, 0x0301, 0x0401, 0x0601, 0x0801, 0x0c01, 0x1001, 0x1801, 0x2001, 0x3001, 0x4001, 0x6001]);\n", " /**\n", " * huffman dist extra-bits table.\n", " * @const\n", " * @type {!(Array.|Uint8Array)}\n", " */\n", "\n", "\n", " Zlib$2.RawInflateStream.DistExtraTable = function (table) {\n", " return new Uint8Array(table) ;\n", " }([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]);\n", " /**\n", " * fixed huffman length code table\n", " * @const\n", " * @type {!Array}\n", " */\n", "\n", "\n", " Zlib$2.RawInflateStream.FixedLiteralLengthTable = function (table) {\n", " return table;\n", " }(function () {\n", " var lengths = new (Uint8Array )(288);\n", " var i, il;\n", "\n", " for (i = 0, il = lengths.length; i < il; ++i) {\n", " lengths[i] = i <= 143 ? 8 : i <= 255 ? 9 : i <= 279 ? 7 : 8;\n", " }\n", "\n", " return buildHuffmanTable$2(lengths);\n", " }());\n", " /**\n", " * fixed huffman distance code table\n", " * @const\n", " * @type {!Array}\n", " */\n", "\n", "\n", " Zlib$2.RawInflateStream.FixedDistanceTable = function (table) {\n", " return table;\n", " }(function () {\n", " var lengths = new (Uint8Array )(30);\n", " var i, il;\n", "\n", " for (i = 0, il = lengths.length; i < il; ++i) {\n", " lengths[i] = 5;\n", " }\n", "\n", " return buildHuffmanTable$2(lengths);\n", " }());\n", " /**\n", " * parse deflated block.\n", " */\n", "\n", "\n", " Zlib$2.RawInflateStream.prototype.readBlockHeader = function () {\n", " /** @type {number} header */\n", " var hdr;\n", " this.status = Zlib$2.RawInflateStream.Status.BLOCK_HEADER_START;\n", " this.save_();\n", "\n", " if ((hdr = this.readBits(3)) < 0) {\n", " this.restore_();\n", " return -1;\n", " } // BFINAL\n", "\n", "\n", " if (hdr & 0x1) {\n", " this.bfinal = true;\n", " } // BTYPE\n", "\n", "\n", " hdr >>>= 1;\n", "\n", " switch (hdr) {\n", " case 0:\n", " // uncompressed\n", " this.currentBlockType = Zlib$2.RawInflateStream.BlockType.UNCOMPRESSED;\n", " break;\n", "\n", " case 1:\n", " // fixed huffman\n", " this.currentBlockType = Zlib$2.RawInflateStream.BlockType.FIXED;\n", " break;\n", "\n", " case 2:\n", " // dynamic huffman\n", " this.currentBlockType = Zlib$2.RawInflateStream.BlockType.DYNAMIC;\n", " break;\n", "\n", " default:\n", " // reserved or other\n", " throw new Error('unknown BTYPE: ' + hdr);\n", " }\n", "\n", " this.status = Zlib$2.RawInflateStream.Status.BLOCK_HEADER_END;\n", " };\n", " /**\n", " * read inflate bits\n", " * @param {number} length bits length.\n", " * @return {number} read bits.\n", " */\n", "\n", "\n", " Zlib$2.RawInflateStream.prototype.readBits = function (length) {\n", " var bitsbuf = this.bitsbuf;\n", " var bitsbuflen = this.bitsbuflen;\n", " var input = this.input;\n", " var ip = this.ip;\n", " /** @type {number} input and output byte. */\n", "\n", " var octet; // not enough buffer\n", "\n", " while (bitsbuflen < length) {\n", " // input byte\n", " if (input.length <= ip) {\n", " return -1;\n", " }\n", "\n", " octet = input[ip++]; // concat octet\n", "\n", " bitsbuf |= octet << bitsbuflen;\n", " bitsbuflen += 8;\n", " } // output byte\n", "\n", "\n", " octet = bitsbuf &\n", " /* MASK */\n", " (1 << length) - 1;\n", " bitsbuf >>>= length;\n", " bitsbuflen -= length;\n", " this.bitsbuf = bitsbuf;\n", " this.bitsbuflen = bitsbuflen;\n", " this.ip = ip;\n", " return octet;\n", " };\n", " /**\n", " * read huffman code using table\n", " * @param {Array} table huffman code table.\n", " * @return {number} huffman code.\n", " */\n", "\n", "\n", " Zlib$2.RawInflateStream.prototype.readCodeByTable = function (table) {\n", " var bitsbuf = this.bitsbuf;\n", " var bitsbuflen = this.bitsbuflen;\n", " var input = this.input;\n", " var ip = this.ip;\n", " /** @type {!(Array|Uint8Array)} huffman code table */\n", "\n", " var codeTable = table[0];\n", " /** @type {number} */\n", "\n", " var maxCodeLength = table[1];\n", " /** @type {number} input byte */\n", "\n", " var octet;\n", " /** @type {number} code length & code (16bit, 16bit) */\n", "\n", " var codeWithLength;\n", " /** @type {number} code bits length */\n", "\n", " var codeLength; // not enough buffer\n", "\n", " while (bitsbuflen < maxCodeLength) {\n", " if (input.length <= ip) {\n", " return -1;\n", " }\n", "\n", " octet = input[ip++];\n", " bitsbuf |= octet << bitsbuflen;\n", " bitsbuflen += 8;\n", " } // read max length\n", "\n", "\n", " codeWithLength = codeTable[bitsbuf & (1 << maxCodeLength) - 1];\n", " codeLength = codeWithLength >>> 16;\n", "\n", " if (codeLength > bitsbuflen) {\n", " throw new Error('invalid code length: ' + codeLength);\n", " }\n", "\n", " this.bitsbuf = bitsbuf >> codeLength;\n", " this.bitsbuflen = bitsbuflen - codeLength;\n", " this.ip = ip;\n", " return codeWithLength & 0xffff;\n", " };\n", " /**\n", " * read uncompressed block header\n", " */\n", "\n", "\n", " Zlib$2.RawInflateStream.prototype.readUncompressedBlockHeader = function () {\n", " /** @type {number} block length */\n", " var len;\n", " /** @type {number} number for check block length */\n", "\n", " var nlen;\n", " var input = this.input;\n", " var ip = this.ip;\n", " this.status = Zlib$2.RawInflateStream.Status.BLOCK_BODY_START;\n", "\n", " if (ip + 4 >= input.length) {\n", " return -1;\n", " }\n", "\n", " len = input[ip++] | input[ip++] << 8;\n", " nlen = input[ip++] | input[ip++] << 8; // check len & nlen\n", "\n", " if (len === ~nlen) {\n", " throw new Error('invalid uncompressed block header: length verify');\n", " } // skip buffered header bits\n", "\n", "\n", " this.bitsbuf = 0;\n", " this.bitsbuflen = 0;\n", " this.ip = ip;\n", " this.blockLength = len;\n", " this.status = Zlib$2.RawInflateStream.Status.BLOCK_BODY_END;\n", " };\n", " /**\n", " * parse uncompressed block.\n", " */\n", "\n", "\n", " Zlib$2.RawInflateStream.prototype.parseUncompressedBlock = function () {\n", " var input = this.input;\n", " var ip = this.ip;\n", " var output = this.output;\n", " var op = this.op;\n", " var len = this.blockLength;\n", " this.status = Zlib$2.RawInflateStream.Status.DECODE_BLOCK_START; // copy\n", " // XXX: とりあえず素直にコピー\n", "\n", " while (len--) {\n", " if (op === output.length) {\n", " output = this.expandBuffer({\n", " fixRatio: 2\n", " });\n", " } // not enough input buffer\n", "\n", "\n", " if (ip >= input.length) {\n", " this.ip = ip;\n", " this.op = op;\n", " this.blockLength = len + 1; // コピーしてないので戻す\n", "\n", " return -1;\n", " }\n", "\n", " output[op++] = input[ip++];\n", " }\n", "\n", " if (len < 0) {\n", " this.status = Zlib$2.RawInflateStream.Status.DECODE_BLOCK_END;\n", " }\n", "\n", " this.ip = ip;\n", " this.op = op;\n", " return 0;\n", " };\n", " /**\n", " * parse fixed huffman block.\n", " */\n", "\n", "\n", " Zlib$2.RawInflateStream.prototype.parseFixedHuffmanBlock = function () {\n", " this.status = Zlib$2.RawInflateStream.Status.BLOCK_BODY_START;\n", " this.litlenTable = Zlib$2.RawInflateStream.FixedLiteralLengthTable;\n", " this.distTable = Zlib$2.RawInflateStream.FixedDistanceTable;\n", " this.status = Zlib$2.RawInflateStream.Status.BLOCK_BODY_END;\n", " return 0;\n", " };\n", " /**\n", " * オブジェクトのコンテキストを別のプロパティに退避する.\n", " * @private\n", " */\n", "\n", "\n", " Zlib$2.RawInflateStream.prototype.save_ = function () {\n", " this.ip_ = this.ip;\n", " this.bitsbuflen_ = this.bitsbuflen;\n", " this.bitsbuf_ = this.bitsbuf;\n", " };\n", " /**\n", " * 別のプロパティに退避したコンテキストを復元する.\n", " * @private\n", " */\n", "\n", "\n", " Zlib$2.RawInflateStream.prototype.restore_ = function () {\n", " this.ip = this.ip_;\n", " this.bitsbuflen = this.bitsbuflen_;\n", " this.bitsbuf = this.bitsbuf_;\n", " };\n", " /**\n", " * parse dynamic huffman block.\n", " */\n", "\n", "\n", " Zlib$2.RawInflateStream.prototype.parseDynamicHuffmanBlock = function () {\n", " /** @type {number} number of literal and length codes. */\n", " var hlit;\n", " /** @type {number} number of distance codes. */\n", "\n", " var hdist;\n", " /** @type {number} number of code lengths. */\n", "\n", " var hclen;\n", " /** @type {!(Uint8Array|Array)} code lengths. */\n", "\n", " var codeLengths = new (Uint8Array )(Zlib$2.RawInflateStream.Order.length);\n", " /** @type {!Array} code lengths table. */\n", "\n", " var codeLengthsTable;\n", " this.status = Zlib$2.RawInflateStream.Status.BLOCK_BODY_START;\n", " this.save_();\n", " hlit = this.readBits(5) + 257;\n", " hdist = this.readBits(5) + 1;\n", " hclen = this.readBits(4) + 4;\n", "\n", " if (hlit < 0 || hdist < 0 || hclen < 0) {\n", " this.restore_();\n", " return -1;\n", " }\n", "\n", " try {\n", " parseDynamicHuffmanBlockImpl.call(this);\n", " } catch (e) {\n", " this.restore_();\n", " return -1;\n", " }\n", "\n", " function parseDynamicHuffmanBlockImpl() {\n", " /** @type {number} */\n", " var bits;\n", " var code;\n", " var prev = 0;\n", " var repeat;\n", " /** @type {!(Uint8Array|Array.)} code length table. */\n", "\n", " var lengthTable;\n", " /** @type {number} loop counter. */\n", "\n", " var i;\n", " /** @type {number} loop limit. */\n", "\n", " var il; // decode code lengths\n", "\n", " for (i = 0; i < hclen; ++i) {\n", " if ((bits = this.readBits(3)) < 0) {\n", " throw new Error('not enough input');\n", " }\n", "\n", " codeLengths[Zlib$2.RawInflateStream.Order[i]] = bits;\n", " } // decode length table\n", "\n", "\n", " codeLengthsTable = buildHuffmanTable$2(codeLengths);\n", " lengthTable = new (Uint8Array )(hlit + hdist);\n", "\n", " for (i = 0, il = hlit + hdist; i < il;) {\n", " code = this.readCodeByTable(codeLengthsTable);\n", "\n", " if (code < 0) {\n", " throw new Error('not enough input');\n", " }\n", "\n", " switch (code) {\n", " case 16:\n", " if ((bits = this.readBits(2)) < 0) {\n", " throw new Error('not enough input');\n", " }\n", "\n", " repeat = 3 + bits;\n", "\n", " while (repeat--) {\n", " lengthTable[i++] = prev;\n", " }\n", "\n", " break;\n", "\n", " case 17:\n", " if ((bits = this.readBits(3)) < 0) {\n", " throw new Error('not enough input');\n", " }\n", "\n", " repeat = 3 + bits;\n", "\n", " while (repeat--) {\n", " lengthTable[i++] = 0;\n", " }\n", "\n", " prev = 0;\n", " break;\n", "\n", " case 18:\n", " if ((bits = this.readBits(7)) < 0) {\n", " throw new Error('not enough input');\n", " }\n", "\n", " repeat = 11 + bits;\n", "\n", " while (repeat--) {\n", " lengthTable[i++] = 0;\n", " }\n", "\n", " prev = 0;\n", " break;\n", "\n", " default:\n", " lengthTable[i++] = code;\n", " prev = code;\n", " break;\n", " }\n", " } // literal and length code\n", " this.litlenTable = buildHuffmanTable$2(lengthTable.subarray(0, hlit)) ;\n", " this.distTable = buildHuffmanTable$2(lengthTable.subarray(hlit)) ;\n", " }\n", "\n", " this.status = Zlib$2.RawInflateStream.Status.BLOCK_BODY_END;\n", " return 0;\n", " };\n", " /**\n", " * decode huffman code (dynamic)\n", " * @return {(number|undefined)} -1 is error.\n", " */\n", "\n", "\n", " Zlib$2.RawInflateStream.prototype.decodeHuffman = function () {\n", " var output = this.output;\n", " var op = this.op;\n", " /** @type {number} huffman code. */\n", "\n", " var code;\n", " /** @type {number} table index. */\n", "\n", " var ti;\n", " /** @type {number} huffman code distination. */\n", "\n", " var codeDist;\n", " /** @type {number} huffman code length. */\n", "\n", " var codeLength;\n", " var litlen = this.litlenTable;\n", " var dist = this.distTable;\n", " var olength = output.length;\n", " var bits;\n", " this.status = Zlib$2.RawInflateStream.Status.DECODE_BLOCK_START;\n", "\n", " while (true) {\n", " this.save_();\n", " code = this.readCodeByTable(litlen);\n", "\n", " if (code < 0) {\n", " this.op = op;\n", " this.restore_();\n", " return -1;\n", " }\n", "\n", " if (code === 256) {\n", " break;\n", " } // literal\n", "\n", "\n", " if (code < 256) {\n", " if (op === olength) {\n", " output = this.expandBuffer();\n", " olength = output.length;\n", " }\n", "\n", " output[op++] = code;\n", " continue;\n", " } // length code\n", "\n", "\n", " ti = code - 257;\n", " codeLength = Zlib$2.RawInflateStream.LengthCodeTable[ti];\n", "\n", " if (Zlib$2.RawInflateStream.LengthExtraTable[ti] > 0) {\n", " bits = this.readBits(Zlib$2.RawInflateStream.LengthExtraTable[ti]);\n", "\n", " if (bits < 0) {\n", " this.op = op;\n", " this.restore_();\n", " return -1;\n", " }\n", "\n", " codeLength += bits;\n", " } // dist code\n", "\n", "\n", " code = this.readCodeByTable(dist);\n", "\n", " if (code < 0) {\n", " this.op = op;\n", " this.restore_();\n", " return -1;\n", " }\n", "\n", " codeDist = Zlib$2.RawInflateStream.DistCodeTable[code];\n", "\n", " if (Zlib$2.RawInflateStream.DistExtraTable[code] > 0) {\n", " bits = this.readBits(Zlib$2.RawInflateStream.DistExtraTable[code]);\n", "\n", " if (bits < 0) {\n", " this.op = op;\n", " this.restore_();\n", " return -1;\n", " }\n", "\n", " codeDist += bits;\n", " } // lz77 decode\n", "\n", "\n", " if (op + codeLength >= olength) {\n", " output = this.expandBuffer();\n", " olength = output.length;\n", " }\n", "\n", " while (codeLength--) {\n", " output[op] = output[op++ - codeDist];\n", " } // break\n", "\n", "\n", " if (this.ip === this.input.length) {\n", " this.op = op;\n", " return -1;\n", " }\n", " }\n", "\n", " while (this.bitsbuflen >= 8) {\n", " this.bitsbuflen -= 8;\n", " this.ip--;\n", " }\n", "\n", " this.op = op;\n", " this.status = Zlib$2.RawInflateStream.Status.DECODE_BLOCK_END;\n", " };\n", " /**\n", " * expand output buffer. (dynamic)\n", " * @param {Object=} opt_param option parameters.\n", " * @return {!(Array|Uint8Array)} output buffer pointer.\n", " */\n", "\n", "\n", " Zlib$2.RawInflateStream.prototype.expandBuffer = function (opt_param) {\n", " /** @type {!(Array|Uint8Array)} store buffer. */\n", " var buffer;\n", " /** @type {number} expantion ratio. */\n", "\n", " var ratio = this.input.length / this.ip + 1 | 0;\n", " /** @type {number} maximum number of huffman code. */\n", "\n", " var maxHuffCode;\n", " /** @type {number} new output buffer size. */\n", "\n", " var newSize;\n", " /** @type {number} max inflate size. */\n", "\n", " var maxInflateSize;\n", " var input = this.input;\n", " var output = this.output;\n", "\n", " if (opt_param) {\n", " if (typeof opt_param.fixRatio === 'number') {\n", " ratio = opt_param.fixRatio;\n", " }\n", "\n", " if (typeof opt_param.addRatio === 'number') {\n", " ratio += opt_param.addRatio;\n", " }\n", " } // calculate new buffer size\n", "\n", "\n", " if (ratio < 2) {\n", " maxHuffCode = (input.length - this.ip) / this.litlenTable[2];\n", " maxInflateSize = maxHuffCode / 2 * 258 | 0;\n", " newSize = maxInflateSize < output.length ? output.length + maxInflateSize : output.length << 1;\n", " } else {\n", " newSize = output.length * ratio;\n", " } // buffer expantion\n", "\n", "\n", " {\n", " buffer = new Uint8Array(newSize);\n", " buffer.set(output);\n", " }\n", "\n", " this.output = buffer;\n", " return this.output;\n", " };\n", " /**\n", " * concat output buffer. (dynamic)\n", " * @return {!(Array|Uint8Array)} output buffer.\n", " */\n", "\n", "\n", " Zlib$2.RawInflateStream.prototype.concatBuffer = function () {\n", " /** @type {!(Array|Uint8Array)} output buffer. */\n", " var buffer;\n", " /** @type {number} */\n", "\n", " var op = this.op;\n", " /** @type {Uint8Array} */\n", "\n", " var tmp;\n", "\n", " if (this.resize) {\n", " {\n", " buffer = new Uint8Array(this.output.subarray(this.sp, op));\n", " }\n", " } else {\n", " buffer = this.output.subarray(this.sp, op) ;\n", " }\n", "\n", " this.sp = op; // compaction\n", "\n", " if (op > Zlib$2.RawInflateStream.MaxBackwardLength + this.bufferSize) {\n", " this.op = this.sp = Zlib$2.RawInflateStream.MaxBackwardLength;\n", "\n", " {\n", " tmp =\n", " /** @type {Uint8Array} */\n", " this.output;\n", " this.output = new Uint8Array(this.bufferSize + Zlib$2.RawInflateStream.MaxBackwardLength);\n", " this.output.set(tmp.subarray(op - Zlib$2.RawInflateStream.MaxBackwardLength, op));\n", " }\n", " }\n", "\n", " return buffer;\n", " };\n", " /**\n", " * @constructor\n", " * @param {!(Uint8Array|Array)} input deflated buffer.\n", " * @param {Object=} opt_params option parameters.\n", " *\n", " * opt_params は以下のプロパティを指定する事ができます。\n", " * - index: input buffer の deflate コンテナの開始位置.\n", " * - blockSize: バッファのブロックサイズ.\n", " * - verify: 伸張が終わった後 adler-32 checksum の検証を行うか.\n", " * - bufferType: Zlib.Inflate.BufferType の値によってバッファの管理方法を指定する.\n", " * Zlib.Inflate.BufferType は Zlib.RawInflate.BufferType のエイリアス.\n", " */\n", "\n", "\n", " Zlib$2.Inflate = function (input, opt_params) {\n", " /** @type {number} */\n", "\n", " var cmf;\n", " /** @type {number} */\n", "\n", " var flg;\n", " /** @type {!(Uint8Array|Array)} */\n", "\n", " this.input = input;\n", " /** @type {number} */\n", "\n", " this.ip = 0;\n", " /** @type {Zlib.RawInflate} */\n", "\n", " this.rawinflate;\n", " /** @type {(boolean|undefined)} verify flag. */\n", "\n", " this.verify; // option parameters\n", "\n", " if (opt_params || !(opt_params = {})) {\n", " if (opt_params['index']) {\n", " this.ip = opt_params['index'];\n", " }\n", "\n", " if (opt_params['verify']) {\n", " this.verify = opt_params['verify'];\n", " }\n", " } // Compression Method and Flags\n", "\n", "\n", " cmf = input[this.ip++];\n", " flg = input[this.ip++]; // compression method\n", "\n", " switch (cmf & 0x0f) {\n", " case Zlib$2.CompressionMethod.DEFLATE:\n", " this.method = Zlib$2.CompressionMethod.DEFLATE;\n", " break;\n", "\n", " default:\n", " throw new Error('unsupported compression method');\n", " } // fcheck\n", "\n", "\n", " if (((cmf << 8) + flg) % 31 !== 0) {\n", " throw new Error('invalid fcheck flag:' + ((cmf << 8) + flg) % 31);\n", " } // fdict (not supported)\n", "\n", "\n", " if (flg & 0x20) {\n", " throw new Error('fdict flag is not supported');\n", " } // RawInflate\n", "\n", "\n", " this.rawinflate = new Zlib$2.RawInflate(input, {\n", " 'index': this.ip,\n", " 'bufferSize': opt_params['bufferSize'],\n", " 'bufferType': opt_params['bufferType'],\n", " 'resize': opt_params['resize']\n", " });\n", " };\n", " /**\n", " * @enum {number}\n", " */\n", "\n", "\n", " Zlib$2.Inflate.BufferType = Zlib$2.RawInflate.BufferType;\n", " /**\n", " * decompress.\n", " * @return {!(Uint8Array|Array)} inflated buffer.\n", " */\n", "\n", " Zlib$2.Inflate.prototype.decompress = function () {\n", " /** @type {!(Array|Uint8Array)} input buffer. */\n", " var input = this.input;\n", " /** @type {!(Uint8Array|Array)} inflated buffer. */\n", "\n", " var buffer;\n", " /** @type {number} adler-32 checksum */\n", "\n", " var adler32;\n", " buffer = this.rawinflate.decompress();\n", " this.ip = this.rawinflate.ip; // verify adler-32\n", "\n", " if (this.verify) {\n", " adler32 = (input[this.ip++] << 24 | input[this.ip++] << 16 | input[this.ip++] << 8 | input[this.ip++]) >>> 0;\n", "\n", " if (adler32 !== Zlib$2.Adler32(buffer)) {\n", " throw new Error('invalid adler-32 checksum');\n", " }\n", " }\n", "\n", " return buffer;\n", " };\n", " /* vim:set expandtab ts=2 sw=2 tw=80: */\n", "\n", " /**\n", " * @param {!(Uint8Array|Array)} input deflated buffer.\n", " * @constructor\n", " */\n", "\n", "\n", " Zlib$2.InflateStream = function (input) {\n", " /** @type {!(Uint8Array|Array)} */\n", " this.input = input === void 0 ? new (Uint8Array )() : input;\n", " /** @type {number} */\n", "\n", " this.ip = 0;\n", " /** @type {Zlib.RawInflateStream} */\n", "\n", " this.rawinflate = new Zlib$2.RawInflateStream(this.input, this.ip);\n", " /** @type {Zlib.CompressionMethod} */\n", "\n", " this.method;\n", " /** @type {!(Array|Uint8Array)} */\n", "\n", " this.output = this.rawinflate.output;\n", " };\n", " /**\n", " * decompress.\n", " * @return {!(Uint8Array|Array)} inflated buffer.\n", " */\n", "\n", "\n", " Zlib$2.InflateStream.prototype.decompress = function (input) {\n", " /** @type {!(Uint8Array|Array)} inflated buffer. */\n", " var buffer;\n", " // XXX Array, Uint8Array のチェックを行うか確認する\n", "\n", " if (input !== void 0) {\n", " {\n", " var tmp = new Uint8Array(this.input.length + input.length);\n", " tmp.set(this.input, 0);\n", " tmp.set(input, this.input.length);\n", " this.input = tmp;\n", " }\n", " }\n", "\n", " if (this.method === void 0) {\n", " if (this.readHeader() < 0) {\n", " return new (Uint8Array )();\n", " }\n", " }\n", "\n", " buffer = this.rawinflate.decompress(this.input, this.ip);\n", "\n", " if (this.rawinflate.ip !== 0) {\n", " this.input = this.input.subarray(this.rawinflate.ip) ;\n", " this.ip = 0;\n", " } // verify adler-32\n", "\n", " /*\n", " if (this.verify) {\n", " adler32 =\n", " input[this.ip++] << 24 | input[this.ip++] << 16 |\n", " input[this.ip++] << 8 | input[this.ip++];\n", " if (adler32 !== Zlib.Adler32(buffer)) {\n", " throw new Error('invalid adler-32 checksum');\n", " }\n", " }\n", " */\n", "\n", "\n", " return buffer;\n", " };\n", "\n", " Zlib$2.InflateStream.prototype.readHeader = function () {\n", " var ip = this.ip;\n", " var input = this.input; // Compression Method and Flags\n", "\n", " var cmf = input[ip++];\n", " var flg = input[ip++];\n", "\n", " if (cmf === void 0 || flg === void 0) {\n", " return -1;\n", " } // compression method\n", "\n", "\n", " switch (cmf & 0x0f) {\n", " case Zlib$2.CompressionMethod.DEFLATE:\n", " this.method = Zlib$2.CompressionMethod.DEFLATE;\n", " break;\n", "\n", " default:\n", " throw new Error('unsupported compression method');\n", " } // fcheck\n", "\n", "\n", " if (((cmf << 8) + flg) % 31 !== 0) {\n", " throw new Error('invalid fcheck flag:' + ((cmf << 8) + flg) % 31);\n", " } // fdict (not supported)\n", "\n", "\n", " if (flg & 0x20) {\n", " throw new Error('fdict flag is not supported');\n", " }\n", "\n", " this.ip = ip;\n", " };\n", " /**\n", " * @fileoverview GZIP (RFC1952) 展開コンテナ実装.\n", " */\n", "\n", " /**\n", " * @constructor\n", " * @param {!(Array|Uint8Array)} input input buffer.\n", " * @param {Object=} opt_params option parameters.\n", " */\n", "\n", "\n", " Zlib$2.Gunzip = function (input, opt_params) {\n", " /** @type {!(Array.|Uint8Array)} input buffer. */\n", " this.input = input;\n", " /** @type {number} input buffer pointer. */\n", "\n", " this.ip = 0;\n", " /** @type {Array.} */\n", "\n", " this.member = [];\n", " /** @type {boolean} */\n", "\n", " this.decompressed = false;\n", " };\n", " /**\n", " * @return {Array.}\n", " */\n", "\n", "\n", " Zlib$2.Gunzip.prototype.getMembers = function () {\n", " if (!this.decompressed) {\n", " this.decompress();\n", " }\n", "\n", " return this.member.slice();\n", " };\n", " /**\n", " * inflate gzip data.\n", " * @return {!(Array.|Uint8Array)} inflated buffer.\n", " */\n", "\n", "\n", " Zlib$2.Gunzip.prototype.decompress = function () {\n", " /** @type {number} input length. */\n", " var il = this.input.length;\n", "\n", " while (this.ip < il) {\n", " this.decodeMember();\n", " }\n", "\n", " this.decompressed = true;\n", " return this.concatMember();\n", " };\n", " /**\n", " * decode gzip member.\n", " */\n", "\n", "\n", " Zlib$2.Gunzip.prototype.decodeMember = function () {\n", " /** @type {Zlib.GunzipMember} */\n", " var member = new Zlib$2.GunzipMember();\n", " /** @type {number} */\n", "\n", " var isize;\n", " /** @type {Zlib.RawInflate} RawInflate implementation. */\n", "\n", " var rawinflate;\n", " /** @type {!(Array.|Uint8Array)} inflated data. */\n", "\n", " var inflated;\n", " /** @type {number} inflate size */\n", "\n", " var inflen;\n", " /** @type {number} character code */\n", "\n", " var c;\n", " /** @type {number} character index in string. */\n", "\n", " var ci;\n", " /** @type {Array.} character array. */\n", "\n", " var str;\n", " /** @type {number} modification time. */\n", "\n", " var mtime;\n", " /** @type {number} */\n", "\n", " var crc32;\n", " var input = this.input;\n", " var ip = this.ip;\n", " member.id1 = input[ip++];\n", " member.id2 = input[ip++]; // check signature\n", "\n", " if (member.id1 !== 0x1f || member.id2 !== 0x8b) {\n", " throw new Error('invalid file signature:' + member.id1 + ',' + member.id2);\n", " } // check compression method\n", "\n", "\n", " member.cm = input[ip++];\n", "\n", " switch (member.cm) {\n", " case 8:\n", " /* XXX: use Zlib const */\n", " break;\n", "\n", " default:\n", " throw new Error('unknown compression method: ' + member.cm);\n", " } // flags\n", "\n", "\n", " member.flg = input[ip++]; // modification time\n", "\n", " mtime = input[ip++] | input[ip++] << 8 | input[ip++] << 16 | input[ip++] << 24;\n", " member.mtime = new Date(mtime * 1000); // extra flags\n", "\n", " member.xfl = input[ip++]; // operating system\n", "\n", " member.os = input[ip++]; // extra\n", "\n", " if ((member.flg & Zlib$2.Gzip.FlagsMask.FEXTRA) > 0) {\n", " member.xlen = input[ip++] | input[ip++] << 8;\n", " ip = this.decodeSubField(ip, member.xlen);\n", " } // fname\n", "\n", "\n", " if ((member.flg & Zlib$2.Gzip.FlagsMask.FNAME) > 0) {\n", " for (str = [], ci = 0; (c = input[ip++]) > 0;) {\n", " str[ci++] = String.fromCharCode(c);\n", " }\n", "\n", " member.name = str.join('');\n", " } // fcomment\n", "\n", "\n", " if ((member.flg & Zlib$2.Gzip.FlagsMask.FCOMMENT) > 0) {\n", " for (str = [], ci = 0; (c = input[ip++]) > 0;) {\n", " str[ci++] = String.fromCharCode(c);\n", " }\n", "\n", " member.comment = str.join('');\n", " } // fhcrc\n", "\n", "\n", " if ((member.flg & Zlib$2.Gzip.FlagsMask.FHCRC) > 0) {\n", " member.crc16 = Zlib$2.CRC32.calc(input, 0, ip) & 0xffff;\n", "\n", " if (member.crc16 !== (input[ip++] | input[ip++] << 8)) {\n", " throw new Error('invalid header crc16');\n", " }\n", " } // isize を事前に取得すると展開後のサイズが分かるため、\n", " // inflate処理のバッファサイズが事前に分かり、高速になる\n", "\n", "\n", " isize = input[input.length - 4] | input[input.length - 3] << 8 | input[input.length - 2] << 16 | input[input.length - 1] << 24; // isize の妥当性チェック\n", " // ハフマン符号では最小 2-bit のため、最大で 1/4 になる\n", " // LZ77 符号では 長さと距離 2-Byte で最大 258-Byte を表現できるため、\n", " // 1/128 になるとする\n", " // ここから入力バッファの残りが isize の 512 倍以上だったら\n", " // サイズ指定のバッファ確保は行わない事とする\n", "\n", " if (input.length - ip -\n", " /* CRC-32 */\n", " 4 -\n", " /* ISIZE */\n", " 4 < isize * 512) {\n", " inflen = isize;\n", " } // compressed block\n", "\n", "\n", " rawinflate = new Zlib$2.RawInflate(input, {\n", " 'index': ip,\n", " 'bufferSize': inflen\n", " });\n", " member.data = inflated = rawinflate.decompress();\n", " ip = rawinflate.ip; // crc32\n", "\n", " member.crc32 = crc32 = (input[ip++] | input[ip++] << 8 | input[ip++] << 16 | input[ip++] << 24) >>> 0;\n", "\n", " if (Zlib$2.CRC32.calc(inflated) !== crc32) {\n", " throw new Error('invalid CRC-32 checksum: 0x' + Zlib$2.CRC32.calc(inflated).toString(16) + ' / 0x' + crc32.toString(16));\n", " } // input size\n", "\n", "\n", " member.isize = isize = (input[ip++] | input[ip++] << 8 | input[ip++] << 16 | input[ip++] << 24) >>> 0;\n", "\n", " if ((inflated.length & 0xffffffff) !== isize) {\n", " throw new Error('invalid input size: ' + (inflated.length & 0xffffffff) + ' / ' + isize);\n", " }\n", "\n", " this.member.push(member);\n", " this.ip = ip;\n", " };\n", " /**\n", " * サブフィールドのデコード\n", " * XXX: 現在は何もせずスキップする\n", " */\n", "\n", "\n", " Zlib$2.Gunzip.prototype.decodeSubField = function (ip, length) {\n", " return ip + length;\n", " };\n", " /**\n", " * @return {!(Array.|Uint8Array)}\n", " */\n", "\n", "\n", " Zlib$2.Gunzip.prototype.concatMember = function () {\n", " /** @type {Array.} */\n", " var member = this.member;\n", " /** @type {number} */\n", "\n", " var i;\n", " /** @type {number} */\n", "\n", " var il;\n", " /** @type {number} */\n", "\n", " var p = 0;\n", " /** @type {number} */\n", "\n", " var size = 0;\n", " /** @type {!(Array.|Uint8Array)} */\n", "\n", " var buffer;\n", "\n", " for (i = 0, il = member.length; i < il; ++i) {\n", " size += member[i].data.length;\n", " }\n", "\n", " {\n", " buffer = new Uint8Array(size);\n", "\n", " for (i = 0; i < il; ++i) {\n", " buffer.set(member[i].data, p);\n", " p += member[i].data.length;\n", " }\n", " }\n", "\n", " return buffer;\n", " };\n", " /**\n", " * @constructor\n", " */\n", "\n", "\n", " Zlib$2.GunzipMember = function () {\n", " /** @type {number} signature first byte. */\n", " this.id1;\n", " /** @type {number} signature second byte. */\n", "\n", " this.id2;\n", " /** @type {number} compression method. */\n", "\n", " this.cm;\n", " /** @type {number} flags. */\n", "\n", " this.flg;\n", " /** @type {Date} modification time. */\n", "\n", " this.mtime;\n", " /** @type {number} extra flags. */\n", "\n", " this.xfl;\n", " /** @type {number} operating system number. */\n", "\n", " this.os;\n", " /** @type {number} CRC-16 value for FHCRC flag. */\n", "\n", " this.crc16;\n", " /** @type {number} extra length. */\n", "\n", " this.xlen;\n", " /** @type {number} CRC-32 value for verification. */\n", "\n", " this.crc32;\n", " /** @type {number} input size modulo 32 value. */\n", "\n", " this.isize;\n", " /** @type {string} filename. */\n", "\n", " this.name;\n", " /** @type {string} comment. */\n", "\n", " this.comment;\n", " /** @type {!(Uint8Array|Array.)} */\n", "\n", " this.data;\n", " };\n", "\n", " Zlib$2.GunzipMember.prototype.getName = function () {\n", " return this.name;\n", " };\n", "\n", " Zlib$2.GunzipMember.prototype.getData = function () {\n", " return this.data;\n", " };\n", "\n", " Zlib$2.GunzipMember.prototype.getMtime = function () {\n", " return this.mtime;\n", " };\n", " /**\n", " * @fileoverview GZIP (RFC1952) 実装.\n", " */\n", "\n", " /**\n", " * @constructor\n", " * @param {!(Array|Uint8Array)} input input buffer.\n", " * @param {Object=} opt_params option parameters.\n", " */\n", "\n", "\n", " Zlib$2.Gzip = function (input, opt_params) {\n", " /** @type {!(Array.|Uint8Array)} input buffer. */\n", " this.input = input;\n", " /** @type {number} input buffer pointer. */\n", "\n", " this.ip = 0;\n", " /** @type {!(Array.|Uint8Array)} output buffer. */\n", "\n", " this.output;\n", " /** @type {number} output buffer. */\n", "\n", " this.op = 0;\n", " /** @type {!Object} flags option flags. */\n", "\n", " this.flags = {};\n", " /** @type {!string} filename. */\n", "\n", " this.filename;\n", " /** @type {!string} comment. */\n", "\n", " this.comment;\n", " /** @type {!Object} deflate options. */\n", "\n", " this.deflateOptions; // option parameters\n", "\n", " if (opt_params) {\n", " if (opt_params['flags']) {\n", " this.flags = opt_params['flags'];\n", " }\n", "\n", " if (typeof opt_params['filename'] === 'string') {\n", " this.filename = opt_params['filename'];\n", " }\n", "\n", " if (typeof opt_params['comment'] === 'string') {\n", " this.comment = opt_params['comment'];\n", " }\n", "\n", " if (opt_params['deflateOptions']) {\n", " this.deflateOptions = opt_params['deflateOptions'];\n", " }\n", " }\n", "\n", " if (!this.deflateOptions) {\n", " this.deflateOptions = {};\n", " }\n", " };\n", " /**\n", " * @type {number}\n", " * @const\n", " */\n", "\n", "\n", " Zlib$2.Gzip.DefaultBufferSize = 0x8000;\n", " /**\n", " * encode gzip members.\n", " * @return {!(Array|Uint8Array)} gzip binary array.\n", " */\n", "\n", " Zlib$2.Gzip.prototype.compress = function () {\n", " /** @type {number} flags. */\n", " var flg;\n", " /** @type {number} modification time. */\n", "\n", " var mtime;\n", " /** @type {number} CRC-16 value for FHCRC flag. */\n", "\n", " var crc16;\n", " /** @type {number} CRC-32 value for verification. */\n", "\n", " var crc32;\n", " /** @type {!Zlib.RawDeflate} raw deflate object. */\n", "\n", " var rawdeflate;\n", " /** @type {number} character code */\n", "\n", " var c;\n", " /** @type {number} loop counter. */\n", "\n", " var i;\n", " /** @type {number} loop limiter. */\n", "\n", " var il;\n", " /** @type {!(Array|Uint8Array)} output buffer. */\n", "\n", " var output = new (Uint8Array )(Zlib$2.Gzip.DefaultBufferSize);\n", " /** @type {number} output buffer pointer. */\n", "\n", " var op = 0;\n", " var input = this.input;\n", " var ip = this.ip;\n", " var filename = this.filename;\n", " var comment = this.comment; // check signature\n", "\n", " output[op++] = 0x1f;\n", " output[op++] = 0x8b; // check compression method\n", "\n", " output[op++] = 8;\n", " /* XXX: use Zlib const */\n", " // flags\n", "\n", " flg = 0;\n", " if (this.flags['fname']) flg |= Zlib$2.Gzip.FlagsMask.FNAME;\n", " if (this.flags['fcomment']) flg |= Zlib$2.Gzip.FlagsMask.FCOMMENT;\n", " if (this.flags['fhcrc']) flg |= Zlib$2.Gzip.FlagsMask.FHCRC; // XXX: FTEXT\n", " // XXX: FEXTRA\n", "\n", " output[op++] = flg; // modification time\n", "\n", " mtime = (Date.now ? Date.now() : +new Date()) / 1000 | 0;\n", " output[op++] = mtime & 0xff;\n", " output[op++] = mtime >>> 8 & 0xff;\n", " output[op++] = mtime >>> 16 & 0xff;\n", " output[op++] = mtime >>> 24 & 0xff; // extra flags\n", "\n", " output[op++] = 0; // operating system\n", "\n", " output[op++] = Zlib$2.Gzip.OperatingSystem.UNKNOWN; // extra\n", "\n", " /* NOP */\n", " // fname\n", "\n", " if (this.flags['fname'] !== void 0) {\n", " for (i = 0, il = filename.length; i < il; ++i) {\n", " c = filename.charCodeAt(i);\n", "\n", " if (c > 0xff) {\n", " output[op++] = c >>> 8 & 0xff;\n", " }\n", "\n", " output[op++] = c & 0xff;\n", " }\n", "\n", " output[op++] = 0; // null termination\n", " } // fcomment\n", "\n", "\n", " if (this.flags['comment']) {\n", " for (i = 0, il = comment.length; i < il; ++i) {\n", " c = comment.charCodeAt(i);\n", "\n", " if (c > 0xff) {\n", " output[op++] = c >>> 8 & 0xff;\n", " }\n", "\n", " output[op++] = c & 0xff;\n", " }\n", "\n", " output[op++] = 0; // null termination\n", " } // fhcrc\n", "\n", "\n", " if (this.flags['fhcrc']) {\n", " crc16 = Zlib$2.CRC32.calc(output, 0, op) & 0xffff;\n", " output[op++] = crc16 & 0xff;\n", " output[op++] = crc16 >>> 8 & 0xff;\n", " } // add compress option\n", "\n", "\n", " this.deflateOptions['outputBuffer'] = output;\n", " this.deflateOptions['outputIndex'] = op; // compress\n", "\n", " rawdeflate = new Zlib$2.RawDeflate(input, this.deflateOptions);\n", " output = rawdeflate.compress();\n", " op = rawdeflate.op; // expand buffer\n", "\n", " {\n", " if (op + 8 > output.buffer.byteLength) {\n", " this.output = new Uint8Array(op + 8);\n", " this.output.set(new Uint8Array(output.buffer));\n", " output = this.output;\n", " } else {\n", " output = new Uint8Array(output.buffer);\n", " }\n", " } // crc32\n", "\n", "\n", " crc32 = Zlib$2.CRC32.calc(input);\n", " output[op++] = crc32 & 0xff;\n", " output[op++] = crc32 >>> 8 & 0xff;\n", " output[op++] = crc32 >>> 16 & 0xff;\n", " output[op++] = crc32 >>> 24 & 0xff; // input size\n", "\n", " il = input.length;\n", " output[op++] = il & 0xff;\n", " output[op++] = il >>> 8 & 0xff;\n", " output[op++] = il >>> 16 & 0xff;\n", " output[op++] = il >>> 24 & 0xff;\n", " this.ip = ip;\n", "\n", " if (op < output.length) {\n", " this.output = output = output.subarray(0, op);\n", " }\n", "\n", " return output;\n", " };\n", " /** @enum {number} */\n", "\n", "\n", " Zlib$2.Gzip.OperatingSystem = {\n", " FAT: 0,\n", " AMIGA: 1,\n", " VMS: 2,\n", " UNIX: 3,\n", " VM_CMS: 4,\n", " ATARI_TOS: 5,\n", " HPFS: 6,\n", " MACINTOSH: 7,\n", " Z_SYSTEM: 8,\n", " CP_M: 9,\n", " TOPS_20: 10,\n", " NTFS: 11,\n", " QDOS: 12,\n", " ACORN_RISCOS: 13,\n", " UNKNOWN: 255\n", " };\n", " /** @enum {number} */\n", "\n", " Zlib$2.Gzip.FlagsMask = {\n", " FTEXT: 0x01,\n", " FHCRC: 0x02,\n", " FEXTRA: 0x04,\n", " FNAME: 0x08,\n", " FCOMMENT: 0x10\n", " };\n", " /**\n", " * @fileoverview Heap Sort 実装. ハフマン符号化で使用する.\n", " */\n", "\n", " /**\n", " * カスタムハフマン符号で使用するヒープ実装\n", " * @param {number} length ヒープサイズ.\n", " * @constructor\n", " */\n", "\n", " Zlib$2.Heap = function (length) {\n", " this.buffer = new (Uint16Array )(length * 2);\n", " this.length = 0;\n", " };\n", " /**\n", " * 親ノードの index 取得\n", " * @param {number} index 子ノードの index.\n", " * @return {number} 親ノードの index.\n", " *\n", " */\n", "\n", "\n", " Zlib$2.Heap.prototype.getParent = function (index) {\n", " return ((index - 2) / 4 | 0) * 2;\n", " };\n", " /**\n", " * 子ノードの index 取得\n", " * @param {number} index 親ノードの index.\n", " * @return {number} 子ノードの index.\n", " */\n", "\n", "\n", " Zlib$2.Heap.prototype.getChild = function (index) {\n", " return 2 * index + 2;\n", " };\n", " /**\n", " * Heap に値を追加する\n", " * @param {number} index キー index.\n", " * @param {number} value 値.\n", " * @return {number} 現在のヒープ長.\n", " */\n", "\n", "\n", " Zlib$2.Heap.prototype.push = function (index, value) {\n", " var current,\n", " parent,\n", " heap = this.buffer,\n", " swap;\n", " current = this.length;\n", " heap[this.length++] = value;\n", " heap[this.length++] = index; // ルートノードにたどり着くまで入れ替えを試みる\n", "\n", " while (current > 0) {\n", " parent = this.getParent(current); // 親ノードと比較して親の方が小さければ入れ替える\n", "\n", " if (heap[current] > heap[parent]) {\n", " swap = heap[current];\n", " heap[current] = heap[parent];\n", " heap[parent] = swap;\n", " swap = heap[current + 1];\n", " heap[current + 1] = heap[parent + 1];\n", " heap[parent + 1] = swap;\n", " current = parent; // 入れ替えが必要なくなったらそこで抜ける\n", " } else {\n", " break;\n", " }\n", " }\n", "\n", " return this.length;\n", " };\n", " /**\n", " * Heapから一番大きい値を返す\n", " * @return {{index: number, value: number, length: number}} {index: キーindex,\n", " * value: 値, length: ヒープ長} の Object.\n", " */\n", "\n", "\n", " Zlib$2.Heap.prototype.pop = function () {\n", " var index,\n", " value,\n", " heap = this.buffer,\n", " swap,\n", " current,\n", " parent;\n", " value = heap[0];\n", " index = heap[1]; // 後ろから値を取る\n", "\n", " this.length -= 2;\n", " heap[0] = heap[this.length];\n", " heap[1] = heap[this.length + 1];\n", " parent = 0; // ルートノードから下がっていく\n", "\n", " while (true) {\n", " current = this.getChild(parent); // 範囲チェック\n", "\n", " if (current >= this.length) {\n", " break;\n", " } // 隣のノードと比較して、隣の方が値が大きければ隣を現在ノードとして選択\n", "\n", "\n", " if (current + 2 < this.length && heap[current + 2] > heap[current]) {\n", " current += 2;\n", " } // 親ノードと比較して親の方が小さい場合は入れ替える\n", "\n", "\n", " if (heap[current] > heap[parent]) {\n", " swap = heap[parent];\n", " heap[parent] = heap[current];\n", " heap[current] = swap;\n", " swap = heap[parent + 1];\n", " heap[parent + 1] = heap[current + 1];\n", " heap[current + 1] = swap;\n", " } else {\n", " break;\n", " }\n", "\n", " parent = current;\n", " }\n", "\n", " return {\n", " index: index,\n", " value: value,\n", " length: this.length\n", " };\n", " };\n", " /* vim:set expandtab ts=2 sw=2 tw=80: */\n", "\n", " /**\n", " * @fileoverview Deflate (RFC1951) 符号化アルゴリズム実装.\n", " */\n", "\n", " /**\n", " * Raw Deflate 実装\n", " *\n", " * @constructor\n", " * @param {!(Array.|Uint8Array)} input 符号化する対象のバッファ.\n", " * @param {Object=} opt_params option parameters.\n", " *\n", " * typed array が使用可能なとき、outputBuffer が Array は自動的に Uint8Array に\n", " * 変換されます.\n", " * 別のオブジェクトになるため出力バッファを参照している変数などは\n", " * 更新する必要があります.\n", " */\n", "\n", "\n", " Zlib$2.RawDeflate = function (input, opt_params) {\n", " /** @type {Zlib.RawDeflate.CompressionType} */\n", " this.compressionType = Zlib$2.RawDeflate.CompressionType.DYNAMIC;\n", " /** @type {number} */\n", "\n", " this.lazy = 0;\n", " /** @type {!(Array.|Uint32Array)} */\n", "\n", " this.freqsLitLen;\n", " /** @type {!(Array.|Uint32Array)} */\n", "\n", " this.freqsDist;\n", " /** @type {!(Array.|Uint8Array)} */\n", "\n", " this.input = input instanceof Array ? new Uint8Array(input) : input;\n", " /** @type {!(Array.|Uint8Array)} output output buffer. */\n", "\n", " this.output;\n", " /** @type {number} pos output buffer position. */\n", "\n", " this.op = 0; // option parameters\n", "\n", " if (opt_params) {\n", " if (opt_params['lazy']) {\n", " this.lazy = opt_params['lazy'];\n", " }\n", "\n", " if (typeof opt_params['compressionType'] === 'number') {\n", " this.compressionType = opt_params['compressionType'];\n", " }\n", "\n", " if (opt_params['outputBuffer']) {\n", " this.output = opt_params['outputBuffer'] instanceof Array ? new Uint8Array(opt_params['outputBuffer']) : opt_params['outputBuffer'];\n", " }\n", "\n", " if (typeof opt_params['outputIndex'] === 'number') {\n", " this.op = opt_params['outputIndex'];\n", " }\n", " }\n", "\n", " if (!this.output) {\n", " this.output = new (Uint8Array )(0x8000);\n", " }\n", " };\n", " /**\n", " * @enum {number}\n", " */\n", "\n", "\n", " Zlib$2.RawDeflate.CompressionType = {\n", " NONE: 0,\n", " FIXED: 1,\n", " DYNAMIC: 2,\n", " RESERVED: 3\n", " };\n", " /**\n", " * LZ77 の最小マッチ長\n", " * @const\n", " * @type {number}\n", " */\n", "\n", " Zlib$2.RawDeflate.Lz77MinLength = 3;\n", " /**\n", " * LZ77 の最大マッチ長\n", " * @const\n", " * @type {number}\n", " */\n", "\n", " Zlib$2.RawDeflate.Lz77MaxLength = 258;\n", " /**\n", " * LZ77 のウィンドウサイズ\n", " * @const\n", " * @type {number}\n", " */\n", "\n", " Zlib$2.RawDeflate.WindowSize = 0x8000;\n", " /**\n", " * 最長の符号長\n", " * @const\n", " * @type {number}\n", " */\n", "\n", " Zlib$2.RawDeflate.MaxCodeLength = 16;\n", " /**\n", " * ハフマン符号の最大数値\n", " * @const\n", " * @type {number}\n", " */\n", "\n", " Zlib$2.RawDeflate.HUFMAX = 286;\n", " /**\n", " * 固定ハフマン符号の符号化テーブル\n", " * @const\n", " * @type {Array.>}\n", " */\n", "\n", " Zlib$2.RawDeflate.FixedHuffmanTable = function () {\n", " var table = [],\n", " i;\n", "\n", " for (i = 0; i < 288; i++) {\n", " switch (true) {\n", " case i <= 143:\n", " table.push([i + 0x030, 8]);\n", " break;\n", "\n", " case i <= 255:\n", " table.push([i - 144 + 0x190, 9]);\n", " break;\n", "\n", " case i <= 279:\n", " table.push([i - 256 + 0x000, 7]);\n", " break;\n", "\n", " case i <= 287:\n", " table.push([i - 280 + 0x0C0, 8]);\n", " break;\n", "\n", " default:\n", " throw 'invalid literal: ' + i;\n", " }\n", " }\n", "\n", " return table;\n", " }();\n", " /**\n", " * DEFLATE ブロックの作成\n", " * @return {!(Array.|Uint8Array)} 圧縮済み byte array.\n", " */\n", "\n", "\n", " Zlib$2.RawDeflate.prototype.compress = function () {\n", " /** @type {!(Array.|Uint8Array)} */\n", " var blockArray;\n", " /** @type {number} */\n", "\n", " var position;\n", " /** @type {number} */\n", "\n", " var length;\n", " var input = this.input; // compression\n", "\n", " switch (this.compressionType) {\n", " case Zlib$2.RawDeflate.CompressionType.NONE:\n", " // each 65535-Byte (length header: 16-bit)\n", " for (position = 0, length = input.length; position < length;) {\n", " blockArray = input.subarray(position, position + 0xffff) ;\n", " position += blockArray.length;\n", " this.makeNocompressBlock(blockArray, position === length);\n", " }\n", "\n", " break;\n", "\n", " case Zlib$2.RawDeflate.CompressionType.FIXED:\n", " this.output = this.makeFixedHuffmanBlock(input, true);\n", " this.op = this.output.length;\n", " break;\n", "\n", " case Zlib$2.RawDeflate.CompressionType.DYNAMIC:\n", " this.output = this.makeDynamicHuffmanBlock(input, true);\n", " this.op = this.output.length;\n", " break;\n", "\n", " default:\n", " throw 'invalid compression type';\n", " }\n", "\n", " return this.output;\n", " };\n", " /**\n", " * 非圧縮ブロックの作成\n", " * @param {!(Array.|Uint8Array)} blockArray ブロックデータ byte array.\n", " * @param {!boolean} isFinalBlock 最後のブロックならばtrue.\n", " * @return {!(Array.|Uint8Array)} 非圧縮ブロック byte array.\n", " */\n", "\n", "\n", " Zlib$2.RawDeflate.prototype.makeNocompressBlock = function (blockArray, isFinalBlock) {\n", " /** @type {number} */\n", " var bfinal;\n", " /** @type {Zlib.RawDeflate.CompressionType} */\n", "\n", " var btype;\n", " /** @type {number} */\n", "\n", " var len;\n", " /** @type {number} */\n", "\n", " var nlen;\n", " var output = this.output;\n", " var op = this.op; // expand buffer\n", "\n", " {\n", " output = new Uint8Array(this.output.buffer);\n", "\n", " while (output.length <= op + blockArray.length + 5) {\n", " output = new Uint8Array(output.length << 1);\n", " }\n", "\n", " output.set(this.output);\n", " } // header\n", "\n", "\n", " bfinal = isFinalBlock ? 1 : 0;\n", " btype = Zlib$2.RawDeflate.CompressionType.NONE;\n", " output[op++] = bfinal | btype << 1; // length\n", "\n", " len = blockArray.length;\n", " nlen = ~len + 0x10000 & 0xffff;\n", " output[op++] = len & 0xff;\n", " output[op++] = len >>> 8 & 0xff;\n", " output[op++] = nlen & 0xff;\n", " output[op++] = nlen >>> 8 & 0xff; // copy buffer\n", "\n", " {\n", " output.set(blockArray, op);\n", " op += blockArray.length;\n", " output = output.subarray(0, op);\n", " }\n", "\n", " this.op = op;\n", " this.output = output;\n", " return output;\n", " };\n", " /**\n", " * 固定ハフマンブロックの作成\n", " * @param {!(Array.|Uint8Array)} blockArray ブロックデータ byte array.\n", " * @param {!boolean} isFinalBlock 最後のブロックならばtrue.\n", " * @return {!(Array.|Uint8Array)} 固定ハフマン符号化ブロック byte array.\n", " */\n", "\n", "\n", " Zlib$2.RawDeflate.prototype.makeFixedHuffmanBlock = function (blockArray, isFinalBlock) {\n", " /** @type {Zlib.BitStream} */\n", " var stream = new Zlib$2.BitStream(new Uint8Array(this.output.buffer) , this.op);\n", " /** @type {number} */\n", "\n", " var bfinal;\n", " /** @type {Zlib.RawDeflate.CompressionType} */\n", "\n", " var btype;\n", " /** @type {!(Array.|Uint16Array)} */\n", "\n", " var data; // header\n", "\n", " bfinal = isFinalBlock ? 1 : 0;\n", " btype = Zlib$2.RawDeflate.CompressionType.FIXED;\n", " stream.writeBits(bfinal, 1, true);\n", " stream.writeBits(btype, 2, true);\n", " data = this.lz77(blockArray);\n", " this.fixedHuffman(data, stream);\n", " return stream.finish();\n", " };\n", " /**\n", " * 動的ハフマンブロックの作成\n", " * @param {!(Array.|Uint8Array)} blockArray ブロックデータ byte array.\n", " * @param {!boolean} isFinalBlock 最後のブロックならばtrue.\n", " * @return {!(Array.|Uint8Array)} 動的ハフマン符号ブロック byte array.\n", " */\n", "\n", "\n", " Zlib$2.RawDeflate.prototype.makeDynamicHuffmanBlock = function (blockArray, isFinalBlock) {\n", " /** @type {Zlib.BitStream} */\n", " var stream = new Zlib$2.BitStream(new Uint8Array(this.output.buffer) , this.op);\n", " /** @type {number} */\n", "\n", " var bfinal;\n", " /** @type {Zlib.RawDeflate.CompressionType} */\n", "\n", " var btype;\n", " /** @type {!(Array.|Uint16Array)} */\n", "\n", " var data;\n", " /** @type {number} */\n", "\n", " var hlit;\n", " /** @type {number} */\n", "\n", " var hdist;\n", " /** @type {number} */\n", "\n", " var hclen;\n", " /** @const @type {Array.} */\n", "\n", " var hclenOrder = [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15];\n", " /** @type {!(Array.|Uint8Array)} */\n", "\n", " var litLenLengths;\n", " /** @type {!(Array.|Uint16Array)} */\n", "\n", " var litLenCodes;\n", " /** @type {!(Array.|Uint8Array)} */\n", "\n", " var distLengths;\n", " /** @type {!(Array.|Uint16Array)} */\n", "\n", " var distCodes;\n", " /** @type {{\n", " * codes: !(Array.|Uint32Array),\n", " * freqs: !(Array.|Uint8Array)\n", " * }} */\n", "\n", " var treeSymbols;\n", " /** @type {!(Array.|Uint8Array)} */\n", "\n", " var treeLengths;\n", " /** @type {Array} */\n", "\n", " var transLengths = new Array(19);\n", " /** @type {!(Array.|Uint16Array)} */\n", "\n", " var treeCodes;\n", " /** @type {number} */\n", "\n", " var code;\n", " /** @type {number} */\n", "\n", " var bitlen;\n", " /** @type {number} */\n", "\n", " var i;\n", " /** @type {number} */\n", "\n", " var il; // header\n", "\n", " bfinal = isFinalBlock ? 1 : 0;\n", " btype = Zlib$2.RawDeflate.CompressionType.DYNAMIC;\n", " stream.writeBits(bfinal, 1, true);\n", " stream.writeBits(btype, 2, true);\n", " data = this.lz77(blockArray); // リテラル・長さ, 距離のハフマン符号と符号長の算出\n", "\n", " litLenLengths = this.getLengths_(this.freqsLitLen, 15);\n", " litLenCodes = this.getCodesFromLengths_(litLenLengths);\n", " distLengths = this.getLengths_(this.freqsDist, 7);\n", " distCodes = this.getCodesFromLengths_(distLengths); // HLIT, HDIST の決定\n", "\n", " for (hlit = 286; hlit > 257 && litLenLengths[hlit - 1] === 0; hlit--) {}\n", "\n", " for (hdist = 30; hdist > 1 && distLengths[hdist - 1] === 0; hdist--) {} // HCLEN\n", "\n", "\n", " treeSymbols = this.getTreeSymbols_(hlit, litLenLengths, hdist, distLengths);\n", " treeLengths = this.getLengths_(treeSymbols.freqs, 7);\n", "\n", " for (i = 0; i < 19; i++) {\n", " transLengths[i] = treeLengths[hclenOrder[i]];\n", " }\n", "\n", " for (hclen = 19; hclen > 4 && transLengths[hclen - 1] === 0; hclen--) {}\n", "\n", " treeCodes = this.getCodesFromLengths_(treeLengths); // 出力\n", "\n", " stream.writeBits(hlit - 257, 5, true);\n", " stream.writeBits(hdist - 1, 5, true);\n", " stream.writeBits(hclen - 4, 4, true);\n", "\n", " for (i = 0; i < hclen; i++) {\n", " stream.writeBits(transLengths[i], 3, true);\n", " } // ツリーの出力\n", "\n", "\n", " for (i = 0, il = treeSymbols.codes.length; i < il; i++) {\n", " code = treeSymbols.codes[i];\n", " stream.writeBits(treeCodes[code], treeLengths[code], true); // extra bits\n", "\n", " if (code >= 16) {\n", " i++;\n", "\n", " switch (code) {\n", " case 16:\n", " bitlen = 2;\n", " break;\n", "\n", " case 17:\n", " bitlen = 3;\n", " break;\n", "\n", " case 18:\n", " bitlen = 7;\n", " break;\n", "\n", " default:\n", " throw 'invalid code: ' + code;\n", " }\n", "\n", " stream.writeBits(treeSymbols.codes[i], bitlen, true);\n", " }\n", " }\n", "\n", " this.dynamicHuffman(data, [litLenCodes, litLenLengths], [distCodes, distLengths], stream);\n", " return stream.finish();\n", " };\n", " /**\n", " * 動的ハフマン符号化(カスタムハフマンテーブル)\n", " * @param {!(Array.|Uint16Array)} dataArray LZ77 符号化済み byte array.\n", " * @param {!Zlib.BitStream} stream 書き込み用ビットストリーム.\n", " * @return {!Zlib.BitStream} ハフマン符号化済みビットストリームオブジェクト.\n", " */\n", "\n", "\n", " Zlib$2.RawDeflate.prototype.dynamicHuffman = function (dataArray, litLen, dist, stream) {\n", " /** @type {number} */\n", " var index;\n", " /** @type {number} */\n", "\n", " var length;\n", " /** @type {number} */\n", "\n", " var literal;\n", " /** @type {number} */\n", "\n", " var code;\n", " /** @type {number} */\n", "\n", " var litLenCodes;\n", " /** @type {number} */\n", "\n", " var litLenLengths;\n", " /** @type {number} */\n", "\n", " var distCodes;\n", " /** @type {number} */\n", "\n", " var distLengths;\n", " litLenCodes = litLen[0];\n", " litLenLengths = litLen[1];\n", " distCodes = dist[0];\n", " distLengths = dist[1]; // 符号を BitStream に書き込んでいく\n", "\n", " for (index = 0, length = dataArray.length; index < length; ++index) {\n", " literal = dataArray[index]; // literal or length\n", "\n", " stream.writeBits(litLenCodes[literal], litLenLengths[literal], true); // 長さ・距離符号\n", "\n", " if (literal > 256) {\n", " // length extra\n", " stream.writeBits(dataArray[++index], dataArray[++index], true); // distance\n", "\n", " code = dataArray[++index];\n", " stream.writeBits(distCodes[code], distLengths[code], true); // distance extra\n", "\n", " stream.writeBits(dataArray[++index], dataArray[++index], true); // 終端\n", " } else if (literal === 256) {\n", " break;\n", " }\n", " }\n", "\n", " return stream;\n", " };\n", " /**\n", " * 固定ハフマン符号化\n", " * @param {!(Array.|Uint16Array)} dataArray LZ77 符号化済み byte array.\n", " * @param {!Zlib.BitStream} stream 書き込み用ビットストリーム.\n", " * @return {!Zlib.BitStream} ハフマン符号化済みビットストリームオブジェクト.\n", " */\n", "\n", "\n", " Zlib$2.RawDeflate.prototype.fixedHuffman = function (dataArray, stream) {\n", " /** @type {number} */\n", " var index;\n", " /** @type {number} */\n", "\n", " var length;\n", " /** @type {number} */\n", "\n", " var literal; // 符号を BitStream に書き込んでいく\n", "\n", " for (index = 0, length = dataArray.length; index < length; index++) {\n", " literal = dataArray[index]; // 符号の書き込み\n", "\n", " Zlib$2.BitStream.prototype.writeBits.apply(stream, Zlib$2.RawDeflate.FixedHuffmanTable[literal]); // 長さ・距離符号\n", "\n", " if (literal > 0x100) {\n", " // length extra\n", " stream.writeBits(dataArray[++index], dataArray[++index], true); // distance\n", "\n", " stream.writeBits(dataArray[++index], 5); // distance extra\n", "\n", " stream.writeBits(dataArray[++index], dataArray[++index], true); // 終端\n", " } else if (literal === 0x100) {\n", " break;\n", " }\n", " }\n", "\n", " return stream;\n", " };\n", " /**\n", " * マッチ情報\n", " * @param {!number} length マッチした長さ.\n", " * @param {!number} backwardDistance マッチ位置との距離.\n", " * @constructor\n", " */\n", "\n", "\n", " Zlib$2.RawDeflate.Lz77Match = function (length, backwardDistance) {\n", " /** @type {number} match length. */\n", " this.length = length;\n", " /** @type {number} backward distance. */\n", "\n", " this.backwardDistance = backwardDistance;\n", " };\n", " /**\n", " * 長さ符号テーブル.\n", " * [コード, 拡張ビット, 拡張ビット長] の配列となっている.\n", " * @const\n", " * @type {!(Array.|Uint32Array)}\n", " */\n", "\n", "\n", " Zlib$2.RawDeflate.Lz77Match.LengthCodeTable = function (table) {\n", " return new Uint32Array(table) ;\n", " }(function () {\n", " /** @type {!Array} */\n", " var table = [];\n", " /** @type {number} */\n", "\n", " var i;\n", " /** @type {!Array.} */\n", "\n", " var c;\n", "\n", " for (i = 3; i <= 258; i++) {\n", " c = code(i);\n", " table[i] = c[2] << 24 | c[1] << 16 | c[0];\n", " }\n", " /**\n", " * @param {number} length lz77 length.\n", " * @return {!Array.} lz77 codes.\n", " */\n", "\n", "\n", " function code(length) {\n", " switch (true) {\n", " case length === 3:\n", " return [257, length - 3, 0];\n", "\n", " case length === 4:\n", " return [258, length - 4, 0];\n", "\n", " case length === 5:\n", " return [259, length - 5, 0];\n", "\n", " case length === 6:\n", " return [260, length - 6, 0];\n", "\n", " case length === 7:\n", " return [261, length - 7, 0];\n", "\n", " case length === 8:\n", " return [262, length - 8, 0];\n", "\n", " case length === 9:\n", " return [263, length - 9, 0];\n", "\n", " case length === 10:\n", " return [264, length - 10, 0];\n", "\n", " case length <= 12:\n", " return [265, length - 11, 1];\n", "\n", " case length <= 14:\n", " return [266, length - 13, 1];\n", "\n", " case length <= 16:\n", " return [267, length - 15, 1];\n", "\n", " case length <= 18:\n", " return [268, length - 17, 1];\n", "\n", " case length <= 22:\n", " return [269, length - 19, 2];\n", "\n", " case length <= 26:\n", " return [270, length - 23, 2];\n", "\n", " case length <= 30:\n", " return [271, length - 27, 2];\n", "\n", " case length <= 34:\n", " return [272, length - 31, 2];\n", "\n", " case length <= 42:\n", " return [273, length - 35, 3];\n", "\n", " case length <= 50:\n", " return [274, length - 43, 3];\n", "\n", " case length <= 58:\n", " return [275, length - 51, 3];\n", "\n", " case length <= 66:\n", " return [276, length - 59, 3];\n", "\n", " case length <= 82:\n", " return [277, length - 67, 4];\n", "\n", " case length <= 98:\n", " return [278, length - 83, 4];\n", "\n", " case length <= 114:\n", " return [279, length - 99, 4];\n", "\n", " case length <= 130:\n", " return [280, length - 115, 4];\n", "\n", " case length <= 162:\n", " return [281, length - 131, 5];\n", "\n", " case length <= 194:\n", " return [282, length - 163, 5];\n", "\n", " case length <= 226:\n", " return [283, length - 195, 5];\n", "\n", " case length <= 257:\n", " return [284, length - 227, 5];\n", "\n", " case length === 258:\n", " return [285, length - 258, 0];\n", "\n", " default:\n", " throw 'invalid length: ' + length;\n", " }\n", " }\n", "\n", " return table;\n", " }());\n", " /**\n", " * 距離符号テーブル\n", " * @param {!number} dist 距離.\n", " * @return {!Array.} コード、拡張ビット、拡張ビット長の配列.\n", " * @private\n", " */\n", "\n", "\n", " Zlib$2.RawDeflate.Lz77Match.prototype.getDistanceCode_ = function (dist) {\n", " /** @type {!Array.} distance code table. */\n", " var r;\n", "\n", " switch (true) {\n", " case dist === 1:\n", " r = [0, dist - 1, 0];\n", " break;\n", "\n", " case dist === 2:\n", " r = [1, dist - 2, 0];\n", " break;\n", "\n", " case dist === 3:\n", " r = [2, dist - 3, 0];\n", " break;\n", "\n", " case dist === 4:\n", " r = [3, dist - 4, 0];\n", " break;\n", "\n", " case dist <= 6:\n", " r = [4, dist - 5, 1];\n", " break;\n", "\n", " case dist <= 8:\n", " r = [5, dist - 7, 1];\n", " break;\n", "\n", " case dist <= 12:\n", " r = [6, dist - 9, 2];\n", " break;\n", "\n", " case dist <= 16:\n", " r = [7, dist - 13, 2];\n", " break;\n", "\n", " case dist <= 24:\n", " r = [8, dist - 17, 3];\n", " break;\n", "\n", " case dist <= 32:\n", " r = [9, dist - 25, 3];\n", " break;\n", "\n", " case dist <= 48:\n", " r = [10, dist - 33, 4];\n", " break;\n", "\n", " case dist <= 64:\n", " r = [11, dist - 49, 4];\n", " break;\n", "\n", " case dist <= 96:\n", " r = [12, dist - 65, 5];\n", " break;\n", "\n", " case dist <= 128:\n", " r = [13, dist - 97, 5];\n", " break;\n", "\n", " case dist <= 192:\n", " r = [14, dist - 129, 6];\n", " break;\n", "\n", " case dist <= 256:\n", " r = [15, dist - 193, 6];\n", " break;\n", "\n", " case dist <= 384:\n", " r = [16, dist - 257, 7];\n", " break;\n", "\n", " case dist <= 512:\n", " r = [17, dist - 385, 7];\n", " break;\n", "\n", " case dist <= 768:\n", " r = [18, dist - 513, 8];\n", " break;\n", "\n", " case dist <= 1024:\n", " r = [19, dist - 769, 8];\n", " break;\n", "\n", " case dist <= 1536:\n", " r = [20, dist - 1025, 9];\n", " break;\n", "\n", " case dist <= 2048:\n", " r = [21, dist - 1537, 9];\n", " break;\n", "\n", " case dist <= 3072:\n", " r = [22, dist - 2049, 10];\n", " break;\n", "\n", " case dist <= 4096:\n", " r = [23, dist - 3073, 10];\n", " break;\n", "\n", " case dist <= 6144:\n", " r = [24, dist - 4097, 11];\n", " break;\n", "\n", " case dist <= 8192:\n", " r = [25, dist - 6145, 11];\n", " break;\n", "\n", " case dist <= 12288:\n", " r = [26, dist - 8193, 12];\n", " break;\n", "\n", " case dist <= 16384:\n", " r = [27, dist - 12289, 12];\n", " break;\n", "\n", " case dist <= 24576:\n", " r = [28, dist - 16385, 13];\n", " break;\n", "\n", " case dist <= 32768:\n", " r = [29, dist - 24577, 13];\n", " break;\n", "\n", " default:\n", " throw 'invalid distance';\n", " }\n", "\n", " return r;\n", " };\n", " /**\n", " * マッチ情報を LZ77 符号化配列で返す.\n", " * なお、ここでは以下の内部仕様で符号化している\n", " * [ CODE, EXTRA-BIT-LEN, EXTRA, CODE, EXTRA-BIT-LEN, EXTRA ]\n", " * @return {!Array.} LZ77 符号化 byte array.\n", " */\n", "\n", "\n", " Zlib$2.RawDeflate.Lz77Match.prototype.toLz77Array = function () {\n", " /** @type {number} */\n", " var length = this.length;\n", " /** @type {number} */\n", "\n", " var dist = this.backwardDistance;\n", " /** @type {Array} */\n", "\n", " var codeArray = [];\n", " /** @type {number} */\n", "\n", " var pos = 0;\n", " /** @type {!Array.} */\n", "\n", " var code; // length\n", "\n", " code = Zlib$2.RawDeflate.Lz77Match.LengthCodeTable[length];\n", " codeArray[pos++] = code & 0xffff;\n", " codeArray[pos++] = code >> 16 & 0xff;\n", " codeArray[pos++] = code >> 24; // distance\n", "\n", " code = this.getDistanceCode_(dist);\n", " codeArray[pos++] = code[0];\n", " codeArray[pos++] = code[1];\n", " codeArray[pos++] = code[2];\n", " return codeArray;\n", " };\n", " /**\n", " * LZ77 実装\n", " * @param {!(Array.|Uint8Array)} dataArray LZ77 符号化するバイト配列.\n", " * @return {!(Array.|Uint16Array)} LZ77 符号化した配列.\n", " */\n", "\n", "\n", " Zlib$2.RawDeflate.prototype.lz77 = function (dataArray) {\n", " /** @type {number} input position */\n", " var position;\n", " /** @type {number} input length */\n", "\n", " var length;\n", " /** @type {number} loop counter */\n", "\n", " var i;\n", " /** @type {number} loop limiter */\n", "\n", " var il;\n", " /** @type {number} chained-hash-table key */\n", "\n", " var matchKey;\n", " /** @type {Object.>} chained-hash-table */\n", "\n", " var table = {};\n", " /** @const @type {number} */\n", "\n", " var windowSize = Zlib$2.RawDeflate.WindowSize;\n", " /** @type {Array.} match list */\n", "\n", " var matchList;\n", " /** @type {Zlib.RawDeflate.Lz77Match} longest match */\n", "\n", " var longestMatch;\n", " /** @type {Zlib.RawDeflate.Lz77Match} previous longest match */\n", "\n", " var prevMatch;\n", " /** @type {!(Array.|Uint16Array)} lz77 buffer */\n", "\n", " var lz77buf = new Uint16Array(dataArray.length * 2) ;\n", " /** @type {number} lz77 output buffer pointer */\n", "\n", " var pos = 0;\n", " /** @type {number} lz77 skip length */\n", "\n", " var skipLength = 0;\n", " /** @type {!(Array.|Uint32Array)} */\n", "\n", " var freqsLitLen = new (Uint32Array )(286);\n", " /** @type {!(Array.|Uint32Array)} */\n", "\n", " var freqsDist = new (Uint32Array )(30);\n", " /** @type {number} */\n", "\n", " var lazy = this.lazy;\n", " /** @type {*} temporary variable */\n", "\n", " var tmp; // 初期化\n", "\n", " freqsLitLen[256] = 1; // EOB の最低出現回数は 1\n", "\n", " /**\n", " * マッチデータの書き込み\n", " * @param {Zlib.RawDeflate.Lz77Match} match LZ77 Match data.\n", " * @param {!number} offset スキップ開始位置(相対指定).\n", " * @private\n", " */\n", "\n", " function writeMatch(match, offset) {\n", " /** @type {Array.} */\n", " var lz77Array = match.toLz77Array();\n", " /** @type {number} */\n", "\n", " var i;\n", " /** @type {number} */\n", "\n", " var il;\n", "\n", " for (i = 0, il = lz77Array.length; i < il; ++i) {\n", " lz77buf[pos++] = lz77Array[i];\n", " }\n", "\n", " freqsLitLen[lz77Array[0]]++;\n", " freqsDist[lz77Array[3]]++;\n", " skipLength = match.length + offset - 1;\n", " prevMatch = null;\n", " } // LZ77 符号化\n", "\n", "\n", " for (position = 0, length = dataArray.length; position < length; ++position) {\n", " // ハッシュキーの作成\n", " for (matchKey = 0, i = 0, il = Zlib$2.RawDeflate.Lz77MinLength; i < il; ++i) {\n", " if (position + i === length) {\n", " break;\n", " }\n", "\n", " matchKey = matchKey << 8 | dataArray[position + i];\n", " } // テーブルが未定義だったら作成する\n", "\n", "\n", " if (table[matchKey] === void 0) {\n", " table[matchKey] = [];\n", " }\n", "\n", " matchList = table[matchKey]; // skip\n", "\n", " if (skipLength-- > 0) {\n", " matchList.push(position);\n", " continue;\n", " } // マッチテーブルの更新 (最大戻り距離を超えているものを削除する)\n", "\n", "\n", " while (matchList.length > 0 && position - matchList[0] > windowSize) {\n", " matchList.shift();\n", " } // データ末尾でマッチしようがない場合はそのまま流しこむ\n", "\n", "\n", " if (position + Zlib$2.RawDeflate.Lz77MinLength >= length) {\n", " if (prevMatch) {\n", " writeMatch(prevMatch, -1);\n", " }\n", "\n", " for (i = 0, il = length - position; i < il; ++i) {\n", " tmp = dataArray[position + i];\n", " lz77buf[pos++] = tmp;\n", " ++freqsLitLen[tmp];\n", " }\n", "\n", " break;\n", " } // マッチ候補から最長のものを探す\n", "\n", "\n", " if (matchList.length > 0) {\n", " longestMatch = this.searchLongestMatch_(dataArray, position, matchList);\n", "\n", " if (prevMatch) {\n", " // 現在のマッチの方が前回のマッチよりも長い\n", " if (prevMatch.length < longestMatch.length) {\n", " // write previous literal\n", " tmp = dataArray[position - 1];\n", " lz77buf[pos++] = tmp;\n", " ++freqsLitLen[tmp]; // write current match\n", "\n", " writeMatch(longestMatch, 0);\n", " } else {\n", " // write previous match\n", " writeMatch(prevMatch, -1);\n", " }\n", " } else if (longestMatch.length < lazy) {\n", " prevMatch = longestMatch;\n", " } else {\n", " writeMatch(longestMatch, 0);\n", " } // 前回マッチしていて今回マッチがなかったら前回のを採用\n", "\n", " } else if (prevMatch) {\n", " writeMatch(prevMatch, -1);\n", " } else {\n", " tmp = dataArray[position];\n", " lz77buf[pos++] = tmp;\n", " ++freqsLitLen[tmp];\n", " }\n", "\n", " matchList.push(position); // マッチテーブルに現在の位置を保存\n", " } // 終端処理\n", "\n", "\n", " lz77buf[pos++] = 256;\n", " freqsLitLen[256]++;\n", " this.freqsLitLen = freqsLitLen;\n", " this.freqsDist = freqsDist;\n", " return (\n", " /** @type {!(Uint16Array|Array.)} */\n", " lz77buf.subarray(0, pos) \n", " );\n", " };\n", " /**\n", " * マッチした候補の中から最長一致を探す\n", " * @param {!Object} data plain data byte array.\n", " * @param {!number} position plain data byte array position.\n", " * @param {!Array.} matchList 候補となる位置の配列.\n", " * @return {!Zlib.RawDeflate.Lz77Match} 最長かつ最短距離のマッチオブジェクト.\n", " * @private\n", " */\n", "\n", "\n", " Zlib$2.RawDeflate.prototype.searchLongestMatch_ = function (data, position, matchList) {\n", " var match,\n", " currentMatch,\n", " matchMax = 0,\n", " matchLength,\n", " i,\n", " j,\n", " l,\n", " dl = data.length; // 候補を後ろから 1 つずつ絞り込んでゆく\n", "\n", " permatch: for (i = 0, l = matchList.length; i < l; i++) {\n", " match = matchList[l - i - 1];\n", " matchLength = Zlib$2.RawDeflate.Lz77MinLength; // 前回までの最長一致を末尾から一致検索する\n", "\n", " if (matchMax > Zlib$2.RawDeflate.Lz77MinLength) {\n", " for (j = matchMax; j > Zlib$2.RawDeflate.Lz77MinLength; j--) {\n", " if (data[match + j - 1] !== data[position + j - 1]) {\n", " continue permatch;\n", " }\n", " }\n", "\n", " matchLength = matchMax;\n", " } // 最長一致探索\n", "\n", "\n", " while (matchLength < Zlib$2.RawDeflate.Lz77MaxLength && position + matchLength < dl && data[match + matchLength] === data[position + matchLength]) {\n", " ++matchLength;\n", " } // マッチ長が同じ場合は後方を優先\n", "\n", "\n", " if (matchLength > matchMax) {\n", " currentMatch = match;\n", " matchMax = matchLength;\n", " } // 最長が確定したら後の処理は省略\n", "\n", "\n", " if (matchLength === Zlib$2.RawDeflate.Lz77MaxLength) {\n", " break;\n", " }\n", " }\n", "\n", " return new Zlib$2.RawDeflate.Lz77Match(matchMax, position - currentMatch);\n", " };\n", " /**\n", " * Tree-Transmit Symbols の算出\n", " * reference: PuTTY Deflate implementation\n", " * @param {number} hlit HLIT.\n", " * @param {!(Array.|Uint8Array)} litlenLengths リテラルと長さ符号の符号長配列.\n", " * @param {number} hdist HDIST.\n", " * @param {!(Array.|Uint8Array)} distLengths 距離符号の符号長配列.\n", " * @return {{\n", " * codes: !(Array.|Uint32Array),\n", " * freqs: !(Array.|Uint8Array)\n", " * }} Tree-Transmit Symbols.\n", " */\n", "\n", "\n", " Zlib$2.RawDeflate.prototype.getTreeSymbols_ = function (hlit, litlenLengths, hdist, distLengths) {\n", " var src = new (Uint32Array )(hlit + hdist),\n", " i,\n", " j,\n", " runLength,\n", " l,\n", " result = new (Uint32Array )(286 + 30),\n", " nResult,\n", " rpt,\n", " freqs = new (Uint8Array )(19);\n", " j = 0;\n", "\n", " for (i = 0; i < hlit; i++) {\n", " src[j++] = litlenLengths[i];\n", " }\n", "\n", " for (i = 0; i < hdist; i++) {\n", " src[j++] = distLengths[i];\n", " } // 初期化\n", "\n", "\n", " nResult = 0;\n", "\n", " for (i = 0, l = src.length; i < l; i += j) {\n", " // Run Length Encoding\n", " for (j = 1; i + j < l && src[i + j] === src[i]; ++j) {}\n", "\n", " runLength = j;\n", "\n", " if (src[i] === 0) {\n", " // 0 の繰り返しが 3 回未満ならばそのまま\n", " if (runLength < 3) {\n", " while (runLength-- > 0) {\n", " result[nResult++] = 0;\n", " freqs[0]++;\n", " }\n", " } else {\n", " while (runLength > 0) {\n", " // 繰り返しは最大 138 までなので切り詰める\n", " rpt = runLength < 138 ? runLength : 138;\n", "\n", " if (rpt > runLength - 3 && rpt < runLength) {\n", " rpt = runLength - 3;\n", " } // 3-10 回 -> 17\n", "\n", "\n", " if (rpt <= 10) {\n", " result[nResult++] = 17;\n", " result[nResult++] = rpt - 3;\n", " freqs[17]++; // 11-138 回 -> 18\n", " } else {\n", " result[nResult++] = 18;\n", " result[nResult++] = rpt - 11;\n", " freqs[18]++;\n", " }\n", "\n", " runLength -= rpt;\n", " }\n", " }\n", " } else {\n", " result[nResult++] = src[i];\n", " freqs[src[i]]++;\n", " runLength--; // 繰り返し回数が3回未満ならばランレングス符号は要らない\n", "\n", " if (runLength < 3) {\n", " while (runLength-- > 0) {\n", " result[nResult++] = src[i];\n", " freqs[src[i]]++;\n", " } // 3 回以上ならばランレングス符号化\n", "\n", " } else {\n", " while (runLength > 0) {\n", " // runLengthを 3-6 で分割\n", " rpt = runLength < 6 ? runLength : 6;\n", "\n", " if (rpt > runLength - 3 && rpt < runLength) {\n", " rpt = runLength - 3;\n", " }\n", "\n", " result[nResult++] = 16;\n", " result[nResult++] = rpt - 3;\n", " freqs[16]++;\n", " runLength -= rpt;\n", " }\n", " }\n", " }\n", " }\n", "\n", " return {\n", " codes: result.subarray(0, nResult) ,\n", " freqs: freqs\n", " };\n", " };\n", " /**\n", " * ハフマン符号の長さを取得する\n", " * @param {!(Array.|Uint8Array|Uint32Array)} freqs 出現カウント.\n", " * @param {number} limit 符号長の制限.\n", " * @return {!(Array.|Uint8Array)} 符号長配列.\n", " * @private\n", " */\n", "\n", "\n", " Zlib$2.RawDeflate.prototype.getLengths_ = function (freqs, limit) {\n", " /** @type {number} */\n", " var nSymbols = freqs.length;\n", " /** @type {Zlib.Heap} */\n", "\n", " var heap = new Zlib$2.Heap(2 * Zlib$2.RawDeflate.HUFMAX);\n", " /** @type {!(Array.|Uint8Array)} */\n", "\n", " var length = new (Uint8Array )(nSymbols);\n", " /** @type {Array} */\n", "\n", " var nodes;\n", " /** @type {!(Array.|Uint32Array)} */\n", "\n", " var values;\n", " /** @type {!(Array.|Uint8Array)} */\n", "\n", " var codeLength;\n", " /** @type {number} */\n", "\n", " var i;\n", " /** @type {number} */\n", "\n", " var il; // 配列の初期化\n", "\n", "\n", " for (i = 0; i < nSymbols; ++i) {\n", " if (freqs[i] > 0) {\n", " heap.push(i, freqs[i]);\n", " }\n", " }\n", "\n", " nodes = new Array(heap.length / 2);\n", " values = new (Uint32Array )(heap.length / 2); // 非 0 の要素が一つだけだった場合は、そのシンボルに符号長 1 を割り当てて終了\n", "\n", " if (nodes.length === 1) {\n", " length[heap.pop().index] = 1;\n", " return length;\n", " } // Reverse Package Merge Algorithm による Canonical Huffman Code の符号長決定\n", "\n", "\n", " for (i = 0, il = heap.length / 2; i < il; ++i) {\n", " nodes[i] = heap.pop();\n", " values[i] = nodes[i].value;\n", " }\n", "\n", " codeLength = this.reversePackageMerge_(values, values.length, limit);\n", "\n", " for (i = 0, il = nodes.length; i < il; ++i) {\n", " length[nodes[i].index] = codeLength[i];\n", " }\n", "\n", " return length;\n", " };\n", " /**\n", " * Reverse Package Merge Algorithm.\n", " * @param {!(Array.|Uint32Array)} freqs sorted probability.\n", " * @param {number} symbols number of symbols.\n", " * @param {number} limit code length limit.\n", " * @return {!(Array.|Uint8Array)} code lengths.\n", " */\n", "\n", "\n", " Zlib$2.RawDeflate.prototype.reversePackageMerge_ = function (freqs, symbols, limit) {\n", " /** @type {!(Array.|Uint16Array)} */\n", " var minimumCost = new (Uint16Array )(limit);\n", " /** @type {!(Array.|Uint8Array)} */\n", "\n", " var flag = new (Uint8Array )(limit);\n", " /** @type {!(Array.|Uint8Array)} */\n", "\n", " var codeLength = new (Uint8Array )(symbols);\n", " /** @type {Array} */\n", "\n", " var value = new Array(limit);\n", " /** @type {Array} */\n", "\n", " var type = new Array(limit);\n", " /** @type {Array.} */\n", "\n", " var currentPosition = new Array(limit);\n", " /** @type {number} */\n", "\n", " var excess = (1 << limit) - symbols;\n", " /** @type {number} */\n", "\n", " var half = 1 << limit - 1;\n", " /** @type {number} */\n", "\n", " var i;\n", " /** @type {number} */\n", "\n", " var j;\n", " /** @type {number} */\n", "\n", " var t;\n", " /** @type {number} */\n", "\n", " var weight;\n", " /** @type {number} */\n", "\n", " var next;\n", " /**\n", " * @param {number} j\n", " */\n", "\n", " function takePackage(j) {\n", " /** @type {number} */\n", " var x = type[j][currentPosition[j]];\n", "\n", " if (x === symbols) {\n", " takePackage(j + 1);\n", " takePackage(j + 1);\n", " } else {\n", " --codeLength[x];\n", " }\n", "\n", " ++currentPosition[j];\n", " }\n", "\n", " minimumCost[limit - 1] = symbols;\n", "\n", " for (j = 0; j < limit; ++j) {\n", " if (excess < half) {\n", " flag[j] = 0;\n", " } else {\n", " flag[j] = 1;\n", " excess -= half;\n", " }\n", "\n", " excess <<= 1;\n", " minimumCost[limit - 2 - j] = (minimumCost[limit - 1 - j] / 2 | 0) + symbols;\n", " }\n", "\n", " minimumCost[0] = flag[0];\n", " value[0] = new Array(minimumCost[0]);\n", " type[0] = new Array(minimumCost[0]);\n", "\n", " for (j = 1; j < limit; ++j) {\n", " if (minimumCost[j] > 2 * minimumCost[j - 1] + flag[j]) {\n", " minimumCost[j] = 2 * minimumCost[j - 1] + flag[j];\n", " }\n", "\n", " value[j] = new Array(minimumCost[j]);\n", " type[j] = new Array(minimumCost[j]);\n", " }\n", "\n", " for (i = 0; i < symbols; ++i) {\n", " codeLength[i] = limit;\n", " }\n", "\n", " for (t = 0; t < minimumCost[limit - 1]; ++t) {\n", " value[limit - 1][t] = freqs[t];\n", " type[limit - 1][t] = t;\n", " }\n", "\n", " for (i = 0; i < limit; ++i) {\n", " currentPosition[i] = 0;\n", " }\n", "\n", " if (flag[limit - 1] === 1) {\n", " --codeLength[0];\n", " ++currentPosition[limit - 1];\n", " }\n", "\n", " for (j = limit - 2; j >= 0; --j) {\n", " i = 0;\n", " weight = 0;\n", " next = currentPosition[j + 1];\n", "\n", " for (t = 0; t < minimumCost[j]; t++) {\n", " weight = value[j + 1][next] + value[j + 1][next + 1];\n", "\n", " if (weight > freqs[i]) {\n", " value[j][t] = weight;\n", " type[j][t] = symbols;\n", " next += 2;\n", " } else {\n", " value[j][t] = freqs[i];\n", " type[j][t] = i;\n", " ++i;\n", " }\n", " }\n", "\n", " currentPosition[j] = 0;\n", "\n", " if (flag[j] === 1) {\n", " takePackage(j);\n", " }\n", " }\n", "\n", " return codeLength;\n", " };\n", " /**\n", " * 符号長配列からハフマン符号を取得する\n", " * reference: PuTTY Deflate implementation\n", " * @param {!(Array.|Uint8Array)} lengths 符号長配列.\n", " * @return {!(Array.|Uint16Array)} ハフマン符号配列.\n", " * @private\n", " */\n", "\n", "\n", " Zlib$2.RawDeflate.prototype.getCodesFromLengths_ = function (lengths) {\n", " var codes = new (Uint16Array )(lengths.length),\n", " count = [],\n", " startCode = [],\n", " code = 0,\n", " i,\n", " il,\n", " j,\n", " m; // Count the codes of each length.\n", "\n", " for (i = 0, il = lengths.length; i < il; i++) {\n", " count[lengths[i]] = (count[lengths[i]] | 0) + 1;\n", " } // Determine the starting code for each length block.\n", "\n", "\n", " for (i = 1, il = Zlib$2.RawDeflate.MaxCodeLength; i <= il; i++) {\n", " startCode[i] = code;\n", " code += count[i] | 0;\n", " code <<= 1;\n", " } // Determine the code for each symbol. Mirrored, of course.\n", "\n", "\n", " for (i = 0, il = lengths.length; i < il; i++) {\n", " code = startCode[lengths[i]];\n", " startCode[lengths[i]] += 1;\n", " codes[i] = 0;\n", "\n", " for (j = 0, m = lengths[i]; j < m; j++) {\n", " codes[i] = codes[i] << 1 | code & 1;\n", " code >>>= 1;\n", " }\n", " }\n", "\n", " return codes;\n", " };\n", " /**\n", " * @param {!(Array.|Uint8Array)} input input buffer.\n", " * @param {Object=} opt_params options.\n", " * @constructor\n", " */\n", "\n", "\n", " Zlib$2.Unzip = function (input, opt_params) {\n", " opt_params = opt_params || {};\n", " /** @type {!(Array.|Uint8Array)} */\n", "\n", " this.input = input instanceof Array ? new Uint8Array(input) : input;\n", " /** @type {number} */\n", "\n", " this.ip = 0;\n", " /** @type {number} */\n", "\n", " this.eocdrOffset;\n", " /** @type {number} */\n", "\n", " this.numberOfThisDisk;\n", " /** @type {number} */\n", "\n", " this.startDisk;\n", " /** @type {number} */\n", "\n", " this.totalEntriesThisDisk;\n", " /** @type {number} */\n", "\n", " this.totalEntries;\n", " /** @type {number} */\n", "\n", " this.centralDirectorySize;\n", " /** @type {number} */\n", "\n", " this.centralDirectoryOffset;\n", " /** @type {number} */\n", "\n", " this.commentLength;\n", " /** @type {(Array.|Uint8Array)} */\n", "\n", " this.comment;\n", " /** @type {Array.} */\n", "\n", " this.fileHeaderList;\n", " /** @type {Object.} */\n", "\n", " this.filenameToIndex;\n", " /** @type {boolean} */\n", "\n", " this.verify = opt_params['verify'] || false;\n", " /** @type {(Array.|Uint8Array)} */\n", "\n", " this.password = opt_params['password'];\n", " };\n", "\n", " Zlib$2.Unzip.CompressionMethod = Zlib$2.Zip.CompressionMethod;\n", " /**\n", " * @type {Array.}\n", " * @const\n", " */\n", "\n", " Zlib$2.Unzip.FileHeaderSignature = Zlib$2.Zip.FileHeaderSignature;\n", " /**\n", " * @type {Array.}\n", " * @const\n", " */\n", "\n", " Zlib$2.Unzip.LocalFileHeaderSignature = Zlib$2.Zip.LocalFileHeaderSignature;\n", " /**\n", " * @type {Array.}\n", " * @const\n", " */\n", "\n", " Zlib$2.Unzip.CentralDirectorySignature = Zlib$2.Zip.CentralDirectorySignature;\n", " /**\n", " * @param {!(Array.|Uint8Array)} input input buffer.\n", " * @param {number} ip input position.\n", " * @constructor\n", " */\n", "\n", " Zlib$2.Unzip.FileHeader = function (input, ip) {\n", " /** @type {!(Array.|Uint8Array)} */\n", " this.input = input;\n", " /** @type {number} */\n", "\n", " this.offset = ip;\n", " /** @type {number} */\n", "\n", " this.length;\n", " /** @type {number} */\n", "\n", " this.version;\n", " /** @type {number} */\n", "\n", " this.os;\n", " /** @type {number} */\n", "\n", " this.needVersion;\n", " /** @type {number} */\n", "\n", " this.flags;\n", " /** @type {number} */\n", "\n", " this.compression;\n", " /** @type {number} */\n", "\n", " this.time;\n", " /** @type {number} */\n", "\n", " this.date;\n", " /** @type {number} */\n", "\n", " this.crc32;\n", " /** @type {number} */\n", "\n", " this.compressedSize;\n", " /** @type {number} */\n", "\n", " this.plainSize;\n", " /** @type {number} */\n", "\n", " this.fileNameLength;\n", " /** @type {number} */\n", "\n", " this.extraFieldLength;\n", " /** @type {number} */\n", "\n", " this.fileCommentLength;\n", " /** @type {number} */\n", "\n", " this.diskNumberStart;\n", " /** @type {number} */\n", "\n", " this.internalFileAttributes;\n", " /** @type {number} */\n", "\n", " this.externalFileAttributes;\n", " /** @type {number} */\n", "\n", " this.relativeOffset;\n", " /** @type {string} */\n", "\n", " this.filename;\n", " /** @type {!(Array.|Uint8Array)} */\n", "\n", " this.extraField;\n", " /** @type {!(Array.|Uint8Array)} */\n", "\n", " this.comment;\n", " };\n", "\n", " Zlib$2.Unzip.FileHeader.prototype.parse = function () {\n", " /** @type {!(Array.|Uint8Array)} */\n", " var input = this.input;\n", " /** @type {number} */\n", "\n", " var ip = this.offset; // central file header signature\n", "\n", " if (input[ip++] !== Zlib$2.Unzip.FileHeaderSignature[0] || input[ip++] !== Zlib$2.Unzip.FileHeaderSignature[1] || input[ip++] !== Zlib$2.Unzip.FileHeaderSignature[2] || input[ip++] !== Zlib$2.Unzip.FileHeaderSignature[3]) {\n", " throw new Error('invalid file header signature');\n", " } // version made by\n", "\n", "\n", " this.version = input[ip++];\n", " this.os = input[ip++]; // version needed to extract\n", "\n", " this.needVersion = input[ip++] | input[ip++] << 8; // general purpose bit flag\n", "\n", " this.flags = input[ip++] | input[ip++] << 8; // compression method\n", "\n", " this.compression = input[ip++] | input[ip++] << 8; // last mod file time\n", "\n", " this.time = input[ip++] | input[ip++] << 8; //last mod file date\n", "\n", " this.date = input[ip++] | input[ip++] << 8; // crc-32\n", "\n", " this.crc32 = (input[ip++] | input[ip++] << 8 | input[ip++] << 16 | input[ip++] << 24) >>> 0; // compressed size\n", "\n", " this.compressedSize = (input[ip++] | input[ip++] << 8 | input[ip++] << 16 | input[ip++] << 24) >>> 0; // uncompressed size\n", "\n", " this.plainSize = (input[ip++] | input[ip++] << 8 | input[ip++] << 16 | input[ip++] << 24) >>> 0; // file name length\n", "\n", " this.fileNameLength = input[ip++] | input[ip++] << 8; // extra field length\n", "\n", " this.extraFieldLength = input[ip++] | input[ip++] << 8; // file comment length\n", "\n", " this.fileCommentLength = input[ip++] | input[ip++] << 8; // disk number start\n", "\n", " this.diskNumberStart = input[ip++] | input[ip++] << 8; // internal file attributes\n", "\n", " this.internalFileAttributes = input[ip++] | input[ip++] << 8; // external file attributes\n", "\n", " this.externalFileAttributes = input[ip++] | input[ip++] << 8 | input[ip++] << 16 | input[ip++] << 24; // relative offset of local header\n", "\n", " this.relativeOffset = (input[ip++] | input[ip++] << 8 | input[ip++] << 16 | input[ip++] << 24) >>> 0; // file name\n", "\n", " this.filename = String.fromCharCode.apply(null, input.subarray(ip, ip += this.fileNameLength) ); // extra field\n", "\n", " this.extraField = input.subarray(ip, ip += this.extraFieldLength) ; // file comment\n", "\n", " this.comment = input.subarray(ip, ip + this.fileCommentLength) ;\n", " this.length = ip - this.offset;\n", " };\n", " /**\n", " * @param {!(Array.|Uint8Array)} input input buffer.\n", " * @param {number} ip input position.\n", " * @constructor\n", " */\n", "\n", "\n", " Zlib$2.Unzip.LocalFileHeader = function (input, ip) {\n", " /** @type {!(Array.|Uint8Array)} */\n", " this.input = input;\n", " /** @type {number} */\n", "\n", " this.offset = ip;\n", " /** @type {number} */\n", "\n", " this.length;\n", " /** @type {number} */\n", "\n", " this.needVersion;\n", " /** @type {number} */\n", "\n", " this.flags;\n", " /** @type {number} */\n", "\n", " this.compression;\n", " /** @type {number} */\n", "\n", " this.time;\n", " /** @type {number} */\n", "\n", " this.date;\n", " /** @type {number} */\n", "\n", " this.crc32;\n", " /** @type {number} */\n", "\n", " this.compressedSize;\n", " /** @type {number} */\n", "\n", " this.plainSize;\n", " /** @type {number} */\n", "\n", " this.fileNameLength;\n", " /** @type {number} */\n", "\n", " this.extraFieldLength;\n", " /** @type {string} */\n", "\n", " this.filename;\n", " /** @type {!(Array.|Uint8Array)} */\n", "\n", " this.extraField;\n", " };\n", "\n", " Zlib$2.Unzip.LocalFileHeader.Flags = Zlib$2.Zip.Flags;\n", "\n", " Zlib$2.Unzip.LocalFileHeader.prototype.parse = function () {\n", " /** @type {!(Array.|Uint8Array)} */\n", " var input = this.input;\n", " /** @type {number} */\n", "\n", " var ip = this.offset; // local file header signature\n", "\n", " if (input[ip++] !== Zlib$2.Unzip.LocalFileHeaderSignature[0] || input[ip++] !== Zlib$2.Unzip.LocalFileHeaderSignature[1] || input[ip++] !== Zlib$2.Unzip.LocalFileHeaderSignature[2] || input[ip++] !== Zlib$2.Unzip.LocalFileHeaderSignature[3]) {\n", " throw new Error('invalid local file header signature');\n", " } // version needed to extract\n", "\n", "\n", " this.needVersion = input[ip++] | input[ip++] << 8; // general purpose bit flag\n", "\n", " this.flags = input[ip++] | input[ip++] << 8; // compression method\n", "\n", " this.compression = input[ip++] | input[ip++] << 8; // last mod file time\n", "\n", " this.time = input[ip++] | input[ip++] << 8; //last mod file date\n", "\n", " this.date = input[ip++] | input[ip++] << 8; // crc-32\n", "\n", " this.crc32 = (input[ip++] | input[ip++] << 8 | input[ip++] << 16 | input[ip++] << 24) >>> 0; // compressed size\n", "\n", " this.compressedSize = (input[ip++] | input[ip++] << 8 | input[ip++] << 16 | input[ip++] << 24) >>> 0; // uncompressed size\n", "\n", " this.plainSize = (input[ip++] | input[ip++] << 8 | input[ip++] << 16 | input[ip++] << 24) >>> 0; // file name length\n", "\n", " this.fileNameLength = input[ip++] | input[ip++] << 8; // extra field length\n", "\n", " this.extraFieldLength = input[ip++] | input[ip++] << 8; // file name\n", "\n", " this.filename = String.fromCharCode.apply(null, input.subarray(ip, ip += this.fileNameLength) ); // extra field\n", "\n", " this.extraField = input.subarray(ip, ip += this.extraFieldLength) ;\n", " this.length = ip - this.offset;\n", " };\n", "\n", " Zlib$2.Unzip.prototype.searchEndOfCentralDirectoryRecord = function () {\n", " /** @type {!(Array.|Uint8Array)} */\n", " var input = this.input;\n", " /** @type {number} */\n", "\n", " var ip;\n", "\n", " for (ip = input.length - 12; ip > 0; --ip) {\n", " if (input[ip] === Zlib$2.Unzip.CentralDirectorySignature[0] && input[ip + 1] === Zlib$2.Unzip.CentralDirectorySignature[1] && input[ip + 2] === Zlib$2.Unzip.CentralDirectorySignature[2] && input[ip + 3] === Zlib$2.Unzip.CentralDirectorySignature[3]) {\n", " this.eocdrOffset = ip;\n", " return;\n", " }\n", " }\n", "\n", " throw new Error('End of Central Directory Record not found');\n", " };\n", "\n", " Zlib$2.Unzip.prototype.parseEndOfCentralDirectoryRecord = function () {\n", " /** @type {!(Array.|Uint8Array)} */\n", " var input = this.input;\n", " /** @type {number} */\n", "\n", " var ip;\n", "\n", " if (!this.eocdrOffset) {\n", " this.searchEndOfCentralDirectoryRecord();\n", " }\n", "\n", " ip = this.eocdrOffset; // signature\n", "\n", " if (input[ip++] !== Zlib$2.Unzip.CentralDirectorySignature[0] || input[ip++] !== Zlib$2.Unzip.CentralDirectorySignature[1] || input[ip++] !== Zlib$2.Unzip.CentralDirectorySignature[2] || input[ip++] !== Zlib$2.Unzip.CentralDirectorySignature[3]) {\n", " throw new Error('invalid signature');\n", " } // number of this disk\n", "\n", "\n", " this.numberOfThisDisk = input[ip++] | input[ip++] << 8; // number of the disk with the start of the central directory\n", "\n", " this.startDisk = input[ip++] | input[ip++] << 8; // total number of entries in the central directory on this disk\n", "\n", " this.totalEntriesThisDisk = input[ip++] | input[ip++] << 8; // total number of entries in the central directory\n", "\n", " this.totalEntries = input[ip++] | input[ip++] << 8; // size of the central directory\n", "\n", " this.centralDirectorySize = (input[ip++] | input[ip++] << 8 | input[ip++] << 16 | input[ip++] << 24) >>> 0; // offset of start of central directory with respect to the starting disk number\n", "\n", " this.centralDirectoryOffset = (input[ip++] | input[ip++] << 8 | input[ip++] << 16 | input[ip++] << 24) >>> 0; // .ZIP file comment length\n", "\n", " this.commentLength = input[ip++] | input[ip++] << 8; // .ZIP file comment\n", "\n", " this.comment = input.subarray(ip, ip + this.commentLength) ;\n", " };\n", "\n", " Zlib$2.Unzip.prototype.parseFileHeader = function () {\n", " /** @type {Array.} */\n", " var filelist = [];\n", " /** @type {Object.} */\n", "\n", " var filetable = {};\n", " /** @type {number} */\n", "\n", " var ip;\n", " /** @type {Zlib.Unzip.FileHeader} */\n", "\n", " var fileHeader;\n", " /*: @type {number} */\n", "\n", " var i;\n", " /*: @type {number} */\n", "\n", " var il;\n", "\n", " if (this.fileHeaderList) {\n", " return;\n", " }\n", "\n", " if (this.centralDirectoryOffset === void 0) {\n", " this.parseEndOfCentralDirectoryRecord();\n", " }\n", "\n", " ip = this.centralDirectoryOffset;\n", "\n", " for (i = 0, il = this.totalEntries; i < il; ++i) {\n", " fileHeader = new Zlib$2.Unzip.FileHeader(this.input, ip);\n", " fileHeader.parse();\n", " ip += fileHeader.length;\n", " filelist[i] = fileHeader;\n", " filetable[fileHeader.filename] = i;\n", " }\n", "\n", " if (this.centralDirectorySize < ip - this.centralDirectoryOffset) {\n", " throw new Error('invalid file header size');\n", " }\n", "\n", " this.fileHeaderList = filelist;\n", " this.filenameToIndex = filetable;\n", " };\n", " /**\n", " * @param {number} index file header index.\n", " * @param {Object=} opt_params\n", " * @return {!(Array.|Uint8Array)} file data.\n", " */\n", "\n", "\n", " Zlib$2.Unzip.prototype.getFileData = function (index, opt_params) {\n", " opt_params = opt_params || {};\n", " /** @type {!(Array.|Uint8Array)} */\n", "\n", " var input = this.input;\n", " /** @type {Array.} */\n", "\n", " var fileHeaderList = this.fileHeaderList;\n", " /** @type {Zlib.Unzip.LocalFileHeader} */\n", "\n", " var localFileHeader;\n", " /** @type {number} */\n", "\n", " var offset;\n", " /** @type {number} */\n", "\n", " var length;\n", " /** @type {!(Array.|Uint8Array)} */\n", "\n", " var buffer;\n", " /** @type {number} */\n", "\n", " var crc32;\n", " /** @type {Array.|Uint32Array|Object} */\n", "\n", " var key;\n", " /** @type {number} */\n", "\n", " var i;\n", " /** @type {number} */\n", "\n", " var il;\n", "\n", " if (!fileHeaderList) {\n", " this.parseFileHeader();\n", " }\n", "\n", " if (fileHeaderList[index] === void 0) {\n", " throw new Error('wrong index');\n", " }\n", "\n", " offset = fileHeaderList[index].relativeOffset;\n", " localFileHeader = new Zlib$2.Unzip.LocalFileHeader(this.input, offset);\n", " localFileHeader.parse();\n", " offset += localFileHeader.length;\n", " length = localFileHeader.compressedSize; // decryption\n", "\n", " if ((localFileHeader.flags & Zlib$2.Unzip.LocalFileHeader.Flags.ENCRYPT) !== 0) {\n", " if (!(opt_params['password'] || this.password)) {\n", " throw new Error('please set password');\n", " }\n", "\n", " key = this.createDecryptionKey(opt_params['password'] || this.password); // encryption header\n", "\n", " for (i = offset, il = offset + 12; i < il; ++i) {\n", " this.decode(key, input[i]);\n", " }\n", "\n", " offset += 12;\n", " length -= 12; // decryption\n", "\n", " for (i = offset, il = offset + length; i < il; ++i) {\n", " input[i] = this.decode(key, input[i]);\n", " }\n", " }\n", "\n", " switch (localFileHeader.compression) {\n", " case Zlib$2.Unzip.CompressionMethod.STORE:\n", " buffer = this.input.subarray(offset, offset + length) ;\n", " break;\n", "\n", " case Zlib$2.Unzip.CompressionMethod.DEFLATE:\n", " buffer = new Zlib$2.RawInflate(this.input, {\n", " 'index': offset,\n", " 'bufferSize': localFileHeader.plainSize\n", " }).decompress();\n", " break;\n", "\n", " default:\n", " throw new Error('unknown compression type');\n", " }\n", "\n", " if (this.verify) {\n", " crc32 = Zlib$2.CRC32.calc(buffer);\n", "\n", " if (localFileHeader.crc32 !== crc32) {\n", " throw new Error('wrong crc: file=0x' + localFileHeader.crc32.toString(16) + ', data=0x' + crc32.toString(16));\n", " }\n", " }\n", "\n", " return buffer;\n", " };\n", " /**\n", " * @return {Array.}\n", " */\n", "\n", "\n", " Zlib$2.Unzip.prototype.getFilenames = function () {\n", " /** @type {Array.} */\n", " var filenameList = [];\n", " /** @type {number} */\n", "\n", " var i;\n", " /** @type {number} */\n", "\n", " var il;\n", " /** @type {Array.} */\n", "\n", " var fileHeaderList;\n", "\n", " if (!this.fileHeaderList) {\n", " this.parseFileHeader();\n", " }\n", "\n", " fileHeaderList = this.fileHeaderList;\n", "\n", " for (i = 0, il = fileHeaderList.length; i < il; ++i) {\n", " filenameList[i] = fileHeaderList[i].filename;\n", " }\n", "\n", " return filenameList;\n", " };\n", " /**\n", " * @param {string} filename extract filename.\n", " * @param {Object=} opt_params\n", " * @return {!(Array.|Uint8Array)} decompressed data.\n", " */\n", "\n", "\n", " Zlib$2.Unzip.prototype.decompress = function (filename, opt_params) {\n", " /** @type {number} */\n", " var index;\n", "\n", " if (!this.filenameToIndex) {\n", " this.parseFileHeader();\n", " }\n", "\n", " index = this.filenameToIndex[filename];\n", "\n", " if (index === void 0) {\n", " throw new Error(filename + ' not found');\n", " }\n", "\n", " return this.getFileData(index, opt_params);\n", " };\n", " /**\n", " * @param {(Array.|Uint8Array)} password\n", " */\n", "\n", "\n", " Zlib$2.Unzip.prototype.setPassword = function (password) {\n", " this.password = password;\n", " };\n", " /**\n", " * @param {(Array.|Uint32Array|Object)} key\n", " * @param {number} n\n", " * @return {number}\n", " */\n", "\n", "\n", " Zlib$2.Unzip.prototype.decode = function (key, n) {\n", " n ^= this.getByte(\n", " /** @type {(Array.|Uint32Array)} */\n", " key);\n", " this.updateKeys(\n", " /** @type {(Array.|Uint32Array)} */\n", " key, n);\n", " return n;\n", " }; // common method\n", "\n", "\n", " Zlib$2.Unzip.prototype.updateKeys = Zlib$2.Zip.prototype.updateKeys;\n", " Zlib$2.Unzip.prototype.createDecryptionKey = Zlib$2.Zip.prototype.createEncryptionKey;\n", " Zlib$2.Unzip.prototype.getByte = Zlib$2.Zip.prototype.getByte;\n", " /**\n", " * @fileoverview 雑多な関数群をまとめたモジュール実装.\n", " */\n", "\n", " /**\n", " * Byte String から Byte Array に変換.\n", " * @param {!string} str byte string.\n", " * @return {!Array.} byte array.\n", " */\n", "\n", " Zlib$2.Util.stringToByteArray = function (str) {\n", " /** @type {!Array.<(string|number)>} */\n", " var tmp = str.split('');\n", " /** @type {number} */\n", "\n", " var i;\n", " /** @type {number} */\n", "\n", " var il;\n", "\n", " for (i = 0, il = tmp.length; i < il; i++) {\n", " tmp[i] = (tmp[i].charCodeAt(0) & 0xff) >>> 0;\n", " }\n", "\n", " return tmp;\n", " };\n", " /**\n", " * @fileoverview Adler32 checksum 実装.\n", " */\n", "\n", " /**\n", " * Adler32 ハッシュ値の作成\n", " * @param {!(Array|Uint8Array|string)} array 算出に使用する byte array.\n", " * @return {number} Adler32 ハッシュ値.\n", " */\n", "\n", "\n", " Zlib$2.Adler32 = function (array) {\n", " if (typeof array === 'string') {\n", " array = Zlib$2.Util.stringToByteArray(array);\n", " }\n", "\n", " return Zlib$2.Adler32.update(1, array);\n", " };\n", " /**\n", " * Adler32 ハッシュ値の更新\n", " * @param {number} adler 現在のハッシュ値.\n", " * @param {!(Array|Uint8Array)} array 更新に使用する byte array.\n", " * @return {number} Adler32 ハッシュ値.\n", " */\n", "\n", "\n", " Zlib$2.Adler32.update = function (adler, array) {\n", " /** @type {number} */\n", " var s1 = adler & 0xffff;\n", " /** @type {number} */\n", "\n", " var s2 = adler >>> 16 & 0xffff;\n", " /** @type {number} array length */\n", "\n", " var len = array.length;\n", " /** @type {number} loop length (don't overflow) */\n", "\n", " var tlen;\n", " /** @type {number} array index */\n", "\n", " var i = 0;\n", "\n", " while (len > 0) {\n", " tlen = len > Zlib$2.Adler32.OptimizationParameter ? Zlib$2.Adler32.OptimizationParameter : len;\n", " len -= tlen;\n", "\n", " do {\n", " s1 += array[i++];\n", " s2 += s1;\n", " } while (--tlen);\n", "\n", " s1 %= 65521;\n", " s2 %= 65521;\n", " }\n", "\n", " return (s2 << 16 | s1) >>> 0;\n", " };\n", " /**\n", " * Adler32 最適化パラメータ\n", " * 現状では 1024 程度が最適.\n", " * @see http://jsperf.com/adler-32-simple-vs-optimized/3\n", " * @define {number}\n", " */\n", "\n", "\n", " Zlib$2.Adler32.OptimizationParameter = 1024;\n", " /**\n", " * ビットストリーム\n", " * @constructor\n", " * @param {!(Array|Uint8Array)=} buffer output buffer.\n", " * @param {number=} bufferPosition start buffer pointer.\n", " */\n", "\n", " Zlib$2.BitStream = function (buffer, bufferPosition) {\n", " /** @type {number} buffer index. */\n", " this.index = typeof bufferPosition === 'number' ? bufferPosition : 0;\n", " /** @type {number} bit index. */\n", "\n", " this.bitindex = 0;\n", " /** @type {!(Array|Uint8Array)} bit-stream output buffer. */\n", "\n", " this.buffer = buffer instanceof (Uint8Array ) ? buffer : new (Uint8Array )(Zlib$2.BitStream.DefaultBlockSize); // 入力された index が足りなかったら拡張するが、倍にしてもダメなら不正とする\n", "\n", " if (this.buffer.length * 2 <= this.index) {\n", " throw new Error(\"invalid index\");\n", " } else if (this.buffer.length <= this.index) {\n", " this.expandBuffer();\n", " }\n", " };\n", " /**\n", " * デフォルトブロックサイズ.\n", " * @const\n", " * @type {number}\n", " */\n", "\n", "\n", " Zlib$2.BitStream.DefaultBlockSize = 0x8000;\n", " /**\n", " * expand buffer.\n", " * @return {!(Array|Uint8Array)} new buffer.\n", " */\n", "\n", " Zlib$2.BitStream.prototype.expandBuffer = function () {\n", " /** @type {!(Array|Uint8Array)} old buffer. */\n", " var oldbuf = this.buffer;\n", " /** @type {number} loop limiter. */\n", "\n", " var il = oldbuf.length;\n", " /** @type {!(Array|Uint8Array)} new buffer. */\n", "\n", " var buffer = new (Uint8Array )(il << 1); // copy buffer\n", "\n", " {\n", " buffer.set(oldbuf);\n", " }\n", "\n", " return this.buffer = buffer;\n", " };\n", " /**\n", " * 数値をビットで指定した数だけ書き込む.\n", " * @param {number} number 書き込む数値.\n", " * @param {number} n 書き込むビット数.\n", " * @param {boolean=} reverse 逆順に書き込むならば true.\n", " */\n", "\n", "\n", " Zlib$2.BitStream.prototype.writeBits = function (number, n, reverse) {\n", " var buffer = this.buffer;\n", " var index = this.index;\n", " var bitindex = this.bitindex;\n", " /** @type {number} current octet. */\n", "\n", " var current = buffer[index];\n", " /** @type {number} loop counter. */\n", "\n", " var i;\n", " /**\n", " * 32-bit 整数のビット順を逆にする\n", " * @param {number} n 32-bit integer.\n", " * @return {number} reversed 32-bit integer.\n", " * @private\n", " */\n", "\n", " function rev32_(n) {\n", " return Zlib$2.BitStream.ReverseTable[n & 0xFF] << 24 | Zlib$2.BitStream.ReverseTable[n >>> 8 & 0xFF] << 16 | Zlib$2.BitStream.ReverseTable[n >>> 16 & 0xFF] << 8 | Zlib$2.BitStream.ReverseTable[n >>> 24 & 0xFF];\n", " }\n", "\n", " if (reverse && n > 1) {\n", " number = n > 8 ? rev32_(number) >> 32 - n : Zlib$2.BitStream.ReverseTable[number] >> 8 - n;\n", " } // Byte 境界を超えないとき\n", "\n", "\n", " if (n + bitindex < 8) {\n", " current = current << n | number;\n", " bitindex += n; // Byte 境界を超えるとき\n", " } else {\n", " for (i = 0; i < n; ++i) {\n", " current = current << 1 | number >> n - i - 1 & 1; // next byte\n", "\n", " if (++bitindex === 8) {\n", " bitindex = 0;\n", " buffer[index++] = Zlib$2.BitStream.ReverseTable[current];\n", " current = 0; // expand\n", "\n", " if (index === buffer.length) {\n", " buffer = this.expandBuffer();\n", " }\n", " }\n", " }\n", " }\n", "\n", " buffer[index] = current;\n", " this.buffer = buffer;\n", " this.bitindex = bitindex;\n", " this.index = index;\n", " };\n", " /**\n", " * ストリームの終端処理を行う\n", " * @return {!(Array|Uint8Array)} 終端処理後のバッファを byte array で返す.\n", " */\n", "\n", "\n", " Zlib$2.BitStream.prototype.finish = function () {\n", " var buffer = this.buffer;\n", " var index = this.index;\n", " /** @type {!(Array|Uint8Array)} output buffer. */\n", "\n", " var output; // bitindex が 0 の時は余分に index が進んでいる状態\n", "\n", " if (this.bitindex > 0) {\n", " buffer[index] <<= 8 - this.bitindex;\n", " buffer[index] = Zlib$2.BitStream.ReverseTable[buffer[index]];\n", " index++;\n", " } // array truncation\n", "\n", "\n", " {\n", " output = buffer.subarray(0, index);\n", " }\n", "\n", " return output;\n", " };\n", " /**\n", " * 0-255 のビット順を反転したテーブル\n", " * @const\n", " * @type {!(Uint8Array|Array.)}\n", " */\n", "\n", "\n", " Zlib$2.BitStream.ReverseTable = function (table) {\n", " return table;\n", " }(function () {\n", " /** @type {!(Array|Uint8Array)} reverse table. */\n", " var table = new (Uint8Array )(256);\n", " /** @type {number} loop counter. */\n", "\n", " var i; // generate\n", "\n", " for (i = 0; i < 256; ++i) {\n", " table[i] = function (n) {\n", " var r = n;\n", " var s = 7;\n", "\n", " for (n >>>= 1; n; n >>>= 1) {\n", " r <<= 1;\n", " r |= n & 1;\n", " --s;\n", " }\n", "\n", " return (r << s & 0xff) >>> 0;\n", " }(i);\n", " }\n", "\n", " return table;\n", " }());\n", " /**\n", " * CRC32 ハッシュ値を取得\n", " * @param {!(Array.|Uint8Array)} data data byte array.\n", " * @param {number=} pos data position.\n", " * @param {number=} length data length.\n", " * @return {number} CRC32.\n", " */\n", "\n", " Zlib$2.CRC32.calc = function (data, pos, length) {\n", " return Zlib$2.CRC32.update(data, 0, pos, length);\n", " };\n", " /**\n", " * CRC32ハッシュ値を更新\n", " * @param {!(Array.|Uint8Array)} data data byte array.\n", " * @param {number} crc CRC32.\n", " * @param {number=} pos data position.\n", " * @param {number=} length data length.\n", " * @return {number} CRC32.\n", " */\n", "\n", "\n", " Zlib$2.CRC32.update = function (data, crc, pos, length) {\n", " var table = Zlib$2.CRC32.Table;\n", " var i = typeof pos === 'number' ? pos : pos = 0;\n", " var il = typeof length === 'number' ? length : data.length;\n", " crc ^= 0xffffffff; // loop unrolling for performance\n", "\n", " for (i = il & 7; i--; ++pos) {\n", " crc = crc >>> 8 ^ table[(crc ^ data[pos]) & 0xff];\n", " }\n", "\n", " for (i = il >> 3; i--; pos += 8) {\n", " crc = crc >>> 8 ^ table[(crc ^ data[pos]) & 0xff];\n", " crc = crc >>> 8 ^ table[(crc ^ data[pos + 1]) & 0xff];\n", " crc = crc >>> 8 ^ table[(crc ^ data[pos + 2]) & 0xff];\n", " crc = crc >>> 8 ^ table[(crc ^ data[pos + 3]) & 0xff];\n", " crc = crc >>> 8 ^ table[(crc ^ data[pos + 4]) & 0xff];\n", " crc = crc >>> 8 ^ table[(crc ^ data[pos + 5]) & 0xff];\n", " crc = crc >>> 8 ^ table[(crc ^ data[pos + 6]) & 0xff];\n", " crc = crc >>> 8 ^ table[(crc ^ data[pos + 7]) & 0xff];\n", " }\n", "\n", " return (crc ^ 0xffffffff) >>> 0;\n", " };\n", " /**\n", " * @param {number} num\n", " * @param {number} crc\n", " * @returns {number}\n", " */\n", "\n", "\n", " Zlib$2.CRC32.single = function (num, crc) {\n", " return (Zlib$2.CRC32.Table[(num ^ crc) & 0xff] ^ num >>> 8) >>> 0;\n", " };\n", " /**\n", " * @type {Array.}\n", " * @const\n", " * @private\n", " */\n", "\n", "\n", " Zlib$2.CRC32.Table_ = [0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d];\n", " /**\n", " * @type {!(Array.|Uint32Array)} CRC-32 Table.\n", " * @const\n", " */\n", "\n", " Zlib$2.CRC32.Table = new Uint32Array(Zlib$2.CRC32.Table_) ;\n", " /**\n", " * @fileoverview Deflate (RFC1951) 実装.\n", " * Deflateアルゴリズム本体は Zlib.RawDeflate で実装されている.\n", " */\n", "\n", " /**\n", " * Zlib Deflate\n", " * @constructor\n", " * @param {!(Array|Uint8Array)} input 符号化する対象の byte array.\n", " * @param {Object=} opt_params option parameters.\n", " */\n", "\n", " Zlib$2.Deflate = function (input, opt_params) {\n", " /** @type {!(Array|Uint8Array)} */\n", " this.input = input;\n", " /** @type {!(Array|Uint8Array)} */\n", "\n", " this.output = new (Uint8Array )(Zlib$2.Deflate.DefaultBufferSize);\n", " /** @type {Zlib.Deflate.CompressionType} */\n", "\n", " this.compressionType = Zlib$2.Deflate.CompressionType.DYNAMIC;\n", " /** @type {Zlib.RawDeflate} */\n", "\n", " this.rawDeflate;\n", " /** @type {Object} */\n", "\n", " var rawDeflateOption = {};\n", " /** @type {string} */\n", "\n", " var prop; // option parameters\n", "\n", " if (opt_params || !(opt_params = {})) {\n", " if (typeof opt_params['compressionType'] === 'number') {\n", " this.compressionType = opt_params['compressionType'];\n", " }\n", " } // copy options\n", "\n", "\n", " for (prop in opt_params) {\n", " rawDeflateOption[prop] = opt_params[prop];\n", " } // set raw-deflate output buffer\n", "\n", "\n", " rawDeflateOption['outputBuffer'] = this.output;\n", " this.rawDeflate = new Zlib$2.RawDeflate(this.input, rawDeflateOption);\n", " };\n", " /**\n", " * @const\n", " * @type {number} デフォルトバッファサイズ.\n", " */\n", "\n", "\n", " Zlib$2.Deflate.DefaultBufferSize = 0x8000;\n", " /**\n", " * @enum {number}\n", " */\n", "\n", " Zlib$2.Deflate.CompressionType = Zlib$2.RawDeflate.CompressionType;\n", " /**\n", " * 直接圧縮に掛ける.\n", " * @param {!(Array|Uint8Array)} input target buffer.\n", " * @param {Object=} opt_params option parameters.\n", " * @return {!(Array|Uint8Array)} compressed data byte array.\n", " */\n", "\n", " Zlib$2.Deflate.compress = function (input, opt_params) {\n", " return new Zlib$2.Deflate(input, opt_params).compress();\n", " };\n", " /**\n", " * Deflate Compression.\n", " * @return {!(Array|Uint8Array)} compressed data byte array.\n", " */\n", "\n", "\n", " Zlib$2.Deflate.prototype.compress = function () {\n", " /** @type {Zlib.CompressionMethod} */\n", " var cm;\n", " /** @type {number} */\n", "\n", " var cinfo;\n", " /** @type {number} */\n", "\n", " var cmf;\n", " /** @type {number} */\n", "\n", " var flg;\n", " /** @type {number} */\n", "\n", " var fcheck;\n", " /** @type {number} */\n", "\n", " var fdict;\n", " /** @type {number} */\n", "\n", " var flevel;\n", " /** @type {number} */\n", "\n", " var adler;\n", " /** @type {!(Array|Uint8Array)} */\n", "\n", " var output;\n", " /** @type {number} */\n", "\n", " var pos = 0;\n", " output = this.output; // Compression Method and Flags\n", "\n", " cm = Zlib$2.CompressionMethod.DEFLATE;\n", "\n", " switch (cm) {\n", " case Zlib$2.CompressionMethod.DEFLATE:\n", " cinfo = Math.LOG2E * Math.log(Zlib$2.RawDeflate.WindowSize) - 8;\n", " break;\n", "\n", " default:\n", " throw new Error('invalid compression method');\n", " }\n", "\n", " cmf = cinfo << 4 | cm;\n", " output[pos++] = cmf; // Flags\n", "\n", " fdict = 0;\n", "\n", " switch (cm) {\n", " case Zlib$2.CompressionMethod.DEFLATE:\n", " switch (this.compressionType) {\n", " case Zlib$2.Deflate.CompressionType.NONE:\n", " flevel = 0;\n", " break;\n", "\n", " case Zlib$2.Deflate.CompressionType.FIXED:\n", " flevel = 1;\n", " break;\n", "\n", " case Zlib$2.Deflate.CompressionType.DYNAMIC:\n", " flevel = 2;\n", " break;\n", "\n", " default:\n", " throw new Error('unsupported compression type');\n", " }\n", "\n", " break;\n", "\n", " default:\n", " throw new Error('invalid compression method');\n", " }\n", "\n", " flg = flevel << 6 | fdict << 5;\n", " fcheck = 31 - (cmf * 256 + flg) % 31;\n", " flg |= fcheck;\n", " output[pos++] = flg; // Adler-32 checksum\n", "\n", " adler = Zlib$2.Adler32(this.input);\n", " this.rawDeflate.op = pos;\n", " output = this.rawDeflate.compress();\n", " pos = output.length;\n", "\n", " {\n", " // subarray 分を元にもどす\n", " output = new Uint8Array(output.buffer); // expand buffer\n", "\n", " if (output.length <= pos + 4) {\n", " this.output = new Uint8Array(output.length + 4);\n", " this.output.set(output);\n", " output = this.output;\n", " }\n", "\n", " output = output.subarray(0, pos + 4);\n", " } // adler32\n", "\n", "\n", " output[pos++] = adler >> 24 & 0xff;\n", " output[pos++] = adler >> 16 & 0xff;\n", " output[pos++] = adler >> 8 & 0xff;\n", " output[pos++] = adler & 0xff;\n", " return output;\n", " };\n", "\n", " /**\n", " * Covers string literals and String objects\n", " * @param x\n", " * @returns {boolean}\n", " */\n", "\n", " function isString$2(x) {\n", " return typeof x === \"string\" || x instanceof String;\n", " } // StackOverflow: http://stackoverflow.com/a/10810674/116169\n", "\n", "\n", " function numberFormatter(rawNumber) {\n", " var dec = String(rawNumber).split(/[.,]/),\n", " sep = ',',\n", " decsep = '.';\n", " return dec[0].split('').reverse().reduce(function (prev, now, i) {\n", " return i % 3 === 0 ? prev + sep + now : prev + now;\n", " }).split('').reverse().join('') + (dec[1] ? decsep + dec[1] : '');\n", " }\n", "\n", " const numberUnFormatter = formatedNumber => formatedNumber.split(\",\").join().replace(\",\", \"\", \"g\");\n", "\n", " const splitLines = function (string) {\n", " return string.split(/\\n|\\r\\n|\\r/g);\n", " };\n", "\n", " function splitStringRespectingQuotes(string, delim) {\n", " var tokens = [],\n", " len = string.length,\n", " i,\n", " n = 0,\n", " quote = false,\n", " c;\n", "\n", " if (len > 0) {\n", " tokens[n] = string.charAt(0);\n", "\n", " for (i = 1; i < len; i++) {\n", " c = string.charAt(i);\n", "\n", " if (c === '\"') {\n", " quote = !quote;\n", " } else if (!quote && c === delim) {\n", " n++;\n", " tokens[n] = \"\";\n", " } else {\n", " tokens[n] += c;\n", " }\n", " }\n", " }\n", "\n", " return tokens;\n", " }\n", "\n", " function stripQuotes(str) {\n", " if (str === undefined) {\n", " return str;\n", " }\n", "\n", " if (str.startsWith(\"'\") || str.startsWith('\"')) {\n", " str = str.substring(1);\n", " }\n", "\n", " if (str.endsWith(\"'\") || str.endsWith('\"')) {\n", " str = str.substring(0, str.length - 1);\n", " }\n", "\n", " return str;\n", " }\n", " /**\n", " * Compress string and encode in a url safe form\n", " * @param s\n", " */\n", "\n", "\n", " function compressString(str) {\n", " const bytes = [];\n", "\n", " for (var i = 0; i < str.length; i++) {\n", " bytes.push(str.charCodeAt(i));\n", " }\n", "\n", " const compressedBytes = new Zlib$2.RawDeflate(bytes).compress(); // UInt8Arry\n", "\n", " const compressedString = String.fromCharCode.apply(null, compressedBytes); // Convert to string\n", "\n", " let enc = btoa(compressedString);\n", " return enc.replace(/\\+/g, '.').replace(/\\//g, '_').replace(/=/g, '-'); // URL safe\n", " }\n", " /**\n", " * Uncompress the url-safe encoded compressed string, presumably created by compressString above\n", " *\n", " * @param enc\n", " * @returns {string}\n", " */\n", "\n", "\n", " function uncompressString(enc) {\n", " enc = enc.replace(/\\./g, '+').replace(/_/g, '/').replace(/-/g, '=');\n", " const compressedString = atob(enc);\n", " const compressedBytes = [];\n", "\n", " for (let i = 0; i < compressedString.length; i++) {\n", " compressedBytes.push(compressedString.charCodeAt(i));\n", " }\n", "\n", " const bytes = new Zlib$2.RawInflate(compressedBytes).decompress();\n", " let str = '';\n", "\n", " for (let b of bytes) {\n", " str += String.fromCharCode(b);\n", " }\n", "\n", " return str;\n", " }\n", "\n", " function capitalize(str) {\n", " return str.length > 0 ? str.charAt(0).toUpperCase() + str.slice(1) : str;\n", " }\n", "\n", " const FileFormats = {\n", " gwascatalog: {\n", " fields: ['bin', 'chr', 'start', 'end', 'name', 'pubMedID', 'author', 'pubDate', 'journal', 'title', 'trait', 'initSample', 'replSample', 'region', 'genes', 'riskAllele', 'riskAlFreq', 'pValue', 'pValueDesc', 'orOrBeta', 'ci95', 'platform', 'cnv']\n", " },\n", " wgrna: {\n", " fields: ['bin', 'chr', 'start', 'end', 'name', 'score', 'strand', 'thickStart', 'thickEnd', 'type']\n", " },\n", " cpgislandext: {\n", " fields: ['bin', 'chr', 'start', 'end', 'name', 'length', 'cpgNum', 'gcNum', 'perCpg', 'perGc', 'obsExp']\n", " },\n", " clinVarMain: {\n", " fields: ['chr1', 'start', 'end', 'name', 'score', 'strand', 'thickStart', 'thickEnd', 'reserved', 'blockCount', // Number of blocks\n", " 'blockSizes', // Comma separated list of block sizes\n", " 'chromStarts', // Start positions relative to chromStart\n", " 'origName', // NM_198053.2(CD247):c.462C>T (p.Asp154=)\tClinVar Variation Report\n", " 'clinSign', // Likely benign\tClinical significance\n", " 'reviewStatus', // \tbased on: criteria provided,single submitter\tReview Status\n", " 'type', // single nucleotide variant\tType of Variant\n", " 'geneId', // CD247\tGene Symbol\n", " 'snpId', //\t181656780\tdbSNP ID\n", " 'nsvId', //\t\tdbVar ID\n", " 'rcvAcc', //\tRCV000642347\tClinVar Allele Submission\n", " 'testedInGtr', //\tN\tGenetic Testing Registry\n", " 'phenotypeList', //\tImmunodeficiency due to defect in cd3-zeta\tPhenotypes\n", " 'phenotype', //\tMedGen:C1857798, OMIM:610163\tPhenotype identifiers\n", " 'origin', //\tgermline\tData origin\n", " 'assembly', //\tGRCh37\tGenome assembly\n", " 'cytogenetic', //\t1q24.2\tCytogenetic status\n", " 'hgvsCod', //\tNM_198053.2:c.462C>T\tNucleotide HGVS\n", " 'hgvsProt', //\tNP_932170.1:p.Asp154=\tProtein HGVS\n", " 'numSubmit', //\t1\tNumber of submitters\n", " 'lastEval', //\tDec 19,2017\tLast evaluation\n", " 'guidelines', //\t\tGuidelines\n", " 'otherIds']\n", " }\n", " };\n", "\n", " /*\n", " * The MIT License (MIT)\n", " *\n", " * Copyright (c) 2014 Broad Institute\n", " *\n", " * Permission is hereby granted, free of charge, to any person obtaining a copy\n", " * of this software and associated documentation files (the \"Software\"), to deal\n", " * in the Software without restriction, including without limitation the rights\n", " * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n", " * copies of the Software, and to permit persons to whom the Software is\n", " * furnished to do so, subject to the following conditions:\n", " *\n", " * The above copyright notice and this permission notice shall be included in\n", " * all copies or substantial portions of the Software.\n", " *\n", " *\n", " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n", " * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n", " * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n", " * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n", " * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n", " * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n", " * THE SOFTWARE.\n", " */\n", " 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\"]);\n", " /**\n", " * Return a custom format object with the given name.\n", " * @param name\n", " * @returns {*}\n", " */\n", "\n", " function getFormat(name) {\n", " if (FileFormats && FileFormats[name]) {\n", " return expandFormat(FileFormats[name]);\n", " } else {\n", " return undefined;\n", " }\n", "\n", " function expandFormat(format) {\n", " const fields = format.fields;\n", " const keys = ['chr', 'start', 'end'];\n", "\n", " for (let i = 0; i < fields.length; i++) {\n", " for (let key of keys) {\n", " if (key === fields[i]) {\n", " format[key] = i;\n", " }\n", " }\n", " }\n", "\n", " return format;\n", " }\n", " }\n", "\n", " function inferFileFormat(fn) {\n", " var idx, ext;\n", " fn = fn.toLowerCase(); // Special case -- UCSC refgene files\n", "\n", " 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\")) {\n", " return \"refgene\";\n", " } //Strip parameters -- handle local files later\n", "\n", "\n", " idx = fn.indexOf(\"?\");\n", "\n", " if (idx > 0) {\n", " fn = fn.substr(0, idx);\n", " } //Strip aux extensions .gz, .tab, and .txt\n", "\n", "\n", " if (fn.endsWith(\".gz\")) {\n", " fn = fn.substr(0, fn.length - 3);\n", " }\n", "\n", " if (fn.endsWith(\".txt\") || fn.endsWith(\".tab\") || fn.endsWith(\".bgz\")) {\n", " fn = fn.substr(0, fn.length - 4);\n", " }\n", "\n", " idx = fn.lastIndexOf(\".\");\n", " ext = idx < 0 ? fn : fn.substr(idx + 1);\n", "\n", " switch (ext) {\n", " case \"bw\":\n", " return \"bigwig\";\n", "\n", " case \"bb\":\n", " return \"bigbed\";\n", "\n", " default:\n", " if (knownFileExtensions.has(ext)) {\n", " return ext;\n", " } else {\n", " return undefined;\n", " }\n", "\n", " }\n", " }\n", "\n", " function isGoogleURL(url) {\n", " return url.includes(\"googleapis\") && !url.includes(\"urlshortener\") || isGoogleStorageURL(url) || isGoogleDriveURL(url);\n", " }\n", "\n", " function isGoogleStorageURL(url) {\n", " return url.startsWith(\"gs://\") || url.startsWith(\"https://www.googleapis.com/storage\") || url.startsWith(\"https://storage.cloud.google.com\") || url.startsWith(\"https://storage.googleapis.com\");\n", " }\n", "\n", " function isGoogleDriveURL(url) {\n", " return url.indexOf(\"drive.google.com\") >= 0 || url.indexOf(\"www.googleapis.com/drive\") > 0;\n", " }\n", " /**\n", " * Translate gs:// urls to https\n", " * See https://cloud.google.com/storage/docs/json_api/v1\n", " * @param gsUrl\n", " * @returns {string|*}\n", " */\n", "\n", "\n", " function translateGoogleCloudURL(gsUrl) {\n", " let {\n", " bucket,\n", " object\n", " } = parseBucketName(gsUrl);\n", " object = encode(object);\n", " const qIdx = gsUrl.indexOf('?');\n", " const paramString = qIdx > 0 ? gsUrl.substring(qIdx) + \"&alt=media\" : \"?alt=media\";\n", " return `https://storage.googleapis.com/storage/v1/b/${bucket}/o/${object}${paramString}`;\n", " }\n", " /**\n", " * Parse a google bucket and object name from a google storage URL. Known forms include\n", " *\n", " * gs://BUCKET_NAME/OBJECT_NAME\n", " * https://storage.googleapis.com/BUCKET_NAME/OBJECT_NAME\n", " * https://storage.googleapis.com/storage/v1/b/BUCKET_NAME/o/OBJECT_NAME\n", " * https://www.googleapis.com/storage/v1/b/BUCKET_NAME/o/OBJECT_NAME\"\n", " * https://storage.googleapis.com/download/storage/v1/b/BUCKET_NAME/o/OBJECT_NAME\n", " *\n", " * @param url\n", " */\n", "\n", "\n", " function parseBucketName(url) {\n", " let bucket;\n", " let object;\n", "\n", " if (url.startsWith(\"gs://\")) {\n", " const i = url.indexOf('/', 5);\n", "\n", " if (i >= 0) {\n", " bucket = url.substring(5, i);\n", " const qIdx = url.indexOf('?');\n", " object = qIdx < 0 ? url.substring(i + 1) : url.substring(i + 1, qIdx);\n", " }\n", " } else if (url.startsWith(\"https://storage.googleapis.com\") || url.startsWith(\"https://storage.cloud.google.com\")) {\n", " const bucketIdx = url.indexOf(\"/v1/b/\", 8);\n", "\n", " if (bucketIdx > 0) {\n", " const objIdx = url.indexOf(\"/o/\", bucketIdx);\n", "\n", " if (objIdx > 0) {\n", " const queryIdx = url.indexOf(\"?\", objIdx);\n", " bucket = url.substring(bucketIdx + 6, objIdx);\n", " object = queryIdx > 0 ? url.substring(objIdx + 3, queryIdx) : url.substring(objIdx + 3);\n", " }\n", " } else {\n", " const idx1 = url.indexOf(\"/\", 8);\n", " const idx2 = url.indexOf(\"/\", idx1 + 1);\n", " const idx3 = url.indexOf(\"?\", idx2);\n", "\n", " if (idx2 > 0) {\n", " bucket = url.substring(idx1 + 1, idx2);\n", " object = idx3 < 0 ? url.substring(idx2 + 1) : url.substring(idx2 + 1, idx3);\n", " }\n", " }\n", " } else if (url.startsWith(\"https://www.googleapis.com/storage/v1/b\")) {\n", " const bucketIdx = url.indexOf(\"/v1/b/\", 8);\n", " const objIdx = url.indexOf(\"/o/\", bucketIdx);\n", "\n", " if (objIdx > 0) {\n", " const queryIdx = url.indexOf(\"?\", objIdx);\n", " bucket = url.substring(bucketIdx + 6, objIdx);\n", " object = queryIdx > 0 ? url.substring(objIdx + 3, queryIdx) : url.substring(objIdx + 3);\n", " }\n", " }\n", "\n", " if (bucket && object) {\n", " return {\n", " bucket,\n", " object\n", " };\n", " } else {\n", " throw Error(`Unrecognized Google Storage URI: ${url}`);\n", " }\n", " }\n", "\n", " function driveDownloadURL(link) {\n", " // Return a google drive download url for the sharable link\n", " //https://drive.google.com/open?id=0B-lleX9c2pZFbDJ4VVRxakJzVGM\n", " //https://drive.google.com/file/d/1_FC4kCeO8E3V4dJ1yIW7A0sn1yURKIX-/view?usp=sharing\n", " var id = getGoogleDriveFileID(link);\n", " return id ? \"https://www.googleapis.com/drive/v3/files/\" + id + \"?alt=media&supportsTeamDrives=true\" : link;\n", " }\n", "\n", " function getGoogleDriveFileID(link) {\n", " //https://drive.google.com/file/d/1_FC4kCeO8E3V4dJ1yIW7A0sn1yURKIX-/view?usp=sharing\n", " //https://www.googleapis.com/drive/v3/files/1w-tvo6p1SH4p1OaQSVxpkV_EJgGIstWF?alt=media&supportsTeamDrives=true\"\n", " if (link.includes(\"/open?id=\")) {\n", " const i1 = link.indexOf(\"/open?id=\") + 9;\n", " const i2 = link.indexOf(\"&\");\n", "\n", " if (i1 > 0 && i2 > i1) {\n", " return link.substring(i1, i2);\n", " } else if (i1 > 0) {\n", " return link.substring(i1);\n", " }\n", " } else if (link.includes(\"/file/d/\")) {\n", " const i1 = link.indexOf(\"/file/d/\") + 8;\n", " const i2 = link.lastIndexOf(\"/\");\n", " return link.substring(i1, i2);\n", " } else if (link.startsWith(\"https://www.googleapis.com/drive\")) {\n", " let i1 = link.indexOf(\"/files/\");\n", " const i2 = link.indexOf(\"?\");\n", "\n", " if (i1 > 0) {\n", " i1 += 7;\n", " return i2 > 0 ? link.substring(i1, i2) : link.substring(i1);\n", " }\n", " }\n", "\n", " throw Error(\"Unknown Google Drive url format: \" + link);\n", " }\n", " /**\n", " * Percent a GCS object name. See https://cloud.google.com/storage/docs/request-endpoints\n", " * Specific characters to encode:\n", " * !, #, $, &, ', (, ), *, +, ,, /, :, ;, =, ?, @, [, ], and space characters.\n", " * @param obj\n", " */\n", "\n", "\n", " function encode(objectName) {\n", " let result = '';\n", " objectName.split('').forEach(function (letter) {\n", " if (encodings.has(letter)) {\n", " result += encodings.get(letter);\n", " } else {\n", " result += letter;\n", " }\n", " });\n", " return result;\n", " } //\t%23\t%24\t%25\t%26\t%27\t%28\t%29\t%2A\t%2B\t%2C\t%2F\t%3A\t%3B\t%3D\t%3F\t%40\t%5B\t%5D\n", "\n", "\n", " const encodings = new Map();\n", " encodings.set(\"!\", \"%21\");\n", " encodings.set(\"#\", \"%23\");\n", " encodings.set(\"$\", \"%24\");\n", " encodings.set(\"%\", \"%25\");\n", " encodings.set(\"&\", \"%26\");\n", " encodings.set(\"'\", \"%27\");\n", " encodings.set(\"(\", \"%28\");\n", " encodings.set(\")\", \"%29\");\n", " encodings.set(\"*\", \"%2A\");\n", " encodings.set(\"+\", \"%2B\");\n", " encodings.set(\",\", \"%2C\");\n", " encodings.set(\"/\", \"%2F\");\n", " encodings.set(\":\", \"%3A\");\n", " encodings.set(\";\", \"%3B\");\n", " encodings.set(\"=\", \"%3D\");\n", " encodings.set(\"?\", \"%3F\");\n", " encodings.set(\"@\", \"%40\");\n", " encodings.set(\"[\", \"%5B\");\n", " encodings.set(\"]\", \"%5D\");\n", " encodings.set(\" \", \"%20\"); // For testing\n", "\n", " // Convenience functions for the gapi oAuth library.\n", " const FIVE_MINUTES = 5 * 60 * 1000;\n", "\n", " function isInitialized() {\n", " return typeof gapi !== \"undefined\" && gapi.auth2 && gapi.auth2.getAuthInstance();\n", " }\n", "\n", " let inProgress = false;\n", "\n", " async function getAccessToken(scope) {\n", " if (typeof gapi === \"undefined\") {\n", " throw Error(\"Google authentication requires the 'gapi' library\");\n", " }\n", "\n", " if (!gapi.auth2) {\n", " throw Error(\"Google 'auth2' has not been initialized\");\n", " }\n", "\n", " if (inProgress) {\n", " return new Promise(function (resolve, reject) {\n", " let intervalID;\n", "\n", " const checkForToken = () => {\n", " // Wait for inProgress to equal \"false\"\n", " try {\n", " if (inProgress === false) {\n", " //console.log(\"Delayed resolution for \" + scope);\n", " resolve(getAccessToken(scope));\n", " clearInterval(intervalID);\n", " }\n", " } catch (e) {\n", " clearInterval(intervalID);\n", " reject(e);\n", " }\n", " };\n", "\n", " intervalID = setInterval(checkForToken, 100);\n", " });\n", " } else {\n", " inProgress = true;\n", "\n", " try {\n", " let currentUser = gapi.auth2.getAuthInstance().currentUser.get();\n", " let token;\n", "\n", " if (currentUser.isSignedIn()) {\n", " if (!currentUser.hasGrantedScopes(scope)) {\n", " await currentUser.grant({\n", " scope\n", " });\n", " }\n", "\n", " const {\n", " access_token,\n", " expires_at\n", " } = currentUser.getAuthResponse();\n", "\n", " if (Date.now() < expires_at - FIVE_MINUTES) {\n", " token = {\n", " access_token,\n", " expires_at\n", " };\n", " } else {\n", " const {\n", " access_token,\n", " expires_at\n", " } = currentUser.reloadAuthResponse();\n", " token = {\n", " access_token,\n", " expires_at\n", " };\n", " }\n", " } else {\n", " currentUser = await signIn(scope);\n", " const {\n", " access_token,\n", " expires_at\n", " } = currentUser.getAuthResponse();\n", " token = {\n", " access_token,\n", " expires_at\n", " };\n", " }\n", "\n", " return token;\n", " } finally {\n", " inProgress = false;\n", " }\n", " }\n", " }\n", " /**\n", " * Return the current access token if the user is signed in, or undefined otherwise. This function does not\n", " * attempt a signIn or request any specfic scopes.\n", " *\n", " * @returns access_token || undefined\n", " */\n", "\n", "\n", " function getCurrentAccessToken() {\n", " let currentUser = gapi.auth2.getAuthInstance().currentUser.get();\n", "\n", " if (currentUser && currentUser.isSignedIn()) {\n", " const {\n", " access_token,\n", " expires_at\n", " } = currentUser.getAuthResponse();\n", " return {\n", " access_token,\n", " expires_at\n", " };\n", " } else {\n", " return undefined;\n", " }\n", " }\n", "\n", " async function signIn(scope) {\n", " const options = new gapi.auth2.SigninOptionsBuilder();\n", " options.setPrompt('select_account');\n", " options.setScope(scope);\n", " return gapi.auth2.getAuthInstance().signIn(options);\n", " }\n", "\n", " function getScopeForURL(url) {\n", " if (isGoogleDriveURL(url)) {\n", " return \"https://www.googleapis.com/auth/drive.file\";\n", " } else if (isGoogleStorageURL(url)) {\n", " return \"https://www.googleapis.com/auth/devstorage.read_only\";\n", " } else {\n", " return 'https://www.googleapis.com/auth/userinfo.profile';\n", " }\n", " }\n", "\n", " function getApiKey() {\n", " return gapi.apiKey;\n", " }\n", "\n", " async function getDriveFileInfo(googleDriveURL) {\n", " const id = getGoogleDriveFileID(googleDriveURL);\n", " let endPoint = \"https://www.googleapis.com/drive/v3/files/\" + id + \"?supportsTeamDrives=true\";\n", " const apiKey = getApiKey();\n", "\n", " if (apiKey) {\n", " endPoint += \"&key=\" + apiKey;\n", " }\n", "\n", " const response = await fetch(endPoint);\n", " let json = await response.json();\n", "\n", " if (json.error && json.error.code === 404) {\n", " const {\n", " access_token\n", " } = await getAccessToken(\"https://www.googleapis.com/auth/drive.readonly\");\n", "\n", " if (access_token) {\n", " const response = await fetch(endPoint, {\n", " headers: {\n", " 'Authorization': `Bearer ${access_token}`\n", " }\n", " });\n", " json = await response.json();\n", "\n", " if (json.error) {\n", " throw Error(json.error);\n", " }\n", " } else {\n", " throw Error(json.error);\n", " }\n", " }\n", "\n", " return json;\n", " }\n", "\n", " if (typeof process === 'object' && typeof window === 'undefined') {\n", " global.atob = function (str) {\n", " return Buffer.from(str, 'base64').toString('binary');\n", " };\n", " }\n", " /**\n", " * @param dataURI\n", " * @returns {Array|Uint8Array}\n", " */\n", "\n", "\n", " function decodeDataURI(dataURI) {\n", " const split = dataURI.split(',');\n", " const info = split[0].split(':')[1];\n", " let dataString = split[1];\n", "\n", " if (info.indexOf('base64') >= 0) {\n", " dataString = atob(dataString);\n", " } else {\n", " dataString = decodeURI(dataString); // URL encoded string -- not currently used of tested\n", " }\n", "\n", " const bytes = new Uint8Array(dataString.length);\n", "\n", " for (let i = 0; i < dataString.length; i++) {\n", " bytes[i] = dataString.charCodeAt(i);\n", " }\n", "\n", " let plain;\n", "\n", " if (info.indexOf('gzip') > 0) {\n", " const inflate = new Zlib$2.Gunzip(bytes);\n", " plain = inflate.decompress();\n", " } else {\n", " plain = bytes;\n", " }\n", "\n", " return plain;\n", " }\n", "\n", " function parseUri(str) {\n", " var o = options,\n", " m = o.parser[\"loose\"].exec(str),\n", " uri = {},\n", " i = 14;\n", "\n", " while (i--) uri[o.key[i]] = m[i] || \"\";\n", "\n", " uri[o.q.name] = {};\n", " uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) {\n", " if ($1) uri[o.q.name][$1] = $2;\n", " });\n", " return uri;\n", " }\n", "\n", " const options = {\n", " strictMode: false,\n", " key: [\"source\", \"protocol\", \"authority\", \"userInfo\", \"user\", \"password\", \"host\", \"port\", \"relative\", \"path\", \"directory\", \"file\", \"query\", \"anchor\"],\n", " q: {\n", " name: \"queryKey\",\n", " parser: /(?:^|&)([^&=]*)=?([^&]*)/g\n", " },\n", " parser: {\n", " strict: /^(?:([^:\\/?#]+):)?(?:\\/\\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\\/?#]*)(?::(\\d*))?))?((((?:[^?#\\/]*\\/)*)([^?#]*))(?:\\?([^#]*))?(?:#(.*))?)/,\n", " loose: /^(?:(?![^:@]+:[^:@\\/]*@)([^:\\/?#.]+):)?(?:\\/\\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\\/?#]*)(?::(\\d*))?)(((\\/(?:[^?#](?![^?#\\/]*\\.[^?#\\/.]+(?:[?#]|$)))*\\/?)?([^?#\\/]*))(?:\\?([^#]*))?(?:#(.*))?)/\n", " }\n", " };\n", " /**\n", " * Resolve a url, which might be a string, function (that returns a string or Promse), or Promise (that resolves to a string)\n", " *\n", " * @param url\n", " * @returns {Promise<*>}\n", " */\n", "\n", "\n", " async function resolveURL(url) {\n", " return typeof url === 'function' ? url() : url;\n", " }\n", "\n", " /**\n", " * Return the filename from the path. Example\n", " * https://foo.com/bar.bed?param=2 => bar.bed\n", " * @param urlOrFile\n", " */\n", "\n", "\n", " function getFilename$2(urlOrFile) {\n", " if (urlOrFile.name !== undefined) {\n", " return urlOrFile.name;\n", " } else if (isString$2(urlOrFile)) {\n", " let index = urlOrFile.lastIndexOf(\"/\");\n", " let filename = index < 0 ? urlOrFile : urlOrFile.substr(index + 1); //Strip parameters -- handle local files later\n", "\n", " index = filename.indexOf(\"?\");\n", "\n", " if (index > 0) {\n", " filename = filename.substr(0, index);\n", " }\n", "\n", " return filename;\n", " } else {\n", " throw Error(`Expected File or string, got ${typeof urlOrFile}`);\n", " }\n", " }\n", "\n", " async function getFilenameExtended(path) {\n", " if (isFile$1(path)) {\n", " return path.name;\n", " } else if (isGoogleDriveURL(path)) {\n", " if (typeof gapi === \"undefined\") {\n", " throw Error(`Google initialization with API key is required to load Google urls (${path})`);\n", " }\n", "\n", " const info = await getDriveFileInfo(path);\n", " return info.name || info.originalFileName;\n", " } else {\n", " const result = parseUri(path);\n", " return result.file;\n", " }\n", " }\n", " /**\n", " * Test if object is a File or File-like object.\n", " *\n", " * @param object\n", " */\n", "\n", "\n", " function isFile$1(object) {\n", " if (!object) {\n", " return false;\n", " }\n", "\n", " return typeof object !== 'function' && (object instanceof File || object.hasOwnProperty(\"name\") && typeof object.slice === 'function' && typeof object.arrayBuffer === 'function');\n", " }\n", "\n", " // Uncompress data, assumed to be series of bgzipped blocks\n", "\n", " function unbgzf(data, lim) {\n", " const oBlockList = [];\n", " let ptr = 0;\n", " let totalSize = 0;\n", " lim = lim || data.byteLength - 18;\n", "\n", " while (ptr < lim) {\n", " try {\n", " const ba = new Uint8Array(data, ptr, 18);\n", " const xlen = ba[11] << 8 | ba[10];\n", " const si1 = ba[12];\n", " const si2 = ba[13];\n", " const slen = ba[15] << 8 | ba[14];\n", " const bsize = (ba[17] << 8 | ba[16]) + 1;\n", " const start = 12 + xlen + ptr; // Start of CDATA\n", "\n", " const bytesLeft = data.byteLength - start;\n", " const cDataSize = bsize - xlen - 19;\n", " if (bytesLeft < cDataSize || cDataSize <= 0) break;\n", " const a = new Uint8Array(data, start, cDataSize);\n", " const inflate = new Zlib$2.RawInflate(a);\n", " const unc = inflate.decompress();\n", " ptr += inflate.ip + 26;\n", " totalSize += unc.byteLength;\n", " oBlockList.push(unc);\n", " } catch (e) {\n", " console.error(e);\n", " break;\n", " }\n", " } // Concatenate decompressed blocks\n", "\n", "\n", " if (oBlockList.length === 1) {\n", " return oBlockList[0];\n", " } else {\n", " const out = new Uint8Array(totalSize);\n", " let cursor = 0;\n", "\n", " for (let i = 0; i < oBlockList.length; ++i) {\n", " var b = new Uint8Array(oBlockList[i]);\n", " arrayCopy(b, 0, out, cursor, b.length);\n", " cursor += b.length;\n", " }\n", "\n", " return out;\n", " }\n", " }\n", "\n", " function bgzBlockSize(data) {\n", " const ba = new Uint8Array(data);\n", " const bsize = (ba[17] << 8 | ba[16]) + 1;\n", " return bsize;\n", " } // From Thomas Down's zlib implementation\n", "\n", "\n", " const testArray = new Uint8Array(1);\n", " const hasSubarray = typeof testArray.subarray === 'function';\n", " /* (typeof testArray.slice === 'function'); */\n", " // Chrome slice performance is so dire that we're currently not using it...\n", "\n", " function arrayCopy(src, srcOffset, dest, destOffset, count) {\n", " if (count === 0) {\n", " return;\n", " }\n", "\n", " if (!src) {\n", " throw \"Undef src\";\n", " } else if (!dest) {\n", " throw \"Undef dest\";\n", " }\n", "\n", " if (srcOffset === 0 && count === src.length) {\n", " arrayCopy_fast(src, dest, destOffset);\n", " } else if (hasSubarray) {\n", " arrayCopy_fast(src.subarray(srcOffset, srcOffset + count), dest, destOffset);\n", " } else if (src.BYTES_PER_ELEMENT === 1 && count > 100) {\n", " arrayCopy_fast(new Uint8Array(src.buffer, src.byteOffset + srcOffset, count), dest, destOffset);\n", " } else {\n", " arrayCopy_slow(src, srcOffset, dest, destOffset, count);\n", " }\n", " }\n", "\n", " function arrayCopy_slow(src, srcOffset, dest, destOffset, count) {\n", " for (let i = 0; i < count; ++i) {\n", " dest[destOffset + i] = src[srcOffset + i];\n", " }\n", " }\n", "\n", " function arrayCopy_fast(src, dest, destOffset) {\n", " dest.set(src, destOffset);\n", " }\n", "\n", " /*\n", " * The MIT License (MIT)\n", " *\n", " * Copyright (c) 2016-2017 The Regents of the University of California\n", " * Author: Jim Robinson\n", " *\n", " * Permission is hereby granted, free of charge, to any person obtaining a copy\n", " * of this software and associated documentation files (the \"Software\"), to deal\n", " * in the Software without restriction, including without limitation the rights\n", " * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n", " * copies of the Software, and to permit persons to whom the Software is\n", " * furnished to do so, subject to the following conditions:\n", " *\n", " * The above copyright notice and this permission notice shall be included in\n", " * all copies or substantial portions of the Software.\n", " *\n", " *\n", " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n", " * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n", " * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n", " * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n", " * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n", " * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n", " * THE SOFTWARE.\n", " */\n", " const IGVMath = {\n", " lerp: (v0, v1, t) => {\n", " return (1 - t) * v0 + t * v1;\n", " },\n", " mean: function (array) {\n", " var t = 0,\n", " n = 0,\n", " i;\n", "\n", " for (i = 0; i < array.length; i++) {\n", " if (!isNaN(array[i])) {\n", " t += array[i];\n", " n++;\n", " }\n", " }\n", "\n", " return n > 0 ? t / n : 0;\n", " },\n", " meanAndStdev: function (array) {\n", " var v,\n", " t = 0,\n", " t2 = 0,\n", " n = 0,\n", " i;\n", "\n", " for (i = 0; i < array.length; i++) {\n", " v = array[i];\n", "\n", " if (!isNaN(v)) {\n", " t += v;\n", " t2 += v * v;\n", " n++;\n", " }\n", " }\n", "\n", " return n > 0 ? {\n", " mean: t / n,\n", " stdev: Math.sqrt(t2 - t * t / n)\n", " } : {\n", " mean: 0,\n", " stdev: 0\n", " };\n", " },\n", " median: function (numbers) {\n", " // median of [3, 5, 4, 4, 1, 1, 2, 3] = 3\n", " var median = 0,\n", " numsLen = numbers.length;\n", " numbers.sort();\n", "\n", " if (numsLen % 2 === 0 // is even\n", " ) {\n", " // average of two middle numbers\n", " median = (numbers[numsLen / 2 - 1] + numbers[numsLen / 2]) / 2;\n", " } else {\n", " // is odd\n", " // middle number only\n", " median = numbers[(numsLen - 1) / 2];\n", " }\n", "\n", " return median;\n", " },\n", " // Fast percentile function for \"p\" near edges. This needs profiled for p in middle (e.g. median)\n", " percentile: function (array, p) {\n", " if (array.length === 0) return undefined;\n", " var k = Math.floor(array.length * ((100 - p) / 100));\n", "\n", " if (k === 0) {\n", " array.sort(function (a, b) {\n", " return b - a;\n", " });\n", " return array[k];\n", " } else {\n", " return selectElement(array, k);\n", " }\n", " },\n", " clamp: function (value, min, max) {\n", " return Math.min(Math.max(value, min), max);\n", " },\n", " log2: function (x) {\n", " return Math.log(x) / Math.LN2;\n", " }\n", " };\n", "\n", " function selectElement(array, k) {\n", " // Credit Steve Hanov http://stevehanov.ca/blog/index.php?id=122\n", " var heap = new BinaryHeap(),\n", " i;\n", "\n", " for (i = 0; i < array.length; i++) {\n", " var item = array[i]; // If we have not yet found k items, or the current item is larger than\n", " // the smallest item on the heap, add current item\n", "\n", " if (heap.content.length < k || item > heap.content[0]) {\n", " // If the heap is full, remove the smallest element on the heap.\n", " if (heap.content.length === k) {\n", " heap.pop();\n", " }\n", "\n", " heap.push(item);\n", " }\n", " }\n", "\n", " return heap.content[0];\n", " }\n", "\n", " function BinaryHeap() {\n", " this.content = [];\n", " }\n", "\n", " BinaryHeap.prototype = {\n", " push: function (element) {\n", " // Add the new element to the end of the array.\n", " this.content.push(element); // Allow it to bubble up.\n", "\n", " this.bubbleUp(this.content.length - 1);\n", " },\n", " pop: function () {\n", " // Store the first element so we can return it later.\n", " var result = this.content[0]; // Get the element at the end of the array.\n", "\n", " var end = this.content.pop(); // If there are any elements left, put the end element at the\n", " // start, and let it sink down.\n", "\n", " if (this.content.length > 0) {\n", " this.content[0] = end;\n", " this.sinkDown(0);\n", " }\n", "\n", " return result;\n", " },\n", " remove: function (node) {\n", " var length = this.content.length; // To remove a value, we must search through the array to find\n", " // it.\n", "\n", " for (var i = 0; i < length; i++) {\n", " if (this.content[i] !== node) continue; // When it is found, the process seen in 'pop' is repeated\n", " // to fill up the hole.\n", "\n", " var end = this.content.pop(); // If the element we popped was the one we needed to remove,\n", " // we're done.\n", "\n", " if (i === length - 1) break; // Otherwise, we replace the removed element with the popped\n", " // one, and allow it to float up or sink down as appropriate.\n", "\n", " this.content[i] = end;\n", " this.bubbleUp(i);\n", " this.sinkDown(i);\n", " break;\n", " }\n", " },\n", " size: function () {\n", " return this.content.length;\n", " },\n", " bubbleUp: function (n) {\n", " // Fetch the element that has to be moved.\n", " var element = this.content[n],\n", " score = element; // When at 0, an element can not go up any further.\n", "\n", " while (n > 0) {\n", " // Compute the parent element's index, and fetch it.\n", " var parentN = Math.floor((n + 1) / 2) - 1,\n", " parent = this.content[parentN]; // If the parent has a lesser score, things are in order and we\n", " // are done.\n", "\n", " if (score >= parent) break; // Otherwise, swap the parent with the current element and\n", " // continue.\n", "\n", " this.content[parentN] = element;\n", " this.content[n] = parent;\n", " n = parentN;\n", " }\n", " },\n", " sinkDown: function (n) {\n", " // Look up the target element and its score.\n", " var length = this.content.length,\n", " element = this.content[n],\n", " elemScore = element;\n", "\n", " while (true) {\n", " // Compute the indices of the child elements.\n", " var child2N = (n + 1) * 2,\n", " child1N = child2N - 1; // This is used to store the new position of the element,\n", " // if any.\n", "\n", " var swap = null; // If the first child exists (is inside the array)...\n", "\n", " if (child1N < length) {\n", " // Look it up and compute its score.\n", " var child1 = this.content[child1N],\n", " child1Score = child1; // If the score is less than our element's, we need to swap.\n", "\n", " if (child1Score < elemScore) swap = child1N;\n", " } // Do the same checks for the other child.\n", "\n", "\n", " if (child2N < length) {\n", " var child2 = this.content[child2N],\n", " child2Score = child2;\n", " if (child2Score < (swap == null ? elemScore : child1Score)) swap = child2N;\n", " } // No need to swap further, we are done.\n", "\n", "\n", " if (swap == null) break; // Otherwise, swap and continue.\n", "\n", " this.content[n] = this.content[swap];\n", " this.content[swap] = element;\n", " n = swap;\n", " }\n", " }\n", " };\n", "\n", " /*\n", " * The MIT License (MIT)\n", " *\n", " * Copyright (c) 2014 Broad Institute\n", " *\n", " * Permission is hereby granted, free of charge, to any person obtaining a copy\n", " * of this software and associated documentation files (the \"Software\"), to deal\n", " * in the Software without restriction, including without limitation the rights\n", " * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n", " * copies of the Software, and to permit persons to whom the Software is\n", " * furnished to do so, subject to the following conditions:\n", " *\n", " * The above copyright notice and this permission notice shall be included in\n", " * all copies or substantial portions of the Software.\n", " *\n", " *\n", " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n", " * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n", " * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n", " * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n", " * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n", " * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n", " * THE SOFTWARE.\n", " */\n", "\n", " function _random(min, max) {\n", " return Math.random() * (max - min) + min;\n", " }\n", "\n", " const IGVColor = {\n", " rgbListFromHSV: () => {\n", " let s = 1;\n", " let accumulation = [];\n", "\n", " for (let v = 1; v >= 0.5; v -= .1) {\n", " for (let h = 0; h < 1; h += 1 / 28) {\n", " const r = \"rgb(\" + IGVColor.hsvToRgb(h, s, v).join(\",\") + \")\";\n", " accumulation.push(r);\n", " }\n", " } // add black\n", "\n", "\n", " accumulation.pop();\n", " accumulation.push(IGVColor.rgbColor(16, 16, 16));\n", " return accumulation;\n", " },\n", " rgbToHex: function (rgb) {\n", " rgb = rgb.match(/^rgba?[\\s+]?\\([\\s+]?(\\d+)[\\s+]?,[\\s+]?(\\d+)[\\s+]?,[\\s+]?(\\d+)[\\s+]?/i);\n", " 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) : '';\n", " },\n", " hexToRgb: function (hex) {\n", " var cooked = /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i.exec(hex);\n", "\n", " if (null === cooked) {\n", " return undefined;\n", " }\n", "\n", " return \"rgb(\" + parseInt(cooked[1], 16) + \",\" + parseInt(cooked[2], 16) + \",\" + parseInt(cooked[3], 16) + \")\";\n", " },\n", "\n", " /**\n", " * Converts an HSV color value to RGB. Conversion formula\n", " * adapted from http://en.wikipedia.org/wiki/HSV_color_space.\n", " * Assumes h, s, and v are contained in the set [0, 1] and\n", " * returns r, g, and b in the set [0, 255].\n", " *\n", " * Credit: https://gist.githubusercontent.com/mjackson/5311256\n", " *\n", " * @param h The hue\n", " * @param s The saturation\n", " * @param v The value\n", " * @return Array The RGB representation\n", " */\n", " hsvToRgb: function (h, s, v) {\n", " var r, g, b;\n", " var i = Math.floor(h * 6);\n", " var f = h * 6 - i;\n", " var p = v * (1 - s);\n", " var q = v * (1 - f * s);\n", " var t = v * (1 - (1 - f) * s);\n", "\n", " switch (i % 6) {\n", " case 0:\n", " r = v, g = t, b = p;\n", " break;\n", "\n", " case 1:\n", " r = q, g = v, b = p;\n", " break;\n", "\n", " case 2:\n", " r = p, g = v, b = t;\n", " break;\n", "\n", " case 3:\n", " r = p, g = q, b = v;\n", " break;\n", "\n", " case 4:\n", " r = t, g = p, b = v;\n", " break;\n", "\n", " case 5:\n", " r = v, g = p, b = q;\n", " break;\n", " }\n", "\n", " return [Math.floor(r * 255), Math.floor(g * 255), Math.floor(b * 255)];\n", " },\n", "\n", " /**\n", " * Converts an HSL color value to RGB. Conversion formula\n", " * adapted from http://en.wikipedia.org/wiki/HSL_color_space.\n", " * Assumes h, s, and l are contained in the set [0, 1] and\n", " * returns r, g, and b in the set [0, 255].\n", " *\n", " * Credit: https://gist.githubusercontent.com/mjackson/5311256\n", " *\n", " * @param h The hue\n", " * @param s The saturation\n", " * @param l The lightness\n", " * @return Array The RGB representation\n", " */\n", " hslToRgb: function (h, s, l) {\n", " var r, g, b;\n", "\n", " if (s === 0) {\n", " r = g = b = l; // achromatic\n", " } else {\n", " var q = l < 0.5 ? l * (1 + s) : l + s - l * s;\n", " var p = 2 * l - q;\n", " r = IGVColor.hue2rgb(p, q, h + 1 / 3);\n", " g = IGVColor.hue2rgb(p, q, h);\n", " b = IGVColor.hue2rgb(p, q, h - 1 / 3);\n", " }\n", "\n", " return [r * 255, g * 255, b * 255];\n", " },\n", " hue2rgb: (p, q, t) => {\n", " if (t < 0) t += 1;\n", " if (t > 1) t -= 1;\n", " if (t < 1 / 6) return p + (q - p) * 6 * t;\n", " if (t < 1 / 2) return q;\n", " if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;\n", " return p;\n", " },\n", " rgbaColor: function (r, g, b, a) {\n", " r = IGVMath.clamp(r, 0, 255);\n", " g = IGVMath.clamp(g, 0, 255);\n", " b = IGVMath.clamp(b, 0, 255);\n", " a = IGVMath.clamp(a, 0.0, 1.0);\n", " return \"rgba(\" + r + \",\" + g + \",\" + b + \",\" + a + \")\";\n", " },\n", " rgbColor: function (r, g, b) {\n", " r = IGVMath.clamp(r, 0, 255);\n", " g = IGVMath.clamp(g, 0, 255);\n", " b = IGVMath.clamp(b, 0, 255);\n", " return \"rgb(\" + r + \",\" + g + \",\" + b + \")\";\n", " },\n", " greyScale: function (value) {\n", " var grey = IGVMath.clamp(value, 0, 255);\n", " return \"rgb(\" + grey + \",\" + grey + \",\" + grey + \")\";\n", " },\n", " randomGrey: function (min, max) {\n", " min = IGVMath.clamp(min, 0, 255);\n", " max = IGVMath.clamp(max, 0, 255);\n", " var g = Math.round(_random(min, max)).toString(10);\n", " return \"rgb(\" + g + \",\" + g + \",\" + g + \")\";\n", " },\n", " randomRGB: function (min, max) {\n", " min = IGVMath.clamp(min, 0, 255);\n", " max = IGVMath.clamp(max, 0, 255);\n", " var r = Math.round(_random(min, max)).toString(10);\n", " var g = Math.round(_random(min, max)).toString(10);\n", " var b = Math.round(_random(min, max)).toString(10);\n", " return \"rgb(\" + r + \",\" + g + \",\" + b + \")\";\n", " },\n", " randomRGBConstantAlpha: function (min, max, alpha) {\n", " min = IGVMath.clamp(min, 0, 255);\n", " max = IGVMath.clamp(max, 0, 255);\n", " var r = Math.round(_random(min, max)).toString(10);\n", " var g = Math.round(_random(min, max)).toString(10);\n", " var b = Math.round(_random(min, max)).toString(10);\n", " return \"rgba(\" + r + \",\" + g + \",\" + b + \",\" + alpha + \")\";\n", " },\n", " addAlpha: function (color, alpha) {\n", " if (color === \"0\" || color === \".\") {\n", " color = \"rgb(0,0,0)\";\n", " } else {\n", " const c = this.colorNameToHex(color);\n", "\n", " if (c) {\n", " color = c;\n", " }\n", " }\n", "\n", " var isHex = /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(color);\n", "\n", " if (color.startsWith(\"rgba\")) {\n", " const idx = color.lastIndexOf(\",\");\n", " return color.substring(0, idx + 1) + alpha.toString() + \")\";\n", " }\n", "\n", " if (isHex) {\n", " color = IGVColor.hexToRgb(color);\n", " }\n", "\n", " if (color.startsWith(\"rgb\")) {\n", " return color.replace(\"rgb\", \"rgba\").replace(\")\", \", \" + alpha + \")\");\n", " } else {\n", " console.log(color + \" is not an rgb style string\");\n", " return color;\n", " }\n", " },\n", " rgbComponents: function (color) {\n", " if (color === \"0\" || color === \".\") {\n", " return [0, 0, 0];\n", " }\n", "\n", " const isHex = /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(color);\n", "\n", " if (isHex) {\n", " color = IGVColor.hexToRgb(color);\n", " } else {\n", " if (!color.startsWith(\"rgb\")) {\n", " const hex = this.colorNameToHex(color);\n", " color = this.hexToRgb(hex);\n", " }\n", " }\n", "\n", " if (color.startsWith(\"rgb(\")) {\n", " return color.substring(4, color.length - 1).split(\",\").map(s => Number.parseInt(s.trim()));\n", " } else if (color.startsWith(\"rgba(\")) {\n", " return color.substring(5, color.length - 1).split(\",\").map((s, i) => {\n", " s = s.trim();\n", " return i === 3 ? Number.parseFloat(s) : Number.parseInt(s);\n", " });\n", " } else {\n", " throw Error(\"Unrecognized color string: color\");\n", " }\n", " },\n", "\n", " /**\n", " *\n", " * @param dest RGB components as an array\n", " * @param src RGB components as an array\n", " * @param alpha alpha transparancy in the range 0-1\n", " * @returns {}\n", " */\n", " getCompositeColor: function (dest, src, alpha) {\n", " var r = Math.floor(alpha * src[0] + (1 - alpha) * dest[0]),\n", " g = Math.floor(alpha * src[1] + (1 - alpha) * dest[1]),\n", " b = Math.floor(alpha * src[2] + (1 - alpha) * dest[2]);\n", " return \"rgb(\" + r + \",\" + g + \",\" + b + \")\";\n", " },\n", " createColorString: function (str) {\n", " // Excel will quote color strings, strip all quotes\n", " str = stripQuotes(str);\n", "\n", " if (str.includes(\",\")) {\n", " return str.startsWith(\"rgb\") ? str : \"rgb(\" + str + \")\";\n", " } else {\n", " return str;\n", " }\n", " },\n", " darkenLighten: function (color, amt) {\n", " let src;\n", " let hexColor = this.colorNameToHex(color);\n", "\n", " if (hexColor) {\n", " src = IGVColor.hexToRgb(hexColor);\n", " } else {\n", " src = color.startsWith('rgb(') ? color : IGVColor.hexToRgb(color);\n", " }\n", "\n", " const components = src.replace(\")\", \"\").substring(4).split(\",\");\n", " const r = Math.max(0, Math.min(255, Number.parseInt(components[0].trim()) + amt));\n", " const g = Math.max(0, Math.min(255, Number.parseInt(components[1].trim()) + amt));\n", " const b = Math.max(0, Math.min(255, Number.parseInt(components[2].trim()) + amt));\n", " return 'rgb(' + r.toString() + ',' + g.toString() + ',' + b.toString() + ')';\n", " },\n", "\n", " /**\n", " * Convert html/css color name to hex value. Adapted from https://gist.github.com/mxfh/4719348\n", " * @param colorName\n", " * @returns {*}\n", " */\n", " colorNameToHex: function (colorName) {\n", " // color list from http://stackoverflow.com/q/1573053/731179 with added gray/gray\n", " const definedColorNames = {\n", " \"aliceblue\": \"#f0f8ff\",\n", " \"antiquewhite\": \"#faebd7\",\n", " \"aqua\": \"#00ffff\",\n", " \"aquamarine\": \"#7fffd4\",\n", " \"azure\": \"#f0ffff\",\n", " \"beige\": \"#f5f5dc\",\n", " \"bisque\": \"#ffe4c4\",\n", " \"black\": \"#000000\",\n", " \"blanchedalmond\": \"#ffebcd\",\n", " \"blue\": \"#0000ff\",\n", " \"blueviolet\": \"#8a2be2\",\n", " \"brown\": \"#a52a2a\",\n", " \"burlywood\": \"#deb887\",\n", " \"cadetblue\": \"#5f9ea0\",\n", " \"chartreuse\": \"#7fff00\",\n", " \"chocolate\": \"#d2691e\",\n", " \"coral\": \"#ff7f50\",\n", " \"cornflowerblue\": \"#6495ed\",\n", " \"cornsilk\": \"#fff8dc\",\n", " \"crimson\": \"#dc143c\",\n", " \"cyan\": \"#00ffff\",\n", " \"darkblue\": \"#00008b\",\n", " \"darkcyan\": \"#008b8b\",\n", " \"darkgoldenrod\": \"#b8860b\",\n", " \"darkgray\": \"#a9a9a9\",\n", " \"darkgreen\": \"#006400\",\n", " \"darkkhaki\": \"#bdb76b\",\n", " \"darkmagenta\": \"#8b008b\",\n", " \"darkolivegreen\": \"#556b2f\",\n", " \"darkorange\": \"#ff8c00\",\n", " \"darkorchid\": \"#9932cc\",\n", " \"darkred\": \"#8b0000\",\n", " \"darksalmon\": \"#e9967a\",\n", " \"darkseagreen\": \"#8fbc8f\",\n", " \"darkslateblue\": \"#483d8b\",\n", " \"darkslategray\": \"#2f4f4f\",\n", " \"darkturquoise\": \"#00ced1\",\n", " \"darkviolet\": \"#9400d3\",\n", " \"deeppink\": \"#ff1493\",\n", " \"deepskyblue\": \"#00bfff\",\n", " \"dimgray\": \"#696969\",\n", " \"dodgerblue\": \"#1e90ff\",\n", " \"firebrick\": \"#b22222\",\n", " \"floralwhite\": \"#fffaf0\",\n", " \"forestgreen\": \"#228b22\",\n", " \"fuchsia\": \"#ff00ff\",\n", " \"gainsboro\": \"#dcdcdc\",\n", " \"ghostwhite\": \"#f8f8ff\",\n", " \"gold\": \"#ffd700\",\n", " \"goldenrod\": \"#daa520\",\n", " \"gray\": \"#808080\",\n", " \"green\": \"#008000\",\n", " \"greenyellow\": \"#adff2f\",\n", " \"honeydew\": \"#f0fff0\",\n", " \"hotpink\": \"#ff69b4\",\n", " \"indianred \": \"#cd5c5c\",\n", " \"indigo \": \"#4b0082\",\n", " \"ivory\": \"#fffff0\",\n", " \"khaki\": \"#f0e68c\",\n", " \"lavender\": \"#e6e6fa\",\n", " \"lavenderblush\": \"#fff0f5\",\n", " \"lawngreen\": \"#7cfc00\",\n", " \"lemonchiffon\": \"#fffacd\",\n", " \"lightblue\": \"#add8e6\",\n", " \"lightcoral\": \"#f08080\",\n", " \"lightcyan\": \"#e0ffff\",\n", " \"lightgoldenrodyellow\": \"#fafad2\",\n", " \"lightgrey\": \"#d3d3d3\",\n", " \"lightgreen\": \"#90ee90\",\n", " \"lightpink\": \"#ffb6c1\",\n", " \"lightsalmon\": \"#ffa07a\",\n", " \"lightseagreen\": \"#20b2aa\",\n", " \"lightskyblue\": \"#87cefa\",\n", " \"lightslategray\": \"#778899\",\n", " \"lightsteelblue\": \"#b0c4de\",\n", " \"lightyellow\": \"#ffffe0\",\n", " \"lime\": \"#00ff00\",\n", " \"limegreen\": \"#32cd32\",\n", " \"linen\": \"#faf0e6\",\n", " \"magenta\": \"#ff00ff\",\n", " \"maroon\": \"#800000\",\n", " \"mediumaquamarine\": \"#66cdaa\",\n", " \"mediumblue\": \"#0000cd\",\n", " \"mediumorchid\": \"#ba55d3\",\n", " \"mediumpurple\": \"#9370d8\",\n", " \"mediumseagreen\": \"#3cb371\",\n", " \"mediumslateblue\": \"#7b68ee\",\n", " \"mediumspringgreen\": \"#00fa9a\",\n", " \"mediumturquoise\": \"#48d1cc\",\n", " \"mediumvioletred\": \"#c71585\",\n", " \"midnightblue\": \"#191970\",\n", " \"mintcream\": \"#f5fffa\",\n", " \"mistyrose\": \"#ffe4e1\",\n", " \"moccasin\": \"#ffe4b5\",\n", " \"navajowhite\": \"#ffdead\",\n", " \"navy\": \"#000080\",\n", " \"oldlace\": \"#fdf5e6\",\n", " \"olive\": \"#808000\",\n", " \"olivedrab\": \"#6b8e23\",\n", " \"orange\": \"#ffa500\",\n", " \"orangered\": \"#ff4500\",\n", " \"orchid\": \"#da70d6\",\n", " \"palegoldenrod\": \"#eee8aa\",\n", " \"palegreen\": \"#98fb98\",\n", " \"paleturquoise\": \"#afeeee\",\n", " \"palevioletred\": \"#d87093\",\n", " \"papayawhip\": \"#ffefd5\",\n", " \"peachpuff\": \"#ffdab9\",\n", " \"peru\": \"#cd853f\",\n", " \"pink\": \"#ffc0cb\",\n", " \"plum\": \"#dda0dd\",\n", " \"powderblue\": \"#b0e0e6\",\n", " \"purple\": \"#800080\",\n", " \"red\": \"#ff0000\",\n", " \"rosybrown\": \"#bc8f8f\",\n", " \"royalblue\": \"#4169e1\",\n", " \"saddlebrown\": \"#8b4513\",\n", " \"salmon\": \"#fa8072\",\n", " \"sandybrown\": \"#f4a460\",\n", " \"seagreen\": \"#2e8b57\",\n", " \"seashell\": \"#fff5ee\",\n", " \"sienna\": \"#a0522d\",\n", " \"silver\": \"#c0c0c0\",\n", " \"skyblue\": \"#87ceeb\",\n", " \"slateblue\": \"#6a5acd\",\n", " \"slategray\": \"#708090\",\n", " \"snow\": \"#fffafa\",\n", " \"springgreen\": \"#00ff7f\",\n", " \"steelblue\": \"#4682b4\",\n", " \"tan\": \"#d2b48c\",\n", " \"teal\": \"#008080\",\n", " \"thistle\": \"#d8bfd8\",\n", " \"tomato\": \"#ff6347\",\n", " \"turquoise\": \"#40e0d0\",\n", " \"violet\": \"#ee82ee\",\n", " \"wheat\": \"#f5deb3\",\n", " \"white\": \"#ffffff\",\n", " \"whitesmoke\": \"#f5f5f5\",\n", " \"yellow\": \"#ffff00\",\n", " \"yellowgreen\": \"#9acd32\",\n", " \"darkgrey\": \"#a9a9a9\",\n", " \"darkslategrey\": \"#2f4f4f\",\n", " \"dimgrey\": \"#696969\",\n", " \"grey\": \"#808080\",\n", " \"lightgray\": \"#d3d3d3\",\n", " \"lightslategrey\": \"#778899\",\n", " \"slategrey\": \"#708090\"\n", " };\n", " return definedColorNames[colorName];\n", " }\n", " };\n", "\n", " /**\n", " * Make the target element movable by clicking and dragging on the handle. This is not a general purprose function,\n", " * it makes several options specific to igv dialogs, the primary one being that the\n", " * target is absolutely positioned in pixel coordinates\n", "\n", " */\n", " let dragData$1; // Its assumed we are only dragging one element at a time.\n", "\n", " function makeDraggable$1(target, handle) {\n", " handle.addEventListener('mousedown', dragStart$1.bind(target));\n", " }\n", "\n", " function dragStart$1(event) {\n", " event.stopPropagation();\n", " event.preventDefault();\n", " offset$1(this);\n", " const dragFunction = drag$1.bind(this);\n", " const dragEndFunction = dragEnd$1.bind(this);\n", " const computedStyle = getComputedStyle(this);\n", " const top = parseInt(computedStyle.top.replace(\"px\", \"\"));\n", " const left = parseInt(computedStyle.left.replace(\"px\", \"\"));\n", " dragData$1 = {\n", " dragFunction: dragFunction,\n", " dragEndFunction: dragEndFunction,\n", " screenX: event.screenX,\n", " screenY: event.screenY,\n", " top: top,\n", " left: left\n", " };\n", " document.addEventListener('mousemove', dragFunction);\n", " document.addEventListener('mouseup', dragEndFunction);\n", " document.addEventListener('mouseleave', dragEndFunction);\n", " document.addEventListener('mouseexit', dragEndFunction);\n", " }\n", "\n", " function drag$1(event) {\n", " if (!dragData$1) {\n", " console.log(\"No drag data!\");\n", " return;\n", " }\n", "\n", " event.stopPropagation();\n", " event.preventDefault();\n", " const dx = event.screenX - dragData$1.screenX;\n", " const dy = event.screenY - dragData$1.screenY;\n", " this.style.left = `${dragData$1.left + dx}px`;\n", " this.style.top = `${dragData$1.top + dy}px`;\n", " }\n", "\n", " function dragEnd$1(event) {\n", " if (!dragData$1) {\n", " console.log(\"No drag data!\");\n", " return;\n", " }\n", "\n", " event.stopPropagation();\n", " event.preventDefault();\n", " const dragFunction = dragData$1.dragFunction;\n", " const dragEndFunction = dragData$1.dragEndFunction;\n", " document.removeEventListener('mousemove', dragFunction);\n", " document.removeEventListener('mouseup', dragEndFunction);\n", " document.removeEventListener('mouseleave', dragEndFunction);\n", " document.removeEventListener('mouseexit', dragEndFunction);\n", " dragData$1 = undefined;\n", " }\n", "\n", " const colorPalettes = {\n", " 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)\"],\n", " 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)\"],\n", " 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)\"],\n", " 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)\"],\n", " 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)\"],\n", " 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)\"],\n", " 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)\"]\n", " };\n", "\n", " function PaletteColorTable(palette) {\n", " this.colors = colorPalettes[palette];\n", " if (!Array.isArray(this.colors)) this.colors = [];\n", " this.colorTable = {};\n", " this.nextIdx = 0;\n", " this.colorGenerator = new RandomColorGenerator();\n", " }\n", "\n", " PaletteColorTable.prototype.getColor = function (key) {\n", " if (!this.colorTable.hasOwnProperty(key)) {\n", " if (this.nextIdx < this.colors.length) {\n", " this.colorTable[key] = this.colors[this.nextIdx];\n", " } else {\n", " this.colorTable[key] = this.colorGenerator.get();\n", " }\n", "\n", " this.nextIdx++;\n", " }\n", "\n", " return this.colorTable[key];\n", " }; // Random color generator from https://github.com/sterlingwes/RandomColor/blob/master/rcolor.js\n", " // Free to use & distribute under the MIT license\n", " // Wes Johnson (@SterlingWes)\n", " //\n", " // inspired by http://martin.ankerl.com/2009/12/09/how-to-create-random-colors-programmatically/\n", "\n", "\n", " function RandomColorGenerator() {\n", " this.hue = Math.random();\n", " this.goldenRatio = 0.618033988749895;\n", " this.hexwidth = 2;\n", " }\n", "\n", " RandomColorGenerator.prototype.hsvToRgb = function (h, s, v) {\n", " var h_i = Math.floor(h * 6),\n", " f = h * 6 - h_i,\n", " p = v * (1 - s),\n", " q = v * (1 - f * s),\n", " t = v * (1 - (1 - f) * s),\n", " r = 255,\n", " g = 255,\n", " b = 255;\n", "\n", " switch (h_i) {\n", " case 0:\n", " r = v, g = t, b = p;\n", " break;\n", "\n", " case 1:\n", " r = q, g = v, b = p;\n", " break;\n", "\n", " case 2:\n", " r = p, g = v, b = t;\n", " break;\n", "\n", " case 3:\n", " r = p, g = q, b = v;\n", " break;\n", "\n", " case 4:\n", " r = t, g = p, b = v;\n", " break;\n", "\n", " case 5:\n", " r = v, g = p, b = q;\n", " break;\n", " }\n", "\n", " return [Math.floor(r * 256), Math.floor(g * 256), Math.floor(b * 256)];\n", " };\n", "\n", " RandomColorGenerator.prototype.padHex = function (str) {\n", " if (str.length > this.hexwidth) return str;\n", " return new Array(this.hexwidth - str.length + 1).join('0') + str;\n", " };\n", "\n", " RandomColorGenerator.prototype.get = function (saturation, value) {\n", " this.hue += this.goldenRatio;\n", " this.hue %= 1;\n", " if (typeof saturation !== \"number\") saturation = 0.5;\n", " if (typeof value !== \"number\") value = 0.95;\n", " var rgb = this.hsvToRgb(this.hue, saturation, value);\n", " return \"#\" + this.padHex(rgb[0].toString(16)) + this.padHex(rgb[1].toString(16)) + this.padHex(rgb[2].toString(16));\n", " }; // Returns a random number between min (inclusive) and max (exclusive)\n", "\n", " // Support for oauth token based authorization\n", " // This class supports explicit setting of an oauth token either globally or for specific hosts.\n", " //\n", " // The variable oauth.google.access_token, which becomes igv.oauth.google.access_token on ES5 conversion is\n", " // supported for backward compatibility\n", " const DEFAULT_HOST = \"googleapis\";\n", " const oauth = {\n", " oauthTokens: {},\n", " setToken: function (token, host) {\n", " host = host || DEFAULT_HOST;\n", " this.oauthTokens[host] = token;\n", "\n", " if (host === DEFAULT_HOST) {\n", " this.google.access_token = token; // legacy support\n", " }\n", " },\n", " getToken: function (host) {\n", " host = host || DEFAULT_HOST;\n", " let token;\n", "\n", " for (let key of Object.keys(this.oauthTokens)) {\n", " const regex = wildcardToRegExp(key);\n", "\n", " if (regex.test(host)) {\n", " token = this.oauthTokens[key];\n", " break;\n", " }\n", " }\n", "\n", " return token;\n", " },\n", " removeToken: function (host) {\n", " host = host || DEFAULT_HOST;\n", "\n", " for (let key of Object.keys(this.oauthTokens)) {\n", " const regex = wildcardToRegExp(key);\n", "\n", " if (regex.test(host)) {\n", " this.oauthTokens[key] = undefined;\n", " }\n", " }\n", "\n", " if (host === DEFAULT_HOST) {\n", " this.google.access_token = undefined; // legacy support\n", " }\n", " },\n", " // Special object for google -- legacy support\n", " google: {\n", " setToken: function (token) {\n", " oauth.setToken(token);\n", " }\n", " }\n", " };\n", " /**\n", " * Creates a RegExp from the given string, converting asterisks to .* expressions,\n", " * and escaping all other characters.\n", " *\n", " * credit https://gist.github.com/donmccurdy/6d073ce2c6f3951312dfa45da14a420f\n", " */\n", "\n", " function wildcardToRegExp(s) {\n", " return new RegExp('^' + s.split(/\\*+/).map(regExpEscape).join('.*') + '$');\n", " }\n", " /**\n", " * RegExp-escapes all characters in the given string.\n", " *\n", " * credit https://gist.github.com/donmccurdy/6d073ce2c6f3951312dfa45da14a420f\n", " */\n", "\n", "\n", " function regExpEscape(s) {\n", " return s.replace(/[|\\\\{}()[\\]^$+*?.]/g, '\\\\$&');\n", " }\n", "\n", " // The MIT License (MIT)\n", " /**\n", " * @constructor\n", " * @param {Object} options A set op options to pass to the throttle function\n", " * @param {number} requestsPerSecond The amount of requests per second\n", " * the library will limit to\n", " */\n", "\n", " class Throttle$1 {\n", " constructor(options) {\n", " this.requestsPerSecond = options.requestsPerSecond || 10;\n", " this.lastStartTime = 0;\n", " this.queued = [];\n", " }\n", " /**\n", " * Adds a promise\n", " * @param {Function} async function to be executed\n", " * @param {Object} options A set of options.\n", " * @return {Promise} A promise\n", " */\n", "\n", "\n", " add(asyncFunction, options) {\n", " var self = this;\n", " return new Promise(function (resolve, reject) {\n", " self.queued.push({\n", " resolve: resolve,\n", " reject: reject,\n", " asyncFunction: asyncFunction\n", " });\n", " self.dequeue();\n", " });\n", " }\n", " /**\n", " * Adds all the promises passed as parameters\n", " * @param {Function} promises An array of functions that return a promise\n", " * @param {Object} options A set of options.\n", " * @param {number} options.signal An AbortSignal object that can be used to abort the returned promise\n", " * @param {number} options.weight A \"weight\" of each operation resolving by array of promises\n", " * @return {Promise} A promise that succeeds when all the promises passed as options do\n", " */\n", "\n", "\n", " addAll(promises, options) {\n", " var addedPromises = promises.map(function (promise) {\n", " return this.add(promise, options);\n", " }.bind(this));\n", " return Promise.all(addedPromises);\n", " }\n", "\n", " /**\n", " * Dequeues a promise\n", " * @return {void}\n", " */\n", " dequeue() {\n", " if (this.queued.length > 0) {\n", " var now = new Date(),\n", " inc = 1000 / this.requestsPerSecond + 1,\n", " elapsed = now - this.lastStartTime;\n", "\n", " if (elapsed >= inc) {\n", " this._execute();\n", " } else {\n", " // we have reached the limit, schedule a dequeue operation\n", " setTimeout(function () {\n", " this.dequeue();\n", " }.bind(this), inc - elapsed);\n", " }\n", " }\n", " }\n", " /**\n", " * Executes the promise\n", " * @private\n", " * @return {void}\n", " */\n", "\n", "\n", " async _execute() {\n", " this.lastStartTime = new Date();\n", " var candidate = this.queued.shift();\n", " const f = candidate.asyncFunction;\n", "\n", " try {\n", " const r = await f();\n", " candidate.resolve(r);\n", " } catch (e) {\n", " candidate.reject(e);\n", " }\n", " }\n", "\n", " }\n", "\n", " /*\n", " * The MIT License (MIT)\n", " *\n", " * Copyright (c) 2014 Broad Institute\n", " *\n", " * Permission is hereby granted, free of charge, to any person obtaining a copy\n", " * of this software and associated documentation files (the \"Software\"), to deal\n", " * in the Software without restriction, including without limitation the rights\n", " * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n", " * copies of the Software, and to permit persons to whom the Software is\n", " * furnished to do so, subject to the following conditions:\n", " *\n", " * The above copyright notice and this permission notice shall be included in\n", " * all copies or substantial portions of the Software.\n", " *\n", " *\n", " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n", " * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n", " * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n", " * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n", " * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n", " * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n", " * THE SOFTWARE.\n", " */\n", " var NONE = 0;\n", " var GZIP = 1;\n", " var BGZF = 2;\n", " var UNKNOWN = 3;\n", " let RANGE_WARNING_GIVEN = false;\n", " const googleThrottle = new Throttle$1({\n", " requestsPerSecond: 8\n", " });\n", " const igvxhr = {\n", " apiKey: undefined,\n", " setApiKey: function (key) {\n", " this.apiKey = key;\n", " },\n", " load: load,\n", " loadArrayBuffer: async function (url, options) {\n", " options = options || {};\n", "\n", " if (!options.responseType) {\n", " options.responseType = \"arraybuffer\";\n", " }\n", "\n", " if (isFile$1(url)) {\n", " return loadFileSlice(url, options);\n", " } else {\n", " return load(url, options);\n", " }\n", " },\n", " loadJson: async function (url, options) {\n", " options = options || {};\n", " const method = options.method || (options.sendData ? \"POST\" : \"GET\");\n", "\n", " if (method === \"POST\") {\n", " options.contentType = \"application/json\";\n", " }\n", "\n", " const result = await this.loadString(url, options);\n", "\n", " if (result) {\n", " return JSON.parse(result);\n", " } else {\n", " return result;\n", " }\n", " },\n", " loadString: async function (path, options) {\n", " options = options || {};\n", "\n", " if (isFile$1(path)) {\n", " return loadStringFromFile(path, options);\n", " } else {\n", " return loadStringFromUrl(path, options);\n", " }\n", " }\n", " };\n", "\n", " async function load(url, options) {\n", " options = options || {};\n", " const urlType = typeof url; // Resolve functions, promises, and functions that return promises\n", "\n", " url = await (typeof url === 'function' ? url() : url);\n", "\n", " if (isFile$1(url)) {\n", " return loadFileSlice(url, options);\n", " } else if (typeof url.startsWith === 'function') {\n", " // Test for string\n", " if (url.startsWith(\"data:\")) {\n", " return decodeDataURI(url);\n", " } else {\n", " if (url.startsWith(\"https://drive.google.com\")) {\n", " url = driveDownloadURL(url);\n", " }\n", "\n", " if (isGoogleDriveURL(url) || url.startsWith(\"https://www.dropbox.com\")) {\n", " return googleThrottle.add(async function () {\n", " return loadURL(url, options);\n", " });\n", " } else {\n", " return loadURL(url, options);\n", " }\n", " }\n", " } else {\n", " throw Error(`url must be either a 'File', 'string', 'function', or 'Promise'. Actual type: ${urlType}`);\n", " }\n", " }\n", "\n", " async function loadURL(url, options) {\n", " //console.log(`${Date.now()} ${url}`)\n", " url = mapUrl$1(url);\n", " options = options || {};\n", " let oauthToken = options.oauthToken || getOauthToken(url);\n", "\n", " if (oauthToken) {\n", " oauthToken = await (typeof oauthToken === 'function' ? oauthToken() : oauthToken);\n", " }\n", "\n", " return new Promise(function (resolve, reject) {\n", " // Various Google tansformations\n", " if (isGoogleURL(url)) {\n", " if (isGoogleStorageURL(url)) {\n", " url = translateGoogleCloudURL(url);\n", " }\n", "\n", " url = addApiKey(url);\n", "\n", " if (isGoogleDriveURL(url)) {\n", " addTeamDrive(url);\n", " } // If we have an access token try it, but don't force a signIn or request for scopes yet\n", "\n", "\n", " if (!oauthToken) {\n", " oauthToken = getCurrentGoogleAccessToken();\n", " }\n", " }\n", "\n", " const headers = options.headers || {};\n", "\n", " if (oauthToken) {\n", " addOauthHeaders(headers, oauthToken);\n", " }\n", "\n", " const range = options.range;\n", " const isChrome = navigator.userAgent.indexOf('Chrome') > -1;\n", " navigator.vendor.indexOf(\"Apple\") === 0 && /\\sSafari\\//.test(navigator.userAgent);\n", "\n", " if (range && isChrome && !isAmazonV4Signed(url)) {\n", " // Hack to prevent caching for byte-ranges. Attempt to fix net:err-cache errors in Chrome\n", " url += url.includes(\"?\") ? \"&\" : \"?\";\n", " url += \"someRandomSeed=\" + Math.random().toString(36);\n", " }\n", "\n", " const xhr = new XMLHttpRequest();\n", " const sendData = options.sendData || options.body;\n", " const method = options.method || (sendData ? \"POST\" : \"GET\");\n", " const responseType = options.responseType;\n", " const contentType = options.contentType;\n", " const mimeType = options.mimeType;\n", " xhr.open(method, url);\n", "\n", " if (options.timeout) {\n", " xhr.timeout = options.timeout;\n", " }\n", "\n", " if (range) {\n", " var rangeEnd = range.size ? range.start + range.size - 1 : \"\";\n", " xhr.setRequestHeader(\"Range\", \"bytes=\" + range.start + \"-\" + rangeEnd); // xhr.setRequestHeader(\"Cache-Control\", \"no-cache\"); <= This can cause CORS issues, disabled for now\n", " }\n", "\n", " if (contentType) {\n", " xhr.setRequestHeader(\"Content-Type\", contentType);\n", " }\n", "\n", " if (mimeType) {\n", " xhr.overrideMimeType(mimeType);\n", " }\n", "\n", " if (responseType) {\n", " xhr.responseType = responseType;\n", " }\n", "\n", " if (headers) {\n", " for (let key of Object.keys(headers)) {\n", " const value = headers[key];\n", " xhr.setRequestHeader(key, value);\n", " }\n", " } // NOTE: using withCredentials with servers that return \"*\" for access-allowed-origin will fail\n", "\n", "\n", " if (options.withCredentials === true) {\n", " xhr.withCredentials = true;\n", " }\n", "\n", " xhr.onload = async function (event) {\n", " // when the url points to a local file, the status is 0 but that is not an error\n", " if (xhr.status === 0 || xhr.status >= 200 && xhr.status <= 300) {\n", " if (range && xhr.status !== 206 && range.start !== 0) {\n", " // For small files a range starting at 0 can return the whole file => 200\n", " // Provide just the slice we asked for, throw out the rest quietly\n", " // If file is large warn user\n", " if (xhr.response.length > 100000 && !RANGE_WARNING_GIVEN) {\n", " alert(`Warning: Range header ignored for URL: ${url}. This can have performance impacts.`);\n", " }\n", "\n", " resolve(xhr.response.slice(range.start, range.start + range.size));\n", " } else {\n", " resolve(xhr.response);\n", " }\n", " } else if (typeof gapi !== \"undefined\" && (xhr.status === 404 || xhr.status === 401 || xhr.status === 403) && isGoogleURL(url) && !options.retries) {\n", " tryGoogleAuth();\n", " } else {\n", " if (xhr.status === 403) {\n", " handleError(\"Access forbidden: \" + url);\n", " } else if (xhr.status === 416) {\n", " // Tried to read off the end of the file. This shouldn't happen, but if it does return an\n", " handleError(\"Unsatisfiable range\");\n", " } else {\n", " handleError(xhr.status);\n", " }\n", " }\n", " };\n", "\n", " xhr.onerror = function (event) {\n", " if (isGoogleURL(url) && !options.retries) {\n", " tryGoogleAuth();\n", " }\n", "\n", " handleError(\"Error accessing resource: \" + url + \" Status: \" + xhr.status);\n", " };\n", "\n", " xhr.ontimeout = function (event) {\n", " handleError(\"Timed out\");\n", " };\n", "\n", " xhr.onabort = function (event) {\n", " console.log(\"Aborted\");\n", " reject(event);\n", " };\n", "\n", " try {\n", " xhr.send(sendData);\n", " } catch (e) {\n", " reject(e);\n", " }\n", "\n", " function handleError(error) {\n", " if (reject) {\n", " reject(error);\n", " } else {\n", " throw error;\n", " }\n", " }\n", "\n", " async function tryGoogleAuth() {\n", " try {\n", " const accessToken = await fetchGoogleAccessToken(url);\n", " options.retries = 1;\n", " options.oauthToken = accessToken;\n", " const response = await load(url, options);\n", " resolve(response);\n", " } catch (e) {\n", " if (e.error) {\n", " const msg = e.error.startsWith(\"popup_blocked\") ? \"Google login popup blocked by browser.\" : e.error;\n", " alert(msg);\n", " } else {\n", " handleError(e);\n", " }\n", " }\n", " }\n", " });\n", " }\n", "\n", " async function loadFileSlice(localfile, options) {\n", " let blob = options && options.range ? localfile.slice(options.range.start, options.range.start + options.range.size) : localfile;\n", "\n", " if (\"arraybuffer\" === options.responseType) {\n", " return blobToArrayBuffer(blob);\n", " } else {\n", " // binary string format, shouldn't be used anymore\n", " return new Promise(function (resolve, reject) {\n", " const fileReader = new FileReader();\n", "\n", " fileReader.onload = function (e) {\n", " resolve(fileReader.result);\n", " };\n", "\n", " fileReader.onerror = function (e) {\n", " console.error(\"reject uploading local file \" + localfile.name);\n", " reject(null, fileReader);\n", " };\n", "\n", " fileReader.readAsBinaryString(blob);\n", " console.warn(\"Deprecated method used: readAsBinaryString\");\n", " });\n", " }\n", " }\n", "\n", " async function loadStringFromFile(localfile, options) {\n", " const blob = options.range ? localfile.slice(options.range.start, options.range.start + options.range.size) : localfile;\n", " let compression = NONE;\n", "\n", " if (options && options.bgz || localfile.name.endsWith(\".bgz\")) {\n", " compression = BGZF;\n", " } else if (localfile.name.endsWith(\".gz\")) {\n", " compression = GZIP;\n", " }\n", "\n", " if (compression === NONE) {\n", " return blobToText(blob);\n", " } else {\n", " const arrayBuffer = await blobToArrayBuffer(blob);\n", " return arrayBufferToString(arrayBuffer, compression);\n", " }\n", " }\n", "\n", " async function blobToArrayBuffer(blob) {\n", " if (typeof blob.arrayBuffer === 'function') {\n", " return blob.arrayBuffer();\n", " }\n", "\n", " return new Promise(function (resolve, reject) {\n", " const fileReader = new FileReader();\n", "\n", " fileReader.onload = function (e) {\n", " resolve(fileReader.result);\n", " };\n", "\n", " fileReader.onerror = function (e) {\n", " console.error(\"reject uploading local file \" + localfile.name);\n", " reject(null, fileReader);\n", " };\n", "\n", " fileReader.readAsArrayBuffer(blob);\n", " });\n", " }\n", "\n", " async function blobToText(blob) {\n", " if (typeof blob.text === 'function') {\n", " return blob.text();\n", " }\n", "\n", " return new Promise(function (resolve, reject) {\n", " const fileReader = new FileReader();\n", "\n", " fileReader.onload = function (e) {\n", " resolve(fileReader.result);\n", " };\n", "\n", " fileReader.onerror = function (e) {\n", " console.error(\"reject uploading local file \" + localfile.name);\n", " reject(null, fileReader);\n", " };\n", "\n", " fileReader.readAsText(blob);\n", " });\n", " }\n", "\n", " async function loadStringFromUrl(url, options) {\n", " options = options || {};\n", " const fn = options.filename || (await getFilename$1(url));\n", " let compression = UNKNOWN;\n", "\n", " if (options.bgz) {\n", " compression = BGZF;\n", " } else if (fn.endsWith(\".gz\")) {\n", " compression = GZIP;\n", " }\n", "\n", " options.responseType = \"arraybuffer\";\n", " const data = await igvxhr.load(url, options);\n", " return arrayBufferToString(data, compression);\n", " }\n", "\n", " function isAmazonV4Signed(url) {\n", " return url.indexOf(\"X-Amz-Signature\") > -1;\n", " }\n", "\n", " function getOauthToken(url) {\n", " // Google is the default provider, don't try to parse host for google URLs\n", " const host = isGoogleURL(url) ? undefined : parseUri(url).host;\n", " let token = oauth.getToken(host);\n", "\n", " if (token) {\n", " return token;\n", " } else if (host === undefined) {\n", " const googleToken = getCurrentGoogleAccessToken();\n", "\n", " if (googleToken && googleToken.expires_at > Date.now()) {\n", " return googleToken.access_token;\n", " }\n", " }\n", " }\n", " /**\n", " * Return a Google oAuth token, triggering a sign in if required. This method should not be called until we know\n", " * a token is required, that is until we've tried the url and received a 401, 403, or 404.\n", " *\n", " * @param url\n", " * @returns the oauth token\n", " */\n", "\n", "\n", " async function fetchGoogleAccessToken(url) {\n", " console.log(\"Fetch token for \" + url);\n", "\n", " if (isInitialized()) {\n", " const scope = getScopeForURL(url);\n", " const googleToken = await getAccessToken(scope);\n", " return googleToken ? googleToken.access_token : undefined;\n", " } else {\n", " throw Error(`Authorization is required, but Google oAuth has not been initalized. Contact your site administrator for assistance.`);\n", " }\n", " }\n", " /**\n", " * Return the current google access token, if one exists. Do not triger signOn or request additional scopes.\n", " * @returns {undefined|access_token}\n", " */\n", "\n", "\n", " function getCurrentGoogleAccessToken() {\n", " if (isInitialized()) {\n", " const googleToken = getCurrentAccessToken();\n", " return googleToken ? googleToken.access_token : undefined;\n", " } else {\n", " return undefined;\n", " }\n", " }\n", "\n", " function addOauthHeaders(headers, acToken) {\n", " if (acToken) {\n", " headers[\"Cache-Control\"] = \"no-cache\";\n", " headers[\"Authorization\"] = \"Bearer \" + acToken;\n", " }\n", "\n", " return headers;\n", " }\n", "\n", " function addApiKey(url) {\n", " let apiKey = igvxhr.apiKey;\n", "\n", " if (!apiKey && typeof gapi !== \"undefined\") {\n", " apiKey = gapi.apiKey;\n", " }\n", "\n", " if (apiKey !== undefined && !url.includes(\"key=\")) {\n", " const paramSeparator = url.includes(\"?\") ? \"&\" : \"?\";\n", " url = url + paramSeparator + \"key=\" + apiKey;\n", " }\n", "\n", " return url;\n", " }\n", "\n", " function addTeamDrive(url) {\n", " if (url.includes(\"supportsTeamDrive\")) {\n", " return url;\n", " } else {\n", " const paramSeparator = url.includes(\"?\") ? \"&\" : \"?\";\n", " url = url + paramSeparator + \"supportsTeamDrive=true\";\n", " }\n", " }\n", " /**\n", " * Perform some well-known url mappings.\n", " * @param url\n", " */\n", "\n", "\n", " function mapUrl$1(url) {\n", " if (url.includes(\"//www.dropbox.com\")) {\n", " return url.replace(\"//www.dropbox.com\", \"//dl.dropboxusercontent.com\");\n", " } else if (url.includes(\"//drive.google.com\")) {\n", " return driveDownloadURL(url);\n", " } else if (url.includes(\"//www.broadinstitute.org/igvdata\")) {\n", " return url.replace(\"//www.broadinstitute.org/igvdata\", \"//data.broadinstitute.org/igvdata\");\n", " } else if (url.includes(\"//igvdata.broadinstitute.org\")) {\n", " return url.replace(\"//igvdata.broadinstitute.org\", \"https://dn7ywbm9isq8j.cloudfront.net\");\n", " } else if (url.startsWith(\"ftp://ftp.ncbi.nlm.nih.gov/geo\")) {\n", " return url.replace(\"ftp://\", \"https://\");\n", " } else {\n", " return url;\n", " }\n", " }\n", "\n", " function arrayBufferToString(arraybuffer, compression) {\n", " if (compression === UNKNOWN && arraybuffer.byteLength > 2) {\n", " const m = new Uint8Array(arraybuffer, 0, 2);\n", "\n", " if (m[0] === 31 && m[1] === 139) {\n", " compression = GZIP;\n", " }\n", " }\n", "\n", " let plain;\n", "\n", " if (compression === GZIP) {\n", " const inflate = new Zlib$2.Gunzip(new Uint8Array(arraybuffer));\n", " plain = inflate.decompress();\n", " } else if (compression === BGZF) {\n", " plain = unbgzf(arraybuffer);\n", " } else {\n", " plain = new Uint8Array(arraybuffer);\n", " }\n", "\n", " if ('TextDecoder' in getGlobalObject()) {\n", " return new TextDecoder().decode(plain);\n", " } else {\n", " return decodeUTF8(plain);\n", " }\n", " }\n", " /**\n", " * Use when TextDecoder is not available (primarily IE).\n", " *\n", " * From: https://gist.github.com/Yaffle/5458286\n", " *\n", " * @param octets\n", " * @returns {string}\n", " */\n", "\n", "\n", " function decodeUTF8(octets) {\n", " var string = \"\";\n", " var i = 0;\n", "\n", " while (i < octets.length) {\n", " var octet = octets[i];\n", " var bytesNeeded = 0;\n", " var codePoint = 0;\n", "\n", " if (octet <= 0x7F) {\n", " bytesNeeded = 0;\n", " codePoint = octet & 0xFF;\n", " } else if (octet <= 0xDF) {\n", " bytesNeeded = 1;\n", " codePoint = octet & 0x1F;\n", " } else if (octet <= 0xEF) {\n", " bytesNeeded = 2;\n", " codePoint = octet & 0x0F;\n", " } else if (octet <= 0xF4) {\n", " bytesNeeded = 3;\n", " codePoint = octet & 0x07;\n", " }\n", "\n", " if (octets.length - i - bytesNeeded > 0) {\n", " var k = 0;\n", "\n", " while (k < bytesNeeded) {\n", " octet = octets[i + k + 1];\n", " codePoint = codePoint << 6 | octet & 0x3F;\n", " k += 1;\n", " }\n", " } else {\n", " codePoint = 0xFFFD;\n", " bytesNeeded = octets.length - i;\n", " }\n", "\n", " string += String.fromCodePoint(codePoint);\n", " i += bytesNeeded + 1;\n", " }\n", "\n", " return string;\n", " }\n", "\n", " function getGlobalObject() {\n", " if (typeof self !== 'undefined') {\n", " return self;\n", " }\n", "\n", " if (typeof global !== 'undefined') {\n", " return global;\n", " } else {\n", " return window;\n", " }\n", " }\n", "\n", " async function getFilename$1(url) {\n", " if (isString$2(url) && url.startsWith(\"https://drive.google.com\")) {\n", " // This will fail if Google API key is not defined\n", " if (getApiKey() === undefined) {\n", " throw Error(\"Google drive is referenced, but API key is not defined. An API key is required for Google Drive access\");\n", " }\n", "\n", " const json = await getDriveFileInfo(url);\n", " return json.originalFileName || json.name;\n", " } else {\n", " return getFilename$2(url);\n", " }\n", " }\n", "\n", " /*\n", " * The MIT License (MIT)\n", " *\n", " * Copyright (c) 2014 Broad Institute\n", " *\n", " * Permission is hereby granted, free of charge, to any person obtaining a copy\n", " * of this software and associated documentation files (the \"Software\"), to deal\n", " * in the Software without restriction, including without limitation the rights\n", " * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n", " * copies of the Software, and to permit persons to whom the Software is\n", " * furnished to do so, subject to the following conditions:\n", " *\n", " * The above copyright notice and this permission notice shall be included in\n", " * all copies or substantial portions of the Software.\n", " *\n", " *\n", " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n", " * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n", " * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n", " * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n", " * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n", " * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n", " * THE SOFTWARE.\n", " */\n", "\n", " /** An implementation of an interval tree, following the explanation.\n", " * from CLR.\n", " *\n", " * Public interface:\n", " * Constructor IntervalTree\n", " * Insertion insert\n", " * Search findOverlapping\n", " */\n", " var BLACK = 1;\n", " var RED = 2;\n", " var NIL = {};\n", " NIL.color = BLACK;\n", " NIL.parent = NIL;\n", " NIL.left = NIL;\n", " NIL.right = NIL;\n", "\n", " class IntervalTree {\n", " constructor() {\n", " this.root = NIL;\n", " }\n", "\n", " insert(start, end, value) {\n", " var interval = new Interval(start, end, value);\n", " var x = new Node$1(interval);\n", " this.treeInsert(x);\n", " x.color = RED;\n", "\n", " while (x !== this.root && x.parent.color === RED) {\n", " if (x.parent === x.parent.parent.left) {\n", " let y = x.parent.parent.right;\n", "\n", " if (y.color === RED) {\n", " x.parent.color = BLACK;\n", " y.color = BLACK;\n", " x.parent.parent.color = RED;\n", " x = x.parent.parent;\n", " } else {\n", " if (x === x.parent.right) {\n", " x = x.parent;\n", " leftRotate.call(this, x);\n", " }\n", "\n", " x.parent.color = BLACK;\n", " x.parent.parent.color = RED;\n", " rightRotate.call(this, x.parent.parent);\n", " }\n", " } else {\n", " let y = x.parent.parent.left;\n", "\n", " if (y.color === RED) {\n", " x.parent.color = BLACK;\n", " y.color = BLACK;\n", " x.parent.parent.color = RED;\n", " x = x.parent.parent;\n", " } else {\n", " if (x === x.parent.left) {\n", " x = x.parent;\n", " rightRotate.call(this, x);\n", " }\n", "\n", " x.parent.color = BLACK;\n", " x.parent.parent.color = RED;\n", " leftRotate.call(this, x.parent.parent);\n", " }\n", " }\n", " }\n", "\n", " this.root.color = BLACK;\n", " }\n", " /**\n", " *\n", " * @param start - query interval\n", " * @param end - query interval\n", " * @returns Array of all intervals overlapping the query region\n", " */\n", "\n", "\n", " findOverlapping(start, end) {\n", " var searchInterval = new Interval(start, end, 0);\n", " if (this.root === NIL) return [];\n", " var intervals = searchAll.call(this, searchInterval, this.root, []);\n", "\n", " if (intervals.length > 1) {\n", " intervals.sort(function (i1, i2) {\n", " return i1.low - i2.low;\n", " });\n", " }\n", "\n", " return intervals;\n", " }\n", " /**\n", " * Dump info on intervals to console. For debugging.\n", " */\n", "\n", "\n", " logIntervals() {\n", " logNode(this.root, 0);\n", "\n", " function logNode(node, indent) {\n", " var space = \"\";\n", "\n", " for (var i = 0; i < indent; i++) space += \" \";\n", "\n", " console.log(space + node.interval.low + \" \" + node.interval.high); // + \" \" + (node.interval.value ? node.interval.value : \" null\"));\n", "\n", " indent += 5;\n", " if (node.left !== NIL) logNode(node.left, indent);\n", " if (node.right !== NIL) logNode(node.right, indent);\n", " }\n", " }\n", "\n", " mapIntervals(func) {\n", " applyInterval(this.root);\n", "\n", " function applyInterval(node) {\n", " func(node.interval);\n", " if (node.left !== NIL) applyInterval(node.left);\n", " if (node.right !== NIL) applyInterval(node.right);\n", " }\n", " }\n", " /**\n", " * Note: Does not maintain RB constraints, this is done post insert\n", " *\n", " * @param x a Node\n", " */\n", "\n", "\n", " treeInsert(x) {\n", " var node = this.root;\n", " var y = NIL;\n", "\n", " while (node !== NIL) {\n", " y = node;\n", "\n", " if (x.interval.low <= node.interval.low) {\n", " node = node.left;\n", " } else {\n", " node = node.right;\n", " }\n", " }\n", "\n", " x.parent = y;\n", "\n", " if (y === NIL) {\n", " this.root = x;\n", " x.left = x.right = NIL;\n", " } else {\n", " if (x.interval.low <= y.interval.low) {\n", " y.left = x;\n", " } else {\n", " y.right = x;\n", " }\n", " }\n", "\n", " applyUpdate.call(this, x);\n", " }\n", "\n", " }\n", "\n", " function searchAll(interval, node, results) {\n", " if (node.interval.overlaps(interval)) {\n", " results.push(node.interval);\n", " }\n", "\n", " if (node.left !== NIL && node.left.max >= interval.low) {\n", " searchAll.call(this, interval, node.left, results);\n", " }\n", "\n", " if (node.right !== NIL && node.right.min <= interval.high) {\n", " searchAll.call(this, interval, node.right, results);\n", " }\n", "\n", " return results;\n", " }\n", "\n", " function leftRotate(x) {\n", " var y = x.right;\n", " x.right = y.left;\n", "\n", " if (y.left !== NIL) {\n", " y.left.parent = x;\n", " }\n", "\n", " y.parent = x.parent;\n", "\n", " if (x.parent === NIL) {\n", " this.root = y;\n", " } else {\n", " if (x.parent.left === x) {\n", " x.parent.left = y;\n", " } else {\n", " x.parent.right = y;\n", " }\n", " }\n", "\n", " y.left = x;\n", " x.parent = y;\n", " applyUpdate.call(this, x); // no need to apply update on y, since it'll y is an ancestor\n", " // of x, and will be touched by applyUpdate().\n", " }\n", "\n", " function rightRotate(x) {\n", " var y = x.left;\n", " x.left = y.right;\n", "\n", " if (y.right !== NIL) {\n", " y.right.parent = x;\n", " }\n", "\n", " y.parent = x.parent;\n", "\n", " if (x.parent === NIL) {\n", " this.root = y;\n", " } else {\n", " if (x.parent.right === x) {\n", " x.parent.right = y;\n", " } else {\n", " x.parent.left = y;\n", " }\n", " }\n", "\n", " y.right = x;\n", " x.parent = y;\n", " applyUpdate.call(this, x); // no need to apply update on y, since it'll y is an ancestor\n", " // of x, and will be touched by applyUpdate().\n", " } // Applies the statistic update on the node and its ancestors.\n", "\n", "\n", " function applyUpdate(node) {\n", " while (node !== NIL) {\n", " var nodeMax = node.left.max > node.right.max ? node.left.max : node.right.max;\n", " var intervalHigh = node.interval.high;\n", " node.max = nodeMax > intervalHigh ? nodeMax : intervalHigh;\n", " var nodeMin = node.left.min < node.right.min ? node.left.min : node.right.min;\n", " var intervalLow = node.interval.low;\n", " node.min = nodeMin < intervalLow ? nodeMin : intervalLow;\n", " node = node.parent;\n", " }\n", " }\n", "\n", " class Interval {\n", " constructor(low, high, value) {\n", " this.low = low;\n", " this.high = high;\n", " this.value = value;\n", " }\n", "\n", " equals(other) {\n", " if (!other) {\n", " return false;\n", " }\n", "\n", " if (this === other) {\n", " return true;\n", " }\n", "\n", " return this.low === other.low && this.high === other.high;\n", " }\n", "\n", " compareTo(other) {\n", " if (this.low < other.low) return -1;\n", " if (this.low > other.low) return 1;\n", " if (this.high < other.high) return -1;\n", " if (this.high > other.high) return 1;\n", " return 0;\n", " }\n", " /**\n", " * Returns true if this interval overlaps the other.\n", " */\n", "\n", "\n", " overlaps(other) {\n", " return this.low <= other.high && other.low <= this.high;\n", " }\n", "\n", " }\n", "\n", " function Node$1(interval) {\n", " this.parent = NIL;\n", " this.left = NIL;\n", " this.right = NIL;\n", " this.interval = interval;\n", " this.color = RED;\n", " } //\n", "\n", " /*\n", " * The MIT License (MIT)\n", " *\n", " * Copyright (c) 2014 Broad Institute\n", " *\n", " * Permission is hereby granted, free of charge, to any person obtaining a copy\n", " * of this software and associated documentation files (the \"Software\"), to deal\n", " * in the Software without restriction, including without limitation the rights\n", " * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n", " * copies of the Software, and to permit persons to whom the Software is\n", " * furnished to do so, subject to the following conditions:\n", " *\n", " * The above copyright notice and this permission notice shall be included in\n", " * all copies or substantial portions of the Software.\n", " *\n", " *\n", " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n", " * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n", " * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n", " * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n", " * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n", " * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n", " * THE SOFTWARE.\n", " */\n", " /**\n", " * Object for caching lists of features. Supports effecient queries for sub-range (chr, start, end)\n", " *\n", " * @param featureList\n", " * @param The genomic range spanned by featureList (optional)\n", " * @constructor\n", " */\n", "\n", " class FeatureCache {\n", " constructor(featureList, genome, range) {\n", " featureList = featureList || [];\n", " this.treeMap = this.buildTreeMap(featureList, genome);\n", " this.range = range;\n", " this.count = featureList.length;\n", " }\n", "\n", " containsRange(genomicRange) {\n", " // No range means cache contains all features\n", " return this.range === undefined || this.range.contains(genomicRange.chr, genomicRange.start, genomicRange.end);\n", " }\n", "\n", " queryFeatures(chr, start, end) {\n", " const tree = this.treeMap[chr];\n", " if (!tree) return [];\n", " const intervals = tree.findOverlapping(start, end);\n", "\n", " if (intervals.length === 0) {\n", " return [];\n", " } else {\n", " // Trim the list of features in the intervals to those\n", " // overlapping the requested range.\n", " // Assumption: features are sorted by start position\n", " const featureList = [];\n", " const all = this.allFeatures[chr];\n", "\n", " if (all) {\n", " for (let interval of intervals) {\n", " const indexRange = interval.value;\n", "\n", " for (let i = indexRange.start; i < indexRange.end; i++) {\n", " let feature = all[i];\n", " if (feature.start > end) break;else if (feature.end >= start) {\n", " featureList.push(feature);\n", " }\n", " }\n", " }\n", "\n", " featureList.sort(function (a, b) {\n", " return a.start - b.start;\n", " });\n", " }\n", "\n", " return featureList;\n", " }\n", " }\n", "\n", " /**\n", " * Returns all features, unsorted.\n", " *\n", " * @returns {Array}\n", " */\n", " getAllFeatures() {\n", " return this.allFeatures;\n", " }\n", "\n", " buildTreeMap(featureList, genome) {\n", " const treeMap = {};\n", " const chromosomes = [];\n", " this.allFeatures = {};\n", "\n", " if (featureList) {\n", " for (let feature of featureList) {\n", " let chr = feature.chr; // Translate to \"official\" name\n", "\n", " if (genome) {\n", " chr = genome.getChromosomeName(chr);\n", " }\n", "\n", " let geneList = this.allFeatures[chr];\n", "\n", " if (!geneList) {\n", " chromosomes.push(chr);\n", " geneList = [];\n", " this.allFeatures[chr] = geneList;\n", " }\n", "\n", " geneList.push(feature);\n", " } // Now build interval tree for each chromosome\n", "\n", "\n", " for (let chr of chromosomes) {\n", " const chrFeatures = this.allFeatures[chr];\n", " chrFeatures.sort(function (f1, f2) {\n", " return f1.start === f2.start ? 0 : f1.start > f2.start ? 1 : -1;\n", " });\n", " treeMap[chr] = buildIntervalTree$1(chrFeatures);\n", " }\n", " }\n", "\n", " return treeMap;\n", " }\n", "\n", " }\n", " /**\n", " * Build an interval tree from the feature list for fast interval based queries. We lump features in groups\n", " * of 10, or total size / 100, to reduce size of the tree.\n", " *\n", " * @param featureList\n", " */\n", "\n", "\n", " function buildIntervalTree$1(featureList) {\n", " const tree = new IntervalTree();\n", " const len = featureList.length;\n", " const chunkSize = Math.max(10, Math.round(len / 10));\n", "\n", " for (let i = 0; i < len; i += chunkSize) {\n", " const e = Math.min(len, i + chunkSize);\n", " const subArray = new IndexRange(i, e); //featureList.slice(i, e);\n", "\n", " const iStart = featureList[i].start; //\n", "\n", " let iEnd = iStart;\n", "\n", " for (let j = i; j < e; j++) {\n", " iEnd = Math.max(iEnd, featureList[j].end);\n", " }\n", "\n", " tree.insert(iStart, iEnd, subArray);\n", " }\n", "\n", " return tree;\n", " }\n", "\n", " class IndexRange {\n", " constructor(start, end) {\n", " this.start = start;\n", " this.end = end;\n", " }\n", "\n", " }\n", "\n", " /*\n", " * The MIT License (MIT)\n", " *\n", " * Copyright (c) 2016-2017 The Regents of the University of California\n", " * Author: Jim Robinson\n", " *\n", " * Permission is hereby granted, free of charge, to any person obtaining a copy\n", " * of this software and associated documentation files (the \"Software\"), to deal\n", " * in the Software without restriction, including without limitation the rights\n", " * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n", " * copies of the Software, and to permit persons to whom the Software is\n", " * furnished to do so, subject to the following conditions:\n", " *\n", " * The above copyright notice and this permission notice shall be included in\n", " * all copies or substantial portions of the Software.\n", " *\n", " *\n", " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n", " * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n", " * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n", " * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n", " * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n", " * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n", " * THE SOFTWARE.\n", " */\n", " const FeatureUtils = {\n", " packFeatures: function (features, maxRows, sorted) {\n", " var start;\n", " var end;\n", " if (!features) return;\n", " maxRows = maxRows || 10000;\n", "\n", " if (!sorted) {\n", " features.sort(function (a, b) {\n", " return a.start - b.start;\n", " });\n", " }\n", "\n", " if (features.length === 0) {\n", " return [];\n", " } else {\n", " var bucketList = [],\n", " allocatedCount = 0,\n", " lastAllocatedCount = 0,\n", " nextStart,\n", " row,\n", " index,\n", " bucket,\n", " feature,\n", " gap = 2,\n", " bucketStart;\n", " start = features[0].start;\n", " end = features[features.length - 1].start;\n", " bucketStart = Math.max(start, features[0].start);\n", " nextStart = bucketStart;\n", " features.forEach(function (alignment) {\n", " var buckListIndex = Math.max(0, alignment.start - bucketStart);\n", "\n", " if (bucketList[buckListIndex] === undefined) {\n", " bucketList[buckListIndex] = [];\n", " }\n", "\n", " bucketList[buckListIndex].push(alignment);\n", " });\n", " row = 0;\n", "\n", " while (allocatedCount < features.length && row <= maxRows) {\n", " while (nextStart <= end) {\n", " bucket = undefined;\n", "\n", " while (!bucket && nextStart <= end) {\n", " index = nextStart - bucketStart;\n", "\n", " if (bucketList[index] === undefined) {\n", " ++nextStart; // No buckets at this index\n", " } else {\n", " bucket = bucketList[index];\n", " }\n", " } // while (bucket)\n", "\n", "\n", " if (!bucket) {\n", " break;\n", " }\n", "\n", " feature = bucket.pop();\n", "\n", " if (0 === bucket.length) {\n", " bucketList[index] = undefined;\n", " }\n", "\n", " feature.row = row;\n", " nextStart = feature.end + gap;\n", " ++allocatedCount;\n", " } // while (nextStart)\n", "\n", "\n", " row++;\n", " nextStart = bucketStart;\n", " if (allocatedCount === lastAllocatedCount) break; // Protect from infinite loops\n", "\n", " lastAllocatedCount = allocatedCount;\n", " } // while (allocatedCount)\n", "\n", " }\n", " },\n", "\n", " /**\n", " * Find features overlapping the given interval. It is assumed that all features share the same chromosome.\n", " *\n", " * TODO -- significant overlap with FeatureCache, refactor to combine\n", " *\n", " * @param featureList\n", " * @param start\n", " * @param end\n", " */\n", " findOverlapping: function (featureList, start, end) {\n", " if (!featureList || featureList.length === 0) {\n", " return [];\n", " } else {\n", " const tree = buildIntervalTree(featureList);\n", " const intervals = tree.findOverlapping(start, end);\n", "\n", " if (intervals.length === 0) {\n", " return [];\n", " } else {\n", " // Trim the list of features in the intervals to those\n", " // overlapping the requested range.\n", " // Assumption: features are sorted by start position\n", " featureList = [];\n", " intervals.forEach(function (interval) {\n", " const intervalFeatures = interval.value;\n", " const len = intervalFeatures.length;\n", "\n", " for (let i = 0; i < len; i++) {\n", " const feature = intervalFeatures[i];\n", " if (feature.start > end) break;else if (feature.end > start) {\n", " featureList.push(feature);\n", " }\n", " }\n", " });\n", " featureList.sort(function (a, b) {\n", " return a.start - b.start;\n", " });\n", " return featureList;\n", " }\n", " }\n", " }\n", " };\n", " /**\n", " * Build an interval tree from the feature list for fast interval based queries. We lump features in groups\n", " * of 10, or total size / 100, to reduce size of the tree.\n", " *\n", " * @param featureList\n", " */\n", "\n", " function buildIntervalTree(featureList) {\n", " const tree = new IntervalTree();\n", " const len = featureList.length;\n", " const chunkSize = Math.max(10, Math.round(len / 100));\n", " featureList.sort(function (f1, f2) {\n", " return f1.start === f2.start ? 0 : f1.start > f2.start ? 1 : -1;\n", " });\n", "\n", " for (let i = 0; i < len; i += chunkSize) {\n", " const e = Math.min(len, i + chunkSize);\n", " const subArray = featureList.slice(i, e);\n", " const iStart = subArray[0].start;\n", " let iEnd = iStart;\n", " subArray.forEach(function (feature) {\n", " iEnd = Math.max(iEnd, feature.end);\n", " });\n", " tree.insert(iStart, iEnd, subArray);\n", " }\n", "\n", " return tree;\n", " }\n", "\n", " /*!\n", " * 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\n", " * https://jquery.com/\n", " *\n", " * Includes Sizzle.js\n", " * https://sizzlejs.com/\n", " *\n", " * Copyright JS Foundation and other contributors\n", " * Released under the MIT license\n", " * https://jquery.org/license\n", " *\n", " * Date: 2018-01-20T17:24Z\n", " */\n", "\n", " var arr = [];\n", " var document$2 = window.document;\n", " var getProto = Object.getPrototypeOf;\n", " var slice = arr.slice;\n", " var concat = arr.concat;\n", " var push = arr.push;\n", " var indexOf = arr.indexOf;\n", " var class2type = {};\n", " var toString$2 = class2type.toString;\n", " var hasOwn$6 = class2type.hasOwnProperty;\n", " var fnToString = hasOwn$6.toString;\n", " var ObjectFunctionString = fnToString.call(Object);\n", " var support = {};\n", "\n", " var isFunction = function isFunction(obj) {\n", " // Support: Chrome <=57, Firefox <=52\n", " // In some browsers, typeof returns \"function\" for HTML elements\n", " // (i.e., `typeof document.createElement( \"object\" ) === \"function\"`).\n", " // We don't want to classify *any* DOM node as a function.\n", " return typeof obj === \"function\" && typeof obj.nodeType !== \"number\";\n", " };\n", "\n", " var isWindow = function isWindow(obj) {\n", " return obj != null && obj === obj.window;\n", " };\n", "\n", " var preservedScriptAttributes = {\n", " type: true,\n", " src: true,\n", " noModule: true\n", " };\n", "\n", " function DOMEval(code, doc, node) {\n", " doc = doc || document$2;\n", " var i,\n", " script = doc.createElement(\"script\");\n", " script.text = code;\n", "\n", " if (node) {\n", " for (i in preservedScriptAttributes) {\n", " if (node[i]) {\n", " script[i] = node[i];\n", " }\n", " }\n", " }\n", "\n", " doc.head.appendChild(script).parentNode.removeChild(script);\n", " }\n", "\n", " function toType(obj) {\n", " if (obj == null) {\n", " return obj + \"\";\n", " } // Support: Android <=2.3 only (functionish RegExp)\n", "\n", "\n", " return typeof obj === \"object\" || typeof obj === \"function\" ? class2type[toString$2.call(obj)] || \"object\" : typeof obj;\n", " } // global Symbol\n", " // Defining this global in .eslintrc.json would create a danger of using the global\n", " // unguarded in another place, it seems safer to define global only for this module\n", "\n", "\n", " 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\",\n", " // Define a local copy of jQuery\n", " jQuery = function (selector, context) {\n", " // The jQuery object is actually just the init constructor 'enhanced'\n", " // Need init if jQuery is called (just allow error to be thrown if not included)\n", " return new jQuery.fn.init(selector, context);\n", " },\n", " // Support: Android <=4.0 only\n", " // Make sure we trim BOM and NBSP\n", " rtrim = /^[\\s\\uFEFF\\xA0]+|[\\s\\uFEFF\\xA0]+$/g;\n", "\n", " jQuery.fn = jQuery.prototype = {\n", " // The current version of jQuery being used\n", " jquery: version$2,\n", " constructor: jQuery,\n", " // The default length of a jQuery object is 0\n", " length: 0,\n", " toArray: function () {\n", " return slice.call(this);\n", " },\n", " // Get the Nth element in the matched element set OR\n", " // Get the whole matched element set as a clean array\n", " get: function (num) {\n", " // Return all the elements in a clean array\n", " if (num == null) {\n", " return slice.call(this);\n", " } // Return just the one element from the set\n", "\n", "\n", " return num < 0 ? this[num + this.length] : this[num];\n", " },\n", " // Take an array of elements and push it onto the stack\n", " // (returning the new matched element set)\n", " pushStack: function (elems) {\n", " // Build a new jQuery matched element set\n", " var ret = jQuery.merge(this.constructor(), elems); // Add the old object onto the stack (as a reference)\n", "\n", " ret.prevObject = this; // Return the newly-formed element set\n", "\n", " return ret;\n", " },\n", " // Execute a callback for every element in the matched set.\n", " each: function (callback) {\n", " return jQuery.each(this, callback);\n", " },\n", " map: function (callback) {\n", " return this.pushStack(jQuery.map(this, function (elem, i) {\n", " return callback.call(elem, i, elem);\n", " }));\n", " },\n", " slice: function () {\n", " return this.pushStack(slice.apply(this, arguments));\n", " },\n", " first: function () {\n", " return this.eq(0);\n", " },\n", " last: function () {\n", " return this.eq(-1);\n", " },\n", " eq: function (i) {\n", " var len = this.length,\n", " j = +i + (i < 0 ? len : 0);\n", " return this.pushStack(j >= 0 && j < len ? [this[j]] : []);\n", " },\n", " end: function () {\n", " return this.prevObject || this.constructor();\n", " },\n", " // For internal use only.\n", " // Behaves like an Array's method, not like a jQuery method.\n", " push: push,\n", " sort: arr.sort,\n", " splice: arr.splice\n", " };\n", "\n", " jQuery.extend = jQuery.fn.extend = function () {\n", " var options,\n", " name,\n", " src,\n", " copy,\n", " copyIsArray,\n", " clone,\n", " target = arguments[0] || {},\n", " i = 1,\n", " length = arguments.length,\n", " deep = false; // Handle a deep copy situation\n", "\n", " if (typeof target === \"boolean\") {\n", " deep = target; // Skip the boolean and the target\n", "\n", " target = arguments[i] || {};\n", " i++;\n", " } // Handle case when target is a string or something (possible in deep copy)\n", "\n", "\n", " if (typeof target !== \"object\" && !isFunction(target)) {\n", " target = {};\n", " } // Extend jQuery itself if only one argument is passed\n", "\n", "\n", " if (i === length) {\n", " target = this;\n", " i--;\n", " }\n", "\n", " for (; i < length; i++) {\n", " // Only deal with non-null/undefined values\n", " if ((options = arguments[i]) != null) {\n", " // Extend the base object\n", " for (name in options) {\n", " src = target[name];\n", " copy = options[name]; // Prevent never-ending loop\n", "\n", " if (target === copy) {\n", " continue;\n", " } // Recurse if we're merging plain objects or arrays\n", "\n", "\n", " if (deep && copy && (jQuery.isPlainObject(copy) || (copyIsArray = Array.isArray(copy)))) {\n", " if (copyIsArray) {\n", " copyIsArray = false;\n", " clone = src && Array.isArray(src) ? src : [];\n", " } else {\n", " clone = src && jQuery.isPlainObject(src) ? src : {};\n", " } // Never move original objects, clone them\n", "\n", "\n", " target[name] = jQuery.extend(deep, clone, copy); // Don't bring in undefined values\n", " } else if (copy !== undefined) {\n", " target[name] = copy;\n", " }\n", " }\n", " }\n", " } // Return the modified object\n", "\n", "\n", " return target;\n", " };\n", "\n", " jQuery.extend({\n", " // Unique for each copy of jQuery on the page\n", " expando: \"jQuery\" + (version$2 + Math.random()).replace(/\\D/g, \"\"),\n", " // Assume jQuery is ready without the ready module\n", " isReady: true,\n", " error: function (msg) {\n", " throw new Error(msg);\n", " },\n", " noop: function () {},\n", " isPlainObject: function (obj) {\n", " var proto, Ctor; // Detect obvious negatives\n", " // Use toString instead of jQuery.type to catch host objects\n", "\n", " if (!obj || toString$2.call(obj) !== \"[object Object]\") {\n", " return false;\n", " }\n", "\n", " proto = getProto(obj); // Objects with no prototype (e.g., `Object.create( null )`) are plain\n", "\n", " if (!proto) {\n", " return true;\n", " } // Objects with prototype are plain iff they were constructed by a global Object function\n", "\n", "\n", " Ctor = hasOwn$6.call(proto, \"constructor\") && proto.constructor;\n", " return typeof Ctor === \"function\" && fnToString.call(Ctor) === ObjectFunctionString;\n", " },\n", " isEmptyObject: function (obj) {\n", " /* eslint-disable no-unused-vars */\n", " // See https://github.com/eslint/eslint/issues/6125\n", " var name;\n", "\n", " for (name in obj) {\n", " return false;\n", " }\n", "\n", " return true;\n", " },\n", " // Evaluates a script in a global context\n", " globalEval: function (code) {\n", " DOMEval(code);\n", " },\n", " each: function (obj, callback) {\n", " var length,\n", " i = 0;\n", "\n", " if (isArrayLike(obj)) {\n", " length = obj.length;\n", "\n", " for (; i < length; i++) {\n", " if (callback.call(obj[i], i, obj[i]) === false) {\n", " break;\n", " }\n", " }\n", " } else {\n", " for (i in obj) {\n", " if (callback.call(obj[i], i, obj[i]) === false) {\n", " break;\n", " }\n", " }\n", " }\n", "\n", " return obj;\n", " },\n", " // Support: Android <=4.0 only\n", " trim: function (text) {\n", " return text == null ? \"\" : (text + \"\").replace(rtrim, \"\");\n", " },\n", " // results is for internal usage only\n", " makeArray: function (arr, results) {\n", " var ret = results || [];\n", "\n", " if (arr != null) {\n", " if (isArrayLike(Object(arr))) {\n", " jQuery.merge(ret, typeof arr === \"string\" ? [arr] : arr);\n", " } else {\n", " push.call(ret, arr);\n", " }\n", " }\n", "\n", " return ret;\n", " },\n", " inArray: function (elem, arr, i) {\n", " return arr == null ? -1 : indexOf.call(arr, elem, i);\n", " },\n", " // Support: Android <=4.0 only, PhantomJS 1 only\n", " // push.apply(_, arraylike) throws on ancient WebKit\n", " merge: function (first, second) {\n", " var len = +second.length,\n", " j = 0,\n", " i = first.length;\n", "\n", " for (; j < len; j++) {\n", " first[i++] = second[j];\n", " }\n", "\n", " first.length = i;\n", " return first;\n", " },\n", " grep: function (elems, callback, invert) {\n", " var callbackInverse,\n", " matches = [],\n", " i = 0,\n", " length = elems.length,\n", " callbackExpect = !invert; // Go through the array, only saving the items\n", " // that pass the validator function\n", "\n", " for (; i < length; i++) {\n", " callbackInverse = !callback(elems[i], i);\n", "\n", " if (callbackInverse !== callbackExpect) {\n", " matches.push(elems[i]);\n", " }\n", " }\n", "\n", " return matches;\n", " },\n", " // arg is for internal usage only\n", " map: function (elems, callback, arg) {\n", " var length,\n", " value,\n", " i = 0,\n", " ret = []; // Go through the array, translating each of the items to their new values\n", "\n", " if (isArrayLike(elems)) {\n", " length = elems.length;\n", "\n", " for (; i < length; i++) {\n", " value = callback(elems[i], i, arg);\n", "\n", " if (value != null) {\n", " ret.push(value);\n", " }\n", " } // Go through every key on the object,\n", "\n", " } else {\n", " for (i in elems) {\n", " value = callback(elems[i], i, arg);\n", "\n", " if (value != null) {\n", " ret.push(value);\n", " }\n", " }\n", " } // Flatten any nested arrays\n", "\n", "\n", " return concat.apply([], ret);\n", " },\n", " // A global GUID counter for objects\n", " guid: 1,\n", " // jQuery.support is not used in Core but other projects attach their\n", " // properties to it so it needs to exist.\n", " support: support\n", " });\n", "\n", " if (typeof Symbol === \"function\") {\n", " jQuery.fn[Symbol.iterator] = arr[Symbol.iterator];\n", " } // Populate the class2type map\n", "\n", "\n", " jQuery.each(\"Boolean Number String Function Array Date RegExp Object Error Symbol\".split(\" \"), function (i, name) {\n", " class2type[\"[object \" + name + \"]\"] = name.toLowerCase();\n", " });\n", "\n", " function isArrayLike(obj) {\n", " // Support: real iOS 8.2 only (not reproducible in simulator)\n", " // `in` check used to prevent JIT error (gh-2145)\n", " // hasOwn isn't used here due to false negatives\n", " // regarding Nodelist length in IE\n", " var length = !!obj && \"length\" in obj && obj.length,\n", " type = toType(obj);\n", "\n", " if (isFunction(obj) || isWindow(obj)) {\n", " return false;\n", " }\n", "\n", " return type === \"array\" || length === 0 || typeof length === \"number\" && length > 0 && length - 1 in obj;\n", " }\n", "\n", " var Sizzle =\n", " /*!\n", " * Sizzle CSS Selector Engine v2.3.3\n", " * https://sizzlejs.com/\n", " *\n", " * Copyright jQuery Foundation and other contributors\n", " * Released under the MIT license\n", " * http://jquery.org/license\n", " *\n", " * Date: 2016-08-08\n", " */\n", " function (window) {\n", " var i,\n", " support,\n", " Expr,\n", " getText,\n", " isXML,\n", " tokenize,\n", " compile,\n", " select,\n", " outermostContext,\n", " sortInput,\n", " hasDuplicate,\n", " // Local document vars\n", " setDocument,\n", " document,\n", " docElem,\n", " documentIsHTML,\n", " rbuggyQSA,\n", " rbuggyMatches,\n", " matches,\n", " contains,\n", " // Instance-specific data\n", " expando = \"sizzle\" + 1 * new Date(),\n", " preferredDoc = window.document,\n", " dirruns = 0,\n", " done = 0,\n", " classCache = createCache(),\n", " tokenCache = createCache(),\n", " compilerCache = createCache(),\n", " sortOrder = function (a, b) {\n", " if (a === b) {\n", " hasDuplicate = true;\n", " }\n", "\n", " return 0;\n", " },\n", " // Instance methods\n", " hasOwn = {}.hasOwnProperty,\n", " arr = [],\n", " pop = arr.pop,\n", " push_native = arr.push,\n", " push = arr.push,\n", " slice = arr.slice,\n", " // Use a stripped-down indexOf as it's faster than native\n", " // https://jsperf.com/thor-indexof-vs-for/5\n", " indexOf = function (list, elem) {\n", " var i = 0,\n", " len = list.length;\n", "\n", " for (; i < len; i++) {\n", " if (list[i] === elem) {\n", " return i;\n", " }\n", " }\n", "\n", " return -1;\n", " },\n", " booleans = \"checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped\",\n", " // Regular expressions\n", " // http://www.w3.org/TR/css3-selectors/#whitespace\n", " whitespace = \"[\\\\x20\\\\t\\\\r\\\\n\\\\f]\",\n", " // http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier\n", " identifier = \"(?:\\\\\\\\.|[\\\\w-]|[^\\0-\\\\xa0])+\",\n", " // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors\n", " attributes = \"\\\\[\" + whitespace + \"*(\" + identifier + \")(?:\" + whitespace + // Operator (capture 2)\n", " \"*([*^$|!~]?=)\" + whitespace + // \"Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]\"\n", " \"*(?:'((?:\\\\\\\\.|[^\\\\\\\\'])*)'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\"|(\" + identifier + \"))|)\" + whitespace + \"*\\\\]\",\n", " pseudos = \":(\" + identifier + \")(?:\\\\((\" + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:\n", " // 1. quoted (capture 3; capture 4 or capture 5)\n", " \"('((?:\\\\\\\\.|[^\\\\\\\\'])*)'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\")|\" + // 2. simple (capture 6)\n", " \"((?:\\\\\\\\.|[^\\\\\\\\()[\\\\]]|\" + attributes + \")*)|\" + // 3. anything else (capture 2)\n", " \".*\" + \")\\\\)|)\",\n", " // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter\n", " rwhitespace = new RegExp(whitespace + \"+\", \"g\"),\n", " rtrim = new RegExp(\"^\" + whitespace + \"+|((?:^|[^\\\\\\\\])(?:\\\\\\\\.)*)\" + whitespace + \"+$\", \"g\"),\n", " rcomma = new RegExp(\"^\" + whitespace + \"*,\" + whitespace + \"*\"),\n", " rcombinators = new RegExp(\"^\" + whitespace + \"*([>+~]|\" + whitespace + \")\" + whitespace + \"*\"),\n", " rattributeQuotes = new RegExp(\"=\" + whitespace + \"*([^\\\\]'\\\"]*?)\" + whitespace + \"*\\\\]\", \"g\"),\n", " rpseudo = new RegExp(pseudos),\n", " ridentifier = new RegExp(\"^\" + identifier + \"$\"),\n", " matchExpr = {\n", " \"ID\": new RegExp(\"^#(\" + identifier + \")\"),\n", " \"CLASS\": new RegExp(\"^\\\\.(\" + identifier + \")\"),\n", " \"TAG\": new RegExp(\"^(\" + identifier + \"|[*])\"),\n", " \"ATTR\": new RegExp(\"^\" + attributes),\n", " \"PSEUDO\": new RegExp(\"^\" + pseudos),\n", " \"CHILD\": new RegExp(\"^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\\\(\" + whitespace + \"*(even|odd|(([+-]|)(\\\\d*)n|)\" + whitespace + \"*(?:([+-]|)\" + whitespace + \"*(\\\\d+)|))\" + whitespace + \"*\\\\)|)\", \"i\"),\n", " \"bool\": new RegExp(\"^(?:\" + booleans + \")$\", \"i\"),\n", " // For use in libraries implementing .is()\n", " // We use this for POS matching in `select`\n", " \"needsContext\": new RegExp(\"^\" + whitespace + \"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\\\(\" + whitespace + \"*((?:-\\\\d)?\\\\d*)\" + whitespace + \"*\\\\)|)(?=[^-]|$)\", \"i\")\n", " },\n", " rinputs = /^(?:input|select|textarea|button)$/i,\n", " rheader = /^h\\d$/i,\n", " rnative = /^[^{]+\\{\\s*\\[native \\w/,\n", " // Easily-parseable/retrievable ID or TAG or CLASS selectors\n", " rquickExpr = /^(?:#([\\w-]+)|(\\w+)|\\.([\\w-]+))$/,\n", " rsibling = /[+~]/,\n", " // CSS escapes\n", " // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters\n", " runescape = new RegExp(\"\\\\\\\\([\\\\da-f]{1,6}\" + whitespace + \"?|(\" + whitespace + \")|.)\", \"ig\"),\n", " funescape = function (_, escaped, escapedWhitespace) {\n", " var high = \"0x\" + escaped - 0x10000; // NaN means non-codepoint\n", " // Support: Firefox<24\n", " // Workaround erroneous numeric interpretation of +\"0x\"\n", "\n", " return high !== high || escapedWhitespace ? escaped : high < 0 ? // BMP codepoint\n", " String.fromCharCode(high + 0x10000) : // Supplemental Plane codepoint (surrogate pair)\n", " String.fromCharCode(high >> 10 | 0xD800, high & 0x3FF | 0xDC00);\n", " },\n", " // CSS string/identifier serialization\n", " // https://drafts.csswg.org/cssom/#common-serializing-idioms\n", " // eslint-disable-next-line no-control-regex\n", " rcssescape = /([\\0-\\x1f\\x7f]|^-?\\d)|^-$|[^\\0-\\x1f\\x7f-\\uFFFF\\w-]/g,\n", " fcssescape = function (ch, asCodePoint) {\n", " if (asCodePoint) {\n", " // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER\n", " if (ch === \"\\0\") {\n", " return \"\\uFFFD\";\n", " } // Control characters and (dependent upon position) numbers get escaped as code points\n", "\n", "\n", " return ch.slice(0, -1) + \"\\\\\" + ch.charCodeAt(ch.length - 1).toString(16) + \" \";\n", " } // Other potentially-special ASCII characters get backslash-escaped\n", "\n", "\n", " return \"\\\\\" + ch;\n", " },\n", " // Used for iframes\n", " // See setDocument()\n", " // Removing the function wrapper causes a \"Permission Denied\"\n", " // error in IE\n", " unloadHandler = function () {\n", " setDocument();\n", " },\n", " disabledAncestor = addCombinator(function (elem) {\n", " return elem.disabled === true && (\"form\" in elem || \"label\" in elem);\n", " }, {\n", " dir: \"parentNode\",\n", " next: \"legend\"\n", " }); // Optimize for push.apply( _, NodeList )\n", "\n", "\n", " try {\n", " push.apply(arr = slice.call(preferredDoc.childNodes), preferredDoc.childNodes); // Support: Android<4.0\n", " // Detect silently failing push.apply\n", "\n", " arr[preferredDoc.childNodes.length].nodeType;\n", " } catch (e) {\n", " push = {\n", " apply: arr.length ? // Leverage slice if possible\n", " function (target, els) {\n", " push_native.apply(target, slice.call(els));\n", " } : // Support: IE<9\n", " // Otherwise append directly\n", " function (target, els) {\n", " var j = target.length,\n", " i = 0; // Can't trust NodeList.length\n", "\n", " while (target[j++] = els[i++]) {}\n", "\n", " target.length = j - 1;\n", " }\n", " };\n", " }\n", "\n", " function Sizzle(selector, context, results, seed) {\n", " var m,\n", " i,\n", " elem,\n", " nid,\n", " match,\n", " groups,\n", " newSelector,\n", " newContext = context && context.ownerDocument,\n", " // nodeType defaults to 9, since context defaults to document\n", " nodeType = context ? context.nodeType : 9;\n", " results = results || []; // Return early from calls with invalid selector or context\n", "\n", " if (typeof selector !== \"string\" || !selector || nodeType !== 1 && nodeType !== 9 && nodeType !== 11) {\n", " return results;\n", " } // Try to shortcut find operations (as opposed to filters) in HTML documents\n", "\n", "\n", " if (!seed) {\n", " if ((context ? context.ownerDocument || context : preferredDoc) !== document) {\n", " setDocument(context);\n", " }\n", "\n", " context = context || document;\n", "\n", " if (documentIsHTML) {\n", " // If the selector is sufficiently simple, try using a \"get*By*\" DOM method\n", " // (excepting DocumentFragment context, where the methods don't exist)\n", " if (nodeType !== 11 && (match = rquickExpr.exec(selector))) {\n", " // ID selector\n", " if (m = match[1]) {\n", " // Document context\n", " if (nodeType === 9) {\n", " if (elem = context.getElementById(m)) {\n", " // Support: IE, Opera, Webkit\n", " // TODO: identify versions\n", " // getElementById can match elements by name instead of ID\n", " if (elem.id === m) {\n", " results.push(elem);\n", " return results;\n", " }\n", " } else {\n", " return results;\n", " } // Element context\n", "\n", " } else {\n", " // Support: IE, Opera, Webkit\n", " // TODO: identify versions\n", " // getElementById can match elements by name instead of ID\n", " if (newContext && (elem = newContext.getElementById(m)) && contains(context, elem) && elem.id === m) {\n", " results.push(elem);\n", " return results;\n", " }\n", " } // Type selector\n", "\n", " } else if (match[2]) {\n", " push.apply(results, context.getElementsByTagName(selector));\n", " return results; // Class selector\n", " } else if ((m = match[3]) && support.getElementsByClassName && context.getElementsByClassName) {\n", " push.apply(results, context.getElementsByClassName(m));\n", " return results;\n", " }\n", " } // Take advantage of querySelectorAll\n", "\n", "\n", " if (support.qsa && !compilerCache[selector + \" \"] && (!rbuggyQSA || !rbuggyQSA.test(selector))) {\n", " if (nodeType !== 1) {\n", " newContext = context;\n", " newSelector = selector; // qSA looks outside Element context, which is not what we want\n", " // Thanks to Andrew Dupont for this workaround technique\n", " // Support: IE <=8\n", " // Exclude object elements\n", " } else if (context.nodeName.toLowerCase() !== \"object\") {\n", " // Capture the context ID, setting it first if necessary\n", " if (nid = context.getAttribute(\"id\")) {\n", " nid = nid.replace(rcssescape, fcssescape);\n", " } else {\n", " context.setAttribute(\"id\", nid = expando);\n", " } // Prefix every selector in the list\n", "\n", "\n", " groups = tokenize(selector);\n", " i = groups.length;\n", "\n", " while (i--) {\n", " groups[i] = \"#\" + nid + \" \" + toSelector(groups[i]);\n", " }\n", "\n", " newSelector = groups.join(\",\"); // Expand context for sibling selectors\n", "\n", " newContext = rsibling.test(selector) && testContext(context.parentNode) || context;\n", " }\n", "\n", " if (newSelector) {\n", " try {\n", " push.apply(results, newContext.querySelectorAll(newSelector));\n", " return results;\n", " } catch (qsaError) {} finally {\n", " if (nid === expando) {\n", " context.removeAttribute(\"id\");\n", " }\n", " }\n", " }\n", " }\n", " }\n", " } // All others\n", "\n", "\n", " return select(selector.replace(rtrim, \"$1\"), context, results, seed);\n", " }\n", " /**\n", " * Create key-value caches of limited size\n", " * @returns {function(string, object)} Returns the Object data after storing it on itself with\n", " * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)\n", " * deleting the oldest entry\n", " */\n", "\n", "\n", " function createCache() {\n", " var keys = [];\n", "\n", " function cache(key, value) {\n", " // Use (key + \" \") to avoid collision with native prototype properties (see Issue #157)\n", " if (keys.push(key + \" \") > Expr.cacheLength) {\n", " // Only keep the most recent entries\n", " delete cache[keys.shift()];\n", " }\n", "\n", " return cache[key + \" \"] = value;\n", " }\n", "\n", " return cache;\n", " }\n", " /**\n", " * Mark a function for special use by Sizzle\n", " * @param {Function} fn The function to mark\n", " */\n", "\n", "\n", " function markFunction(fn) {\n", " fn[expando] = true;\n", " return fn;\n", " }\n", " /**\n", " * Support testing using an element\n", " * @param {Function} fn Passed the created element and returns a boolean result\n", " */\n", "\n", "\n", " function assert(fn) {\n", " // When unit testing from Node document will be undefined. We don't care about assertions in that case.\n", " if (!document) return true;\n", " var el = document.createElement(\"fieldset\");\n", "\n", " try {\n", " return !!fn(el);\n", " } catch (e) {\n", " return false;\n", " } finally {\n", " // Remove from its parent by default\n", " if (el.parentNode) {\n", " el.parentNode.removeChild(el);\n", " } // release memory in IE\n", "\n", "\n", " el = null;\n", " }\n", " }\n", " /**\n", " * Adds the same handler for all of the specified attrs\n", " * @param {String} attrs Pipe-separated list of attributes\n", " * @param {Function} handler The method that will be applied\n", " */\n", "\n", "\n", " function addHandle(attrs, handler) {\n", " var arr = attrs.split(\"|\"),\n", " i = arr.length;\n", "\n", " while (i--) {\n", " Expr.attrHandle[arr[i]] = handler;\n", " }\n", " }\n", " /**\n", " * Checks document order of two siblings\n", " * @param {Element} a\n", " * @param {Element} b\n", " * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b\n", " */\n", "\n", "\n", " function siblingCheck(a, b) {\n", " var cur = b && a,\n", " diff = cur && a.nodeType === 1 && b.nodeType === 1 && a.sourceIndex - b.sourceIndex; // Use IE sourceIndex if available on both nodes\n", "\n", " if (diff) {\n", " return diff;\n", " } // Check if b follows a\n", "\n", "\n", " if (cur) {\n", " while (cur = cur.nextSibling) {\n", " if (cur === b) {\n", " return -1;\n", " }\n", " }\n", " }\n", "\n", " return a ? 1 : -1;\n", " }\n", " /**\n", " * Returns a function to use in pseudos for input types\n", " * @param {String} type\n", " */\n", "\n", "\n", " function createInputPseudo(type) {\n", " return function (elem) {\n", " var name = elem.nodeName.toLowerCase();\n", " return name === \"input\" && elem.type === type;\n", " };\n", " }\n", " /**\n", " * Returns a function to use in pseudos for buttons\n", " * @param {String} type\n", " */\n", "\n", "\n", " function createButtonPseudo(type) {\n", " return function (elem) {\n", " var name = elem.nodeName.toLowerCase();\n", " return (name === \"input\" || name === \"button\") && elem.type === type;\n", " };\n", " }\n", " /**\n", " * Returns a function to use in pseudos for :enabled/:disabled\n", " * @param {Boolean} disabled true for :disabled; false for :enabled\n", " */\n", "\n", "\n", " function createDisabledPseudo(disabled) {\n", " // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable\n", " return function (elem) {\n", " // Only certain elements can match :enabled or :disabled\n", " // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled\n", " // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled\n", " if (\"form\" in elem) {\n", " // Check for inherited disabledness on relevant non-disabled elements:\n", " // * listed form-associated elements in a disabled fieldset\n", " // https://html.spec.whatwg.org/multipage/forms.html#category-listed\n", " // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled\n", " // * option elements in a disabled optgroup\n", " // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled\n", " // All such elements have a \"form\" property.\n", " if (elem.parentNode && elem.disabled === false) {\n", " // Option elements defer to a parent optgroup if present\n", " if (\"label\" in elem) {\n", " if (\"label\" in elem.parentNode) {\n", " return elem.parentNode.disabled === disabled;\n", " } else {\n", " return elem.disabled === disabled;\n", " }\n", " } // Support: IE 6 - 11\n", " // Use the isDisabled shortcut property to check for disabled fieldset ancestors\n", "\n", "\n", " return elem.isDisabled === disabled || // Where there is no isDisabled, check manually\n", "\n", " /* jshint -W018 */\n", " elem.isDisabled !== !disabled && disabledAncestor(elem) === disabled;\n", " }\n", "\n", " return elem.disabled === disabled; // Try to winnow out elements that can't be disabled before trusting the disabled property.\n", " // Some victims get caught in our net (label, legend, menu, track), but it shouldn't\n", " // even exist on them, let alone have a boolean value.\n", " } else if (\"label\" in elem) {\n", " return elem.disabled === disabled;\n", " } // Remaining elements are neither :enabled nor :disabled\n", "\n", "\n", " return false;\n", " };\n", " }\n", " /**\n", " * Returns a function to use in pseudos for positionals\n", " * @param {Function} fn\n", " */\n", "\n", "\n", " function createPositionalPseudo(fn) {\n", " return markFunction(function (argument) {\n", " argument = +argument;\n", " return markFunction(function (seed, matches) {\n", " var j,\n", " matchIndexes = fn([], seed.length, argument),\n", " i = matchIndexes.length; // Match elements found at the specified indexes\n", "\n", " while (i--) {\n", " if (seed[j = matchIndexes[i]]) {\n", " seed[j] = !(matches[j] = seed[j]);\n", " }\n", " }\n", " });\n", " });\n", " }\n", " /**\n", " * Checks a node for validity as a Sizzle context\n", " * @param {Element|Object=} context\n", " * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value\n", " */\n", "\n", "\n", " function testContext(context) {\n", " return context && typeof context.getElementsByTagName !== \"undefined\" && context;\n", " } // Expose support vars for convenience\n", "\n", "\n", " support = Sizzle.support = {};\n", " /**\n", " * Detects XML nodes\n", " * @param {Element|Object} elem An element or a document\n", " * @returns {Boolean} True iff elem is a non-HTML XML node\n", " */\n", "\n", " isXML = Sizzle.isXML = function (elem) {\n", " // documentElement is verified for cases where it doesn't yet exist\n", " // (such as loading iframes in IE - #4833)\n", " var documentElement = elem && (elem.ownerDocument || elem).documentElement;\n", " return documentElement ? documentElement.nodeName !== \"HTML\" : false;\n", " };\n", " /**\n", " * Sets document-related variables once based on the current document\n", " * @param {Element|Object} [doc] An element or document object to use to set the document\n", " * @returns {Object} Returns the current document\n", " */\n", "\n", "\n", " setDocument = Sizzle.setDocument = function (node) {\n", " var hasCompare,\n", " subWindow,\n", " doc = node ? node.ownerDocument || node : preferredDoc; // Return early if doc is invalid or already selected\n", "\n", " if (doc === document || doc.nodeType !== 9 || !doc.documentElement) {\n", " return document;\n", " } // Update global variables\n", "\n", "\n", " document = doc;\n", " docElem = document.documentElement;\n", " documentIsHTML = !isXML(document); // Support: IE 9-11, Edge\n", " // Accessing iframe documents after unload throws \"permission denied\" errors (jQuery #13936)\n", "\n", " if (preferredDoc !== document && (subWindow = document.defaultView) && subWindow.top !== subWindow) {\n", " // Support: IE 11, Edge\n", " if (subWindow.addEventListener) {\n", " subWindow.addEventListener(\"unload\", unloadHandler, false); // Support: IE 9 - 10 only\n", " } else if (subWindow.attachEvent) {\n", " subWindow.attachEvent(\"onunload\", unloadHandler);\n", " }\n", " }\n", " /* Attributes\n", " ---------------------------------------------------------------------- */\n", " // Support: IE<8\n", " // Verify that getAttribute really returns attributes and not properties\n", " // (excepting IE8 booleans)\n", "\n", "\n", " support.attributes = assert(function (el) {\n", " el.className = \"i\";\n", " return !el.getAttribute(\"className\");\n", " });\n", " /* getElement(s)By*\n", " ---------------------------------------------------------------------- */\n", " // Check if getElementsByTagName(\"*\") returns only elements\n", "\n", " support.getElementsByTagName = assert(function (el) {\n", " el.appendChild(document.createComment(\"\"));\n", " return !el.getElementsByTagName(\"*\").length;\n", " }); // Support: IE<9\n", "\n", " support.getElementsByClassName = rnative.test(document.getElementsByClassName); // Support: IE<10\n", " // Check if getElementById returns elements by name\n", " // The broken getElementById methods don't pick up programmatically-set names,\n", " // so use a roundabout getElementsByName test\n", "\n", " support.getById = assert(function (el) {\n", " docElem.appendChild(el).id = expando;\n", " return !document.getElementsByName || !document.getElementsByName(expando).length;\n", " }); // ID filter and find\n", "\n", " if (support.getById) {\n", " Expr.filter[\"ID\"] = function (id) {\n", " var attrId = id.replace(runescape, funescape);\n", " return function (elem) {\n", " return elem.getAttribute(\"id\") === attrId;\n", " };\n", " };\n", "\n", " Expr.find[\"ID\"] = function (id, context) {\n", " if (typeof context.getElementById !== \"undefined\" && documentIsHTML) {\n", " var elem = context.getElementById(id);\n", " return elem ? [elem] : [];\n", " }\n", " };\n", " } else {\n", " Expr.filter[\"ID\"] = function (id) {\n", " var attrId = id.replace(runescape, funescape);\n", " return function (elem) {\n", " var node = typeof elem.getAttributeNode !== \"undefined\" && elem.getAttributeNode(\"id\");\n", " return node && node.value === attrId;\n", " };\n", " }; // Support: IE 6 - 7 only\n", " // getElementById is not reliable as a find shortcut\n", "\n", "\n", " Expr.find[\"ID\"] = function (id, context) {\n", " if (typeof context.getElementById !== \"undefined\" && documentIsHTML) {\n", " var node,\n", " i,\n", " elems,\n", " elem = context.getElementById(id);\n", "\n", " if (elem) {\n", " // Verify the id attribute\n", " node = elem.getAttributeNode(\"id\");\n", "\n", " if (node && node.value === id) {\n", " return [elem];\n", " } // Fall back on getElementsByName\n", "\n", "\n", " elems = context.getElementsByName(id);\n", " i = 0;\n", "\n", " while (elem = elems[i++]) {\n", " node = elem.getAttributeNode(\"id\");\n", "\n", " if (node && node.value === id) {\n", " return [elem];\n", " }\n", " }\n", " }\n", "\n", " return [];\n", " }\n", " };\n", " } // Tag\n", "\n", "\n", " Expr.find[\"TAG\"] = support.getElementsByTagName ? function (tag, context) {\n", " if (typeof context.getElementsByTagName !== \"undefined\") {\n", " return context.getElementsByTagName(tag); // DocumentFragment nodes don't have gEBTN\n", " } else if (support.qsa) {\n", " return context.querySelectorAll(tag);\n", " }\n", " } : function (tag, context) {\n", " var elem,\n", " tmp = [],\n", " i = 0,\n", " // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too\n", " results = context.getElementsByTagName(tag); // Filter out possible comments\n", "\n", " if (tag === \"*\") {\n", " while (elem = results[i++]) {\n", " if (elem.nodeType === 1) {\n", " tmp.push(elem);\n", " }\n", " }\n", "\n", " return tmp;\n", " }\n", "\n", " return results;\n", " }; // Class\n", "\n", " Expr.find[\"CLASS\"] = support.getElementsByClassName && function (className, context) {\n", " if (typeof context.getElementsByClassName !== \"undefined\" && documentIsHTML) {\n", " return context.getElementsByClassName(className);\n", " }\n", " };\n", " /* QSA/matchesSelector\n", " ---------------------------------------------------------------------- */\n", " // QSA and matchesSelector support\n", " // matchesSelector(:active) reports false when true (IE9/Opera 11.5)\n", "\n", "\n", " rbuggyMatches = []; // qSa(:focus) reports false when true (Chrome 21)\n", " // We allow this because of a bug in IE8/9 that throws an error\n", " // whenever `document.activeElement` is accessed on an iframe\n", " // So, we allow :focus to pass through QSA all the time to avoid the IE error\n", " // See https://bugs.jquery.com/ticket/13378\n", "\n", " rbuggyQSA = [];\n", "\n", " if (support.qsa = rnative.test(document.querySelectorAll)) {\n", " // Build QSA regex\n", " // Regex strategy adopted from Diego Perini\n", " assert(function (el) {\n", " // Select is set to empty string on purpose\n", " // This is to test IE's treatment of not explicitly\n", " // setting a boolean content attribute,\n", " // since its presence should be enough\n", " // https://bugs.jquery.com/ticket/12359\n", " docElem.appendChild(el).innerHTML = \"\" + \"\"; // Support: IE8, Opera 11-12.16\n", " // Nothing should be selected when empty strings follow ^= or $= or *=\n", " // The test attribute must be unknown in Opera but \"safe\" for WinRT\n", " // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section\n", "\n", " if (el.querySelectorAll(\"[msallowcapture^='']\").length) {\n", " rbuggyQSA.push(\"[*^$]=\" + whitespace + \"*(?:''|\\\"\\\")\");\n", " } // Support: IE8\n", " // Boolean attributes and \"value\" are not treated correctly\n", "\n", "\n", " if (!el.querySelectorAll(\"[selected]\").length) {\n", " rbuggyQSA.push(\"\\\\[\" + whitespace + \"*(?:value|\" + booleans + \")\");\n", " } // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+\n", "\n", "\n", " if (!el.querySelectorAll(\"[id~=\" + expando + \"-]\").length) {\n", " rbuggyQSA.push(\"~=\");\n", " } // Webkit/Opera - :checked should return selected option elements\n", " // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked\n", " // IE8 throws error here and will not see later tests\n", "\n", "\n", " if (!el.querySelectorAll(\":checked\").length) {\n", " rbuggyQSA.push(\":checked\");\n", " } // Support: Safari 8+, iOS 8+\n", " // https://bugs.webkit.org/show_bug.cgi?id=136851\n", " // In-page `selector#id sibling-combinator selector` fails\n", "\n", "\n", " if (!el.querySelectorAll(\"a#\" + expando + \"+*\").length) {\n", " rbuggyQSA.push(\".#.+[+~]\");\n", " }\n", " });\n", " assert(function (el) {\n", " el.innerHTML = \"\" + \"\"; // Support: Windows 8 Native Apps\n", " // The type and name attributes are restricted during .innerHTML assignment\n", "\n", " var input = document.createElement(\"input\");\n", " input.setAttribute(\"type\", \"hidden\");\n", " el.appendChild(input).setAttribute(\"name\", \"D\"); // Support: IE8\n", " // Enforce case-sensitivity of name attribute\n", "\n", " if (el.querySelectorAll(\"[name=d]\").length) {\n", " rbuggyQSA.push(\"name\" + whitespace + \"*[*^$|!~]?=\");\n", " } // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)\n", " // IE8 throws error here and will not see later tests\n", "\n", "\n", " if (el.querySelectorAll(\":enabled\").length !== 2) {\n", " rbuggyQSA.push(\":enabled\", \":disabled\");\n", " } // Support: IE9-11+\n", " // IE's :disabled selector does not pick up the children of disabled fieldsets\n", "\n", "\n", " docElem.appendChild(el).disabled = true;\n", "\n", " if (el.querySelectorAll(\":disabled\").length !== 2) {\n", " rbuggyQSA.push(\":enabled\", \":disabled\");\n", " } // Opera 10-11 does not throw on post-comma invalid pseudos\n", "\n", "\n", " el.querySelectorAll(\"*,:x\");\n", " rbuggyQSA.push(\",.*:\");\n", " });\n", " }\n", "\n", " if (support.matchesSelector = rnative.test(matches = docElem.matches || docElem.webkitMatchesSelector || docElem.mozMatchesSelector || docElem.oMatchesSelector || docElem.msMatchesSelector)) {\n", " assert(function (el) {\n", " // Check to see if it's possible to do matchesSelector\n", " // on a disconnected node (IE 9)\n", " support.disconnectedMatch = matches.call(el, \"*\"); // This should fail with an exception\n", " // Gecko does not error, returns false instead\n", "\n", " matches.call(el, \"[s!='']:x\");\n", " rbuggyMatches.push(\"!=\", pseudos);\n", " });\n", " }\n", "\n", " rbuggyQSA = rbuggyQSA.length && new RegExp(rbuggyQSA.join(\"|\"));\n", " rbuggyMatches = rbuggyMatches.length && new RegExp(rbuggyMatches.join(\"|\"));\n", " /* Contains\n", " ---------------------------------------------------------------------- */\n", "\n", " hasCompare = rnative.test(docElem.compareDocumentPosition); // Element contains another\n", " // Purposefully self-exclusive\n", " // As in, an element does not contain itself\n", "\n", " contains = hasCompare || rnative.test(docElem.contains) ? function (a, b) {\n", " var adown = a.nodeType === 9 ? a.documentElement : a,\n", " bup = b && b.parentNode;\n", " return a === bup || !!(bup && bup.nodeType === 1 && (adown.contains ? adown.contains(bup) : a.compareDocumentPosition && a.compareDocumentPosition(bup) & 16));\n", " } : function (a, b) {\n", " if (b) {\n", " while (b = b.parentNode) {\n", " if (b === a) {\n", " return true;\n", " }\n", " }\n", " }\n", "\n", " return false;\n", " };\n", " /* Sorting\n", " ---------------------------------------------------------------------- */\n", " // Document order sorting\n", "\n", " sortOrder = hasCompare ? function (a, b) {\n", " // Flag for duplicate removal\n", " if (a === b) {\n", " hasDuplicate = true;\n", " return 0;\n", " } // Sort on method existence if only one input has compareDocumentPosition\n", "\n", "\n", " var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;\n", "\n", " if (compare) {\n", " return compare;\n", " } // Calculate position if both inputs belong to the same document\n", "\n", "\n", " compare = (a.ownerDocument || a) === (b.ownerDocument || b) ? a.compareDocumentPosition(b) : // Otherwise we know they are disconnected\n", " 1; // Disconnected nodes\n", "\n", " if (compare & 1 || !support.sortDetached && b.compareDocumentPosition(a) === compare) {\n", " // Choose the first element that is related to our preferred document\n", " if (a === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a)) {\n", " return -1;\n", " }\n", "\n", " if (b === document || b.ownerDocument === preferredDoc && contains(preferredDoc, b)) {\n", " return 1;\n", " } // Maintain original order\n", "\n", "\n", " return sortInput ? indexOf(sortInput, a) - indexOf(sortInput, b) : 0;\n", " }\n", "\n", " return compare & 4 ? -1 : 1;\n", " } : function (a, b) {\n", " // Exit early if the nodes are identical\n", " if (a === b) {\n", " hasDuplicate = true;\n", " return 0;\n", " }\n", "\n", " var cur,\n", " i = 0,\n", " aup = a.parentNode,\n", " bup = b.parentNode,\n", " ap = [a],\n", " bp = [b]; // Parentless nodes are either documents or disconnected\n", "\n", " if (!aup || !bup) {\n", " 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\n", " } else if (aup === bup) {\n", " return siblingCheck(a, b);\n", " } // Otherwise we need full lists of their ancestors for comparison\n", "\n", "\n", " cur = a;\n", "\n", " while (cur = cur.parentNode) {\n", " ap.unshift(cur);\n", " }\n", "\n", " cur = b;\n", "\n", " while (cur = cur.parentNode) {\n", " bp.unshift(cur);\n", " } // Walk down the tree looking for a discrepancy\n", "\n", "\n", " while (ap[i] === bp[i]) {\n", " i++;\n", " }\n", "\n", " return i ? // Do a sibling check if the nodes have a common ancestor\n", " siblingCheck(ap[i], bp[i]) : // Otherwise nodes in our document sort first\n", " ap[i] === preferredDoc ? -1 : bp[i] === preferredDoc ? 1 : 0;\n", " };\n", " return document;\n", " };\n", "\n", " Sizzle.matches = function (expr, elements) {\n", " return Sizzle(expr, null, null, elements);\n", " };\n", "\n", " Sizzle.matchesSelector = function (elem, expr) {\n", " // Set document vars if needed\n", " if ((elem.ownerDocument || elem) !== document) {\n", " setDocument(elem);\n", " } // Make sure that attribute selectors are quoted\n", "\n", "\n", " expr = expr.replace(rattributeQuotes, \"='$1']\");\n", "\n", " if (support.matchesSelector && documentIsHTML && !compilerCache[expr + \" \"] && (!rbuggyMatches || !rbuggyMatches.test(expr)) && (!rbuggyQSA || !rbuggyQSA.test(expr))) {\n", " try {\n", " var ret = matches.call(elem, expr); // IE 9's matchesSelector returns false on disconnected nodes\n", "\n", " if (ret || support.disconnectedMatch || // As well, disconnected nodes are said to be in a document\n", " // fragment in IE 9\n", " elem.document && elem.document.nodeType !== 11) {\n", " return ret;\n", " }\n", " } catch (e) {}\n", " }\n", "\n", " return Sizzle(expr, document, null, [elem]).length > 0;\n", " };\n", "\n", " Sizzle.contains = function (context, elem) {\n", " // Set document vars if needed\n", " if ((context.ownerDocument || context) !== document) {\n", " setDocument(context);\n", " }\n", "\n", " return contains(context, elem);\n", " };\n", "\n", " Sizzle.attr = function (elem, name) {\n", " // Set document vars if needed\n", " if ((elem.ownerDocument || elem) !== document) {\n", " setDocument(elem);\n", " }\n", "\n", " var fn = Expr.attrHandle[name.toLowerCase()],\n", " // Don't get fooled by Object.prototype properties (jQuery #13807)\n", " val = fn && hasOwn.call(Expr.attrHandle, name.toLowerCase()) ? fn(elem, name, !documentIsHTML) : undefined;\n", " return val !== undefined ? val : support.attributes || !documentIsHTML ? elem.getAttribute(name) : (val = elem.getAttributeNode(name)) && val.specified ? val.value : null;\n", " };\n", "\n", " Sizzle.escape = function (sel) {\n", " return (sel + \"\").replace(rcssescape, fcssescape);\n", " };\n", "\n", " Sizzle.error = function (msg) {\n", " throw new Error(\"Syntax error, unrecognized expression: \" + msg);\n", " };\n", " /**\n", " * Document sorting and removing duplicates\n", " * @param {ArrayLike} results\n", " */\n", "\n", "\n", " Sizzle.uniqueSort = function (results) {\n", " var elem,\n", " duplicates = [],\n", " j = 0,\n", " i = 0; // Unless we *know* we can detect duplicates, assume their presence\n", "\n", " hasDuplicate = !support.detectDuplicates;\n", " sortInput = !support.sortStable && results.slice(0);\n", " results.sort(sortOrder);\n", "\n", " if (hasDuplicate) {\n", " while (elem = results[i++]) {\n", " if (elem === results[i]) {\n", " j = duplicates.push(i);\n", " }\n", " }\n", "\n", " while (j--) {\n", " results.splice(duplicates[j], 1);\n", " }\n", " } // Clear input after sorting to release objects\n", " // See https://github.com/jquery/sizzle/pull/225\n", "\n", "\n", " sortInput = null;\n", " return results;\n", " };\n", " /**\n", " * Utility function for retrieving the text value of an array of DOM nodes\n", " * @param {Array|Element} elem\n", " */\n", "\n", "\n", " getText = Sizzle.getText = function (elem) {\n", " var node,\n", " ret = \"\",\n", " i = 0,\n", " nodeType = elem.nodeType;\n", "\n", " if (!nodeType) {\n", " // If no nodeType, this is expected to be an array\n", " while (node = elem[i++]) {\n", " // Do not traverse comment nodes\n", " ret += getText(node);\n", " }\n", " } else if (nodeType === 1 || nodeType === 9 || nodeType === 11) {\n", " // Use textContent for elements\n", " // innerText usage removed for consistency of new lines (jQuery #11153)\n", " if (typeof elem.textContent === \"string\") {\n", " return elem.textContent;\n", " } else {\n", " // Traverse its children\n", " for (elem = elem.firstChild; elem; elem = elem.nextSibling) {\n", " ret += getText(elem);\n", " }\n", " }\n", " } else if (nodeType === 3 || nodeType === 4) {\n", " return elem.nodeValue;\n", " } // Do not include comment or processing instruction nodes\n", "\n", "\n", " return ret;\n", " };\n", "\n", " Expr = Sizzle.selectors = {\n", " // Can be adjusted by the user\n", " cacheLength: 50,\n", " createPseudo: markFunction,\n", " match: matchExpr,\n", " attrHandle: {},\n", " find: {},\n", " relative: {\n", " \">\": {\n", " dir: \"parentNode\",\n", " first: true\n", " },\n", " \" \": {\n", " dir: \"parentNode\"\n", " },\n", " \"+\": {\n", " dir: \"previousSibling\",\n", " first: true\n", " },\n", " \"~\": {\n", " dir: \"previousSibling\"\n", " }\n", " },\n", " preFilter: {\n", " \"ATTR\": function (match) {\n", " match[1] = match[1].replace(runescape, funescape); // Move the given value to match[3] whether quoted or unquoted\n", "\n", " match[3] = (match[3] || match[4] || match[5] || \"\").replace(runescape, funescape);\n", "\n", " if (match[2] === \"~=\") {\n", " match[3] = \" \" + match[3] + \" \";\n", " }\n", "\n", " return match.slice(0, 4);\n", " },\n", " \"CHILD\": function (match) {\n", " /* matches from matchExpr[\"CHILD\"]\n", " 1 type (only|nth|...)\n", " 2 what (child|of-type)\n", " 3 argument (even|odd|\\d*|\\d*n([+-]\\d+)?|...)\n", " 4 xn-component of xn+y argument ([+-]?\\d*n|)\n", " 5 sign of xn-component\n", " 6 x of xn-component\n", " 7 sign of y-component\n", " 8 y of y-component\n", " */\n", " match[1] = match[1].toLowerCase();\n", "\n", " if (match[1].slice(0, 3) === \"nth\") {\n", " // nth-* requires argument\n", " if (!match[3]) {\n", " Sizzle.error(match[0]);\n", " } // numeric x and y parameters for Expr.filter.CHILD\n", " // remember that false/true cast respectively to 0/1\n", "\n", "\n", " match[4] = +(match[4] ? match[5] + (match[6] || 1) : 2 * (match[3] === \"even\" || match[3] === \"odd\"));\n", " match[5] = +(match[7] + match[8] || match[3] === \"odd\"); // other types prohibit arguments\n", " } else if (match[3]) {\n", " Sizzle.error(match[0]);\n", " }\n", "\n", " return match;\n", " },\n", " \"PSEUDO\": function (match) {\n", " var excess,\n", " unquoted = !match[6] && match[2];\n", "\n", " if (matchExpr[\"CHILD\"].test(match[0])) {\n", " return null;\n", " } // Accept quoted arguments as-is\n", "\n", "\n", " if (match[3]) {\n", " match[2] = match[4] || match[5] || \"\"; // Strip excess characters from unquoted arguments\n", " } else if (unquoted && rpseudo.test(unquoted) && ( // Get excess from tokenize (recursively)\n", " excess = tokenize(unquoted, true)) && ( // advance to the next closing parenthesis\n", " excess = unquoted.indexOf(\")\", unquoted.length - excess) - unquoted.length)) {\n", " // excess is a negative index\n", " match[0] = match[0].slice(0, excess);\n", " match[2] = unquoted.slice(0, excess);\n", " } // Return only captures needed by the pseudo filter method (type and argument)\n", "\n", "\n", " return match.slice(0, 3);\n", " }\n", " },\n", " filter: {\n", " \"TAG\": function (nodeNameSelector) {\n", " var nodeName = nodeNameSelector.replace(runescape, funescape).toLowerCase();\n", " return nodeNameSelector === \"*\" ? function () {\n", " return true;\n", " } : function (elem) {\n", " return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;\n", " };\n", " },\n", " \"CLASS\": function (className) {\n", " var pattern = classCache[className + \" \"];\n", " return pattern || (pattern = new RegExp(\"(^|\" + whitespace + \")\" + className + \"(\" + whitespace + \"|$)\")) && classCache(className, function (elem) {\n", " return pattern.test(typeof elem.className === \"string\" && elem.className || typeof elem.getAttribute !== \"undefined\" && elem.getAttribute(\"class\") || \"\");\n", " });\n", " },\n", " \"ATTR\": function (name, operator, check) {\n", " return function (elem) {\n", " var result = Sizzle.attr(elem, name);\n", "\n", " if (result == null) {\n", " return operator === \"!=\";\n", " }\n", "\n", " if (!operator) {\n", " return true;\n", " }\n", "\n", " result += \"\";\n", " 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;\n", " };\n", " },\n", " \"CHILD\": function (type, what, argument, first, last) {\n", " var simple = type.slice(0, 3) !== \"nth\",\n", " forward = type.slice(-4) !== \"last\",\n", " ofType = what === \"of-type\";\n", " return first === 1 && last === 0 ? // Shortcut for :nth-*(n)\n", " function (elem) {\n", " return !!elem.parentNode;\n", " } : function (elem, context, xml) {\n", " var cache,\n", " uniqueCache,\n", " outerCache,\n", " node,\n", " nodeIndex,\n", " start,\n", " dir = simple !== forward ? \"nextSibling\" : \"previousSibling\",\n", " parent = elem.parentNode,\n", " name = ofType && elem.nodeName.toLowerCase(),\n", " useCache = !xml && !ofType,\n", " diff = false;\n", "\n", " if (parent) {\n", " // :(first|last|only)-(child|of-type)\n", " if (simple) {\n", " while (dir) {\n", " node = elem;\n", "\n", " while (node = node[dir]) {\n", " if (ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1) {\n", " return false;\n", " }\n", " } // Reverse direction for :only-* (if we haven't yet done so)\n", "\n", "\n", " start = dir = type === \"only\" && !start && \"nextSibling\";\n", " }\n", "\n", " return true;\n", " }\n", "\n", " start = [forward ? parent.firstChild : parent.lastChild]; // non-xml :nth-child(...) stores cache data on `parent`\n", "\n", " if (forward && useCache) {\n", " // Seek `elem` from a previously-cached index\n", " // ...in a gzip-friendly way\n", " node = parent;\n", " outerCache = node[expando] || (node[expando] = {}); // Support: IE <9 only\n", " // Defend against cloned attroperties (jQuery gh-1709)\n", "\n", " uniqueCache = outerCache[node.uniqueID] || (outerCache[node.uniqueID] = {});\n", " cache = uniqueCache[type] || [];\n", " nodeIndex = cache[0] === dirruns && cache[1];\n", " diff = nodeIndex && cache[2];\n", " node = nodeIndex && parent.childNodes[nodeIndex];\n", "\n", " while (node = ++nodeIndex && node && node[dir] || ( // Fallback to seeking `elem` from the start\n", " diff = nodeIndex = 0) || start.pop()) {\n", " // When found, cache indexes on `parent` and break\n", " if (node.nodeType === 1 && ++diff && node === elem) {\n", " uniqueCache[type] = [dirruns, nodeIndex, diff];\n", " break;\n", " }\n", " }\n", " } else {\n", " // Use previously-cached element index if available\n", " if (useCache) {\n", " // ...in a gzip-friendly way\n", " node = elem;\n", " outerCache = node[expando] || (node[expando] = {}); // Support: IE <9 only\n", " // Defend against cloned attroperties (jQuery gh-1709)\n", "\n", " uniqueCache = outerCache[node.uniqueID] || (outerCache[node.uniqueID] = {});\n", " cache = uniqueCache[type] || [];\n", " nodeIndex = cache[0] === dirruns && cache[1];\n", " diff = nodeIndex;\n", " } // xml :nth-child(...)\n", " // or :nth-last-child(...) or :nth(-last)?-of-type(...)\n", "\n", "\n", " if (diff === false) {\n", " // Use the same loop as above to seek `elem` from the start\n", " while (node = ++nodeIndex && node && node[dir] || (diff = nodeIndex = 0) || start.pop()) {\n", " if ((ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1) && ++diff) {\n", " // Cache the index of each encountered element\n", " if (useCache) {\n", " outerCache = node[expando] || (node[expando] = {}); // Support: IE <9 only\n", " // Defend against cloned attroperties (jQuery gh-1709)\n", "\n", " uniqueCache = outerCache[node.uniqueID] || (outerCache[node.uniqueID] = {});\n", " uniqueCache[type] = [dirruns, diff];\n", " }\n", "\n", " if (node === elem) {\n", " break;\n", " }\n", " }\n", " }\n", " }\n", " } // Incorporate the offset, then check against cycle size\n", "\n", "\n", " diff -= last;\n", " return diff === first || diff % first === 0 && diff / first >= 0;\n", " }\n", " };\n", " },\n", " \"PSEUDO\": function (pseudo, argument) {\n", " // pseudo-class names are case-insensitive\n", " // http://www.w3.org/TR/selectors/#pseudo-classes\n", " // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters\n", " // Remember that setFilters inherits from pseudos\n", " var args,\n", " fn = Expr.pseudos[pseudo] || Expr.setFilters[pseudo.toLowerCase()] || Sizzle.error(\"unsupported pseudo: \" + pseudo); // The user may use createPseudo to indicate that\n", " // arguments are needed to create the filter function\n", " // just as Sizzle does\n", "\n", " if (fn[expando]) {\n", " return fn(argument);\n", " } // But maintain support for old signatures\n", "\n", "\n", " if (fn.length > 1) {\n", " args = [pseudo, pseudo, \"\", argument];\n", " return Expr.setFilters.hasOwnProperty(pseudo.toLowerCase()) ? markFunction(function (seed, matches) {\n", " var idx,\n", " matched = fn(seed, argument),\n", " i = matched.length;\n", "\n", " while (i--) {\n", " idx = indexOf(seed, matched[i]);\n", " seed[idx] = !(matches[idx] = matched[i]);\n", " }\n", " }) : function (elem) {\n", " return fn(elem, 0, args);\n", " };\n", " }\n", "\n", " return fn;\n", " }\n", " },\n", " pseudos: {\n", " // Potentially complex pseudos\n", " \"not\": markFunction(function (selector) {\n", " // Trim the selector passed to compile\n", " // to avoid treating leading and trailing\n", " // spaces as combinators\n", " var input = [],\n", " results = [],\n", " matcher = compile(selector.replace(rtrim, \"$1\"));\n", " return matcher[expando] ? markFunction(function (seed, matches, context, xml) {\n", " var elem,\n", " unmatched = matcher(seed, null, xml, []),\n", " i = seed.length; // Match elements unmatched by `matcher`\n", "\n", " while (i--) {\n", " if (elem = unmatched[i]) {\n", " seed[i] = !(matches[i] = elem);\n", " }\n", " }\n", " }) : function (elem, context, xml) {\n", " input[0] = elem;\n", " matcher(input, null, xml, results); // Don't keep the element (issue #299)\n", "\n", " input[0] = null;\n", " return !results.pop();\n", " };\n", " }),\n", " \"has\": markFunction(function (selector) {\n", " return function (elem) {\n", " return Sizzle(selector, elem).length > 0;\n", " };\n", " }),\n", " \"contains\": markFunction(function (text) {\n", " text = text.replace(runescape, funescape);\n", " return function (elem) {\n", " return (elem.textContent || elem.innerText || getText(elem)).indexOf(text) > -1;\n", " };\n", " }),\n", " // \"Whether an element is represented by a :lang() selector\n", " // is based solely on the element's language value\n", " // being equal to the identifier C,\n", " // or beginning with the identifier C immediately followed by \"-\".\n", " // The matching of C against the element's language value is performed case-insensitively.\n", " // The identifier C does not have to be a valid language name.\"\n", " // http://www.w3.org/TR/selectors/#lang-pseudo\n", " \"lang\": markFunction(function (lang) {\n", " // lang value must be a valid identifier\n", " if (!ridentifier.test(lang || \"\")) {\n", " Sizzle.error(\"unsupported lang: \" + lang);\n", " }\n", "\n", " lang = lang.replace(runescape, funescape).toLowerCase();\n", " return function (elem) {\n", " var elemLang;\n", "\n", " do {\n", " if (elemLang = documentIsHTML ? elem.lang : elem.getAttribute(\"xml:lang\") || elem.getAttribute(\"lang\")) {\n", " elemLang = elemLang.toLowerCase();\n", " return elemLang === lang || elemLang.indexOf(lang + \"-\") === 0;\n", " }\n", " } while ((elem = elem.parentNode) && elem.nodeType === 1);\n", "\n", " return false;\n", " };\n", " }),\n", " // Miscellaneous\n", " \"target\": function (elem) {\n", " var hash = window.location && window.location.hash;\n", " return hash && hash.slice(1) === elem.id;\n", " },\n", " \"root\": function (elem) {\n", " return elem === docElem;\n", " },\n", " \"focus\": function (elem) {\n", " return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);\n", " },\n", " // Boolean properties\n", " \"enabled\": createDisabledPseudo(false),\n", " \"disabled\": createDisabledPseudo(true),\n", " \"checked\": function (elem) {\n", " // In CSS3, :checked should return both checked and selected elements\n", " // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked\n", " var nodeName = elem.nodeName.toLowerCase();\n", " return nodeName === \"input\" && !!elem.checked || nodeName === \"option\" && !!elem.selected;\n", " },\n", " \"selected\": function (elem) {\n", " // Accessing this property makes selected-by-default\n", " // options in Safari work properly\n", " if (elem.parentNode) {\n", " elem.parentNode.selectedIndex;\n", " }\n", "\n", " return elem.selected === true;\n", " },\n", " // Contents\n", " \"empty\": function (elem) {\n", " // http://www.w3.org/TR/selectors/#empty-pseudo\n", " // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),\n", " // but not by others (comment: 8; processing instruction: 7; etc.)\n", " // nodeType < 6 works because attributes (2) do not appear as children\n", " for (elem = elem.firstChild; elem; elem = elem.nextSibling) {\n", " if (elem.nodeType < 6) {\n", " return false;\n", " }\n", " }\n", "\n", " return true;\n", " },\n", " \"parent\": function (elem) {\n", " return !Expr.pseudos[\"empty\"](elem);\n", " },\n", " // Element/input types\n", " \"header\": function (elem) {\n", " return rheader.test(elem.nodeName);\n", " },\n", " \"input\": function (elem) {\n", " return rinputs.test(elem.nodeName);\n", " },\n", " \"button\": function (elem) {\n", " var name = elem.nodeName.toLowerCase();\n", " return name === \"input\" && elem.type === \"button\" || name === \"button\";\n", " },\n", " \"text\": function (elem) {\n", " var attr;\n", " return elem.nodeName.toLowerCase() === \"input\" && elem.type === \"text\" && ( // Support: IE<8\n", " // New HTML5 attribute values (e.g., \"search\") appear with elem.type === \"text\"\n", " (attr = elem.getAttribute(\"type\")) == null || attr.toLowerCase() === \"text\");\n", " },\n", " // Position-in-collection\n", " \"first\": createPositionalPseudo(function () {\n", " return [0];\n", " }),\n", " \"last\": createPositionalPseudo(function (matchIndexes, length) {\n", " return [length - 1];\n", " }),\n", " \"eq\": createPositionalPseudo(function (matchIndexes, length, argument) {\n", " return [argument < 0 ? argument + length : argument];\n", " }),\n", " \"even\": createPositionalPseudo(function (matchIndexes, length) {\n", " var i = 0;\n", "\n", " for (; i < length; i += 2) {\n", " matchIndexes.push(i);\n", " }\n", "\n", " return matchIndexes;\n", " }),\n", " \"odd\": createPositionalPseudo(function (matchIndexes, length) {\n", " var i = 1;\n", "\n", " for (; i < length; i += 2) {\n", " matchIndexes.push(i);\n", " }\n", "\n", " return matchIndexes;\n", " }),\n", " \"lt\": createPositionalPseudo(function (matchIndexes, length, argument) {\n", " var i = argument < 0 ? argument + length : argument;\n", "\n", " for (; --i >= 0;) {\n", " matchIndexes.push(i);\n", " }\n", "\n", " return matchIndexes;\n", " }),\n", " \"gt\": createPositionalPseudo(function (matchIndexes, length, argument) {\n", " var i = argument < 0 ? argument + length : argument;\n", "\n", " for (; ++i < length;) {\n", " matchIndexes.push(i);\n", " }\n", "\n", " return matchIndexes;\n", " })\n", " }\n", " };\n", " Expr.pseudos[\"nth\"] = Expr.pseudos[\"eq\"]; // Add button/input type pseudos\n", "\n", " for (i in {\n", " radio: true,\n", " checkbox: true,\n", " file: true,\n", " password: true,\n", " image: true\n", " }) {\n", " Expr.pseudos[i] = createInputPseudo(i);\n", " }\n", "\n", " for (i in {\n", " submit: true,\n", " reset: true\n", " }) {\n", " Expr.pseudos[i] = createButtonPseudo(i);\n", " } // Easy API for creating new setFilters\n", "\n", "\n", " function setFilters() {}\n", "\n", " setFilters.prototype = Expr.filters = Expr.pseudos;\n", " Expr.setFilters = new setFilters();\n", "\n", " tokenize = Sizzle.tokenize = function (selector, parseOnly) {\n", " var matched,\n", " match,\n", " tokens,\n", " type,\n", " soFar,\n", " groups,\n", " preFilters,\n", " cached = tokenCache[selector + \" \"];\n", "\n", " if (cached) {\n", " return parseOnly ? 0 : cached.slice(0);\n", " }\n", "\n", " soFar = selector;\n", " groups = [];\n", " preFilters = Expr.preFilter;\n", "\n", " while (soFar) {\n", " // Comma and first run\n", " if (!matched || (match = rcomma.exec(soFar))) {\n", " if (match) {\n", " // Don't consume trailing commas as valid\n", " soFar = soFar.slice(match[0].length) || soFar;\n", " }\n", "\n", " groups.push(tokens = []);\n", " }\n", "\n", " matched = false; // Combinators\n", "\n", " if (match = rcombinators.exec(soFar)) {\n", " matched = match.shift();\n", " tokens.push({\n", " value: matched,\n", " // Cast descendant combinators to space\n", " type: match[0].replace(rtrim, \" \")\n", " });\n", " soFar = soFar.slice(matched.length);\n", " } // Filters\n", "\n", "\n", " for (type in Expr.filter) {\n", " if ((match = matchExpr[type].exec(soFar)) && (!preFilters[type] || (match = preFilters[type](match)))) {\n", " matched = match.shift();\n", " tokens.push({\n", " value: matched,\n", " type: type,\n", " matches: match\n", " });\n", " soFar = soFar.slice(matched.length);\n", " }\n", " }\n", "\n", " if (!matched) {\n", " break;\n", " }\n", " } // Return the length of the invalid excess\n", " // if we're just parsing\n", " // Otherwise, throw an error or return tokens\n", "\n", "\n", " return parseOnly ? soFar.length : soFar ? Sizzle.error(selector) : // Cache the tokens\n", " tokenCache(selector, groups).slice(0);\n", " };\n", "\n", " function toSelector(tokens) {\n", " var i = 0,\n", " len = tokens.length,\n", " selector = \"\";\n", "\n", " for (; i < len; i++) {\n", " selector += tokens[i].value;\n", " }\n", "\n", " return selector;\n", " }\n", "\n", " function addCombinator(matcher, combinator, base) {\n", " var dir = combinator.dir,\n", " skip = combinator.next,\n", " key = skip || dir,\n", " checkNonElements = base && key === \"parentNode\",\n", " doneName = done++;\n", " return combinator.first ? // Check against closest ancestor/preceding element\n", " function (elem, context, xml) {\n", " while (elem = elem[dir]) {\n", " if (elem.nodeType === 1 || checkNonElements) {\n", " return matcher(elem, context, xml);\n", " }\n", " }\n", "\n", " return false;\n", " } : // Check against all ancestor/preceding elements\n", " function (elem, context, xml) {\n", " var oldCache,\n", " uniqueCache,\n", " outerCache,\n", " newCache = [dirruns, doneName]; // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching\n", "\n", " if (xml) {\n", " while (elem = elem[dir]) {\n", " if (elem.nodeType === 1 || checkNonElements) {\n", " if (matcher(elem, context, xml)) {\n", " return true;\n", " }\n", " }\n", " }\n", " } else {\n", " while (elem = elem[dir]) {\n", " if (elem.nodeType === 1 || checkNonElements) {\n", " outerCache = elem[expando] || (elem[expando] = {}); // Support: IE <9 only\n", " // Defend against cloned attroperties (jQuery gh-1709)\n", "\n", " uniqueCache = outerCache[elem.uniqueID] || (outerCache[elem.uniqueID] = {});\n", "\n", " if (skip && skip === elem.nodeName.toLowerCase()) {\n", " elem = elem[dir] || elem;\n", " } else if ((oldCache = uniqueCache[key]) && oldCache[0] === dirruns && oldCache[1] === doneName) {\n", " // Assign to newCache so results back-propagate to previous elements\n", " return newCache[2] = oldCache[2];\n", " } else {\n", " // Reuse newcache so results back-propagate to previous elements\n", " uniqueCache[key] = newCache; // A match means we're done; a fail means we have to keep checking\n", "\n", " if (newCache[2] = matcher(elem, context, xml)) {\n", " return true;\n", " }\n", " }\n", " }\n", " }\n", " }\n", "\n", " return false;\n", " };\n", " }\n", "\n", " function elementMatcher(matchers) {\n", " return matchers.length > 1 ? function (elem, context, xml) {\n", " var i = matchers.length;\n", "\n", " while (i--) {\n", " if (!matchers[i](elem, context, xml)) {\n", " return false;\n", " }\n", " }\n", "\n", " return true;\n", " } : matchers[0];\n", " }\n", "\n", " function multipleContexts(selector, contexts, results) {\n", " var i = 0,\n", " len = contexts.length;\n", "\n", " for (; i < len; i++) {\n", " Sizzle(selector, contexts[i], results);\n", " }\n", "\n", " return results;\n", " }\n", "\n", " function condense(unmatched, map, filter, context, xml) {\n", " var elem,\n", " newUnmatched = [],\n", " i = 0,\n", " len = unmatched.length,\n", " mapped = map != null;\n", "\n", " for (; i < len; i++) {\n", " if (elem = unmatched[i]) {\n", " if (!filter || filter(elem, context, xml)) {\n", " newUnmatched.push(elem);\n", "\n", " if (mapped) {\n", " map.push(i);\n", " }\n", " }\n", " }\n", " }\n", "\n", " return newUnmatched;\n", " }\n", "\n", " function setMatcher(preFilter, selector, matcher, postFilter, postFinder, postSelector) {\n", " if (postFilter && !postFilter[expando]) {\n", " postFilter = setMatcher(postFilter);\n", " }\n", "\n", " if (postFinder && !postFinder[expando]) {\n", " postFinder = setMatcher(postFinder, postSelector);\n", " }\n", "\n", " return markFunction(function (seed, results, context, xml) {\n", " var temp,\n", " i,\n", " elem,\n", " preMap = [],\n", " postMap = [],\n", " preexisting = results.length,\n", " // Get initial elements from seed or context\n", " elems = seed || multipleContexts(selector || \"*\", context.nodeType ? [context] : context, []),\n", " // Prefilter to get matcher input, preserving a map for seed-results synchronization\n", " matcherIn = preFilter && (seed || !selector) ? condense(elems, preMap, preFilter, context, xml) : elems,\n", " matcherOut = matcher ? // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,\n", " postFinder || (seed ? preFilter : preexisting || postFilter) ? // ...intermediate processing is necessary\n", " [] : // ...otherwise use results directly\n", " results : matcherIn; // Find primary matches\n", "\n", " if (matcher) {\n", " matcher(matcherIn, matcherOut, context, xml);\n", " } // Apply postFilter\n", "\n", "\n", " if (postFilter) {\n", " temp = condense(matcherOut, postMap);\n", " postFilter(temp, [], context, xml); // Un-match failing elements by moving them back to matcherIn\n", "\n", " i = temp.length;\n", "\n", " while (i--) {\n", " if (elem = temp[i]) {\n", " matcherOut[postMap[i]] = !(matcherIn[postMap[i]] = elem);\n", " }\n", " }\n", " }\n", "\n", " if (seed) {\n", " if (postFinder || preFilter) {\n", " if (postFinder) {\n", " // Get the final matcherOut by condensing this intermediate into postFinder contexts\n", " temp = [];\n", " i = matcherOut.length;\n", "\n", " while (i--) {\n", " if (elem = matcherOut[i]) {\n", " // Restore matcherIn since elem is not yet a final match\n", " temp.push(matcherIn[i] = elem);\n", " }\n", " }\n", "\n", " postFinder(null, matcherOut = [], temp, xml);\n", " } // Move matched elements from seed to results to keep them synchronized\n", "\n", "\n", " i = matcherOut.length;\n", "\n", " while (i--) {\n", " if ((elem = matcherOut[i]) && (temp = postFinder ? indexOf(seed, elem) : preMap[i]) > -1) {\n", " seed[temp] = !(results[temp] = elem);\n", " }\n", " }\n", " } // Add elements to results, through postFinder if defined\n", "\n", " } else {\n", " matcherOut = condense(matcherOut === results ? matcherOut.splice(preexisting, matcherOut.length) : matcherOut);\n", "\n", " if (postFinder) {\n", " postFinder(null, results, matcherOut, xml);\n", " } else {\n", " push.apply(results, matcherOut);\n", " }\n", " }\n", " });\n", " }\n", "\n", " function matcherFromTokens(tokens) {\n", " var checkContext,\n", " matcher,\n", " j,\n", " len = tokens.length,\n", " leadingRelative = Expr.relative[tokens[0].type],\n", " implicitRelative = leadingRelative || Expr.relative[\" \"],\n", " i = leadingRelative ? 1 : 0,\n", " // The foundational matcher ensures that elements are reachable from top-level context(s)\n", " matchContext = addCombinator(function (elem) {\n", " return elem === checkContext;\n", " }, implicitRelative, true),\n", " matchAnyContext = addCombinator(function (elem) {\n", " return indexOf(checkContext, elem) > -1;\n", " }, implicitRelative, true),\n", " matchers = [function (elem, context, xml) {\n", " var ret = !leadingRelative && (xml || context !== outermostContext) || ((checkContext = context).nodeType ? matchContext(elem, context, xml) : matchAnyContext(elem, context, xml)); // Avoid hanging onto element (issue #299)\n", "\n", " checkContext = null;\n", " return ret;\n", " }];\n", "\n", " for (; i < len; i++) {\n", " if (matcher = Expr.relative[tokens[i].type]) {\n", " matchers = [addCombinator(elementMatcher(matchers), matcher)];\n", " } else {\n", " matcher = Expr.filter[tokens[i].type].apply(null, tokens[i].matches); // Return special upon seeing a positional matcher\n", "\n", " if (matcher[expando]) {\n", " // Find the next relative operator (if any) for proper handling\n", " j = ++i;\n", "\n", " for (; j < len; j++) {\n", " if (Expr.relative[tokens[j].type]) {\n", " break;\n", " }\n", " }\n", "\n", " return setMatcher(i > 1 && elementMatcher(matchers), i > 1 && toSelector( // If the preceding token was a descendant combinator, insert an implicit any-element `*`\n", " tokens.slice(0, i - 1).concat({\n", " value: tokens[i - 2].type === \" \" ? \"*\" : \"\"\n", " })).replace(rtrim, \"$1\"), matcher, i < j && matcherFromTokens(tokens.slice(i, j)), j < len && matcherFromTokens(tokens = tokens.slice(j)), j < len && toSelector(tokens));\n", " }\n", "\n", " matchers.push(matcher);\n", " }\n", " }\n", "\n", " return elementMatcher(matchers);\n", " }\n", "\n", " function matcherFromGroupMatchers(elementMatchers, setMatchers) {\n", " var bySet = setMatchers.length > 0,\n", " byElement = elementMatchers.length > 0,\n", " superMatcher = function (seed, context, xml, results, outermost) {\n", " var elem,\n", " j,\n", " matcher,\n", " matchedCount = 0,\n", " i = \"0\",\n", " unmatched = seed && [],\n", " setMatched = [],\n", " contextBackup = outermostContext,\n", " // We must always have either seed elements or outermost context\n", " elems = seed || byElement && Expr.find[\"TAG\"](\"*\", outermost),\n", " // Use integer dirruns iff this is the outermost matcher\n", " dirrunsUnique = dirruns += contextBackup == null ? 1 : Math.random() || 0.1,\n", " len = elems.length;\n", "\n", " if (outermost) {\n", " outermostContext = context === document || context || outermost;\n", " } // Add elements passing elementMatchers directly to results\n", " // Support: IE<9, Safari\n", " // Tolerate NodeList properties (IE: \"length\"; Safari: ) matching elements by id\n", "\n", "\n", " for (; i !== len && (elem = elems[i]) != null; i++) {\n", " if (byElement && elem) {\n", " j = 0;\n", "\n", " if (!context && elem.ownerDocument !== document) {\n", " setDocument(elem);\n", " xml = !documentIsHTML;\n", " }\n", "\n", " while (matcher = elementMatchers[j++]) {\n", " if (matcher(elem, context || document, xml)) {\n", " results.push(elem);\n", " break;\n", " }\n", " }\n", "\n", " if (outermost) {\n", " dirruns = dirrunsUnique;\n", " }\n", " } // Track unmatched elements for set filters\n", "\n", "\n", " if (bySet) {\n", " // They will have gone through all possible matchers\n", " if (elem = !matcher && elem) {\n", " matchedCount--;\n", " } // Lengthen the array for every element, matched or not\n", "\n", "\n", " if (seed) {\n", " unmatched.push(elem);\n", " }\n", " }\n", " } // `i` is now the count of elements visited above, and adding it to `matchedCount`\n", " // makes the latter nonnegative.\n", "\n", "\n", " matchedCount += i; // Apply set filters to unmatched elements\n", " // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount`\n", " // equals `i`), unless we didn't visit _any_ elements in the above loop because we have\n", " // no element matchers and no seed.\n", " // Incrementing an initially-string \"0\" `i` allows `i` to remain a string only in that\n", " // case, which will result in a \"00\" `matchedCount` that differs from `i` but is also\n", " // numerically zero.\n", "\n", " if (bySet && i !== matchedCount) {\n", " j = 0;\n", "\n", " while (matcher = setMatchers[j++]) {\n", " matcher(unmatched, setMatched, context, xml);\n", " }\n", "\n", " if (seed) {\n", " // Reintegrate element matches to eliminate the need for sorting\n", " if (matchedCount > 0) {\n", " while (i--) {\n", " if (!(unmatched[i] || setMatched[i])) {\n", " setMatched[i] = pop.call(results);\n", " }\n", " }\n", " } // Discard index placeholder values to get only actual matches\n", "\n", "\n", " setMatched = condense(setMatched);\n", " } // Add matches to results\n", "\n", "\n", " push.apply(results, setMatched); // Seedless set matches succeeding multiple successful matchers stipulate sorting\n", "\n", " if (outermost && !seed && setMatched.length > 0 && matchedCount + setMatchers.length > 1) {\n", " Sizzle.uniqueSort(results);\n", " }\n", " } // Override manipulation of globals by nested matchers\n", "\n", "\n", " if (outermost) {\n", " dirruns = dirrunsUnique;\n", " outermostContext = contextBackup;\n", " }\n", "\n", " return unmatched;\n", " };\n", "\n", " return bySet ? markFunction(superMatcher) : superMatcher;\n", " }\n", "\n", " compile = Sizzle.compile = function (selector, match\n", " /* Internal Use Only */\n", " ) {\n", " var i,\n", " setMatchers = [],\n", " elementMatchers = [],\n", " cached = compilerCache[selector + \" \"];\n", "\n", " if (!cached) {\n", " // Generate a function of recursive functions that can be used to check each element\n", " if (!match) {\n", " match = tokenize(selector);\n", " }\n", "\n", " i = match.length;\n", "\n", " while (i--) {\n", " cached = matcherFromTokens(match[i]);\n", "\n", " if (cached[expando]) {\n", " setMatchers.push(cached);\n", " } else {\n", " elementMatchers.push(cached);\n", " }\n", " } // Cache the compiled function\n", "\n", "\n", " cached = compilerCache(selector, matcherFromGroupMatchers(elementMatchers, setMatchers)); // Save selector and tokenization\n", "\n", " cached.selector = selector;\n", " }\n", "\n", " return cached;\n", " };\n", " /**\n", " * A low-level selection function that works with Sizzle's compiled\n", " * selector functions\n", " * @param {String|Function} selector A selector or a pre-compiled\n", " * selector function built with Sizzle.compile\n", " * @param {Element} context\n", " * @param {Array} [results]\n", " * @param {Array} [seed] A set of elements to match against\n", " */\n", "\n", "\n", " select = Sizzle.select = function (selector, context, results, seed) {\n", " var i,\n", " tokens,\n", " token,\n", " type,\n", " find,\n", " compiled = typeof selector === \"function\" && selector,\n", " match = !seed && tokenize(selector = compiled.selector || selector);\n", " results = results || []; // Try to minimize operations if there is only one selector in the list and no seed\n", " // (the latter of which guarantees us context)\n", "\n", " if (match.length === 1) {\n", " // Reduce context if the leading compound selector is an ID\n", " tokens = match[0] = match[0].slice(0);\n", "\n", " if (tokens.length > 2 && (token = tokens[0]).type === \"ID\" && context.nodeType === 9 && documentIsHTML && Expr.relative[tokens[1].type]) {\n", " context = (Expr.find[\"ID\"](token.matches[0].replace(runescape, funescape), context) || [])[0];\n", "\n", " if (!context) {\n", " return results; // Precompiled matchers will still verify ancestry, so step up a level\n", " } else if (compiled) {\n", " context = context.parentNode;\n", " }\n", "\n", " selector = selector.slice(tokens.shift().value.length);\n", " } // Fetch a seed set for right-to-left matching\n", "\n", "\n", " i = matchExpr[\"needsContext\"].test(selector) ? 0 : tokens.length;\n", "\n", " while (i--) {\n", " token = tokens[i]; // Abort if we hit a combinator\n", "\n", " if (Expr.relative[type = token.type]) {\n", " break;\n", " }\n", "\n", " if (find = Expr.find[type]) {\n", " // Search, expanding context for leading sibling combinators\n", " if (seed = find(token.matches[0].replace(runescape, funescape), rsibling.test(tokens[0].type) && testContext(context.parentNode) || context)) {\n", " // If seed is empty or no tokens remain, we can return early\n", " tokens.splice(i, 1);\n", " selector = seed.length && toSelector(tokens);\n", "\n", " if (!selector) {\n", " push.apply(results, seed);\n", " return results;\n", " }\n", "\n", " break;\n", " }\n", " }\n", " }\n", " } // Compile and execute a filtering function if one is not provided\n", " // Provide `match` to avoid retokenization if we modified the selector above\n", "\n", "\n", " (compiled || compile(selector, match))(seed, context, !documentIsHTML, results, !context || rsibling.test(selector) && testContext(context.parentNode) || context);\n", " return results;\n", " }; // One-time assignments\n", " // Sort stability\n", "\n", "\n", " support.sortStable = expando.split(\"\").sort(sortOrder).join(\"\") === expando; // Support: Chrome 14-35+\n", " // Always assume duplicates if they aren't passed to the comparison function\n", "\n", " support.detectDuplicates = !!hasDuplicate; // Initialize against the default document\n", "\n", " setDocument(); // Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)\n", " // Detached nodes confoundingly follow *each other*\n", "\n", " support.sortDetached = assert(function (el) {\n", " // Should return 1, but returns 4 (following)\n", " return el.compareDocumentPosition(document.createElement(\"fieldset\")) & 1;\n", " }); // Support: IE<8\n", " // Prevent attribute/property \"interpolation\"\n", " // https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx\n", "\n", " if (!assert(function (el) {\n", " el.innerHTML = \"\";\n", " return el.firstChild.getAttribute(\"href\") === \"#\";\n", " })) {\n", " addHandle(\"type|href|height|width\", function (elem, name, isXML) {\n", " if (!isXML) {\n", " return elem.getAttribute(name, name.toLowerCase() === \"type\" ? 1 : 2);\n", " }\n", " });\n", " } // Support: IE<9\n", " // Use defaultValue in place of getAttribute(\"value\")\n", "\n", "\n", " if (!support.attributes || !assert(function (el) {\n", " el.innerHTML = \"\";\n", " el.firstChild.setAttribute(\"value\", \"\");\n", " return el.firstChild.getAttribute(\"value\") === \"\";\n", " })) {\n", " addHandle(\"value\", function (elem, name, isXML) {\n", " if (!isXML && elem.nodeName.toLowerCase() === \"input\") {\n", " return elem.defaultValue;\n", " }\n", " });\n", " } // Support: IE<9\n", " // Use getAttributeNode to fetch booleans when getAttribute lies\n", "\n", "\n", " if (!assert(function (el) {\n", " return el.getAttribute(\"disabled\") == null;\n", " })) {\n", " addHandle(booleans, function (elem, name, isXML) {\n", " var val;\n", "\n", " if (!isXML) {\n", " return elem[name] === true ? name.toLowerCase() : (val = elem.getAttributeNode(name)) && val.specified ? val.value : null;\n", " }\n", " });\n", " }\n", "\n", " return Sizzle;\n", " }(window);\n", "\n", " jQuery.find = Sizzle;\n", " jQuery.expr = Sizzle.selectors; // Deprecated\n", "\n", " jQuery.expr[\":\"] = jQuery.expr.pseudos;\n", " jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort;\n", " jQuery.text = Sizzle.getText;\n", " jQuery.isXMLDoc = Sizzle.isXML;\n", " jQuery.contains = Sizzle.contains;\n", " jQuery.escapeSelector = Sizzle.escape;\n", "\n", " var dir = function (elem, dir, until) {\n", " var matched = [],\n", " truncate = until !== undefined;\n", "\n", " while ((elem = elem[dir]) && elem.nodeType !== 9) {\n", " if (elem.nodeType === 1) {\n", " if (truncate && jQuery(elem).is(until)) {\n", " break;\n", " }\n", "\n", " matched.push(elem);\n", " }\n", " }\n", "\n", " return matched;\n", " };\n", "\n", " var siblings = function (n, elem) {\n", " var matched = [];\n", "\n", " for (; n; n = n.nextSibling) {\n", " if (n.nodeType === 1 && n !== elem) {\n", " matched.push(n);\n", " }\n", " }\n", "\n", " return matched;\n", " };\n", "\n", " var rneedsContext = jQuery.expr.match.needsContext;\n", "\n", " function nodeName(elem, name) {\n", " return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();\n", " }\n", "\n", " 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\n", "\n", " function winnow(elements, qualifier, not) {\n", " if (isFunction(qualifier)) {\n", " return jQuery.grep(elements, function (elem, i) {\n", " return !!qualifier.call(elem, i, elem) !== not;\n", " });\n", " } // Single element\n", "\n", "\n", " if (qualifier.nodeType) {\n", " return jQuery.grep(elements, function (elem) {\n", " return elem === qualifier !== not;\n", " });\n", " } // Arraylike of elements (jQuery, arguments, Array)\n", "\n", "\n", " if (typeof qualifier !== \"string\") {\n", " return jQuery.grep(elements, function (elem) {\n", " return indexOf.call(qualifier, elem) > -1 !== not;\n", " });\n", " } // Filtered directly for both simple and complex selectors\n", "\n", "\n", " return jQuery.filter(qualifier, elements, not);\n", " }\n", "\n", " jQuery.filter = function (expr, elems, not) {\n", " var elem = elems[0];\n", "\n", " if (not) {\n", " expr = \":not(\" + expr + \")\";\n", " }\n", "\n", " if (elems.length === 1 && elem.nodeType === 1) {\n", " return jQuery.find.matchesSelector(elem, expr) ? [elem] : [];\n", " }\n", "\n", " return jQuery.find.matches(expr, jQuery.grep(elems, function (elem) {\n", " return elem.nodeType === 1;\n", " }));\n", " };\n", "\n", " jQuery.fn.extend({\n", " find: function (selector) {\n", " var i,\n", " ret,\n", " len = this.length,\n", " self = this;\n", "\n", " if (typeof selector !== \"string\") {\n", " return this.pushStack(jQuery(selector).filter(function () {\n", " for (i = 0; i < len; i++) {\n", " if (jQuery.contains(self[i], this)) {\n", " return true;\n", " }\n", " }\n", " }));\n", " }\n", "\n", " ret = this.pushStack([]);\n", "\n", " for (i = 0; i < len; i++) {\n", " jQuery.find(selector, self[i], ret);\n", " }\n", "\n", " return len > 1 ? jQuery.uniqueSort(ret) : ret;\n", " },\n", " filter: function (selector) {\n", " return this.pushStack(winnow(this, selector || [], false));\n", " },\n", " not: function (selector) {\n", " return this.pushStack(winnow(this, selector || [], true));\n", " },\n", " is: function (selector) {\n", " return !!winnow(this, // If this is a positional/relative selector, check membership in the returned set\n", " // so $(\"p:first\").is(\"p:last\") won't return true for a doc with two \"p\".\n", " typeof selector === \"string\" && rneedsContext.test(selector) ? jQuery(selector) : selector || [], false).length;\n", " }\n", " }); // Initialize a jQuery object\n", " // A central reference to the root jQuery(document)\n", "\n", " var rootjQuery,\n", " // A simple way to check for HTML strings\n", " // Prioritize #id over to avoid XSS via location.hash (#9521)\n", " // Strict HTML recognition (#11290: must start with <)\n", " // Shortcut simple #id case for speed\n", " rquickExpr = /^(?:\\s*(<[\\w\\W]+>)[^>]*|#([\\w-]+))$/,\n", " init$1 = jQuery.fn.init = function (selector, context, root) {\n", " var match, elem; // HANDLE: $(\"\"), $(null), $(undefined), $(false)\n", "\n", " if (!selector) {\n", " return this;\n", " } // Method init() accepts an alternate rootjQuery\n", " // so migrate can support jQuery.sub (gh-2101)\n", "\n", "\n", " root = root || rootjQuery; // Handle HTML strings\n", "\n", " if (typeof selector === \"string\") {\n", " if (selector[0] === \"<\" && selector[selector.length - 1] === \">\" && selector.length >= 3) {\n", " // Assume that strings that start and end with <> are HTML and skip the regex check\n", " match = [null, selector, null];\n", " } else {\n", " match = rquickExpr.exec(selector);\n", " } // Match html or make sure no context is specified for #id\n", "\n", "\n", " if (match && (match[1] || !context)) {\n", " // HANDLE: $(html) -> $(array)\n", " if (match[1]) {\n", " context = context instanceof jQuery ? context[0] : context; // Option to run scripts is true for back-compat\n", " // Intentionally let the error be thrown if parseHTML is not present\n", "\n", " jQuery.merge(this, jQuery.parseHTML(match[1], context && context.nodeType ? context.ownerDocument || context : document$2, true)); // HANDLE: $(html, props)\n", "\n", " if (rsingleTag.test(match[1]) && jQuery.isPlainObject(context)) {\n", " for (match in context) {\n", " // Properties of context are called as methods if possible\n", " if (isFunction(this[match])) {\n", " this[match](context[match]); // ...and otherwise set as attributes\n", " } else {\n", " this.attr(match, context[match]);\n", " }\n", " }\n", " }\n", "\n", " return this; // HANDLE: $(#id)\n", " } else {\n", " elem = document$2.getElementById(match[2]);\n", "\n", " if (elem) {\n", " // Inject the element directly into the jQuery object\n", " this[0] = elem;\n", " this.length = 1;\n", " }\n", "\n", " return this;\n", " } // HANDLE: $(expr, $(...))\n", "\n", " } else if (!context || context.jquery) {\n", " return (context || root).find(selector); // HANDLE: $(expr, context)\n", " // (which is just equivalent to: $(context).find(expr)\n", " } else {\n", " return this.constructor(context).find(selector);\n", " } // HANDLE: $(DOMElement)\n", "\n", " } else if (selector.nodeType) {\n", " this[0] = selector;\n", " this.length = 1;\n", " return this; // HANDLE: $(function)\n", " // Shortcut for document ready\n", " } else if (isFunction(selector)) {\n", " return root.ready !== undefined ? root.ready(selector) : // Execute immediately if ready is not present\n", " selector(jQuery);\n", " }\n", "\n", " return jQuery.makeArray(selector, this);\n", " }; // Give the init function the jQuery prototype for later instantiation\n", "\n", "\n", " init$1.prototype = jQuery.fn; // Initialize central reference\n", "\n", " rootjQuery = jQuery(document$2);\n", " var rparentsprev = /^(?:parents|prev(?:Until|All))/,\n", " // Methods guaranteed to produce a unique set when starting from a unique set\n", " guaranteedUnique = {\n", " children: true,\n", " contents: true,\n", " next: true,\n", " prev: true\n", " };\n", " jQuery.fn.extend({\n", " has: function (target) {\n", " var targets = jQuery(target, this),\n", " l = targets.length;\n", " return this.filter(function () {\n", " var i = 0;\n", "\n", " for (; i < l; i++) {\n", " if (jQuery.contains(this, targets[i])) {\n", " return true;\n", " }\n", " }\n", " });\n", " },\n", " closest: function (selectors, context) {\n", " var cur,\n", " i = 0,\n", " l = this.length,\n", " matched = [],\n", " targets = typeof selectors !== \"string\" && jQuery(selectors); // Positional selectors never match, since there's no _selection_ context\n", "\n", " if (!rneedsContext.test(selectors)) {\n", " for (; i < l; i++) {\n", " for (cur = this[i]; cur && cur !== context; cur = cur.parentNode) {\n", " // Always skip document fragments\n", " if (cur.nodeType < 11 && (targets ? targets.index(cur) > -1 : // Don't pass non-elements to Sizzle\n", " cur.nodeType === 1 && jQuery.find.matchesSelector(cur, selectors))) {\n", " matched.push(cur);\n", " break;\n", " }\n", " }\n", " }\n", " }\n", "\n", " return this.pushStack(matched.length > 1 ? jQuery.uniqueSort(matched) : matched);\n", " },\n", " // Determine the position of an element within the set\n", " index: function (elem) {\n", " // No argument, return index in parent\n", " if (!elem) {\n", " return this[0] && this[0].parentNode ? this.first().prevAll().length : -1;\n", " } // Index in selector\n", "\n", "\n", " if (typeof elem === \"string\") {\n", " return indexOf.call(jQuery(elem), this[0]);\n", " } // Locate the position of the desired element\n", "\n", "\n", " return indexOf.call(this, // If it receives a jQuery object, the first element is used\n", " elem.jquery ? elem[0] : elem);\n", " },\n", " add: function (selector, context) {\n", " return this.pushStack(jQuery.uniqueSort(jQuery.merge(this.get(), jQuery(selector, context))));\n", " },\n", " addBack: function (selector) {\n", " return this.add(selector == null ? this.prevObject : this.prevObject.filter(selector));\n", " }\n", " });\n", "\n", " function sibling(cur, dir) {\n", " while ((cur = cur[dir]) && cur.nodeType !== 1) {}\n", "\n", " return cur;\n", " }\n", "\n", " jQuery.each({\n", " parent: function (elem) {\n", " var parent = elem.parentNode;\n", " return parent && parent.nodeType !== 11 ? parent : null;\n", " },\n", " parents: function (elem) {\n", " return dir(elem, \"parentNode\");\n", " },\n", " parentsUntil: function (elem, i, until) {\n", " return dir(elem, \"parentNode\", until);\n", " },\n", " next: function (elem) {\n", " return sibling(elem, \"nextSibling\");\n", " },\n", " prev: function (elem) {\n", " return sibling(elem, \"previousSibling\");\n", " },\n", " nextAll: function (elem) {\n", " return dir(elem, \"nextSibling\");\n", " },\n", " prevAll: function (elem) {\n", " return dir(elem, \"previousSibling\");\n", " },\n", " nextUntil: function (elem, i, until) {\n", " return dir(elem, \"nextSibling\", until);\n", " },\n", " prevUntil: function (elem, i, until) {\n", " return dir(elem, \"previousSibling\", until);\n", " },\n", " siblings: function (elem) {\n", " return siblings((elem.parentNode || {}).firstChild, elem);\n", " },\n", " children: function (elem) {\n", " return siblings(elem.firstChild);\n", " },\n", " contents: function (elem) {\n", " if (nodeName(elem, \"iframe\")) {\n", " return elem.contentDocument;\n", " } // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only\n", " // Treat the template element as a regular one in browsers that\n", " // don't support it.\n", "\n", "\n", " if (nodeName(elem, \"template\")) {\n", " elem = elem.content || elem;\n", " }\n", "\n", " return jQuery.merge([], elem.childNodes);\n", " }\n", " }, function (name, fn) {\n", " jQuery.fn[name] = function (until, selector) {\n", " var matched = jQuery.map(this, fn, until);\n", "\n", " if (name.slice(-5) !== \"Until\") {\n", " selector = until;\n", " }\n", "\n", " if (selector && typeof selector === \"string\") {\n", " matched = jQuery.filter(selector, matched);\n", " }\n", "\n", " if (this.length > 1) {\n", " // Remove duplicates\n", " if (!guaranteedUnique[name]) {\n", " jQuery.uniqueSort(matched);\n", " } // Reverse order for parents* and prev-derivatives\n", "\n", "\n", " if (rparentsprev.test(name)) {\n", " matched.reverse();\n", " }\n", " }\n", "\n", " return this.pushStack(matched);\n", " };\n", " });\n", " var rnothtmlwhite = /[^\\x20\\t\\r\\n\\f]+/g; // Convert String-formatted options into Object-formatted ones\n", "\n", " function createOptions(options) {\n", " var object = {};\n", " jQuery.each(options.match(rnothtmlwhite) || [], function (_, flag) {\n", " object[flag] = true;\n", " });\n", " return object;\n", " }\n", " /*\n", " * Create a callback list using the following parameters:\n", " *\n", " *\toptions: an optional list of space-separated options that will change how\n", " *\t\t\tthe callback list behaves or a more traditional option object\n", " *\n", " * By default a callback list will act like an event callback list and can be\n", " * \"fired\" multiple times.\n", " *\n", " * Possible options:\n", " *\n", " *\tonce:\t\t\twill ensure the callback list can only be fired once (like a Deferred)\n", " *\n", " *\tmemory:\t\t\twill keep track of previous values and will call any callback added\n", " *\t\t\t\t\tafter the list has been fired right away with the latest \"memorized\"\n", " *\t\t\t\t\tvalues (like a Deferred)\n", " *\n", " *\tunique:\t\t\twill ensure a callback can only be added once (no duplicate in the list)\n", " *\n", " *\tstopOnFalse:\tinterrupt callings when a callback returns false\n", " *\n", " */\n", "\n", "\n", " jQuery.Callbacks = function (options) {\n", " // Convert options from String-formatted to Object-formatted if needed\n", " // (we check in cache first)\n", " options = typeof options === \"string\" ? createOptions(options) : jQuery.extend({}, options);\n", "\n", " var // Flag to know if list is currently firing\n", " firing,\n", " // Last fire value for non-forgettable lists\n", " memory,\n", " // Flag to know if list was already fired\n", " fired,\n", " // Flag to prevent firing\n", " locked,\n", " // Actual callback list\n", " list = [],\n", " // Queue of execution data for repeatable lists\n", " queue = [],\n", " // Index of currently firing callback (modified by add/remove as needed)\n", " firingIndex = -1,\n", " // Fire callbacks\n", " fire = function () {\n", " // Enforce single-firing\n", " locked = locked || options.once; // Execute callbacks for all pending executions,\n", " // respecting firingIndex overrides and runtime changes\n", "\n", " fired = firing = true;\n", "\n", " for (; queue.length; firingIndex = -1) {\n", " memory = queue.shift();\n", "\n", " while (++firingIndex < list.length) {\n", " // Run callback and check for early termination\n", " if (list[firingIndex].apply(memory[0], memory[1]) === false && options.stopOnFalse) {\n", " // Jump to end and forget the data so .add doesn't re-fire\n", " firingIndex = list.length;\n", " memory = false;\n", " }\n", " }\n", " } // Forget the data if we're done with it\n", "\n", "\n", " if (!options.memory) {\n", " memory = false;\n", " }\n", "\n", " firing = false; // Clean up if we're done firing for good\n", "\n", " if (locked) {\n", " // Keep an empty list if we have data for future add calls\n", " if (memory) {\n", " list = []; // Otherwise, this object is spent\n", " } else {\n", " list = \"\";\n", " }\n", " }\n", " },\n", " // Actual Callbacks object\n", " self = {\n", " // Add a callback or a collection of callbacks to the list\n", " add: function () {\n", " if (list) {\n", " // If we have memory from a past run, we should fire after adding\n", " if (memory && !firing) {\n", " firingIndex = list.length - 1;\n", " queue.push(memory);\n", " }\n", "\n", " (function add(args) {\n", " jQuery.each(args, function (_, arg) {\n", " if (isFunction(arg)) {\n", " if (!options.unique || !self.has(arg)) {\n", " list.push(arg);\n", " }\n", " } else if (arg && arg.length && toType(arg) !== \"string\") {\n", " // Inspect recursively\n", " add(arg);\n", " }\n", " });\n", " })(arguments);\n", "\n", " if (memory && !firing) {\n", " fire();\n", " }\n", " }\n", "\n", " return this;\n", " },\n", " // Remove a callback from the list\n", " remove: function () {\n", " jQuery.each(arguments, function (_, arg) {\n", " var index;\n", "\n", " while ((index = jQuery.inArray(arg, list, index)) > -1) {\n", " list.splice(index, 1); // Handle firing indexes\n", "\n", " if (index <= firingIndex) {\n", " firingIndex--;\n", " }\n", " }\n", " });\n", " return this;\n", " },\n", " // Check if a given callback is in the list.\n", " // If no argument is given, return whether or not list has callbacks attached.\n", " has: function (fn) {\n", " return fn ? jQuery.inArray(fn, list) > -1 : list.length > 0;\n", " },\n", " // Remove all callbacks from the list\n", " empty: function () {\n", " if (list) {\n", " list = [];\n", " }\n", "\n", " return this;\n", " },\n", " // Disable .fire and .add\n", " // Abort any current/pending executions\n", " // Clear all callbacks and values\n", " disable: function () {\n", " locked = queue = [];\n", " list = memory = \"\";\n", " return this;\n", " },\n", " disabled: function () {\n", " return !list;\n", " },\n", " // Disable .fire\n", " // Also disable .add unless we have memory (since it would have no effect)\n", " // Abort any pending executions\n", " lock: function () {\n", " locked = queue = [];\n", "\n", " if (!memory && !firing) {\n", " list = memory = \"\";\n", " }\n", "\n", " return this;\n", " },\n", " locked: function () {\n", " return !!locked;\n", " },\n", " // Call all callbacks with the given context and arguments\n", " fireWith: function (context, args) {\n", " if (!locked) {\n", " args = args || [];\n", " args = [context, args.slice ? args.slice() : args];\n", " queue.push(args);\n", "\n", " if (!firing) {\n", " fire();\n", " }\n", " }\n", "\n", " return this;\n", " },\n", " // Call all the callbacks with the given arguments\n", " fire: function () {\n", " self.fireWith(this, arguments);\n", " return this;\n", " },\n", " // To know if the callbacks have already been called at least once\n", " fired: function () {\n", " return !!fired;\n", " }\n", " };\n", "\n", " return self;\n", " };\n", "\n", " function Identity(v) {\n", " return v;\n", " }\n", "\n", " function Thrower(ex) {\n", " throw ex;\n", " }\n", "\n", " function adoptValue(value, resolve, reject, noValue) {\n", " var method;\n", "\n", " try {\n", " // Check for promise aspect first to privilege synchronous behavior\n", " if (value && isFunction(method = value.promise)) {\n", " method.call(value).done(resolve).fail(reject); // Other thenables\n", " } else if (value && isFunction(method = value.then)) {\n", " method.call(value, resolve, reject); // Other non-thenables\n", " } else {\n", " // Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer:\n", " // * false: [ value ].slice( 0 ) => resolve( value )\n", " // * true: [ value ].slice( 1 ) => resolve()\n", " resolve.apply(undefined, [value].slice(noValue));\n", " } // For Promises/A+, convert exceptions into rejections\n", " // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in\n", " // Deferred#then to conditionally suppress rejection.\n", "\n", " } catch (value) {\n", " // Support: Android 4.0 only\n", " // Strict mode functions invoked without .call/.apply get global-object context\n", " reject.apply(undefined, [value]);\n", " }\n", " }\n", "\n", " jQuery.extend({\n", " Deferred: function (func) {\n", " var tuples = [// action, add listener, callbacks,\n", " // ... .then handlers, argument index, [final state]\n", " [\"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\"]],\n", " state = \"pending\",\n", " promise = {\n", " state: function () {\n", " return state;\n", " },\n", " always: function () {\n", " deferred.done(arguments).fail(arguments);\n", " return this;\n", " },\n", " \"catch\": function (fn) {\n", " return promise.then(null, fn);\n", " },\n", " // Keep pipe for back-compat\n", " pipe: function\n", " /* fnDone, fnFail, fnProgress */\n", " () {\n", " var fns = arguments;\n", " return jQuery.Deferred(function (newDefer) {\n", " jQuery.each(tuples, function (i, tuple) {\n", " // Map tuples (progress, done, fail) to arguments (done, fail, progress)\n", " var fn = isFunction(fns[tuple[4]]) && fns[tuple[4]]; // deferred.progress(function() { bind to newDefer or newDefer.notify })\n", " // deferred.done(function() { bind to newDefer or newDefer.resolve })\n", " // deferred.fail(function() { bind to newDefer or newDefer.reject })\n", "\n", " deferred[tuple[1]](function () {\n", " var returned = fn && fn.apply(this, arguments);\n", "\n", " if (returned && isFunction(returned.promise)) {\n", " returned.promise().progress(newDefer.notify).done(newDefer.resolve).fail(newDefer.reject);\n", " } else {\n", " newDefer[tuple[0] + \"With\"](this, fn ? [returned] : arguments);\n", " }\n", " });\n", " });\n", " fns = null;\n", " }).promise();\n", " },\n", " then: function (onFulfilled, onRejected, onProgress) {\n", " var maxDepth = 0;\n", "\n", " function resolve(depth, deferred, handler, special) {\n", " return function () {\n", " var that = this,\n", " args = arguments,\n", " mightThrow = function () {\n", " var returned, then; // Support: Promises/A+ section 2.3.3.3.3\n", " // https://promisesaplus.com/#point-59\n", " // Ignore double-resolution attempts\n", "\n", " if (depth < maxDepth) {\n", " return;\n", " }\n", "\n", " returned = handler.apply(that, args); // Support: Promises/A+ section 2.3.1\n", " // https://promisesaplus.com/#point-48\n", "\n", " if (returned === deferred.promise()) {\n", " throw new TypeError(\"Thenable self-resolution\");\n", " } // Support: Promises/A+ sections 2.3.3.1, 3.5\n", " // https://promisesaplus.com/#point-54\n", " // https://promisesaplus.com/#point-75\n", " // Retrieve `then` only once\n", "\n", "\n", " then = returned && ( // Support: Promises/A+ section 2.3.4\n", " // https://promisesaplus.com/#point-64\n", " // Only check objects and functions for thenability\n", " typeof returned === \"object\" || typeof returned === \"function\") && returned.then; // Handle a returned thenable\n", "\n", " if (isFunction(then)) {\n", " // Special processors (notify) just wait for resolution\n", " if (special) {\n", " then.call(returned, resolve(maxDepth, deferred, Identity, special), resolve(maxDepth, deferred, Thrower, special)); // Normal processors (resolve) also hook into progress\n", " } else {\n", " // ...and disregard older resolution values\n", " maxDepth++;\n", " then.call(returned, resolve(maxDepth, deferred, Identity, special), resolve(maxDepth, deferred, Thrower, special), resolve(maxDepth, deferred, Identity, deferred.notifyWith));\n", " } // Handle all other returned values\n", "\n", " } else {\n", " // Only substitute handlers pass on context\n", " // and multiple values (non-spec behavior)\n", " if (handler !== Identity) {\n", " that = undefined;\n", " args = [returned];\n", " } // Process the value(s)\n", " // Default process is resolve\n", "\n", "\n", " (special || deferred.resolveWith)(that, args);\n", " }\n", " },\n", " // Only normal processors (resolve) catch and reject exceptions\n", " process = special ? mightThrow : function () {\n", " try {\n", " mightThrow();\n", " } catch (e) {\n", " if (jQuery.Deferred.exceptionHook) {\n", " jQuery.Deferred.exceptionHook(e, process.stackTrace);\n", " } // Support: Promises/A+ section 2.3.3.3.4.1\n", " // https://promisesaplus.com/#point-61\n", " // Ignore post-resolution exceptions\n", "\n", "\n", " if (depth + 1 >= maxDepth) {\n", " // Only substitute handlers pass on context\n", " // and multiple values (non-spec behavior)\n", " if (handler !== Thrower) {\n", " that = undefined;\n", " args = [e];\n", " }\n", "\n", " deferred.rejectWith(that, args);\n", " }\n", " }\n", " }; // Support: Promises/A+ section 2.3.3.3.1\n", " // https://promisesaplus.com/#point-57\n", " // Re-resolve promises immediately to dodge false rejection from\n", " // subsequent errors\n", "\n", "\n", " if (depth) {\n", " process();\n", " } else {\n", " // Call an optional hook to record the stack, in case of exception\n", " // since it's otherwise lost when execution goes async\n", " if (jQuery.Deferred.getStackHook) {\n", " process.stackTrace = jQuery.Deferred.getStackHook();\n", " }\n", "\n", " window.setTimeout(process);\n", " }\n", " };\n", " }\n", "\n", " return jQuery.Deferred(function (newDefer) {\n", " // progress_handlers.add( ... )\n", " tuples[0][3].add(resolve(0, newDefer, isFunction(onProgress) ? onProgress : Identity, newDefer.notifyWith)); // fulfilled_handlers.add( ... )\n", "\n", " tuples[1][3].add(resolve(0, newDefer, isFunction(onFulfilled) ? onFulfilled : Identity)); // rejected_handlers.add( ... )\n", "\n", " tuples[2][3].add(resolve(0, newDefer, isFunction(onRejected) ? onRejected : Thrower));\n", " }).promise();\n", " },\n", " // Get a promise for this deferred\n", " // If obj is provided, the promise aspect is added to the object\n", " promise: function (obj) {\n", " return obj != null ? jQuery.extend(obj, promise) : promise;\n", " }\n", " },\n", " deferred = {}; // Add list-specific methods\n", "\n", " jQuery.each(tuples, function (i, tuple) {\n", " var list = tuple[2],\n", " stateString = tuple[5]; // promise.progress = list.add\n", " // promise.done = list.add\n", " // promise.fail = list.add\n", "\n", " promise[tuple[1]] = list.add; // Handle state\n", "\n", " if (stateString) {\n", " list.add(function () {\n", " // state = \"resolved\" (i.e., fulfilled)\n", " // state = \"rejected\"\n", " state = stateString;\n", " }, // rejected_callbacks.disable\n", " // fulfilled_callbacks.disable\n", " tuples[3 - i][2].disable, // rejected_handlers.disable\n", " // fulfilled_handlers.disable\n", " tuples[3 - i][3].disable, // progress_callbacks.lock\n", " tuples[0][2].lock, // progress_handlers.lock\n", " tuples[0][3].lock);\n", " } // progress_handlers.fire\n", " // fulfilled_handlers.fire\n", " // rejected_handlers.fire\n", "\n", "\n", " list.add(tuple[3].fire); // deferred.notify = function() { deferred.notifyWith(...) }\n", " // deferred.resolve = function() { deferred.resolveWith(...) }\n", " // deferred.reject = function() { deferred.rejectWith(...) }\n", "\n", " deferred[tuple[0]] = function () {\n", " deferred[tuple[0] + \"With\"](this === deferred ? undefined : this, arguments);\n", " return this;\n", " }; // deferred.notifyWith = list.fireWith\n", " // deferred.resolveWith = list.fireWith\n", " // deferred.rejectWith = list.fireWith\n", "\n", "\n", " deferred[tuple[0] + \"With\"] = list.fireWith;\n", " }); // Make the deferred a promise\n", "\n", " promise.promise(deferred); // Call given func if any\n", "\n", " if (func) {\n", " func.call(deferred, deferred);\n", " } // All done!\n", "\n", "\n", " return deferred;\n", " },\n", " // Deferred helper\n", " when: function (singleValue) {\n", " var // count of uncompleted subordinates\n", " remaining = arguments.length,\n", " // count of unprocessed arguments\n", " i = remaining,\n", " // subordinate fulfillment data\n", " resolveContexts = Array(i),\n", " resolveValues = slice.call(arguments),\n", " // the master Deferred\n", " master = jQuery.Deferred(),\n", " // subordinate callback factory\n", " updateFunc = function (i) {\n", " return function (value) {\n", " resolveContexts[i] = this;\n", " resolveValues[i] = arguments.length > 1 ? slice.call(arguments) : value;\n", "\n", " if (! --remaining) {\n", " master.resolveWith(resolveContexts, resolveValues);\n", " }\n", " };\n", " }; // Single- and empty arguments are adopted like Promise.resolve\n", "\n", "\n", " if (remaining <= 1) {\n", " adoptValue(singleValue, master.done(updateFunc(i)).resolve, master.reject, !remaining); // Use .then() to unwrap secondary thenables (cf. gh-3000)\n", "\n", " if (master.state() === \"pending\" || isFunction(resolveValues[i] && resolveValues[i].then)) {\n", " return master.then();\n", " }\n", " } // Multiple arguments are aggregated like Promise.all array elements\n", "\n", "\n", " while (i--) {\n", " adoptValue(resolveValues[i], updateFunc(i), master.reject);\n", " }\n", "\n", " return master.promise();\n", " }\n", " }); // These usually indicate a programmer mistake during development,\n", " // warn about them ASAP rather than swallowing them by default.\n", "\n", " var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;\n", "\n", " jQuery.Deferred.exceptionHook = function (error, stack) {\n", " // Support: IE 8 - 9 only\n", " // Console exists when dev tools are open, which can happen at any time\n", " if (window.console && window.console.warn && error && rerrorNames.test(error.name)) {\n", " window.console.warn(\"jQuery.Deferred exception: \" + error.message, error.stack, stack);\n", " }\n", " };\n", "\n", " jQuery.readyException = function (error) {\n", " window.setTimeout(function () {\n", " throw error;\n", " });\n", " }; // The deferred used on DOM ready\n", "\n", "\n", " var readyList = jQuery.Deferred();\n", "\n", " jQuery.fn.ready = function (fn) {\n", " readyList.then(fn) // Wrap jQuery.readyException in a function so that the lookup\n", " // happens at the time of error handling instead of callback\n", " // registration.\n", " .catch(function (error) {\n", " jQuery.readyException(error);\n", " });\n", " return this;\n", " };\n", "\n", " jQuery.extend({\n", " // Is the DOM ready to be used? Set to true once it occurs.\n", " isReady: false,\n", " // A counter to track how many items to wait for before\n", " // the ready event fires. See #6781\n", " readyWait: 1,\n", " // Handle when the DOM is ready\n", " ready: function (wait) {\n", " // Abort if there are pending holds or we're already ready\n", " if (wait === true ? --jQuery.readyWait : jQuery.isReady) {\n", " return;\n", " } // Remember that the DOM is ready\n", "\n", "\n", " jQuery.isReady = true; // If a normal DOM Ready event fired, decrement, and wait if need be\n", "\n", " if (wait !== true && --jQuery.readyWait > 0) {\n", " return;\n", " } // If there are functions bound, to execute\n", "\n", "\n", " readyList.resolveWith(document$2, [jQuery]);\n", " }\n", " });\n", " jQuery.ready.then = readyList.then; // The ready event handler and self cleanup method\n", "\n", " function completed() {\n", " document$2.removeEventListener(\"DOMContentLoaded\", completed);\n", " window.removeEventListener(\"load\", completed);\n", " jQuery.ready();\n", " } // Catch cases where $(document).ready() is called\n", " // after the browser event has already occurred.\n", " // Support: IE <=9 - 10 only\n", " // Older IE sometimes signals \"interactive\" too soon\n", "\n", "\n", " if (document$2.readyState === \"complete\" || document$2.readyState !== \"loading\" && !document$2.documentElement.doScroll) {\n", " // Handle it asynchronously to allow scripts the opportunity to delay ready\n", " window.setTimeout(jQuery.ready);\n", " } else {\n", " // Use the handy event callback\n", " document$2.addEventListener(\"DOMContentLoaded\", completed); // A fallback to window.onload, that will always work\n", "\n", " window.addEventListener(\"load\", completed);\n", " } // Multifunctional method to get and set values of a collection\n", " // The value/s can optionally be executed if it's a function\n", "\n", "\n", " var access = function (elems, fn, key, value, chainable, emptyGet, raw) {\n", " var i = 0,\n", " len = elems.length,\n", " bulk = key == null; // Sets many values\n", "\n", " if (toType(key) === \"object\") {\n", " chainable = true;\n", "\n", " for (i in key) {\n", " access(elems, fn, i, key[i], true, emptyGet, raw);\n", " } // Sets one value\n", "\n", " } else if (value !== undefined) {\n", " chainable = true;\n", "\n", " if (!isFunction(value)) {\n", " raw = true;\n", " }\n", "\n", " if (bulk) {\n", " // Bulk operations run against the entire set\n", " if (raw) {\n", " fn.call(elems, value);\n", " fn = null; // ...except when executing function values\n", " } else {\n", " bulk = fn;\n", "\n", " fn = function (elem, key, value) {\n", " return bulk.call(jQuery(elem), value);\n", " };\n", " }\n", " }\n", "\n", " if (fn) {\n", " for (; i < len; i++) {\n", " fn(elems[i], key, raw ? value : value.call(elems[i], i, fn(elems[i], key)));\n", " }\n", " }\n", " }\n", "\n", " if (chainable) {\n", " return elems;\n", " } // Gets\n", "\n", "\n", " if (bulk) {\n", " return fn.call(elems);\n", " }\n", "\n", " return len ? fn(elems[0], key) : emptyGet;\n", " }; // Matches dashed string for camelizing\n", "\n", "\n", " var rmsPrefix = /^-ms-/,\n", " rdashAlpha = /-([a-z])/g; // Used by camelCase as callback to replace()\n", "\n", " function fcamelCase(all, letter) {\n", " return letter.toUpperCase();\n", " } // Convert dashed to camelCase; used by the css and data modules\n", " // Support: IE <=9 - 11, Edge 12 - 15\n", " // Microsoft forgot to hump their vendor prefix (#9572)\n", "\n", "\n", " function camelCase(string) {\n", " return string.replace(rmsPrefix, \"ms-\").replace(rdashAlpha, fcamelCase);\n", " }\n", "\n", " var acceptData = function (owner) {\n", " // Accepts only:\n", " // - Node\n", " // - Node.ELEMENT_NODE\n", " // - Node.DOCUMENT_NODE\n", " // - Object\n", " // - Any\n", " return owner.nodeType === 1 || owner.nodeType === 9 || !+owner.nodeType;\n", " };\n", "\n", " function Data() {\n", " this.expando = jQuery.expando + Data.uid++;\n", " }\n", "\n", " Data.uid = 1;\n", " Data.prototype = {\n", " cache: function (owner) {\n", " // Check if the owner object already has a cache\n", " var value = owner[this.expando]; // If not, create one\n", "\n", " if (!value) {\n", " value = {}; // We can accept data for non-element nodes in modern browsers,\n", " // but we should not, see #8335.\n", " // Always return an empty object.\n", "\n", " if (acceptData(owner)) {\n", " // If it is a node unlikely to be stringify-ed or looped over\n", " // use plain assignment\n", " if (owner.nodeType) {\n", " owner[this.expando] = value; // Otherwise secure it in a non-enumerable property\n", " // configurable must be true to allow the property to be\n", " // deleted when data is removed\n", " } else {\n", " Object.defineProperty(owner, this.expando, {\n", " value: value,\n", " configurable: true\n", " });\n", " }\n", " }\n", " }\n", "\n", " return value;\n", " },\n", " set: function (owner, data, value) {\n", " var prop,\n", " cache = this.cache(owner); // Handle: [ owner, key, value ] args\n", " // Always use camelCase key (gh-2257)\n", "\n", " if (typeof data === \"string\") {\n", " cache[camelCase(data)] = value; // Handle: [ owner, { properties } ] args\n", " } else {\n", " // Copy the properties one-by-one to the cache object\n", " for (prop in data) {\n", " cache[camelCase(prop)] = data[prop];\n", " }\n", " }\n", "\n", " return cache;\n", " },\n", " get: function (owner, key) {\n", " return key === undefined ? this.cache(owner) : // Always use camelCase key (gh-2257)\n", " owner[this.expando] && owner[this.expando][camelCase(key)];\n", " },\n", " access: function (owner, key, value) {\n", " // In cases where either:\n", " //\n", " // 1. No key was specified\n", " // 2. A string key was specified, but no value provided\n", " //\n", " // Take the \"read\" path and allow the get method to determine\n", " // which value to return, respectively either:\n", " //\n", " // 1. The entire cache object\n", " // 2. The data stored at the key\n", " //\n", " if (key === undefined || key && typeof key === \"string\" && value === undefined) {\n", " return this.get(owner, key);\n", " } // When the key is not a string, or both a key and value\n", " // are specified, set or extend (existing objects) with either:\n", " //\n", " // 1. An object of properties\n", " // 2. A key and value\n", " //\n", "\n", "\n", " this.set(owner, key, value); // Since the \"set\" path can have two possible entry points\n", " // return the expected data based on which path was taken[*]\n", "\n", " return value !== undefined ? value : key;\n", " },\n", " remove: function (owner, key) {\n", " var i,\n", " cache = owner[this.expando];\n", "\n", " if (cache === undefined) {\n", " return;\n", " }\n", "\n", " if (key !== undefined) {\n", " // Support array or space separated string of keys\n", " if (Array.isArray(key)) {\n", " // If key is an array of keys...\n", " // We always set camelCase keys, so remove that.\n", " key = key.map(camelCase);\n", " } else {\n", " key = camelCase(key); // If a key with the spaces exists, use it.\n", " // Otherwise, create an array by matching non-whitespace\n", "\n", " key = key in cache ? [key] : key.match(rnothtmlwhite) || [];\n", " }\n", "\n", " i = key.length;\n", "\n", " while (i--) {\n", " delete cache[key[i]];\n", " }\n", " } // Remove the expando if there's no more data\n", "\n", "\n", " if (key === undefined || jQuery.isEmptyObject(cache)) {\n", " // Support: Chrome <=35 - 45\n", " // Webkit & Blink performance suffers when deleting properties\n", " // from DOM nodes, so set to undefined instead\n", " // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted)\n", " if (owner.nodeType) {\n", " owner[this.expando] = undefined;\n", " } else {\n", " delete owner[this.expando];\n", " }\n", " }\n", " },\n", " hasData: function (owner) {\n", " var cache = owner[this.expando];\n", " return cache !== undefined && !jQuery.isEmptyObject(cache);\n", " }\n", " };\n", " var dataPriv = new Data();\n", " var dataUser = new Data(); //\tImplementation Summary\n", " //\n", " //\t1. Enforce API surface and semantic compatibility with 1.9.x branch\n", " //\t2. Improve the module's maintainability by reducing the storage\n", " //\t\tpaths to a single mechanism.\n", " //\t3. Use the same single mechanism to support \"private\" and \"user\" data.\n", " //\t4. _Never_ expose \"private\" data to user code (TODO: Drop _data, _removeData)\n", " //\t5. Avoid exposing implementation details on user objects (eg. expando properties)\n", " //\t6. Provide a clear path for implementation upgrade to WeakMap in 2014\n", "\n", " var rbrace = /^(?:\\{[\\w\\W]*\\}|\\[[\\w\\W]*\\])$/,\n", " rmultiDash = /[A-Z]/g;\n", "\n", " function getData(data) {\n", " if (data === \"true\") {\n", " return true;\n", " }\n", "\n", " if (data === \"false\") {\n", " return false;\n", " }\n", "\n", " if (data === \"null\") {\n", " return null;\n", " } // Only convert to a number if it doesn't change the string\n", "\n", "\n", " if (data === +data + \"\") {\n", " return +data;\n", " }\n", "\n", " if (rbrace.test(data)) {\n", " return JSON.parse(data);\n", " }\n", "\n", " return data;\n", " }\n", "\n", " function dataAttr(elem, key, data) {\n", " var name; // If nothing was found internally, try to fetch any\n", " // data from the HTML5 data-* attribute\n", "\n", " if (data === undefined && elem.nodeType === 1) {\n", " name = \"data-\" + key.replace(rmultiDash, \"-$&\").toLowerCase();\n", " data = elem.getAttribute(name);\n", "\n", " if (typeof data === \"string\") {\n", " try {\n", " data = getData(data);\n", " } catch (e) {} // Make sure we set the data so it isn't changed later\n", "\n", "\n", " dataUser.set(elem, key, data);\n", " } else {\n", " data = undefined;\n", " }\n", " }\n", "\n", " return data;\n", " }\n", "\n", " jQuery.extend({\n", " hasData: function (elem) {\n", " return dataUser.hasData(elem) || dataPriv.hasData(elem);\n", " },\n", " data: function (elem, name, data) {\n", " return dataUser.access(elem, name, data);\n", " },\n", " removeData: function (elem, name) {\n", " dataUser.remove(elem, name);\n", " },\n", " // TODO: Now that all calls to _data and _removeData have been replaced\n", " // with direct calls to dataPriv methods, these can be deprecated.\n", " _data: function (elem, name, data) {\n", " return dataPriv.access(elem, name, data);\n", " },\n", " _removeData: function (elem, name) {\n", " dataPriv.remove(elem, name);\n", " }\n", " });\n", " jQuery.fn.extend({\n", " data: function (key, value) {\n", " var i,\n", " name,\n", " data,\n", " elem = this[0],\n", " attrs = elem && elem.attributes; // Gets all values\n", "\n", " if (key === undefined) {\n", " if (this.length) {\n", " data = dataUser.get(elem);\n", "\n", " if (elem.nodeType === 1 && !dataPriv.get(elem, \"hasDataAttrs\")) {\n", " i = attrs.length;\n", "\n", " while (i--) {\n", " // Support: IE 11 only\n", " // The attrs elements can be null (#14894)\n", " if (attrs[i]) {\n", " name = attrs[i].name;\n", "\n", " if (name.indexOf(\"data-\") === 0) {\n", " name = camelCase(name.slice(5));\n", " dataAttr(elem, name, data[name]);\n", " }\n", " }\n", " }\n", "\n", " dataPriv.set(elem, \"hasDataAttrs\", true);\n", " }\n", " }\n", "\n", " return data;\n", " } // Sets multiple values\n", "\n", "\n", " if (typeof key === \"object\") {\n", " return this.each(function () {\n", " dataUser.set(this, key);\n", " });\n", " }\n", "\n", " return access(this, function (value) {\n", " var data; // The calling jQuery object (element matches) is not empty\n", " // (and therefore has an element appears at this[ 0 ]) and the\n", " // `value` parameter was not undefined. An empty jQuery object\n", " // will result in `undefined` for elem = this[ 0 ] which will\n", " // throw an exception if an attempt to read a data cache is made.\n", "\n", " if (elem && value === undefined) {\n", " // Attempt to get data from the cache\n", " // The key will always be camelCased in Data\n", " data = dataUser.get(elem, key);\n", "\n", " if (data !== undefined) {\n", " return data;\n", " } // Attempt to \"discover\" the data in\n", " // HTML5 custom data-* attrs\n", "\n", "\n", " data = dataAttr(elem, key);\n", "\n", " if (data !== undefined) {\n", " return data;\n", " } // We tried really hard, but the data doesn't exist.\n", "\n", "\n", " return;\n", " } // Set the data...\n", "\n", "\n", " this.each(function () {\n", " // We always store the camelCased key\n", " dataUser.set(this, key, value);\n", " });\n", " }, null, value, arguments.length > 1, null, true);\n", " },\n", " removeData: function (key) {\n", " return this.each(function () {\n", " dataUser.remove(this, key);\n", " });\n", " }\n", " });\n", " jQuery.extend({\n", " queue: function (elem, type, data) {\n", " var queue;\n", "\n", " if (elem) {\n", " type = (type || \"fx\") + \"queue\";\n", " queue = dataPriv.get(elem, type); // Speed up dequeue by getting out quickly if this is just a lookup\n", "\n", " if (data) {\n", " if (!queue || Array.isArray(data)) {\n", " queue = dataPriv.access(elem, type, jQuery.makeArray(data));\n", " } else {\n", " queue.push(data);\n", " }\n", " }\n", "\n", " return queue || [];\n", " }\n", " },\n", " dequeue: function (elem, type) {\n", " type = type || \"fx\";\n", "\n", " var queue = jQuery.queue(elem, type),\n", " startLength = queue.length,\n", " fn = queue.shift(),\n", " hooks = jQuery._queueHooks(elem, type),\n", " next = function () {\n", " jQuery.dequeue(elem, type);\n", " }; // If the fx queue is dequeued, always remove the progress sentinel\n", "\n", "\n", " if (fn === \"inprogress\") {\n", " fn = queue.shift();\n", " startLength--;\n", " }\n", "\n", " if (fn) {\n", " // Add a progress sentinel to prevent the fx queue from being\n", " // automatically dequeued\n", " if (type === \"fx\") {\n", " queue.unshift(\"inprogress\");\n", " } // Clear up the last queue stop function\n", "\n", "\n", " delete hooks.stop;\n", " fn.call(elem, next, hooks);\n", " }\n", "\n", " if (!startLength && hooks) {\n", " hooks.empty.fire();\n", " }\n", " },\n", " // Not public - generate a queueHooks object, or return the current one\n", " _queueHooks: function (elem, type) {\n", " var key = type + \"queueHooks\";\n", " return dataPriv.get(elem, key) || dataPriv.access(elem, key, {\n", " empty: jQuery.Callbacks(\"once memory\").add(function () {\n", " dataPriv.remove(elem, [type + \"queue\", key]);\n", " })\n", " });\n", " }\n", " });\n", " jQuery.fn.extend({\n", " queue: function (type, data) {\n", " var setter = 2;\n", "\n", " if (typeof type !== \"string\") {\n", " data = type;\n", " type = \"fx\";\n", " setter--;\n", " }\n", "\n", " if (arguments.length < setter) {\n", " return jQuery.queue(this[0], type);\n", " }\n", "\n", " return data === undefined ? this : this.each(function () {\n", " var queue = jQuery.queue(this, type, data); // Ensure a hooks for this queue\n", "\n", " jQuery._queueHooks(this, type);\n", "\n", " if (type === \"fx\" && queue[0] !== \"inprogress\") {\n", " jQuery.dequeue(this, type);\n", " }\n", " });\n", " },\n", " dequeue: function (type) {\n", " return this.each(function () {\n", " jQuery.dequeue(this, type);\n", " });\n", " },\n", " clearQueue: function (type) {\n", " return this.queue(type || \"fx\", []);\n", " },\n", " // Get a promise resolved when queues of a certain type\n", " // are emptied (fx is the type by default)\n", " promise: function (type, obj) {\n", " var tmp,\n", " count = 1,\n", " defer = jQuery.Deferred(),\n", " elements = this,\n", " i = this.length,\n", " resolve = function () {\n", " if (! --count) {\n", " defer.resolveWith(elements, [elements]);\n", " }\n", " };\n", "\n", " if (typeof type !== \"string\") {\n", " obj = type;\n", " type = undefined;\n", " }\n", "\n", " type = type || \"fx\";\n", "\n", " while (i--) {\n", " tmp = dataPriv.get(elements[i], type + \"queueHooks\");\n", "\n", " if (tmp && tmp.empty) {\n", " count++;\n", " tmp.empty.add(resolve);\n", " }\n", " }\n", "\n", " resolve();\n", " return defer.promise(obj);\n", " }\n", " });\n", " var pnum = /[+-]?(?:\\d*\\.|)\\d+(?:[eE][+-]?\\d+|)/.source;\n", " var rcssNum = new RegExp(\"^(?:([+-])=|)(\" + pnum + \")([a-z%]*)$\", \"i\");\n", " var cssExpand = [\"Top\", \"Right\", \"Bottom\", \"Left\"];\n", "\n", " var isHiddenWithinTree = function (elem, el) {\n", " // isHiddenWithinTree might be called from jQuery#filter function;\n", " // in that case, element will be second argument\n", " elem = el || elem; // Inline style trumps all\n", "\n", " return elem.style.display === \"none\" || elem.style.display === \"\" && // Otherwise, check computed style\n", " // Support: Firefox <=43 - 45\n", " // Disconnected elements can have computed display: none, so first confirm that elem is\n", " // in the document.\n", " jQuery.contains(elem.ownerDocument, elem) && jQuery.css(elem, \"display\") === \"none\";\n", " };\n", "\n", " var swap = function (elem, options, callback, args) {\n", " var ret,\n", " name,\n", " old = {}; // Remember the old values, and insert the new ones\n", "\n", " for (name in options) {\n", " old[name] = elem.style[name];\n", " elem.style[name] = options[name];\n", " }\n", "\n", " ret = callback.apply(elem, args || []); // Revert the old values\n", "\n", " for (name in options) {\n", " elem.style[name] = old[name];\n", " }\n", "\n", " return ret;\n", " };\n", "\n", " function adjustCSS(elem, prop, valueParts, tween) {\n", " var adjusted,\n", " scale,\n", " maxIterations = 20,\n", " currentValue = tween ? function () {\n", " return tween.cur();\n", " } : function () {\n", " return jQuery.css(elem, prop, \"\");\n", " },\n", " initial = currentValue(),\n", " unit = valueParts && valueParts[3] || (jQuery.cssNumber[prop] ? \"\" : \"px\"),\n", " // Starting value computation is required for potential unit mismatches\n", " initialInUnit = (jQuery.cssNumber[prop] || unit !== \"px\" && +initial) && rcssNum.exec(jQuery.css(elem, prop));\n", "\n", " if (initialInUnit && initialInUnit[3] !== unit) {\n", " // Support: Firefox <=54\n", " // Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144)\n", " initial = initial / 2; // Trust units reported by jQuery.css\n", "\n", " unit = unit || initialInUnit[3]; // Iteratively approximate from a nonzero starting point\n", "\n", " initialInUnit = +initial || 1;\n", "\n", " while (maxIterations--) {\n", " // Evaluate and update our best guess (doubling guesses that zero out).\n", " // Finish if the scale equals or crosses 1 (making the old*new product non-positive).\n", " jQuery.style(elem, prop, initialInUnit + unit);\n", "\n", " if ((1 - scale) * (1 - (scale = currentValue() / initial || 0.5)) <= 0) {\n", " maxIterations = 0;\n", " }\n", "\n", " initialInUnit = initialInUnit / scale;\n", " }\n", "\n", " initialInUnit = initialInUnit * 2;\n", " jQuery.style(elem, prop, initialInUnit + unit); // Make sure we update the tween properties later on\n", "\n", " valueParts = valueParts || [];\n", " }\n", "\n", " if (valueParts) {\n", " initialInUnit = +initialInUnit || +initial || 0; // Apply relative offset (+=/-=) if specified\n", "\n", " adjusted = valueParts[1] ? initialInUnit + (valueParts[1] + 1) * valueParts[2] : +valueParts[2];\n", "\n", " if (tween) {\n", " tween.unit = unit;\n", " tween.start = initialInUnit;\n", " tween.end = adjusted;\n", " }\n", " }\n", "\n", " return adjusted;\n", " }\n", "\n", " var defaultDisplayMap = {};\n", "\n", " function getDefaultDisplay(elem) {\n", " var temp,\n", " doc = elem.ownerDocument,\n", " nodeName = elem.nodeName,\n", " display = defaultDisplayMap[nodeName];\n", "\n", " if (display) {\n", " return display;\n", " }\n", "\n", " temp = doc.body.appendChild(doc.createElement(nodeName));\n", " display = jQuery.css(temp, \"display\");\n", " temp.parentNode.removeChild(temp);\n", "\n", " if (display === \"none\") {\n", " display = \"block\";\n", " }\n", "\n", " defaultDisplayMap[nodeName] = display;\n", " return display;\n", " }\n", "\n", " function showHide(elements, show) {\n", " var display,\n", " elem,\n", " values = [],\n", " index = 0,\n", " length = elements.length; // Determine new display value for elements that need to change\n", "\n", " for (; index < length; index++) {\n", " elem = elements[index];\n", "\n", " if (!elem.style) {\n", " continue;\n", " }\n", "\n", " display = elem.style.display;\n", "\n", " if (show) {\n", " // Since we force visibility upon cascade-hidden elements, an immediate (and slow)\n", " // check is required in this first loop unless we have a nonempty display value (either\n", " // inline or about-to-be-restored)\n", " if (display === \"none\") {\n", " values[index] = dataPriv.get(elem, \"display\") || null;\n", "\n", " if (!values[index]) {\n", " elem.style.display = \"\";\n", " }\n", " }\n", "\n", " if (elem.style.display === \"\" && isHiddenWithinTree(elem)) {\n", " values[index] = getDefaultDisplay(elem);\n", " }\n", " } else {\n", " if (display !== \"none\") {\n", " values[index] = \"none\"; // Remember what we're overwriting\n", "\n", " dataPriv.set(elem, \"display\", display);\n", " }\n", " }\n", " } // Set the display of the elements in a second loop to avoid constant reflow\n", "\n", "\n", " for (index = 0; index < length; index++) {\n", " if (values[index] != null) {\n", " elements[index].style.display = values[index];\n", " }\n", " }\n", "\n", " return elements;\n", " }\n", "\n", " jQuery.fn.extend({\n", " show: function () {\n", " return showHide(this, true);\n", " },\n", " hide: function () {\n", " return showHide(this);\n", " },\n", " toggle: function (state) {\n", " if (typeof state === \"boolean\") {\n", " return state ? this.show() : this.hide();\n", " }\n", "\n", " return this.each(function () {\n", " if (isHiddenWithinTree(this)) {\n", " jQuery(this).show();\n", " } else {\n", " jQuery(this).hide();\n", " }\n", " });\n", " }\n", " });\n", " var rcheckableType = /^(?:checkbox|radio)$/i;\n", " var rtagName = /<([a-z][^\\/\\0>\\x20\\t\\r\\n\\f]+)/i;\n", " var rscriptType = /^$|^module$|\\/(?:java|ecma)script/i; // We have to close these tags to support XHTML (#13200)\n", "\n", " var wrapMap = {\n", " // Support: IE <=9 only\n", " option: [1, \"\"],\n", " // XHTML parsers do not magically insert elements in the\n", " // same way that tag soup parsers do. So we cannot shorten\n", " // this by omitting or other required elements.\n", " thead: [1, \"\", \"
\"],\n", " col: [2, \"\", \"
\"],\n", " tr: [2, \"\", \"
\"],\n", " td: [3, \"\", \"
\"],\n", " _default: [0, \"\", \"\"]\n", " }; // Support: IE <=9 only\n", "\n", " wrapMap.optgroup = wrapMap.option;\n", " wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;\n", " wrapMap.th = wrapMap.td;\n", "\n", " function getAll(context, tag) {\n", " // Support: IE <=9 - 11 only\n", " // Use typeof to avoid zero-argument method invocation on host objects (#15151)\n", " var ret;\n", "\n", " if (typeof context.getElementsByTagName !== \"undefined\") {\n", " ret = context.getElementsByTagName(tag || \"*\");\n", " } else if (typeof context.querySelectorAll !== \"undefined\") {\n", " ret = context.querySelectorAll(tag || \"*\");\n", " } else {\n", " ret = [];\n", " }\n", "\n", " if (tag === undefined || tag && nodeName(context, tag)) {\n", " return jQuery.merge([context], ret);\n", " }\n", "\n", " return ret;\n", " } // Mark scripts as having already been evaluated\n", "\n", "\n", " function setGlobalEval(elems, refElements) {\n", " var i = 0,\n", " l = elems.length;\n", "\n", " for (; i < l; i++) {\n", " dataPriv.set(elems[i], \"globalEval\", !refElements || dataPriv.get(refElements[i], \"globalEval\"));\n", " }\n", " }\n", "\n", " var rhtml = /<|&#?\\w+;/;\n", "\n", " function buildFragment(elems, context, scripts, selection, ignored) {\n", " var elem,\n", " tmp,\n", " tag,\n", " wrap,\n", " contains,\n", " j,\n", " fragment = context.createDocumentFragment(),\n", " nodes = [],\n", " i = 0,\n", " l = elems.length;\n", "\n", " for (; i < l; i++) {\n", " elem = elems[i];\n", "\n", " if (elem || elem === 0) {\n", " // Add nodes directly\n", " if (toType(elem) === \"object\") {\n", " // Support: Android <=4.0 only, PhantomJS 1 only\n", " // push.apply(_, arraylike) throws on ancient WebKit\n", " jQuery.merge(nodes, elem.nodeType ? [elem] : elem); // Convert non-html into a text node\n", " } else if (!rhtml.test(elem)) {\n", " nodes.push(context.createTextNode(elem)); // Convert html into DOM nodes\n", " } else {\n", " tmp = tmp || fragment.appendChild(context.createElement(\"div\")); // Deserialize a standard representation\n", "\n", " tag = (rtagName.exec(elem) || [\"\", \"\"])[1].toLowerCase();\n", " wrap = wrapMap[tag] || wrapMap._default;\n", " tmp.innerHTML = wrap[1] + jQuery.htmlPrefilter(elem) + wrap[2]; // Descend through wrappers to the right content\n", "\n", " j = wrap[0];\n", "\n", " while (j--) {\n", " tmp = tmp.lastChild;\n", " } // Support: Android <=4.0 only, PhantomJS 1 only\n", " // push.apply(_, arraylike) throws on ancient WebKit\n", "\n", "\n", " jQuery.merge(nodes, tmp.childNodes); // Remember the top-level container\n", "\n", " tmp = fragment.firstChild; // Ensure the created nodes are orphaned (#12392)\n", "\n", " tmp.textContent = \"\";\n", " }\n", " }\n", " } // Remove wrapper from fragment\n", "\n", "\n", " fragment.textContent = \"\";\n", " i = 0;\n", "\n", " while (elem = nodes[i++]) {\n", " // Skip elements already in the context collection (trac-4087)\n", " if (selection && jQuery.inArray(elem, selection) > -1) {\n", " if (ignored) {\n", " ignored.push(elem);\n", " }\n", "\n", " continue;\n", " }\n", "\n", " contains = jQuery.contains(elem.ownerDocument, elem); // Append to fragment\n", "\n", " tmp = getAll(fragment.appendChild(elem), \"script\"); // Preserve script evaluation history\n", "\n", " if (contains) {\n", " setGlobalEval(tmp);\n", " } // Capture executables\n", "\n", "\n", " if (scripts) {\n", " j = 0;\n", "\n", " while (elem = tmp[j++]) {\n", " if (rscriptType.test(elem.type || \"\")) {\n", " scripts.push(elem);\n", " }\n", " }\n", " }\n", " }\n", "\n", " return fragment;\n", " }\n", "\n", " (function () {\n", " var fragment = document$2.createDocumentFragment(),\n", " div = fragment.appendChild(document$2.createElement(\"div\")),\n", " input = document$2.createElement(\"input\"); // Support: Android 4.0 - 4.3 only\n", " // Check state lost if the name is set (#11217)\n", " // Support: Windows Web Apps (WWA)\n", " // `name` and `type` must use .setAttribute for WWA (#14901)\n", "\n", " input.setAttribute(\"type\", \"radio\");\n", " input.setAttribute(\"checked\", \"checked\");\n", " input.setAttribute(\"name\", \"t\");\n", " div.appendChild(input); // Support: Android <=4.1 only\n", " // Older WebKit doesn't clone checked state correctly in fragments\n", "\n", " support.checkClone = div.cloneNode(true).cloneNode(true).lastChild.checked; // Support: IE <=11 only\n", " // Make sure textarea (and checkbox) defaultValue is properly cloned\n", "\n", " div.innerHTML = \"\";\n", " support.noCloneChecked = !!div.cloneNode(true).lastChild.defaultValue;\n", " })();\n", "\n", " var documentElement = document$2.documentElement;\n", " var rkeyEvent = /^key/,\n", " rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/,\n", " rtypenamespace = /^([^.]*)(?:\\.(.+)|)/;\n", "\n", " function returnTrue() {\n", " return true;\n", " }\n", "\n", " function returnFalse() {\n", " return false;\n", " } // Support: IE <=9 only\n", " // See #13393 for more info\n", "\n", "\n", " function safeActiveElement() {\n", " try {\n", " return document$2.activeElement;\n", " } catch (err) {}\n", " }\n", "\n", " function on(elem, types, selector, data, fn, one) {\n", " var origFn, type; // Types can be a map of types/handlers\n", "\n", " if (typeof types === \"object\") {\n", " // ( types-Object, selector, data )\n", " if (typeof selector !== \"string\") {\n", " // ( types-Object, data )\n", " data = data || selector;\n", " selector = undefined;\n", " }\n", "\n", " for (type in types) {\n", " on(elem, type, selector, data, types[type], one);\n", " }\n", "\n", " return elem;\n", " }\n", "\n", " if (data == null && fn == null) {\n", " // ( types, fn )\n", " fn = selector;\n", " data = selector = undefined;\n", " } else if (fn == null) {\n", " if (typeof selector === \"string\") {\n", " // ( types, selector, fn )\n", " fn = data;\n", " data = undefined;\n", " } else {\n", " // ( types, data, fn )\n", " fn = data;\n", " data = selector;\n", " selector = undefined;\n", " }\n", " }\n", "\n", " if (fn === false) {\n", " fn = returnFalse;\n", " } else if (!fn) {\n", " return elem;\n", " }\n", "\n", " if (one === 1) {\n", " origFn = fn;\n", "\n", " fn = function (event) {\n", " // Can use an empty set, since event contains the info\n", " jQuery().off(event);\n", " return origFn.apply(this, arguments);\n", " }; // Use same guid so caller can remove using origFn\n", "\n", "\n", " fn.guid = origFn.guid || (origFn.guid = jQuery.guid++);\n", " }\n", "\n", " return elem.each(function () {\n", " jQuery.event.add(this, types, fn, data, selector);\n", " });\n", " }\n", " /*\n", " * Helper functions for managing events -- not part of the public interface.\n", " * Props to Dean Edwards' addEvent library for many of the ideas.\n", " */\n", "\n", "\n", " jQuery.event = {\n", " global: {},\n", " add: function (elem, types, handler, data, selector) {\n", " var handleObjIn,\n", " eventHandle,\n", " tmp,\n", " events,\n", " t,\n", " handleObj,\n", " special,\n", " handlers,\n", " type,\n", " namespaces,\n", " origType,\n", " elemData = dataPriv.get(elem); // Don't attach events to noData or text/comment nodes (but allow plain objects)\n", "\n", " if (!elemData) {\n", " return;\n", " } // Caller can pass in an object of custom data in lieu of the handler\n", "\n", "\n", " if (handler.handler) {\n", " handleObjIn = handler;\n", " handler = handleObjIn.handler;\n", " selector = handleObjIn.selector;\n", " } // Ensure that invalid selectors throw exceptions at attach time\n", " // Evaluate against documentElement in case elem is a non-element node (e.g., document)\n", "\n", "\n", " if (selector) {\n", " jQuery.find.matchesSelector(documentElement, selector);\n", " } // Make sure that the handler has a unique ID, used to find/remove it later\n", "\n", "\n", " if (!handler.guid) {\n", " handler.guid = jQuery.guid++;\n", " } // Init the element's event structure and main handler, if this is the first\n", "\n", "\n", " if (!(events = elemData.events)) {\n", " events = elemData.events = {};\n", " }\n", "\n", " if (!(eventHandle = elemData.handle)) {\n", " eventHandle = elemData.handle = function (e) {\n", " // Discard the second event of a jQuery.event.trigger() and\n", " // when an event is called after a page has unloaded\n", " return typeof jQuery !== \"undefined\" && jQuery.event.triggered !== e.type ? jQuery.event.dispatch.apply(elem, arguments) : undefined;\n", " };\n", " } // Handle multiple events separated by a space\n", "\n", "\n", " types = (types || \"\").match(rnothtmlwhite) || [\"\"];\n", " t = types.length;\n", "\n", " while (t--) {\n", " tmp = rtypenamespace.exec(types[t]) || [];\n", " type = origType = tmp[1];\n", " namespaces = (tmp[2] || \"\").split(\".\").sort(); // There *must* be a type, no attaching namespace-only handlers\n", "\n", " if (!type) {\n", " continue;\n", " } // If event changes its type, use the special event handlers for the changed type\n", "\n", "\n", " special = jQuery.event.special[type] || {}; // If selector defined, determine special event api type, otherwise given type\n", "\n", " type = (selector ? special.delegateType : special.bindType) || type; // Update special based on newly reset type\n", "\n", " special = jQuery.event.special[type] || {}; // handleObj is passed to all event handlers\n", "\n", " handleObj = jQuery.extend({\n", " type: type,\n", " origType: origType,\n", " data: data,\n", " handler: handler,\n", " guid: handler.guid,\n", " selector: selector,\n", " needsContext: selector && jQuery.expr.match.needsContext.test(selector),\n", " namespace: namespaces.join(\".\")\n", " }, handleObjIn); // Init the event handler queue if we're the first\n", "\n", " if (!(handlers = events[type])) {\n", " handlers = events[type] = [];\n", " handlers.delegateCount = 0; // Only use addEventListener if the special events handler returns false\n", "\n", " if (!special.setup || special.setup.call(elem, data, namespaces, eventHandle) === false) {\n", " if (elem.addEventListener) {\n", " elem.addEventListener(type, eventHandle);\n", " }\n", " }\n", " }\n", "\n", " if (special.add) {\n", " special.add.call(elem, handleObj);\n", "\n", " if (!handleObj.handler.guid) {\n", " handleObj.handler.guid = handler.guid;\n", " }\n", " } // Add to the element's handler list, delegates in front\n", "\n", "\n", " if (selector) {\n", " handlers.splice(handlers.delegateCount++, 0, handleObj);\n", " } else {\n", " handlers.push(handleObj);\n", " } // Keep track of which events have ever been used, for event optimization\n", "\n", "\n", " jQuery.event.global[type] = true;\n", " }\n", " },\n", " // Detach an event or set of events from an element\n", " remove: function (elem, types, handler, selector, mappedTypes) {\n", " var j,\n", " origCount,\n", " tmp,\n", " events,\n", " t,\n", " handleObj,\n", " special,\n", " handlers,\n", " type,\n", " namespaces,\n", " origType,\n", " elemData = dataPriv.hasData(elem) && dataPriv.get(elem);\n", "\n", " if (!elemData || !(events = elemData.events)) {\n", " return;\n", " } // Once for each type.namespace in types; type may be omitted\n", "\n", "\n", " types = (types || \"\").match(rnothtmlwhite) || [\"\"];\n", " t = types.length;\n", "\n", " while (t--) {\n", " tmp = rtypenamespace.exec(types[t]) || [];\n", " type = origType = tmp[1];\n", " namespaces = (tmp[2] || \"\").split(\".\").sort(); // Unbind all events (on this namespace, if provided) for the element\n", "\n", " if (!type) {\n", " for (type in events) {\n", " jQuery.event.remove(elem, type + types[t], handler, selector, true);\n", " }\n", "\n", " continue;\n", " }\n", "\n", " special = jQuery.event.special[type] || {};\n", " type = (selector ? special.delegateType : special.bindType) || type;\n", " handlers = events[type] || [];\n", " tmp = tmp[2] && new RegExp(\"(^|\\\\.)\" + namespaces.join(\"\\\\.(?:.*\\\\.|)\") + \"(\\\\.|$)\"); // Remove matching events\n", "\n", " origCount = j = handlers.length;\n", "\n", " while (j--) {\n", " handleObj = handlers[j];\n", "\n", " if ((mappedTypes || origType === handleObj.origType) && (!handler || handler.guid === handleObj.guid) && (!tmp || tmp.test(handleObj.namespace)) && (!selector || selector === handleObj.selector || selector === \"**\" && handleObj.selector)) {\n", " handlers.splice(j, 1);\n", "\n", " if (handleObj.selector) {\n", " handlers.delegateCount--;\n", " }\n", "\n", " if (special.remove) {\n", " special.remove.call(elem, handleObj);\n", " }\n", " }\n", " } // Remove generic event handler if we removed something and no more handlers exist\n", " // (avoids potential for endless recursion during removal of special event handlers)\n", "\n", "\n", " if (origCount && !handlers.length) {\n", " if (!special.teardown || special.teardown.call(elem, namespaces, elemData.handle) === false) {\n", " jQuery.removeEvent(elem, type, elemData.handle);\n", " }\n", "\n", " delete events[type];\n", " }\n", " } // Remove data and the expando if it's no longer used\n", "\n", "\n", " if (jQuery.isEmptyObject(events)) {\n", " dataPriv.remove(elem, \"handle events\");\n", " }\n", " },\n", " dispatch: function (nativeEvent) {\n", " // Make a writable jQuery.Event from the native event object\n", " var event = jQuery.event.fix(nativeEvent);\n", " var i,\n", " j,\n", " ret,\n", " matched,\n", " handleObj,\n", " handlerQueue,\n", " args = new Array(arguments.length),\n", " handlers = (dataPriv.get(this, \"events\") || {})[event.type] || [],\n", " special = jQuery.event.special[event.type] || {}; // Use the fix-ed jQuery.Event rather than the (read-only) native event\n", "\n", " args[0] = event;\n", "\n", " for (i = 1; i < arguments.length; i++) {\n", " args[i] = arguments[i];\n", " }\n", "\n", " event.delegateTarget = this; // Call the preDispatch hook for the mapped type, and let it bail if desired\n", "\n", " if (special.preDispatch && special.preDispatch.call(this, event) === false) {\n", " return;\n", " } // Determine handlers\n", "\n", "\n", " handlerQueue = jQuery.event.handlers.call(this, event, handlers); // Run delegates first; they may want to stop propagation beneath us\n", "\n", " i = 0;\n", "\n", " while ((matched = handlerQueue[i++]) && !event.isPropagationStopped()) {\n", " event.currentTarget = matched.elem;\n", " j = 0;\n", "\n", " while ((handleObj = matched.handlers[j++]) && !event.isImmediatePropagationStopped()) {\n", " // Triggered event must either 1) have no namespace, or 2) have namespace(s)\n", " // a subset or equal to those in the bound event (both can have no namespace).\n", " if (!event.rnamespace || event.rnamespace.test(handleObj.namespace)) {\n", " event.handleObj = handleObj;\n", " event.data = handleObj.data;\n", " ret = ((jQuery.event.special[handleObj.origType] || {}).handle || handleObj.handler).apply(matched.elem, args);\n", "\n", " if (ret !== undefined) {\n", " if ((event.result = ret) === false) {\n", " event.preventDefault();\n", " event.stopPropagation();\n", " }\n", " }\n", " }\n", " }\n", " } // Call the postDispatch hook for the mapped type\n", "\n", "\n", " if (special.postDispatch) {\n", " special.postDispatch.call(this, event);\n", " }\n", "\n", " return event.result;\n", " },\n", " handlers: function (event, handlers) {\n", " var i,\n", " handleObj,\n", " sel,\n", " matchedHandlers,\n", " matchedSelectors,\n", " handlerQueue = [],\n", " delegateCount = handlers.delegateCount,\n", " cur = event.target; // Find delegate handlers\n", "\n", " if (delegateCount && // Support: IE <=9\n", " // Black-hole SVG instance trees (trac-13180)\n", " cur.nodeType && // Support: Firefox <=42\n", " // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861)\n", " // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click\n", " // Support: IE 11 only\n", " // ...but not arrow key \"clicks\" of radio inputs, which can have `button` -1 (gh-2343)\n", " !(event.type === \"click\" && event.button >= 1)) {\n", " for (; cur !== this; cur = cur.parentNode || this) {\n", " // Don't check non-elements (#13208)\n", " // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)\n", " if (cur.nodeType === 1 && !(event.type === \"click\" && cur.disabled === true)) {\n", " matchedHandlers = [];\n", " matchedSelectors = {};\n", "\n", " for (i = 0; i < delegateCount; i++) {\n", " handleObj = handlers[i]; // Don't conflict with Object.prototype properties (#13203)\n", "\n", " sel = handleObj.selector + \" \";\n", "\n", " if (matchedSelectors[sel] === undefined) {\n", " matchedSelectors[sel] = handleObj.needsContext ? jQuery(sel, this).index(cur) > -1 : jQuery.find(sel, this, null, [cur]).length;\n", " }\n", "\n", " if (matchedSelectors[sel]) {\n", " matchedHandlers.push(handleObj);\n", " }\n", " }\n", "\n", " if (matchedHandlers.length) {\n", " handlerQueue.push({\n", " elem: cur,\n", " handlers: matchedHandlers\n", " });\n", " }\n", " }\n", " }\n", " } // Add the remaining (directly-bound) handlers\n", "\n", "\n", " cur = this;\n", "\n", " if (delegateCount < handlers.length) {\n", " handlerQueue.push({\n", " elem: cur,\n", " handlers: handlers.slice(delegateCount)\n", " });\n", " }\n", "\n", " return handlerQueue;\n", " },\n", " addProp: function (name, hook) {\n", " Object.defineProperty(jQuery.Event.prototype, name, {\n", " enumerable: true,\n", " configurable: true,\n", " get: isFunction(hook) ? function () {\n", " if (this.originalEvent) {\n", " return hook(this.originalEvent);\n", " }\n", " } : function () {\n", " if (this.originalEvent) {\n", " return this.originalEvent[name];\n", " }\n", " },\n", " set: function (value) {\n", " Object.defineProperty(this, name, {\n", " enumerable: true,\n", " configurable: true,\n", " writable: true,\n", " value: value\n", " });\n", " }\n", " });\n", " },\n", " fix: function (originalEvent) {\n", " return originalEvent[jQuery.expando] ? originalEvent : new jQuery.Event(originalEvent);\n", " },\n", " special: {\n", " load: {\n", " // Prevent triggered image.load events from bubbling to window.load\n", " noBubble: true\n", " },\n", " focus: {\n", " // Fire native event if possible so blur/focus sequence is correct\n", " trigger: function () {\n", " if (this !== safeActiveElement() && this.focus) {\n", " this.focus();\n", " return false;\n", " }\n", " },\n", " delegateType: \"focusin\"\n", " },\n", " blur: {\n", " trigger: function () {\n", " if (this === safeActiveElement() && this.blur) {\n", " this.blur();\n", " return false;\n", " }\n", " },\n", " delegateType: \"focusout\"\n", " },\n", " click: {\n", " // For checkbox, fire native event so checked state will be right\n", " trigger: function () {\n", " if (this.type === \"checkbox\" && this.click && nodeName(this, \"input\")) {\n", " this.click();\n", " return false;\n", " }\n", " },\n", " // For cross-browser consistency, don't fire native .click() on links\n", " _default: function (event) {\n", " return nodeName(event.target, \"a\");\n", " }\n", " },\n", " beforeunload: {\n", " postDispatch: function (event) {\n", " // Support: Firefox 20+\n", " // Firefox doesn't alert if the returnValue field is not set.\n", " if (event.result !== undefined && event.originalEvent) {\n", " event.originalEvent.returnValue = event.result;\n", " }\n", " }\n", " }\n", " }\n", " };\n", "\n", " jQuery.removeEvent = function (elem, type, handle) {\n", " // This \"if\" is needed for plain objects\n", " if (elem.removeEventListener) {\n", " elem.removeEventListener(type, handle);\n", " }\n", " };\n", "\n", " jQuery.Event = function (src, props) {\n", " // Allow instantiation without the 'new' keyword\n", " if (!(this instanceof jQuery.Event)) {\n", " return new jQuery.Event(src, props);\n", " } // Event object\n", "\n", "\n", " if (src && src.type) {\n", " this.originalEvent = src;\n", " this.type = src.type; // Events bubbling up the document may have been marked as prevented\n", " // by a handler lower down the tree; reflect the correct value.\n", "\n", " this.isDefaultPrevented = src.defaultPrevented || src.defaultPrevented === undefined && // Support: Android <=2.3 only\n", " src.returnValue === false ? returnTrue : returnFalse; // Create target properties\n", " // Support: Safari <=6 - 7 only\n", " // Target should not be a text node (#504, #13143)\n", "\n", " this.target = src.target && src.target.nodeType === 3 ? src.target.parentNode : src.target;\n", " this.currentTarget = src.currentTarget;\n", " this.relatedTarget = src.relatedTarget; // Event type\n", " } else {\n", " this.type = src;\n", " } // Put explicitly provided properties onto the event object\n", "\n", "\n", " if (props) {\n", " jQuery.extend(this, props);\n", " } // Create a timestamp if incoming event doesn't have one\n", "\n", "\n", " this.timeStamp = src && src.timeStamp || Date.now(); // Mark it as fixed\n", "\n", " this[jQuery.expando] = true;\n", " }; // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding\n", " // https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html\n", "\n", "\n", " jQuery.Event.prototype = {\n", " constructor: jQuery.Event,\n", " isDefaultPrevented: returnFalse,\n", " isPropagationStopped: returnFalse,\n", " isImmediatePropagationStopped: returnFalse,\n", " isSimulated: false,\n", " preventDefault: function () {\n", " var e = this.originalEvent;\n", " this.isDefaultPrevented = returnTrue;\n", "\n", " if (e && !this.isSimulated) {\n", " e.preventDefault();\n", " }\n", " },\n", " stopPropagation: function () {\n", " var e = this.originalEvent;\n", " this.isPropagationStopped = returnTrue;\n", "\n", " if (e && !this.isSimulated) {\n", " e.stopPropagation();\n", " }\n", " },\n", " stopImmediatePropagation: function () {\n", " var e = this.originalEvent;\n", " this.isImmediatePropagationStopped = returnTrue;\n", "\n", " if (e && !this.isSimulated) {\n", " e.stopImmediatePropagation();\n", " }\n", "\n", " this.stopPropagation();\n", " }\n", " }; // Includes all common event props including KeyEvent and MouseEvent specific props\n", "\n", " jQuery.each({\n", " altKey: true,\n", " bubbles: true,\n", " cancelable: true,\n", " changedTouches: true,\n", " ctrlKey: true,\n", " detail: true,\n", " eventPhase: true,\n", " metaKey: true,\n", " pageX: true,\n", " pageY: true,\n", " shiftKey: true,\n", " view: true,\n", " \"char\": true,\n", " charCode: true,\n", " key: true,\n", " keyCode: true,\n", " button: true,\n", " buttons: true,\n", " clientX: true,\n", " clientY: true,\n", " offsetX: true,\n", " offsetY: true,\n", " pointerId: true,\n", " pointerType: true,\n", " screenX: true,\n", " screenY: true,\n", " targetTouches: true,\n", " toElement: true,\n", " touches: true,\n", " which: function (event) {\n", " var button = event.button; // Add which for key events\n", "\n", " if (event.which == null && rkeyEvent.test(event.type)) {\n", " return event.charCode != null ? event.charCode : event.keyCode;\n", " } // Add which for click: 1 === left; 2 === middle; 3 === right\n", "\n", "\n", " if (!event.which && button !== undefined && rmouseEvent.test(event.type)) {\n", " if (button & 1) {\n", " return 1;\n", " }\n", "\n", " if (button & 2) {\n", " return 3;\n", " }\n", "\n", " if (button & 4) {\n", " return 2;\n", " }\n", "\n", " return 0;\n", " }\n", "\n", " return event.which;\n", " }\n", " }, jQuery.event.addProp); // Create mouseenter/leave events using mouseover/out and event-time checks\n", " // so that event delegation works in jQuery.\n", " // Do the same for pointerenter/pointerleave and pointerover/pointerout\n", " //\n", " // Support: Safari 7 only\n", " // Safari sends mouseenter too often; see:\n", " // https://bugs.chromium.org/p/chromium/issues/detail?id=470258\n", " // for the description of the bug (it existed in older Chrome versions as well).\n", "\n", " jQuery.each({\n", " mouseenter: \"mouseover\",\n", " mouseleave: \"mouseout\",\n", " pointerenter: \"pointerover\",\n", " pointerleave: \"pointerout\"\n", " }, function (orig, fix) {\n", " jQuery.event.special[orig] = {\n", " delegateType: fix,\n", " bindType: fix,\n", " handle: function (event) {\n", " var ret,\n", " target = this,\n", " related = event.relatedTarget,\n", " handleObj = event.handleObj; // For mouseenter/leave call the handler if related is outside the target.\n", " // NB: No relatedTarget if the mouse left/entered the browser window\n", "\n", " if (!related || related !== target && !jQuery.contains(target, related)) {\n", " event.type = handleObj.origType;\n", " ret = handleObj.handler.apply(this, arguments);\n", " event.type = fix;\n", " }\n", "\n", " return ret;\n", " }\n", " };\n", " });\n", " jQuery.fn.extend({\n", " on: function (types, selector, data, fn) {\n", " return on(this, types, selector, data, fn);\n", " },\n", " one: function (types, selector, data, fn) {\n", " return on(this, types, selector, data, fn, 1);\n", " },\n", " off: function (types, selector, fn) {\n", " var handleObj, type;\n", "\n", " if (types && types.preventDefault && types.handleObj) {\n", " // ( event ) dispatched jQuery.Event\n", " handleObj = types.handleObj;\n", " jQuery(types.delegateTarget).off(handleObj.namespace ? handleObj.origType + \".\" + handleObj.namespace : handleObj.origType, handleObj.selector, handleObj.handler);\n", " return this;\n", " }\n", "\n", " if (typeof types === \"object\") {\n", " // ( types-object [, selector] )\n", " for (type in types) {\n", " this.off(type, selector, types[type]);\n", " }\n", "\n", " return this;\n", " }\n", "\n", " if (selector === false || typeof selector === \"function\") {\n", " // ( types [, fn] )\n", " fn = selector;\n", " selector = undefined;\n", " }\n", "\n", " if (fn === false) {\n", " fn = returnFalse;\n", " }\n", "\n", " return this.each(function () {\n", " jQuery.event.remove(this, types, fn, selector);\n", " });\n", " }\n", " });\n", " var\n", " /* eslint-disable max-len */\n", " // See https://github.com/eslint/eslint/issues/3229\n", " rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\\/\\0>\\x20\\t\\r\\n\\f]*)[^>]*)\\/>/gi,\n", "\n", " /* eslint-enable */\n", " // Support: IE <=10 - 11, Edge 12 - 13 only\n", " // In IE/Edge using regex groups here causes severe slowdowns.\n", " // See https://connect.microsoft.com/IE/feedback/details/1736512/\n", " rnoInnerhtml = /\\s*$/g; // Prefer a tbody over its parent table for containing new rows\n", "\n", " function manipulationTarget(elem, content) {\n", " if (nodeName(elem, \"table\") && nodeName(content.nodeType !== 11 ? content : content.firstChild, \"tr\")) {\n", " return jQuery(elem).children(\"tbody\")[0] || elem;\n", " }\n", "\n", " return elem;\n", " } // Replace/restore the type attribute of script elements for safe DOM manipulation\n", "\n", "\n", " function disableScript(elem) {\n", " elem.type = (elem.getAttribute(\"type\") !== null) + \"/\" + elem.type;\n", " return elem;\n", " }\n", "\n", " function restoreScript(elem) {\n", " if ((elem.type || \"\").slice(0, 5) === \"true/\") {\n", " elem.type = elem.type.slice(5);\n", " } else {\n", " elem.removeAttribute(\"type\");\n", " }\n", "\n", " return elem;\n", " }\n", "\n", " function cloneCopyEvent(src, dest) {\n", " var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events;\n", "\n", " if (dest.nodeType !== 1) {\n", " return;\n", " } // 1. Copy private data: events, handlers, etc.\n", "\n", "\n", " if (dataPriv.hasData(src)) {\n", " pdataOld = dataPriv.access(src);\n", " pdataCur = dataPriv.set(dest, pdataOld);\n", " events = pdataOld.events;\n", "\n", " if (events) {\n", " delete pdataCur.handle;\n", " pdataCur.events = {};\n", "\n", " for (type in events) {\n", " for (i = 0, l = events[type].length; i < l; i++) {\n", " jQuery.event.add(dest, type, events[type][i]);\n", " }\n", " }\n", " }\n", " } // 2. Copy user data\n", "\n", "\n", " if (dataUser.hasData(src)) {\n", " udataOld = dataUser.access(src);\n", " udataCur = jQuery.extend({}, udataOld);\n", " dataUser.set(dest, udataCur);\n", " }\n", " } // Fix IE bugs, see support tests\n", "\n", "\n", " function fixInput(src, dest) {\n", " var nodeName = dest.nodeName.toLowerCase(); // Fails to persist the checked state of a cloned checkbox or radio button.\n", "\n", " if (nodeName === \"input\" && rcheckableType.test(src.type)) {\n", " dest.checked = src.checked; // Fails to return the selected option to the default selected state when cloning options\n", " } else if (nodeName === \"input\" || nodeName === \"textarea\") {\n", " dest.defaultValue = src.defaultValue;\n", " }\n", " }\n", "\n", " function domManip(collection, args, callback, ignored) {\n", " // Flatten any nested arrays\n", " args = concat.apply([], args);\n", " var fragment,\n", " first,\n", " scripts,\n", " hasScripts,\n", " node,\n", " doc,\n", " i = 0,\n", " l = collection.length,\n", " iNoClone = l - 1,\n", " value = args[0],\n", " valueIsFunction = isFunction(value); // We can't cloneNode fragments that contain checked, in WebKit\n", "\n", " if (valueIsFunction || l > 1 && typeof value === \"string\" && !support.checkClone && rchecked.test(value)) {\n", " return collection.each(function (index) {\n", " var self = collection.eq(index);\n", "\n", " if (valueIsFunction) {\n", " args[0] = value.call(this, index, self.html());\n", " }\n", "\n", " domManip(self, args, callback, ignored);\n", " });\n", " }\n", "\n", " if (l) {\n", " fragment = buildFragment(args, collection[0].ownerDocument, false, collection, ignored);\n", " first = fragment.firstChild;\n", "\n", " if (fragment.childNodes.length === 1) {\n", " fragment = first;\n", " } // Require either new content or an interest in ignored elements to invoke the callback\n", "\n", "\n", " if (first || ignored) {\n", " scripts = jQuery.map(getAll(fragment, \"script\"), disableScript);\n", " hasScripts = scripts.length; // Use the original fragment for the last item\n", " // instead of the first because it can end up\n", " // being emptied incorrectly in certain situations (#8070).\n", "\n", " for (; i < l; i++) {\n", " node = fragment;\n", "\n", " if (i !== iNoClone) {\n", " node = jQuery.clone(node, true, true); // Keep references to cloned scripts for later restoration\n", "\n", " if (hasScripts) {\n", " // Support: Android <=4.0 only, PhantomJS 1 only\n", " // push.apply(_, arraylike) throws on ancient WebKit\n", " jQuery.merge(scripts, getAll(node, \"script\"));\n", " }\n", " }\n", "\n", " callback.call(collection[i], node, i);\n", " }\n", "\n", " if (hasScripts) {\n", " doc = scripts[scripts.length - 1].ownerDocument; // Reenable scripts\n", "\n", " jQuery.map(scripts, restoreScript); // Evaluate executable scripts on first document insertion\n", "\n", " for (i = 0; i < hasScripts; i++) {\n", " node = scripts[i];\n", "\n", " if (rscriptType.test(node.type || \"\") && !dataPriv.access(node, \"globalEval\") && jQuery.contains(doc, node)) {\n", " if (node.src && (node.type || \"\").toLowerCase() !== \"module\") {\n", " // Optional AJAX dependency, but won't run scripts if not present\n", " if (jQuery._evalUrl) {\n", " jQuery._evalUrl(node.src);\n", " }\n", " } else {\n", " DOMEval(node.textContent.replace(rcleanScript, \"\"), doc, node);\n", " }\n", " }\n", " }\n", " }\n", " }\n", " }\n", "\n", " return collection;\n", " }\n", "\n", " function remove(elem, selector, keepData) {\n", " var node,\n", " nodes = selector ? jQuery.filter(selector, elem) : elem,\n", " i = 0;\n", "\n", " for (; (node = nodes[i]) != null; i++) {\n", " if (!keepData && node.nodeType === 1) {\n", " jQuery.cleanData(getAll(node));\n", " }\n", "\n", " if (node.parentNode) {\n", " if (keepData && jQuery.contains(node.ownerDocument, node)) {\n", " setGlobalEval(getAll(node, \"script\"));\n", " }\n", "\n", " node.parentNode.removeChild(node);\n", " }\n", " }\n", "\n", " return elem;\n", " }\n", "\n", " jQuery.extend({\n", " htmlPrefilter: function (html) {\n", " return html.replace(rxhtmlTag, \"<$1>\");\n", " },\n", " clone: function (elem, dataAndEvents, deepDataAndEvents) {\n", " var i,\n", " l,\n", " srcElements,\n", " destElements,\n", " clone = elem.cloneNode(true),\n", " inPage = jQuery.contains(elem.ownerDocument, elem); // Fix IE cloning issues\n", "\n", " if (!support.noCloneChecked && (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem)) {\n", " // We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2\n", " destElements = getAll(clone);\n", " srcElements = getAll(elem);\n", "\n", " for (i = 0, l = srcElements.length; i < l; i++) {\n", " fixInput(srcElements[i], destElements[i]);\n", " }\n", " } // Copy the events from the original to the clone\n", "\n", "\n", " if (dataAndEvents) {\n", " if (deepDataAndEvents) {\n", " srcElements = srcElements || getAll(elem);\n", " destElements = destElements || getAll(clone);\n", "\n", " for (i = 0, l = srcElements.length; i < l; i++) {\n", " cloneCopyEvent(srcElements[i], destElements[i]);\n", " }\n", " } else {\n", " cloneCopyEvent(elem, clone);\n", " }\n", " } // Preserve script evaluation history\n", "\n", "\n", " destElements = getAll(clone, \"script\");\n", "\n", " if (destElements.length > 0) {\n", " setGlobalEval(destElements, !inPage && getAll(elem, \"script\"));\n", " } // Return the cloned set\n", "\n", "\n", " return clone;\n", " },\n", " cleanData: function (elems) {\n", " var data,\n", " elem,\n", " type,\n", " special = jQuery.event.special,\n", " i = 0;\n", "\n", " for (; (elem = elems[i]) !== undefined; i++) {\n", " if (acceptData(elem)) {\n", " if (data = elem[dataPriv.expando]) {\n", " if (data.events) {\n", " for (type in data.events) {\n", " if (special[type]) {\n", " jQuery.event.remove(elem, type); // This is a shortcut to avoid jQuery.event.remove's overhead\n", " } else {\n", " jQuery.removeEvent(elem, type, data.handle);\n", " }\n", " }\n", " } // Support: Chrome <=35 - 45+\n", " // Assign undefined instead of using delete, see Data#remove\n", "\n", "\n", " elem[dataPriv.expando] = undefined;\n", " }\n", "\n", " if (elem[dataUser.expando]) {\n", " // Support: Chrome <=35 - 45+\n", " // Assign undefined instead of using delete, see Data#remove\n", " elem[dataUser.expando] = undefined;\n", " }\n", " }\n", " }\n", " }\n", " });\n", " jQuery.fn.extend({\n", " detach: function (selector) {\n", " return remove(this, selector, true);\n", " },\n", " remove: function (selector) {\n", " return remove(this, selector);\n", " },\n", " text: function (value) {\n", " return access(this, function (value) {\n", " return value === undefined ? jQuery.text(this) : this.empty().each(function () {\n", " if (this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9) {\n", " this.textContent = value;\n", " }\n", " });\n", " }, null, value, arguments.length);\n", " },\n", " append: function () {\n", " return domManip(this, arguments, function (elem) {\n", " if (this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9) {\n", " var target = manipulationTarget(this, elem);\n", " target.appendChild(elem);\n", " }\n", " });\n", " },\n", " prepend: function () {\n", " return domManip(this, arguments, function (elem) {\n", " if (this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9) {\n", " var target = manipulationTarget(this, elem);\n", " target.insertBefore(elem, target.firstChild);\n", " }\n", " });\n", " },\n", " before: function () {\n", " return domManip(this, arguments, function (elem) {\n", " if (this.parentNode) {\n", " this.parentNode.insertBefore(elem, this);\n", " }\n", " });\n", " },\n", " after: function () {\n", " return domManip(this, arguments, function (elem) {\n", " if (this.parentNode) {\n", " this.parentNode.insertBefore(elem, this.nextSibling);\n", " }\n", " });\n", " },\n", " empty: function () {\n", " var elem,\n", " i = 0;\n", "\n", " for (; (elem = this[i]) != null; i++) {\n", " if (elem.nodeType === 1) {\n", " // Prevent memory leaks\n", " jQuery.cleanData(getAll(elem, false)); // Remove any remaining nodes\n", "\n", " elem.textContent = \"\";\n", " }\n", " }\n", "\n", " return this;\n", " },\n", " clone: function (dataAndEvents, deepDataAndEvents) {\n", " dataAndEvents = dataAndEvents == null ? false : dataAndEvents;\n", " deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;\n", " return this.map(function () {\n", " return jQuery.clone(this, dataAndEvents, deepDataAndEvents);\n", " });\n", " },\n", " html: function (value) {\n", " return access(this, function (value) {\n", " var elem = this[0] || {},\n", " i = 0,\n", " l = this.length;\n", "\n", " if (value === undefined && elem.nodeType === 1) {\n", " return elem.innerHTML;\n", " } // See if we can take a shortcut and just use innerHTML\n", "\n", "\n", " if (typeof value === \"string\" && !rnoInnerhtml.test(value) && !wrapMap[(rtagName.exec(value) || [\"\", \"\"])[1].toLowerCase()]) {\n", " value = jQuery.htmlPrefilter(value);\n", "\n", " try {\n", " for (; i < l; i++) {\n", " elem = this[i] || {}; // Remove element nodes and prevent memory leaks\n", "\n", " if (elem.nodeType === 1) {\n", " jQuery.cleanData(getAll(elem, false));\n", " elem.innerHTML = value;\n", " }\n", " }\n", "\n", " elem = 0; // If using innerHTML throws an exception, use the fallback method\n", " } catch (e) {}\n", " }\n", "\n", " if (elem) {\n", " this.empty().append(value);\n", " }\n", " }, null, value, arguments.length);\n", " },\n", " replaceWith: function () {\n", " var ignored = []; // Make the changes, replacing each non-ignored context element with the new content\n", "\n", " return domManip(this, arguments, function (elem) {\n", " var parent = this.parentNode;\n", "\n", " if (jQuery.inArray(this, ignored) < 0) {\n", " jQuery.cleanData(getAll(this));\n", "\n", " if (parent) {\n", " parent.replaceChild(elem, this);\n", " }\n", " } // Force callback invocation\n", "\n", " }, ignored);\n", " }\n", " });\n", " jQuery.each({\n", " appendTo: \"append\",\n", " prependTo: \"prepend\",\n", " insertBefore: \"before\",\n", " insertAfter: \"after\",\n", " replaceAll: \"replaceWith\"\n", " }, function (name, original) {\n", " jQuery.fn[name] = function (selector) {\n", " var elems,\n", " ret = [],\n", " insert = jQuery(selector),\n", " last = insert.length - 1,\n", " i = 0;\n", "\n", " for (; i <= last; i++) {\n", " elems = i === last ? this : this.clone(true);\n", " jQuery(insert[i])[original](elems); // Support: Android <=4.0 only, PhantomJS 1 only\n", " // .get() because push.apply(_, arraylike) throws on ancient WebKit\n", "\n", " push.apply(ret, elems.get());\n", " }\n", "\n", " return this.pushStack(ret);\n", " };\n", " });\n", " var rnumnonpx = new RegExp(\"^(\" + pnum + \")(?!px)[a-z%]+$\", \"i\");\n", "\n", " var getStyles = function (elem) {\n", " // Support: IE <=11 only, Firefox <=30 (#15098, #14150)\n", " // IE throws on elements created in popups\n", " // FF meanwhile throws on frame elements through \"defaultView.getComputedStyle\"\n", " var view = elem.ownerDocument.defaultView;\n", "\n", " if (!view || !view.opener) {\n", " view = window;\n", " }\n", "\n", " return view.getComputedStyle(elem);\n", " };\n", "\n", " var rboxStyle = new RegExp(cssExpand.join(\"|\"), \"i\");\n", "\n", " (function () {\n", " // Executing both pixelPosition & boxSizingReliable tests require only one layout\n", " // so they're executed at the same time to save the second computation.\n", " function computeStyleTests() {\n", " // This is a singleton, we need to execute it only once\n", " if (!div) {\n", " return;\n", " }\n", "\n", " container.style.cssText = \"position:absolute;left:-11111px;width:60px;\" + \"margin-top:1px;padding:0;border:0\";\n", " div.style.cssText = \"position:relative;display:block;box-sizing:border-box;overflow:scroll;\" + \"margin:auto;border:1px;padding:1px;\" + \"width:60%;top:1%\";\n", " documentElement.appendChild(container).appendChild(div);\n", " var divStyle = window.getComputedStyle(div);\n", " pixelPositionVal = divStyle.top !== \"1%\"; // Support: Android 4.0 - 4.3 only, Firefox <=3 - 44\n", "\n", " reliableMarginLeftVal = roundPixelMeasures(divStyle.marginLeft) === 12; // Support: Android 4.0 - 4.3 only, Safari <=9.1 - 10.1, iOS <=7.0 - 9.3\n", " // Some styles come back with percentage values, even though they shouldn't\n", "\n", " div.style.right = \"60%\";\n", " pixelBoxStylesVal = roundPixelMeasures(divStyle.right) === 36; // Support: IE 9 - 11 only\n", " // Detect misreporting of content dimensions for box-sizing:border-box elements\n", "\n", " boxSizingReliableVal = roundPixelMeasures(divStyle.width) === 36; // Support: IE 9 only\n", " // Detect overflow:scroll screwiness (gh-3699)\n", "\n", " div.style.position = \"absolute\";\n", " scrollboxSizeVal = div.offsetWidth === 36 || \"absolute\";\n", " documentElement.removeChild(container); // Nullify the div so it wouldn't be stored in the memory and\n", " // it will also be a sign that checks already performed\n", "\n", " div = null;\n", " }\n", "\n", " function roundPixelMeasures(measure) {\n", " return Math.round(parseFloat(measure));\n", " }\n", "\n", " var pixelPositionVal,\n", " boxSizingReliableVal,\n", " scrollboxSizeVal,\n", " pixelBoxStylesVal,\n", " reliableMarginLeftVal,\n", " container = document$2.createElement(\"div\"),\n", " div = document$2.createElement(\"div\"); // Finish early in limited (non-browser) environments\n", "\n", " if (!div.style) {\n", " return;\n", " } // Support: IE <=9 - 11 only\n", " // Style of cloned element affects source element cloned (#8908)\n", "\n", "\n", " div.style.backgroundClip = \"content-box\";\n", " div.cloneNode(true).style.backgroundClip = \"\";\n", " support.clearCloneStyle = div.style.backgroundClip === \"content-box\";\n", " jQuery.extend(support, {\n", " boxSizingReliable: function () {\n", " computeStyleTests();\n", " return boxSizingReliableVal;\n", " },\n", " pixelBoxStyles: function () {\n", " computeStyleTests();\n", " return pixelBoxStylesVal;\n", " },\n", " pixelPosition: function () {\n", " computeStyleTests();\n", " return pixelPositionVal;\n", " },\n", " reliableMarginLeft: function () {\n", " computeStyleTests();\n", " return reliableMarginLeftVal;\n", " },\n", " scrollboxSize: function () {\n", " computeStyleTests();\n", " return scrollboxSizeVal;\n", " }\n", " });\n", " })();\n", "\n", " function curCSS(elem, name, computed) {\n", " var width,\n", " minWidth,\n", " maxWidth,\n", " ret,\n", " // Support: Firefox 51+\n", " // Retrieving style before computed somehow\n", " // fixes an issue with getting wrong values\n", " // on detached elements\n", " style = elem.style;\n", " computed = computed || getStyles(elem); // getPropertyValue is needed for:\n", " // .css('filter') (IE 9 only, #12537)\n", " // .css('--customProperty) (#3144)\n", "\n", " if (computed) {\n", " ret = computed.getPropertyValue(name) || computed[name];\n", "\n", " if (ret === \"\" && !jQuery.contains(elem.ownerDocument, elem)) {\n", " ret = jQuery.style(elem, name);\n", " } // A tribute to the \"awesome hack by Dean Edwards\"\n", " // Android Browser returns percentage for some values,\n", " // but width seems to be reliably pixels.\n", " // This is against the CSSOM draft spec:\n", " // https://drafts.csswg.org/cssom/#resolved-values\n", "\n", "\n", " if (!support.pixelBoxStyles() && rnumnonpx.test(ret) && rboxStyle.test(name)) {\n", " // Remember the original values\n", " width = style.width;\n", " minWidth = style.minWidth;\n", " maxWidth = style.maxWidth; // Put in the new values to get a computed value out\n", "\n", " style.minWidth = style.maxWidth = style.width = ret;\n", " ret = computed.width; // Revert the changed values\n", "\n", " style.width = width;\n", " style.minWidth = minWidth;\n", " style.maxWidth = maxWidth;\n", " }\n", " }\n", "\n", " return ret !== undefined ? // Support: IE <=9 - 11 only\n", " // IE returns zIndex value as an integer.\n", " ret + \"\" : ret;\n", " }\n", "\n", " function addGetHookIf(conditionFn, hookFn) {\n", " // Define the hook, we'll check on the first run if it's really needed.\n", " return {\n", " get: function () {\n", " if (conditionFn()) {\n", " // Hook not needed (or it's not possible to use it due\n", " // to missing dependency), remove it.\n", " delete this.get;\n", " return;\n", " } // Hook needed; redefine it so that the support test is not executed again.\n", "\n", "\n", " return (this.get = hookFn).apply(this, arguments);\n", " }\n", " };\n", " }\n", "\n", " var // Swappable if display is none or starts with table\n", " // except \"table\", \"table-cell\", or \"table-caption\"\n", " // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display\n", " rdisplayswap = /^(none|table(?!-c[ea]).+)/,\n", " rcustomProp = /^--/,\n", " cssShow = {\n", " position: \"absolute\",\n", " visibility: \"hidden\",\n", " display: \"block\"\n", " },\n", " cssNormalTransform = {\n", " letterSpacing: \"0\",\n", " fontWeight: \"400\"\n", " },\n", " cssPrefixes = [\"Webkit\", \"Moz\", \"ms\"],\n", " emptyStyle = document$2.createElement(\"div\").style; // Return a css property mapped to a potentially vendor prefixed property\n", "\n", " function vendorPropName(name) {\n", " // Shortcut for names that are not vendor prefixed\n", " if (name in emptyStyle) {\n", " return name;\n", " } // Check for vendor prefixed names\n", "\n", "\n", " var capName = name[0].toUpperCase() + name.slice(1),\n", " i = cssPrefixes.length;\n", "\n", " while (i--) {\n", " name = cssPrefixes[i] + capName;\n", "\n", " if (name in emptyStyle) {\n", " return name;\n", " }\n", " }\n", " } // Return a property mapped along what jQuery.cssProps suggests or to\n", " // a vendor prefixed property.\n", "\n", "\n", " function finalPropName(name) {\n", " var ret = jQuery.cssProps[name];\n", "\n", " if (!ret) {\n", " ret = jQuery.cssProps[name] = vendorPropName(name) || name;\n", " }\n", "\n", " return ret;\n", " }\n", "\n", " function setPositiveNumber(elem, value, subtract) {\n", " // Any relative (+/-) values have already been\n", " // normalized at this point\n", " var matches = rcssNum.exec(value);\n", " return matches ? // Guard against undefined \"subtract\", e.g., when used as in cssHooks\n", " Math.max(0, matches[2] - (subtract || 0)) + (matches[3] || \"px\") : value;\n", " }\n", "\n", " function boxModelAdjustment(elem, dimension, box, isBorderBox, styles, computedVal) {\n", " var i = dimension === \"width\" ? 1 : 0,\n", " extra = 0,\n", " delta = 0; // Adjustment may not be necessary\n", "\n", " if (box === (isBorderBox ? \"border\" : \"content\")) {\n", " return 0;\n", " }\n", "\n", " for (; i < 4; i += 2) {\n", " // Both box models exclude margin\n", " if (box === \"margin\") {\n", " delta += jQuery.css(elem, box + cssExpand[i], true, styles);\n", " } // If we get here with a content-box, we're seeking \"padding\" or \"border\" or \"margin\"\n", "\n", "\n", " if (!isBorderBox) {\n", " // Add padding\n", " delta += jQuery.css(elem, \"padding\" + cssExpand[i], true, styles); // For \"border\" or \"margin\", add border\n", "\n", " if (box !== \"padding\") {\n", " delta += jQuery.css(elem, \"border\" + cssExpand[i] + \"Width\", true, styles); // But still keep track of it otherwise\n", " } else {\n", " extra += jQuery.css(elem, \"border\" + cssExpand[i] + \"Width\", true, styles);\n", " } // If we get here with a border-box (content + padding + border), we're seeking \"content\" or\n", " // \"padding\" or \"margin\"\n", "\n", " } else {\n", " // For \"content\", subtract padding\n", " if (box === \"content\") {\n", " delta -= jQuery.css(elem, \"padding\" + cssExpand[i], true, styles);\n", " } // For \"content\" or \"padding\", subtract border\n", "\n", "\n", " if (box !== \"margin\") {\n", " delta -= jQuery.css(elem, \"border\" + cssExpand[i] + \"Width\", true, styles);\n", " }\n", " }\n", " } // Account for positive content-box scroll gutter when requested by providing computedVal\n", "\n", "\n", " if (!isBorderBox && computedVal >= 0) {\n", " // offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border\n", " // Assuming integer scroll gutter, subtract the rest and round down\n", " delta += Math.max(0, Math.ceil(elem[\"offset\" + dimension[0].toUpperCase() + dimension.slice(1)] - computedVal - delta - extra - 0.5));\n", " }\n", "\n", " return delta;\n", " }\n", "\n", " function getWidthOrHeight(elem, dimension, extra) {\n", " // Start with computed style\n", " var styles = getStyles(elem),\n", " val = curCSS(elem, dimension, styles),\n", " isBorderBox = jQuery.css(elem, \"boxSizing\", false, styles) === \"border-box\",\n", " valueIsBorderBox = isBorderBox; // Support: Firefox <=54\n", " // Return a confounding non-pixel value or feign ignorance, as appropriate.\n", "\n", " if (rnumnonpx.test(val)) {\n", " if (!extra) {\n", " return val;\n", " }\n", "\n", " val = \"auto\";\n", " } // Check for style in case a browser which returns unreliable values\n", " // for getComputedStyle silently falls back to the reliable elem.style\n", "\n", "\n", " valueIsBorderBox = valueIsBorderBox && (support.boxSizingReliable() || val === elem.style[dimension]); // Fall back to offsetWidth/offsetHeight when value is \"auto\"\n", " // This happens for inline elements with no explicit setting (gh-3571)\n", " // Support: Android <=4.1 - 4.3 only\n", " // Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602)\n", "\n", " if (val === \"auto\" || !parseFloat(val) && jQuery.css(elem, \"display\", false, styles) === \"inline\") {\n", " val = elem[\"offset\" + dimension[0].toUpperCase() + dimension.slice(1)]; // offsetWidth/offsetHeight provide border-box values\n", "\n", " valueIsBorderBox = true;\n", " } // Normalize \"\" and auto\n", "\n", "\n", " val = parseFloat(val) || 0; // Adjust for the element's box model\n", "\n", " return val + boxModelAdjustment(elem, dimension, extra || (isBorderBox ? \"border\" : \"content\"), valueIsBorderBox, styles, // Provide the current computed size to request scroll gutter calculation (gh-3589)\n", " val) + \"px\";\n", " }\n", "\n", " jQuery.extend({\n", " // Add in style property hooks for overriding the default\n", " // behavior of getting and setting a style property\n", " cssHooks: {\n", " opacity: {\n", " get: function (elem, computed) {\n", " if (computed) {\n", " // We should always get a number back from opacity\n", " var ret = curCSS(elem, \"opacity\");\n", " return ret === \"\" ? \"1\" : ret;\n", " }\n", " }\n", " }\n", " },\n", " // Don't automatically add \"px\" to these possibly-unitless properties\n", " cssNumber: {\n", " \"animationIterationCount\": true,\n", " \"columnCount\": true,\n", " \"fillOpacity\": true,\n", " \"flexGrow\": true,\n", " \"flexShrink\": true,\n", " \"fontWeight\": true,\n", " \"lineHeight\": true,\n", " \"opacity\": true,\n", " \"order\": true,\n", " \"orphans\": true,\n", " \"widows\": true,\n", " \"zIndex\": true,\n", " \"zoom\": true\n", " },\n", " // Add in properties whose names you wish to fix before\n", " // setting or getting the value\n", " cssProps: {},\n", " // Get and set the style property on a DOM Node\n", " style: function (elem, name, value, extra) {\n", " // Don't set styles on text and comment nodes\n", " if (!elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style) {\n", " return;\n", " } // Make sure that we're working with the right name\n", "\n", "\n", " var ret,\n", " type,\n", " hooks,\n", " origName = camelCase(name),\n", " isCustomProp = rcustomProp.test(name),\n", " style = elem.style; // Make sure that we're working with the right name. We don't\n", " // want to query the value if it is a CSS custom property\n", " // since they are user-defined.\n", "\n", " if (!isCustomProp) {\n", " name = finalPropName(origName);\n", " } // Gets hook for the prefixed version, then unprefixed version\n", "\n", "\n", " hooks = jQuery.cssHooks[name] || jQuery.cssHooks[origName]; // Check if we're setting a value\n", "\n", " if (value !== undefined) {\n", " type = typeof value; // Convert \"+=\" or \"-=\" to relative numbers (#7345)\n", "\n", " if (type === \"string\" && (ret = rcssNum.exec(value)) && ret[1]) {\n", " value = adjustCSS(elem, name, ret); // Fixes bug #9237\n", "\n", " type = \"number\";\n", " } // Make sure that null and NaN values aren't set (#7116)\n", "\n", "\n", " if (value == null || value !== value) {\n", " return;\n", " } // If a number was passed in, add the unit (except for certain CSS properties)\n", "\n", "\n", " if (type === \"number\") {\n", " value += ret && ret[3] || (jQuery.cssNumber[origName] ? \"\" : \"px\");\n", " } // background-* props affect original clone's values\n", "\n", "\n", " if (!support.clearCloneStyle && value === \"\" && name.indexOf(\"background\") === 0) {\n", " style[name] = \"inherit\";\n", " } // If a hook was provided, use that value, otherwise just set the specified value\n", "\n", "\n", " if (!hooks || !(\"set\" in hooks) || (value = hooks.set(elem, value, extra)) !== undefined) {\n", " if (isCustomProp) {\n", " style.setProperty(name, value);\n", " } else {\n", " style[name] = value;\n", " }\n", " }\n", " } else {\n", " // If a hook was provided get the non-computed value from there\n", " if (hooks && \"get\" in hooks && (ret = hooks.get(elem, false, extra)) !== undefined) {\n", " return ret;\n", " } // Otherwise just get the value from the style object\n", "\n", "\n", " return style[name];\n", " }\n", " },\n", " css: function (elem, name, extra, styles) {\n", " var val,\n", " num,\n", " hooks,\n", " origName = camelCase(name),\n", " isCustomProp = rcustomProp.test(name); // Make sure that we're working with the right name. We don't\n", " // want to modify the value if it is a CSS custom property\n", " // since they are user-defined.\n", "\n", " if (!isCustomProp) {\n", " name = finalPropName(origName);\n", " } // Try prefixed name followed by the unprefixed name\n", "\n", "\n", " hooks = jQuery.cssHooks[name] || jQuery.cssHooks[origName]; // If a hook was provided get the computed value from there\n", "\n", " if (hooks && \"get\" in hooks) {\n", " val = hooks.get(elem, true, extra);\n", " } // Otherwise, if a way to get the computed value exists, use that\n", "\n", "\n", " if (val === undefined) {\n", " val = curCSS(elem, name, styles);\n", " } // Convert \"normal\" to computed value\n", "\n", "\n", " if (val === \"normal\" && name in cssNormalTransform) {\n", " val = cssNormalTransform[name];\n", " } // Make numeric if forced or a qualifier was provided and val looks numeric\n", "\n", "\n", " if (extra === \"\" || extra) {\n", " num = parseFloat(val);\n", " return extra === true || isFinite(num) ? num || 0 : val;\n", " }\n", "\n", " return val;\n", " }\n", " });\n", " jQuery.each([\"height\", \"width\"], function (i, dimension) {\n", " jQuery.cssHooks[dimension] = {\n", " get: function (elem, computed, extra) {\n", " if (computed) {\n", " // Certain elements can have dimension info if we invisibly show them\n", " // but it must have a current display style that would benefit\n", " return rdisplayswap.test(jQuery.css(elem, \"display\")) && ( // Support: Safari 8+\n", " // Table columns in Safari have non-zero offsetWidth & zero\n", " // getBoundingClientRect().width unless display is changed.\n", " // Support: IE <=11 only\n", " // Running getBoundingClientRect on a disconnected node\n", " // in IE throws an error.\n", " !elem.getClientRects().length || !elem.getBoundingClientRect().width) ? swap(elem, cssShow, function () {\n", " return getWidthOrHeight(elem, dimension, extra);\n", " }) : getWidthOrHeight(elem, dimension, extra);\n", " }\n", " },\n", " set: function (elem, value, extra) {\n", " var matches,\n", " styles = getStyles(elem),\n", " isBorderBox = jQuery.css(elem, \"boxSizing\", false, styles) === \"border-box\",\n", " subtract = extra && boxModelAdjustment(elem, dimension, extra, isBorderBox, styles); // Account for unreliable border-box dimensions by comparing offset* to computed and\n", " // faking a content-box to get border and padding (gh-3699)\n", "\n", " if (isBorderBox && support.scrollboxSize() === styles.position) {\n", " subtract -= Math.ceil(elem[\"offset\" + dimension[0].toUpperCase() + dimension.slice(1)] - parseFloat(styles[dimension]) - boxModelAdjustment(elem, dimension, \"border\", false, styles) - 0.5);\n", " } // Convert to pixels if value adjustment is needed\n", "\n", "\n", " if (subtract && (matches = rcssNum.exec(value)) && (matches[3] || \"px\") !== \"px\") {\n", " elem.style[dimension] = value;\n", " value = jQuery.css(elem, dimension);\n", " }\n", "\n", " return setPositiveNumber(elem, value, subtract);\n", " }\n", " };\n", " });\n", " jQuery.cssHooks.marginLeft = addGetHookIf(support.reliableMarginLeft, function (elem, computed) {\n", " if (computed) {\n", " return (parseFloat(curCSS(elem, \"marginLeft\")) || elem.getBoundingClientRect().left - swap(elem, {\n", " marginLeft: 0\n", " }, function () {\n", " return elem.getBoundingClientRect().left;\n", " })) + \"px\";\n", " }\n", " }); // These hooks are used by animate to expand properties\n", "\n", " jQuery.each({\n", " margin: \"\",\n", " padding: \"\",\n", " border: \"Width\"\n", " }, function (prefix, suffix) {\n", " jQuery.cssHooks[prefix + suffix] = {\n", " expand: function (value) {\n", " var i = 0,\n", " expanded = {},\n", " // Assumes a single number if not a string\n", " parts = typeof value === \"string\" ? value.split(\" \") : [value];\n", "\n", " for (; i < 4; i++) {\n", " expanded[prefix + cssExpand[i] + suffix] = parts[i] || parts[i - 2] || parts[0];\n", " }\n", "\n", " return expanded;\n", " }\n", " };\n", "\n", " if (prefix !== \"margin\") {\n", " jQuery.cssHooks[prefix + suffix].set = setPositiveNumber;\n", " }\n", " });\n", " jQuery.fn.extend({\n", " css: function (name, value) {\n", " return access(this, function (elem, name, value) {\n", " var styles,\n", " len,\n", " map = {},\n", " i = 0;\n", "\n", " if (Array.isArray(name)) {\n", " styles = getStyles(elem);\n", " len = name.length;\n", "\n", " for (; i < len; i++) {\n", " map[name[i]] = jQuery.css(elem, name[i], false, styles);\n", " }\n", "\n", " return map;\n", " }\n", "\n", " return value !== undefined ? jQuery.style(elem, name, value) : jQuery.css(elem, name);\n", " }, name, value, arguments.length > 1);\n", " }\n", " }); // Based off of the plugin by Clint Helfers, with permission.\n", " // https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/\n", "\n", " jQuery.fn.delay = function (time, type) {\n", " time = jQuery.fx ? jQuery.fx.speeds[time] || time : time;\n", " type = type || \"fx\";\n", " return this.queue(type, function (next, hooks) {\n", " var timeout = window.setTimeout(next, time);\n", "\n", " hooks.stop = function () {\n", " window.clearTimeout(timeout);\n", " };\n", " });\n", " };\n", "\n", " (function () {\n", " var input = document$2.createElement(\"input\"),\n", " select = document$2.createElement(\"select\"),\n", " opt = select.appendChild(document$2.createElement(\"option\"));\n", " input.type = \"checkbox\"; // Support: Android <=4.3 only\n", " // Default value for a checkbox should be \"on\"\n", "\n", " support.checkOn = input.value !== \"\"; // Support: IE <=11 only\n", " // Must access selectedIndex to make default options select\n", "\n", " support.optSelected = opt.selected; // Support: IE <=11 only\n", " // An input loses its value after becoming a radio\n", "\n", " input = document$2.createElement(\"input\");\n", " input.value = \"t\";\n", " input.type = \"radio\";\n", " support.radioValue = input.value === \"t\";\n", " })();\n", "\n", " var boolHook,\n", " attrHandle = jQuery.expr.attrHandle;\n", " jQuery.fn.extend({\n", " attr: function (name, value) {\n", " return access(this, jQuery.attr, name, value, arguments.length > 1);\n", " },\n", " removeAttr: function (name) {\n", " return this.each(function () {\n", " jQuery.removeAttr(this, name);\n", " });\n", " }\n", " });\n", " jQuery.extend({\n", " attr: function (elem, name, value) {\n", " var ret,\n", " hooks,\n", " nType = elem.nodeType; // Don't get/set attributes on text, comment and attribute nodes\n", "\n", " if (nType === 3 || nType === 8 || nType === 2) {\n", " return;\n", " } // Fallback to prop when attributes are not supported\n", "\n", "\n", " if (typeof elem.getAttribute === \"undefined\") {\n", " return jQuery.prop(elem, name, value);\n", " } // Attribute hooks are determined by the lowercase version\n", " // Grab necessary hook if one is defined\n", "\n", "\n", " if (nType !== 1 || !jQuery.isXMLDoc(elem)) {\n", " hooks = jQuery.attrHooks[name.toLowerCase()] || (jQuery.expr.match.bool.test(name) ? boolHook : undefined);\n", " }\n", "\n", " if (value !== undefined) {\n", " if (value === null) {\n", " jQuery.removeAttr(elem, name);\n", " return;\n", " }\n", "\n", " if (hooks && \"set\" in hooks && (ret = hooks.set(elem, value, name)) !== undefined) {\n", " return ret;\n", " }\n", "\n", " elem.setAttribute(name, value + \"\");\n", " return value;\n", " }\n", "\n", " if (hooks && \"get\" in hooks && (ret = hooks.get(elem, name)) !== null) {\n", " return ret;\n", " }\n", "\n", " ret = jQuery.find.attr(elem, name); // Non-existent attributes return null, we normalize to undefined\n", "\n", " return ret == null ? undefined : ret;\n", " },\n", " attrHooks: {\n", " type: {\n", " set: function (elem, value) {\n", " if (!support.radioValue && value === \"radio\" && nodeName(elem, \"input\")) {\n", " var val = elem.value;\n", " elem.setAttribute(\"type\", value);\n", "\n", " if (val) {\n", " elem.value = val;\n", " }\n", "\n", " return value;\n", " }\n", " }\n", " }\n", " },\n", " removeAttr: function (elem, value) {\n", " var name,\n", " i = 0,\n", " // Attribute names can contain non-HTML whitespace characters\n", " // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2\n", " attrNames = value && value.match(rnothtmlwhite);\n", "\n", " if (attrNames && elem.nodeType === 1) {\n", " while (name = attrNames[i++]) {\n", " elem.removeAttribute(name);\n", " }\n", " }\n", " }\n", " }); // Hooks for boolean attributes\n", "\n", " boolHook = {\n", " set: function (elem, value, name) {\n", " if (value === false) {\n", " // Remove boolean attributes when set to false\n", " jQuery.removeAttr(elem, name);\n", " } else {\n", " elem.setAttribute(name, name);\n", " }\n", "\n", " return name;\n", " }\n", " };\n", " jQuery.each(jQuery.expr.match.bool.source.match(/\\w+/g), function (i, name) {\n", " var getter = attrHandle[name] || jQuery.find.attr;\n", "\n", " attrHandle[name] = function (elem, name, isXML) {\n", " var ret,\n", " handle,\n", " lowercaseName = name.toLowerCase();\n", "\n", " if (!isXML) {\n", " // Avoid an infinite loop by temporarily removing this function from the getter\n", " handle = attrHandle[lowercaseName];\n", " attrHandle[lowercaseName] = ret;\n", " ret = getter(elem, name, isXML) != null ? lowercaseName : null;\n", " attrHandle[lowercaseName] = handle;\n", " }\n", "\n", " return ret;\n", " };\n", " });\n", " var rfocusable = /^(?:input|select|textarea|button)$/i,\n", " rclickable = /^(?:a|area)$/i;\n", " jQuery.fn.extend({\n", " prop: function (name, value) {\n", " return access(this, jQuery.prop, name, value, arguments.length > 1);\n", " },\n", " removeProp: function (name) {\n", " return this.each(function () {\n", " delete this[jQuery.propFix[name] || name];\n", " });\n", " }\n", " });\n", " jQuery.extend({\n", " prop: function (elem, name, value) {\n", " var ret,\n", " hooks,\n", " nType = elem.nodeType; // Don't get/set properties on text, comment and attribute nodes\n", "\n", " if (nType === 3 || nType === 8 || nType === 2) {\n", " return;\n", " }\n", "\n", " if (nType !== 1 || !jQuery.isXMLDoc(elem)) {\n", " // Fix name and attach hooks\n", " name = jQuery.propFix[name] || name;\n", " hooks = jQuery.propHooks[name];\n", " }\n", "\n", " if (value !== undefined) {\n", " if (hooks && \"set\" in hooks && (ret = hooks.set(elem, value, name)) !== undefined) {\n", " return ret;\n", " }\n", "\n", " return elem[name] = value;\n", " }\n", "\n", " if (hooks && \"get\" in hooks && (ret = hooks.get(elem, name)) !== null) {\n", " return ret;\n", " }\n", "\n", " return elem[name];\n", " },\n", " propHooks: {\n", " tabIndex: {\n", " get: function (elem) {\n", " // Support: IE <=9 - 11 only\n", " // elem.tabIndex doesn't always return the\n", " // correct value when it hasn't been explicitly set\n", " // https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/\n", " // Use proper attribute retrieval(#12072)\n", " var tabindex = jQuery.find.attr(elem, \"tabindex\");\n", "\n", " if (tabindex) {\n", " return parseInt(tabindex, 10);\n", " }\n", "\n", " if (rfocusable.test(elem.nodeName) || rclickable.test(elem.nodeName) && elem.href) {\n", " return 0;\n", " }\n", "\n", " return -1;\n", " }\n", " }\n", " },\n", " propFix: {\n", " \"for\": \"htmlFor\",\n", " \"class\": \"className\"\n", " }\n", " }); // Support: IE <=11 only\n", " // Accessing the selectedIndex property\n", " // forces the browser to respect setting selected\n", " // on the option\n", " // The getter ensures a default option is selected\n", " // when in an optgroup\n", " // eslint rule \"no-unused-expressions\" is disabled for this code\n", " // since it considers such accessions noop\n", "\n", " if (!support.optSelected) {\n", " jQuery.propHooks.selected = {\n", " get: function (elem) {\n", " /* eslint no-unused-expressions: \"off\" */\n", " var parent = elem.parentNode;\n", "\n", " if (parent && parent.parentNode) {\n", " parent.parentNode.selectedIndex;\n", " }\n", "\n", " return null;\n", " },\n", " set: function (elem) {\n", " /* eslint no-unused-expressions: \"off\" */\n", " var parent = elem.parentNode;\n", "\n", " if (parent) {\n", " parent.selectedIndex;\n", "\n", " if (parent.parentNode) {\n", " parent.parentNode.selectedIndex;\n", " }\n", " }\n", " }\n", " };\n", " }\n", "\n", " jQuery.each([\"tabIndex\", \"readOnly\", \"maxLength\", \"cellSpacing\", \"cellPadding\", \"rowSpan\", \"colSpan\", \"useMap\", \"frameBorder\", \"contentEditable\"], function () {\n", " jQuery.propFix[this.toLowerCase()] = this;\n", " }); // Strip and collapse whitespace according to HTML spec\n", " // https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace\n", "\n", " function stripAndCollapse(value) {\n", " var tokens = value.match(rnothtmlwhite) || [];\n", " return tokens.join(\" \");\n", " }\n", "\n", " function getClass(elem) {\n", " return elem.getAttribute && elem.getAttribute(\"class\") || \"\";\n", " }\n", "\n", " function classesToArray(value) {\n", " if (Array.isArray(value)) {\n", " return value;\n", " }\n", "\n", " if (typeof value === \"string\") {\n", " return value.match(rnothtmlwhite) || [];\n", " }\n", "\n", " return [];\n", " }\n", "\n", " jQuery.fn.extend({\n", " addClass: function (value) {\n", " var classes,\n", " elem,\n", " cur,\n", " curValue,\n", " clazz,\n", " j,\n", " finalValue,\n", " i = 0;\n", "\n", " if (isFunction(value)) {\n", " return this.each(function (j) {\n", " jQuery(this).addClass(value.call(this, j, getClass(this)));\n", " });\n", " }\n", "\n", " classes = classesToArray(value);\n", "\n", " if (classes.length) {\n", " while (elem = this[i++]) {\n", " curValue = getClass(elem);\n", " cur = elem.nodeType === 1 && \" \" + stripAndCollapse(curValue) + \" \";\n", "\n", " if (cur) {\n", " j = 0;\n", "\n", " while (clazz = classes[j++]) {\n", " if (cur.indexOf(\" \" + clazz + \" \") < 0) {\n", " cur += clazz + \" \";\n", " }\n", " } // Only assign if different to avoid unneeded rendering.\n", "\n", "\n", " finalValue = stripAndCollapse(cur);\n", "\n", " if (curValue !== finalValue) {\n", " elem.setAttribute(\"class\", finalValue);\n", " }\n", " }\n", " }\n", " }\n", "\n", " return this;\n", " },\n", " removeClass: function (value) {\n", " var classes,\n", " elem,\n", " cur,\n", " curValue,\n", " clazz,\n", " j,\n", " finalValue,\n", " i = 0;\n", "\n", " if (isFunction(value)) {\n", " return this.each(function (j) {\n", " jQuery(this).removeClass(value.call(this, j, getClass(this)));\n", " });\n", " }\n", "\n", " if (!arguments.length) {\n", " return this.attr(\"class\", \"\");\n", " }\n", "\n", " classes = classesToArray(value);\n", "\n", " if (classes.length) {\n", " while (elem = this[i++]) {\n", " curValue = getClass(elem); // This expression is here for better compressibility (see addClass)\n", "\n", " cur = elem.nodeType === 1 && \" \" + stripAndCollapse(curValue) + \" \";\n", "\n", " if (cur) {\n", " j = 0;\n", "\n", " while (clazz = classes[j++]) {\n", " // Remove *all* instances\n", " while (cur.indexOf(\" \" + clazz + \" \") > -1) {\n", " cur = cur.replace(\" \" + clazz + \" \", \" \");\n", " }\n", " } // Only assign if different to avoid unneeded rendering.\n", "\n", "\n", " finalValue = stripAndCollapse(cur);\n", "\n", " if (curValue !== finalValue) {\n", " elem.setAttribute(\"class\", finalValue);\n", " }\n", " }\n", " }\n", " }\n", "\n", " return this;\n", " },\n", " toggleClass: function (value, stateVal) {\n", " var type = typeof value,\n", " isValidValue = type === \"string\" || Array.isArray(value);\n", "\n", " if (typeof stateVal === \"boolean\" && isValidValue) {\n", " return stateVal ? this.addClass(value) : this.removeClass(value);\n", " }\n", "\n", " if (isFunction(value)) {\n", " return this.each(function (i) {\n", " jQuery(this).toggleClass(value.call(this, i, getClass(this), stateVal), stateVal);\n", " });\n", " }\n", "\n", " return this.each(function () {\n", " var className, i, self, classNames;\n", "\n", " if (isValidValue) {\n", " // Toggle individual class names\n", " i = 0;\n", " self = jQuery(this);\n", " classNames = classesToArray(value);\n", "\n", " while (className = classNames[i++]) {\n", " // Check each className given, space separated list\n", " if (self.hasClass(className)) {\n", " self.removeClass(className);\n", " } else {\n", " self.addClass(className);\n", " }\n", " } // Toggle whole class name\n", "\n", " } else if (value === undefined || type === \"boolean\") {\n", " className = getClass(this);\n", "\n", " if (className) {\n", " // Store className if set\n", " dataPriv.set(this, \"__className__\", className);\n", " } // If the element has a class name or if we're passed `false`,\n", " // then remove the whole classname (if there was one, the above saved it).\n", " // Otherwise bring back whatever was previously saved (if anything),\n", " // falling back to the empty string if nothing was stored.\n", "\n", "\n", " if (this.setAttribute) {\n", " this.setAttribute(\"class\", className || value === false ? \"\" : dataPriv.get(this, \"__className__\") || \"\");\n", " }\n", " }\n", " });\n", " },\n", " hasClass: function (selector) {\n", " var className,\n", " elem,\n", " i = 0;\n", " className = \" \" + selector + \" \";\n", "\n", " while (elem = this[i++]) {\n", " if (elem.nodeType === 1 && (\" \" + stripAndCollapse(getClass(elem)) + \" \").indexOf(className) > -1) {\n", " return true;\n", " }\n", " }\n", "\n", " return false;\n", " }\n", " });\n", " var rreturn = /\\r/g;\n", " jQuery.fn.extend({\n", " val: function (value) {\n", " var hooks,\n", " ret,\n", " valueIsFunction,\n", " elem = this[0];\n", "\n", " if (!arguments.length) {\n", " if (elem) {\n", " hooks = jQuery.valHooks[elem.type] || jQuery.valHooks[elem.nodeName.toLowerCase()];\n", "\n", " if (hooks && \"get\" in hooks && (ret = hooks.get(elem, \"value\")) !== undefined) {\n", " return ret;\n", " }\n", "\n", " ret = elem.value; // Handle most common string cases\n", "\n", " if (typeof ret === \"string\") {\n", " return ret.replace(rreturn, \"\");\n", " } // Handle cases where value is null/undef or number\n", "\n", "\n", " return ret == null ? \"\" : ret;\n", " }\n", "\n", " return;\n", " }\n", "\n", " valueIsFunction = isFunction(value);\n", " return this.each(function (i) {\n", " var val;\n", "\n", " if (this.nodeType !== 1) {\n", " return;\n", " }\n", "\n", " if (valueIsFunction) {\n", " val = value.call(this, i, jQuery(this).val());\n", " } else {\n", " val = value;\n", " } // Treat null/undefined as \"\"; convert numbers to string\n", "\n", "\n", " if (val == null) {\n", " val = \"\";\n", " } else if (typeof val === \"number\") {\n", " val += \"\";\n", " } else if (Array.isArray(val)) {\n", " val = jQuery.map(val, function (value) {\n", " return value == null ? \"\" : value + \"\";\n", " });\n", " }\n", "\n", " hooks = jQuery.valHooks[this.type] || jQuery.valHooks[this.nodeName.toLowerCase()]; // If set returns undefined, fall back to normal setting\n", "\n", " if (!hooks || !(\"set\" in hooks) || hooks.set(this, val, \"value\") === undefined) {\n", " this.value = val;\n", " }\n", " });\n", " }\n", " });\n", " jQuery.extend({\n", " valHooks: {\n", " option: {\n", " get: function (elem) {\n", " var val = jQuery.find.attr(elem, \"value\");\n", " return val != null ? val : // Support: IE <=10 - 11 only\n", " // option.text throws exceptions (#14686, #14858)\n", " // Strip and collapse whitespace\n", " // https://html.spec.whatwg.org/#strip-and-collapse-whitespace\n", " stripAndCollapse(jQuery.text(elem));\n", " }\n", " },\n", " select: {\n", " get: function (elem) {\n", " var value,\n", " option,\n", " i,\n", " options = elem.options,\n", " index = elem.selectedIndex,\n", " one = elem.type === \"select-one\",\n", " values = one ? null : [],\n", " max = one ? index + 1 : options.length;\n", "\n", " if (index < 0) {\n", " i = max;\n", " } else {\n", " i = one ? index : 0;\n", " } // Loop through all the selected options\n", "\n", "\n", " for (; i < max; i++) {\n", " option = options[i]; // Support: IE <=9 only\n", " // IE8-9 doesn't update selected after form reset (#2551)\n", "\n", " if ((option.selected || i === index) && // Don't return options that are disabled or in a disabled optgroup\n", " !option.disabled && (!option.parentNode.disabled || !nodeName(option.parentNode, \"optgroup\"))) {\n", " // Get the specific value for the option\n", " value = jQuery(option).val(); // We don't need an array for one selects\n", "\n", " if (one) {\n", " return value;\n", " } // Multi-Selects return an array\n", "\n", "\n", " values.push(value);\n", " }\n", " }\n", "\n", " return values;\n", " },\n", " set: function (elem, value) {\n", " var optionSet,\n", " option,\n", " options = elem.options,\n", " values = jQuery.makeArray(value),\n", " i = options.length;\n", "\n", " while (i--) {\n", " option = options[i];\n", " /* eslint-disable no-cond-assign */\n", "\n", " if (option.selected = jQuery.inArray(jQuery.valHooks.option.get(option), values) > -1) {\n", " optionSet = true;\n", " }\n", " /* eslint-enable no-cond-assign */\n", "\n", " } // Force browsers to behave consistently when non-matching value is set\n", "\n", "\n", " if (!optionSet) {\n", " elem.selectedIndex = -1;\n", " }\n", "\n", " return values;\n", " }\n", " }\n", " }\n", " }); // Radios and checkboxes getter/setter\n", "\n", " jQuery.each([\"radio\", \"checkbox\"], function () {\n", " jQuery.valHooks[this] = {\n", " set: function (elem, value) {\n", " if (Array.isArray(value)) {\n", " return elem.checked = jQuery.inArray(jQuery(elem).val(), value) > -1;\n", " }\n", " }\n", " };\n", "\n", " if (!support.checkOn) {\n", " jQuery.valHooks[this].get = function (elem) {\n", " return elem.getAttribute(\"value\") === null ? \"on\" : elem.value;\n", " };\n", " }\n", " }); // Return jQuery for attributes-only inclusion\n", "\n", " support.focusin = \"onfocusin\" in window;\n", "\n", " var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,\n", " stopPropagationCallback = function (e) {\n", " e.stopPropagation();\n", " };\n", "\n", " jQuery.extend(jQuery.event, {\n", " trigger: function (event, data, elem, onlyHandlers) {\n", " var i,\n", " cur,\n", " tmp,\n", " bubbleType,\n", " ontype,\n", " handle,\n", " special,\n", " lastElement,\n", " eventPath = [elem || document$2],\n", " type = hasOwn$6.call(event, \"type\") ? event.type : event,\n", " namespaces = hasOwn$6.call(event, \"namespace\") ? event.namespace.split(\".\") : [];\n", " cur = lastElement = tmp = elem = elem || document$2; // Don't do events on text and comment nodes\n", "\n", " if (elem.nodeType === 3 || elem.nodeType === 8) {\n", " return;\n", " } // focus/blur morphs to focusin/out; ensure we're not firing them right now\n", "\n", "\n", " if (rfocusMorph.test(type + jQuery.event.triggered)) {\n", " return;\n", " }\n", "\n", " if (type.indexOf(\".\") > -1) {\n", " // Namespaced trigger; create a regexp to match event type in handle()\n", " namespaces = type.split(\".\");\n", " type = namespaces.shift();\n", " namespaces.sort();\n", " }\n", "\n", " ontype = type.indexOf(\":\") < 0 && \"on\" + type; // Caller can pass in a jQuery.Event object, Object, or just an event type string\n", "\n", " event = event[jQuery.expando] ? event : new jQuery.Event(type, typeof event === \"object\" && event); // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)\n", "\n", " event.isTrigger = onlyHandlers ? 2 : 3;\n", " event.namespace = namespaces.join(\".\");\n", " event.rnamespace = event.namespace ? new RegExp(\"(^|\\\\.)\" + namespaces.join(\"\\\\.(?:.*\\\\.|)\") + \"(\\\\.|$)\") : null; // Clean up the event in case it is being reused\n", "\n", " event.result = undefined;\n", "\n", " if (!event.target) {\n", " event.target = elem;\n", " } // Clone any incoming data and prepend the event, creating the handler arg list\n", "\n", "\n", " data = data == null ? [event] : jQuery.makeArray(data, [event]); // Allow special events to draw outside the lines\n", "\n", " special = jQuery.event.special[type] || {};\n", "\n", " if (!onlyHandlers && special.trigger && special.trigger.apply(elem, data) === false) {\n", " return;\n", " } // Determine event propagation path in advance, per W3C events spec (#9951)\n", " // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)\n", "\n", "\n", " if (!onlyHandlers && !special.noBubble && !isWindow(elem)) {\n", " bubbleType = special.delegateType || type;\n", "\n", " if (!rfocusMorph.test(bubbleType + type)) {\n", " cur = cur.parentNode;\n", " }\n", "\n", " for (; cur; cur = cur.parentNode) {\n", " eventPath.push(cur);\n", " tmp = cur;\n", " } // Only add window if we got to document (e.g., not plain obj or detached DOM)\n", "\n", "\n", " if (tmp === (elem.ownerDocument || document$2)) {\n", " eventPath.push(tmp.defaultView || tmp.parentWindow || window);\n", " }\n", " } // Fire handlers on the event path\n", "\n", "\n", " i = 0;\n", "\n", " while ((cur = eventPath[i++]) && !event.isPropagationStopped()) {\n", " lastElement = cur;\n", " event.type = i > 1 ? bubbleType : special.bindType || type; // jQuery handler\n", "\n", " handle = (dataPriv.get(cur, \"events\") || {})[event.type] && dataPriv.get(cur, \"handle\");\n", "\n", " if (handle) {\n", " handle.apply(cur, data);\n", " } // Native handler\n", "\n", "\n", " handle = ontype && cur[ontype];\n", "\n", " if (handle && handle.apply && acceptData(cur)) {\n", " event.result = handle.apply(cur, data);\n", "\n", " if (event.result === false) {\n", " event.preventDefault();\n", " }\n", " }\n", " }\n", "\n", " event.type = type; // If nobody prevented the default action, do it now\n", "\n", " if (!onlyHandlers && !event.isDefaultPrevented()) {\n", " if ((!special._default || special._default.apply(eventPath.pop(), data) === false) && acceptData(elem)) {\n", " // Call a native DOM method on the target with the same name as the event.\n", " // Don't do default actions on window, that's where global variables be (#6170)\n", " if (ontype && isFunction(elem[type]) && !isWindow(elem)) {\n", " // Don't re-trigger an onFOO event when we call its FOO() method\n", " tmp = elem[ontype];\n", "\n", " if (tmp) {\n", " elem[ontype] = null;\n", " } // Prevent re-triggering of the same event, since we already bubbled it above\n", "\n", "\n", " jQuery.event.triggered = type;\n", "\n", " if (event.isPropagationStopped()) {\n", " lastElement.addEventListener(type, stopPropagationCallback);\n", " }\n", "\n", " elem[type]();\n", "\n", " if (event.isPropagationStopped()) {\n", " lastElement.removeEventListener(type, stopPropagationCallback);\n", " }\n", "\n", " jQuery.event.triggered = undefined;\n", "\n", " if (tmp) {\n", " elem[ontype] = tmp;\n", " }\n", " }\n", " }\n", " }\n", "\n", " return event.result;\n", " },\n", " // Piggyback on a donor event to simulate a different one\n", " // Used only for `focus(in | out)` events\n", " simulate: function (type, elem, event) {\n", " var e = jQuery.extend(new jQuery.Event(), event, {\n", " type: type,\n", " isSimulated: true\n", " });\n", " jQuery.event.trigger(e, null, elem);\n", " }\n", " });\n", " jQuery.fn.extend({\n", " trigger: function (type, data) {\n", " return this.each(function () {\n", " jQuery.event.trigger(type, data, this);\n", " });\n", " },\n", " triggerHandler: function (type, data) {\n", " var elem = this[0];\n", "\n", " if (elem) {\n", " return jQuery.event.trigger(type, data, elem, true);\n", " }\n", " }\n", " }); // Support: Firefox <=44\n", " // Firefox doesn't have focus(in | out) events\n", " // Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787\n", " //\n", " // Support: Chrome <=48 - 49, Safari <=9.0 - 9.1\n", " // focus(in | out) events fire after focus & blur events,\n", " // which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order\n", " // Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857\n", "\n", " if (!support.focusin) {\n", " jQuery.each({\n", " focus: \"focusin\",\n", " blur: \"focusout\"\n", " }, function (orig, fix) {\n", " // Attach a single capturing handler on the document while someone wants focusin/focusout\n", " var handler = function (event) {\n", " jQuery.event.simulate(fix, event.target, jQuery.event.fix(event));\n", " };\n", "\n", " jQuery.event.special[fix] = {\n", " setup: function () {\n", " var doc = this.ownerDocument || this,\n", " attaches = dataPriv.access(doc, fix);\n", "\n", " if (!attaches) {\n", " doc.addEventListener(orig, handler, true);\n", " }\n", "\n", " dataPriv.access(doc, fix, (attaches || 0) + 1);\n", " },\n", " teardown: function () {\n", " var doc = this.ownerDocument || this,\n", " attaches = dataPriv.access(doc, fix) - 1;\n", "\n", " if (!attaches) {\n", " doc.removeEventListener(orig, handler, true);\n", " dataPriv.remove(doc, fix);\n", " } else {\n", " dataPriv.access(doc, fix, attaches);\n", " }\n", " }\n", " };\n", " });\n", " }\n", "\n", " var rbracket = /\\[\\]$/,\n", " rCRLF = /\\r?\\n/g,\n", " rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,\n", " rsubmittable = /^(?:input|select|textarea|keygen)/i;\n", "\n", " function buildParams(prefix, obj, traditional, add) {\n", " var name;\n", "\n", " if (Array.isArray(obj)) {\n", " // Serialize array item.\n", " jQuery.each(obj, function (i, v) {\n", " if (traditional || rbracket.test(prefix)) {\n", " // Treat each array item as a scalar.\n", " add(prefix, v);\n", " } else {\n", " // Item is non-scalar (array or object), encode its numeric index.\n", " buildParams(prefix + \"[\" + (typeof v === \"object\" && v != null ? i : \"\") + \"]\", v, traditional, add);\n", " }\n", " });\n", " } else if (!traditional && toType(obj) === \"object\") {\n", " // Serialize object item.\n", " for (name in obj) {\n", " buildParams(prefix + \"[\" + name + \"]\", obj[name], traditional, add);\n", " }\n", " } else {\n", " // Serialize scalar item.\n", " add(prefix, obj);\n", " }\n", " } // Serialize an array of form elements or a set of\n", " // key/values into a query string\n", "\n", "\n", " jQuery.param = function (a, traditional) {\n", " var prefix,\n", " s = [],\n", " add = function (key, valueOrFunction) {\n", " // If value is a function, invoke it and use its return value\n", " var value = isFunction(valueOrFunction) ? valueOrFunction() : valueOrFunction;\n", " s[s.length] = encodeURIComponent(key) + \"=\" + encodeURIComponent(value == null ? \"\" : value);\n", " }; // If an array was passed in, assume that it is an array of form elements.\n", "\n", "\n", " if (Array.isArray(a) || a.jquery && !jQuery.isPlainObject(a)) {\n", " // Serialize the form elements\n", " jQuery.each(a, function () {\n", " add(this.name, this.value);\n", " });\n", " } else {\n", " // If traditional, encode the \"old\" way (the way 1.3.2 or older\n", " // did it), otherwise encode params recursively.\n", " for (prefix in a) {\n", " buildParams(prefix, a[prefix], traditional, add);\n", " }\n", " } // Return the resulting serialization\n", "\n", "\n", " return s.join(\"&\");\n", " };\n", "\n", " jQuery.fn.extend({\n", " serialize: function () {\n", " return jQuery.param(this.serializeArray());\n", " },\n", " serializeArray: function () {\n", " return this.map(function () {\n", " // Can add propHook for \"elements\" to filter or add form elements\n", " var elements = jQuery.prop(this, \"elements\");\n", " return elements ? jQuery.makeArray(elements) : this;\n", " }).filter(function () {\n", " var type = this.type; // Use .is( \":disabled\" ) so that fieldset[disabled] works\n", "\n", " return this.name && !jQuery(this).is(\":disabled\") && rsubmittable.test(this.nodeName) && !rsubmitterTypes.test(type) && (this.checked || !rcheckableType.test(type));\n", " }).map(function (i, elem) {\n", " var val = jQuery(this).val();\n", "\n", " if (val == null) {\n", " return null;\n", " }\n", "\n", " if (Array.isArray(val)) {\n", " return jQuery.map(val, function (val) {\n", " return {\n", " name: elem.name,\n", " value: val.replace(rCRLF, \"\\r\\n\")\n", " };\n", " });\n", " }\n", "\n", " return {\n", " name: elem.name,\n", " value: val.replace(rCRLF, \"\\r\\n\")\n", " };\n", " }).get();\n", " }\n", " });\n", " jQuery.fn.extend({\n", " wrapAll: function (html) {\n", " var wrap;\n", "\n", " if (this[0]) {\n", " if (isFunction(html)) {\n", " html = html.call(this[0]);\n", " } // The elements to wrap the target around\n", "\n", "\n", " wrap = jQuery(html, this[0].ownerDocument).eq(0).clone(true);\n", "\n", " if (this[0].parentNode) {\n", " wrap.insertBefore(this[0]);\n", " }\n", "\n", " wrap.map(function () {\n", " var elem = this;\n", "\n", " while (elem.firstElementChild) {\n", " elem = elem.firstElementChild;\n", " }\n", "\n", " return elem;\n", " }).append(this);\n", " }\n", "\n", " return this;\n", " },\n", " wrapInner: function (html) {\n", " if (isFunction(html)) {\n", " return this.each(function (i) {\n", " jQuery(this).wrapInner(html.call(this, i));\n", " });\n", " }\n", "\n", " return this.each(function () {\n", " var self = jQuery(this),\n", " contents = self.contents();\n", "\n", " if (contents.length) {\n", " contents.wrapAll(html);\n", " } else {\n", " self.append(html);\n", " }\n", " });\n", " },\n", " wrap: function (html) {\n", " var htmlIsFunction = isFunction(html);\n", " return this.each(function (i) {\n", " jQuery(this).wrapAll(htmlIsFunction ? html.call(this, i) : html);\n", " });\n", " },\n", " unwrap: function (selector) {\n", " this.parent(selector).not(\"body\").each(function () {\n", " jQuery(this).replaceWith(this.childNodes);\n", " });\n", " return this;\n", " }\n", " });\n", "\n", " jQuery.expr.pseudos.hidden = function (elem) {\n", " return !jQuery.expr.pseudos.visible(elem);\n", " };\n", "\n", " jQuery.expr.pseudos.visible = function (elem) {\n", " return !!(elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length);\n", " }; // Support: Safari 8 only\n", " // In Safari 8 documents created via document.implementation.createHTMLDocument\n", " // collapse sibling forms: the second one becomes a child of the first one.\n", " // Because of that, this security measure has to be disabled in Safari 8.\n", " // https://bugs.webkit.org/show_bug.cgi?id=137337\n", "\n", "\n", " support.createHTMLDocument = function () {\n", " var body = document$2.implementation.createHTMLDocument(\"\").body;\n", " body.innerHTML = \"
\";\n", " return body.childNodes.length === 2;\n", " }(); // Argument \"data\" should be string of html\n", " // context (optional): If specified, the fragment will be created in this context,\n", " // defaults to document\n", " // keepScripts (optional): If true, will include scripts passed in the html string\n", "\n", "\n", " jQuery.parseHTML = function (data, context, keepScripts) {\n", " if (typeof data !== \"string\") {\n", " return [];\n", " }\n", "\n", " if (typeof context === \"boolean\") {\n", " keepScripts = context;\n", " context = false;\n", " }\n", "\n", " var base, parsed, scripts;\n", "\n", " if (!context) {\n", " // Stop scripts or inline event handlers from being executed immediately\n", " // by using document.implementation\n", " if (support.createHTMLDocument) {\n", " context = document$2.implementation.createHTMLDocument(\"\"); // Set the base href for the created document\n", " // so any parsed elements with URLs\n", " // are based on the document's URL (gh-2965)\n", "\n", " base = context.createElement(\"base\");\n", " base.href = document$2.location.href;\n", " context.head.appendChild(base);\n", " } else {\n", " context = document$2;\n", " }\n", " }\n", "\n", " parsed = rsingleTag.exec(data);\n", " scripts = !keepScripts && []; // Single tag\n", "\n", " if (parsed) {\n", " return [context.createElement(parsed[1])];\n", " }\n", "\n", " parsed = buildFragment([data], context, scripts);\n", "\n", " if (scripts && scripts.length) {\n", " jQuery(scripts).remove();\n", " }\n", "\n", " return jQuery.merge([], parsed.childNodes);\n", " };\n", "\n", " jQuery.offset = {\n", " setOffset: function (elem, options, i) {\n", " var curPosition,\n", " curLeft,\n", " curCSSTop,\n", " curTop,\n", " curOffset,\n", " curCSSLeft,\n", " calculatePosition,\n", " position = jQuery.css(elem, \"position\"),\n", " curElem = jQuery(elem),\n", " props = {}; // Set position first, in-case top/left are set even on static elem\n", "\n", " if (position === \"static\") {\n", " elem.style.position = \"relative\";\n", " }\n", "\n", " curOffset = curElem.offset();\n", " curCSSTop = jQuery.css(elem, \"top\");\n", " curCSSLeft = jQuery.css(elem, \"left\");\n", " calculatePosition = (position === \"absolute\" || position === \"fixed\") && (curCSSTop + curCSSLeft).indexOf(\"auto\") > -1; // Need to be able to calculate position if either\n", " // top or left is auto and position is either absolute or fixed\n", "\n", " if (calculatePosition) {\n", " curPosition = curElem.position();\n", " curTop = curPosition.top;\n", " curLeft = curPosition.left;\n", " } else {\n", " curTop = parseFloat(curCSSTop) || 0;\n", " curLeft = parseFloat(curCSSLeft) || 0;\n", " }\n", "\n", " if (isFunction(options)) {\n", " // Use jQuery.extend here to allow modification of coordinates argument (gh-1848)\n", " options = options.call(elem, i, jQuery.extend({}, curOffset));\n", " }\n", "\n", " if (options.top != null) {\n", " props.top = options.top - curOffset.top + curTop;\n", " }\n", "\n", " if (options.left != null) {\n", " props.left = options.left - curOffset.left + curLeft;\n", " }\n", "\n", " if (\"using\" in options) {\n", " options.using.call(elem, props);\n", " } else {\n", " curElem.css(props);\n", " }\n", " }\n", " };\n", " jQuery.fn.extend({\n", " // offset() relates an element's border box to the document origin\n", " offset: function (options) {\n", " // Preserve chaining for setter\n", " if (arguments.length) {\n", " return options === undefined ? this : this.each(function (i) {\n", " jQuery.offset.setOffset(this, options, i);\n", " });\n", " }\n", "\n", " var rect,\n", " win,\n", " elem = this[0];\n", "\n", " if (!elem) {\n", " return;\n", " } // Return zeros for disconnected and hidden (display: none) elements (gh-2310)\n", " // Support: IE <=11 only\n", " // Running getBoundingClientRect on a\n", " // disconnected node in IE throws an error\n", "\n", "\n", " if (!elem.getClientRects().length) {\n", " return {\n", " top: 0,\n", " left: 0\n", " };\n", " } // Get document-relative position by adding viewport scroll to viewport-relative gBCR\n", "\n", "\n", " rect = elem.getBoundingClientRect();\n", " win = elem.ownerDocument.defaultView;\n", " return {\n", " top: rect.top + win.pageYOffset,\n", " left: rect.left + win.pageXOffset\n", " };\n", " },\n", " // position() relates an element's margin box to its offset parent's padding box\n", " // This corresponds to the behavior of CSS absolute positioning\n", " position: function () {\n", " if (!this[0]) {\n", " return;\n", " }\n", "\n", " var offsetParent,\n", " offset,\n", " doc,\n", " elem = this[0],\n", " parentOffset = {\n", " top: 0,\n", " left: 0\n", " }; // position:fixed elements are offset from the viewport, which itself always has zero offset\n", "\n", " if (jQuery.css(elem, \"position\") === \"fixed\") {\n", " // Assume position:fixed implies availability of getBoundingClientRect\n", " offset = elem.getBoundingClientRect();\n", " } else {\n", " offset = this.offset(); // Account for the *real* offset parent, which can be the document or its root element\n", " // when a statically positioned element is identified\n", "\n", " doc = elem.ownerDocument;\n", " offsetParent = elem.offsetParent || doc.documentElement;\n", "\n", " while (offsetParent && (offsetParent === doc.body || offsetParent === doc.documentElement) && jQuery.css(offsetParent, \"position\") === \"static\") {\n", " offsetParent = offsetParent.parentNode;\n", " }\n", "\n", " if (offsetParent && offsetParent !== elem && offsetParent.nodeType === 1) {\n", " // Incorporate borders into its offset, since they are outside its content origin\n", " parentOffset = jQuery(offsetParent).offset();\n", " parentOffset.top += jQuery.css(offsetParent, \"borderTopWidth\", true);\n", " parentOffset.left += jQuery.css(offsetParent, \"borderLeftWidth\", true);\n", " }\n", " } // Subtract parent offsets and element margins\n", "\n", "\n", " return {\n", " top: offset.top - parentOffset.top - jQuery.css(elem, \"marginTop\", true),\n", " left: offset.left - parentOffset.left - jQuery.css(elem, \"marginLeft\", true)\n", " };\n", " },\n", " // This method will return documentElement in the following cases:\n", " // 1) For the element inside the iframe without offsetParent, this method will return\n", " // documentElement of the parent window\n", " // 2) For the hidden or detached element\n", " // 3) For body or html element, i.e. in case of the html node - it will return itself\n", " //\n", " // but those exceptions were never presented as a real life use-cases\n", " // and might be considered as more preferable results.\n", " //\n", " // This logic, however, is not guaranteed and can change at any point in the future\n", " offsetParent: function () {\n", " return this.map(function () {\n", " var offsetParent = this.offsetParent;\n", "\n", " while (offsetParent && jQuery.css(offsetParent, \"position\") === \"static\") {\n", " offsetParent = offsetParent.offsetParent;\n", " }\n", "\n", " return offsetParent || documentElement;\n", " });\n", " }\n", " }); // Create scrollLeft and scrollTop methods\n", "\n", " jQuery.each({\n", " scrollLeft: \"pageXOffset\",\n", " scrollTop: \"pageYOffset\"\n", " }, function (method, prop) {\n", " var top = \"pageYOffset\" === prop;\n", "\n", " jQuery.fn[method] = function (val) {\n", " return access(this, function (elem, method, val) {\n", " // Coalesce documents and windows\n", " var win;\n", "\n", " if (isWindow(elem)) {\n", " win = elem;\n", " } else if (elem.nodeType === 9) {\n", " win = elem.defaultView;\n", " }\n", "\n", " if (val === undefined) {\n", " return win ? win[prop] : elem[method];\n", " }\n", "\n", " if (win) {\n", " win.scrollTo(!top ? val : win.pageXOffset, top ? val : win.pageYOffset);\n", " } else {\n", " elem[method] = val;\n", " }\n", " }, method, val, arguments.length);\n", " };\n", " }); // Support: Safari <=7 - 9.1, Chrome <=37 - 49\n", " // Add the top/left cssHooks using jQuery.fn.position\n", " // Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084\n", " // Blink bug: https://bugs.chromium.org/p/chromium/issues/detail?id=589347\n", " // getComputedStyle returns percent when specified for top/left/bottom/right;\n", " // rather than make the css module depend on the offset module, just check for it here\n", "\n", " jQuery.each([\"top\", \"left\"], function (i, prop) {\n", " jQuery.cssHooks[prop] = addGetHookIf(support.pixelPosition, function (elem, computed) {\n", " if (computed) {\n", " computed = curCSS(elem, prop); // If curCSS returns percentage, fallback to offset\n", "\n", " return rnumnonpx.test(computed) ? jQuery(elem).position()[prop] + \"px\" : computed;\n", " }\n", " });\n", " }); // Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods\n", "\n", " jQuery.each({\n", " Height: \"height\",\n", " Width: \"width\"\n", " }, function (name, type) {\n", " jQuery.each({\n", " padding: \"inner\" + name,\n", " content: type,\n", " \"\": \"outer\" + name\n", " }, function (defaultExtra, funcName) {\n", " // Margin is only for outerHeight, outerWidth\n", " jQuery.fn[funcName] = function (margin, value) {\n", " var chainable = arguments.length && (defaultExtra || typeof margin !== \"boolean\"),\n", " extra = defaultExtra || (margin === true || value === true ? \"margin\" : \"border\");\n", " return access(this, function (elem, type, value) {\n", " var doc;\n", "\n", " if (isWindow(elem)) {\n", " // $( window ).outerWidth/Height return w/h including scrollbars (gh-1729)\n", " return funcName.indexOf(\"outer\") === 0 ? elem[\"inner\" + name] : elem.document.documentElement[\"client\" + name];\n", " } // Get document width or height\n", "\n", "\n", " if (elem.nodeType === 9) {\n", " doc = elem.documentElement; // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height],\n", " // whichever is greatest\n", "\n", " return Math.max(elem.body[\"scroll\" + name], doc[\"scroll\" + name], elem.body[\"offset\" + name], doc[\"offset\" + name], doc[\"client\" + name]);\n", " }\n", "\n", " return value === undefined ? // Get width or height on the element, requesting but not forcing parseFloat\n", " jQuery.css(elem, type, extra) : // Set width or height on the element\n", " jQuery.style(elem, type, value, extra);\n", " }, type, chainable ? margin : undefined, chainable);\n", " };\n", " });\n", " });\n", " 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) {\n", " // Handle event binding\n", " jQuery.fn[name] = function (data, fn) {\n", " return arguments.length > 0 ? this.on(name, null, data, fn) : this.trigger(name);\n", " };\n", " });\n", " jQuery.fn.extend({\n", " hover: function (fnOver, fnOut) {\n", " return this.mouseenter(fnOver).mouseleave(fnOut || fnOver);\n", " }\n", " });\n", " jQuery.fn.extend({\n", " bind: function (types, data, fn) {\n", " return this.on(types, null, data, fn);\n", " },\n", " unbind: function (types, fn) {\n", " return this.off(types, null, fn);\n", " },\n", " delegate: function (selector, types, data, fn) {\n", " return this.on(types, selector, data, fn);\n", " },\n", " undelegate: function (selector, types, fn) {\n", " // ( namespace ) or ( selector, types [, fn] )\n", " return arguments.length === 1 ? this.off(selector, \"**\") : this.off(types, selector || \"**\", fn);\n", " }\n", " }); // Bind a function to a context, optionally partially applying any\n", " // arguments.\n", " // jQuery.proxy is deprecated to promote standards (specifically Function#bind)\n", " // However, it is not slated for removal any time soon\n", "\n", " jQuery.proxy = function (fn, context) {\n", " var tmp, args, proxy;\n", "\n", " if (typeof context === \"string\") {\n", " tmp = fn[context];\n", " context = fn;\n", " fn = tmp;\n", " } // Quick check to determine if target is callable, in the spec\n", " // this throws a TypeError, but we will just return undefined.\n", "\n", "\n", " if (!isFunction(fn)) {\n", " return undefined;\n", " } // Simulated bind\n", "\n", "\n", " args = slice.call(arguments, 2);\n", "\n", " proxy = function () {\n", " return fn.apply(context || this, args.concat(slice.call(arguments)));\n", " }; // Set the guid of unique handler to the same of original handler, so it can be removed\n", "\n", "\n", " proxy.guid = fn.guid = fn.guid || jQuery.guid++;\n", " return proxy;\n", " };\n", "\n", " jQuery.holdReady = function (hold) {\n", " if (hold) {\n", " jQuery.readyWait++;\n", " } else {\n", " jQuery.ready(true);\n", " }\n", " };\n", "\n", " jQuery.isArray = Array.isArray;\n", " jQuery.parseJSON = JSON.parse;\n", " jQuery.nodeName = nodeName;\n", " jQuery.isFunction = isFunction;\n", " jQuery.isWindow = isWindow;\n", " jQuery.camelCase = camelCase;\n", " jQuery.type = toType;\n", " jQuery.now = Date.now;\n", "\n", " jQuery.isNumeric = function (obj) {\n", " // As of jQuery 3.0, isNumeric is limited to\n", " // strings and numbers (primitives or objects)\n", " // that can be coerced to finite numbers (gh-2662)\n", " var type = jQuery.type(obj);\n", " return (type === \"number\" || type === \"string\") && // parseFloat NaNs numeric-cast false positives (\"\")\n", " // ...but misinterprets leading-number strings, particularly hex literals (\"0x...\")\n", " // subtraction forces infinities to NaN\n", " !isNaN(obj - parseFloat(obj));\n", " };\n", "\n", " const $ = jQuery;\n", "\n", " /**\n", " * Test if object is a File or File-like object.\n", " *\n", " * Copied from igv-utils.FileUtils version 1.3.8\n", " *\n", " * @param object\n", " */\n", " function isFile(object) {\n", " if (!object) {\n", " return false;\n", " }\n", "\n", " return typeof object !== 'function' && (object instanceof File || object.name !== undefined && typeof object.slice === 'function' && typeof object.arrayBuffer === 'function');\n", " }\n", "\n", " /*\n", " * The MIT License (MIT)\n", " *\n", " * Copyright (c) 2014 Broad Institute\n", " *\n", " * Permission is hereby granted, free of charge, to any person obtaining a copy\n", " * of this software and associated documentation files (the \"Software\"), to deal\n", " * in the Software without restriction, including without limitation the rights\n", " * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n", " * copies of the Software, and to permit persons to whom the Software is\n", " * furnished to do so, subject to the following conditions:\n", " *\n", " * The above copyright notice and this permission notice shall be included in\n", " * all copies or substantial portions of the Software.\n", " *\n", " *\n", " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n", " * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n", " * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n", " * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n", " * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n", " * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n", " * THE SOFTWARE.\n", " */\n", " /**\n", " * Test if the given value is a string or number. Not using typeof as it fails on boxed primitives.\n", " *\n", " * @param value\n", " * @returns boolean\n", " */\n", "\n", "\n", " function isSimpleType(value) {\n", " const simpleTypes = new Set([\"boolean\", \"number\", \"string\", \"symbol\"]);\n", " const valueType = typeof value;\n", " return value !== undefined && (simpleTypes.has(valueType) || value.substring || value.toFixed);\n", " }\n", "\n", " function buildOptions$1(config, options) {\n", " var defaultOptions = {\n", " oauthToken: config.oauthToken,\n", " headers: config.headers,\n", " withCredentials: config.withCredentials,\n", " filename: config.filename\n", " };\n", " return Object.assign(defaultOptions, options);\n", " }\n", " /**\n", " * isMobile test from http://detectmobilebrowsers.com\n", " * TODO -- improve UI design so this isn't neccessary\n", " * @returns {boolean}\n", " */\n", " // igv.isMobile = function () {\n", " //\n", " // const a = (navigator.userAgent || navigator.vendor || window.opera);\n", " // 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) ||\n", " // /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 )|sy(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)))\n", " //\n", " // }\n", "\n", "\n", " const doAutoscale = function (features) {\n", " var min, max;\n", "\n", " if (features.length > 0) {\n", " min = Number.MAX_VALUE;\n", " max = -Number.MAX_VALUE;\n", " features.forEach(function (f) {\n", " if (!Number.isNaN(f.value)) {\n", " min = Math.min(min, f.value);\n", " max = Math.max(max, f.value);\n", " }\n", " }); // Insure we have a zero baseline\n", "\n", " if (max > 0) min = Math.min(0, min);\n", " if (max < 0) max = 0;\n", " } else {\n", " // No features -- default\n", " min = 0;\n", " max = 100;\n", " }\n", "\n", " return {\n", " min: min,\n", " max: max\n", " };\n", " };\n", " /*!\n", " * is-number \n", " *\n", " * Copyright (c) 2014-present, Jon Schlinkert.\n", " * Released under the MIT License.\n", " */\n", "\n", "\n", " const isNumber = function (num) {\n", " if (typeof num === 'number') {\n", " return num - num === 0;\n", " }\n", "\n", " if (typeof num === 'string' && num.trim() !== '') {\n", " return Number.isFinite ? Number.isFinite(+num) : isFinite(+num);\n", " }\n", "\n", " return false;\n", " };\n", "\n", " function inferTrackType(config) {\n", " translateDeprecatedTypes(config);\n", "\n", " if (config.type) {\n", " return config.type;\n", " }\n", "\n", " let format;\n", "\n", " if (\"file\" === config.sourceType || undefined === config.sourceType && config.url) {\n", " if (undefined === config.format) {\n", " const path = isFile(config.url) ? config.url.name : config.url;\n", " format = inferFileFormat(path);\n", " } else {\n", " format = config.format.toLowerCase();\n", " }\n", " }\n", "\n", " if (format) {\n", " switch (format) {\n", " case \"bw\":\n", " case \"bigwig\":\n", " case \"wig\":\n", " case \"bedgraph\":\n", " case \"tdf\":\n", " return \"wig\";\n", "\n", " case \"vcf\":\n", " return \"variant\";\n", "\n", " case \"seg\":\n", " return \"seg\";\n", "\n", " case \"bam\":\n", " case \"cram\":\n", " return \"alignment\";\n", "\n", " case \"bedpe\":\n", " case \"bedpe-loop\":\n", " return \"interaction\";\n", "\n", " case \"bp\":\n", " return \"arc\";\n", "\n", " case \"gwas\":\n", " return \"gwas\";\n", "\n", " case \"bed\":\n", " case \"bigbed\":\n", " case \"bb\":\n", " return \"bedtype\";\n", "\n", " default:\n", " return \"annotation\";\n", " }\n", " }\n", " }\n", "\n", " function translateDeprecatedTypes(config) {\n", " if (config.featureType) {\n", " // Translate deprecated \"feature\" type\n", " config.type = config.type || config.featureType;\n", " config.featureType = undefined;\n", " }\n", "\n", " if (\"junctions\" === config.type) {\n", " config.type = \"spliceJunctions\";\n", " } else if (\"bed\" === config.type) {\n", " config.type = \"annotation\";\n", " config.format = config.format || \"bed\";\n", " } else if (\"annotations\" === config.type) {\n", " config.type = \"annotation\";\n", " } else if (\"alignments\" === config.type) {\n", " config.type = \"alignment\";\n", " } else if (\"bam\" === config.type) {\n", " config.type = \"alignment\";\n", " config.format = \"bam\";\n", " } else if (\"vcf\" === config.type) {\n", " config.type = \"variant\";\n", " config.format = \"vcf\";\n", " } else if (\"t2d\" === config.type) {\n", " config.type = \"gwas\";\n", " } else if (\"FusionJuncSpan\" === config.type && !config.format) {\n", " config.format = \"fusionjuncspan\";\n", " } else if (\"aed\" === config.type) {\n", " config.type = \"annotation\";\n", " config.format = config.format || \"aed\";\n", " }\n", " }\n", "\n", " /**\n", " * Decoder for bedpe records.\n", " *\n", " * Bedpe format was created by Aaron Quinlan et al as part of the bedtools project.\n", " * The spec is here: https://bedtools.readthedocs.io/en/latest/content/general-usage.html, however there\n", " * are off spec variants, an important one being a 7 column format with score in place of the standard\n", " * name column.\n", " *\n", " * Another common variant is a \"hiccups\" output file, which is standard bedpe with the exception of a header line\n", " * of the form\n", " * chr1 x1 x2 chr2 y1 y2 name score strand1 strand2 color observed expectedBL expectedDonut expectedH expectedV fdrBL fdrDonut fdrH fdrV\n", " *\n", " * @param tokens\n", " * @param ignore\n", " * @returns {{start1: number, end2: number, end1: number, chr1: *, chr2: *, start2: number}|undefined}\n", " */\n", "\n", " function decodeBedpe(tokens, header) {\n", " if (tokens.length < 6) {\n", " console.log(\"Skipping line: \" + tokens.join(' '));\n", " return undefined;\n", " }\n", "\n", " var feature = {\n", " chr1: tokens[0],\n", " start1: Number.parseInt(tokens[1]),\n", " end1: Number.parseInt(tokens[2]),\n", " chr2: tokens[3],\n", " start2: Number.parseInt(tokens[4]),\n", " end2: Number.parseInt(tokens[5])\n", " };\n", "\n", " if (isNaN(feature.start1) || isNaN(feature.end1) || isNaN(feature.start2) || isNaN(feature.end2)) {\n", " //throw Error(`Error parsing line: ${tokens.join('\\t')}`);\n", " return undefined;\n", " }\n", "\n", " if (tokens.length > 6 && tokens[6] !== \".\") {\n", " feature.name = tokens[6];\n", " }\n", "\n", " if (tokens.length > 7 && tokens[7] !== \".\") {\n", " feature.score = parseFloat(tokens[7]);\n", " }\n", "\n", " if (tokens.length > 8 && tokens[8] !== \".\") {\n", " feature.strand1 = tokens[8];\n", " }\n", "\n", " if (tokens.length > 9 && tokens[9] !== \".\") {\n", " feature.strand2 = tokens[9];\n", " } // Optional extra columns\n", "\n", "\n", " if (header) {\n", " const colorColumn = header.colorColumn;\n", "\n", " if (colorColumn && colorColumn < tokens.length) {\n", " feature.color = IGVColor.createColorString(tokens[colorColumn]);\n", " }\n", "\n", " const thicknessColumn = header.thicknessColumn;\n", "\n", " if (thicknessColumn && thicknessColumn < tokens.length) {\n", " feature.thickness = tokens[thicknessColumn];\n", " }\n", "\n", " if (tokens.length > 10 && header.columnNames && header.columnNames.length === tokens.length) {\n", " feature.extras = tokens.slice(10);\n", " }\n", " } // Set total extent of feature\n", "\n", "\n", " if (feature.chr1 === feature.chr2) {\n", " feature.chr = feature.chr1;\n", " feature.start = Math.min(feature.start1, feature.start2);\n", " feature.end = Math.max(feature.end1, feature.end2);\n", " }\n", "\n", " return feature;\n", " }\n", " /**\n", " * Hack for non-standard bedPE formats, where numeric score can be in column 7 (name field from spec)\n", " * @param features\n", " */\n", "\n", "\n", " function fixBedPE(features) {\n", " if (features.length == 0) return; // Assume all features have same properties\n", "\n", " const firstFeature = features[0];\n", "\n", " if (firstFeature.score === undefined && firstFeature.name !== undefined) {\n", " // Name field (col 7) is sometimes used for score.\n", " for (let f of features) {\n", " if (!(isNumber(f.name) || f.name === '.')) return;\n", " }\n", "\n", " for (let f of features) {\n", " f.score = parseFloat(f.name);\n", " delete f.name;\n", " }\n", " } // Make copies of inter-chr features, one for each chromosome\n", "\n", "\n", " const interChrFeatures = features.filter(f => f.chr1 !== f.chr2);\n", "\n", " for (let f1 of interChrFeatures) {\n", " const f2 = Object.assign({}, f1);\n", " f2.dup = true;\n", " features.push(f2);\n", " f1.chr = f1.chr1;\n", " f1.start = f1.start1;\n", " f1.end = f1.end1;\n", " f2.chr = f2.chr2;\n", " f2.start = f2.start2;\n", " f2.end = f2.end2;\n", " }\n", " }\n", " /**\n", " * Special decoder for Hic Domain files. In these files feature1 == feature2, they are really bed records.\n", " * @param tokens\n", " * @param ignore\n", " * @returns {*}\n", " */\n", "\n", "\n", " function decodeBedpeDomain(tokens, header) {\n", " if (tokens.length < 8) return undefined;\n", " return {\n", " chr: tokens[0],\n", " start: Number.parseInt(tokens[1]),\n", " end: Number.parseInt(tokens[2]),\n", " color: IGVColor.createColorString(tokens[6]),\n", " value: Number.parseFloat(tokens[7])\n", " };\n", " }\n", "\n", " /**\n", " * Decode UCSC \"interact\" files. See https://genome.ucsc.edu/goldenpath/help/interact.html\n", " *\n", " 0 string chrom; \"Chromosome (or contig, scaffold, etc.). For interchromosomal, use 2 records\"\n", " 1 uint chromStart; \"Start position of lower region. For interchromosomal, set to chromStart of this region\"\n", " 2 uint chromEnd; \"End position of upper region. For interchromosomal, set to chromEnd of this region\"\n", " 3 string name; \"Name of item, for display. Usually 'sourceName/targetName/exp' or empty\"\n", " 4 uint score; \"Score (0-1000)\"\n", " 5 double value; \"Strength of interaction or other data value. Typically basis for score\"\n", " 6 string exp; \"Experiment name (metadata for filtering). Use . if not applicable\"\n", " 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\"\n", " 8 string sourceChrom; \"Chromosome of source region (directional) or lower region. For non-directional interchromosomal, chrom of this region.\"\n", " 9 uint sourceStart; \"Start position in chromosome of source/lower/this region\"\n", " 10 uint sourceEnd; \"End position in chromosome of source/lower/this region\"\n", " 11 string sourceName; \"Identifier of source/lower/this region\"\n", " 12 string sourceStrand; \"Orientation of source/lower/this region: + or -. Use . if not applicable\"\n", " 13 string targetChrom; \"Chromosome of target region (directional) or upper region. For non-directional interchromosomal, chrom of other region\"\n", " 14 uint targetStart; \"Start position in chromosome of target/upper/this region\"\n", " 15 uint targetEnd; \"End position in chromosome of target/upper/this region\"\n", " 16 string targetName; \"Identifier of target/upper/this region\"\n", " 17 string targetStrand; \"Orientation of target/upper/this region: + or -. Use . if not applicable\"\n", " *\n", " * @param tokens\n", " * @param ignore\n", " * @returns {*}\n", " */\n", "\n", " function decodeInteract(tokens, header) {\n", " if (tokens.length < 6) {\n", " console.log(\"Skipping line: \" + tokens.join(' '));\n", " return undefined;\n", " }\n", "\n", " var feature = {\n", " chr: tokens[0],\n", " start: tokens[1],\n", " end: tokens[2],\n", " chr1: tokens[8],\n", " start1: Number.parseInt(tokens[9]),\n", " end1: Number.parseInt(tokens[10]),\n", " chr2: tokens[13],\n", " start2: Number.parseInt(tokens[14]),\n", " end2: Number.parseInt(tokens[15]),\n", " name: tokens[3],\n", " score: Number.parseFloat(tokens[4]),\n", " value: Number.parseFloat(tokens[5]),\n", " color: tokens[7] === '.' ? undefined : tokens[7] === \"0\" ? \"rgb(0,0,0)\" : tokens[7]\n", " };\n", " return feature;\n", " }\n", "\n", " const gffNameFields = [\"Name\", \"gene_name\", \"gene\", \"gene_id\", \"alias\", \"locus\", \"name\"];\n", " /**\n", " * Decode a single gff record (1 line in file). Aggregations such as gene models are constructed at a higher level.\n", " * ctg123 . mRNA 1050 9000 . + . ID=mRNA00001;Parent=gene00001\n", " * @param tokens\n", " * @param ignore\n", " * @returns {*}\n", " */\n", "\n", " function decodeGFF(tokens, header) {\n", " var tokenCount,\n", " chr,\n", " start,\n", " end,\n", " strand,\n", " type,\n", " score,\n", " attributeString,\n", " color,\n", " name,\n", " i,\n", " format = header.format;\n", " tokenCount = tokens.length;\n", "\n", " if (tokenCount < 9) {\n", " return null; // Not a valid gff record\n", " }\n", "\n", " chr = tokens[0];\n", " type = tokens[2];\n", " start = parseInt(tokens[3]) - 1;\n", " end = parseInt(tokens[4]);\n", " score = \".\" === tokens[5] ? 0 : parseFloat(tokens[5]);\n", " strand = tokens[6];\n", " \".\" === tokens[7] ? 0 : parseInt(tokens[7]);\n", " attributeString = tokens[8]; // Find ID and Parent, or transcript_id\n", "\n", " var delim = 'gff3' === format ? '=' : /\\s+/;\n", " var attributes = parseAttributeString(attributeString, delim);\n", "\n", " for (let [key, value] of Object.entries(attributes)) {\n", " const keyLower = key.toLowerCase();\n", "\n", " if (\"color\" === keyLower || \"colour\" === keyLower) {\n", " color = IGVColor.createColorString(value);\n", " } else if ('gff3' === format) try {\n", " attributes[key] = unescape(value);\n", " } catch (e) {\n", " attributes[key] = value; // Invalid\n", "\n", " console.error(`Malformed gff3 attibute value: ${value}`);\n", " }\n", " } // Find name (label) property\n", "\n", "\n", " if (header.nameField) {\n", " name = attributes[header.nameField];\n", " } else {\n", " for (i = 0; i < gffNameFields.length; i++) {\n", " if (attributes.hasOwnProperty(gffNameFields[i])) {\n", " header.nameField = gffNameFields[i];\n", " name = attributes[header.nameField];\n", " break;\n", " }\n", " }\n", " }\n", "\n", " const id = attributes[\"ID\"] || attributes[\"transcript_id\"];\n", " const parent = attributes[\"Parent\"];\n", " return {\n", " id: id,\n", " parent: parent,\n", " name: name,\n", " type: type,\n", " chr: chr,\n", " start: start,\n", " end: end,\n", " score: score,\n", " strand: strand,\n", " color: color,\n", " attributeString: attributeString,\n", " delim: delim,\n", " popupData: popupData\n", " };\n", " }\n", "\n", " function parseAttributeString(attributeString, keyValueDelim) {\n", " // parse 'attributes' string (see column 9 docs in https://github.com/The-Sequence-Ontology/Specifications/blob/master/gff3.md)\n", " var attributes = {};\n", "\n", " for (let kv of attributeString.split(';')) {\n", " const t = kv.trim().split(keyValueDelim, 2);\n", "\n", " if (t.length === 2) {\n", " const key = t[0].trim();\n", " let value = t[1].trim(); //Strip off quotes, if any\n", "\n", " if (value.startsWith('\"') && value.endsWith('\"')) {\n", " value = value.substr(1, value.length - 2);\n", " }\n", "\n", " attributes[key] = value;\n", " }\n", " }\n", "\n", " return attributes;\n", " }\n", "\n", " function popupData(genomicLocation) {\n", " const kvs = this.attributeString.split(';');\n", " const pd = [];\n", "\n", " if (this.name) {\n", " pd.push({\n", " name: 'name:',\n", " value: this.name\n", " });\n", " }\n", "\n", " pd.push({\n", " name: 'type:',\n", " value: this.type\n", " });\n", "\n", " for (let kv of kvs) {\n", " const t = kv.trim().split(this.delim, 2);\n", "\n", " if (t.length === 2 && t[1] !== undefined) {\n", " const key = t[0].trim();\n", " if ('name' === key.toLowerCase()) continue;\n", " let value = t[1].trim(); //Strip off quotes, if any\n", "\n", " if (value.startsWith('\"') && value.endsWith('\"')) {\n", " value = value.substr(1, value.length - 2);\n", " }\n", "\n", " pd.push({\n", " name: key + \":\",\n", " value: value\n", " });\n", " }\n", " }\n", "\n", " pd.push({\n", " name: 'position:',\n", " value: `${this.chr}:${numberFormatter(this.start + 1)}-${numberFormatter(this.end)}`\n", " });\n", " return pd;\n", " }\n", "\n", " /**\n", " * Decode the UCSC bed format. Only the first 3 columns (chr, start, end) are required. The remaining columns\n", " * must follow standard bed order, but we will tolerate deviations after column 3.\n", " *\n", " * @param tokens\n", " * @param ignore\n", " * @returns decoded feature, or null if this is not a valid record\n", " */\n", "\n", " function decodeBed(tokens, header) {\n", " if (tokens.length < 3) return undefined;\n", " header && header.gffTags;\n", " const chr = tokens[0];\n", " const start = parseInt(tokens[1]);\n", " const end = tokens.length > 2 ? parseInt(tokens[2]) : start + 1;\n", "\n", " if (isNaN(start) || isNaN(end)) {\n", " throw Error(`Unparsable bed record: ${tokens.join('\\t')}`);\n", " }\n", "\n", " const feature = {\n", " chr: chr,\n", " start: start,\n", " end: end,\n", " score: 1000\n", " };\n", "\n", " try {\n", " if (tokens.length > 3) {\n", " // Note: these are very special rules for the gencode gene files.\n", " // tmp = tokens[3].replace(/\"/g, '');\n", " // idName = tmp.split(';');\n", " // for (var i = 0; i < idName.length; i++) {\n", " // var kv = idName[i].split('=');\n", " // if (kv[0] == \"gene_id\") {\n", " // id = kv[1];\n", " // }\n", " // if (kv[0] == \"gene_name\") {\n", " // name = kv[1];\n", " // }\n", " // }\n", " // feature.id = id ? id : tmp;\n", " // feature.name = name ? name : tmp;\n", " //parse gffTags in the name field\n", " if (tokens[3].indexOf(';') > 0 && tokens[3].indexOf('=') > 0) {\n", " const attributes = parseAttributeString(tokens[3], '=');\n", "\n", " for (let nmField of gffNameFields) {\n", " if (attributes.hasOwnProperty(nmField)) {\n", " feature.name = attributes[nmField];\n", " delete attributes[nmField];\n", " break;\n", " }\n", " }\n", "\n", " feature.attributes = attributes;\n", " }\n", "\n", " if (!feature.name) {\n", " feature.name = tokens[3] === '.' ? '' : tokens[3];\n", " }\n", " }\n", "\n", " if (tokens.length > 4) {\n", " feature.score = tokens[4] === '.' ? 0 : parseFloat(tokens[4]);\n", "\n", " if (isNaN(feature.score)) {\n", " return feature;\n", " }\n", " }\n", "\n", " if (tokens.length > 5) {\n", " feature.strand = tokens[5];\n", "\n", " if (!(feature.strand === '.' || feature.strand === '+' || feature.strand === '-')) {\n", " return feature;\n", " }\n", " }\n", "\n", " if (tokens.length > 6) {\n", " feature.cdStart = parseInt(tokens[6]);\n", "\n", " if (isNaN(feature.cdStart)) {\n", " return feature;\n", " }\n", " }\n", "\n", " if (tokens.length > 7) {\n", " feature.cdEnd = parseInt(tokens[7]);\n", "\n", " if (isNaN(feature.cdEnd)) {\n", " return feature;\n", " }\n", " }\n", "\n", " if (tokens.length > 8) {\n", " if (tokens[8] !== \".\" && tokens[8] !== \"0\") feature.color = IGVColor.createColorString(tokens[8]);\n", " }\n", "\n", " if (tokens.length > 11) {\n", " const exonCount = parseInt(tokens[9]); // Some basic validation\n", "\n", " if (exonCount > 1000) {\n", " // unlikely\n", " return feature;\n", " }\n", "\n", " const exonSizes = tokens[10].replace(/,$/, '').split(',');\n", " const exonStarts = tokens[11].replace(/,$/, '').split(',');\n", "\n", " if (!(exonSizes.length === exonStarts.length && exonCount === exonSizes.length)) {\n", " return feature;\n", " }\n", "\n", " const exons = [];\n", "\n", " for (let i = 0; i < exonCount; i++) {\n", " const eStart = start + parseInt(exonStarts[i]);\n", " const eEnd = eStart + parseInt(exonSizes[i]);\n", " exons.push({\n", " start: eStart,\n", " end: eEnd\n", " });\n", " }\n", "\n", " findUTRs(exons, feature.cdStart, feature.cdEnd);\n", " feature.exons = exons;\n", " } // Optional extra columns\n", "\n", "\n", " if (header) {\n", " let thicknessColumn = header.thicknessColumn;\n", " let colorColumn = header.colorColumn;\n", "\n", " if (colorColumn && colorColumn < tokens.length) {\n", " feature.color = IGVColor.createColorString(tokens[colorColumn]);\n", " }\n", "\n", " if (thicknessColumn && thicknessColumn < tokens.length) {\n", " feature.thickness = tokens[thicknessColumn];\n", " }\n", " }\n", " } catch (e) {}\n", "\n", " return feature;\n", " }\n", " /**\n", " * Decode a UCSC repeat masker record.\n", " *\n", " * Columns, from UCSC documentation\n", " *\n", " * 0 bin 585 smallint(5) unsigned Indexing field to speed chromosome range queries.\n", " * 1 swScore 1504 int(10) unsigned Smith Waterman alignment score\n", " * 2 milliDiv 13 int(10) unsigned Base mismatches in parts per thousand\n", " * 3 milliDel 4 int(10) unsigned Bases deleted in parts per thousand\n", " * 4 milliIns 13 int(10) unsigned Bases inserted in parts per thousand\n", " * 5 genoName chr1 varchar(255) Genomic sequence name\n", " * 6 genoStart 10000 int(10) unsigned Start in genomic sequence\n", " * 7 genoEnd 10468 int(10) unsigned End in genomic sequence\n", " * 8 genoLeft -249240153 int(11) -#bases after match in genomic sequence\n", " * 9 strand + char(1) Relative orientation + or -\n", " * 10 repName (CCCTAA)n varchar(255) Name of repeat\n", " * 11 repClass Simple_repeat varchar(255) Class of repeat\n", " * 12 repFamily Simple_repeat varchar(255) Family of repeat\n", " * 13 repStart 1 int(11) Start (if strand is +) or -#bases after match (if strand is -) in repeat sequence\n", " * 14 repEnd 463 int(11) End in repeat sequence\n", " * 15 repLeft 0 int(11) -#bases after match (if strand is +) or start (if strand is -) in repeat sequence\n", " * 16 id 1 char(1) First digit of id field in RepeatMasker .out file. Best ignored.\n", " */\n", "\n", "\n", " function decodeRepeatMasker(tokens, header) {\n", " if (tokens.length <= 15) return undefined;\n", " const feature = {\n", " swScore: Number.parseInt(tokens[1]),\n", " milliDiv: Number.parseInt(tokens[2]),\n", " milliDel: Number.parseInt(tokens[3]),\n", " milliIns: Number.parseInt(tokens[4]),\n", " chr: tokens[5],\n", " start: Number.parseInt(tokens[6]),\n", " end: Number.parseInt(tokens[7]),\n", " //genoLeft: tokens[8],\n", " strand: tokens[9],\n", " repName: tokens[10],\n", " repClass: tokens[11],\n", " repFamily: tokens[12],\n", " repStart: Number.parseInt(tokens[13]),\n", " repEnd: Number.parseInt(tokens[14]),\n", " repLeft: Number.parseInt(tokens[15])\n", " };\n", " return feature;\n", " }\n", " /**\n", " * Decode a UCSC \"genePred\" record.\n", " *\n", " * @param tokens\n", " * @param ignore\n", " * @returns {*}\n", " */\n", "\n", "\n", " function decodeGenePred(tokens, header) {\n", " var shift = header.shift === undefined ? 0 : 1;\n", " if (tokens.length <= 9 + shift) return undefined;\n", " const cdStart = parseInt(tokens[5 + shift]);\n", " const cdEnd = parseInt(tokens[6 + shift]);\n", " var feature = {\n", " name: tokens[0 + shift],\n", " chr: tokens[1 + shift],\n", " strand: tokens[2 + shift],\n", " start: parseInt(tokens[3 + shift]),\n", " end: parseInt(tokens[4 + shift]),\n", " cdStart: cdStart,\n", " cdEnd: cdEnd,\n", " id: tokens[0 + shift]\n", " },\n", " exonCount = parseInt(tokens[7 + shift]),\n", " exonStarts = tokens[8 + shift].split(','),\n", " exonEnds = tokens[9 + shift].split(','),\n", " exons = [];\n", "\n", " for (let i = 0; i < exonCount; i++) {\n", " const start = parseInt(exonStarts[i]);\n", " const end = parseInt(exonEnds[i]);\n", " exons.push({\n", " start: start,\n", " end: end\n", " });\n", " }\n", "\n", " findUTRs(exons, cdStart, cdEnd);\n", " feature.exons = exons;\n", " return feature;\n", " }\n", " /**\n", " * Decode a UCSC \"genePredExt\" record. refGene files are in this format.\n", " *\n", " * @param tokens\n", " * @param ignore\n", " * @returns {*}\n", " */\n", "\n", "\n", " function decodeGenePredExt(tokens, header) {\n", " var shift = header.shift === undefined ? 0 : 1;\n", " if (tokens.length <= 11 + shift) return undefined;\n", " const cdStart = parseInt(tokens[5 + shift]);\n", " const cdEnd = parseInt(tokens[6 + shift]);\n", " const feature = {\n", " name: tokens[11 + shift],\n", " chr: tokens[1 + shift],\n", " strand: tokens[2 + shift],\n", " start: parseInt(tokens[3 + shift]),\n", " end: parseInt(tokens[4 + shift]),\n", " cdStart: cdStart,\n", " cdEnd: cdEnd,\n", " id: tokens[0 + shift]\n", " },\n", " exonCount = parseInt(tokens[7 + shift]),\n", " exonStarts = tokens[8 + shift].split(','),\n", " exonEnds = tokens[9 + shift].split(','),\n", " exons = [];\n", "\n", " for (let i = 0; i < exonCount; i++) {\n", " const start = parseInt(exonStarts[i]);\n", " const end = parseInt(exonEnds[i]);\n", " exons.push({\n", " start: start,\n", " end: end\n", " });\n", " }\n", "\n", " findUTRs(exons, cdStart, cdEnd);\n", " feature.exons = exons;\n", " return feature;\n", " }\n", " /**\n", " * Decode a UCSC \"refFlat\" record\n", " * @param tokens\n", " * @param ignore\n", " * @returns {*}\n", " */\n", "\n", "\n", " function decodeReflat(tokens, header) {\n", " var shift = header.shift === undefined ? 0 : 1;\n", " if (tokens.length <= 10 + shift) return undefined;\n", " const cdStart = parseInt(tokens[6 + shift]);\n", " const cdEnd = parseInt(tokens[7 + shift]);\n", " var feature = {\n", " name: tokens[0 + shift],\n", " id: tokens[1 + shift],\n", " chr: tokens[2 + shift],\n", " strand: tokens[3 + shift],\n", " start: parseInt(tokens[4 + shift]),\n", " end: parseInt(tokens[5 + shift]),\n", " cdStart: cdStart,\n", " cdEnd: cdEnd\n", " },\n", " exonCount = parseInt(tokens[8 + shift]),\n", " exonStarts = tokens[9 + shift].split(','),\n", " exonEnds = tokens[10 + shift].split(','),\n", " exons = [];\n", "\n", " for (let i = 0; i < exonCount; i++) {\n", " const start = parseInt(exonStarts[i]);\n", " const end = parseInt(exonEnds[i]);\n", " exons.push({\n", " start: start,\n", " end: end\n", " });\n", " }\n", "\n", " findUTRs(exons, cdStart, cdEnd);\n", " feature.exons = exons;\n", " return feature;\n", " }\n", "\n", " function findUTRs(exons, cdStart, cdEnd) {\n", " for (let exon of exons) {\n", " const end = exon.end;\n", " const start = exon.start;\n", "\n", " if (end < cdStart || start > cdEnd) {\n", " exon.utr = true;\n", " } else {\n", " if (cdStart >= start && cdStart <= end) {\n", " exon.cdStart = cdStart;\n", " }\n", "\n", " if (cdEnd >= start && cdEnd <= end) {\n", " exon.cdEnd = cdEnd;\n", " }\n", " }\n", " }\n", " }\n", "\n", " function decodePeak(tokens, header) {\n", " var tokenCount, chr, start, end, strand, name, score, qValue, signal, pValue;\n", " tokenCount = tokens.length;\n", "\n", " if (tokenCount < 9) {\n", " return undefined;\n", " }\n", "\n", " chr = tokens[0];\n", " start = parseInt(tokens[1]);\n", " end = parseInt(tokens[2]);\n", " name = tokens[3];\n", " score = parseFloat(tokens[4]);\n", " strand = tokens[5].trim();\n", " signal = parseFloat(tokens[6]);\n", " pValue = parseFloat(tokens[7]);\n", " qValue = parseFloat(tokens[8]);\n", " if (score === 0) score = signal;\n", " return {\n", " chr: chr,\n", " start: start,\n", " end: end,\n", " name: name,\n", " score: score,\n", " strand: strand,\n", " signal: signal,\n", " pValue: pValue,\n", " qValue: qValue\n", " };\n", " }\n", "\n", " function decodeBedGraph(tokens, header) {\n", " var chr, start, end, value;\n", " if (tokens.length <= 3) return undefined;\n", " chr = tokens[0];\n", " start = parseInt(tokens[1]);\n", " end = parseInt(tokens[2]);\n", " value = parseFloat(tokens[3]);\n", " const feature = {\n", " chr: chr,\n", " start: start,\n", " end: end,\n", " value: value\n", " }; // Optional extra columns\n", "\n", " if (header) {\n", " let colorColumn = header.colorColumn;\n", "\n", " if (colorColumn && colorColumn < tokens.length) {\n", " feature.color = IGVColor.createColorString(tokens[colorColumn]);\n", " }\n", " }\n", "\n", " return feature;\n", " }\n", "\n", " function decodeWig(tokens, header) {\n", " const wig = header.wig;\n", "\n", " if (wig && wig.format === \"fixedStep\") {\n", " const ss = wig.index * wig.step + wig.start;\n", " const ee = ss + wig.span;\n", " const value = parseFloat(tokens[0]);\n", " ++wig.index;\n", " return isNaN(value) ? null : {\n", " chr: wig.chrom,\n", " start: ss,\n", " end: ee,\n", " value: value\n", " };\n", " } else if (wig && wig.format === \"variableStep\") {\n", " if (tokens.length < 2) return null;\n", " const ss = parseInt(tokens[0], 10) - 1;\n", " const ee = ss + wig.span;\n", " const value = parseFloat(tokens[1]);\n", " return isNaN(value) ? null : {\n", " chr: wig.chrom,\n", " start: ss,\n", " end: ee,\n", " value: value\n", " };\n", " } else {\n", " return decodeBedGraph(tokens);\n", " }\n", " }\n", "\n", " function decodeSNP(tokens, header) {\n", " if (tokens.length < 6) return undefined;\n", " 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'];\n", " const feature = {\n", " chr: tokens[1],\n", " start: Number.parseInt(tokens[2]),\n", " end: Number.parseInt(tokens[3]),\n", " name: tokens[4],\n", " score: Number.parseInt(tokens[5])\n", " };\n", " const n = Math.min(tokens.length, autoSql.length);\n", "\n", " for (let i = 6; i < n; i++) {\n", " feature[autoSql[i]] = tokens[i];\n", " }\n", "\n", " return feature;\n", " }\n", "\n", " /*\n", " * The MIT License (MIT)\n", " *\n", " * Copyright (c) 2014 Broad Institute\n", " *\n", " * Permission is hereby granted, free of charge, to any person obtaining a copy\n", " * of this software and associated documentation files (the \"Software\"), to deal\n", " * in the Software without restriction, including without limitation the rights\n", " * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n", " * copies of the Software, and to permit persons to whom the Software is\n", " * furnished to do so, subject to the following conditions:\n", " *\n", " * The above copyright notice and this permission notice shall be included in\n", " * all copies or substantial portions of the Software.\n", " *\n", " *\n", " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n", " * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n", " * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n", " * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n", " * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n", " * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n", " * THE SOFTWARE.\n", " */\n", " /**\n", " * Parser for column style (tab delimited, etc) text file formats (bed, gff, vcf, etc).\n", " *\n", " *\n", " */\n", "\n", " /**\n", " * Return a parser for the given file format.\n", " */\n", "\n", " class FeatureParser {\n", " constructor(config) {\n", " this.config = config;\n", " this.header = {};\n", "\n", " if (config.nameField) {\n", " this.header.nameField = config.nameField;\n", " }\n", "\n", " this.skipRows = 0; // The number of fixed header rows to skip. Override for specific types as needed\n", "\n", " if (config.decode) {\n", " this.decode = config.decode;\n", " this.delimiter = config.delimiter || \"\\t\";\n", " } else if (config.format) {\n", " this.header.format = config.format.toLowerCase();\n", " this.setDecoder(this.header.format);\n", " }\n", "\n", " if (!this.delimiter) {\n", " this.delimiter = \"\\t\";\n", " }\n", " }\n", " /**\n", " * Parse metadata from the file. A variety of conventions are in use to supply metadata about file contents\n", " * through header lines (e.g. 'track') and # directives. This method unifies metadata as properties of a\n", " * 'header' object.\n", " *\n", " * @param data\n", " * @returns {{}}\n", " */\n", "\n", "\n", " async parseHeader(dataWrapper) {\n", " let header = this.header;\n", " let columnNames;\n", " let line;\n", "\n", " while ((line = await dataWrapper.nextLine()) !== undefined) {\n", " if (line.startsWith(\"track\") || line.startsWith(\"#track\")) {\n", " let h = parseTrackLine(line);\n", " Object.assign(header, h);\n", " } else if (line.startsWith(\"browser\")) ; else if (line.startsWith(\"#columns\")) {\n", " let h = parseColumnsDirective(line);\n", " Object.assign(header, h);\n", " } else if (line.startsWith(\"##gff-version 3\")) {\n", " header.format = \"gff3\";\n", " } else if (line.startsWith(\"#gffTags\")) {\n", " header.gffTags = true;\n", " } else if (line.startsWith(\"fixedStep\") || line.startsWith(\"variableStep\")) {\n", " // Wig directives -- we are in the data section\n", " break;\n", " } else if (line.startsWith(\"#\")) {\n", " const tokens = line.split(this.delimiter || \"\\t\");\n", "\n", " if (tokens.length > 1) {\n", " columnNames = tokens; // Possible column names\n", " }\n", " } else {\n", " // All directives that could change the format, and thus decoder, should have been read by now.\n", " this.setDecoder(header.format); // If the line can be parsed as a feature assume we are beyond the header, if any\n", "\n", " try {\n", " const tokens = line.split(this.delimiter || \"\\t\");\n", " const tmpHeader = Object.assign({\n", " columnNames\n", " }, header);\n", "\n", " if (this.decode(tokens, tmpHeader)) {\n", " break;\n", " } else {\n", " if (tokens.length > 1) {\n", " columnNames = tokens; // possible column names\n", " }\n", " }\n", " } catch (e) {// Not a feature\n", " }\n", " }\n", " }\n", "\n", " if (columnNames) {\n", " header.columnNames = columnNames;\n", "\n", " for (let n = 0; n < columnNames.length; n++) {\n", " if (columnNames[n] === \"color\" || columnNames[n] === \"colour\") {\n", " header.colorColumn = n;\n", " } else if (columnNames[n] === \"thickness\") {\n", " header.thicknessColumn = n;\n", " }\n", " }\n", " }\n", "\n", " this.header = header; // Directives might be needed for parsing lines\n", "\n", " return header;\n", " }\n", "\n", " async parseFeatures(dataWrapper) {\n", " const allFeatures = [];\n", " const decode = this.decode;\n", " const format = this.header.format;\n", " const delimiter = this.delimiter || \"\\t\";\n", " let i = 0;\n", " let line;\n", "\n", " while ((line = await dataWrapper.nextLine()) !== undefined) {\n", " i++;\n", " if (i <= this.skipRows) continue;\n", "\n", " if (!line || line.startsWith(\"track\") || line.startsWith(\"#\") || line.startsWith(\"browser\")) {\n", " continue;\n", " } else if (format === \"wig\" && line.startsWith(\"fixedStep\")) {\n", " this.header.wig = parseFixedStep(line);\n", " continue;\n", " } else if (format === \"wig\" && line.startsWith(\"variableStep\")) {\n", " this.header.wig = parseVariableStep(line);\n", " continue;\n", " }\n", "\n", " const tokens = line.split(delimiter);\n", "\n", " if (tokens.length < 1) {\n", " continue;\n", " }\n", "\n", " const feature = decode(tokens, this.header);\n", "\n", " if (feature) {\n", " allFeatures.push(feature);\n", " }\n", " } // Special hack for bedPE\n", "\n", "\n", " if (decode === decodeBedpe) {\n", " fixBedPE(allFeatures);\n", " }\n", "\n", " return allFeatures;\n", " }\n", "\n", " setDecoder(format) {\n", " switch (format) {\n", " case \"narrowpeak\":\n", " case \"broadpeak\":\n", " case \"regionpeak\":\n", " case \"peaks\":\n", " this.decode = decodePeak;\n", " this.delimiter = this.config.delimiter || /\\s+/;\n", " break;\n", "\n", " case \"bedgraph\":\n", " this.decode = decodeBedGraph;\n", " this.delimiter = /\\s+/;\n", " break;\n", "\n", " case \"wig\":\n", " this.decode = decodeWig;\n", " this.delimiter = this.config.delimiter || /\\s+/;\n", " break;\n", "\n", " case \"gff3\":\n", " case \"gff\":\n", " case \"gtf\":\n", " this.decode = decodeGFF;\n", " this.delimiter = \"\\t\";\n", " break;\n", "\n", " case \"fusionjuncspan\":\n", " // bhaas, needed for FusionInspector view\n", " this.decode = decodeFusionJuncSpan;\n", " this.delimiter = this.config.delimiter || /\\s+/;\n", " break;\n", "\n", " case \"gtexgwas\":\n", " this.skipRows = 1;\n", " this.decode = decodeGtexGWAS;\n", " this.delimiter = \"\\t\";\n", " break;\n", "\n", " case \"refflat\":\n", " this.decode = decodeReflat;\n", " this.delimiter = this.config.delimiter || /\\s+/;\n", " break;\n", "\n", " case \"genepred\":\n", " this.decode = decodeGenePred;\n", " this.delimiter = this.config.delimiter || /\\s+/;\n", " break;\n", "\n", " case \"genepredext\":\n", " this.decode = decodeGenePredExt;\n", " this.delimiter = this.config.delimiter || /\\s+/;\n", " break;\n", "\n", " case \"ensgene\":\n", " this.decode = decodeGenePred;\n", " this.header.shift = 1;\n", " this.delimiter = this.config.delimiter || /\\s+/;\n", " break;\n", "\n", " case \"refgene\":\n", " this.decode = decodeGenePredExt;\n", " this.delimiter = this.config.delimiter || /\\s+/;\n", " this.header.shift = 1;\n", " break;\n", "\n", " case \"bed\":\n", " this.decode = decodeBed;\n", " this.delimiter = this.config.delimiter || /\\s+/;\n", " break;\n", "\n", " case \"bedpe\":\n", " this.decode = decodeBedpe;\n", " this.delimiter = this.config.delimiter || \"\\t\";\n", " break;\n", "\n", " case \"bedpe-domain\":\n", " this.decode = decodeBedpeDomain;\n", " this.headerLine = true;\n", " this.delimiter = this.config.delimiter || \"\\t\";\n", " break;\n", "\n", " case \"bedpe-loop\":\n", " this.decode = decodeBedpe;\n", " this.delimiter = this.config.delimiter || \"\\t\";\n", " this.header = {\n", " colorColumn: 7\n", " };\n", " break;\n", "\n", " case \"interact\":\n", " this.decode = decodeInteract;\n", " this.delimiter = this.config.delimiter || /\\s+/;\n", " break;\n", "\n", " case \"snp\":\n", " this.decode = decodeSNP;\n", " this.delimiter = \"\\t\";\n", " break;\n", "\n", " case \"rmsk\":\n", " this.decode = decodeRepeatMasker;\n", " this.delimiter = \"\\t\";\n", " break;\n", "\n", " case \"gcnv\":\n", " this.decode = decodeGcnv;\n", " this.delimiter = \"\\t\";\n", " break;\n", "\n", " default:\n", " const customFormat = getFormat(format);\n", "\n", " if (customFormat !== undefined) {\n", " this.decode = decodeCustom;\n", " this.header.customFormat = customFormat;\n", " this.delimiter = customFormat.delimiter || \"\\t\";\n", " } else {\n", " this.decode = decodeBed;\n", " this.delimiter = this.config.delimiter || /\\s+/;\n", " }\n", "\n", " }\n", " }\n", "\n", " }\n", "\n", " function parseTrackLine(line) {\n", " const properties = {};\n", " const tokens = line.split(/(?:\")([^\"]+)(?:\")|([^\\s\"]+)(?=\\s+|$)/g); // Clean up tokens array\n", "\n", " let curr;\n", " const tmp = [];\n", "\n", " for (let tk of tokens) {\n", " if (!tk || tk.trim().length === 0) continue;\n", "\n", " if (tk.endsWith(\"=\")) {\n", " curr = tk;\n", " } else if (curr) {\n", " tmp.push(curr + tk);\n", " curr = undefined;\n", " } else {\n", " tmp.push(tk);\n", " }\n", " }\n", "\n", " for (let str of tmp) {\n", " if (!str) return;\n", " var kv = str.split('=', 2);\n", "\n", " if (kv.length === 2) {\n", " const key = kv[0].trim();\n", " const value = kv[1].trim();\n", "\n", " if (properties.hasOwnProperty(key)) {\n", " let currentValue = properties[key];\n", "\n", " if (Array.isArray(currentValue)) {\n", " currentValue.push(value);\n", " } else {\n", " properties[key] = [currentValue, value];\n", " }\n", " } else {\n", " properties[key] = value;\n", " }\n", " }\n", " }\n", "\n", " if (\"interact\" == properties[\"type\"]) {\n", " properties[\"format\"] = \"interact\";\n", " } else if (\"gcnv\" === properties[\"type\"]) {\n", " properties[\"format\"] = \"gcnv\";\n", " }\n", "\n", " return properties;\n", " }\n", "\n", " function parseColumnsDirective(line) {\n", " let properties = {};\n", " let t1 = line.split(/\\s+/);\n", "\n", " if (t1.length === 2) {\n", " let t2 = t1[1].split(\";\");\n", " t2.forEach(function (keyValue) {\n", " let t = keyValue.split(\"=\");\n", "\n", " if (t[0] === \"color\") {\n", " properties.colorColumn = Number.parseInt(t[1]) - 1;\n", " } else if (t[0] === \"thickness\") {\n", " properties.thicknessColumn = Number.parseInt(t[1]) - 1;\n", " }\n", " });\n", " }\n", "\n", " return properties;\n", " }\n", "\n", " function parseFixedStep(line) {\n", " const tokens = line.split(/\\s+/);\n", " const chrom = tokens[1].split(\"=\")[1];\n", " const start = parseInt(tokens[2].split(\"=\")[1], 10) - 1;\n", " const step = parseInt(tokens[3].split(\"=\")[1], 10);\n", " const span = tokens.length > 4 ? parseInt(tokens[4].split(\"=\")[1], 10) : 1;\n", " return {\n", " format: \"fixedStep\",\n", " chrom,\n", " start,\n", " step,\n", " span,\n", " index: 0\n", " };\n", " }\n", "\n", " function parseVariableStep(line) {\n", " const tokens = line.split(/\\s+/);\n", " const chrom = tokens[1].split(\"=\")[1];\n", " const span = tokens.length > 2 ? parseInt(tokens[2].split(\"=\")[1], 10) : 1;\n", " return {\n", " format: \"variableStep\",\n", " chrom,\n", " span\n", " };\n", " }\n", "\n", " /*\n", " * The MIT License (MIT)\n", " *\n", " * Copyright (c) 2018 Regents of the University of California\n", " *\n", " * Permission is hereby granted, free of charge, to any person obtaining a copy\n", " * of this software and associated documentation files (the \"Software\"), to deal\n", " * in the Software without restriction, including without limitation the rights\n", " * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n", " * copies of the Software, and to permit persons to whom the Software is\n", " * furnished to do so, subject to the following conditions:\n", " *\n", " * The above copyright notice and this permission notice shall be included in\n", " * all copies or substantial portions of the Software.\n", " *\n", " *\n", " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n", " * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n", " * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n", " * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n", " * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n", " * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n", " * THE SOFTWARE.\n", " */\n", " /**\n", " * A collection of properties and methods shared by all (or most) track types.\n", " *\n", " * @param config\n", " * @param browser\n", " * @constructor\n", " */\n", "\n", " class TrackBase {\n", " constructor(config, browser) {\n", " if (config.displayMode) {\n", " config.displayMode = config.displayMode.toUpperCase();\n", " }\n", "\n", " this.config = config;\n", " this.browser = browser;\n", " this.url = config.url;\n", " this.type = config.type;\n", " this.description = config.description;\n", " this.supportHiDPI = config.supportHiDPI === undefined ? true : config.supportHiDPI;\n", "\n", " if (config.name || config.label) {\n", " this.name = config.name || config.label;\n", " } else {\n", " if (isFile(config.url)) this.name = config.url.name;else this.name = config.url;\n", " }\n", "\n", " this.id = this.config.id === undefined ? this.name : this.config.id;\n", " this.order = config.order;\n", " this.color = config.color;\n", " this.altColor = config.altColor;\n", "\n", " if (\"civic-ws\" === config.sourceType) {\n", " // Ugly proxy for specialized track type\n", " this.defaultColor = \"rgb(155,20,20)\";\n", " } else {\n", " this.defaultColor = \"rgb(0,0,150)\";\n", " }\n", "\n", " this.autoscaleGroup = config.autoscaleGroup;\n", " this.removable = config.removable === undefined ? true : config.removable; // Defaults to true\n", "\n", " this.height = config.height || 100;\n", " this.autoHeight = config.autoHeight;\n", " this.minHeight = config.minHeight || Math.min(25, this.height);\n", " this.maxHeight = config.maxHeight || Math.max(1000, this.height);\n", " this.visibilityWindow = config.visibilityWindow;\n", " }\n", " /**\n", " * Default implementation -- update config with current values.\n", " * to create session object for bookmarking, sharing. Updates the track \"config\" object to reflect the\n", " * current state. Only simple properties (string, number, boolean) are updated.\n", " */\n", "\n", "\n", " getState() {\n", " // Create copy of config, minus transient properties (convention is name starts with '_')\n", " const state = {};\n", "\n", " for (let key of Object.keys(this.config)) {\n", " if (!key.startsWith(\"_\")) {\n", " state[key] = this.config[key];\n", " }\n", " } // Update original config values with any changes\n", "\n", "\n", " for (let key of Object.keys(state)) {\n", " if (key.startsWith(\"_\")) continue; // transient property\n", "\n", " const value = this[key];\n", "\n", " if (value && (isSimpleType(value) || typeof value === \"boolean\")) {\n", " state[key] = value;\n", " }\n", " }\n", "\n", " if (this.color) state.color = this.color;\n", " if (this.altColor) state.altColor = this.altColor; // Flatten dataRange if present\n", "\n", " if (!this.autoscale && this.dataRange) {\n", " if (state.min !== undefined && state.min !== null) {\n", " state.min = this.dataRange.min;\n", " }\n", "\n", " if (state.max !== undefined && state.max !== null) {\n", " state.max = this.dataRange.max;\n", " }\n", " } // Check for non-json-if-yable properties. Perhaps we should test what can be saved.\n", "\n", "\n", " for (let key of Object.keys(state)) {\n", " if (typeof state[key] === 'function') {\n", " throw Error(`Property '${key}' of track '${this.name} is a function. Functions cannot be saved in sessions.`);\n", " }\n", "\n", " if (state[key] instanceof File) {\n", " throw Error(`Property '${key}' of track '${this.name} is a local File. Local file references cannot be saved in sessions.`);\n", " }\n", "\n", " if (state[key] instanceof Promise) {\n", " throw Error(`Property '${key}' of track '${this.name} is a Promise. Promises cannot be saved in sessions.`);\n", " }\n", " } // Remove properties with undefined values, no reason to save these\n", "\n", "\n", " let keys = Object.keys(state);\n", "\n", " for (let key of keys) {\n", " if (state[key] === undefined) {\n", " delete state[key];\n", " }\n", " }\n", "\n", " return state;\n", " }\n", "\n", " supportsWholeGenome() {\n", " return false;\n", " }\n", "\n", " getGenomeId() {\n", " return this.browser.genome ? this.browser.genome.id : undefined;\n", " }\n", " /**\n", " * Set certain track properties, usually from a \"track\" line. Not all UCSC properties are supported.\n", " *\n", " * Track configuration settings have precendence over track line properties, so if both are present ignore the\n", " * track line.\n", " *\n", " * @param properties\n", " */\n", "\n", "\n", " setTrackProperties(properties) {\n", " const tracklineConfg = {};\n", " let tokens;\n", "\n", " for (let key of Object.keys(properties)) {\n", " switch (key.toLowerCase()) {\n", " case \"usescore\":\n", " tracklineConfg.useScore = properties[key] === 1 || properties[key] === \"1\" || properties[key] === \"on\" || properties[key] === true;\n", " break;\n", "\n", " case \"visibility\":\n", " //0 - hide, 1 - dense, 2 - full, 3 - pack, and 4 - squish\n", " switch (properties[key]) {\n", " case \"2\":\n", " case \"3\":\n", " case \"pack\":\n", " case \"full\":\n", " tracklineConfg.displayMode = \"EXPANDED\";\n", " break;\n", "\n", " case \"4\":\n", " case \"squish\":\n", " tracklineConfg.displayMode = \"SQUISHED\";\n", " break;\n", "\n", " case \"1\":\n", " case \"dense\":\n", " tracklineConfg.displayMode = \"COLLAPSED\";\n", " }\n", "\n", " break;\n", "\n", " case \"color\":\n", " case \"altcolor\":\n", " tracklineConfg[key] = properties[key].startsWith(\"rgb(\") ? properties[key] : \"rgb(\" + properties[key] + \")\";\n", " break;\n", "\n", " case \"featurevisiblitywindow\":\n", " case \"visibilitywindow\":\n", " tracklineConfg.visibilityWindow = Number.parseInt(properties[key]);\n", " break;\n", "\n", " case \"maxheightpixels\":\n", " tokens = properties[key].split(\":\");\n", "\n", " if (tokens.length === 3) {\n", " tracklineConfg.minHeight = Number.parseInt(tokens[2]);\n", " tracklineConfg.height = Number.parseInt(tokens[1]);\n", " tracklineConfg.maxHeight = Number.parseInt(tokens[0]);\n", " }\n", "\n", " break;\n", "\n", " case \"viewlimits\":\n", " if (!this.config.autoscale) {\n", " // autoscale in the config has precedence\n", " tokens = properties[key].split(\":\");\n", " let min = 0;\n", " let max;\n", "\n", " if (tokens.length == 1) {\n", " max = Number.parseFloat(tokens[0]);\n", " } else if (tokens.length == 2) {\n", " min = Number.parseFloat(tokens[0]);\n", " max = Number.parseFloat(tokens[1]);\n", " }\n", "\n", " tracklineConfg.autoscale = false;\n", " tracklineConfg.dataRange = {\n", " min,\n", " max\n", " };\n", " }\n", "\n", " case \"name\":\n", " tracklineConfg[key] = properties[key];\n", " }\n", " } // Track configuration objects have precendence over track line properties\n", "\n", "\n", " for (let key of Object.keys(tracklineConfg)) {\n", " if (!this.config.hasOwnProperty(key)) {\n", " this[key] = tracklineConfg[key];\n", " }\n", " }\n", " }\n", "\n", " getVisibilityWindow() {\n", " return this.visibilityWindow;\n", " }\n", "\n", " clickedFeatures(clickState) {\n", " // We use the cached features rather than method to avoid async load. If the\n", " // feature is not already loaded this won't work, but the user wouldn't be mousing over it either.\n", " const features = clickState.viewport.getCachedFeatures();\n", "\n", " if (!features || features.length === 0) {\n", " return [];\n", " }\n", "\n", " const genomicLocation = clickState.genomicLocation; // When zoomed out we need some tolerance around genomicLocation\n", "\n", " const tolerance = clickState.referenceFrame.bpPerPixel > 0.2 ? 3 * clickState.referenceFrame.bpPerPixel : 0;\n", " const ss = Math.floor(genomicLocation) - tolerance;\n", " const ee = Math.floor(genomicLocation) + tolerance;\n", " return FeatureUtils.findOverlapping(features, ss, ee);\n", " }\n", " /**\n", " * Default popup text function -- just extracts string and number properties in random order.\n", " * @param feature\n", " * @returns {Array}\n", " */\n", "\n", "\n", " static extractPopupData(feature, genomeId) {\n", " const filteredProperties = new Set(['row', 'color', 'chr', 'start', 'end', 'cdStart', 'cdEnd', 'strand', 'alpha']);\n", " const data = [];\n", " let alleles, alleleFreqs;\n", "\n", " for (var property in feature) {\n", " if (feature.hasOwnProperty(property) && !filteredProperties.has(property) && isSimpleType(feature[property])) {\n", " let value = feature[property];\n", " data.push({\n", " name: capitalize(property),\n", " value: value\n", " });\n", "\n", " if (property === \"alleles\") {\n", " alleles = feature[property];\n", " } else if (property === \"alleleFreqs\") {\n", " alleleFreqs = feature[property];\n", " }\n", " }\n", " } //const genomeId = this.getGenomeId()\n", "\n", "\n", " if (alleles && alleleFreqs) {\n", " if (alleles.endsWith(\",\")) {\n", " alleles = alleles.substr(0, alleles.length - 1);\n", " }\n", "\n", " if (alleleFreqs.endsWith(\",\")) {\n", " alleleFreqs = alleleFreqs.substr(0, alleleFreqs.length - 1);\n", " }\n", "\n", " let a = alleles.split(\",\");\n", " let af = alleleFreqs.split(\",\");\n", "\n", " if (af.length > 1) {\n", " let b = [];\n", "\n", " for (let i = 0; i < af.length; i++) {\n", " b.push({\n", " a: a[i],\n", " af: Number.parseFloat(af[i])\n", " });\n", " }\n", "\n", " b.sort(function (x, y) {\n", " return x.af - y.af;\n", " });\n", " let ref = b[b.length - 1].a;\n", "\n", " if (ref.length === 1) {\n", " for (let i = b.length - 2; i >= 0; i--) {\n", " let alt = b[i].a;\n", "\n", " if (alt.length === 1) {\n", " const cravatLink = TrackBase.getCravatLink(feature.chr, feature.start + 1, ref, alt, genomeId);\n", "\n", " if (cravatLink) {\n", " data.push(\"
\");\n", " data.push(cravatLink);\n", " }\n", " }\n", " }\n", " }\n", " }\n", " }\n", "\n", " if (feature.attributes) {\n", " for (let key of Object.keys(feature.attributes)) {\n", " data.push({\n", " name: key,\n", " value: feature.attributes[key]\n", " });\n", " }\n", " } // final chr position\n", "\n", "\n", " let posString = `${feature.chr}:${numberFormatter(feature.start + 1)}-${numberFormatter(feature.end)}`;\n", "\n", " if (feature.strand) {\n", " posString += ` (${feature.strand})`;\n", " }\n", "\n", " data.push('');\n", " data.push(posString);\n", " return data;\n", " }\n", "\n", " static getCravatLink(chr, position, ref, alt, genomeID) {\n", " if (\"hg38\" === genomeID || \"GRCh38\" === genomeID) {\n", " const cravatChr = chr.startsWith(\"chr\") ? chr : \"chr\" + chr;\n", " return `Cravat ${ref}->${alt}`; // return \"Cravat \" + ref + \"->\" + alt + \"\"\n", " } else {\n", " return undefined;\n", " }\n", " }\n", "\n", " }\n", "\n", " /*\n", " * The MIT License (MIT)\n", " *\n", " * Copyright (c) 2014 Broad Institute\n", " *\n", " * Permission is hereby granted, free of charge, to any person obtaining a copy\n", " * of this software and associated documentation files (the \"Software\"), to deal\n", " * in the Software without restriction, including without limitation the rights\n", " * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n", " * copies of the Software, and to permit persons to whom the Software is\n", " * furnished to do so, subject to the following conditions:\n", " *\n", " * The above copyright notice and this permission notice shall be included in\n", " * all copies or substantial portions of the Software.\n", " *\n", " *\n", " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n", " * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n", " * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n", " * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n", " * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n", " * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n", " * THE SOFTWARE.\n", " */\n", " const knownAltBases = new Set([\"A\", \"C\", \"T\", \"G\"].map(c => c.charCodeAt(0)));\n", "\n", " function createVCFVariant(tokens) {\n", " return new Variant(tokens);\n", " }\n", "\n", " class Variant {\n", " constructor(tokens) {\n", " this.chr = tokens[0]; // TODO -- use genome aliases\n", "\n", " this.pos = parseInt(tokens[1]);\n", " this.names = tokens[2]; // id in VCF\n", "\n", " this.referenceBases = tokens[3];\n", " this.alternateBases = tokens[4];\n", " this.quality = tokens[5];\n", " this.filter = tokens[6];\n", " this.info = getInfoObject(tokens[7]);\n", " this.init();\n", " }\n", "\n", " init() {\n", " const ref = this.referenceBases;\n", " const altBases = this.alternateBases;\n", "\n", " if (this.info) {\n", " if (this.info[\"VT\"]) {\n", " this.type = this.info[\"VT\"];\n", " } else if (this.info[\"SVTYPE\"]) {\n", " this.type = \"SV\";\n", " } else if (this.info[\"PERIOD\"]) {\n", " this.type = \"STR\";\n", " }\n", " }\n", "\n", " if (this.type === undefined) {\n", " this.type = determineType(ref, altBases);\n", " }\n", "\n", " if (this.type === \"NONVARIANT\") {\n", " this.heterozygosity = 0;\n", " } // Determine start/end coordinates -- these are the coordinates representing the actual variant,\n", " // not the leading or trailing reference\n", "\n", "\n", " if (this.info[\"END\"]) {\n", " this.start = this.pos - 1;\n", "\n", " if (this.info[\"CHR2\"] && this.info[\"CHR2\"] !== this.chr) {\n", " this.end = this.start + 1;\n", " } else {\n", " this.end = Number.parseInt(this.info[\"END\"]);\n", " }\n", " } else {\n", " if (this.type === \"NONVARIANT\") {\n", " this.start = this.pos - 1; // convert to 0-based coordinate convention\n", "\n", " this.end = this.start + ref.length;\n", " } else {\n", " const altTokens = altBases.split(\",\").filter(token => token.length > 0);\n", " this.alleles = [];\n", " this.start = undefined;\n", " this.end = undefined;\n", "\n", " for (let alt of altTokens) {\n", " this.alleles.push(alt); // We don't yet handle SV and other special alt representations\n", "\n", " if (\"SV\" !== this.type && isKnownAlt(alt)) {\n", " let altLength = alt.length;\n", " let lengthOnRef = ref.length; // Trim off matching bases. Try first match, then right -> left, then any remaining left -> right\n", "\n", " let s = 0;\n", "\n", " if (ref.charCodeAt(0) === alt.charCodeAt(0)) {\n", " s++;\n", " altLength--;\n", " lengthOnRef--;\n", " } // right -> left from end\n", "\n", "\n", " while (altLength > 0 && lengthOnRef > 0) {\n", " const altIdx = s + altLength - 1;\n", " const refIdx = s + lengthOnRef - 1;\n", "\n", " if (alt.charCodeAt(altIdx) === ref.charCodeAt(refIdx)) {\n", " altLength--;\n", " lengthOnRef--;\n", " } else {\n", " break;\n", " }\n", " } // if any remaining, left -> right\n", "\n", "\n", " while (altLength > 0 && lengthOnRef > 0) {\n", " const altIdx = s;\n", " const refIdx = s;\n", "\n", " if (alt.charCodeAt(altIdx) === ref.charCodeAt(refIdx)) {\n", " s++;\n", " altLength--;\n", " lengthOnRef--;\n", " } else {\n", " break;\n", " }\n", " }\n", "\n", " const alleleStart = this.pos + s - 1; // -1 for zero based coordinates\n", "\n", " const alleleEnd = alleleStart + lengthOnRef; // insertions have zero length on ref, but we give them 1\n", "\n", " this.start = this.start === undefined ? alleleStart : Math.min(this.start, alleleStart);\n", " this.end = this.end === undefined ? alleleEnd : Math.max(this.end, alleleEnd);\n", " }\n", " } // Default to single base representation @ position for variant types not otherwise handled\n", "\n", "\n", " if (this.start === undefined) {\n", " this.start = this.pos - 1;\n", " this.end = this.pos;\n", " }\n", " }\n", " }\n", " }\n", "\n", " popupData(genomicLocation, genomeId) {\n", " var self = this,\n", " fields,\n", " gt;\n", " const posString = this.end === this.pos ? this.pos : `${this.pos}-${this.end}`;\n", " fields = [{\n", " name: \"Chr\",\n", " value: this.chr\n", " }, {\n", " name: \"Pos\",\n", " value: posString\n", " }, {\n", " name: \"Names\",\n", " value: this.names ? this.names : \"\"\n", " }, {\n", " name: \"Ref\",\n", " value: this.referenceBases\n", " }, {\n", " name: \"Alt\",\n", " value: this.alternateBases.replace(\"<\", \"<\")\n", " }, {\n", " name: \"Qual\",\n", " value: this.quality\n", " }, {\n", " name: \"Filter\",\n", " value: this.filter\n", " }];\n", "\n", " if (\"SNP\" === this.type) {\n", " let ref = this.referenceBases;\n", "\n", " if (ref.length === 1) {\n", " let altArray = this.alternateBases.split(\",\");\n", "\n", " for (let alt of altArray) {\n", " if (alt.length === 1) {\n", " let l = TrackBase.getCravatLink(this.chr, this.pos, ref, alt, genomeId);\n", "\n", " if (l) {\n", " fields.push(\"
\");\n", " fields.push(l);\n", " }\n", " }\n", " }\n", " }\n", " }\n", "\n", " if (this.hasOwnProperty(\"heterozygosity\")) {\n", " fields.push({\n", " name: \"Heterozygosity\",\n", " value: this.heterozygosity\n", " });\n", " }\n", "\n", " if (this.info) {\n", " fields.push('
');\n", " Object.keys(this.info).forEach(function (key) {\n", " fields.push({\n", " name: key,\n", " value: arrayToString(self.info[key])\n", " });\n", " });\n", " } // Special case of VCF with a single sample\n", "\n", "\n", " if (this.calls && this.calls.length === 1) {\n", " fields.push('
');\n", " gt = this.alleles[this.calls[0].genotype[0]] + this.alleles[this.calls[0].genotype[1]];\n", " fields.push({\n", " name: \"Genotype\",\n", " value: gt\n", " });\n", " }\n", "\n", " return fields;\n", " }\n", "\n", " isRefBlock() {\n", " return \"NONVARIANT\" === this.type;\n", " }\n", "\n", " }\n", "\n", " function getInfoObject(infoStr) {\n", " var info = {};\n", "\n", " if (infoStr) {\n", " infoStr.split(';').forEach(function (elem) {\n", " var element = elem.split('=');\n", " info[element[0]] = element[1];\n", " });\n", " }\n", "\n", " return info;\n", " }\n", "\n", " function isKnownAlt(alt) {\n", " for (let i = 0; i < alt.length; i++) {\n", " if (!knownAltBases.has(alt.charCodeAt(i))) {\n", " return false;\n", " }\n", " }\n", "\n", " return true;\n", " }\n", "\n", " function determineType(ref, altAlleles) {\n", " const refLength = ref.length;\n", "\n", " if (altAlleles === undefined) {\n", " return \"UNKNOWN\";\n", " } else if (altAlleles.trim().length === 0 || altAlleles === \"\" || altAlleles === \"<*>\" || altAlleles === \".\") {\n", " return \"NONVARIANT\";\n", " } else {\n", " const alleles = altAlleles.split(\",\");\n", " const types = alleles.map(function (a) {\n", " if (refLength === 1 && a.length === 1) {\n", " return \"SNP\";\n", " } else {\n", " return \"\" === a ? \"NONVARIANT\" : \"OTHER\";\n", " }\n", " });\n", " let type = types[0];\n", "\n", " for (let t of types) {\n", " if (t !== type) {\n", " return \"MIXED\";\n", " }\n", " }\n", "\n", " return type;\n", " }\n", " }\n", "\n", " function arrayToString(value, delim) {\n", " if (delim === undefined) delim = \",\";\n", "\n", " if (!Array.isArray(value)) {\n", " return value;\n", " }\n", "\n", " return value.join(delim);\n", " }\n", "\n", " /*\n", " * The MIT License (MIT)\n", " *\n", " * Copyright (c) 2014 Broad Institute\n", " *\n", " * Permission is hereby granted, free of charge, to any person obtaining a copy\n", " * of this software and associated documentation files (the \"Software\"), to deal\n", " * in the Software without restriction, including without limitation the rights\n", " * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n", " * copies of the Software, and to permit persons to whom the Software is\n", " * furnished to do so, subject to the following conditions:\n", " *\n", " * The above copyright notice and this permission notice shall be included in\n", " * all copies or substantial portions of the Software.\n", " *\n", " *\n", " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n", " * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n", " * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n", " * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n", " * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n", " * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n", " * THE SOFTWARE.\n", " */\n", " /**\n", " * Parser for VCF files.\n", " */\n", "\n", " class VcfParser {\n", " construtor() {}\n", "\n", " async parseHeader(dataWrapper) {\n", " const header = {}; // First line must be file format\n", "\n", " let line = await dataWrapper.nextLine();\n", "\n", " if (line.startsWith(\"##fileformat\")) {\n", " header.version = line.substr(13);\n", " } else {\n", " throw new Error(\"Invalid VCF file: missing fileformat line\");\n", " }\n", "\n", " while ((line = await dataWrapper.nextLine()) !== undefined) {\n", " if (line.startsWith(\"#\")) {\n", " let id;\n", " const values = {};\n", "\n", " if (line.startsWith(\"##\")) {\n", " if (line.startsWith(\"##INFO\") || line.startsWith(\"##FILTER\") || line.startsWith(\"##FORMAT\")) {\n", " const ltIdx = line.indexOf(\"<\");\n", " const gtIdx = line.lastIndexOf(\">\");\n", "\n", " if (!(ltIdx > 2 && gtIdx > 0)) {\n", " console.log(\"Malformed VCF header line: \" + line);\n", " continue;\n", " }\n", "\n", " const type = line.substring(2, ltIdx - 1);\n", " if (!header[type]) header[type] = {}; //##INFO=\n", " // ##FILTER=\n", " // ##FORMAT=\n", "\n", " const tokens = splitStringRespectingQuotes(line.substring(ltIdx + 1, gtIdx - 1), \",\");\n", "\n", " for (let token of tokens) {\n", " var kv = token.split(\"=\");\n", "\n", " if (kv.length > 1) {\n", " if (kv[0] === \"ID\") {\n", " id = kv[1];\n", " } else {\n", " values[kv[0]] = kv[1];\n", " }\n", " }\n", " }\n", "\n", " if (id) {\n", " header[type][id] = values;\n", " }\n", " }\n", " } else if (line.startsWith(\"#CHROM\")) {\n", " const tokens = line.split(\"\\t\");\n", "\n", " if (tokens.length > 8) {\n", " // call set names -- use column index for id\n", " header.callSets = [];\n", "\n", " for (let j = 9; j < tokens.length; j++) {\n", " header.callSets.push({\n", " id: j,\n", " name: tokens[j]\n", " });\n", " }\n", " }\n", " }\n", " } else {\n", " break;\n", " }\n", " }\n", "\n", " this.header = header; // Will need to intrepret genotypes and info field\n", "\n", " return header;\n", " }\n", " /**\n", " * Parse data as a collection of Variant objects.\n", " *\n", " * @param data\n", " * @returns {Array}\n", " */\n", "\n", "\n", " async parseFeatures(dataWrapper) {\n", " const allFeatures = [];\n", " const callSets = this.header.callSets;\n", " const nExpectedColumns = 8 + (callSets ? callSets.length + 1 : 0);\n", " let line;\n", "\n", " while ((line = await dataWrapper.nextLine()) !== undefined) {\n", " if (line && !line.startsWith(\"#\")) {\n", " const tokens = line.split(\"\\t\");\n", "\n", " if (tokens.length === nExpectedColumns) {\n", " const variant = createVCFVariant(tokens);\n", " variant.header = this.header; // Keep a pointer to the header to interpret fields for popup text\n", "\n", " allFeatures.push(variant);\n", "\n", " if (tokens.length > 9) {\n", " // Format\n", " const callFields = extractCallFields(tokens[8].split(\":\"));\n", " variant.calls = {};\n", "\n", " for (let index = 9; index < tokens.length; index++) {\n", " const token = tokens[index];\n", " var callSet = callSets[index - 9],\n", " call = {\n", " callSetName: callSet.name,\n", " info: {}\n", " };\n", " variant.calls[callSet.id] = call;\n", " token.split(\":\").forEach(function (callToken, idx) {\n", " switch (idx) {\n", " case callFields.genotypeIndex:\n", " call.genotype = [];\n", " callToken.split(/[\\|\\/]/).forEach(function (s) {\n", " call.genotype.push('.' === s ? s : parseInt(s));\n", " });\n", " break;\n", "\n", " default:\n", " call.info[callFields.fields[idx]] = callToken;\n", " }\n", " });\n", " }\n", " }\n", " }\n", " }\n", " }\n", "\n", " return allFeatures;\n", " }\n", "\n", " }\n", "\n", " function extractCallFields(tokens) {\n", " const callFields = {\n", " genotypeIndex: -1,\n", " fields: tokens\n", " };\n", "\n", " for (let i = 0; i < tokens.length; i++) {\n", " if (\"GT\" === tokens[i]) {\n", " callFields.genotypeIndex = i;\n", " }\n", " }\n", "\n", " return callFields;\n", " }\n", "\n", " var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};\n", "\n", " var check = function (it) {\n", " return it && it.Math == Math && it;\n", " }; // https://github.com/zloirock/core-js/issues/86#issuecomment-115759028\n", "\n", "\n", " var global$q = // eslint-disable-next-line es/no-global-this -- safe\n", " check(typeof globalThis == 'object' && globalThis) || check(typeof window == 'object' && window) || // eslint-disable-next-line no-restricted-globals -- safe\n", " check(typeof self == 'object' && self) || check(typeof commonjsGlobal == 'object' && commonjsGlobal) || // eslint-disable-next-line no-new-func -- fallback\n", " function () {\n", " return this;\n", " }() || Function('return this')();\n", "\n", " var fails$7 = function (exec) {\n", " try {\n", " return !!exec();\n", " } catch (error) {\n", " return true;\n", " }\n", " };\n", "\n", " var fails$6 = fails$7;\n", " var functionBindNative = !fails$6(function () {\n", " var test = function () {\n", " /* empty */\n", " }.bind(); // eslint-disable-next-line no-prototype-builtins -- safe\n", "\n", "\n", " return typeof test != 'function' || test.hasOwnProperty('prototype');\n", " });\n", "\n", " var NATIVE_BIND$1 = functionBindNative;\n", " var call$4 = Function.prototype.call;\n", " var functionCall = NATIVE_BIND$1 ? call$4.bind(call$4) : function () {\n", " return call$4.apply(call$4, arguments);\n", " };\n", "\n", " var arrayBufferNative = typeof ArrayBuffer != 'undefined' && typeof DataView != 'undefined';\n", "\n", " var fails$5 = fails$7; // Detect IE8's incomplete defineProperty implementation\n", "\n", " var descriptors = !fails$5(function () {\n", " // eslint-disable-next-line es/no-object-defineproperty -- required for testing\n", " return Object.defineProperty({}, 1, {\n", " get: function () {\n", " return 7;\n", " }\n", " })[1] != 7;\n", " });\n", "\n", " // https://tc39.es/ecma262/#sec-iscallable\n", "\n", " var isCallable$c = function (argument) {\n", " return typeof argument == 'function';\n", " };\n", "\n", " var isCallable$b = isCallable$c;\n", "\n", " var isObject$6 = function (it) {\n", " return typeof it == 'object' ? it !== null : isCallable$b(it);\n", " };\n", "\n", " var NATIVE_BIND = functionBindNative;\n", " var FunctionPrototype$1 = Function.prototype;\n", " var bind = FunctionPrototype$1.bind;\n", " var call$3 = FunctionPrototype$1.call;\n", " var uncurryThis$7 = NATIVE_BIND && bind.bind(call$3, call$3);\n", " var functionUncurryThis = NATIVE_BIND ? function (fn) {\n", " return fn && uncurryThis$7(fn);\n", " } : function (fn) {\n", " return fn && function () {\n", " return call$3.apply(fn, arguments);\n", " };\n", " };\n", "\n", " var global$p = global$q;\n", " var TypeError$9 = global$p.TypeError; // `RequireObjectCoercible` abstract operation\n", " // https://tc39.es/ecma262/#sec-requireobjectcoercible\n", "\n", " var requireObjectCoercible$1 = function (it) {\n", " if (it == undefined) throw TypeError$9(\"Can't call method on \" + it);\n", " return it;\n", " };\n", "\n", " var global$o = global$q;\n", " var requireObjectCoercible = requireObjectCoercible$1;\n", " var Object$4 = global$o.Object; // `ToObject` abstract operation\n", " // https://tc39.es/ecma262/#sec-toobject\n", "\n", " var toObject$2 = function (argument) {\n", " return Object$4(requireObjectCoercible(argument));\n", " };\n", "\n", " var uncurryThis$6 = functionUncurryThis;\n", " var toObject$1 = toObject$2;\n", " var hasOwnProperty = uncurryThis$6({}.hasOwnProperty); // `HasOwnProperty` abstract operation\n", " // https://tc39.es/ecma262/#sec-hasownproperty\n", "\n", " var hasOwnProperty_1 = Object.hasOwn || function hasOwn(it, key) {\n", " return hasOwnProperty(toObject$1(it), key);\n", " };\n", "\n", " var shared$3 = {exports: {}};\n", "\n", " var global$n = global$q; // eslint-disable-next-line es/no-object-defineproperty -- safe\n", "\n", " var defineProperty$1 = Object.defineProperty;\n", "\n", " var setGlobal$2 = function (key, value) {\n", " try {\n", " defineProperty$1(global$n, key, {\n", " value: value,\n", " configurable: true,\n", " writable: true\n", " });\n", " } catch (error) {\n", " global$n[key] = value;\n", " }\n", "\n", " return value;\n", " };\n", "\n", " var global$m = global$q;\n", " var setGlobal$1 = setGlobal$2;\n", " var SHARED = '__core-js_shared__';\n", " var store$3 = global$m[SHARED] || setGlobal$1(SHARED, {});\n", " var sharedStore = store$3;\n", "\n", " var store$2 = sharedStore;\n", " (shared$3.exports = function (key, value) {\n", " return store$2[key] || (store$2[key] = value !== undefined ? value : {});\n", " })('versions', []).push({\n", " version: '3.21.1',\n", " mode: 'global',\n", " copyright: '© 2014-2022 Denis Pushkarev (zloirock.ru)',\n", " license: 'https://github.com/zloirock/core-js/blob/v3.21.1/LICENSE',\n", " source: 'https://github.com/zloirock/core-js'\n", " });\n", "\n", " var uncurryThis$5 = functionUncurryThis;\n", " var id = 0;\n", " var postfix = Math.random();\n", " var toString$1 = uncurryThis$5(1.0.toString);\n", "\n", " var uid$3 = function (key) {\n", " return 'Symbol(' + (key === undefined ? '' : key) + ')_' + toString$1(++id + postfix, 36);\n", " };\n", "\n", " var global$l = global$q;\n", " var isCallable$a = isCallable$c;\n", "\n", " var aFunction = function (argument) {\n", " return isCallable$a(argument) ? argument : undefined;\n", " };\n", "\n", " var getBuiltIn$2 = function (namespace, method) {\n", " return arguments.length < 2 ? aFunction(global$l[namespace]) : global$l[namespace] && global$l[namespace][method];\n", " };\n", "\n", " var getBuiltIn$1 = getBuiltIn$2;\n", " var engineUserAgent = getBuiltIn$1('navigator', 'userAgent') || '';\n", "\n", " var global$k = global$q;\n", " var userAgent = engineUserAgent;\n", " var process$1 = global$k.process;\n", " var Deno = global$k.Deno;\n", " var versions = process$1 && process$1.versions || Deno && Deno.version;\n", " var v8 = versions && versions.v8;\n", " var match, version$1;\n", "\n", " if (v8) {\n", " match = v8.split('.'); // in old Chrome, versions of V8 isn't V8 = Chrome / 10\n", " // but their correct versions are not interesting for us\n", "\n", " version$1 = match[0] > 0 && match[0] < 4 ? 1 : +(match[0] + match[1]);\n", " } // BrowserFS NodeJS `process` polyfill incorrectly set `.v8` to `0.0`\n", " // so check `userAgent` even if `.v8` exists, but 0\n", "\n", "\n", " if (!version$1 && userAgent) {\n", " match = userAgent.match(/Edge\\/(\\d+)/);\n", "\n", " if (!match || match[1] >= 74) {\n", " match = userAgent.match(/Chrome\\/(\\d+)/);\n", " if (match) version$1 = +match[1];\n", " }\n", " }\n", "\n", " var engineV8Version = version$1;\n", "\n", " /* eslint-disable es/no-symbol -- required for testing */\n", " var V8_VERSION = engineV8Version;\n", " var fails$4 = fails$7; // eslint-disable-next-line es/no-object-getownpropertysymbols -- required for testing\n", "\n", " var nativeSymbol = !!Object.getOwnPropertySymbols && !fails$4(function () {\n", " var symbol = Symbol(); // Chrome 38 Symbol has incorrect toString conversion\n", " // `get-own-property-symbols` polyfill symbols converted to object are not Symbol instances\n", "\n", " return !String(symbol) || !(Object(symbol) instanceof Symbol) || // Chrome 38-40 symbols are not inherited from DOM collections prototypes to instances\n", " !Symbol.sham && V8_VERSION && V8_VERSION < 41;\n", " });\n", "\n", " /* eslint-disable es/no-symbol -- required for testing */\n", " var NATIVE_SYMBOL$1 = nativeSymbol;\n", " var useSymbolAsUid = NATIVE_SYMBOL$1 && !Symbol.sham && typeof Symbol.iterator == 'symbol';\n", "\n", " var global$j = global$q;\n", " var shared$2 = shared$3.exports;\n", " var hasOwn$5 = hasOwnProperty_1;\n", " var uid$2 = uid$3;\n", " var NATIVE_SYMBOL = nativeSymbol;\n", " var USE_SYMBOL_AS_UID$1 = useSymbolAsUid;\n", " var WellKnownSymbolsStore = shared$2('wks');\n", " var Symbol$1 = global$j.Symbol;\n", " var symbolFor = Symbol$1 && Symbol$1['for'];\n", " var createWellKnownSymbol = USE_SYMBOL_AS_UID$1 ? Symbol$1 : Symbol$1 && Symbol$1.withoutSetter || uid$2;\n", "\n", " var wellKnownSymbol$4 = function (name) {\n", " if (!hasOwn$5(WellKnownSymbolsStore, name) || !(NATIVE_SYMBOL || typeof WellKnownSymbolsStore[name] == 'string')) {\n", " var description = 'Symbol.' + name;\n", "\n", " if (NATIVE_SYMBOL && hasOwn$5(Symbol$1, name)) {\n", " WellKnownSymbolsStore[name] = Symbol$1[name];\n", " } else if (USE_SYMBOL_AS_UID$1 && symbolFor) {\n", " WellKnownSymbolsStore[name] = symbolFor(description);\n", " } else {\n", " WellKnownSymbolsStore[name] = createWellKnownSymbol(description);\n", " }\n", " }\n", "\n", " return WellKnownSymbolsStore[name];\n", " };\n", "\n", " var wellKnownSymbol$3 = wellKnownSymbol$4;\n", " var TO_STRING_TAG$2 = wellKnownSymbol$3('toStringTag');\n", " var test = {};\n", " test[TO_STRING_TAG$2] = 'z';\n", " var toStringTagSupport = String(test) === '[object z]';\n", "\n", " var uncurryThis$4 = functionUncurryThis;\n", " var toString = uncurryThis$4({}.toString);\n", " var stringSlice = uncurryThis$4(''.slice);\n", "\n", " var classofRaw$1 = function (it) {\n", " return stringSlice(toString(it), 8, -1);\n", " };\n", "\n", " var global$i = global$q;\n", " var TO_STRING_TAG_SUPPORT = toStringTagSupport;\n", " var isCallable$9 = isCallable$c;\n", " var classofRaw = classofRaw$1;\n", " var wellKnownSymbol$2 = wellKnownSymbol$4;\n", " var TO_STRING_TAG$1 = wellKnownSymbol$2('toStringTag');\n", " var Object$3 = global$i.Object; // ES3 wrong here\n", "\n", " var CORRECT_ARGUMENTS = classofRaw(function () {\n", " return arguments;\n", " }()) == 'Arguments'; // fallback for IE11 Script Access Denied error\n", "\n", " var tryGet = function (it, key) {\n", " try {\n", " return it[key];\n", " } catch (error) {\n", " /* empty */\n", " }\n", " }; // getting tag from ES6+ `Object.prototype.toString`\n", "\n", "\n", " var classof$1 = TO_STRING_TAG_SUPPORT ? classofRaw : function (it) {\n", " var O, tag, result;\n", " return it === undefined ? 'Undefined' : it === null ? 'Null' // @@toStringTag case\n", " : typeof (tag = tryGet(O = Object$3(it), TO_STRING_TAG$1)) == 'string' ? tag // builtinTag case\n", " : CORRECT_ARGUMENTS ? classofRaw(O) // ES3 arguments fallback\n", " : (result = classofRaw(O)) == 'Object' && isCallable$9(O.callee) ? 'Arguments' : result;\n", " };\n", "\n", " var global$h = global$q;\n", " var String$3 = global$h.String;\n", "\n", " var tryToString$2 = function (argument) {\n", " try {\n", " return String$3(argument);\n", " } catch (error) {\n", " return 'Object';\n", " }\n", " };\n", "\n", " var objectDefineProperty = {};\n", "\n", " var global$g = global$q;\n", " var isObject$5 = isObject$6;\n", " var document$1 = global$g.document; // typeof document.createElement is 'object' in old IE\n", "\n", " var EXISTS$1 = isObject$5(document$1) && isObject$5(document$1.createElement);\n", "\n", " var documentCreateElement = function (it) {\n", " return EXISTS$1 ? document$1.createElement(it) : {};\n", " };\n", "\n", " var DESCRIPTORS$5 = descriptors;\n", " var fails$3 = fails$7;\n", " var createElement = documentCreateElement; // Thanks to IE8 for its funny defineProperty\n", "\n", " var ie8DomDefine = !DESCRIPTORS$5 && !fails$3(function () {\n", " // eslint-disable-next-line es/no-object-defineproperty -- required for testing\n", " return Object.defineProperty(createElement('div'), 'a', {\n", " get: function () {\n", " return 7;\n", " }\n", " }).a != 7;\n", " });\n", "\n", " var DESCRIPTORS$4 = descriptors;\n", " var fails$2 = fails$7; // V8 ~ Chrome 36-\n", " // https://bugs.chromium.org/p/v8/issues/detail?id=3334\n", "\n", " var v8PrototypeDefineBug = DESCRIPTORS$4 && fails$2(function () {\n", " // eslint-disable-next-line es/no-object-defineproperty -- required for testing\n", " return Object.defineProperty(function () {\n", " /* empty */\n", " }, 'prototype', {\n", " value: 42,\n", " writable: false\n", " }).prototype != 42;\n", " });\n", "\n", " var global$f = global$q;\n", " var isObject$4 = isObject$6;\n", " var String$2 = global$f.String;\n", " var TypeError$8 = global$f.TypeError; // `Assert: Type(argument) is Object`\n", "\n", " var anObject$2 = function (argument) {\n", " if (isObject$4(argument)) return argument;\n", " throw TypeError$8(String$2(argument) + ' is not an object');\n", " };\n", "\n", " var uncurryThis$3 = functionUncurryThis;\n", " var objectIsPrototypeOf = uncurryThis$3({}.isPrototypeOf);\n", "\n", " var global$e = global$q;\n", " var getBuiltIn = getBuiltIn$2;\n", " var isCallable$8 = isCallable$c;\n", " var isPrototypeOf$1 = objectIsPrototypeOf;\n", " var USE_SYMBOL_AS_UID = useSymbolAsUid;\n", " var Object$2 = global$e.Object;\n", " var isSymbol$2 = USE_SYMBOL_AS_UID ? function (it) {\n", " return typeof it == 'symbol';\n", " } : function (it) {\n", " var $Symbol = getBuiltIn('Symbol');\n", " return isCallable$8($Symbol) && isPrototypeOf$1($Symbol.prototype, Object$2(it));\n", " };\n", "\n", " var global$d = global$q;\n", " var isCallable$7 = isCallable$c;\n", " var tryToString$1 = tryToString$2;\n", " var TypeError$7 = global$d.TypeError; // `Assert: IsCallable(argument) is true`\n", "\n", " var aCallable$1 = function (argument) {\n", " if (isCallable$7(argument)) return argument;\n", " throw TypeError$7(tryToString$1(argument) + ' is not a function');\n", " };\n", "\n", " var aCallable = aCallable$1; // `GetMethod` abstract operation\n", " // https://tc39.es/ecma262/#sec-getmethod\n", "\n", " var getMethod$1 = function (V, P) {\n", " var func = V[P];\n", " return func == null ? undefined : aCallable(func);\n", " };\n", "\n", " var global$c = global$q;\n", " var call$2 = functionCall;\n", " var isCallable$6 = isCallable$c;\n", " var isObject$3 = isObject$6;\n", " var TypeError$6 = global$c.TypeError; // `OrdinaryToPrimitive` abstract operation\n", " // https://tc39.es/ecma262/#sec-ordinarytoprimitive\n", "\n", " var ordinaryToPrimitive$1 = function (input, pref) {\n", " var fn, val;\n", " if (pref === 'string' && isCallable$6(fn = input.toString) && !isObject$3(val = call$2(fn, input))) return val;\n", " if (isCallable$6(fn = input.valueOf) && !isObject$3(val = call$2(fn, input))) return val;\n", " if (pref !== 'string' && isCallable$6(fn = input.toString) && !isObject$3(val = call$2(fn, input))) return val;\n", " throw TypeError$6(\"Can't convert object to primitive value\");\n", " };\n", "\n", " var global$b = global$q;\n", " var call$1 = functionCall;\n", " var isObject$2 = isObject$6;\n", " var isSymbol$1 = isSymbol$2;\n", " var getMethod = getMethod$1;\n", " var ordinaryToPrimitive = ordinaryToPrimitive$1;\n", " var wellKnownSymbol$1 = wellKnownSymbol$4;\n", " var TypeError$5 = global$b.TypeError;\n", " var TO_PRIMITIVE = wellKnownSymbol$1('toPrimitive'); // `ToPrimitive` abstract operation\n", " // https://tc39.es/ecma262/#sec-toprimitive\n", "\n", " var toPrimitive$1 = function (input, pref) {\n", " if (!isObject$2(input) || isSymbol$1(input)) return input;\n", " var exoticToPrim = getMethod(input, TO_PRIMITIVE);\n", " var result;\n", "\n", " if (exoticToPrim) {\n", " if (pref === undefined) pref = 'default';\n", " result = call$1(exoticToPrim, input, pref);\n", " if (!isObject$2(result) || isSymbol$1(result)) return result;\n", " throw TypeError$5(\"Can't convert object to primitive value\");\n", " }\n", "\n", " if (pref === undefined) pref = 'number';\n", " return ordinaryToPrimitive(input, pref);\n", " };\n", "\n", " var toPrimitive = toPrimitive$1;\n", " var isSymbol = isSymbol$2; // `ToPropertyKey` abstract operation\n", " // https://tc39.es/ecma262/#sec-topropertykey\n", "\n", " var toPropertyKey$1 = function (argument) {\n", " var key = toPrimitive(argument, 'string');\n", " return isSymbol(key) ? key : key + '';\n", " };\n", "\n", " var global$a = global$q;\n", " var DESCRIPTORS$3 = descriptors;\n", " var IE8_DOM_DEFINE = ie8DomDefine;\n", " var V8_PROTOTYPE_DEFINE_BUG = v8PrototypeDefineBug;\n", " var anObject$1 = anObject$2;\n", " var toPropertyKey = toPropertyKey$1;\n", " var TypeError$4 = global$a.TypeError; // eslint-disable-next-line es/no-object-defineproperty -- safe\n", "\n", " var $defineProperty = Object.defineProperty; // eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe\n", "\n", " var $getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n", " var ENUMERABLE = 'enumerable';\n", " var CONFIGURABLE$1 = 'configurable';\n", " var WRITABLE = 'writable'; // `Object.defineProperty` method\n", " // https://tc39.es/ecma262/#sec-object.defineproperty\n", "\n", " objectDefineProperty.f = DESCRIPTORS$3 ? V8_PROTOTYPE_DEFINE_BUG ? function defineProperty(O, P, Attributes) {\n", " anObject$1(O);\n", " P = toPropertyKey(P);\n", " anObject$1(Attributes);\n", "\n", " if (typeof O === 'function' && P === 'prototype' && 'value' in Attributes && WRITABLE in Attributes && !Attributes[WRITABLE]) {\n", " var current = $getOwnPropertyDescriptor(O, P);\n", "\n", " if (current && current[WRITABLE]) {\n", " O[P] = Attributes.value;\n", " Attributes = {\n", " configurable: CONFIGURABLE$1 in Attributes ? Attributes[CONFIGURABLE$1] : current[CONFIGURABLE$1],\n", " enumerable: ENUMERABLE in Attributes ? Attributes[ENUMERABLE] : current[ENUMERABLE],\n", " writable: false\n", " };\n", " }\n", " }\n", "\n", " return $defineProperty(O, P, Attributes);\n", " } : $defineProperty : function defineProperty(O, P, Attributes) {\n", " anObject$1(O);\n", " P = toPropertyKey(P);\n", " anObject$1(Attributes);\n", " if (IE8_DOM_DEFINE) try {\n", " return $defineProperty(O, P, Attributes);\n", " } catch (error) {\n", " /* empty */\n", " }\n", " if ('get' in Attributes || 'set' in Attributes) throw TypeError$4('Accessors not supported');\n", " if ('value' in Attributes) O[P] = Attributes.value;\n", " return O;\n", " };\n", "\n", " var createPropertyDescriptor$1 = function (bitmap, value) {\n", " return {\n", " enumerable: !(bitmap & 1),\n", " configurable: !(bitmap & 2),\n", " writable: !(bitmap & 4),\n", " value: value\n", " };\n", " };\n", "\n", " var DESCRIPTORS$2 = descriptors;\n", " var definePropertyModule = objectDefineProperty;\n", " var createPropertyDescriptor = createPropertyDescriptor$1;\n", " var createNonEnumerableProperty$3 = DESCRIPTORS$2 ? function (object, key, value) {\n", " return definePropertyModule.f(object, key, createPropertyDescriptor(1, value));\n", " } : function (object, key, value) {\n", " object[key] = value;\n", " return object;\n", " };\n", "\n", " var redefine$1 = {exports: {}};\n", "\n", " var uncurryThis$2 = functionUncurryThis;\n", " var isCallable$5 = isCallable$c;\n", " var store$1 = sharedStore;\n", " var functionToString = uncurryThis$2(Function.toString); // this helper broken in `core-js@3.4.1-3.4.4`, so we can't use `shared` helper\n", "\n", " if (!isCallable$5(store$1.inspectSource)) {\n", " store$1.inspectSource = function (it) {\n", " return functionToString(it);\n", " };\n", " }\n", "\n", " var inspectSource$2 = store$1.inspectSource;\n", "\n", " var global$9 = global$q;\n", " var isCallable$4 = isCallable$c;\n", " var inspectSource$1 = inspectSource$2;\n", " var WeakMap$1 = global$9.WeakMap;\n", " var nativeWeakMap = isCallable$4(WeakMap$1) && /native code/.test(inspectSource$1(WeakMap$1));\n", "\n", " var shared$1 = shared$3.exports;\n", " var uid$1 = uid$3;\n", " var keys = shared$1('keys');\n", "\n", " var sharedKey$2 = function (key) {\n", " return keys[key] || (keys[key] = uid$1(key));\n", " };\n", "\n", " var hiddenKeys$1 = {};\n", "\n", " var NATIVE_WEAK_MAP = nativeWeakMap;\n", " var global$8 = global$q;\n", " var uncurryThis$1 = functionUncurryThis;\n", " var isObject$1 = isObject$6;\n", " var createNonEnumerableProperty$2 = createNonEnumerableProperty$3;\n", " var hasOwn$4 = hasOwnProperty_1;\n", " var shared = sharedStore;\n", " var sharedKey$1 = sharedKey$2;\n", " var hiddenKeys = hiddenKeys$1;\n", " var OBJECT_ALREADY_INITIALIZED = 'Object already initialized';\n", " var TypeError$3 = global$8.TypeError;\n", " var WeakMap = global$8.WeakMap;\n", " var set, get, has;\n", "\n", " var enforce = function (it) {\n", " return has(it) ? get(it) : set(it, {});\n", " };\n", "\n", " var getterFor = function (TYPE) {\n", " return function (it) {\n", " var state;\n", "\n", " if (!isObject$1(it) || (state = get(it)).type !== TYPE) {\n", " throw TypeError$3('Incompatible receiver, ' + TYPE + ' required');\n", " }\n", "\n", " return state;\n", " };\n", " };\n", "\n", " if (NATIVE_WEAK_MAP || shared.state) {\n", " var store = shared.state || (shared.state = new WeakMap());\n", " var wmget = uncurryThis$1(store.get);\n", " var wmhas = uncurryThis$1(store.has);\n", " var wmset = uncurryThis$1(store.set);\n", "\n", " set = function (it, metadata) {\n", " if (wmhas(store, it)) throw new TypeError$3(OBJECT_ALREADY_INITIALIZED);\n", " metadata.facade = it;\n", " wmset(store, it, metadata);\n", " return metadata;\n", " };\n", "\n", " get = function (it) {\n", " return wmget(store, it) || {};\n", " };\n", "\n", " has = function (it) {\n", " return wmhas(store, it);\n", " };\n", " } else {\n", " var STATE = sharedKey$1('state');\n", " hiddenKeys[STATE] = true;\n", "\n", " set = function (it, metadata) {\n", " if (hasOwn$4(it, STATE)) throw new TypeError$3(OBJECT_ALREADY_INITIALIZED);\n", " metadata.facade = it;\n", " createNonEnumerableProperty$2(it, STATE, metadata);\n", " return metadata;\n", " };\n", "\n", " get = function (it) {\n", " return hasOwn$4(it, STATE) ? it[STATE] : {};\n", " };\n", "\n", " has = function (it) {\n", " return hasOwn$4(it, STATE);\n", " };\n", " }\n", "\n", " var internalState = {\n", " set: set,\n", " get: get,\n", " has: has,\n", " enforce: enforce,\n", " getterFor: getterFor\n", " };\n", "\n", " var DESCRIPTORS$1 = descriptors;\n", " var hasOwn$3 = hasOwnProperty_1;\n", " var FunctionPrototype = Function.prototype; // eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe\n", "\n", " var getDescriptor = DESCRIPTORS$1 && Object.getOwnPropertyDescriptor;\n", " var EXISTS = hasOwn$3(FunctionPrototype, 'name'); // additional protection from minified / mangled / dropped function names\n", "\n", " var PROPER = EXISTS && function something() {\n", " /* empty */\n", " }.name === 'something';\n", "\n", " var CONFIGURABLE = EXISTS && (!DESCRIPTORS$1 || DESCRIPTORS$1 && getDescriptor(FunctionPrototype, 'name').configurable);\n", " var functionName = {\n", " EXISTS: EXISTS,\n", " PROPER: PROPER,\n", " CONFIGURABLE: CONFIGURABLE\n", " };\n", "\n", " var global$7 = global$q;\n", " var isCallable$3 = isCallable$c;\n", " var hasOwn$2 = hasOwnProperty_1;\n", " var createNonEnumerableProperty$1 = createNonEnumerableProperty$3;\n", " var setGlobal = setGlobal$2;\n", " var inspectSource = inspectSource$2;\n", " var InternalStateModule = internalState;\n", " var CONFIGURABLE_FUNCTION_NAME = functionName.CONFIGURABLE;\n", " var getInternalState = InternalStateModule.get;\n", " var enforceInternalState = InternalStateModule.enforce;\n", " var TEMPLATE = String(String).split('String');\n", " (redefine$1.exports = function (O, key, value, options) {\n", " var unsafe = options ? !!options.unsafe : false;\n", " var simple = options ? !!options.enumerable : false;\n", " var noTargetGet = options ? !!options.noTargetGet : false;\n", " var name = options && options.name !== undefined ? options.name : key;\n", " var state;\n", "\n", " if (isCallable$3(value)) {\n", " if (String(name).slice(0, 7) === 'Symbol(') {\n", " name = '[' + String(name).replace(/^Symbol\\(([^)]*)\\)/, '$1') + ']';\n", " }\n", "\n", " if (!hasOwn$2(value, 'name') || CONFIGURABLE_FUNCTION_NAME && value.name !== name) {\n", " createNonEnumerableProperty$1(value, 'name', name);\n", " }\n", "\n", " state = enforceInternalState(value);\n", "\n", " if (!state.source) {\n", " state.source = TEMPLATE.join(typeof name == 'string' ? name : '');\n", " }\n", " }\n", "\n", " if (O === global$7) {\n", " if (simple) O[key] = value;else setGlobal(key, value);\n", " return;\n", " } else if (!unsafe) {\n", " delete O[key];\n", " } else if (!noTargetGet && O[key]) {\n", " simple = true;\n", " }\n", "\n", " if (simple) O[key] = value;else createNonEnumerableProperty$1(O, key, value); // add fake Function#toString for correct work wrapped methods / constructors with methods like LoDash isNative\n", " })(Function.prototype, 'toString', function toString() {\n", " return isCallable$3(this) && getInternalState(this).source || inspectSource(this);\n", " });\n", "\n", " var fails$1 = fails$7;\n", " var correctPrototypeGetter = !fails$1(function () {\n", " function F() {\n", " /* empty */\n", " }\n", "\n", " F.prototype.constructor = null; // eslint-disable-next-line es/no-object-getprototypeof -- required for testing\n", "\n", " return Object.getPrototypeOf(new F()) !== F.prototype;\n", " });\n", "\n", " var global$6 = global$q;\n", " var hasOwn$1 = hasOwnProperty_1;\n", " var isCallable$2 = isCallable$c;\n", " var toObject = toObject$2;\n", " var sharedKey = sharedKey$2;\n", " var CORRECT_PROTOTYPE_GETTER = correctPrototypeGetter;\n", " var IE_PROTO = sharedKey('IE_PROTO');\n", " var Object$1 = global$6.Object;\n", " var ObjectPrototype$1 = Object$1.prototype; // `Object.getPrototypeOf` method\n", " // https://tc39.es/ecma262/#sec-object.getprototypeof\n", "\n", " var objectGetPrototypeOf = CORRECT_PROTOTYPE_GETTER ? Object$1.getPrototypeOf : function (O) {\n", " var object = toObject(O);\n", " if (hasOwn$1(object, IE_PROTO)) return object[IE_PROTO];\n", " var constructor = object.constructor;\n", "\n", " if (isCallable$2(constructor) && object instanceof constructor) {\n", " return constructor.prototype;\n", " }\n", "\n", " return object instanceof Object$1 ? ObjectPrototype$1 : null;\n", " };\n", "\n", " var global$5 = global$q;\n", " var isCallable$1 = isCallable$c;\n", " var String$1 = global$5.String;\n", " var TypeError$2 = global$5.TypeError;\n", "\n", " var aPossiblePrototype$1 = function (argument) {\n", " if (typeof argument == 'object' || isCallable$1(argument)) return argument;\n", " throw TypeError$2(\"Can't set \" + String$1(argument) + ' as a prototype');\n", " };\n", "\n", " /* eslint-disable no-proto -- safe */\n", " var uncurryThis = functionUncurryThis;\n", " var anObject = anObject$2;\n", " var aPossiblePrototype = aPossiblePrototype$1; // `Object.setPrototypeOf` method\n", " // https://tc39.es/ecma262/#sec-object.setprototypeof\n", " // Works with __proto__ only. Old v8 can't work with null proto objects.\n", " // eslint-disable-next-line es/no-object-setprototypeof -- safe\n", "\n", " var objectSetPrototypeOf = Object.setPrototypeOf || ('__proto__' in {} ? function () {\n", " var CORRECT_SETTER = false;\n", " var test = {};\n", " var setter;\n", "\n", " try {\n", " // eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe\n", " setter = uncurryThis(Object.getOwnPropertyDescriptor(Object.prototype, '__proto__').set);\n", " setter(test, []);\n", " CORRECT_SETTER = test instanceof Array;\n", " } catch (error) {\n", " /* empty */\n", " }\n", "\n", " return function setPrototypeOf(O, proto) {\n", " anObject(O);\n", " aPossiblePrototype(proto);\n", " if (CORRECT_SETTER) setter(O, proto);else O.__proto__ = proto;\n", " return O;\n", " };\n", " }() : undefined);\n", "\n", " var NATIVE_ARRAY_BUFFER = arrayBufferNative;\n", " var DESCRIPTORS = descriptors;\n", " var global$4 = global$q;\n", " var isCallable = isCallable$c;\n", " var isObject = isObject$6;\n", " var hasOwn = hasOwnProperty_1;\n", " var classof = classof$1;\n", " var tryToString = tryToString$2;\n", " var createNonEnumerableProperty = createNonEnumerableProperty$3;\n", " var redefine = redefine$1.exports;\n", " var defineProperty = objectDefineProperty.f;\n", " var isPrototypeOf = objectIsPrototypeOf;\n", " var getPrototypeOf = objectGetPrototypeOf;\n", " var setPrototypeOf = objectSetPrototypeOf;\n", " var wellKnownSymbol = wellKnownSymbol$4;\n", " var uid = uid$3;\n", " var Int8Array$1 = global$4.Int8Array;\n", " var Int8ArrayPrototype$1 = Int8Array$1 && Int8Array$1.prototype;\n", " var Uint8ClampedArray$1 = global$4.Uint8ClampedArray;\n", " var Uint8ClampedArrayPrototype = Uint8ClampedArray$1 && Uint8ClampedArray$1.prototype;\n", " var TypedArray = Int8Array$1 && getPrototypeOf(Int8Array$1);\n", " var TypedArrayPrototype = Int8ArrayPrototype$1 && getPrototypeOf(Int8ArrayPrototype$1);\n", " var ObjectPrototype = Object.prototype;\n", " var TypeError$1 = global$4.TypeError;\n", " var TO_STRING_TAG = wellKnownSymbol('toStringTag');\n", " var TYPED_ARRAY_TAG = uid('TYPED_ARRAY_TAG');\n", " var TYPED_ARRAY_CONSTRUCTOR = uid('TYPED_ARRAY_CONSTRUCTOR'); // Fixing native typed arrays in Opera Presto crashes the browser, see #595\n", "\n", " var NATIVE_ARRAY_BUFFER_VIEWS = NATIVE_ARRAY_BUFFER && !!setPrototypeOf && classof(global$4.opera) !== 'Opera';\n", " var TYPED_ARRAY_TAG_REQUIRED = false;\n", " var NAME, Constructor, Prototype;\n", " var TypedArrayConstructorsList = {\n", " Int8Array: 1,\n", " Uint8Array: 1,\n", " Uint8ClampedArray: 1,\n", " Int16Array: 2,\n", " Uint16Array: 2,\n", " Int32Array: 4,\n", " Uint32Array: 4,\n", " Float32Array: 4,\n", " Float64Array: 8\n", " };\n", " var BigIntArrayConstructorsList = {\n", " BigInt64Array: 8,\n", " BigUint64Array: 8\n", " };\n", "\n", " var isView = function isView(it) {\n", " if (!isObject(it)) return false;\n", " var klass = classof(it);\n", " return klass === 'DataView' || hasOwn(TypedArrayConstructorsList, klass) || hasOwn(BigIntArrayConstructorsList, klass);\n", " };\n", "\n", " var isTypedArray = function (it) {\n", " if (!isObject(it)) return false;\n", " var klass = classof(it);\n", " return hasOwn(TypedArrayConstructorsList, klass) || hasOwn(BigIntArrayConstructorsList, klass);\n", " };\n", "\n", " var aTypedArray$1 = function (it) {\n", " if (isTypedArray(it)) return it;\n", " throw TypeError$1('Target is not a typed array');\n", " };\n", "\n", " var aTypedArrayConstructor = function (C) {\n", " if (isCallable(C) && (!setPrototypeOf || isPrototypeOf(TypedArray, C))) return C;\n", " throw TypeError$1(tryToString(C) + ' is not a typed array constructor');\n", " };\n", "\n", " var exportTypedArrayMethod$1 = function (KEY, property, forced, options) {\n", " if (!DESCRIPTORS) return;\n", " if (forced) for (var ARRAY in TypedArrayConstructorsList) {\n", " var TypedArrayConstructor = global$4[ARRAY];\n", " if (TypedArrayConstructor && hasOwn(TypedArrayConstructor.prototype, KEY)) try {\n", " delete TypedArrayConstructor.prototype[KEY];\n", " } catch (error) {\n", " // old WebKit bug - some methods are non-configurable\n", " try {\n", " TypedArrayConstructor.prototype[KEY] = property;\n", " } catch (error2) {\n", " /* empty */\n", " }\n", " }\n", " }\n", "\n", " if (!TypedArrayPrototype[KEY] || forced) {\n", " redefine(TypedArrayPrototype, KEY, forced ? property : NATIVE_ARRAY_BUFFER_VIEWS && Int8ArrayPrototype$1[KEY] || property, options);\n", " }\n", " };\n", "\n", " var exportTypedArrayStaticMethod = function (KEY, property, forced) {\n", " var ARRAY, TypedArrayConstructor;\n", " if (!DESCRIPTORS) return;\n", "\n", " if (setPrototypeOf) {\n", " if (forced) for (ARRAY in TypedArrayConstructorsList) {\n", " TypedArrayConstructor = global$4[ARRAY];\n", " if (TypedArrayConstructor && hasOwn(TypedArrayConstructor, KEY)) try {\n", " delete TypedArrayConstructor[KEY];\n", " } catch (error) {\n", " /* empty */\n", " }\n", " }\n", "\n", " if (!TypedArray[KEY] || forced) {\n", " // V8 ~ Chrome 49-50 `%TypedArray%` methods are non-writable non-configurable\n", " try {\n", " return redefine(TypedArray, KEY, forced ? property : NATIVE_ARRAY_BUFFER_VIEWS && TypedArray[KEY] || property);\n", " } catch (error) {\n", " /* empty */\n", " }\n", " } else return;\n", " }\n", "\n", " for (ARRAY in TypedArrayConstructorsList) {\n", " TypedArrayConstructor = global$4[ARRAY];\n", "\n", " if (TypedArrayConstructor && (!TypedArrayConstructor[KEY] || forced)) {\n", " redefine(TypedArrayConstructor, KEY, property);\n", " }\n", " }\n", " };\n", "\n", " for (NAME in TypedArrayConstructorsList) {\n", " Constructor = global$4[NAME];\n", " Prototype = Constructor && Constructor.prototype;\n", " if (Prototype) createNonEnumerableProperty(Prototype, TYPED_ARRAY_CONSTRUCTOR, Constructor);else NATIVE_ARRAY_BUFFER_VIEWS = false;\n", " }\n", "\n", " for (NAME in BigIntArrayConstructorsList) {\n", " Constructor = global$4[NAME];\n", " Prototype = Constructor && Constructor.prototype;\n", " if (Prototype) createNonEnumerableProperty(Prototype, TYPED_ARRAY_CONSTRUCTOR, Constructor);\n", " } // WebKit bug - typed arrays constructors prototype is Object.prototype\n", "\n", "\n", " if (!NATIVE_ARRAY_BUFFER_VIEWS || !isCallable(TypedArray) || TypedArray === Function.prototype) {\n", " // eslint-disable-next-line no-shadow -- safe\n", " TypedArray = function TypedArray() {\n", " throw TypeError$1('Incorrect invocation');\n", " };\n", "\n", " if (NATIVE_ARRAY_BUFFER_VIEWS) for (NAME in TypedArrayConstructorsList) {\n", " if (global$4[NAME]) setPrototypeOf(global$4[NAME], TypedArray);\n", " }\n", " }\n", "\n", " if (!NATIVE_ARRAY_BUFFER_VIEWS || !TypedArrayPrototype || TypedArrayPrototype === ObjectPrototype) {\n", " TypedArrayPrototype = TypedArray.prototype;\n", " if (NATIVE_ARRAY_BUFFER_VIEWS) for (NAME in TypedArrayConstructorsList) {\n", " if (global$4[NAME]) setPrototypeOf(global$4[NAME].prototype, TypedArrayPrototype);\n", " }\n", " } // WebKit bug - one more object in Uint8ClampedArray prototype chain\n", "\n", "\n", " if (NATIVE_ARRAY_BUFFER_VIEWS && getPrototypeOf(Uint8ClampedArrayPrototype) !== TypedArrayPrototype) {\n", " setPrototypeOf(Uint8ClampedArrayPrototype, TypedArrayPrototype);\n", " }\n", "\n", " if (DESCRIPTORS && !hasOwn(TypedArrayPrototype, TO_STRING_TAG)) {\n", " TYPED_ARRAY_TAG_REQUIRED = true;\n", " defineProperty(TypedArrayPrototype, TO_STRING_TAG, {\n", " get: function () {\n", " return isObject(this) ? this[TYPED_ARRAY_TAG] : undefined;\n", " }\n", " });\n", "\n", " for (NAME in TypedArrayConstructorsList) if (global$4[NAME]) {\n", " createNonEnumerableProperty(global$4[NAME], TYPED_ARRAY_TAG, NAME);\n", " }\n", " }\n", "\n", " var arrayBufferViewCore = {\n", " NATIVE_ARRAY_BUFFER_VIEWS: NATIVE_ARRAY_BUFFER_VIEWS,\n", " TYPED_ARRAY_CONSTRUCTOR: TYPED_ARRAY_CONSTRUCTOR,\n", " TYPED_ARRAY_TAG: TYPED_ARRAY_TAG_REQUIRED && TYPED_ARRAY_TAG,\n", " aTypedArray: aTypedArray$1,\n", " aTypedArrayConstructor: aTypedArrayConstructor,\n", " exportTypedArrayMethod: exportTypedArrayMethod$1,\n", " exportTypedArrayStaticMethod: exportTypedArrayStaticMethod,\n", " isView: isView,\n", " isTypedArray: isTypedArray,\n", " TypedArray: TypedArray,\n", " TypedArrayPrototype: TypedArrayPrototype\n", " };\n", "\n", " var ceil = Math.ceil;\n", " var floor = Math.floor; // `ToIntegerOrInfinity` abstract operation\n", " // https://tc39.es/ecma262/#sec-tointegerorinfinity\n", "\n", " var toIntegerOrInfinity$2 = function (argument) {\n", " var number = +argument; // eslint-disable-next-line no-self-compare -- safe\n", "\n", " return number !== number || number === 0 ? 0 : (number > 0 ? floor : ceil)(number);\n", " };\n", "\n", " var toIntegerOrInfinity$1 = toIntegerOrInfinity$2;\n", " var min = Math.min; // `ToLength` abstract operation\n", " // https://tc39.es/ecma262/#sec-tolength\n", "\n", " var toLength$1 = function (argument) {\n", " return argument > 0 ? min(toIntegerOrInfinity$1(argument), 0x1FFFFFFFFFFFFF) : 0; // 2 ** 53 - 1 == 9007199254740991\n", " };\n", "\n", " var toLength = toLength$1; // `LengthOfArrayLike` abstract operation\n", " // https://tc39.es/ecma262/#sec-lengthofarraylike\n", "\n", " var lengthOfArrayLike$1 = function (obj) {\n", " return toLength(obj.length);\n", " };\n", "\n", " var global$3 = global$q;\n", " var toIntegerOrInfinity = toIntegerOrInfinity$2;\n", " var RangeError$2 = global$3.RangeError;\n", "\n", " var toPositiveInteger$1 = function (it) {\n", " var result = toIntegerOrInfinity(it);\n", " if (result < 0) throw RangeError$2(\"The argument can't be less than 0\");\n", " return result;\n", " };\n", "\n", " var global$2 = global$q;\n", " var toPositiveInteger = toPositiveInteger$1;\n", " var RangeError$1 = global$2.RangeError;\n", "\n", " var toOffset$1 = function (it, BYTES) {\n", " var offset = toPositiveInteger(it);\n", " if (offset % BYTES) throw RangeError$1('Wrong offset');\n", " return offset;\n", " };\n", "\n", " var global$1 = global$q;\n", " var call = functionCall;\n", " var ArrayBufferViewCore = arrayBufferViewCore;\n", " var lengthOfArrayLike = lengthOfArrayLike$1;\n", " var toOffset = toOffset$1;\n", " var toIndexedObject = toObject$2;\n", " var fails = fails$7;\n", " var RangeError = global$1.RangeError;\n", " var Int8Array = global$1.Int8Array;\n", " var Int8ArrayPrototype = Int8Array && Int8Array.prototype;\n", " var $set = Int8ArrayPrototype && Int8ArrayPrototype.set;\n", " var aTypedArray = ArrayBufferViewCore.aTypedArray;\n", " var exportTypedArrayMethod = ArrayBufferViewCore.exportTypedArrayMethod;\n", " var WORKS_WITH_OBJECTS_AND_GEERIC_ON_TYPED_ARRAYS = !fails(function () {\n", " // eslint-disable-next-line es/no-typed-arrays -- required for testing\n", " var array = new Uint8ClampedArray(2);\n", " call($set, array, {\n", " length: 1,\n", " 0: 3\n", " }, 1);\n", " return array[1] !== 3;\n", " }); // https://bugs.chromium.org/p/v8/issues/detail?id=11294 and other\n", "\n", " var TO_OBJECT_BUG = WORKS_WITH_OBJECTS_AND_GEERIC_ON_TYPED_ARRAYS && ArrayBufferViewCore.NATIVE_ARRAY_BUFFER_VIEWS && fails(function () {\n", " var array = new Int8Array(2);\n", " array.set(1);\n", " array.set('2', 1);\n", " return array[0] !== 0 || array[1] !== 2;\n", " }); // `%TypedArray%.prototype.set` method\n", " // https://tc39.es/ecma262/#sec-%typedarray%.prototype.set\n", "\n", " exportTypedArrayMethod('set', function set(arrayLike\n", " /* , offset */\n", " ) {\n", " aTypedArray(this);\n", " var offset = toOffset(arguments.length > 1 ? arguments[1] : undefined, 1);\n", " var src = toIndexedObject(arrayLike);\n", " if (WORKS_WITH_OBJECTS_AND_GEERIC_ON_TYPED_ARRAYS) return call($set, this, src, offset);\n", " var length = this.length;\n", " var len = lengthOfArrayLike(src);\n", " var index = 0;\n", " if (len + offset > length) throw RangeError('Wrong length');\n", "\n", " while (index < len) this[offset + index] = src[index++];\n", " }, !WORKS_WITH_OBJECTS_AND_GEERIC_ON_TYPED_ARRAYS || TO_OBJECT_BUG);\n", "\n", " /*\n", " * The MIT License (MIT)\n", " *\n", " * Copyright (c) 2014 Broad Institute\n", " *\n", " * Permission is hereby granted, free of charge, to any person obtaining a copy\n", " * of this software and associated documentation files (the \"Software\"), to deal\n", " * in the Software without restriction, including without limitation the rights\n", " * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n", " * copies of the Software, and to permit persons to whom the Software is\n", " * furnished to do so, subject to the following conditions:\n", " *\n", " * The above copyright notice and this permission notice shall be included in\n", " * all copies or substantial portions of the Software.\n", " *\n", " *\n", " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n", " * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n", " * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n", " * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n", " * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n", " * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n", " * THE SOFTWARE.\n", " */\n", " // TODO -- big endian?\n", " class BinaryParser$1 {\n", " constructor(dataView, littleEndian) {\n", " this.littleEndian = littleEndian !== undefined ? littleEndian : true;\n", " this.position = 0;\n", " this.view = dataView;\n", " this.length = dataView.byteLength;\n", " }\n", "\n", " available() {\n", " return this.length - this.position;\n", " }\n", "\n", " remLength() {\n", " return this.length - this.position;\n", " }\n", "\n", " hasNext() {\n", " return this.position < this.length - 1;\n", " }\n", "\n", " getByte() {\n", " var retValue = this.view.getUint8(this.position, this.littleEndian);\n", " this.position++;\n", " return retValue;\n", " }\n", "\n", " getShort() {\n", " var retValue = this.view.getInt16(this.position, this.littleEndian);\n", " this.position += 2;\n", " return retValue;\n", " }\n", "\n", " getUShort() {\n", " // var byte1 = this.getByte(),\n", " // byte2 = this.getByte(),\n", " // retValue = ((byte2 << 24 >>> 16) + (byte1 << 24 >>> 24));\n", " // return retValue;\n", " //\n", " var retValue = this.view.getUint16(this.position, this.littleEndian);\n", " this.position += 2;\n", " return retValue;\n", " }\n", "\n", " getInt() {\n", " var retValue = this.view.getInt32(this.position, this.littleEndian);\n", " this.position += 4;\n", " return retValue;\n", " }\n", "\n", " getUInt() {\n", " var retValue = this.view.getUint32(this.position, this.littleEndian);\n", " this.position += 4;\n", " return retValue;\n", " }\n", "\n", " getLong() {\n", " // DataView doesn't support long. So we'll try manually\n", " var b = [];\n", " b[0] = this.view.getUint8(this.position);\n", " b[1] = this.view.getUint8(this.position + 1);\n", " b[2] = this.view.getUint8(this.position + 2);\n", " b[3] = this.view.getUint8(this.position + 3);\n", " b[4] = this.view.getUint8(this.position + 4);\n", " b[5] = this.view.getUint8(this.position + 5);\n", " b[6] = this.view.getUint8(this.position + 6);\n", " b[7] = this.view.getUint8(this.position + 7);\n", " var value = 0;\n", "\n", " if (this.littleEndian) {\n", " for (let i = b.length - 1; i >= 0; i--) {\n", " value = value * 256 + b[i];\n", " }\n", " } else {\n", " for (let i = 0; i < b.length; i++) {\n", " value = value * 256 + b[i];\n", " }\n", " }\n", "\n", " this.position += 8;\n", " return value;\n", " }\n", "\n", " getString(len) {\n", " var s = \"\";\n", " var c;\n", "\n", " while ((c = this.view.getUint8(this.position++)) !== 0) {\n", " s += String.fromCharCode(c);\n", " if (len && s.length === len) break;\n", " }\n", "\n", " return s;\n", " }\n", "\n", " getFixedLengthString(len) {\n", " var s = \"\";\n", " var i;\n", " var c;\n", "\n", " for (i = 0; i < len; i++) {\n", " c = this.view.getUint8(this.position++);\n", "\n", " if (c > 0) {\n", " s += String.fromCharCode(c);\n", " }\n", " }\n", "\n", " return s;\n", " }\n", "\n", " getFixedLengthTrimmedString(len) {\n", " var s = \"\";\n", " var i;\n", " var c;\n", "\n", " for (i = 0; i < len; i++) {\n", " c = this.view.getUint8(this.position++);\n", "\n", " if (c > 32) {\n", " s += String.fromCharCode(c);\n", " }\n", " }\n", "\n", " return s;\n", " }\n", "\n", " getFloat() {\n", " var retValue = this.view.getFloat32(this.position, this.littleEndian);\n", " this.position += 4;\n", " return retValue;\n", " }\n", "\n", " getDouble() {\n", " var retValue = this.view.getFloat64(this.position, this.littleEndian);\n", " this.position += 8;\n", " return retValue;\n", " }\n", "\n", " skip(n) {\n", " this.position += n;\n", " return this.position;\n", " }\n", " /**\n", " * Return a BGZip (bam and tabix) virtual pointer\n", " * TODO -- why isn't 8th byte used ?\n", " * @returns {*}\n", " */\n", "\n", "\n", " getVPointer() {\n", " var position = this.position,\n", " offset = this.view.getUint8(position + 1) << 8 | this.view.getUint8(position),\n", " byte6 = (this.view.getUint8(position + 6) & 0xff) * 0x100000000,\n", " byte5 = (this.view.getUint8(position + 5) & 0xff) * 0x1000000,\n", " byte4 = (this.view.getUint8(position + 4) & 0xff) * 0x10000,\n", " byte3 = (this.view.getUint8(position + 3) & 0xff) * 0x100,\n", " byte2 = this.view.getUint8(position + 2) & 0xff,\n", " block = byte6 + byte5 + byte4 + byte3 + byte2;\n", " this.position += 8; // if (block == 0 && offset == 0) {\n", " // return null;\n", " // } else {\n", "\n", " return new VPointer$1(block, offset); // }\n", " }\n", "\n", " }\n", "\n", " class VPointer$1 {\n", " constructor(block, offset) {\n", " this.block = block;\n", " this.offset = offset;\n", " }\n", "\n", " isLessThan(vp) {\n", " return this.block < vp.block || this.block === vp.block && this.offset < vp.offset;\n", " }\n", "\n", " isGreaterThan(vp) {\n", " return this.block > vp.block || this.block === vp.block && this.offset > vp.offset;\n", " }\n", "\n", " print() {\n", " return \"\" + this.block + \":\" + this.offset;\n", " }\n", "\n", " }\n", "\n", " const CSI1_MAGIC$1 = 21582659; // CSI\\1\n", "\n", " const CSI2_MAGIC$1 = 38359875; // CSI\\2\n", "\n", " async function parseCsiIndex(arrayBuffer, genome) {\n", " const idx = new CSIIndex();\n", " idx.parse(arrayBuffer, genome);\n", " return idx;\n", " }\n", "\n", " class CSIIndex {\n", " constructor(tabix) {\n", " this.tabix = true; // Means whatever is indexed is BGZipped\n", " }\n", "\n", " parse(arrayBuffer, genome) {\n", " const parser = new BinaryParser$1(new DataView(arrayBuffer));\n", " const magic = parser.getInt();\n", "\n", " if (magic !== CSI1_MAGIC$1) {\n", " if (magic === CSI2_MAGIC$1) {\n", " throw Error(\"CSI version 2 is not supported. Please enter an issue at https://github.com/igvteam/igv.js\");\n", " } else {\n", " throw Error(\"Not a CSI index\");\n", " }\n", " }\n", "\n", " this.indices = [];\n", " this.blockMin = Number.MAX_SAFE_INTEGER;\n", " this.blockMax = 0;\n", " this.sequenceIndexMap = {};\n", " this.minShift = parser.getInt();\n", " this.depth = parser.getInt();\n", " const lAux = parser.getInt();\n", "\n", " if (lAux >= 28) {\n", " // Tabix header parameters aren't used, but they must be read to advance the pointer\n", " parser.getInt();\n", " parser.getInt();\n", " parser.getInt();\n", " parser.getInt();\n", " parser.getInt();\n", " parser.getInt();\n", " const l_nm = parser.getInt();\n", " const nameEndPos = parser.position + l_nm;\n", " let i = 0;\n", "\n", " while (parser.position < nameEndPos) {\n", " let seq_name = parser.getString(); // Translate to \"official\" chr name.\n", "\n", " if (genome) {\n", " seq_name = genome.getChromosomeName(seq_name);\n", " }\n", "\n", " this.sequenceIndexMap[seq_name] = i;\n", " i++;\n", " }\n", " }\n", "\n", " const MAX_BIN = this.bin_limit() + 1;\n", " const nref = parser.getInt();\n", "\n", " for (let ref = 0; ref < nref; ref++) {\n", " const binIndex = [];\n", " const loffset = [];\n", " const nbin = parser.getInt();\n", "\n", " for (let b = 0; b < nbin; b++) {\n", " const binNumber = parser.getInt();\n", " loffset[binNumber] = parser.getVPointer();\n", "\n", " if (binNumber > MAX_BIN) {\n", " // This is a psuedo bin, not used but we have to consume the bytes\n", " parser.getInt(); // # of chunks for this bin\n", "\n", " parser.getVPointer(); // unmapped beg\n", "\n", " parser.getVPointer(); // unmapped end\n", "\n", " parser.getLong();\n", " parser.getLong();\n", " } else {\n", " binIndex[binNumber] = [];\n", " const nchnk = parser.getInt(); // # of chunks for this bin\n", "\n", " for (let i = 0; i < nchnk; i++) {\n", " const cs = parser.getVPointer(); //chunk_beg\n", "\n", " const ce = parser.getVPointer(); //chunk_end\n", "\n", " if (cs && ce) {\n", " if (cs.block < this.blockMin) {\n", " this.blockMin = cs.block; // Block containing first alignment\n", " }\n", "\n", " if (ce.block > this.blockMax) {\n", " this.blockMax = ce.block;\n", " }\n", "\n", " binIndex[binNumber].push([cs, ce]);\n", " }\n", " }\n", " }\n", " }\n", "\n", " if (nbin > 0) {\n", " this.indices[ref] = {\n", " binIndex: binIndex,\n", " loffset: loffset\n", " };\n", " }\n", " }\n", " }\n", " /**\n", " * Fetch blocks for a particular genomic range. This method is public so it can be unit-tested.\n", " *\n", " * @param refId the sequence dictionary index of the chromosome\n", " * @param min genomic start position\n", " * @param max genomic end position\n", " * @param return an array of {minv: {filePointer, offset}, {maxv: {filePointer, offset}}\n", " */\n", "\n", "\n", " blocksForRange(refId, min, max) {\n", " const ba = this.indices[refId];\n", "\n", " if (!ba) {\n", " return [];\n", " } else {\n", " const overlappingBins = this.reg2bins(min, max); // List of bin #s that overlap min, max\n", "\n", " if (overlappingBins.length == 0) return [];\n", " const chunks = []; // Find chunks in overlapping bins. Leaf bins (< 4681) are not pruned\n", "\n", " for (let binRange of overlappingBins) {\n", " for (let bin = binRange[0]; bin <= binRange[1]; bin++) {\n", " if (ba.binIndex[bin]) {\n", " const binChunks = ba.binIndex[bin];\n", " const nchnk = binChunks.length;\n", "\n", " for (let c = 0; c < nchnk; ++c) {\n", " const cs = binChunks[c][0];\n", " const ce = binChunks[c][1];\n", " chunks.push({\n", " minv: cs,\n", " maxv: ce,\n", " bin: bin\n", " });\n", " }\n", " }\n", " }\n", " }\n", "\n", " const lowestOffset = ba.loffset[overlappingBins[0]];\n", " return optimizeChunks$1(chunks, lowestOffset);\n", " }\n", " } // reg2bins implementation adapted from GMOD/tabix-js https://github.com/GMOD/tabix-js/blob/master/src/csi.ts\n", "\n", "\n", " reg2bins(beg, end) {\n", " beg -= 1; // < convert to 1-based closed\n", "\n", " if (beg < 1) beg = 1;\n", " if (end > 2 ** 50) end = 2 ** 34; // 17 GiB ought to be enough for anybody\n", "\n", " end -= 1;\n", " let l = 0;\n", " let t = 0;\n", " let s = this.minShift + this.depth * 3;\n", " const bins = [];\n", "\n", " for (; l <= this.depth; s -= 3, t += 1 << l * 3, l += 1) {\n", " const b = t + (beg >> s);\n", " const e = t + (end >> s);\n", " 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)\n", "\n", " bins.push([b, e]);\n", " }\n", "\n", " return bins;\n", " } // function reg2bins(beg, end, min_shift, depth) {\n", " // let l, t, n, s = min_shift + depth * 3;\n", " // const bins = [];\n", " // for (--end, l = n = t = 0; l <= depth; s -= 3, t += 1 << l * 3, ++l) {\n", " // let b = t + (beg >> s), e = t + (end >> s), i;\n", " // for (i = b; i <= e; ++i) bins[n++] = i;\n", " // }\n", " // return bins;\n", " // }\n", "\n", "\n", " bin_limit() {\n", " return ((1 << (this.depth + 1) * 3) - 1) / 7;\n", " }\n", "\n", " }\n", "\n", " function optimizeChunks$1(chunks, lowest) {\n", " const mergedChunks = [];\n", " let lastChunk = null;\n", " if (chunks.length === 0) return chunks;\n", " chunks.sort(function (c0, c1) {\n", " const dif = c0.minv.block - c1.minv.block;\n", "\n", " if (dif !== 0) {\n", " return dif;\n", " } else {\n", " return c0.minv.offset - c1.minv.offset;\n", " }\n", " });\n", " chunks.forEach(function (chunk) {\n", " if (!lowest || chunk.maxv.isGreaterThan(lowest)) {\n", " if (lastChunk === null) {\n", " mergedChunks.push(chunk);\n", " lastChunk = chunk;\n", " } else {\n", " if (canMerge$1(lastChunk, chunk)) {\n", " if (chunk.maxv.isGreaterThan(lastChunk.maxv)) {\n", " lastChunk.maxv = chunk.maxv;\n", " }\n", " } else {\n", " mergedChunks.push(chunk);\n", " lastChunk = chunk;\n", " }\n", " }\n", " } else {\n", " console.log(`skipping chunk ${chunk.minv.block} - ${chunk.maxv.block}`);\n", " }\n", " });\n", " return mergedChunks;\n", " }\n", "\n", " function canMerge$1(chunk1, chunk2) {\n", " return chunk2.minv.block - chunk1.maxv.block < 65000 && chunk2.maxv.block - chunk1.minv.block < 5000000; // lastChunk.minv.block === lastChunk.maxv.block &&\n", " // lastChunk.maxv.block === chunk.minv.block &&\n", " // chunk.minv.block === chunk.maxv.block\n", " }\n", "\n", " const BAI_MAGIC$1 = 21578050;\n", " const TABIX_MAGIC$1 = 21578324;\n", "\n", " async function parseBamIndex(arrayBuffer, genome) {\n", " return parseIndex(arrayBuffer, false, genome);\n", " }\n", "\n", " async function parseTabixIndex(arrayBuffer, genome) {\n", " return parseIndex(arrayBuffer, true, genome);\n", " }\n", "\n", " async function parseIndex(arrayBuffer, tabix, genome) {\n", " const indices = [];\n", " let blockMin = Number.MAX_SAFE_INTEGER;\n", " let blockMax = 0;\n", " const parser = new BinaryParser$1(new DataView(arrayBuffer));\n", " const magic = parser.getInt();\n", " const sequenceIndexMap = {};\n", "\n", " if (magic === BAI_MAGIC$1 || tabix && magic === TABIX_MAGIC$1) {\n", " const nref = parser.getInt();\n", "\n", " if (tabix) {\n", " // Tabix header parameters aren't used, but they must be read to advance the pointer\n", " parser.getInt();\n", " parser.getInt();\n", " parser.getInt();\n", " parser.getInt();\n", " parser.getInt();\n", " parser.getInt();\n", " parser.getInt();\n", "\n", " for (let i = 0; i < nref; i++) {\n", " let seq_name = parser.getString(); // Translate to \"official\" chr name.\n", "\n", " if (genome) {\n", " seq_name = genome.getChromosomeName(seq_name);\n", " }\n", "\n", " sequenceIndexMap[seq_name] = i;\n", " }\n", " }\n", "\n", " for (let ref = 0; ref < nref; ref++) {\n", " const binIndex = {};\n", " const linearIndex = [];\n", " const nbin = parser.getInt();\n", "\n", " for (let b = 0; b < nbin; b++) {\n", " const binNumber = parser.getInt();\n", "\n", " if (binNumber === 37450) {\n", " // This is a psuedo bin, not used but we have to consume the bytes\n", " parser.getInt(); // # of chunks for this bin\n", "\n", " parser.getVPointer(); // unmapped beg\n", "\n", " parser.getVPointer(); // unmapped end\n", "\n", " parser.getLong();\n", " parser.getLong();\n", " } else {\n", " binIndex[binNumber] = [];\n", " const nchnk = parser.getInt(); // # of chunks for this bin\n", "\n", " for (let i = 0; i < nchnk; i++) {\n", " const cs = parser.getVPointer(); //chunk_beg\n", "\n", " const ce = parser.getVPointer(); //chunk_end\n", "\n", " if (cs && ce) {\n", " if (cs.block < blockMin) {\n", " blockMin = cs.block; // Block containing first alignment\n", " }\n", "\n", " if (ce.block > blockMax) {\n", " blockMax = ce.block;\n", " }\n", "\n", " binIndex[binNumber].push([cs, ce]);\n", " }\n", " }\n", " }\n", " }\n", "\n", " const nintv = parser.getInt();\n", "\n", " for (let i = 0; i < nintv; i++) {\n", " const cs = parser.getVPointer();\n", " linearIndex.push(cs); // Might be null\n", " }\n", "\n", " if (nbin > 0) {\n", " indices[ref] = {\n", " binIndex: binIndex,\n", " linearIndex: linearIndex\n", " };\n", " }\n", " }\n", " } else {\n", " throw new Error(indexURL + \" is not a \" + (tabix ? \"tabix\" : \"bai\") + \" file\");\n", " }\n", "\n", " return new BamIndex(indices, blockMin, blockMax, sequenceIndexMap, tabix);\n", " }\n", "\n", " class BamIndex {\n", " constructor(indices, blockMin, blockMax, sequenceIndexMap, tabix) {\n", " this.firstAlignmentBlock = blockMin;\n", " this.lastAlignmentBlock = blockMax;\n", " this.indices = indices;\n", " this.sequenceIndexMap = sequenceIndexMap;\n", " this.tabix = tabix;\n", " }\n", " /**\n", " * Fetch blocks for a particular genomic range. This method is public so it can be unit-tested.\n", " *\n", " * @param refId the sequence dictionary index of the chromosome\n", " * @param min genomic start position\n", " * @param max genomic end position\n", " * @param return an array of {minv: {filePointer, offset}, {maxv: {filePointer, offset}}\n", " */\n", "\n", "\n", " blocksForRange(refId, min, max) {\n", " const bam = this;\n", " const ba = bam.indices[refId];\n", "\n", " if (!ba) {\n", " return [];\n", " } else {\n", " const overlappingBins = reg2bins(min, max); // List of bin #s that overlap min, max\n", "\n", " const chunks = []; // Find chunks in overlapping bins. Leaf bins (< 4681) are not pruned\n", "\n", " for (let binRange of overlappingBins) {\n", " for (let bin = binRange[0]; bin <= binRange[1]; bin++) {\n", " if (ba.binIndex[bin]) {\n", " const binChunks = ba.binIndex[bin],\n", " nchnk = binChunks.length;\n", "\n", " for (let c = 0; c < nchnk; ++c) {\n", " const cs = binChunks[c][0];\n", " const ce = binChunks[c][1];\n", " chunks.push({\n", " minv: cs,\n", " maxv: ce,\n", " bin: bin\n", " });\n", " }\n", " }\n", " }\n", " } // Use the linear index to find minimum file position of chunks that could contain alignments in the region\n", "\n", "\n", " const nintv = ba.linearIndex.length;\n", " let lowest = null;\n", " const minLin = Math.min(min >> 14, nintv - 1);\n", " const maxLin = Math.min(max >> 14, nintv - 1);\n", "\n", " for (let i = minLin; i <= maxLin; ++i) {\n", " const vp = ba.linearIndex[i];\n", "\n", " if (vp) {\n", " // 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\n", " if (!lowest || vp.isLessThan(lowest)) {\n", " lowest = vp;\n", " }\n", " }\n", " }\n", "\n", " return optimizeChunks(chunks, lowest);\n", " }\n", " }\n", "\n", " }\n", "\n", " function optimizeChunks(chunks, lowest) {\n", " const mergedChunks = [];\n", " let lastChunk = null;\n", " if (chunks.length === 0) return chunks;\n", " chunks.sort(function (c0, c1) {\n", " const dif = c0.minv.block - c1.minv.block;\n", "\n", " if (dif !== 0) {\n", " return dif;\n", " } else {\n", " return c0.minv.offset - c1.minv.offset;\n", " }\n", " });\n", " chunks.forEach(function (chunk) {\n", " if (!lowest || chunk.maxv.isGreaterThan(lowest)) {\n", " if (lastChunk === null) {\n", " mergedChunks.push(chunk);\n", " lastChunk = chunk;\n", " } else {\n", " if (canMerge(lastChunk, chunk)) {\n", " if (chunk.maxv.isGreaterThan(lastChunk.maxv)) {\n", " lastChunk.maxv = chunk.maxv;\n", " }\n", " } else {\n", " mergedChunks.push(chunk);\n", " lastChunk = chunk;\n", " }\n", " }\n", " } else {\n", " console.log(`skipping chunk ${chunk.minv.block} - ${chunk.maxv.block}`);\n", " }\n", " });\n", " return mergedChunks;\n", " }\n", "\n", " function canMerge(chunk1, chunk2) {\n", " return chunk2.minv.block - chunk1.maxv.block < 65000 && chunk2.maxv.block - chunk1.minv.block < 5000000; // lastChunk.minv.block === lastChunk.maxv.block &&\n", " // lastChunk.maxv.block === chunk.minv.block &&\n", " // chunk.minv.block === chunk.maxv.block\n", " }\n", " /**\n", " * Calculate the list of bins that overlap with region [beg, end]\n", " *\n", " */\n", "\n", "\n", " function reg2bins(beg, end) {\n", " const list = [];\n", " if (end >= 1 << 29) end = 1 << 29;\n", " --end;\n", " list.push(0);\n", " list.push([1 + (beg >> 26), 1 + (end >> 26)]);\n", " list.push([9 + (beg >> 23), 9 + (end >> 23)]);\n", " list.push([73 + (beg >> 20), 73 + (end >> 20)]);\n", " list.push([585 + (beg >> 17), 585 + (end >> 17)]);\n", " list.push([4681 + (beg >> 14), 4681 + (end >> 14)]); // for (k = 1 + (beg >> 26); k <= 1 + (end >> 26); ++k) list.push(k);\n", " // for (k = 9 + (beg >> 23); k <= 9 + (end >> 23); ++k) list.push(k);\n", " // for (k = 73 + (beg >> 20); k <= 73 + (end >> 20); ++k) list.push(k);\n", " // for (k = 585 + (beg >> 17); k <= 585 + (end >> 17); ++k) list.push(k);\n", " // for (k = 4681 + (beg >> 14); k <= 4681 + (end >> 14); ++k) list.push(k);\n", "\n", " return list;\n", " }\n", "\n", " /*\n", " * The MIT License (MIT)\n", " *\n", " * Copyright (c) 2014 Broad Institute\n", " *\n", " * Permission is hereby granted, free of charge, to any person obtaining a copy\n", " * of this software and associated documentation files (the \"Software\"), to deal\n", " * in the Software without restriction, including without limitation the rights\n", " * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n", " * copies of the Software, and to permit persons to whom the Software is\n", " * furnished to do so, subject to the following conditions:\n", " *\n", " * The above copyright notice and this permission notice shall be included in\n", " * all copies or substantial portions of the Software.\n", " *\n", " *\n", " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n", " * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n", " * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n", " * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n", " * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n", " * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n", " * THE SOFTWARE.\n", " */\n", "\n", " async function parseTribbleIndex(arrayBuffer, genome) {\n", " const index = {};\n", " const parser = new BinaryParser$1(new DataView(arrayBuffer));\n", " readHeader(parser);\n", " let nChrs = parser.getInt();\n", "\n", " while (nChrs-- > 0) {\n", " // todo -- support interval tree index, we're assuming its a linear index\n", " const chrIdx = readLinear(parser);\n", " index[chrIdx.chr] = chrIdx;\n", " }\n", "\n", " return new TribbleIndex(index);\n", " /**\n", " * Read the header file. Data here is not used in igv.js but we need to read it to advance the pointer.\n", " * @param parser\n", " */\n", "\n", " function readHeader(parser) {\n", " parser.getInt(); // view._getInt32(offset += 32, true);\n", "\n", " parser.getInt();\n", " const version = parser.getInt();\n", " parser.getString();\n", " parser.getLong();\n", " parser.getLong();\n", " parser.getString();\n", " parser.getInt();\n", "\n", " if (version >= 3) {\n", " let nProperties = parser.getInt();\n", "\n", " while (nProperties-- > 0) {\n", " parser.getString();\n", " parser.getString();\n", " }\n", " }\n", " }\n", "\n", " function readLinear(parser) {\n", " let chr = parser.getString();\n", "\n", " if (genome) chr = genome.getChromosomeName(chr);\n", " const binWidth = parser.getInt();\n", " const nBins = parser.getInt();\n", " const longestFeature = parser.getInt();\n", " parser.getInt() > 0;\n", " parser.getInt(); // note the code below accounts for > 60% of the total time to read an index\n", "\n", " let pos = parser.getLong();\n", " const blocks = new Array();\n", "\n", " for (let binNumber = 0; binNumber < nBins; binNumber++) {\n", " const nextPos = parser.getLong();\n", " blocks.push({\n", " min: pos,\n", " max: nextPos\n", " }); // {position: pos, size: size});\n", "\n", " pos = nextPos;\n", " }\n", "\n", " return {\n", " chr: chr,\n", " blocks: blocks,\n", " longestFeature: longestFeature,\n", " binWidth: binWidth\n", " };\n", " }\n", " }\n", "\n", " class TribbleIndex {\n", " constructor(chrIndexTable) {\n", " this.chrIndex = chrIndexTable; // Dictionary of chr -> tribble index\n", " }\n", " /**\n", " * Fetch blocks for a particular genomic range.\n", " *\n", " * @param queryChr the sequence dictionary index of the chromosome\n", " * @param min genomic start position\n", " * @param max genomic end position\n", " */\n", "\n", "\n", " blocksForRange(queryChr, min, max) {\n", " const chrIdx = this.chrIndex[queryChr];\n", "\n", " if (chrIdx) {\n", " const blocks = chrIdx.blocks;\n", " const longestFeature = chrIdx.longestFeature;\n", " const binWidth = chrIdx.binWidth;\n", " const adjustedPosition = Math.max(min - longestFeature, 0);\n", " const startBinNumber = Math.floor(adjustedPosition / binWidth);\n", " if (startBinNumber >= blocks.length) // are we off the end of the bin list, so return nothing\n", " return [];else {\n", " 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\n", "\n", " const startPos = blocks[startBinNumber].min;\n", " const endPos = blocks[endBinNumber].max;\n", " const size = endPos - startPos;\n", "\n", " if (size === 0) {\n", " return [];\n", " } else {\n", " const mergedBlock = {\n", " minv: {\n", " block: startPos,\n", " offset: 0\n", " },\n", " maxv: {\n", " block: endPos,\n", " offset: 0\n", " }\n", " };\n", " return [mergedBlock];\n", " }\n", " }\n", " } else {\n", " return undefined;\n", " }\n", " }\n", "\n", " }\n", "\n", " const CSI1_MAGIC = 21582659; // CSI\\1\n", "\n", " const CSI2_MAGIC = 38359875; // CSI\\2\n", "\n", " const BAI_MAGIC = 21578050;\n", " const TABIX_MAGIC = 21578324;\n", " const TRIBBLE_MAGIC = 1480870228; // byte[]{'T', 'I', 'D', 'X'};\n", "\n", " /**\n", " * @param indexURL\n", " * @param config\n", " * @param tabix\n", " *\n", " */\n", "\n", " async function loadIndex(indexURL, config, genome) {\n", " let arrayBuffer = await igvxhr.loadArrayBuffer(indexURL, buildOptions$1(config));\n", " let dv = new DataView(arrayBuffer); // Some indexs are gzipped, specifically tabix, and csi. Bam (bai) are not. Tribble is usually not.\n", " // Check first 2 bytes of file for gzip magic number, and inflate if neccessary\n", "\n", " if (dv.getUint8(0) === 0x1f && dv.getUint8(1) === 0x8b) {\n", " // gzipped\n", " const inflate = new Zlib$2.Gunzip(new Uint8Array(arrayBuffer));\n", " arrayBuffer = inflate.decompress().buffer;\n", " dv = new DataView(arrayBuffer);\n", " }\n", "\n", " const magic = dv.getInt32(0, true);\n", "\n", " switch (magic) {\n", " case BAI_MAGIC:\n", " return parseBamIndex(arrayBuffer, genome);\n", "\n", " case TABIX_MAGIC:\n", " return parseTabixIndex(arrayBuffer, genome);\n", "\n", " case CSI1_MAGIC:\n", " return parseCsiIndex(arrayBuffer, genome);\n", "\n", " case TRIBBLE_MAGIC:\n", " return parseTribbleIndex(arrayBuffer, genome);\n", "\n", " case CSI2_MAGIC:\n", " throw Error(\"CSI version 2 is not supported.\");\n", "\n", " default:\n", " throw Error(`Unrecognized index type: ${indexURL}`);\n", " }\n", " }\n", "\n", " /*\n", " * The MIT License (MIT)\n", " *\n", " * Copyright (c) 2016-2017 The Regents of the University of California\n", " * Author: Jim Robinson\n", " *\n", " * Permission is hereby granted, free of charge, to any person obtaining a copy\n", " * of this software and associated documentation files (the \"Software\"), to deal\n", " * in the Software without restriction, including without limitation the rights\n", " * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n", " * copies of the Software, and to permit persons to whom the Software is\n", " * furnished to do so, subject to the following conditions:\n", " *\n", " * The above copyright notice and this permission notice shall be included in\n", " * all copies or substantial portions of the Software.\n", " *\n", " *\n", " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n", " * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n", " * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n", " * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n", " * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n", " * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n", " * THE SOFTWARE.\n", " */\n", " function getDataWrapper(data) {\n", " if (typeof data == 'string' || data instanceof String) {\n", " return new StringDataWrapper(data);\n", " } else {\n", " return new ByteArrayDataWrapper(data);\n", " }\n", " } // Data might be a string, or an UInt8Array\n", "\n", "\n", " class StringDataWrapper {\n", " constructor(string) {\n", " this.data = string;\n", " this.ptr = 0;\n", " }\n", "\n", " nextLine() {\n", " var start = this.ptr,\n", " idx = this.data.indexOf('\\n', start),\n", " data = this.data;\n", "\n", " if (idx > 0) {\n", " this.ptr = idx + 1; // Advance pointer for next line\n", "\n", " if (idx > start && data.charAt(idx - 1) === '\\r') {\n", " // Trim CR manually in CR/LF sequence\n", " return data.substring(start, idx - 1);\n", " }\n", "\n", " return data.substring(start, idx);\n", " } else {\n", " var length = data.length;\n", " this.ptr = length; // Return undefined only at the very end of the data\n", "\n", " return start >= length ? undefined : data.substring(start);\n", " }\n", " }\n", "\n", " }\n", "\n", " class ByteArrayDataWrapper {\n", " constructor(array) {\n", " this.data = array;\n", " this.length = this.data.length;\n", " this.ptr = 0;\n", " }\n", "\n", " nextLine() {\n", " var c, result;\n", " result = \"\";\n", " if (this.ptr >= this.length) return undefined;\n", "\n", " for (var i = this.ptr; i < this.length; i++) {\n", " c = String.fromCharCode(this.data[i]);\n", " if (c === '\\r') continue;\n", " if (c === '\\n') break;\n", " result = result + c;\n", " }\n", "\n", " this.ptr = i + 1;\n", " return result;\n", " }\n", "\n", " }\n", "\n", " class BGZipLineReader {\n", " constructor(config) {\n", " this.config = config;\n", " this.filePtr = 0;\n", " this.bufferPtr = 0;\n", " this.buffer;\n", " }\n", "\n", " async nextLine() {\n", " let result = undefined;\n", "\n", " try {\n", " while (true) {\n", " const length = this.buffer ? this.buffer.length : 0;\n", "\n", " while (this.bufferPtr < length) {\n", " const c = String.fromCharCode(this.buffer[this.bufferPtr++]);\n", " if (c === '\\r') continue;\n", "\n", " if (c === '\\n') {\n", " return result;\n", " }\n", "\n", " result = result ? result + c : c;\n", " }\n", "\n", " if (this.eof) {\n", " return result;\n", " } else {\n", " await this.readNextBlock();\n", " }\n", " }\n", " } catch (e) {\n", " console.warn(e);\n", " this.eof = true;\n", " return result;\n", " }\n", " }\n", "\n", " async readNextBlock() {\n", " const bsizeOptions = buildOptions$1(this.config, {\n", " range: {\n", " start: this.filePtr,\n", " size: 26\n", " }\n", " });\n", " const abuffer = await igvxhr.loadArrayBuffer(this.config.url, bsizeOptions);\n", " const bufferSize = bgzBlockSize(abuffer); //console.log(`next block ${this.filePtr} ${bufferSize}`);\n", "\n", " if (bufferSize === 0) {\n", " this.eof = true;\n", " this.buffer = undefined;\n", " } else {\n", " const options = buildOptions$1(this.config, {\n", " range: {\n", " start: this.filePtr,\n", " size: bufferSize\n", " }\n", " });\n", " const data = await igvxhr.loadArrayBuffer(this.config.url, options);\n", "\n", " if (data.byteLength < bufferSize) {\n", " this.eof = true; // Assumption\n", " }\n", "\n", " this.buffer = unbgzf(data);\n", " this.bufferPtr = 0;\n", " this.filePtr += data.byteLength; //data.byteLength;\n", " }\n", " }\n", "\n", " }\n", "\n", " /*\n", " * The MIT License (MIT)\n", " *\n", " * Copyright (c) 2014 Broad Institute\n", " *\n", " * Permission is hereby granted, free of charge, to any person obtaining a copy\n", " * of this software and associated documentation files (the \"Software\"), to deal\n", " * in the Software without restriction, including without limitation the rights\n", " * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n", " * copies of the Software, and to permit persons to whom the Software is\n", " * furnished to do so, subject to the following conditions:\n", " *\n", " * The above copyright notice and this permission notice shall be included in\n", " * all copies or substantial portions of the Software.\n", " *\n", " *\n", " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n", " * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n", " * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n", " * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n", " * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n", " * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n", " * THE SOFTWARE.\n", " */\n", " const isString$1 = isString$2;\n", " /**\n", " * Reader for \"bed like\" files (tab delimited files with 1 feature per line: bed, gff, vcf, etc)\n", " *\n", " * @param config\n", " * @constructor\n", " */\n", "\n", " class FeatureFileReader {\n", " constructor(config, genome) {\n", " var uriParts;\n", " this.config = config || {};\n", " this.genome = genome;\n", " this.indexURL = config.indexURL;\n", " this.indexed = config.indexed;\n", "\n", " if (isFile(this.config.url)) {\n", " this.filename = this.config.url.name;\n", " } else if (isString$1(this.config.url) && this.config.url.startsWith('data:')) {\n", " this.indexed = false; // by definition\n", "\n", " this.dataURI = config.url;\n", " } else {\n", " uriParts = parseUri(this.config.url);\n", " this.filename = config.filename || uriParts.file;\n", " }\n", "\n", " this.parser = this.getParser(this.config);\n", "\n", " if (this.config.format === \"vcf\" && !this.config.indexURL) {\n", " console.warn(\"Warning: index file not specified. The entire vcf file will be loaded.\");\n", " }\n", " }\n", " /**\n", " * Return a promise to load features for the genomic interval\n", " * @param chr\n", " * @param start\n", " * @param end\n", " */\n", "\n", "\n", " async readFeatures(chr, start, end) {\n", " const index = await this.getIndex();\n", "\n", " if (index) {\n", " this.indexed = true;\n", " return this.loadFeaturesWithIndex(chr, start, end);\n", " } else if (this.dataURI) {\n", " this.indexed = false;\n", " return this.loadFeaturesFromDataURI();\n", " } else {\n", " this.indexed = false;\n", " return this.loadFeaturesNoIndex();\n", " }\n", " }\n", "\n", " async readHeader() {\n", " if (this.dataURI) {\n", " this.loadFeaturesFromDataURI(this.dataURI);\n", " return this.header;\n", " } else {\n", " if (this.config.indexURL) {\n", " const index = await this.getIndex();\n", "\n", " if (!index) {\n", " // Note - it should be impossible to get here\n", " throw new Error(\"Unable to load index: \" + this.config.indexURL);\n", " }\n", "\n", " let dataWrapper;\n", "\n", " if (index.tabix) {\n", " dataWrapper = new BGZipLineReader(this.config);\n", " } else {\n", " // Tribble\n", " 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);\n", " const options = buildOptions$1(this.config, {\n", " bgz: index.tabix,\n", " range: {\n", " start: 0,\n", " size: maxSize\n", " }\n", " });\n", " const data = await igvxhr.loadString(this.config.url, options);\n", " dataWrapper = getDataWrapper(data);\n", " }\n", "\n", " this.header = await this.parser.parseHeader(dataWrapper); // Cache header, might be needed to parse features\n", "\n", " return this.header;\n", " } else {\n", " // If this is a non-indexed file we will load all features in advance\n", " const options = buildOptions$1(this.config);\n", " const data = await igvxhr.loadString(this.config.url, options);\n", " let dataWrapper = getDataWrapper(data);\n", " this.header = await this.parser.parseHeader(dataWrapper); // Reset data wrapper and parse features\n", "\n", " dataWrapper = getDataWrapper(data);\n", " this.features = await this.parser.parseFeatures(dataWrapper); // cache features\n", "\n", " return this.header;\n", " }\n", " }\n", " }\n", "\n", " getParser(config) {\n", " switch (config.format) {\n", " case \"vcf\":\n", " return new VcfParser(config);\n", "\n", " case \"seg\":\n", " return new SegParser();\n", "\n", " case \"gwas\":\n", " return new GWASParser(config);\n", "\n", " case \"aed\":\n", " return new AEDParser(config);\n", "\n", " default:\n", " return new FeatureParser(config);\n", " }\n", " }\n", "\n", " async loadFeaturesNoIndex() {\n", " if (this.features) {\n", " // An optimization hack for non-indexed files, features are temporarily cached when header is read.\n", " const tmp = this.features;\n", " delete this.features;\n", " return tmp;\n", " } else {\n", " const options = buildOptions$1(this.config); // Add oauth token, if any\n", "\n", " const data = await igvxhr.loadString(this.config.url, options);\n", "\n", " if (!this.header) {\n", " const dataWrapper = getDataWrapper(data);\n", " this.header = await this.parser.parseHeader(dataWrapper);\n", " }\n", "\n", " const dataWrapper = getDataWrapper(data);\n", " const features = await this.parser.parseFeatures(dataWrapper); // <= PARSING DONE HERE\n", "\n", " return features;\n", " }\n", " }\n", "\n", " async loadFeaturesWithIndex(chr, start, end) {\n", " //console.log(\"Using index\"\n", " const config = this.config;\n", " const parser = this.parser;\n", " const tabix = this.index.tabix;\n", " const refId = tabix ? this.index.sequenceIndexMap[chr] : chr;\n", "\n", " if (refId === undefined) {\n", " return [];\n", " }\n", "\n", " const genome = this.genome;\n", " const blocks = this.index.blocksForRange(refId, start, end);\n", "\n", " if (!blocks || blocks.length === 0) {\n", " return [];\n", " } else {\n", " const allFeatures = [];\n", "\n", " for (let block of blocks) {\n", " const startPos = block.minv.block;\n", " const startOffset = block.minv.offset;\n", " const endOffset = block.maxv.offset;\n", " let endPos;\n", "\n", " if (tabix) {\n", " let lastBlockSize = 0;\n", "\n", " if (endOffset > 0) {\n", " const bsizeOptions = buildOptions$1(config, {\n", " range: {\n", " start: block.maxv.block,\n", " size: 26\n", " }\n", " });\n", " const abuffer = await igvxhr.loadArrayBuffer(config.url, bsizeOptions);\n", " lastBlockSize = bgzBlockSize(abuffer);\n", " }\n", "\n", " endPos = block.maxv.block + lastBlockSize;\n", " } else {\n", " endPos = block.maxv.block;\n", " }\n", "\n", " const options = buildOptions$1(config, {\n", " range: {\n", " start: startPos,\n", " size: endPos - startPos + 1\n", " }\n", " });\n", " let inflated;\n", "\n", " if (tabix) {\n", " const data = await igvxhr.loadArrayBuffer(config.url, options);\n", " inflated = unbgzf(data);\n", " } else {\n", " inflated = await igvxhr.loadString(config.url, options);\n", " }\n", "\n", " const slicedData = startOffset ? inflated.slice(startOffset) : inflated;\n", " const dataWrapper = getDataWrapper(slicedData);\n", " const slicedFeatures = await parser.parseFeatures(dataWrapper); // Filter features not in requested range.\n", "\n", " let inInterval = false;\n", "\n", " for (let i = 0; i < slicedFeatures.length; i++) {\n", " const f = slicedFeatures[i];\n", " const canonicalChromosome = genome ? genome.getChromosomeName(f.chr) : f.chr;\n", "\n", " if (canonicalChromosome !== chr) {\n", " if (allFeatures.length === 0) {\n", " continue; //adjacent chr to the left\n", " } else {\n", " break; //adjacent chr to the right\n", " }\n", " }\n", "\n", " if (f.start > end) {\n", " allFeatures.push(f); // First feature beyond interval\n", "\n", " break;\n", " }\n", "\n", " if (f.end >= start && f.start <= end) {\n", " if (!inInterval) {\n", " inInterval = true;\n", "\n", " if (i > 0) {\n", " allFeatures.push(slicedFeatures[i - 1]);\n", " }\n", " }\n", "\n", " allFeatures.push(f);\n", " }\n", " }\n", " }\n", "\n", " allFeatures.sort(function (a, b) {\n", " return a.start - b.start;\n", " });\n", " return allFeatures;\n", " }\n", " }\n", "\n", " async getIndex() {\n", " if (this.index || !this.config.indexURL) {\n", " return this.index;\n", " } else {\n", " this.index = await this.loadIndex();\n", " return this.index;\n", " }\n", " }\n", " /**\n", " * Return a Promise for the async loaded index\n", " */\n", "\n", "\n", " async loadIndex() {\n", " const indexURL = this.config.indexURL;\n", " return loadIndex(indexURL, this.config, this.genome);\n", " }\n", "\n", " async loadFeaturesFromDataURI() {\n", " if (this.features) {\n", " // An optimization hack for non-indexed files, features are temporarily cached when header is read.\n", " const tmp = this.features;\n", " delete this.features;\n", " return tmp;\n", " } else {\n", " const plain = decodeDataURI(this.dataURI);\n", " let dataWrapper = getDataWrapper(plain);\n", " this.header = await this.parser.parseHeader(dataWrapper);\n", "\n", " if (this.header instanceof String && this.header.startsWith(\"##gff-version 3\")) {\n", " this.format = 'gff3';\n", " }\n", "\n", " dataWrapper = getDataWrapper(plain);\n", " this.features = await this.parser.parseFeatures(dataWrapper);\n", " return this.features;\n", " }\n", " }\n", "\n", " }\n", "\n", " /*\n", " * The MIT License (MIT)\n", " *\n", " * Copyright (c) 2016 University of California San Diego\n", " * Author: Jim Robinson\n", " *\n", " * Permission is hereby granted, free of charge, to any person obtaining a copy\n", " * of this software and associated documentation files (the \"Software\"), to deal\n", " * in the Software without restriction, including without limitation the rights\n", " * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n", " * copies of the Software, and to permit persons to whom the Software is\n", " * furnished to do so, subject to the following conditions:\n", " *\n", " * The above copyright notice and this permission notice shall be included in\n", " * all copies or substantial portions of the Software.\n", " *\n", " *\n", " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n", " * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n", " * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n", " * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n", " * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n", " * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n", " * THE SOFTWARE.\n", " */\n", " /**\n", " * Created by jrobinson on 4/7/16.\n", " */\n", "\n", " const transcriptTypes = new Set(['transcript', 'primary_transcript', 'processed_transcript', 'mRNA', 'mrna']);\n", " const cdsTypes = new Set(['CDS', 'cds']);\n", " const codonTypes = new Set(['start_codon', 'stop_codon']);\n", " const utrTypes = new Set(['5UTR', '3UTR', 'UTR', 'five_prime_UTR', 'three_prime_UTR', \"3'-UTR\", \"5'-UTR\"]);\n", " const exonTypes = new Set(['exon', 'coding-exon']);\n", " const intronType = 'intron';\n", "\n", " const transcriptModelTypes = new Set();\n", "\n", " for (let cltn of [transcriptTypes, cdsTypes, codonTypes, utrTypes, exonTypes]) {\n", " for (let t of cltn) {\n", " transcriptModelTypes.add(t);\n", " }\n", " }\n", "\n", " class GFFHelper {\n", " constructor(options) {\n", " this.format = options.format;\n", " this.filterTypes = options.filterTypes === undefined ? new Set(['chromosome']) : new Set(options.filterTypes);\n", " }\n", "\n", " combineFeatures(features) {\n", " let combinedFeatures;\n", "\n", " if (\"gff3\" === this.format) {\n", " const tmp = this.combineFeaturesById(features);\n", " combinedFeatures = this.combineFeaturesGFF(tmp);\n", " } else {\n", " combinedFeatures = this.combineFeaturesGTF(features);\n", " }\n", "\n", " combinedFeatures.sort(function (a, b) {\n", " return a.start - b.start;\n", " });\n", " return combinedFeatures;\n", " }\n", "\n", " combineFeaturesById(features) {\n", " const combinedFeatures = [];\n", " const chrIdHash = {};\n", "\n", " for (let f of features) {\n", " if (f.id === undefined) {\n", " combinedFeatures.push(f);\n", " } else {\n", " let idHash = chrIdHash[f.chr];\n", "\n", " if (!idHash) {\n", " idHash = {};\n", " chrIdHash[f.chr] = idHash;\n", " }\n", "\n", " if (idHash.hasOwnProperty(f.id)) {\n", " const sf = idHash[f.id];\n", "\n", " if (sf.hasOwnProperty(\"exons\")) {\n", " sf.start = Math.min(sf.start, f.start);\n", " sf.end = Math.max(sf.end, f.end);\n", " sf.exons.push(f);\n", " } else {\n", " const cf = {\n", " id: f.id,\n", " type: f.type,\n", " chr: f.chr,\n", " strand: f.strand,\n", " start: Math.min(f.start, sf.start),\n", " end: Math.max(f.end, sf.end),\n", " exons: [sf, f]\n", " };\n", "\n", " if (f.parent && f.parent.trim() !== \"\") {\n", " cf.parent = f.parent;\n", " }\n", "\n", " idHash[f.id] = cf;\n", " }\n", " } else {\n", " idHash[f.id] = f;\n", " }\n", " }\n", " }\n", "\n", " for (let key of Object.keys(chrIdHash)) {\n", " const idHash = chrIdHash[key];\n", "\n", " for (let id of Object.keys(idHash)) {\n", " combinedFeatures.push(idHash[id]);\n", " }\n", " }\n", "\n", " return combinedFeatures;\n", " }\n", "\n", " combineFeaturesGTF(features) {\n", " const transcripts = Object.create(null);\n", " const combinedFeatures = [];\n", " const consumedFeatures = new Set();\n", " const filterTypes = this.filterTypes;\n", " features = features.filter(f => filterTypes === undefined || !filterTypes.has(f.type)); // 1. Build dictionary of transcripts\n", "\n", " for (let f of features) {\n", " if (transcriptTypes.has(f.type)) {\n", " const transcriptId = f.id;\n", "\n", " if (undefined !== transcriptId) {\n", " const gffTranscript = new GFFTranscript(f);\n", " transcripts[transcriptId] = gffTranscript;\n", " combinedFeatures.push(gffTranscript);\n", " consumedFeatures.add(f);\n", " }\n", " }\n", " } // Add exons\n", "\n", "\n", " for (let f of features) {\n", " if (exonTypes.has(f.type)) {\n", " const id = f.id; // transcript_id, GTF groups all features with the same ID, does not have a parent/child hierarchy\n", "\n", " if (id) {\n", " let transcript = transcripts[id];\n", "\n", " if (transcript === undefined) {\n", " transcript = new GFFTranscript(f); // GTF does not require an explicit transcript record\n", "\n", " transcripts[id] = transcript;\n", " combinedFeatures.push(transcript);\n", " }\n", "\n", " transcript.addExon(f);\n", " consumedFeatures.add(f);\n", " }\n", " }\n", " } // Apply CDS and UTR\n", "\n", "\n", " for (let f of features) {\n", " if (cdsTypes.has(f.type) || utrTypes.has(f.type) || codonTypes.has(f.type)) {\n", " const id = f.id;\n", "\n", " if (id) {\n", " let transcript = transcripts[id];\n", "\n", " if (transcript === undefined) {\n", " transcript = new GFFTranscript(f);\n", " transcripts[id] = transcript;\n", " combinedFeatures.push(transcript);\n", " }\n", "\n", " if (utrTypes.has(f.type)) {\n", " transcript.addUTR(f);\n", " } else if (cdsTypes.has(f.type)) {\n", " transcript.addCDS(f);\n", " } else if (codonTypes.has(f.type)) ;\n", "\n", " consumedFeatures.add(f);\n", " }\n", " }\n", " } // Finish transcripts\n", "\n", "\n", " for (let f of combinedFeatures) {\n", " if (typeof f.finish === \"function\") {\n", " f.finish();\n", " }\n", " } // Add other features\n", "\n", "\n", " const others = features.filter(f => !consumedFeatures.has(f));\n", "\n", " for (let f of others) {\n", " combinedFeatures.push(f);\n", " }\n", "\n", " return combinedFeatures;\n", " }\n", "\n", " combineFeaturesGFF(features) {\n", " // Build dictionary of genes (optional)\n", " const genes = features.filter(f => \"gene\" === f.type);\n", " const geneMap = Object.create(null);\n", "\n", " for (let g of genes) {\n", " geneMap[g.id] = g;\n", " } // 1. Build dictionary of transcripts\n", "\n", "\n", " const transcripts = Object.create(null);\n", " const combinedFeatures = [];\n", " const consumedFeatures = new Set();\n", " const filterTypes = this.filterTypes;\n", " features = features.filter(f => filterTypes === undefined || !filterTypes.has(f.type));\n", "\n", " for (let f of features) {\n", " if (transcriptTypes.has(f.type)) {\n", " const transcriptId = f.id; // getAttribute(f.attributeString, \"transcript_id\", /\\s+/);\n", "\n", " if (undefined !== transcriptId) {\n", " const gffTranscript = new GFFTranscript(f);\n", " transcripts[transcriptId] = gffTranscript;\n", " combinedFeatures.push(gffTranscript);\n", " consumedFeatures.add(f);\n", " const g = geneMap[f.parent];\n", "\n", " if (g) {\n", " gffTranscript.gene = geneMap[f.parent];\n", " consumedFeatures.add(g);\n", " }\n", " }\n", " }\n", " } // Remove assigned genes\n", " // Add exons\n", "\n", "\n", " for (let f of features) {\n", " if (exonTypes.has(f.type)) {\n", " const parents = getParents(f);\n", "\n", " if (parents) {\n", " for (let id of parents) {\n", " let transcript = transcripts[id];\n", "\n", " if (transcript !== undefined) {\n", " transcript.addExon(f);\n", " consumedFeatures.add(f);\n", " }\n", " }\n", " }\n", " }\n", " } // Apply CDS and UTR\n", "\n", "\n", " for (let f of features) {\n", " if (cdsTypes.has(f.type) || utrTypes.has(f.type) || codonTypes.has(f.type)) {\n", " const parents = getParents(f);\n", "\n", " if (parents) {\n", " for (let id of parents) {\n", " let transcript = transcripts[id];\n", "\n", " if (transcript !== undefined) {\n", " if (utrTypes.has(f.type)) {\n", " transcript.addUTR(f);\n", " } else if (cdsTypes.has(f.type)) {\n", " transcript.addCDS(f);\n", " } else if (codonTypes.has(f.type)) ;\n", "\n", " consumedFeatures.add(f);\n", " }\n", " }\n", " }\n", " }\n", " } // Introns are ignored, but are consumed\n", "\n", "\n", " const introns = features.filter(f => intronType === f.type);\n", "\n", " for (let i of introns) {\n", " const parents = getParents(i);\n", "\n", " for (let id of parents) {\n", " if (transcripts[id]) {\n", " consumedFeatures.add(i);\n", " break;\n", " }\n", " }\n", " } // Finish transcripts\n", "\n", "\n", " combinedFeatures.forEach(function (f) {\n", " if (typeof f.finish === \"function\") {\n", " f.finish();\n", " }\n", " }); // Add other features\n", "\n", " const others = features.filter(f => !consumedFeatures.has(f));\n", "\n", " for (let f of others) {\n", " combinedFeatures.push(f);\n", " }\n", "\n", " return combinedFeatures;\n", "\n", " function getParents(f) {\n", " if (f.parent && f.parent.trim() !== \"\") {\n", " return f.parent.trim().split(\",\");\n", " } else {\n", " return null;\n", " }\n", " }\n", " }\n", "\n", " }\n", "\n", " var GFFTranscript = function (feature) {\n", " Object.assign(this, feature);\n", " this.exons = [];\n", " };\n", "\n", " GFFTranscript.prototype.addExon = function (feature) {\n", " this.exons.push(feature); // Expand feature -- for transcripts not explicitly represented in the file\n", "\n", " this.start = Math.min(this.start, feature.start);\n", " this.end = Math.max(this.end, feature.end);\n", " };\n", "\n", " GFFTranscript.prototype.addCDS = function (cds) {\n", " let exon;\n", " const exons = this.exons; // Find exon containing CDS\n", "\n", " for (let i = 0; i < exons.length; i++) {\n", " if (exons[i].start <= cds.start && exons[i].end >= cds.end) {\n", " exon = exons[i];\n", " break;\n", " }\n", " }\n", "\n", " if (exon) {\n", " exon.cdStart = exon.cdStart ? Math.min(cds.start, exon.cdStart) : cds.start;\n", " exon.cdEnd = exon.cdEnd ? Math.max(cds.end, exon.cdEnd) : cds.end;\n", "\n", " if (!exon.children) {\n", " exon.children = [];\n", " }\n", "\n", " exon.children.push(cds);\n", " } else {\n", " cds.cdStart = cds.start;\n", " cds.cdEnd = cds.end;\n", " exons.push(cds);\n", " } // Expand feature -- for transcripts not explicitly represented in the file (gtf files)\n", "\n", "\n", " this.start = Math.min(this.start, cds.start);\n", " this.end = Math.max(this.end, cds.end);\n", " this.cdStart = this.cdStart ? Math.min(cds.start, this.cdStart) : cds.start;\n", " this.cdEnd = this.cdEnd ? Math.max(cds.end, this.cdEnd) : cds.end;\n", " };\n", "\n", " GFFTranscript.prototype.addUTR = function (utr) {\n", " let exon;\n", " const exons = this.exons; // Find exon containing CDS\n", "\n", " for (let i = 0; i < exons.length; i++) {\n", " if (exons[i].start <= utr.start && exons[i].end >= utr.end) {\n", " exon = exons[i];\n", " break;\n", " }\n", " }\n", "\n", " if (exon) {\n", " if (utr.start === exon.start && utr.end === exon.end) {\n", " exon.utr = true;\n", " } else {\n", " if (utr.end < exon.end) {\n", " exon.cdStart = utr.end;\n", " }\n", "\n", " if (utr.start > exon.start) {\n", " exon.cdEnd = utr.start;\n", " }\n", " }\n", "\n", " if (!exon.children) {\n", " exon.children = [];\n", " }\n", "\n", " exon.children.push(utr);\n", " } else {\n", " utr.utr = true;\n", " exons.push(utr);\n", " } // Expand feature -- for transcripts not explicitly represented in the file\n", "\n", "\n", " this.start = Math.min(this.start, utr.start);\n", " this.end = Math.max(this.end, utr.end);\n", " };\n", "\n", " GFFTranscript.prototype.finish = function () {\n", " var cdStart = this.cdStart;\n", " var cdEnd = this.cdEnd;\n", " this.exons.sort(function (a, b) {\n", " return a.start - b.start;\n", " }); // Search for UTR exons that were not explicitly tagged\n", "\n", " if (cdStart) {\n", " this.exons.forEach(function (exon) {\n", " if (exon.end < cdStart || exon.start > cdEnd) exon.utr = true;\n", " });\n", " }\n", " };\n", "\n", " GFFTranscript.prototype.popupData = function (genomicLocation) {\n", " const kvs = this.attributeString.split(';');\n", " const pd = []; // If feature has an associated gene list its attributes first\n", "\n", " if (this.gene && typeof this.gene.popupData === 'function') {\n", " const gd = this.gene.popupData(genomicLocation);\n", "\n", " for (let e of gd) {\n", " pd.push(e);\n", " }\n", "\n", " pd.push(\"
\");\n", " }\n", "\n", " if (this.name) {\n", " pd.push({\n", " name: 'name',\n", " value: this.name\n", " });\n", " }\n", "\n", " pd.push({\n", " name: 'type',\n", " value: this.type\n", " });\n", "\n", " for (let kv of kvs) {\n", " var t = kv.trim().split(this.delim, 2);\n", "\n", " if (t.length === 2 && t[1] !== undefined) {\n", " const key = t[0].trim();\n", " if ('name' === key.toLowerCase()) continue;\n", " let value = t[1].trim(); //Strip off quotes, if any\n", "\n", " if (value.startsWith('\"') && value.endsWith('\"')) {\n", " value = value.substr(1, value.length - 2);\n", " }\n", "\n", " pd.push({\n", " name: key,\n", " value: value\n", " });\n", " }\n", " }\n", "\n", " pd.push({\n", " name: 'position',\n", " value: `${this.chr}:${numberFormatter(this.start + 1)}-${numberFormatter(this.end)}`\n", " }); // If clicked over an exon add its attributes\n", "\n", " for (let exon of this.exons) {\n", " if (genomicLocation >= exon.start && genomicLocation < exon.end && typeof exon.popupData === 'function') {\n", " pd.push(\"
\");\n", " const exonData = exon.popupData(genomicLocation);\n", "\n", " for (let att of exonData) {\n", " pd.push(att);\n", " }\n", "\n", " if (exon.children) {\n", " for (let c of exon.children) {\n", " pd.push(\"
\");\n", " const exonData = c.popupData(genomicLocation);\n", "\n", " for (let att of exonData) {\n", " pd.push(att);\n", " }\n", " }\n", " }\n", " }\n", " }\n", "\n", " return pd;\n", " };\n", "\n", " const GenomicInterval = function (chr, start, end, features) {\n", " this.chr = chr;\n", " this.start = start;\n", " this.end = end;\n", " this.features = features;\n", " };\n", "\n", " GenomicInterval.prototype.contains = function (chr, start, end) {\n", " return this.chr === chr && this.start <= start && this.end >= end;\n", " };\n", "\n", " GenomicInterval.prototype.containsRange = function (range) {\n", " return this.chr === range.chr && this.start <= range.start && this.end >= range.end;\n", " };\n", "\n", " // Assigns a row # to each feature. If the feature does not fit in any row and #rows == maxRows no\n", " // row number is assigned.\n", " function pack(featureList, maxRows) {\n", " maxRows = maxRows || Number.MAX_SAFE_INTEGER;\n", " const rows = [];\n", " featureList.sort(function (a, b) {\n", " return a.start - b.start;\n", " });\n", " rows.push(-1000);\n", "\n", " for (let feature of featureList) {\n", " let r = 0;\n", " const len = Math.min(rows.length, maxRows);\n", "\n", " for (r = 0; r < len; r++) {\n", " if (feature.start > rows[r]) {\n", " feature.row = r;\n", " rows[r] = feature.end;\n", " break;\n", " }\n", " }\n", "\n", " feature.row = r;\n", " rows[r] = feature.end;\n", " }\n", " }\n", "\n", " /*\n", " * The MIT License (MIT)\n", " *\n", " * Copyright (c) 2014-2015 Broad Institute\n", " *\n", " * Permission is hereby granted, free of charge, to any person obtaining a copy\n", " * of this software and associated documentation files (the \"Software\"), to deal\n", " * in the Software without restriction, including without limitation the rights\n", " * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n", " * copies of the Software, and to permit persons to whom the Software is\n", " * furnished to do so, subject to the following conditions:\n", " *\n", " * The above copyright notice and this permission notice shall be included in\n", " * all copies or substantial portions of the Software.\n", " *\n", " *\n", " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n", " * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n", " * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n", " * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n", " * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n", " * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n", " * THE SOFTWARE.\n", " */\n", " /**\n", " * feature source for \"bed like\" files (tab or whitespace delimited files with 1 feature per line: bed, gff, vcf, etc)\n", " *\n", " * @param config\n", " * @constructor\n", " */\n", "\n", " class TextFeatureSource {\n", " constructor(config, genome) {\n", " this.config = config || {};\n", " this.genome = genome;\n", " this.sourceType = config.sourceType === undefined ? \"file\" : config.sourceType;\n", " this.visibilityWindow = config.visibilityWindow;\n", " const queryableFormats = new Set([\"bigwig\", \"bw\", \"bigbed\", \"bb\", \"tdf\"]);\n", "\n", " if (config.features && Array.isArray(config.features)) {\n", " let features = fixFeatures(config.features);\n", " packFeatures(features);\n", "\n", " if (config.mappings) {\n", " mapProperties(features, config.mappings);\n", " }\n", "\n", " this.queryable = false;\n", " this.featureCache = new FeatureCache(features, genome);\n", " } else if (config.reader) {\n", " this.reader = config.reader;\n", " this.queryable = config.queryable !== undefined ? config.queryable : true;\n", " this.expandQuery = config.expandQuery ? true : false;\n", " } else if (config.sourceType === \"ga4gh\") {\n", " this.reader = new Ga4ghVariantReader(config, genome);\n", " this.queryable = true;\n", " } else if (config.sourceType === \"immvar\") {\n", " this.reader = new ImmVarReader(config);\n", " this.queryable = true;\n", " } else if (config.type === \"eqtl\" && config.sourceType === \"gtex-ws\") {\n", " this.reader = new GtexReader(config);\n", " this.queryable = true;\n", " this.expandQuery = config.expandQuery ? true : false;\n", " } else if (config.sourceType === 'ucscservice') {\n", " this.reader = new UCSCServiceReader(config.source);\n", " this.queryable = true;\n", " } else if (config.sourceType === 'custom' || config.source !== undefined) {\n", " // Second test for backward compatibility\n", " this.reader = new CustomServiceReader(config.source);\n", " this.queryable = config.source.queryable !== undefined ? config.source.queryable : true;\n", " this.expandQuery = config.expandQuery ? true : false;\n", " } else if (\"civic-ws\" === config.sourceType) {\n", " this.reader = new CivicReader(config);\n", " this.queryable = false;\n", " this.expandQuery = config.expandQuery ? true : false;\n", " } else {\n", " this.reader = new FeatureFileReader(config, genome);\n", "\n", " if (config.queryable !== undefined) {\n", " this.queryable = config.queryable;\n", " } else if (queryableFormats.has(config.format)) {\n", " this.queryable = queryableFormats.has(config.format) || this.reader.indexed;\n", " } else ;\n", " }\n", " }\n", "\n", " supportsWholeGenome() {\n", " return !this.queryable && (this.visibilityWindow === undefined || this.visibilityWindow <= 0);\n", " }\n", "\n", " async trackType() {\n", " const header = await this.getHeader();\n", "\n", " if (header) {\n", " return header.type;\n", " } else {\n", " return undefined; // Convention for unknown or unspecified\n", " }\n", " }\n", "\n", " async getHeader() {\n", " if (!this.header) {\n", " if (this.reader && typeof this.reader.readHeader === \"function\") {\n", " const header = await this.reader.readHeader();\n", "\n", " if (header) {\n", " this.header = header;\n", "\n", " if (header.format) {\n", " this.config.format = header.format;\n", " }\n", " } else {\n", " this.header = {};\n", " }\n", " } else {\n", " this.header = {};\n", " }\n", " }\n", "\n", " return this.header;\n", " }\n", " /**\n", " * Required function for all data source objects. Fetches features for the\n", " * range requested.\n", " *\n", " * This function is quite complex due to the variety of reader types backing it, some indexed, some queryable,\n", " * some not. The whole scheme could use a refactoring.\n", " *\n", " * @param chr\n", " * @param start\n", " * @param end\n", " * @param bpPerPixel\n", " */\n", "\n", "\n", " async getFeatures(_ref) {\n", " let {\n", " chr,\n", " start,\n", " end,\n", " bpPerPixel,\n", " visibilityWindow\n", " } = _ref;\n", " const genome = this.genome;\n", " const queryChr = genome ? genome.getChromosomeName(chr) : chr;\n", " const isWholeGenome = \"all\" === queryChr.toLowerCase(); // Various conditions that can create a feature load\n", " // * view is \"whole genome\" but no features are loaded\n", " // * cache is disabled\n", " // * cache does not contain requested range\n", "\n", " if (isWholeGenome && !this.getWGFeatures || this.config.disableCache || !this.featureCache || !this.featureCache.containsRange(new GenomicInterval(queryChr, start, end))) {\n", " await this.loadFeatures(start, end, visibilityWindow, queryChr);\n", " }\n", "\n", " if (isWholeGenome) {\n", " if (!this.wgFeatures) {\n", " if (this.queryable) {\n", " // queryable sources don't support whole genome view\n", " this.wgFeatures = [];\n", " } else {\n", " this.wgFeatures = this.getWGFeatures(this.featureCache.getAllFeatures());\n", " }\n", " }\n", "\n", " return this.wgFeatures;\n", " } else {\n", " return this.featureCache.queryFeatures(queryChr, start, end);\n", " }\n", " }\n", "\n", " async loadFeatures(start, end, visibilityWindow, queryChr) {\n", " const reader = this.reader;\n", " let intervalStart = start;\n", " let intervalEnd = end; // Use visibility window to potentially expand query interval.\n", " // This can save re-queries as we zoom out. Visibility window <= 0 is a special case\n", " // indicating whole chromosome should be read at once.\n", "\n", " if ((!visibilityWindow || visibilityWindow <= 0) && this.expandQuery !== false) {\n", " // Whole chromosome\n", " const chromosome = this.genome ? this.genome.getChromosome(queryChr) : undefined;\n", " intervalStart = 0;\n", " intervalEnd = chromosome ? chromosome.bpLength : Number.MAX_SAFE_INTEGER;\n", " } else if (visibilityWindow > end - start && this.expandQuery !== false) {\n", " const expansionWindow = Math.min(4.1 * (end - start), visibilityWindow);\n", " intervalStart = Math.max(0, (start + end - expansionWindow) / 2);\n", " intervalEnd = start + expansionWindow;\n", " }\n", "\n", " let features = await reader.readFeatures(queryChr, intervalStart, intervalEnd);\n", "\n", " if (this.queryable === undefined) {\n", " this.queryable = reader.indexed;\n", " }\n", "\n", " const genomicInterval = this.queryable ? new GenomicInterval(queryChr, intervalStart, intervalEnd) : undefined;\n", "\n", " if (features) {\n", " if (\"gtf\" === this.config.format || \"gff3\" === this.config.format || \"gff\" === this.config.format) {\n", " features = new GFFHelper(this.config).combineFeatures(features);\n", " } // Assign overlapping features to rows\n", "\n", "\n", " if (this.config.format !== \"wig\" && this.config.type !== \"junctions\") {\n", " const maxRows = this.config.maxRows || Number.MAX_SAFE_INTEGER;\n", " packFeatures(features, maxRows);\n", " } // Note - replacing previous cache with new one. genomicInterval is optional (might be undefined => includes all features)\n", "\n", "\n", " this.featureCache = new FeatureCache(features, this.genome, genomicInterval); // If track is marked \"searchable\"< cache features by name -- use this with caution, memory intensive\n", "\n", " if (this.config.searchable) {\n", " this.addFeaturesToDB(features);\n", " }\n", " } else {\n", " this.featureCache = new FeatureCache([], genomicInterval); // Empty cache\n", " }\n", " }\n", "\n", " addFeaturesToDB(featureList) {\n", " for (let feature of featureList) {\n", " if (feature.name) {\n", " this.genome.featureDB[feature.name.toUpperCase()] = feature;\n", " }\n", "\n", " if (feature.gene && feature.gene.name) {\n", " this.genome.featureDB[feature.gene.name.toUpperCase()] = feature;\n", " }\n", " }\n", " } // TODO -- filter by pixel size\n", "\n", "\n", " getWGFeatures(allFeatures) {\n", " const genome = this.genome;\n", " const wgChromosomeNames = new Set(genome.wgChromosomeNames);\n", " const wgFeatures = [];\n", "\n", " for (let c of genome.wgChromosomeNames) {\n", " const features = allFeatures[c];\n", "\n", " if (features) {\n", " for (let f of features) {\n", " let queryChr = genome.getChromosomeName(f.chr);\n", "\n", " if (wgChromosomeNames.has(queryChr)) {\n", " const wg = Object.assign({}, f);\n", " wg.chr = \"all\";\n", " wg.start = genome.getGenomeCoordinate(f.chr, f.start);\n", " wg.end = genome.getGenomeCoordinate(f.chr, f.end);\n", " wg._f = f; // Don't draw exons in whole genome view\n", "\n", " if (wg[\"exons\"]) delete wg[\"exons\"];\n", "\n", " wg.popupData = function (genomeLocation) {\n", " if (typeof this._f.popupData === 'function') {\n", " return this._f.popupData();\n", " } else {\n", " return TrackBase.extractPopupData(this._f, genome.id);\n", " }\n", " };\n", "\n", " wgFeatures.push(wg);\n", " }\n", " }\n", " }\n", " }\n", "\n", " wgFeatures.sort(function (a, b) {\n", " return a.start - b.start;\n", " });\n", " return wgFeatures;\n", " }\n", "\n", " }\n", "\n", " function packFeatures(features, maxRows) {\n", " maxRows = maxRows || 1000;\n", "\n", " if (features == null || features.length === 0) {\n", " return;\n", " } // Segregate by chromosome\n", "\n", "\n", " const chrFeatureMap = {};\n", " const chrs = [];\n", "\n", " for (let feature of features) {\n", " const chr = feature.chr;\n", " let flist = chrFeatureMap[chr];\n", "\n", " if (!flist) {\n", " flist = [];\n", " chrFeatureMap[chr] = flist;\n", " chrs.push(chr);\n", " }\n", "\n", " flist.push(feature);\n", " } // Loop through chrosomosomes and pack features;\n", "\n", "\n", " for (let chr of chrs) {\n", " pack(chrFeatureMap[chr], maxRows);\n", " }\n", " }\n", " /**\n", " * This function is used to apply properties normally added during parsing to features supplied directly in the\n", " * config as an array of objects. At the moment the only application is bedpe type features.\n", " * @param features\n", " */\n", "\n", "\n", " function fixFeatures(features) {\n", " if (!features || features.length === 0) return;\n", " const isBedPE = features[0].chr === undefined && features[0].chr1 !== undefined;\n", "\n", " if (isBedPE) {\n", " const interChrFeatures = [];\n", "\n", " for (let feature of features) {\n", " // Set total extent of feature\n", " if (feature.chr1 === feature.chr2) {\n", " feature.chr = feature.chr1;\n", " feature.start = Math.min(feature.start1, feature.start2);\n", " feature.end = Math.max(feature.end1, feature.end2);\n", " } else {\n", " interChrFeatures.push(feature);\n", " }\n", " } // Make copies of inter-chr features, one for each chromosome\n", "\n", "\n", " for (let f1 of interChrFeatures) {\n", " const f2 = Object.assign({\n", " dup: true\n", " }, f1);\n", " features.push(f2);\n", " f1.chr = f1.chr1;\n", " f1.start = f1.start1;\n", " f1.end = f1.end1;\n", " f2.chr = f2.chr2;\n", " f2.start = f2.start2;\n", " f2.end = f2.end2;\n", " }\n", " }\n", "\n", " return features;\n", " }\n", "\n", " function mapProperties(features, mappings) {\n", " let mappingKeys = Object.keys(mappings);\n", " features.forEach(function (f) {\n", " mappingKeys.forEach(function (key) {\n", " f[key] = f[mappings[key]];\n", " });\n", " });\n", " }\n", "\n", " class BufferedReader {\n", " constructor(config, contentLength, bufferSize) {\n", " this.path = config.url;\n", " this.bufferSize = bufferSize ? bufferSize : 512000;\n", " this.range = {\n", " start: -1,\n", " size: -1\n", " };\n", " this.config = config;\n", " }\n", " /**\n", " *\n", " * @param requestedRange - byte rangeas {start, size}\n", " * @param fulfill - function to receive result\n", " * @param asUint8 - optional flag to return result as an UInt8Array\n", " */\n", "\n", "\n", " async dataViewForRange(requestedRange, asUint8) {\n", " const hasData = this.data && this.range.start <= requestedRange.start && this.range.start + this.range.size >= requestedRange.start + requestedRange.size;\n", "\n", " if (!hasData) {\n", " let bufferSize; // If requested range size is specified, potentially expand buffer size\n", "\n", " if (requestedRange.size) {\n", " bufferSize = Math.max(this.bufferSize, requestedRange.size);\n", " } else {\n", " bufferSize = this.bufferSize;\n", " }\n", "\n", " const loadRange = {\n", " start: requestedRange.start,\n", " size: bufferSize\n", " };\n", " const arrayBuffer = await igvxhr.loadArrayBuffer(this.path, buildOptions$1(this.config, {\n", " range: loadRange\n", " }));\n", " this.data = arrayBuffer;\n", " this.range = loadRange;\n", " }\n", "\n", " const len = this.data.byteLength;\n", " const bufferStart = requestedRange.start - this.range.start;\n", " return asUint8 ? new Uint8Array(this.data, bufferStart, len - bufferStart) : new DataView(this.data, bufferStart, len - bufferStart);\n", " }\n", "\n", " }\n", "\n", " //table chromatinInteract\n", "\n", " function getDecoder(definedFieldCount, fieldCount, autoSql) {\n", " if (autoSql && 'chromatinInteract' === autoSql.table) {\n", " return decodeInteract;\n", " } else {\n", " const standardFieldCount = definedFieldCount - 3;\n", " return function (feature, tokens) {\n", " if (standardFieldCount > 0) {\n", " feature.name = tokens[0];\n", " }\n", "\n", " if (standardFieldCount > 1) {\n", " feature.score = parseFloat(tokens[1]);\n", " }\n", "\n", " if (standardFieldCount > 2) {\n", " feature.strand = tokens[2];\n", " }\n", "\n", " if (standardFieldCount > 3) {\n", " feature.cdStart = parseInt(tokens[3]);\n", " }\n", "\n", " if (standardFieldCount > 4) {\n", " feature.cdEnd = parseInt(tokens[4]);\n", " }\n", "\n", " if (standardFieldCount > 5) {\n", " if (tokens[5] !== \".\" && tokens[5] !== \"0\" && tokens[5] !== \"-1\") {\n", " const c = IGVColor.createColorString(tokens[5]);\n", " feature.color = c.startsWith(\"rgb\") ? c : undefined;\n", " }\n", " }\n", "\n", " if (standardFieldCount > 8) {\n", " const exonCount = parseInt(tokens[6]);\n", " const exonSizes = tokens[7].split(',');\n", " const exonStarts = tokens[8].split(',');\n", " const exons = [];\n", "\n", " for (let i = 0; i < exonCount; i++) {\n", " const eStart = feature.start + parseInt(exonStarts[i]);\n", " const eEnd = eStart + parseInt(exonSizes[i]);\n", " exons.push({\n", " start: eStart,\n", " end: eEnd\n", " });\n", " }\n", "\n", " feature.exons = exons;\n", " }\n", "\n", " if (autoSql) {\n", " // TODO -- these should be equal, validate? fieldCount-definedFieldCount, as.fields.length, tokens.length-3\n", " const extraStart = definedFieldCount;\n", "\n", " for (let i = extraStart; i < fieldCount; i++) {\n", " if (i < autoSql.fields.length) {\n", " const name = autoSql.fields[i].name;\n", " const value = tokens[i - 3];\n", " feature[name] = value;\n", " }\n", " }\n", " }\n", " };\n", " }\n", "\n", " function decodeInteract(feature, tokens) {\n", " feature.chr1 = tokens[5];\n", " feature.start1 = Number.parseInt(tokens[6]);\n", " feature.end1 = Number.parseInt(tokens[7]);\n", " feature.chr2 = tokens[10];\n", " feature.start2 = Number.parseInt(tokens[11]);\n", " feature.end2 = Number.parseInt(tokens[12]);\n", " feature.name = tokens[0];\n", " feature.score = Number.parseFloat(tokens[1]);\n", " feature.value = Number.parseFloat(tokens[2]);\n", " feature.color = tokens[4] === '.' ? undefined : tokens[4] === \"0\" ? \"rgb(0,0,0)\" : tokens[4];\n", " return feature;\n", " }\n", " }\n", "\n", " function parseAutoSQL(str) {\n", " let table;\n", " const fields = [];\n", " let startDecoding = false;\n", " const lines = str.trim().split(/\\s*[\\r\\n]+\\s*/g);\n", "\n", " for (let line of lines) {\n", " if (line.startsWith('table')) {\n", " table = line.split(/\\s+/)[1].trim();\n", " } else if (line.startsWith('(')) {\n", " startDecoding = true;\n", " } else if (line.startsWith(')')) ; else if (startDecoding) {\n", " if (line.length > 0) {\n", " const idx = line.indexOf(';');\n", " const tokens = line.substr(0, idx).split(/\\s+/);\n", " const description = line.substr(idx + 1).replace(/\"/g, '').trim();\n", " fields.push({\n", " type: tokens[0],\n", " name: tokens[1],\n", " description: description\n", " });\n", " }\n", " }\n", " }\n", "\n", " return {\n", " table: table,\n", " fields: fields\n", " };\n", " }\n", "\n", " let BIGWIG_MAGIC_LTH = 0x888FFC26; // BigWig Magic Low to High\n", "\n", " let BIGWIG_MAGIC_HTL = 0x26FC8F66; // BigWig Magic High to Low\n", "\n", " let BIGBED_MAGIC_LTH = 0x8789F2EB; // BigBed Magic Low to High\n", "\n", " let BIGBED_MAGIC_HTL = 0xEBF28987; // BigBed Magic High to Low\n", "\n", " let BBFILE_HEADER_SIZE = 64;\n", " let RPTREE_HEADER_SIZE = 48;\n", " let RPTREE_NODE_LEAF_ITEM_SIZE = 32; // leaf item size\n", "\n", " let RPTREE_NODE_CHILD_ITEM_SIZE = 24; // child item size\n", "\n", " let BUFFER_SIZE = 512000; // buffer\n", "\n", " class BWReader {\n", " constructor(config, genome) {\n", " this.path = config.url;\n", " this.genome = genome;\n", " this.rpTreeCache = {};\n", " this.config = config;\n", " }\n", "\n", " async readWGFeatures(bpPerPixel, windowFunction) {\n", " await this.loadHeader();\n", " const chrIdx1 = 0;\n", " const chrIdx2 = this.chromTree.idToChrom.length - 1;\n", " const chr1 = this.chromTree.idToChrom[chrIdx1];\n", " const chr2 = this.chromTree.idToChrom[chrIdx2];\n", " return this.readFeatures(chr1, 0, chr2, Number.MAX_VALUE, bpPerPixel, windowFunction);\n", " }\n", "\n", " async readFeatures(chr1, bpStart, chr2, bpEnd, bpPerPixel, windowFunction) {\n", " await this.loadHeader();\n", " const chrIdx1 = this.chromTree.chromToID[chr1];\n", " const chrIdx2 = this.chromTree.chromToID[chr2];\n", "\n", " if (chrIdx1 === undefined || chrIdx2 === undefined) {\n", " return [];\n", " }\n", "\n", " let treeOffset;\n", " let decodeFunction;\n", "\n", " if (this.type === \"bigwig\") {\n", " // Select a biwig \"zoom level\" appropriate for the current resolution.\n", " const zoomLevelHeaders = await this.getZoomHeaders();\n", " let zoomLevelHeader = bpPerPixel ? zoomLevelForScale$1(bpPerPixel, zoomLevelHeaders) : undefined;\n", "\n", " if (zoomLevelHeader) {\n", " treeOffset = zoomLevelHeader.indexOffset;\n", " decodeFunction = decodeZoomData;\n", " } else {\n", " treeOffset = this.header.fullIndexOffset;\n", " decodeFunction = decodeWigData;\n", " }\n", " } else {\n", " // bigbed, zoom data is not currently used in igv for bed type features\n", " treeOffset = this.header.fullIndexOffset;\n", " decodeFunction = getBedDataDecoder.call(this);\n", " } // Load the R Tree and fine leaf items\n", "\n", "\n", " const rpTree = await this.loadRPTree(treeOffset);\n", " const leafItems = await rpTree.findLeafItemsOverlapping(chrIdx1, bpStart, chrIdx2, bpEnd);\n", "\n", " if (!leafItems || leafItems.length === 0) {\n", " return [];\n", " } else {\n", " // Consolidate leaf items and get all data at once\n", " let start = Number.MAX_VALUE;\n", " let end = 0;\n", "\n", " for (let item of leafItems) {\n", " start = Math.min(start, item.dataOffset);\n", " end = Math.max(end, item.dataOffset + item.dataSize);\n", " }\n", "\n", " const size = end - start;\n", " const arrayBuffer = await igvxhr.loadArrayBuffer(this.config.url, buildOptions$1(this.config, {\n", " range: {\n", " start: start,\n", " size: size\n", " }\n", " })); // Parse data and return features\n", "\n", " const allFeatures = [];\n", " const buffer = new Uint8Array(arrayBuffer);\n", "\n", " for (let item of leafItems) {\n", " const uint8Array = buffer.subarray(item.dataOffset - start, item.dataOffset + item.dataSize);\n", " let plain;\n", " const isCompressed = this.header.uncompressBuffSize > 0;\n", "\n", " if (isCompressed) {\n", " const inflate = new Zlib$2.Inflate(uint8Array);\n", " plain = inflate.decompress();\n", " } else {\n", " plain = uint8Array;\n", " }\n", "\n", " decodeFunction.call(this, new DataView(plain.buffer), chrIdx1, bpStart, chrIdx2, bpEnd, allFeatures, this.chromTree.idToChrom, windowFunction);\n", " }\n", "\n", " allFeatures.sort(function (a, b) {\n", " return a.start - b.start;\n", " });\n", " return allFeatures;\n", " }\n", " }\n", "\n", " async getZoomHeaders() {\n", " if (this.zoomLevelHeaders) {\n", " return this.zoomLevelHeaders;\n", " } else {\n", " await this.loadHeader();\n", " return this.zoomLevelHeaders;\n", " }\n", " }\n", "\n", " async loadHeader() {\n", " if (this.header) {\n", " return this.header;\n", " } else {\n", " let data = await igvxhr.loadArrayBuffer(this.path, buildOptions$1(this.config, {\n", " range: {\n", " start: 0,\n", " size: BBFILE_HEADER_SIZE\n", " }\n", " }));\n", " let header; // Assume low-to-high unless proven otherwise\n", "\n", " this.littleEndian = true;\n", " let binaryParser = new BinaryParser$1(new DataView(data));\n", " let magic = binaryParser.getUInt();\n", "\n", " if (magic === BIGWIG_MAGIC_LTH) {\n", " this.type = \"bigwig\";\n", " } else if (magic === BIGBED_MAGIC_LTH) {\n", " this.type = \"bigbed\";\n", " } else {\n", " //Try big endian order\n", " this.littleEndian = false;\n", " binaryParser.littleEndian = false;\n", " binaryParser.position = 0;\n", " let magic = binaryParser.getUInt();\n", "\n", " if (magic === BIGWIG_MAGIC_HTL) {\n", " this.type = \"bigwig\";\n", " } else if (magic === BIGBED_MAGIC_HTL) {\n", " this.type = \"bigbed\";\n", " } else ;\n", " } // Table 5 \"Common header for bigwig and bigbed files\"\n", "\n", "\n", " header = {\n", " bwVersion: binaryParser.getUShort(),\n", " nZoomLevels: binaryParser.getUShort(),\n", " chromTreeOffset: binaryParser.getLong(),\n", " fullDataOffset: binaryParser.getLong(),\n", " fullIndexOffset: binaryParser.getLong(),\n", " fieldCount: binaryParser.getUShort(),\n", " definedFieldCount: binaryParser.getUShort(),\n", " autoSqlOffset: binaryParser.getLong(),\n", " totalSummaryOffset: binaryParser.getLong(),\n", " uncompressBuffSize: binaryParser.getInt(),\n", " extensionOffset: binaryParser.getLong()\n", " }; ///////////\n", "\n", " const startOffset = BBFILE_HEADER_SIZE;\n", " let range = {\n", " start: startOffset,\n", " size: header.fullDataOffset - startOffset + 5\n", " };\n", " data = await igvxhr.loadArrayBuffer(this.path, buildOptions$1(this.config, {\n", " range: range\n", " }));\n", " const nZooms = header.nZoomLevels;\n", " binaryParser = new BinaryParser$1(new DataView(data));\n", " this.zoomLevelHeaders = [];\n", " this.firstZoomDataOffset = Number.MAX_SAFE_INTEGER;\n", "\n", " for (let i = 1; i <= nZooms; i++) {\n", " const zoomNumber = nZooms - i;\n", " const zlh = new ZoomLevelHeader(zoomNumber, binaryParser);\n", " this.firstZoomDataOffset = Math.min(zlh.dataOffset, this.firstZoomDataOffset);\n", " this.zoomLevelHeaders[zoomNumber] = zlh;\n", " } // Autosql\n", "\n", "\n", " if (header.autoSqlOffset > 0) {\n", " binaryParser.position = header.autoSqlOffset - startOffset;\n", " const autoSqlString = binaryParser.getString();\n", "\n", " if (autoSqlString) {\n", " this.autoSql = parseAutoSQL(autoSqlString);\n", " }\n", " } // Total summary\n", "\n", "\n", " if (header.totalSummaryOffset > 0) {\n", " binaryParser.position = header.totalSummaryOffset - startOffset;\n", " this.totalSummary = new BWTotalSummary(binaryParser);\n", " } // Chrom data index\n", "\n", "\n", " if (header.chromTreeOffset > 0) {\n", " binaryParser.position = header.chromTreeOffset - startOffset;\n", " this.chromTree = new BPTree(binaryParser, startOffset, this.genome);\n", " } else {\n", " // TODO -- this is an error, not expected\n", " throw \"BigWig chromosome tree offset <= 0\";\n", " } //Finally total data count\n", "\n", "\n", " binaryParser.position = header.fullDataOffset - startOffset;\n", " header.dataCount = binaryParser.getInt(); ///////////\n", "\n", " this.setDefaultVisibilityWindow(header);\n", " this.header = header;\n", " return this.header;\n", " }\n", " }\n", "\n", " async loadRPTree(offset) {\n", " let rpTree = this.rpTreeCache[offset];\n", "\n", " if (rpTree) {\n", " return rpTree;\n", " } else {\n", " rpTree = new RPTree(offset, this.config, this.littleEndian);\n", " await rpTree.load();\n", " this.rpTreeCache[offset] = rpTree;\n", " return rpTree;\n", " }\n", " }\n", "\n", " async getType() {\n", " await this.loadHeader();\n", " return this.type;\n", " }\n", "\n", " async getTrackType() {\n", " await this.loadHeader();\n", "\n", " if (this.type === \"bigwig\") {\n", " return \"wig\";\n", " } else {\n", " return this.autoSql && this.autoSql.table === \"chromatinInteract\" ? \"interact\" : \"annotation\";\n", " }\n", " }\n", "\n", " setDefaultVisibilityWindow(header) {\n", " if (this.type === \"bigwig\") {\n", " this.visibilityWindow = -1;\n", " } else {\n", " // bigbed\n", " let genomeSize = this.genome ? this.genome.getGenomeLength() : 3088286401; // Estimate window size to return ~ 1,000 features, assuming even distribution across the genome\n", "\n", " this.visibilityWindow = header.dataCount < 1000 ? -1 : 1000 * (genomeSize / header.dataCount);\n", " }\n", " }\n", "\n", " }\n", "\n", " class ZoomLevelHeader {\n", " constructor(index, byteBuffer) {\n", " this.index = index;\n", " this.reductionLevel = byteBuffer.getInt();\n", " this.reserved = byteBuffer.getInt();\n", " this.dataOffset = byteBuffer.getLong();\n", " this.indexOffset = byteBuffer.getLong();\n", " }\n", "\n", " }\n", "\n", " class RPTree {\n", " constructor(fileOffset, config, littleEndian) {\n", " this.config = config;\n", " this.fileOffset = fileOffset; // File offset to beginning of tree\n", "\n", " this.path = config.url;\n", " this.littleEndian = littleEndian;\n", " }\n", "\n", " async load() {\n", " const rootNodeOffset = this.fileOffset + RPTREE_HEADER_SIZE;\n", " const bufferedReader = new BufferedReader(this.config, BUFFER_SIZE);\n", " this.rootNode = await this.readNode(rootNodeOffset, bufferedReader);\n", " return this;\n", " }\n", "\n", " async readNode(filePosition, bufferedReader) {\n", " let dataView = await bufferedReader.dataViewForRange({\n", " start: filePosition,\n", " size: 4\n", " }, false);\n", " let binaryParser = new BinaryParser$1(dataView, this.littleEndian);\n", " const type = binaryParser.getByte();\n", " const isLeaf = type === 1;\n", " binaryParser.getByte();\n", " const count = binaryParser.getUShort();\n", " filePosition += 4;\n", " let bytesRequired = count * (isLeaf ? RPTREE_NODE_LEAF_ITEM_SIZE : RPTREE_NODE_CHILD_ITEM_SIZE);\n", " let range2 = {\n", " start: filePosition,\n", " size: bytesRequired\n", " };\n", " dataView = await bufferedReader.dataViewForRange(range2, false);\n", " const items = new Array(count);\n", " binaryParser = new BinaryParser$1(dataView);\n", "\n", " if (isLeaf) {\n", " for (let i = 0; i < count; i++) {\n", " let item = {\n", " isLeaf: true,\n", " startChrom: binaryParser.getInt(),\n", " startBase: binaryParser.getInt(),\n", " endChrom: binaryParser.getInt(),\n", " endBase: binaryParser.getInt(),\n", " dataOffset: binaryParser.getLong(),\n", " dataSize: binaryParser.getLong()\n", " };\n", " items[i] = item;\n", " }\n", "\n", " return new RPTreeNode(items);\n", " } else {\n", " // non-leaf\n", " for (let i = 0; i < count; i++) {\n", " let item = {\n", " isLeaf: false,\n", " startChrom: binaryParser.getInt(),\n", " startBase: binaryParser.getInt(),\n", " endChrom: binaryParser.getInt(),\n", " endBase: binaryParser.getInt(),\n", " childOffset: binaryParser.getLong()\n", " };\n", " items[i] = item;\n", " }\n", "\n", " return new RPTreeNode(items);\n", " }\n", " }\n", "\n", " async findLeafItemsOverlapping(chrIdx1, startBase, chrIdx2, endBase) {\n", " let self = this;\n", " return new Promise(function (fulfill, reject) {\n", " let leafItems = [],\n", " processing = new Set(),\n", " bufferedReader = new BufferedReader(self.config, BUFFER_SIZE);\n", " processing.add(0); // Zero represents the root node\n", "\n", " findLeafItems(self.rootNode, 0);\n", "\n", " function findLeafItems(node, nodeId) {\n", " if (overlaps(node, chrIdx1, startBase, chrIdx2, endBase)) {\n", " let items = node.items;\n", " items.forEach(function (item) {\n", " if (overlaps(item, chrIdx1, startBase, chrIdx2, endBase)) {\n", " if (item.isLeaf) {\n", " leafItems.push(item);\n", " } else {\n", " if (item.childNode) {\n", " findLeafItems(item.childNode);\n", " } else {\n", " processing.add(item.childOffset); // Represent node to-be-loaded by its file position\n", "\n", " self.readNode(item.childOffset, bufferedReader).then(function (node) {\n", " item.childNode = node;\n", " findLeafItems(node, item.childOffset);\n", " }).catch(reject);\n", " }\n", " }\n", " }\n", " });\n", " }\n", "\n", " if (nodeId !== undefined) processing.delete(nodeId); // Wait until all nodes are processed\n", "\n", " if (processing.size === 0) {\n", " fulfill(leafItems);\n", " }\n", " }\n", " });\n", " }\n", "\n", " }\n", "\n", " class RPTreeNode {\n", " constructor(items) {\n", " this.items = items;\n", " let minChromId = Number.MAX_SAFE_INTEGER,\n", " maxChromId = 0,\n", " minStartBase = Number.MAX_SAFE_INTEGER,\n", " maxEndBase = 0,\n", " i,\n", " item;\n", "\n", " for (i = 0; i < items.length; i++) {\n", " item = items[i];\n", " minChromId = Math.min(minChromId, item.startChrom);\n", " maxChromId = Math.max(maxChromId, item.endChrom);\n", " minStartBase = Math.min(minStartBase, item.startBase);\n", " maxEndBase = Math.max(maxEndBase, item.endBase);\n", " }\n", "\n", " this.startChrom = minChromId;\n", " this.endChrom = maxChromId;\n", " this.startBase = minStartBase;\n", " this.endBase = maxEndBase;\n", " }\n", "\n", " }\n", "\n", " class BPTree {\n", " constructor(binaryParser, startOffset, genome) {\n", " let magic = binaryParser.getInt();\n", " let blockSize = binaryParser.getInt();\n", " let keySize = binaryParser.getInt();\n", " let valSize = binaryParser.getInt();\n", " let itemCount = binaryParser.getLong();\n", " let reserved = binaryParser.getLong();\n", " let chromToId = {};\n", " let idToChrom = [];\n", " this.header = {\n", " magic: magic,\n", " blockSize: blockSize,\n", " keySize: keySize,\n", " valSize: valSize,\n", " itemCount: itemCount,\n", " reserved: reserved\n", " };\n", " this.chromToID = chromToId;\n", " this.idToChrom = idToChrom; // Recursively walk tree to populate dictionary\n", "\n", " readTreeNode(binaryParser, -1);\n", "\n", " function readTreeNode(byteBuffer, offset) {\n", " if (offset >= 0) byteBuffer.position = offset;\n", " let type = byteBuffer.getByte();\n", " byteBuffer.getByte();\n", " let count = byteBuffer.getUShort(),\n", " i,\n", " key,\n", " chromId,\n", " childOffset,\n", " bufferOffset,\n", " currOffset;\n", "\n", " if (type === 1) {\n", " for (i = 0; i < count; i++) {\n", " key = byteBuffer.getFixedLengthTrimmedString(keySize);\n", " chromId = byteBuffer.getInt();\n", " byteBuffer.getInt();\n", " if (genome) key = genome.getChromosomeName(key); // Translate to canonical chr name\n", "\n", " chromToId[key] = chromId;\n", " idToChrom[chromId] = key;\n", " }\n", " } else {\n", " // non-leaf\n", " for (i = 0; i < count; i++) {\n", " key = byteBuffer.getFixedLengthTrimmedString(keySize);\n", " childOffset = byteBuffer.getLong();\n", " bufferOffset = childOffset - startOffset;\n", " currOffset = byteBuffer.position;\n", " readTreeNode(byteBuffer, bufferOffset);\n", " byteBuffer.position = currOffset;\n", " }\n", " }\n", " }\n", " }\n", "\n", " }\n", " /**\n", " * Return true if {chrIdx1:startBase-chrIdx2:endBase} overlaps item's interval\n", " * @returns {boolean}\n", " */\n", "\n", "\n", " function overlaps(item, chrIdx1, startBase, chrIdx2, endBase) {\n", " if (!item) {\n", " console.log(\"null item for \" + chrIdx1 + \" \" + startBase + \" \" + endBase);\n", " return false;\n", " }\n", "\n", " return (chrIdx2 > item.startChrom || chrIdx2 === item.startChrom && endBase >= item.startBase) && (chrIdx1 < item.endChrom || chrIdx1 === item.endChrom && startBase <= item.endBase);\n", " }\n", "\n", " class BWTotalSummary {\n", " constructor(byteBuffer) {\n", " if (byteBuffer) {\n", " this.basesCovered = byteBuffer.getLong();\n", " this.minVal = byteBuffer.getDouble();\n", " this.maxVal = byteBuffer.getDouble();\n", " this.sumData = byteBuffer.getDouble();\n", " this.sumSquares = byteBuffer.getDouble();\n", " computeStats.call(this);\n", " } else {\n", " this.basesCovered = 0;\n", " this.minVal = 0;\n", " this.maxVal = 0;\n", " this.sumData = 0;\n", " this.sumSquares = 0;\n", " this.mean = 0;\n", " this.stddev = 0;\n", " }\n", " }\n", "\n", " }\n", "\n", " function computeStats() {\n", " let n = this.basesCovered;\n", "\n", " if (n > 0) {\n", " this.mean = this.sumData / n;\n", " this.stddev = Math.sqrt(this.sumSquares / (n - 1));\n", " let min = this.minVal < 0 ? this.mean - 2 * this.stddev : 0,\n", " max = this.maxVal > 0 ? this.mean + 2 * this.stddev : 0;\n", " this.defaultRange = {\n", " min: min,\n", " max: max\n", " };\n", " }\n", " }\n", "\n", " function zoomLevelForScale$1(bpPerPixel, zoomLevelHeaders) {\n", " let level;\n", "\n", " for (let i = 0; i < zoomLevelHeaders.length; i++) {\n", " const zl = zoomLevelHeaders[i];\n", "\n", " if (zl.reductionLevel < bpPerPixel) {\n", " level = zl;\n", " break;\n", " }\n", " }\n", "\n", " return level;\n", " }\n", "\n", " function decodeWigData(data, chrIdx1, bpStart, chrIdx2, bpEnd, featureArray, chrDict) {\n", " const binaryParser = new BinaryParser$1(data);\n", " const chromId = binaryParser.getInt();\n", " let chromStart = binaryParser.getInt();\n", " let chromEnd = binaryParser.getInt();\n", " const itemStep = binaryParser.getInt();\n", " const itemSpan = binaryParser.getInt();\n", " const type = binaryParser.getByte();\n", " binaryParser.getByte();\n", " let itemCount = binaryParser.getUShort();\n", "\n", " if (chromId >= chrIdx1 && chromId <= chrIdx2) {\n", " while (itemCount-- > 0) {\n", " let value;\n", "\n", " switch (type) {\n", " case 1:\n", " chromStart = binaryParser.getInt();\n", " chromEnd = binaryParser.getInt();\n", " value = binaryParser.getFloat();\n", " break;\n", "\n", " case 2:\n", " chromStart = binaryParser.getInt();\n", " value = binaryParser.getFloat();\n", " chromEnd = chromStart + itemSpan;\n", " break;\n", "\n", " case 3:\n", " // Fixed step\n", " value = binaryParser.getFloat();\n", " chromEnd = chromStart + itemSpan;\n", " chromStart += itemStep;\n", " break;\n", " }\n", "\n", " if (chromId < chrIdx1 || chromId === chrIdx1 && chromEnd < bpStart) continue;else if (chromId > chrIdx2 || chromId === chrIdx2 && chromStart >= bpEnd) break;\n", "\n", " if (Number.isFinite(value)) {\n", " const chr = chrDict[chromId];\n", " featureArray.push({\n", " chr: chr,\n", " start: chromStart,\n", " end: chromEnd,\n", " value: value\n", " });\n", " }\n", " }\n", " }\n", " }\n", "\n", " function getBedDataDecoder() {\n", " const minSize = 3 * 4 + 1; // Minimum # of bytes required for a bed record\n", "\n", " const decoder = getDecoder(this.header.definedFieldCount, this.header.fieldCount, this.autoSql);\n", " return function (data, chrIdx1, bpStart, chrIdx2, bpEnd, featureArray, chrDict) {\n", " const binaryParser = new BinaryParser$1(data);\n", "\n", " while (binaryParser.remLength() >= minSize) {\n", " const chromId = binaryParser.getInt();\n", " const chr = chrDict[chromId];\n", " const chromStart = binaryParser.getInt();\n", " const chromEnd = binaryParser.getInt();\n", " const rest = binaryParser.getString();\n", " if (chromId < chrIdx1 || chromId === chrIdx1 && chromEnd < bpStart) continue;else if (chromId > chrIdx2 || chromId === chrIdx2 && chromStart >= bpEnd) break;\n", "\n", " if (chromEnd > 0) {\n", " const feature = {\n", " chr: chr,\n", " start: chromStart,\n", " end: chromEnd\n", " };\n", " featureArray.push(feature);\n", " const tokens = rest.split(\"\\t\");\n", " decoder(feature, tokens);\n", " }\n", " }\n", " };\n", " }\n", "\n", " function decodeZoomData(data, chrIdx1, bpStart, chrIdx2, bpEnd, featureArray, chrDict, windowFunction) {\n", " const binaryParser = new BinaryParser$1(data);\n", " const minSize = 8 * 4; // Minimum # of bytes required for a zoom record\n", "\n", " while (binaryParser.remLength() >= minSize) {\n", " const chromId = binaryParser.getInt();\n", " const chr = chrDict[chromId];\n", " const chromStart = binaryParser.getInt();\n", " const chromEnd = binaryParser.getInt();\n", " const validCount = binaryParser.getInt();\n", " const minVal = binaryParser.getFloat();\n", " const maxVal = binaryParser.getFloat();\n", " const sumData = binaryParser.getFloat();\n", " binaryParser.getFloat();\n", " let value;\n", "\n", " switch (windowFunction) {\n", " case \"min\":\n", " value = minVal;\n", " break;\n", "\n", " case \"max\":\n", " value = maxVal;\n", " break;\n", "\n", " default:\n", " value = validCount === 0 ? 0 : sumData / validCount;\n", " }\n", "\n", " if (chromId < chrIdx1 || chromId === chrIdx1 && chromEnd < bpStart) continue;else if (chromId > chrIdx2 || chromId === chrIdx2 && chromStart >= bpEnd) break;\n", "\n", " if (Number.isFinite(value)) {\n", " featureArray.push({\n", " chr: chr,\n", " start: chromStart,\n", " end: chromEnd,\n", " value: value\n", " });\n", " }\n", " }\n", " }\n", "\n", " /*\n", " * The MIT License (MIT)\n", " *\n", " * Copyright (c) 2014 Broad Institute\n", " *\n", " * Permission is hereby granted, free of charge, to any person obtaining a copy\n", " * of this software and associated documentation files (the \"Software\"), to deal\n", " * in the Software without restriction, including without limitation the rights\n", " * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n", " * copies of the Software, and to permit persons to whom the Software is\n", " * furnished to do so, subject to the following conditions:\n", " *\n", " * The above copyright notice and this permission notice shall be included in\n", " * all copies or substantial portions of the Software.\n", " *\n", " *\n", " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n", " * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n", " * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n", " * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n", " * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n", " * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n", " * THE SOFTWARE.\n", " */\n", "\n", " class BWSource {\n", " constructor(config, genome) {\n", " this.reader = new BWReader(config, genome);\n", " this.genome = genome;\n", " this.format = config.format || \"bigwig\";\n", " this.wgValues = {};\n", " }\n", "\n", " async getFeatures(_ref) {\n", " let {\n", " chr,\n", " start,\n", " end,\n", " bpPerPixel,\n", " windowFunction\n", " } = _ref;\n", " const features = chr.toLowerCase() === \"all\" ? await this.getWGValues(windowFunction) : await this.reader.readFeatures(chr, start, chr, end, bpPerPixel, windowFunction);\n", " const isBigWig = this.reader.type === \"bigwig\";\n", "\n", " if (!isBigWig) {\n", " pack(features);\n", " }\n", "\n", " return features;\n", " }\n", "\n", " async getHeader() {\n", " return this.reader.loadHeader();\n", " }\n", "\n", " getDefaultRange() {\n", " if (this.reader.totalSummary !== undefined) {\n", " return this.reader.totalSummary.defaultRange;\n", " } else {\n", " return undefined;\n", " }\n", " }\n", "\n", " async defaultVisibilityWindow() {\n", " return this.reader.defaultVisibilityWindow;\n", " }\n", "\n", " async getWGValues(windowFunction) {\n", " const nominalScreenWidth = 1000; // This doesn't need to be precise\n", "\n", " const genome = this.genome;\n", "\n", " if (this.wgValues[windowFunction]) {\n", " return this.wgValues[windowFunction];\n", " } else {\n", " const bpPerPixel = genome.getGenomeLength() / nominalScreenWidth;\n", " const features = await this.reader.readWGFeatures(bpPerPixel, windowFunction);\n", " let wgValues = [];\n", "\n", " for (let f of features) {\n", " const chr = f.chr;\n", " const offset = genome.getCumulativeOffset(chr);\n", " const wgFeature = Object.assign({}, f);\n", " wgFeature.chr = \"all\";\n", " wgFeature.start = offset + f.start;\n", " wgFeature.end = offset + f.end;\n", " wgValues.push(wgFeature);\n", " }\n", "\n", " this.wgValues[windowFunction] = wgValues;\n", " return wgValues;\n", " }\n", " }\n", "\n", " supportsWholeGenome() {\n", " return this.reader.type === \"bigwig\" || this.defaultVisibilityWindow() <= 0;\n", " }\n", "\n", " async trackType() {\n", " return this.reader.getTrackType();\n", " }\n", "\n", " }\n", "\n", " const GZIP_FLAG = 0x1;\n", "\n", " class TDFReader {\n", " constructor(config, genome) {\n", " this.config = config;\n", " this.genome = genome;\n", " this.path = config.url;\n", " this.groupCache = {};\n", " this.datasetCache = {};\n", " }\n", "\n", " async readHeader() {\n", " if (this.magic !== undefined) {\n", " return this; // Already read\n", " }\n", "\n", " let data = await igvxhr.loadArrayBuffer(this.path, buildOptions$1(this.config, {\n", " range: {\n", " start: 0,\n", " size: 64000\n", " }\n", " }));\n", " let binaryParser = new BinaryParser$1(new DataView(data));\n", " this.magic = binaryParser.getInt();\n", " this.version = binaryParser.getInt();\n", " this.indexPos = binaryParser.getLong();\n", " this.indexSize = binaryParser.getInt();\n", " binaryParser.getInt();\n", "\n", " if (this.version >= 2) {\n", " let nWindowFunctions = binaryParser.getInt();\n", " this.windowFunctions = [];\n", "\n", " while (nWindowFunctions-- > 0) {\n", " this.windowFunctions.push(binaryParser.getString());\n", " }\n", " }\n", "\n", " this.trackType = binaryParser.getString();\n", " this.trackLine = binaryParser.getString();\n", " let nTracks = binaryParser.getInt();\n", " this.trackNames = [];\n", "\n", " while (nTracks-- > 0) {\n", " this.trackNames.push(binaryParser.getString());\n", " }\n", "\n", " this.genomeID = binaryParser.getString();\n", " this.flags = binaryParser.getInt();\n", " this.compressed = (this.flags & GZIP_FLAG) !== 0; // Now read index\n", "\n", " data = await igvxhr.loadArrayBuffer(this.path, buildOptions$1(this.config, {\n", " range: {\n", " start: this.indexPos,\n", " size: this.indexSize\n", " }\n", " }));\n", " binaryParser = new BinaryParser$1(new DataView(data));\n", " this.datasetIndex = {};\n", " let nEntries = binaryParser.getInt();\n", "\n", " while (nEntries-- > 0) {\n", " const name = binaryParser.getString();\n", " const pos = binaryParser.getLong();\n", " const size = binaryParser.getInt();\n", " this.datasetIndex[name] = {\n", " position: pos,\n", " size: size\n", " };\n", " }\n", "\n", " this.groupIndex = {};\n", " nEntries = binaryParser.getInt();\n", "\n", " while (nEntries-- > 0) {\n", " const name = binaryParser.getString();\n", " const pos = binaryParser.getLong();\n", " const size = binaryParser.getInt();\n", " this.groupIndex[name] = {\n", " position: pos,\n", " size: size\n", " };\n", " }\n", "\n", " return this;\n", " }\n", "\n", " async readDataset(chr, windowFunction, zoom) {\n", " const key = chr + \"_\" + windowFunction + \"_\" + zoom;\n", "\n", " if (this.datasetCache[key]) {\n", " return this.datasetCache[key];\n", " } else {\n", " await this.readHeader();\n", " const wf = this.version < 2 ? \"\" : \"/\" + windowFunction;\n", " const zoomString = chr.toLowerCase() === \"all\" || zoom === undefined ? \"0\" : zoom.toString();\n", " let dsName;\n", "\n", " if (windowFunction === \"raw\") {\n", " dsName = \"/\" + chr + \"/raw\";\n", " } else {\n", " dsName = \"/\" + chr + \"/z\" + zoomString + wf;\n", " }\n", "\n", " const indexEntry = this.datasetIndex[dsName];\n", "\n", " if (indexEntry === undefined) {\n", " return undefined;\n", " }\n", "\n", " const data = await igvxhr.loadArrayBuffer(this.path, buildOptions$1(this.config, {\n", " range: {\n", " start: indexEntry.position,\n", " size: indexEntry.size\n", " }\n", " }));\n", "\n", " if (!data) {\n", " return undefined;\n", " }\n", "\n", " const binaryParser = new BinaryParser$1(new DataView(data));\n", " let nAttributes = binaryParser.getInt();\n", " const attributes = {};\n", "\n", " while (nAttributes-- > 0) {\n", " attributes[binaryParser.getString()] = binaryParser.getString();\n", " }\n", "\n", " const dataType = binaryParser.getString();\n", " const tileWidth = binaryParser.getFloat();\n", " let nTiles = binaryParser.getInt();\n", " const tiles = [];\n", "\n", " while (nTiles-- > 0) {\n", " tiles.push({\n", " position: binaryParser.getLong(),\n", " size: binaryParser.getInt()\n", " });\n", " }\n", "\n", " const dataset = {\n", " name: dsName,\n", " attributes: attributes,\n", " dataType: dataType,\n", " tileWidth: tileWidth,\n", " tiles: tiles\n", " };\n", " this.datasetCache[key] = dataset;\n", " return dataset;\n", " }\n", " }\n", "\n", " async readRootGroup() {\n", " const genome = this.genome;\n", " const rootGroup = this.groupCache[\"/\"];\n", "\n", " if (rootGroup) {\n", " return rootGroup;\n", " } else {\n", " const group = await this.readGroup(\"/\");\n", " const names = group[\"chromosomes\"];\n", " const maxZoomString = group[\"maxZoom\"]; // Now parse out interesting attributes.\n", "\n", " if (maxZoomString) {\n", " this.maxZoom = Number(maxZoomString);\n", " }\n", "\n", " const totalCountString = group[\"totalCount\"];\n", "\n", " if (totalCountString) {\n", " group.totalCount = Number.parseFloat(totalCountString);\n", " } // Chromosome names\n", "\n", "\n", " const chrAliasTable = {};\n", "\n", " if (names) {\n", " names.split(\",\").forEach(function (chr) {\n", " const canonicalName = genome.getChromosomeName(chr);\n", " chrAliasTable[canonicalName] = chr;\n", " });\n", " }\n", "\n", " this.chrAliasTable = chrAliasTable;\n", " this.groupCache[\"/\"] = group;\n", " return group;\n", " }\n", " }\n", "\n", " async readGroup(name) {\n", " const group = this.groupCache[name];\n", "\n", " if (group) {\n", " return group;\n", " } else {\n", " await this.readHeader();\n", " const indexEntry = this.groupIndex[name];\n", "\n", " if (indexEntry === undefined) {\n", " return undefined;\n", " }\n", "\n", " const data = await igvxhr.loadArrayBuffer(this.path, buildOptions$1(this.config, {\n", " range: {\n", " start: indexEntry.position,\n", " size: indexEntry.size\n", " }\n", " }));\n", "\n", " if (!data) {\n", " return undefined;\n", " }\n", "\n", " const binaryParser = new BinaryParser$1(new DataView(data));\n", " const group = {\n", " name: name\n", " };\n", " let nAttributes = binaryParser.getInt();\n", "\n", " while (nAttributes-- > 0) {\n", " const key = binaryParser.getString();\n", " const value = binaryParser.getString();\n", " group[key] = value;\n", " }\n", "\n", " this.groupCache[name] = group;\n", " return group;\n", " }\n", " }\n", "\n", " async readTiles(tileIndeces, nTracks) {\n", " tileIndeces.sort(function (a, b) {\n", " return a.position - b.position;\n", " });\n", " tileIndeces = tileIndeces.filter(function (idx) {\n", " return idx.size > 0;\n", " });\n", "\n", " if (tileIndeces.length === 0) {\n", " return Promise.resolve([]);\n", " }\n", "\n", " const firstEntry = tileIndeces[0];\n", " const lastEntry = tileIndeces[tileIndeces.length - 1];\n", " const position = firstEntry.position;\n", " const size = lastEntry.position + lastEntry.size - position;\n", " const data = await igvxhr.loadArrayBuffer(this.path, buildOptions$1(this.config, {\n", " range: {\n", " start: position,\n", " size: size\n", " }\n", " }));\n", " const tiles = []; // Loop through and decode tiles\n", "\n", " for (let indexEntry of tileIndeces) {\n", " const start = indexEntry.position - position;\n", " const size = indexEntry.size;\n", "\n", " if (size > 0) {\n", " let tileData;\n", "\n", " if (this.compressed) {\n", " const inflate = new Zlib$2.Inflate(new Uint8Array(data, start, size));\n", " const plain = inflate.decompress();\n", " tileData = plain.buffer;\n", " } else {\n", " tileData = data.slice(start, start + size);\n", " }\n", "\n", " const binaryParser = new BinaryParser$1(new DataView(tileData));\n", " const type = binaryParser.getString();\n", " let tile;\n", "\n", " switch (type) {\n", " case \"fixedStep\":\n", " tile = createFixedStep(binaryParser, nTracks);\n", " break;\n", "\n", " case \"variableStep\":\n", " tile = createVariableStep(binaryParser, nTracks);\n", " break;\n", "\n", " case \"bed\":\n", " case \"bedWithName\":\n", " tile = createBed(binaryParser, nTracks, type);\n", " break;\n", "\n", " default:\n", " throw \"Unknown tile type: \" + type;\n", " }\n", "\n", " tiles.push(tile);\n", " }\n", " }\n", "\n", " return tiles;\n", " }\n", "\n", " async readTile(indexEntry, nTracks) {\n", " let data = await igvxhr.loadArrayBuffer(this.path, buildOptions$1(this.config, {\n", " range: {\n", " start: indexEntry.position,\n", " size: indexEntry.size\n", " }\n", " }));\n", "\n", " if (this.compressed) {\n", " const inflate = new Zlib$2.Inflate(new Uint8Array(data));\n", " const plain = inflate.decompress();\n", " data = plain.buffer;\n", " }\n", "\n", " const binaryParser = new BinaryParser$1(new DataView(data));\n", " const type = binaryParser.getString();\n", "\n", " switch (type) {\n", " case \"fixedStep\":\n", " return createFixedStep(binaryParser, nTracks);\n", "\n", " case \"variableStep\":\n", " return createVariableStep(binaryParser, nTracks);\n", "\n", " case \"bed\":\n", " case \"bedWithName\":\n", " return createBed(binaryParser, nTracks, type);\n", "\n", " default:\n", " throw \"Unknown tile type: \" + type;\n", " }\n", " }\n", "\n", " }\n", "\n", " function createFixedStep(binaryParser, nTracks) {\n", " const nPositions = binaryParser.getInt();\n", " const start = binaryParser.getInt();\n", " const span = binaryParser.getFloat();\n", " const data = [];\n", " let nt = nTracks;\n", "\n", " while (nt-- > 0) {\n", " let np = nPositions;\n", " const dtrack = [];\n", "\n", " while (np-- > 0) {\n", " dtrack.push(binaryParser.getFloat());\n", " }\n", "\n", " data.push(dtrack);\n", " }\n", "\n", " return {\n", " type: \"fixedStep\",\n", " start: start,\n", " span: span,\n", " data: data,\n", " nTracks: nTracks,\n", " nPositions: nPositions\n", " };\n", " }\n", "\n", " function createVariableStep(binaryParser, nTracks) {\n", " const tileStart = binaryParser.getInt();\n", " const span = binaryParser.getFloat();\n", " const nPositions = binaryParser.getInt();\n", " const start = [];\n", " let np = nPositions;\n", "\n", " while (np-- > 0) {\n", " start.push(binaryParser.getInt());\n", " }\n", "\n", " binaryParser.getInt(); // # of samples, ignored but should === nTracks\n", "\n", " const data = [];\n", " let nt = nTracks;\n", "\n", " while (nt-- > 0) {\n", " np = nPositions;\n", " const dtrack = [];\n", "\n", " while (np-- > 0) {\n", " dtrack.push(binaryParser.getFloat());\n", " }\n", "\n", " data.push(dtrack);\n", " }\n", "\n", " return {\n", " type: \"variableStep\",\n", " tileStart: tileStart,\n", " span: span,\n", " start: start,\n", " data: data,\n", " nTracks: nTracks,\n", " nPositions: nPositions\n", " };\n", " }\n", "\n", " function createBed(binaryParser, nTracks, type) {\n", " const nPositions = binaryParser.getInt();\n", " let n = nPositions;\n", " const start = [];\n", "\n", " while (n-- > 0) {\n", " start.push(binaryParser.getInt());\n", " }\n", "\n", " n = nPositions;\n", " const end = [];\n", "\n", " while (n-- > 0) {\n", " end.push(binaryParser.getInt());\n", " }\n", "\n", " binaryParser.getInt(); // # of samples, ignored but should === nTracks\n", "\n", " const data = [];\n", " let nt = nTracks;\n", "\n", " while (nt-- > 0) {\n", " let np = nPositions;\n", " const dtrack = [];\n", "\n", " while (np-- > 0) {\n", " dtrack.push(binaryParser.getFloat());\n", " }\n", "\n", " data.push(dtrack);\n", " }\n", "\n", " if (type === \"bedWithName\") {\n", " n = nPositions;\n", " const name = [];\n", "\n", " while (n-- > 0) {\n", " name.push(binaryParser.getString());\n", " }\n", " }\n", "\n", " return {\n", " type: type,\n", " start: start,\n", " end: end,\n", " data: data,\n", " nTracks: nTracks,\n", " nPositions: nPositions\n", " };\n", " }\n", "\n", " /*\n", " * The MIT License (MIT)\n", " *\n", " * Copyright (c) 2016 University of California San Diego\n", " * Author: Jim Robinson\n", " *\n", " * Permission is hereby granted, free of charge, to any person obtaining a copy\n", " * of this software and associated documentation files (the \"Software\"), to deal\n", " * in the Software without restriction, including without limitation the rights\n", " * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n", " * copies of the Software, and to permit persons to whom the Software is\n", " * furnished to do so, subject to the following conditions:\n", " *\n", " * The above copyright notice and this permission notice shall be included in\n", " * all copies or substantial portions of the Software.\n", " *\n", " *\n", " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n", " * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n", " * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n", " * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n", " * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n", " * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n", " * THE SOFTWARE.\n", " */\n", "\n", " class TDFSource {\n", " constructor(config, genome) {\n", " this.genome = genome;\n", " this.windowFunction = config.windowFunction || \"mean\";\n", " this.reader = new TDFReader(config, genome);\n", " }\n", "\n", " async getFeatures(_ref) {\n", " let {\n", " chr,\n", " start,\n", " end,\n", " bpPerPixel\n", " } = _ref;\n", " const genomicInterval = new GenomicInterval(chr, start, end);\n", " const genome = this.genome;\n", "\n", " if (!this.rootGroup) {\n", " this.rootGroup = await this.reader.readRootGroup();\n", "\n", " if (!this.normalizationFactor) {\n", " const totalCount = this.rootGroup.totalCount;\n", "\n", " if (totalCount) {\n", " this.normalizationFactor = 1.0e6 / totalCount;\n", " }\n", " }\n", " }\n", "\n", " if (chr.toLowerCase() === \"all\") {\n", " return []; // Whole genome view not yet supported\n", " }\n", "\n", " genomicInterval.bpPerPixel = bpPerPixel;\n", " const zoom = zoomLevelForScale(chr, bpPerPixel, genome);\n", " let queryChr = this.reader.chrAliasTable[chr];\n", " let maxZoom = this.reader.maxZoom;\n", " if (queryChr === undefined) queryChr = chr;\n", " if (maxZoom === undefined) maxZoom = -1;\n", " const wf = zoom > maxZoom ? \"raw\" : this.windowFunction;\n", " const dataset = await this.reader.readDataset(queryChr, wf, zoom);\n", "\n", " if (dataset == null) {\n", " return [];\n", " }\n", "\n", " const tileWidth = dataset.tileWidth;\n", " const startTile = Math.floor(start / tileWidth);\n", " const endTile = Math.floor(end / tileWidth);\n", " const NTRACKS = 1; // TODO read this\n", "\n", " const tiles = await this.reader.readTiles(dataset.tiles.slice(startTile, endTile + 1), NTRACKS);\n", " const features = [];\n", "\n", " for (let tile of tiles) {\n", " switch (tile.type) {\n", " case \"bed\":\n", " decodeBedTile(tile, chr, start, end, bpPerPixel, features);\n", " break;\n", "\n", " case \"variableStep\":\n", " decodeVaryTile(tile, chr, start, end, bpPerPixel, features);\n", " break;\n", "\n", " case \"fixedStep\":\n", " decodeFixedTile(tile, chr, start, end, bpPerPixel, features);\n", " break;\n", "\n", " default:\n", " throw \"Unknown tile type: \" + tile.type;\n", " }\n", " }\n", "\n", " features.sort(function (a, b) {\n", " return a.start - b.start;\n", " });\n", " return features;\n", " }\n", "\n", " supportsWholeGenome() {\n", " return false;\n", " }\n", "\n", " }\n", "\n", " function decodeBedTile(tile, chr, bpStart, bpEnd, bpPerPixel, features) {\n", " const nPositions = tile.nPositions;\n", " const starts = tile.start;\n", " const ends = tile.end;\n", " const data = tile.data[0]; // Single track for now\n", "\n", " for (let i = 0; i < nPositions; i++) {\n", " const s = starts[i];\n", " const e = ends[i];\n", " if (e < bpStart) continue;\n", " if (s > bpEnd) break;\n", " features.push({\n", " chr: chr,\n", " start: s,\n", " end: e,\n", " value: data[i]\n", " });\n", " }\n", " }\n", "\n", " function decodeVaryTile(tile, chr, bpStart, bpEnd, bpPerPixel, features) {\n", " const nPositions = tile.nPositions;\n", " const starts = tile.start;\n", " const span = tile.span;\n", " const data = tile.data[0]; // Single track for now\n", "\n", " for (let i = 0; i < nPositions; i++) {\n", " const s = starts[i];\n", " const e = s + span;\n", " if (e < bpStart) continue;\n", " if (s > bpEnd) break;\n", " features.push({\n", " chr: chr,\n", " start: s,\n", " end: e,\n", " value: data[i]\n", " });\n", " }\n", " }\n", "\n", " function decodeFixedTile(tile, chr, bpStart, bpEnd, bpPerPixel, features) {\n", " const nPositions = tile.nPositions;\n", " let s = tile.start;\n", " const span = tile.span;\n", " const data = tile.data[0]; // Single track for now\n", "\n", " for (let i = 0; i < nPositions; i++) {\n", " const e = s + span;\n", " if (s > bpEnd) break;\n", "\n", " if (e >= bpStart) {\n", " if (!Number.isNaN(data[i])) {\n", " features.push({\n", " chr: chr,\n", " start: s,\n", " end: e,\n", " value: data[i]\n", " });\n", " }\n", " }\n", "\n", " s = e;\n", " }\n", " }\n", "\n", " var log2 = Math.log(2);\n", "\n", " function zoomLevelForScale(chr, bpPerPixel, genome) {\n", " // Convert bpPerPixel to IGV \"zoom\" level. This is a bit convoluted, IGV computes zoom levels assuming\n", " // display in a 700 pixel window. The fully zoomed out view of a chromosome is zoom level \"0\".\n", " // Zoom level 1 is magnified 2X, and so forth\n", " var chrSize = genome.getChromosome(chr).bpLength;\n", " return Math.ceil(Math.log(Math.max(0, chrSize / (bpPerPixel * 700))) / log2);\n", " }\n", "\n", " /*\n", " * The MIT License (MIT)\n", " *\n", " * Copyright (c) 2014-2015 Broad Institute\n", " *\n", " * Permission is hereby granted, free of charge, to any person obtaining a copy\n", " * of this software and associated documentation files (the \"Software\"), to deal\n", " * in the Software without restriction, including without limitation the rights\n", " * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n", " * copies of the Software, and to permit persons to whom the Software is\n", " * furnished to do so, subject to the following conditions:\n", " *\n", " * The above copyright notice and this permission notice shall be included in\n", " * all copies or substantial portions of the Software.\n", " *\n", " *\n", " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n", " * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n", " * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n", " * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n", " * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n", " * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n", " * THE SOFTWARE.\n", " */\n", "\n", " function FeatureSource(config, genome) {\n", " const format = config.format ? config.format.toLowerCase() : undefined;\n", "\n", " if ('bigwig' === format || 'bigbed' === format || 'bb' === format) {\n", " return new BWSource(config, genome);\n", " } else if (\"tdf\" === format) {\n", " return new TDFSource(config, genome);\n", " } else {\n", " return new TextFeatureSource(config, genome);\n", " }\n", " }\n", "\n", " /*\n", " * The MIT License (MIT)\n", " *\n", " * Copyright (c) 2014 Broad Institute\n", " *\n", " * Permission is hereby granted, free of charge, to any person obtaining a copy\n", " * of ctx software and associated documentation files (the \"Software\"), to deal\n", " * in the Software without restriction, including without limitation the rights\n", " * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n", " * copies of the Software, and to permit persons to whom the Software is\n", " * furnished to do so, subject to the following conditions:\n", " *\n", " * The above copyright notice and ctx permission notice shall be included in\n", " * all copies or substantial portions of the Software.\n", " *\n", " *\n", " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n", " * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n", " * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n", " * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n", " * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n", " * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n", " * THE SOFTWARE.\n", " */\n", "\n", " const IGVGraphics = {\n", " setProperties: function (ctx, properties) {\n", " for (var key in properties) {\n", " if (properties.hasOwnProperty(key)) {\n", " var value = properties[key];\n", " ctx[key] = value;\n", " }\n", " }\n", " },\n", " strokeLine: function (ctx, x1, y1, x2, y2, properties) {\n", " x1 = Math.floor(x1) + 0.5;\n", " y1 = Math.floor(y1) + 0.5;\n", " x2 = Math.floor(x2) + 0.5;\n", " y2 = Math.floor(y2) + 0.5;\n", "\n", " if (properties) {\n", " ctx.save();\n", " IGVGraphics.setProperties(ctx, properties);\n", " }\n", "\n", " ctx.beginPath();\n", " ctx.moveTo(x1, y1);\n", " ctx.lineTo(x2, y2);\n", " ctx.stroke();\n", " if (properties) ctx.restore();\n", " },\n", " fillRect: function (ctx, x, y, w, h, properties) {\n", " x = Math.round(x);\n", " y = Math.round(y);\n", "\n", " if (properties) {\n", " ctx.save();\n", " IGVGraphics.setProperties(ctx, properties);\n", " }\n", "\n", " ctx.fillRect(x, y, w, h);\n", " if (properties) ctx.restore();\n", " },\n", " fillPolygon: function (ctx, x, y, properties) {\n", " if (properties) {\n", " ctx.save();\n", " IGVGraphics.setProperties(ctx, properties);\n", " }\n", "\n", " doPath(ctx, x, y);\n", " ctx.fill();\n", " if (properties) ctx.restore();\n", " },\n", " strokePolygon: function (ctx, x, y, properties) {\n", " if (properties) {\n", " ctx.save();\n", " IGVGraphics.setProperties(ctx, properties);\n", " }\n", "\n", " doPath(ctx, x, y);\n", " ctx.stroke();\n", " if (properties) ctx.restore();\n", " },\n", " fillText: function (ctx, text, x, y, properties, transforms) {\n", " if (properties || transforms) {\n", " ctx.save();\n", " }\n", "\n", " if (properties) {\n", " IGVGraphics.setProperties(ctx, properties);\n", " }\n", "\n", " if (transforms) {\n", " // Slow path with context saving and extra translate\n", " ctx.translate(x, y);\n", "\n", " for (var transform in transforms) {\n", " var value = transforms[transform]; // TODO: Add error checking for robustness\n", "\n", " if (transform === 'translate') {\n", " ctx.translate(value['x'], value['y']);\n", " }\n", "\n", " if (transform === 'rotate') {\n", " ctx.rotate(value['angle'] * Math.PI / 180);\n", " }\n", " }\n", "\n", " ctx.fillText(text, 0, 0);\n", " } else {\n", " ctx.fillText(text, x, y);\n", " }\n", "\n", " if (properties || transforms) ctx.restore();\n", " },\n", " strokeText: function (ctx, text, x, y, properties, transforms) {\n", " if (properties || transforms) {\n", " ctx.save();\n", " }\n", "\n", " if (properties) {\n", " IGVGraphics.setProperties(ctx, properties);\n", " }\n", "\n", " if (transforms) {\n", " ctx.translate(x, y);\n", "\n", " for (var transform in transforms) {\n", " var value = transforms[transform]; // TODO: Add error checking for robustness\n", "\n", " if (transform === 'translate') {\n", " ctx.translate(value['x'], value['y']);\n", " }\n", "\n", " if (transform === 'rotate') {\n", " ctx.rotate(value['angle'] * Math.PI / 180);\n", " }\n", " }\n", "\n", " ctx.strokeText(text, 0, 0);\n", " } else {\n", " ctx.strokeText(text, x, y);\n", " }\n", "\n", " if (properties || transforms) ctx.restore();\n", " },\n", " strokeCircle: function (ctx, x, y, radius, properties) {\n", " if (properties) {\n", " ctx.save();\n", " IGVGraphics.setProperties(ctx, properties);\n", " }\n", "\n", " ctx.beginPath();\n", " ctx.arc(x, y, radius, 0, 2 * Math.PI);\n", " ctx.stroke();\n", " if (properties) ctx.restore();\n", " },\n", " fillCircle: function (ctx, x, y, radius, properties) {\n", " if (properties) {\n", " ctx.save();\n", " IGVGraphics.setProperties(ctx, properties);\n", " }\n", "\n", " ctx.beginPath();\n", " ctx.arc(x, y, radius, 0, 2 * Math.PI);\n", " ctx.fill();\n", " if (properties) ctx.restore();\n", " },\n", " drawArrowhead: function (ctx, x, y, size, lineWidth) {\n", " ctx.save();\n", "\n", " if (!size) {\n", " size = 5;\n", " }\n", "\n", " if (lineWidth) {\n", " ctx.lineWidth = lineWidth;\n", " }\n", "\n", " ctx.beginPath();\n", " ctx.moveTo(x, y - size / 2);\n", " ctx.lineTo(x, y + size / 2);\n", " ctx.lineTo(x + size, y);\n", " ctx.lineTo(x, y - size / 2);\n", " ctx.closePath();\n", " ctx.fill();\n", " ctx.restore();\n", " },\n", " dashedLine: function (ctx, x1, y1, x2, y2, dashLen) {\n", " let properties = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : {};\n", " if (dashLen === undefined) dashLen = 2;\n", " ctx.setLineDash([dashLen, dashLen]);\n", " IGVGraphics.strokeLine(ctx, x1, y1, x2, y2, properties);\n", " ctx.setLineDash([]);\n", " },\n", " roundRect: function (ctx, x, y, width, height, radius, fill, stroke) {\n", " if (typeof stroke == \"undefined\") {\n", " stroke = true;\n", " }\n", "\n", " if (typeof radius === \"undefined\") {\n", " radius = 5;\n", " }\n", "\n", " ctx.beginPath();\n", " ctx.moveTo(x + radius, y);\n", " ctx.lineTo(x + width - radius, y);\n", " ctx.quadraticCurveTo(x + width, y, x + width, y + radius);\n", " ctx.lineTo(x + width, y + height - radius);\n", " ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);\n", " ctx.lineTo(x + radius, y + height);\n", " ctx.quadraticCurveTo(x, y + height, x, y + height - radius);\n", " ctx.lineTo(x, y + radius);\n", " ctx.quadraticCurveTo(x, y, x + radius, y);\n", " ctx.closePath();\n", "\n", " if (stroke) {\n", " ctx.stroke();\n", " }\n", "\n", " if (fill) {\n", " ctx.fill();\n", " }\n", " },\n", " polygon: function (ctx, x, y, fill, stroke) {\n", " if (typeof stroke == \"undefined\") {\n", " stroke = true;\n", " }\n", "\n", " ctx.beginPath();\n", " var len = x.length;\n", " ctx.moveTo(x[0], y[0]);\n", "\n", " for (var i = 1; i < len; i++) {\n", " ctx.lineTo(x[i], y[i]); // this.moveTo(x[i], y[i]);\n", " }\n", "\n", " ctx.closePath();\n", "\n", " if (stroke) {\n", " ctx.stroke();\n", " }\n", "\n", " if (fill) {\n", " ctx.fill();\n", " }\n", " }\n", " };\n", "\n", " function doPath(ctx, x, y) {\n", " var i,\n", " len = x.length;\n", "\n", " for (i = 0; i < len; i++) {\n", " x[i] = Math.round(x[i]);\n", " y[i] = Math.round(y[i]);\n", " }\n", "\n", " ctx.beginPath();\n", " ctx.moveTo(x[0], y[0]);\n", "\n", " for (i = 1; i < len; i++) {\n", " ctx.lineTo(x[i], y[i]);\n", " }\n", "\n", " ctx.closePath();\n", " }\n", "\n", " /*\n", " * The MIT License (MIT)\n", " *\n", " * Copyright (c) 2014 Broad Institute\n", " *\n", " * Permission is hereby granted, free of charge, to any person obtaining a copy\n", " * of this software and associated documentation files (the \"Software\"), to deal\n", " * in the Software without restriction, including without limitation the rights\n", " * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n", " * copies of the Software, and to permit persons to whom the Software is\n", " * furnished to do so, subject to the following conditions:\n", " *\n", " * The above copyright notice and this permission notice shall be included in\n", " * all copies or substantial portions of the Software.\n", " *\n", " *\n", " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n", " * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n", " * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n", " * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n", " * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n", " * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n", " * THE SOFTWARE.\n", " */\n", " 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\n", " // motif values as this varies depending on the RNA-seq pipeline. The current list is based on STAR v2.4 docs.\n", "\n", " const someMotifValues = ['GT/AG', 'CT/AC', 'GC/AG', 'CT/GC', 'AT/AC', 'GT/AT', 'non-canonical'];\n", " someMotifValues.forEach(motif => {\n", " JUNCTION_MOTIF_PALETTE.getColor(motif);\n", " }); // rendering context with values that only need to be computed once per render, rather than for each splice junction\n", "\n", " const junctionRenderingContext = {};\n", "\n", " class FeatureTrack extends TrackBase {\n", " constructor(config, browser) {\n", " super(config, browser); // Set maxRows -- protects against pathological feature packing cases (# of rows of overlapping feaures)\n", "\n", " this.maxRows = config.maxRows === undefined ? 1000 : config.maxRows;\n", " this.displayMode = config.displayMode || \"COLLAPSED\"; // COLLAPSED | EXPANDED | SQUISHED\n", "\n", " this.labelDisplayMode = config.labelDisplayMode;\n", "\n", " if (config._featureSource) {\n", " this.featureSource = config._featureSource;\n", " delete config._featureSource;\n", " } else {\n", " this.featureSource = config.featureSource ? config.featureSource : FeatureSource(config, browser.genome);\n", " } // Set default heights\n", "\n", "\n", " this.autoHeight = config.autoHeight;\n", " this.margin = config.margin === undefined ? 10 : config.margin;\n", " this.featureHeight = config.featureHeight || 14;\n", "\n", " if (\"FusionJuncSpan\" === config.type) {\n", " this.squishedRowHeight = config.squishedRowHeight || 50;\n", " this.expandedRowHeight = config.expandedRowHeight || 50;\n", " this.height = config.height || this.margin + 2 * this.expandedRowHeight;\n", " } else if ('snp' === config.type) {\n", " this.expandedRowHeight = config.expandedRowHeight || 10;\n", " this.squishedRowHeight = config.squishedRowHeight || 5;\n", " this.height = config.height || 30;\n", " } else {\n", " this.squishedRowHeight = config.squishedRowHeight || 15;\n", " this.expandedRowHeight = config.expandedRowHeight || 30;\n", " this.height = config.height || this.margin + 2 * this.expandedRowHeight;\n", " }\n", "\n", " if (this.height === undefined || !this.height) {\n", " this.height = 100;\n", " } //set defaults\n", "\n", "\n", " if ('spliceJunctions' === config.type && config.colorByNumReadsThreshold === undefined) {\n", " config.colorByNumReadsThreshold = 5;\n", " } // Set the render function. This can optionally be passed in the config\n", "\n", "\n", " if (config.render) {\n", " this.render = config.render;\n", " } else if (\"FusionJuncSpan\" === config.type) {\n", " this.render = renderFusionJuncSpan;\n", " } else if ('spliceJunctions' === config.type) {\n", " this.render = renderJunctions;\n", " this.displayMode = \"COLLAPSED\"; // needed for this.clickedFeatures(..) to work\n", " } else if ('snp' === config.type) {\n", " this.render = renderSnp; // colors ordered based on priority least to greatest\n", "\n", " this.snpColors = ['rgb(0,0,0)', 'rgb(0,0,255)', 'rgb(0,255,0)', 'rgb(255,0,0)'];\n", " this.colorBy = 'function';\n", " } else {\n", " this.render = renderFeature;\n", " this.arrowSpacing = 30; // adjust label positions to make sure they're always visible\n", "\n", " monitorTrackDrag(this);\n", " } //UCSC useScore option\n", "\n", "\n", " this.useScore = config.useScore;\n", " }\n", "\n", " async postInit() {\n", " if (typeof this.featureSource.getHeader === \"function\") {\n", " this.header = await this.featureSource.getHeader();\n", " } // Set properties from track line\n", "\n", "\n", " if (this.header) {\n", " this.setTrackProperties(this.header);\n", " }\n", "\n", " if (this.visibilityWindow === undefined && typeof this.featureSource.defaultVisibilityWindow === 'function') {\n", " this.visibilityWindow = await this.featureSource.defaultVisibilityWindow();\n", " this.featureSource.visibilityWindow = this.visibilityWindow; // <- this looks odd\n", " }\n", "\n", " return this;\n", " }\n", "\n", " supportsWholeGenome() {\n", " return (this.config.indexed === false || !this.config.indexURL) && this.config.supportsWholeGenome !== false;\n", " }\n", "\n", " async getFeatures(chr, start, end, bpPerPixel) {\n", " const visibilityWindow = this.visibilityWindow;\n", " return this.featureSource.getFeatures({\n", " chr,\n", " start,\n", " end,\n", " bpPerPixel,\n", " visibilityWindow\n", " });\n", " }\n", "\n", " /**\n", " * The required height in pixels required for the track content. This is not the visible track height, which\n", " * can be smaller (with a scrollbar) or larger.\n", " *\n", " * @param features\n", " * @returns {*}\n", " */\n", " computePixelHeight(features) {\n", " if (this.type === 'spliceJunctions') {\n", " return this.height;\n", " } else if (this.displayMode === \"COLLAPSED\") {\n", " return this.margin + this.expandedRowHeight;\n", " } else {\n", " let maxRow = 0;\n", "\n", " if (features && typeof features.forEach === \"function\") {\n", " for (let feature of features) {\n", " if (feature.row && feature.row > maxRow) {\n", " maxRow = feature.row;\n", " }\n", " }\n", " }\n", "\n", " const height = this.margin + (maxRow + 1) * (\"SQUISHED\" === this.displayMode ? this.squishedRowHeight : this.expandedRowHeight);\n", " return height;\n", " }\n", " }\n", "\n", " draw(options) {\n", " const featureList = options.features;\n", " const ctx = options.context;\n", " const bpPerPixel = options.bpPerPixel;\n", " const bpStart = options.bpStart;\n", " const pixelWidth = options.pixelWidth;\n", " const pixelHeight = options.pixelHeight;\n", " const bpEnd = bpStart + pixelWidth * bpPerPixel + 1;\n", "\n", " if (!this.config.isMergedTrack) {\n", " IGVGraphics.fillRect(ctx, 0, options.pixelTop, pixelWidth, pixelHeight, {\n", " 'fillStyle': \"rgb(255, 255, 255)\"\n", " });\n", " }\n", "\n", " if (featureList) {\n", " const rowFeatureCount = [];\n", " options.rowLastX = [];\n", "\n", " for (let feature of featureList) {\n", " const row = feature.row || 0;\n", "\n", " if (rowFeatureCount[row] === undefined) {\n", " rowFeatureCount[row] = 1;\n", " } else {\n", " rowFeatureCount[row]++;\n", " }\n", "\n", " options.rowLastX[row] = -Number.MAX_SAFE_INTEGER;\n", " }\n", "\n", " if (this.config.type == 'spliceJunctions') {\n", " junctionRenderingContext.referenceFrame = options.viewport.referenceFrame;\n", " junctionRenderingContext.referenceFrameStart = junctionRenderingContext.referenceFrame.start;\n", " junctionRenderingContext.referenceFrameEnd = junctionRenderingContext.referenceFrameStart + junctionRenderingContext.referenceFrame.toBP($(options.viewport.contentDiv).width()); // For a given viewport, records where features that are < 2px in width have been rendered already.\n", " // This prevents wasteful rendering of multiple such features onto the same pixels.\n", "\n", " junctionRenderingContext.featureZoomOutTracker = {};\n", " }\n", "\n", " let lastPxEnd = [];\n", "\n", " for (let feature of featureList) {\n", " if (feature.end < bpStart) continue;\n", " if (feature.start > bpEnd) break;\n", " const row = this.displayMode === 'COLLAPSED' ? 0 : feature.row;\n", " const featureDensity = pixelWidth / rowFeatureCount[row];\n", " options.drawLabel = options.labelAllFeatures || featureDensity > 10;\n", " const pxEnd = Math.ceil((feature.end - bpStart) / bpPerPixel);\n", " const last = lastPxEnd[row];\n", "\n", " if (!last || pxEnd > last || this.config.type === 'spliceJunctions') {\n", " this.render.call(this, feature, bpStart, bpPerPixel, pixelHeight, ctx, options);\n", "\n", " if (this.config.type !== 'spliceJunctions') {\n", " // Ensure a visible gap between features\n", " const pxStart = Math.floor((feature.start - bpStart) / bpPerPixel);\n", "\n", " if (last && pxStart - last <= 0) {\n", " ctx.globalAlpha = 0.5;\n", " IGVGraphics.strokeLine(ctx, pxStart, 0, pxStart, pixelHeight, {\n", " 'strokeStyle': \"rgb(255, 255, 255)\"\n", " });\n", " ctx.globalAlpha = 1.0;\n", " }\n", "\n", " lastPxEnd[row] = pxEnd;\n", " }\n", " }\n", " }\n", " } else {\n", " console.log(\"No feature list\");\n", " }\n", " }\n", "\n", " clickedFeatures(clickState) {\n", " const y = clickState.y - this.margin;\n", " const allFeatures = super.clickedFeatures(clickState);\n", " let row;\n", "\n", " switch (this.displayMode) {\n", " case 'SQUISHED':\n", " row = Math.floor(y / this.squishedRowHeight);\n", " break;\n", "\n", " case 'EXPANDED':\n", " row = Math.floor(y / this.expandedRowHeight);\n", " break;\n", "\n", " default:\n", " row = undefined;\n", " }\n", "\n", " return allFeatures.filter(function (feature) {\n", " return row === undefined || feature.row === undefined || row === feature.row;\n", " });\n", " }\n", " /**\n", " * Return \"popup data\" for feature @ genomic location. Data is an array of key-value pairs\n", " */\n", "\n", "\n", " popupData(clickState, features) {\n", " if (!features) features = this.clickedFeatures(clickState);\n", " const genomicLocation = clickState.genomicLocation;\n", " const data = [];\n", "\n", " for (let feature of features) {\n", " if (this.config.type === 'spliceJunctions') {\n", " if (!feature.isVisible || !feature.attributes) {\n", " continue;\n", " }\n", " }\n", "\n", " const featureData = typeof feature.popupData === \"function\" ? feature.popupData(genomicLocation) : TrackBase.extractPopupData(feature, this.getGenomeId());\n", "\n", " if (featureData) {\n", " if (data.length > 0) {\n", " data.push(\"
\");\n", " }\n", "\n", " Array.prototype.push.apply(data, featureData);\n", " }\n", " }\n", "\n", " return data;\n", " }\n", "\n", " menuItemList() {\n", " const self = this;\n", " const menuItems = [];\n", "\n", " if (this.render === renderSnp) {\n", " [\"function\", \"class\"].forEach(function (colorScheme) {\n", " menuItems.push({\n", " object: $(createCheckbox$1('Color by ' + colorScheme, colorScheme === self.colorBy)),\n", " click: function () {\n", " self.colorBy = colorScheme;\n", " self.trackView.repaintViews();\n", " }\n", " });\n", " });\n", " menuItems.push({\n", " object: $('
')\n", " });\n", " }\n", "\n", " return menuItems;\n", " }\n", "\n", " description() {\n", " // if('snp' === this.type) {\n", " if (renderSnp === this.render) {\n", " let desc = \"\" + this.name + \"
\";\n", " desc += 'Color By Function:
';\n", " desc += 'Red: Coding-Non-Synonymous, Splice Site
';\n", " desc += 'Green: Coding-Synonymous
';\n", " desc += 'Blue: Untranslated
';\n", " desc += 'Black: Intron, Locus, Unknown

';\n", " desc += 'Color By Class:
';\n", " desc += 'Red: Deletion
';\n", " desc += 'Green: MNP
';\n", " desc += 'Blue: Microsatellite, Named
';\n", " desc += 'Black: Indel, Insertion, SNP';\n", " desc += \"\";\n", " return desc;\n", " } else {\n", " return this.name;\n", " }\n", " }\n", "\n", " /**\n", " * Called when the track is removed. Do any needed cleanup here\n", " */\n", " dispose() {\n", " this.trackView = undefined;\n", " }\n", "\n", " }\n", " /**\n", " * Monitors track drag events, updates label position to ensure that they're always visible.\n", " * @param track\n", " */\n", "\n", "\n", " function monitorTrackDrag(track) {\n", " if (track.browser.on) {\n", " track.browser.on('trackdragend', onDragEnd);\n", " track.browser.on('trackremoved', unSubscribe);\n", " }\n", "\n", " function onDragEnd() {\n", " if (!track.trackView || !track.trackView.tile || track.displayMode === \"SQUISHED\") {\n", " return;\n", " }\n", " }\n", "\n", " function unSubscribe(removedTrack) {\n", " if (track.browser.un && track === removedTrack) {\n", " track.browser.un('trackdrag', onDragEnd);\n", " track.browser.un('trackremoved', unSubscribe);\n", " }\n", " }\n", " }\n", " /**\n", " * @param feature\n", " * @param bpStart genomic location of the left edge of the current canvas\n", " * @param xScale scale in base-pairs per pixel\n", " * @returns {{px: number, px1: number, pw: number, h: number, py: number}}\n", " */\n", "\n", "\n", " function calculateFeatureCoordinates(feature, bpStart, xScale) {\n", " let px = (feature.start - bpStart) / xScale;\n", " let px1 = (feature.end - bpStart) / xScale; //px = Math.round((feature.start - bpStart) / xScale),\n", " //px1 = Math.round((feature.end - bpStart) / xScale),\n", "\n", " let pw = px1 - px;\n", "\n", " if (pw < 3) {\n", " pw = 3;\n", " px -= 1.5;\n", " }\n", "\n", " return {\n", " px: px,\n", " px1: px1,\n", " pw: pw\n", " };\n", " }\n", " /**\n", " * Return color for feature. Called in the context of a FeatureTrack instance.\n", " * @param feature\n", " * @returns {string}\n", " */\n", "\n", "\n", " function getColorForFeature(feature) {\n", " let color;\n", "\n", " if (this.altColor && \"-\" === feature.strand) {\n", " color = this.altColor;\n", " } else if (this.color) {\n", " color = this.color; // Explicit setting via menu, or possibly track line if !config.color\n", " } else if (this.config.colorBy) {\n", " const colorByValue = feature[this.config.colorBy.field];\n", "\n", " if (colorByValue) {\n", " color = this.config.colorBy.pallete[colorByValue]; // This is an undocumented option, and its not clear if its used\n", " }\n", " } else if (feature.color) {\n", " color = feature.color; // Explicit color for feature\n", " } else {\n", " color = this.defaultColor; // Track default\n", " }\n", "\n", " if (feature.alpha && feature.alpha !== 1) {\n", " color = IGVColor.addAlpha(color, feature.alpha);\n", " } else if (this.useScore && feature.score && !Number.isNaN(feature.score)) {\n", " // UCSC useScore option, for scores between 0-1000. See https://genome.ucsc.edu/goldenPath/help/customTrack.html#TRACK\n", " const min = this.config.min ? this.config.min : 0; //getViewLimitMin(track);\n", "\n", " const max = this.config.max ? this.config.max : 1000; //getViewLimitMax(track);\n", "\n", " const alpha = getAlpha(min, max, feature.score);\n", " feature.alpha = alpha; // Avoid computing again\n", "\n", " color = IGVColor.addAlpha(color, alpha);\n", " }\n", "\n", " function getAlpha(min, max, score) {\n", " const binWidth = (max - min) / 9;\n", " const binNumber = Math.floor((score - min) / binWidth);\n", " return Math.min(1.0, 0.2 + binNumber * 0.8 / 9);\n", " }\n", "\n", " return color;\n", " }\n", " /**\n", " *\n", " * @param feature\n", " * @param bpStart genomic location of the left edge of the current canvas\n", " * @param xScale scale in base-pairs per pixel\n", " * @param pixelHeight pixel height of the current canvas\n", " * @param ctx the canvas 2d context\n", " * @param options genomic state\n", " */\n", "\n", "\n", " function renderFeature(feature, bpStart, xScale, pixelHeight, ctx, options) {\n", " this.browser;\n", " let color = getColorForFeature.call(this, feature);\n", " ctx.fillStyle = color;\n", " ctx.strokeStyle = color;\n", " let h;\n", " let py;\n", "\n", " if (this.displayMode === \"SQUISHED\" && feature.row !== undefined) {\n", " h = this.featureHeight / 2;\n", " py = this.margin + this.squishedRowHeight * feature.row;\n", " } else if (this.displayMode === \"EXPANDED\" && feature.row !== undefined) {\n", " h = this.featureHeight;\n", " py = this.margin + this.expandedRowHeight * feature.row;\n", " } else {\n", " // collapsed\n", " h = this.featureHeight;\n", " py = this.margin;\n", " }\n", "\n", " const cy = py + h / 2;\n", " const h2 = h / 2;\n", " const py2 = cy - h2 / 2;\n", " const exonCount = feature.exons ? feature.exons.length : 0;\n", " const coord = calculateFeatureCoordinates(feature, bpStart, xScale);\n", " const step = this.arrowSpacing;\n", " const direction = feature.strand === '+' ? 1 : feature.strand === '-' ? -1 : 0;\n", "\n", " if (exonCount === 0) {\n", " // single-exon transcript\n", " ctx.fillRect(coord.px, py, coord.pw, h); // Arrows\n", " // Do not draw if strand is not +/-\n", "\n", " if (direction !== 0) {\n", " ctx.fillStyle = \"white\";\n", " ctx.strokeStyle = \"white\";\n", "\n", " for (let x = coord.px + step / 2; x < coord.px1; x += step) {\n", " // draw arrowheads along central line indicating transcribed orientation\n", " IGVGraphics.strokeLine(ctx, x - direction * 2, cy - 2, x, cy);\n", " IGVGraphics.strokeLine(ctx, x - direction * 2, cy + 2, x, cy);\n", " }\n", "\n", " ctx.fillStyle = color;\n", " ctx.strokeStyle = color;\n", " }\n", " } else {\n", " // multi-exon transcript\n", " IGVGraphics.strokeLine(ctx, coord.px + 1, cy, coord.px1 - 1, cy); // center line for introns\n", "\n", " const pixelWidth = options.pixelWidth;\n", " const xLeft = Math.max(0, coord.px) + step / 2;\n", " const xRight = Math.min(pixelWidth, coord.px1);\n", "\n", " for (let x = xLeft; x < xRight; x += step) {\n", " // draw arrowheads along central line indicating transcribed orientation\n", " IGVGraphics.strokeLine(ctx, x - direction * 2, cy - 2, x, cy);\n", " IGVGraphics.strokeLine(ctx, x - direction * 2, cy + 2, x, cy);\n", " }\n", "\n", " for (let e = 0; e < exonCount; e++) {\n", " // draw the exons\n", " const exon = feature.exons[e];\n", " let ePx = Math.round((exon.start - bpStart) / xScale);\n", " let ePx1 = Math.round((exon.end - bpStart) / xScale);\n", " let ePw = Math.max(1, ePx1 - ePx);\n", " let ePxU;\n", "\n", " if (ePx + ePw < 0) {\n", " continue; // Off the left edge\n", " }\n", "\n", " if (ePx > pixelWidth) {\n", " break; // Off the right edge\n", " }\n", "\n", " if (exon.utr) {\n", " ctx.fillRect(ePx, py2, ePw, h2); // Entire exon is UTR\n", " } else {\n", " if (exon.cdStart) {\n", " ePxU = Math.round((exon.cdStart - bpStart) / xScale);\n", " ctx.fillRect(ePx, py2, ePxU - ePx, h2); // start is UTR\n", "\n", " ePw -= ePxU - ePx;\n", " ePx = ePxU;\n", " }\n", "\n", " if (exon.cdEnd) {\n", " ePxU = Math.round((exon.cdEnd - bpStart) / xScale);\n", " ctx.fillRect(ePxU, py2, ePx1 - ePxU, h2); // start is UTR\n", "\n", " ePw -= ePx1 - ePxU;\n", " ePx1 = ePxU;\n", " }\n", "\n", " ctx.fillRect(ePx, py, ePw, h); // Arrows\n", "\n", " if (ePw > step + 5 && direction !== 0) {\n", " ctx.fillStyle = \"white\";\n", " ctx.strokeStyle = \"white\";\n", "\n", " for (let x = ePx + step / 2; x < ePx1; x += step) {\n", " // draw arrowheads along central line indicating transcribed orientation\n", " IGVGraphics.strokeLine(ctx, x - direction * 2, cy - 2, x, cy);\n", " IGVGraphics.strokeLine(ctx, x - direction * 2, cy + 2, x, cy);\n", " }\n", "\n", " ctx.fillStyle = color;\n", " ctx.strokeStyle = color;\n", " }\n", " }\n", " }\n", " }\n", "\n", " const windowX = Math.round(options.viewportContainerX); // const nLoci = browser.referenceFrameList ? browser.referenceFrameList.length : 1\n", " // const windowX1 = windowX + options.viewportContainerWidth / nLoci;\n", "\n", " const windowX1 = windowX + options.viewportWidth;\n", "\n", " if (options.drawLabel) {\n", " renderFeatureLabel.call(this, ctx, feature, coord.px, coord.px1, py, windowX, windowX1, options.referenceFrame, options);\n", " }\n", " }\n", " /**\n", " * @param ctx the canvas 2d context\n", " * @param feature\n", " * @param featureX feature start x-coordinate\n", " * @param featureX1 feature end x-coordinate\n", " * @param featureY feature y-coordinate\n", " * @param windowX visible window start x-coordinate\n", " * @param windowX1 visible window end x-coordinate\n", " * @param referenceFrame genomic state\n", " * @param options options\n", " */\n", "\n", "\n", " function renderFeatureLabel(ctx, feature, featureX, featureX1, featureY, windowX, windowX1, referenceFrame, options) {\n", " let name = feature.name;\n", " if (name === undefined && feature.gene) name = feature.gene.name;\n", " if (name === undefined) name = feature.id || feature.ID;\n", " if (!name || name === '.') return; // feature outside of viewable window\n", "\n", " let boxX;\n", " let boxX1;\n", "\n", " if (featureX1 < windowX || featureX > windowX1) {\n", " boxX = featureX;\n", " boxX1 = featureX1;\n", " } else {\n", " // center label within visible portion of the feature\n", " boxX = Math.max(featureX, windowX);\n", " boxX1 = Math.min(featureX1, windowX1);\n", " }\n", "\n", " let color = getColorForFeature.call(this, feature);\n", " let geneColor;\n", " let gtexSelection = false;\n", "\n", " if (referenceFrame.selection && GtexUtils.gtexLoaded) {\n", " // TODO -- for gtex, figure out a better way to do this\n", " gtexSelection = true;\n", " geneColor = referenceFrame.selection.colorForGene(name);\n", " }\n", "\n", " if (this.displayMode !== \"SQUISHED\") {\n", " const geneFontStyle = {\n", " textAlign: \"SLANT\" === this.labelDisplayMode ? undefined : 'center',\n", " fillStyle: geneColor || color,\n", " strokeStyle: geneColor || color\n", " };\n", " let transform;\n", "\n", " if (this.displayMode === \"COLLAPSED\" && this.labelDisplayMode === \"SLANT\") {\n", " transform = {\n", " rotate: {\n", " angle: 45\n", " }\n", " };\n", " }\n", "\n", " const labelX = boxX + (boxX1 - boxX) / 2;\n", " const labelY = getFeatureLabelY(featureY, transform);\n", " const textBox = ctx.measureText(name);\n", " const xleft = labelX - textBox.width / 2;\n", " const xright = labelX + textBox.width / 2;\n", "\n", " if (options.labelAllFeatures || xleft > options.rowLastX[feature.row] || gtexSelection) {\n", " options.rowLastX[feature.row] = xright; // This is for compatibility with JuiceboxJS.\n", "\n", " if (options.labelTransform) {\n", " ctx.save();\n", " options.labelTransform(ctx, labelX);\n", " IGVGraphics.fillText(ctx, name, labelX, labelY, geneFontStyle, undefined);\n", " ctx.restore();\n", " } else {\n", " IGVGraphics.fillText(ctx, name, labelX, labelY, geneFontStyle, transform);\n", " }\n", " }\n", " }\n", " }\n", "\n", " function getFeatureLabelY(featureY, transform) {\n", " return transform ? featureY + 20 : featureY + 25;\n", " }\n", " /**\n", " *\n", " * @param feature\n", " * @param bpStart genomic location of the left edge of the current canvas\n", " * @param xScale scale in base-pairs per pixel\n", " * @param pixelHeight pixel height of the current canvas\n", " * @param ctx the canvas 2d context\n", " */\n", "\n", "\n", " function renderFusionJuncSpan(feature, bpStart, xScale, pixelHeight, ctx) {\n", " var py;\n", " var rowHeight = this.displayMode === \"EXPANDED\" ? this.expandedRowHeight : this.squishedRowHeight;\n", "\n", " if (this.display === \"COLLAPSED\") {\n", " py = this.margin;\n", " }\n", "\n", " if (this.displayMode === \"SQUISHED\" && feature.row !== undefined) {\n", " py = this.margin + rowHeight * feature.row;\n", " } else if (this.displayMode === \"EXPANDED\" && feature.row !== undefined) {\n", " py = this.margin + rowHeight * feature.row;\n", " }\n", "\n", " var cy = py + 0.5 * rowHeight;\n", " var topY = cy - 0.5 * rowHeight;\n", " var bottomY = cy + 0.5 * rowHeight; // draw the junction arc\n", "\n", " var junctionLeftPx = Math.round((feature.junction_left - bpStart) / xScale);\n", " var junctionRightPx = Math.round((feature.junction_right - bpStart) / xScale);\n", " ctx.beginPath();\n", " ctx.moveTo(junctionLeftPx, cy);\n", " ctx.bezierCurveTo(junctionLeftPx, topY, junctionRightPx, topY, junctionRightPx, cy);\n", " ctx.lineWidth = 1 + Math.log(feature.num_junction_reads) / Math.log(2);\n", " ctx.strokeStyle = 'blue';\n", " ctx.stroke(); // draw the spanning arcs\n", "\n", " var spanningCoords = feature.spanning_frag_coords;\n", "\n", " for (var i = 0; i < spanningCoords.length; i++) {\n", " var spanningInfo = spanningCoords[i];\n", " var spanLeftPx = Math.round((spanningInfo.left - bpStart) / xScale);\n", " var spanRightPx = Math.round((spanningInfo.right - bpStart) / xScale);\n", " ctx.beginPath();\n", " ctx.moveTo(spanLeftPx, cy);\n", " ctx.bezierCurveTo(spanLeftPx, bottomY, spanRightPx, bottomY, spanRightPx, cy);\n", " ctx.lineWidth = 1;\n", " ctx.strokeStyle = 'purple';\n", " ctx.stroke();\n", " }\n", " }\n", " /**\n", " *\n", " * @param feature\n", " * @param bpStart genomic location of the left edge of the current canvas\n", " * @param xScale scale in base-pairs per pixel\n", " * @param pixelHeight pixel height of the current canvas\n", " * @param ctx the canvas 2d context\n", " */\n", "\n", "\n", " function renderJunctions(feature, bpStart, xScale, pixelHeight, ctx) {\n", " // cache whether this junction is rendered or filtered out. Use later to exclude non-rendered junctions from click detection.\n", " feature.isVisible = false;\n", " const junctionLeftPx = Math.round((feature.start - bpStart) / xScale);\n", " const junctionRightPx = Math.round((feature.end - bpStart) / xScale);\n", " const junctionMiddlePx = (junctionLeftPx + junctionRightPx) / 2;\n", "\n", " if (junctionRightPx - junctionLeftPx <= 3) {\n", " if (junctionMiddlePx in junctionRenderingContext.featureZoomOutTracker) {\n", " return;\n", " }\n", "\n", " junctionRenderingContext.featureZoomOutTracker[junctionMiddlePx] = true;\n", " } // TODO: cache filter and pixel calculations by doing them earlier when features are initially parsed?\n", "\n", "\n", " if (this.config.hideAnnotatedJunctions && feature.attributes.annotated_junction === \"true\") {\n", " return;\n", " }\n", "\n", " if (this.config.hideUnannotatedJunctions && feature.attributes.annotated_junction === \"false\") {\n", " return;\n", " }\n", "\n", " if (this.config.hideMotifs && this.config.hideMotifs.includes(feature.attributes.motif)) {\n", " return;\n", " }\n", "\n", " if (this.config.hideStrand === feature.strand) {\n", " return;\n", " } // check if splice junction is inside viewport\n", "\n", "\n", " if (this.config.minJunctionEndsVisible) {\n", " let numJunctionEndsVisible = 0;\n", "\n", " if (feature.start >= junctionRenderingContext.referenceFrameStart && feature.start <= junctionRenderingContext.referenceFrameEnd) {\n", " numJunctionEndsVisible += 1;\n", " }\n", "\n", " if (feature.end >= junctionRenderingContext.referenceFrameStart && feature.end <= junctionRenderingContext.referenceFrameEnd) {\n", " numJunctionEndsVisible += 1;\n", " }\n", "\n", " if (numJunctionEndsVisible < this.config.minJunctionEndsVisible) {\n", " return;\n", " }\n", " }\n", "\n", " let uniquelyMappedReadCount;\n", " let multiMappedReadCount;\n", " let totalReadCount;\n", "\n", " if (feature.attributes.uniquely_mapped) {\n", " uniquelyMappedReadCount = parseInt(feature.attributes.uniquely_mapped);\n", "\n", " if (uniquelyMappedReadCount < this.config.minUniquelyMappedReads) {\n", " return;\n", " }\n", "\n", " multiMappedReadCount = parseInt(feature.attributes.multi_mapped);\n", " totalReadCount = uniquelyMappedReadCount + multiMappedReadCount;\n", "\n", " if (totalReadCount < this.config.minTotalReads) {\n", " return;\n", " }\n", "\n", " if (totalReadCount > 0 && multiMappedReadCount / totalReadCount > this.config.maxFractionMultiMappedReads) {\n", " return;\n", " }\n", "\n", " if (feature.attributes.maximum_spliced_alignment_overhang && parseInt(feature.attributes.maximum_spliced_alignment_overhang) < this.config.minSplicedAlignmentOverhang) {\n", " return;\n", " }\n", " }\n", "\n", " let numSamplesWithThisJunction;\n", "\n", " if (feature.attributes.num_samples_with_this_junction) {\n", " numSamplesWithThisJunction = parseInt(feature.attributes.num_samples_with_this_junction);\n", "\n", " if (this.config.minSamplesWithThisJunction && numSamplesWithThisJunction < this.config.minSamplesWithThisJunction) {\n", " return;\n", " }\n", "\n", " if (this.config.maxSamplesWithThisJunction && numSamplesWithThisJunction > this.config.maxSamplesWithThisJunction) {\n", " return;\n", " }\n", "\n", " if (feature.attributes.num_samples_total) {\n", " feature.attributes.percent_samples_with_this_junction = 100 * numSamplesWithThisJunction / parseFloat(feature.attributes.num_samples_total);\n", "\n", " if (this.config.minPercentSamplesWithThisJunction) {\n", " if (feature.attributes.percent_samples_with_this_junction < this.config.minPercentSamplesWithThisJunction || feature.attributes.percent_samples_with_this_junction > this.config.maxPercentSamplesWithThisJunction) {\n", " return;\n", " }\n", " }\n", " }\n", " }\n", "\n", " const py = this.margin;\n", " const rowHeight = this.height;\n", " const cy = py + 0.5 * rowHeight;\n", " let topY = py;\n", " const bottomY = py + rowHeight;\n", " const bezierBottomY = bottomY - 10; // draw the junction arc\n", "\n", " const bezierControlLeftPx = (junctionLeftPx + junctionMiddlePx) / 2;\n", " const bezierControlRightPx = (junctionMiddlePx + junctionRightPx) / 2;\n", " let lineWidth = 1;\n", "\n", " if (feature.attributes.line_width) {\n", " lineWidth = parseFloat(feature.attributes.line_width);\n", " } else {\n", " if (this.config.thicknessBasedOn === undefined || this.config.thicknessBasedOn === 'numUniqueReads') {\n", " lineWidth = uniquelyMappedReadCount;\n", " } else if (this.config.thicknessBasedOn === 'numReads') {\n", " lineWidth = totalReadCount;\n", " } else if (this.config.thicknessBasedOn === 'numSamplesWithThisJunction') {\n", " if (numSamplesWithThisJunction !== undefined) {\n", " lineWidth = numSamplesWithThisJunction;\n", " }\n", " }\n", "\n", " lineWidth = 1 + Math.log(lineWidth + 1) / Math.log(12);\n", " }\n", "\n", " let bounceHeight;\n", "\n", " if (this.config.bounceHeightBasedOn === undefined || this.config.bounceHeightBasedOn === 'random') {\n", " // randomly but deterministically stagger topY coordinates to reduce overlap\n", " bounceHeight = (feature.start + feature.end) % 7;\n", " } else if (this.config.bounceHeightBasedOn === 'distance') {\n", " bounceHeight = 6 * (feature.end - feature.start) / (junctionRenderingContext.referenceFrameEnd - junctionRenderingContext.referenceFrameStart);\n", " } else if (this.config.bounceHeightBasedOn === 'thickness') {\n", " bounceHeight = 2 * lineWidth;\n", " }\n", "\n", " topY += rowHeight * Math.max(7 - bounceHeight, 0) / 10;\n", " let color;\n", "\n", " if (feature.attributes.color) {\n", " color = feature.attributes.color; // Explicit setting\n", " } else if (this.config.colorBy === undefined || this.config.colorBy === 'numUniqueReads') {\n", " color = uniquelyMappedReadCount > this.config.colorByNumReadsThreshold ? 'blue' : '#AAAAAA'; // color gradient?\n", " } else if (this.config.colorBy === 'numReads') {\n", " color = totalReadCount > this.config.colorByNumReadsThreshold ? 'blue' : '#AAAAAA';\n", " } else if (this.config.colorBy === 'isAnnotatedJunction') {\n", " color = feature.attributes.annotated_junction === \"true\" ? '#b0b0ec' : 'orange';\n", " } else if (this.config.colorBy === 'strand') {\n", " color = feature.strand === \"+\" ? '#b0b0ec' : '#ecb0b0';\n", " } else if (this.config.colorBy === 'motif') {\n", " color = JUNCTION_MOTIF_PALETTE.getColor(feature.attributes.motif);\n", " } else {\n", " color = '#AAAAAA';\n", " }\n", "\n", " let label = \"\";\n", "\n", " if (feature.attributes.label) {\n", " label = feature.attributes.label.replace(/_/g, \" \");\n", " } else if (this.config.labelWith === undefined || this.config.labelWith === 'uniqueReadCount') {\n", " //default label\n", " label = uniquelyMappedReadCount;\n", " } else if (this.config.labelWith === 'totalReadCount') {\n", " label = totalReadCount;\n", " } else if (this.config.labelWith === 'numSamplesWithThisJunction') {\n", " if (numSamplesWithThisJunction !== undefined) {\n", " label = numSamplesWithThisJunction;\n", " }\n", " } else if (this.config.labelWith === 'percentSamplesWithThisJunction') {\n", " if (feature.attributes.percent_samples_with_this_junction !== undefined) {\n", " label = feature.attributes.percent_samples_with_this_junction.toFixed(0) + '%';\n", " }\n", " } else if (this.config.labelWith === 'motif') {\n", " if (feature.attributes.motif !== undefined) {\n", " label += feature.attributes.motif;\n", " }\n", " }\n", "\n", " if (this.config.labelWithInParen === 'uniqueReadCount') {\n", " label += ' (' + uniquelyMappedReadCount + ')';\n", " } else if (this.config.labelWithInParen === 'totalReadCount') {\n", " label += ' (' + totalReadCount + ')';\n", " } else if (this.config.labelWithInParen === 'multiMappedReadCount') {\n", " if (multiMappedReadCount > 0) {\n", " label += ' (+' + multiMappedReadCount + ')';\n", " }\n", " } else if (this.config.labelWithInParen === 'numSamplesWithThisJunction') {\n", " if (numSamplesWithThisJunction !== undefined) {\n", " label += ' (' + numSamplesWithThisJunction + ')';\n", " }\n", " } else if (this.config.labelWithInParen === 'percentSamplesWithThisJunction') {\n", " if (feature.attributes.percent_samples_with_this_junction !== undefined) {\n", " label += ' (' + feature.attributes.percent_samples_with_this_junction.toFixed(0) + '%)';\n", " }\n", " } else if (this.config.labelWithInParen === 'motif') {\n", " if (feature.attributes.motif !== undefined) {\n", " label += ` ${feature.attributes.motif}`;\n", " }\n", " } // data source: STAR splice junctions (eg. SJ.out.tab file converted to bed).\n", " // .bed \"name\" field used to store unique + multi-mapped read counts, so:\n", " // feature.score: unique spanning read counts\n", " // feature.name: unique + multi-mapped spanning read counts\n", " //example feature: { chr: \"chr17\", start: 39662344, end: 39662803, name: \"59\", row: 0, score: 38, strand: \"+\"}\n", "\n", "\n", " feature.isVisible = true;\n", " ctx.beginPath();\n", " ctx.moveTo(junctionLeftPx, bezierBottomY);\n", " ctx.bezierCurveTo(bezierControlLeftPx, topY, bezierControlRightPx, topY, junctionRightPx, bezierBottomY);\n", " ctx.lineWidth = lineWidth;\n", " ctx.strokeStyle = color;\n", " ctx.stroke();\n", "\n", " const drawArrowhead = (ctx, x, y, size) => {\n", " //TODO draw better arrow heads: https://stackoverflow.com/questions/21052972/curved-thick-arrows-on-canvas\n", " ctx.beginPath();\n", " ctx.moveTo(x, y);\n", " ctx.lineTo(x - size / 2, y - size);\n", " ctx.lineTo(x + size / 2, y - size);\n", " ctx.lineTo(x, y);\n", " ctx.closePath();\n", " ctx.fill();\n", " };\n", "\n", " if (feature.attributes.left_shape || feature.attributes.right_shape) {\n", " ctx.fillStyle = color;\n", " const arrowSize = ctx.lineWidth > 2 ? 10 : 7;\n", "\n", " if (feature.attributes.left_shape) {\n", " drawArrowhead(ctx, junctionLeftPx, bezierBottomY, arrowSize);\n", " }\n", "\n", " if (feature.attributes.right_shape) {\n", " drawArrowhead(ctx, junctionRightPx, bezierBottomY, arrowSize);\n", " }\n", " }\n", "\n", " ctx.fillText(label, junctionMiddlePx - ctx.measureText(label).width / 2, (7 * topY + cy) / 8);\n", " } // SNP constants\n", "\n", "\n", " const codingNonSynonSet = new Set(['nonsense', 'missense', 'stop-loss', 'frameshift', 'cds-indel']);\n", " const codingSynonSet = new Set(['coding-synon']);\n", " const spliceSiteSet = new Set(['splice-3', 'splice-5']);\n", " const untranslatedSet = new Set(['untranslated-5', 'untranslated-3']);\n", " /**\n", " * Renderer for a UCSC snp track\n", " *\n", " * @param snp\n", " * @param bpStart genomic location of the left edge of the current canvas\n", " * @param xScale scale in base-pairs per pixel\n", " * @param pixelHeight pixel height of the current canvas\n", " * @param ctx the canvas 2d context\n", " */\n", "\n", " function renderSnp(snp, bpStart, xScale, pixelHeight, ctx) {\n", " var coord = calculateFeatureCoordinates(snp, bpStart, xScale),\n", " py = this.margin,\n", " h,\n", " colorArrLength = this.snpColors.length,\n", " colorPriority;\n", " h = this.displayMode === \"squished\" ? this.squishedRowHeight : this.expandedRowHeight;\n", "\n", " switch (this.colorBy) {\n", " case 'function':\n", " colorPriority = colorByFunc(snp.func);\n", " break;\n", "\n", " case 'class':\n", " colorPriority = colorByClass(snp['class']);\n", " }\n", "\n", " ctx.fillStyle = this.snpColors[colorPriority];\n", " ctx.fillRect(coord.px, py, coord.pw, h); // Coloring functions, convert a value to a priority\n", "\n", " function colorByFunc(theFunc) {\n", " var priorities;\n", " var funcArray = theFunc.split(','); // possible func values\n", "\n", " priorities = funcArray.map(function (func) {\n", " if (codingNonSynonSet.has(func) || spliceSiteSet.has(func)) {\n", " return colorArrLength - 1;\n", " } else if (codingSynonSet.has(func)) {\n", " return colorArrLength - 2;\n", " } else if (untranslatedSet.has(func)) {\n", " return colorArrLength - 3;\n", " } else {\n", " // locusSet.has(func) || intronSet.has(func)\n", " return 0;\n", " }\n", " });\n", " return priorities.reduce(function (a, b) {\n", " return Math.max(a, b);\n", " });\n", " }\n", "\n", " function colorByClass(cls) {\n", " if (cls === 'deletion') {\n", " return colorArrLength - 1;\n", " } else if (cls === 'mnp') {\n", " return colorArrLength - 2;\n", " } else if (cls === 'microsatellite' || cls === 'named') {\n", " return colorArrLength - 3;\n", " } else {\n", " // cls === 'single' || cls === 'in-del' || cls === 'insertion'\n", " return 0;\n", " }\n", " }\n", " }\n", "\n", " function paintAxis(ctx, pixelWidth, pixelHeight) {\n", " var x1,\n", " x2,\n", " y1,\n", " y2,\n", " a,\n", " b,\n", " reference,\n", " shim,\n", " font = {\n", " 'font': 'normal 10px Arial',\n", " 'textAlign': 'right',\n", " 'strokeStyle': \"black\"\n", " };\n", "\n", " if (undefined === this.dataRange || undefined === this.dataRange.max || undefined === this.dataRange.min) {\n", " return;\n", " }\n", "\n", " IGVGraphics.fillRect(ctx, 0, 0, pixelWidth, pixelHeight, {\n", " 'fillStyle': \"rgb(255, 255, 255)\"\n", " });\n", " reference = 0.95 * pixelWidth;\n", " x1 = reference - 8;\n", " x2 = reference; //shim = 0.5 * 0.125;\n", "\n", " shim = .01;\n", " y1 = y2 = shim * pixelHeight;\n", " a = {\n", " x: x2,\n", " y: y1\n", " }; // tick\n", "\n", " IGVGraphics.strokeLine(ctx, x1, y1, x2, y2, font);\n", " IGVGraphics.fillText(ctx, prettyPrint(this.dataRange.max), x1 + 4, y1 + 12, font); //shim = 0.25 * 0.125;\n", "\n", " y1 = y2 = (1.0 - shim) * pixelHeight;\n", " b = {\n", " x: x2,\n", " y: y1\n", " }; // tick\n", "\n", " IGVGraphics.strokeLine(ctx, x1, y1, x2, y2, font);\n", " IGVGraphics.fillText(ctx, prettyPrint(this.dataRange.min), x1 + 4, y1 - 4, font);\n", " IGVGraphics.strokeLine(ctx, a.x, a.y, b.x, b.y, font);\n", "\n", " function prettyPrint(number) {\n", " // if number >= 100, show whole number\n", " // if >= 1 show 1 significant digits\n", " // if < 1 show 2 significant digits\n", " if (number === 0) {\n", " return \"0\";\n", " } else if (Math.abs(number) >= 10) {\n", " return number.toFixed();\n", " } else if (Math.abs(number) >= 1) {\n", " return number.toFixed(1);\n", " } else {\n", " return number.toFixed(2);\n", " }\n", " }\n", " }\n", "\n", " /*\n", " * The MIT License (MIT)\n", " *\n", " * Copyright (c) 2016-2017 The Regents of the University of California\n", " * Author: Jim Robinson\n", " *\n", " * Permission is hereby granted, free of charge, to any person obtaining a copy\n", " * of this software and associated documentation files (the \"Software\"), to deal\n", " * in the Software without restriction, including without limitation the rights\n", " * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n", " * copies of the Software, and to permit persons to whom the Software is\n", " * furnished to do so, subject to the following conditions:\n", " *\n", " * The above copyright notice and this permission notice shall be included in\n", " * all copies or substantial portions of the Software.\n", " *\n", " *\n", " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n", " * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n", " * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n", " * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n", " * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n", " * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n", " * THE SOFTWARE.\n", " *\n", " *\n", " * This class uses icons from Font Awesome\n", " * Font Awesome Free 5.0.8 by @fontawesome - https://fontawesome.com\n", " * License - https://fontawesome.com/license (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)\n", " */\n", "\n", " function createCheckbox(name, initialState) {\n", " let $container = $('
', {\n", " class: 'igv-menu-popup-check-container'\n", " });\n", " let $div = $('
');\n", " $container.append($div);\n", " let $svg = iconMarkup$1('check', true === initialState ? '#444' : 'transparent');\n", " $div.append($svg);\n", " let $label = $('
'\n", " /*, { class: 'igv-some-label-class' }*/\n", " );\n", " $label.text(name);\n", " $container.append($label);\n", " return $container;\n", " }\n", "\n", " function createIcon$1(name, color) {\n", " return $(iconMarkup$1(name, color));\n", " }\n", "\n", " function iconMarkup$1(name, color) {\n", " color = color || \"currentColor\";\n", " let icon = icons$1[name];\n", "\n", " if (!icon) {\n", " console.error(`No icon named: ${name}`);\n", " icon = icons$1[\"question\"];\n", " }\n", "\n", " let svg = '';\n", " svg += '' + '';\n", " svg += '';\n", " return svg;\n", " }\n", "\n", " const icons$1 = {\n", " \"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\"],\n", " \"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\"],\n", " \"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\"],\n", " \"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-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\"],\n", " \"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\"],\n", " \"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\"],\n", " \"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\"],\n", " \"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\"],\n", " \"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\"],\n", " \"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\"],\n", " \"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\"],\n", " \"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\"],\n", " \"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\"],\n", " \"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\"],\n", " \"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\"],\n", " \"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\"],\n", " \"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\"],\n", " \"square-full\": [512, 512, [], \"f45c\", \"M512 512H0V0h512v512z\"],\n", " \"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\"],\n", " \"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\"],\n", " \"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\"]\n", " };\n", "\n", " /**\n", " * Configure item list for track \"gear\" menu.\n", " * @param trackRenderer\n", " */\n", "\n", " const MenuUtils = {\n", " trackMenuItemList: function (trackPair) {\n", " let menuItems = [];\n", " menuItems.push(trackRenameMenuItem(trackPair));\n", " menuItems.push(\"
\");\n", " menuItems.push(colorPickerMenuItem({\n", " trackRenderer: trackPair,\n", " label: \"Set color\",\n", " option: \"color\"\n", " }));\n", " menuItems.push(unsetColorMenuItem({\n", " trackRenderer: trackPair,\n", " label: \"Unset color\"\n", " }));\n", " const trackMenuItems = trackPair.track.menuItemList();\n", "\n", " if (trackMenuItems && trackMenuItems.length > 0) {\n", " menuItems.push('
');\n", " menuItems.push.apply(menuItems, trackMenuItems);\n", " } // const vizWindowTypes = new Set(['alignment', 'annotation', 'variant', 'eqtl', 'snp']);\n", " // const hasVizWindow = trackRenderer.track.config && trackRenderer.track.config.visibilityWindow !== undefined;\n", " // if (hasVizWindow || vizWindowTypes.has(trackRenderer.track.config.type)) {\n", " // menuItems.push('
');\n", " // menuItems.push(visibilityWindowMenuItem(trackRenderer));\n", " // }\n", "\n", "\n", " if (trackPair.track.removable !== false) {\n", " menuItems.push('
');\n", " menuItems.push(trackRemovalMenuItem(trackPair));\n", " }\n", "\n", " return menuItems;\n", " },\n", " numericDataMenuItems: function (trackPair) {\n", " const menuItems = []; // Data range\n", "\n", " const $e = $('
');\n", " $e.text('Set data range');\n", "\n", " const clickHandler = function () {\n", " const currentDataRange = trackPair.track.dataRange;\n", " trackPair.dataRangeDialog.show({\n", " min: currentDataRange.min || 0,\n", " max: currentDataRange.max\n", " });\n", " };\n", "\n", " menuItems.push({\n", " object: $e,\n", " click: clickHandler\n", " });\n", "\n", " if (trackPair.track.logScale !== undefined) {\n", " menuItems.push({\n", " object: createCheckbox(\"Log scale\", trackPair.track.logScale),\n", " click: () => {\n", " trackPair.track.logScale = !trackPair.track.logScale;\n", " trackPair.repaintViews();\n", " }\n", " });\n", " }\n", "\n", " menuItems.push({\n", " object: createCheckbox(\"Autoscale\", trackPair.track.autoscale),\n", " click: () => {\n", " trackPair.track.autoscale = !trackPair.track.autoscale;\n", " trackPair.repaintViews();\n", " }\n", " });\n", " return menuItems;\n", " }\n", " };\n", "\n", " function trackRemovalMenuItem(trackRenderer) {\n", " var $e, menuClickHandler;\n", " $e = $('
');\n", " $e.text('Remove track');\n", "\n", " menuClickHandler = function menuClickHandler() {\n", " var browser = trackRenderer.browser;\n", " browser.layoutController.removeTrackXYPair(trackRenderer);\n", " };\n", "\n", " return {\n", " object: $e,\n", " click: menuClickHandler\n", " };\n", " }\n", "\n", " function colorPickerMenuItem(_ref) {\n", " let {\n", " trackRenderer,\n", " label,\n", " option\n", " } = _ref;\n", " var $e, clickHandler;\n", " $e = $('
');\n", " $e.text(label);\n", "\n", " clickHandler = function () {\n", " trackRenderer.colorPicker.show();\n", " };\n", "\n", " return {\n", " object: $e,\n", " click: clickHandler\n", " };\n", " }\n", "\n", " function unsetColorMenuItem(_ref2) {\n", " let {\n", " trackRenderer,\n", " label\n", " } = _ref2;\n", " const $e = $('
');\n", " $e.text(label);\n", " return {\n", " object: $e,\n", " click: () => {\n", " trackRenderer.track.color = undefined;\n", " trackRenderer.repaintViews();\n", " }\n", " };\n", " }\n", "\n", " function trackRenameMenuItem(trackRenderer) {\n", " const click = e => {\n", " const callback = value => {\n", " value = value.trim();\n", " value = '' === value || undefined === value ? 'untitled' : value;\n", " trackRenderer.setTrackName(value);\n", " };\n", "\n", " trackRenderer.browser.inputDialog.present({\n", " label: 'Track Name',\n", " value: trackRenderer.track.name,\n", " callback\n", " }, e);\n", " };\n", "\n", " const object = $('
');\n", " object.text('Set track name');\n", " return {\n", " object,\n", " click\n", " };\n", " } // function visibilityWindowMenuItem(trackRenderer) {\n", "\n", " /*\n", " * The MIT License (MIT)\n", " *\n", " * Copyright (c) 2014 Broad Institute\n", " *\n", " * Permission is hereby granted, free of charge, to any person obtaining a copy\n", " * of this software and associated documentation files (the \"Software\"), to deal\n", " * in the Software without restriction, including without limitation the rights\n", " * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n", " * copies of the Software, and to permit persons to whom the Software is\n", " * furnished to do so, subject to the following conditions:\n", " *\n", " * The above copyright notice and this permission notice shall be included in\n", " * all copies or substantial portions of the Software.\n", " *\n", " *\n", " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n", " * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n", " * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n", " * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n", " * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n", " * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n", " * THE SOFTWARE.\n", " */\n", " const DEFAULT_COLOR = \"rgb(150,150,150)\";\n", "\n", " class WigTrack extends TrackBase {\n", " constructor(config, browser) {\n", " super(config, browser);\n", " this.type = \"wig\";\n", " this.height = config.height || 50;\n", " this.featureType = 'numeric';\n", " const format = config.format ? config.format.toLowerCase() : config.format;\n", "\n", " if (\"bigwig\" === format) {\n", " this.featureSource = new BWSource(config, browser.genome);\n", " } else if (\"tdf\" === format) {\n", " this.featureSource = new TDFSource(config, browser.genome);\n", " } else {\n", " this.featureSource = FeatureSource(config, browser.genome);\n", " }\n", "\n", " this.autoscale = config.autoscale || config.max === undefined;\n", "\n", " if (!this.autoscale) {\n", " this.dataRange = {\n", " min: config.min || 0,\n", " max: config.max\n", " };\n", " }\n", "\n", " this.windowFunction = config.windowFunction || \"mean\";\n", " this.paintAxis = paintAxis;\n", " this.graphType = config.graphType || \"bar\";\n", " this.normalize = config.normalize; // boolean, for use with \"TDF\" files\n", "\n", " this.scaleFactor = config.scaleFactor; // optional scale factor, ignored if normalize === true;\n", " }\n", "\n", " async postInit() {\n", " const header = await this.getHeader();\n", " if (header) this.setTrackProperties(header);\n", " }\n", "\n", " async getFeatures(chr, start, end, bpPerPixel) {\n", " const features = await this.featureSource.getFeatures({\n", " chr,\n", " start,\n", " end,\n", " bpPerPixel,\n", " windowFunction: this.windowFunction\n", " });\n", "\n", " if (this.normalize && this.featureSource.normalizationFactor) {\n", " const scaleFactor = this.featureSource.normalizationFactor;\n", "\n", " for (let f of features) {\n", " f.value *= scaleFactor;\n", " }\n", " }\n", "\n", " if (this.scaleFactor) {\n", " const scaleFactor = this.scaleFactor;\n", "\n", " for (let f of features) {\n", " f.value *= scaleFactor;\n", " }\n", " }\n", "\n", " return features;\n", " }\n", "\n", " menuItemList() {\n", " return MenuUtils.numericDataMenuItems(this.trackView);\n", " }\n", "\n", " async getHeader() {\n", " if (typeof this.featureSource.getHeader === \"function\") {\n", " this.header = await this.featureSource.getHeader();\n", " }\n", "\n", " return this.header;\n", " }\n", "\n", " draw(options) {\n", " const features = options.features;\n", " const ctx = options.context;\n", " const bpPerPixel = options.bpPerPixel;\n", " const bpStart = options.bpStart;\n", " const pixelWidth = options.pixelWidth;\n", " const pixelHeight = options.pixelHeight;\n", " const bpEnd = bpStart + pixelWidth * bpPerPixel + 1;\n", " let lastPixelEnd = -1;\n", " let lastValue = -1;\n", " let lastNegValue = 1;\n", " const posColor = this.color || DEFAULT_COLOR;\n", " let baselineColor;\n", "\n", " if (typeof posColor === \"string\" && posColor.startsWith(\"rgb(\")) {\n", " baselineColor = IGVColor.addAlpha(posColor, 0.1);\n", " }\n", "\n", " const yScale = yValue => {\n", " return (this.dataRange.max - yValue) / (this.dataRange.max - this.dataRange.min) * pixelHeight;\n", " };\n", "\n", " if (features && features.length > 0) {\n", " if (this.dataRange.min === undefined) this.dataRange.min = 0; // Max can be less than min if config.min is set but max left to autoscale. If that's the case there is\n", " // nothing to paint.\n", "\n", " if (this.dataRange.max > this.dataRange.min) {\n", " const y0 = this.dataRange.min == 0 ? pixelHeight : yScale(0);\n", "\n", " for (let f of features) {\n", " if (f.end < bpStart) continue;\n", " if (f.start > bpEnd) break;\n", " const x = Math.floor((f.start - bpStart) / bpPerPixel);\n", " if (isNaN(x)) continue;\n", " let y = yScale(f.value);\n", " const rectEnd = Math.ceil((f.end - bpStart) / bpPerPixel);\n", " const width = Math.max(1, rectEnd - x);\n", " let c = f.value < 0 && this.altColor ? this.altColor : posColor;\n", " const color = typeof c === \"function\" ? c(f.value) : c;\n", "\n", " if (this.graphType === \"points\") {\n", " const pointSize = this.config.pointSize || 3;\n", " const px = x + width / 2;\n", " IGVGraphics.fillCircle(ctx, px, y, pointSize / 2, {\n", " \"fillStyle\": color,\n", " \"strokeStyle\": color\n", " });\n", " } else {\n", " let height = y - y0;\n", "\n", " if (Math.abs(height) < 1) {\n", " height = height < 0 ? -1 : 1;\n", " }\n", "\n", " const pixelEnd = x + width;\n", "\n", " if (pixelEnd > lastPixelEnd || f.value >= 0 && f.value > lastValue || f.value < 0 && f.value < lastNegValue) {\n", " IGVGraphics.fillRect(ctx, x, y0, width, height, {\n", " fillStyle: color\n", " });\n", " }\n", "\n", " lastValue = f.value;\n", " lastPixelEnd = pixelEnd;\n", " }\n", " } // If the track includes negative values draw a baseline\n", "\n", "\n", " if (this.dataRange.min < 0) {\n", " const basepx = this.dataRange.max / (this.dataRange.max - this.dataRange.min) * options.pixelHeight;\n", " IGVGraphics.strokeLine(ctx, 0, basepx, options.pixelWidth, basepx, {\n", " strokeStyle: baselineColor\n", " });\n", " }\n", " }\n", " } // Draw guidelines\n", "\n", "\n", " if (this.config.hasOwnProperty('guideLines')) {\n", " for (let line of this.config.guideLines) {\n", " if (line.hasOwnProperty('color') && line.hasOwnProperty('y') && line.hasOwnProperty('dotted')) {\n", " let y = yScale(line.y);\n", " let props = {\n", " 'strokeStyle': line['color'],\n", " 'strokeWidth': 2\n", " };\n", " 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);\n", " }\n", " }\n", " }\n", " }\n", "\n", " popupData(clickState, features) {\n", " // We use the featureCache property rather than method to avoid async load. If the\n", " // feature is not already loaded this won't work, but the user wouldn't be mousing over it either.\n", " if (!features) features = this.clickedFeatures(clickState);\n", "\n", " if (features && features.length > 0) {\n", " let genomicLocation = clickState.genomicLocation;\n", " let referenceFrame = clickState.viewport.referenceFrame;\n", " let popupData = []; // We need some tolerance around genomicLocation, start with +/- 2 pixels\n", "\n", " let tolerance = 2 * referenceFrame.bpPerPixel;\n", " let selectedFeature = binarySearch(features, genomicLocation, tolerance);\n", "\n", " if (selectedFeature) {\n", " let posString = selectedFeature.end - selectedFeature.start === 1 ? numberFormatter(selectedFeature.start + 1) : numberFormatter(selectedFeature.start + 1) + \"-\" + numberFormatter(selectedFeature.end);\n", " popupData.push({\n", " name: \"Position:\",\n", " value: posString\n", " });\n", " popupData.push({\n", " name: \"Value:     \",\n", " value: numberFormatter(selectedFeature.value)\n", " });\n", " }\n", "\n", " return popupData;\n", " } else {\n", " return [];\n", " }\n", " }\n", "\n", " supportsWholeGenome() {\n", " if (typeof this.featureSource.supportsWholeGenome === 'function') {\n", " return this.featureSource.supportsWholeGenome();\n", " } else {\n", " return false;\n", " }\n", " }\n", " /**\n", " * Called when the track is removed. Do any needed cleanup here\n", " */\n", "\n", "\n", " dispose() {\n", " this.trackView = undefined;\n", " }\n", "\n", " }\n", " /**\n", " * Return the closest feature to the genomic position +/- the specified tolerance. Closest is defined\n", " * by the minimum of the distance between position and start or end of the feature.\n", " *\n", " * @param features\n", " * @param position\n", " * @returns {*}\n", " */\n", "\n", "\n", " function binarySearch(features, position, tolerance) {\n", " var startIndex = 0,\n", " stopIndex = features.length - 1,\n", " index = startIndex + stopIndex >> 1,\n", " candidateFeature,\n", " tmp; // Use binary search to get the index of at least 1 feature in the click tolerance bounds\n", "\n", " while (!test(features[index], position, tolerance) && startIndex < stopIndex) {\n", " if (position < features[index].start) {\n", " stopIndex = index - 1;\n", " } else if (position > features[index].end) {\n", " startIndex = index + 1;\n", " }\n", "\n", " index = startIndex + stopIndex >> 1;\n", " }\n", "\n", " if (test(features[index], position, tolerance)) {\n", " candidateFeature = features[index];\n", " if (test(candidateFeature, position, 0)) return candidateFeature; // Else, find closest feature to click\n", "\n", " tmp = index;\n", "\n", " while (tmp-- >= 0) {\n", " if (!test(features[tmp]), tolerance) {\n", " break;\n", " }\n", "\n", " if (test(features[tmp], position, 0)) {\n", " return features[tmp];\n", " }\n", "\n", " if (delta(features[tmp], position) < delta(candidateFeature, position)) {\n", " candidateFeature = features[tmp];\n", " }\n", "\n", " tmp = index;\n", "\n", " while (tmp++ < features.length) {\n", " if (!test(features[tmp]), tolerance) {\n", " break;\n", " }\n", "\n", " if (test(features[tmp], position, 0)) {\n", " return features[tmp];\n", " }\n", "\n", " if (delta(features[tmp], position) < delta(candidateFeature, position)) {\n", " candidateFeature = features[tmp];\n", " }\n", " }\n", " }\n", "\n", " return candidateFeature;\n", " } else {\n", " console.log(position + ' not found!');\n", " return undefined;\n", " }\n", "\n", " function test(feature, position, tolerance) {\n", " return position >= feature.start - tolerance && position <= feature.end + tolerance;\n", " }\n", "\n", " function delta(feature, position) {\n", " return Math.min(Math.abs(feature.start - position), Math.abs(feature.end - position));\n", " }\n", " }\n", "\n", " /*\n", " * The MIT License (MIT)\n", " *\n", " * Copyright (c) 2016 University of California San Diego\n", " * Author: Jim Robinson\n", " *\n", " * Permission is hereby granted, free of charge, to any person obtaining a copy\n", " * of this software and associated documentation files (the \"Software\"), to deal\n", " * in the Software without restriction, including without limitation the rights\n", " * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n", " * copies of the Software, and to permit persons to whom the Software is\n", " * furnished to do so, subject to the following conditions:\n", " *\n", " * The above copyright notice and this permission notice shall be included in\n", " * all copies or substantial portions of the Software.\n", " *\n", " *\n", " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n", " * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n", " * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n", " * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n", " * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n", " * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n", " * THE SOFTWARE.\n", " */\n", " const isString = isString$2;\n", " const DEFAULT_VISIBILITY_WINDOW = 1000000;\n", " const topMargin = 10;\n", "\n", " class VariantTrack extends TrackBase {\n", " constructor(config, browser) {\n", " super(config, browser);\n", " this.visibilityWindow = config.visibilityWindow;\n", " this.displayMode = config.displayMode || \"EXPANDED\"; // COLLAPSED | EXPANDED | SQUISHED\n", "\n", " this.labelDisplayMode = config.labelDisplayMode;\n", " this.variantHeight = config.variantHeight || 10;\n", " this.squishedCallHeight = config.squishedCallHeight || 1;\n", " this.expandedCallHeight = config.expandedCallHeight || 10;\n", " this.expandedVGap = config.expandedVGap !== undefined ? config.expandedVGap : 2;\n", " this.squishedVGap = config.squishedVGap !== undefined ? config.squishedVGap : 1;\n", " this.expandedGroupGap = config.expandedGroupGap || 10;\n", " this.squishedGroupGap = config.squishedGroupGap || 5;\n", " this.featureHeight = config.featureHeight || 14;\n", " this.visibilityWindow = config.visibilityWindow;\n", " this.featureSource = FeatureSource(config, browser.genome);\n", " this.noCallColor = config.noCallColor || \"rgb(245, 245, 245)\";\n", " this.nonRefColor = config.nonRefColor || \"rgb(200, 200, 215)\";\n", " this.mixedColor = config.mixedColor || \"rgb(200, 220, 200)\";\n", " this.homrefColor = config.homrefColor || \"rgb(200, 200, 200)\";\n", " this.homvarColor = config.homvarColor || \"rgb(17,248,254)\";\n", " this.hetvarColor = config.hetvarColor || \"rgb(34,12,253)\";\n", " this.sortDirection = \"ASC\";\n", " this.type = config.type || \"variant\";\n", " this.nRows = 1; // Computed dynamically\n", " }\n", "\n", " async postInit() {\n", " await this.getHeader(); // cricital, don't remove'\n", "\n", " if (undefined === this.visibilityWindow && this.config.indexed !== false) {\n", " const fn = isFile(this.config.url) ? this.config.url.name : this.config.url;\n", "\n", " if (isString(fn) && fn.toLowerCase().includes(\"gnomad\")) {\n", " this.visibilityWindow = 1000; // these are known to be very dense\n", " } else if (this.callSets) {\n", " const length = this.callSets.length;\n", " this.visibilityWindow = Math.max(1000, DEFAULT_VISIBILITY_WINDOW - length * (DEFAULT_VISIBILITY_WINDOW / 100));\n", " } else {\n", " this.visibilityWindow = DEFAULT_VISIBILITY_WINDOW;\n", " }\n", " }\n", "\n", " return this;\n", " }\n", "\n", " supportsWholeGenome() {\n", " return this.config.indexed === false && this.config.supportsWholeGenome !== false;\n", " }\n", "\n", " async getHeader() {\n", " if (this.header) {\n", " return this.header;\n", " } else if (typeof this.featureSource.getHeader === \"function\") {\n", " const header = await this.featureSource.getHeader();\n", "\n", " if (header) {\n", " this.callSets = header.callSets || [];\n", " }\n", "\n", " this.header = header;\n", " return header;\n", " } else {\n", " this.callSets = [];\n", " return undefined;\n", " }\n", " }\n", "\n", " getCallsetsLength() {\n", " return this.callSets.length;\n", " }\n", "\n", " async getFeatures(chr, start, end, bpPerPixel) {\n", " if (this.header === undefined) {\n", " this.header = await this.getHeader();\n", " }\n", "\n", " return this.featureSource.getFeatures({\n", " chr,\n", " start,\n", " end,\n", " bpPerPixel,\n", " visibilityWindow: this.visibilityWindow\n", " });\n", " }\n", " /**\n", " * The required height in pixels required for the track content. This is not the visible track height, which\n", " * can be smaller (with a scrollbar) or larger.\n", " *\n", " * @param features\n", " * @returns {*}\n", " */\n", "\n", "\n", " computePixelHeight(features) {\n", " if (this.displayMode === \"COLLAPSED\") {\n", " this.nRows = 1;\n", " return topMargin + this.variantHeight;\n", " } else {\n", " var maxRow = 0;\n", "\n", " if (features) {\n", " for (let feature of features) {\n", " if (feature.row && feature.row > maxRow) maxRow = feature.row;\n", " }\n", " }\n", "\n", " const vGap = this.displayMode === 'EXPANDED' ? this.expandedVGap : this.squishedVGap;\n", " this.nRows = maxRow + 1;\n", " const h = topMargin + this.nRows * (this.variantHeight + vGap);\n", " this.variantBandHeight = h;\n", " const callHeight = this.displayMode === \"EXPANDED\" ? this.expandedCallHeight : this.squishedCallHeight;\n", " const nCalls = this.getCallsetsLength() * this.nRows;\n", " return h + vGap + (nCalls + 1) * (callHeight + vGap);\n", " }\n", " }\n", "\n", " draw(options) {\n", " const ctx = options.context;\n", " const callSets = this.callSets;\n", " const nCalls = this.getCallsetsLength();\n", " const pixelWidth = options.pixelWidth;\n", " const pixelHeight = options.pixelHeight;\n", " const callHeight = \"EXPANDED\" === this.displayMode ? this.expandedCallHeight : this.squishedCallHeight;\n", " const bpPerPixel = options.bpPerPixel;\n", " const bpStart = options.bpStart;\n", " const bpEnd = bpStart + pixelWidth * bpPerPixel + 1;\n", " IGVGraphics.fillRect(ctx, 0, options.pixelTop, pixelWidth, pixelHeight, {\n", " 'fillStyle': \"rgb(255, 255, 255)\"\n", " });\n", " const vGap = this.displayMode === 'EXPANDED' ? this.expandedVGap : this.squishedVGap;\n", "\n", " if (callSets && nCalls > 0 && \"COLLAPSED\" !== this.displayMode) {\n", " IGVGraphics.strokeLine(ctx, 0, this.variantBandHeight, pixelWidth, this.variantBandHeight, {\n", " strokeStyle: 'rgb(224,224,224) '\n", " });\n", " }\n", "\n", " const featureList = options.features;\n", "\n", " if (featureList) {\n", " for (let variant of featureList) {\n", " if (variant.end < bpStart) continue;\n", " if (variant.start > bpEnd) break;\n", " const py = topMargin + (\"COLLAPSED\" === this.displayMode ? 0 : variant.row * (this.variantHeight + vGap));\n", " const vh = this.variantHeight; // Compute pixel width. Minimum width is 3 pixels, if > 5 pixels create gap between variants\n", "\n", " let px = Math.round((variant.start - bpStart) / bpPerPixel);\n", " let px1 = Math.round((variant.end - bpStart) / bpPerPixel);\n", " let pw = Math.max(1, px1 - px);\n", "\n", " if (pw < 3) {\n", " pw = 3;\n", " px -= 1;\n", " } else if (pw > 5) {\n", " px += 1;\n", " pw -= 2;\n", " }\n", "\n", " if (\"NONVARIANT\" === variant.type) {\n", " ctx.fillStyle = this.nonRefColor;\n", " } else if (\"MIXED\" === variant.type) {\n", " ctx.fillStyle = this.mixedColor;\n", " } else {\n", " ctx.fillStyle = this.color || this.defaultColor;\n", " }\n", "\n", " ctx.fillRect(px, py, pw, vh);\n", "\n", " if (nCalls > 0 && variant.calls && \"COLLAPSED\" !== this.displayMode) {\n", " let callsDrawn = 0;\n", "\n", " for (let callSet of callSets) {\n", " const call = variant.calls[callSet.id];\n", "\n", " if (call) {\n", " const py = this.variantBandHeight + vGap + (callsDrawn + variant.row) * (callHeight + vGap);\n", " let allVar = true; // until proven otherwise\n", "\n", " let allRef = true;\n", " let noCall = false;\n", "\n", " for (let g of call.genotype) {\n", " if ('.' === g) {\n", " noCall = true;\n", " break;\n", " } else {\n", " if (g !== 0) allRef = false;\n", " if (g === 0) allVar = false;\n", " }\n", " }\n", "\n", " if (noCall) {\n", " ctx.fillStyle = this.noCallColor;\n", " } else if (allRef) {\n", " ctx.fillStyle = this.homrefColor;\n", " } else if (allVar) {\n", " ctx.fillStyle = this.homvarColor;\n", " } else {\n", " ctx.fillStyle = this.hetvarColor;\n", " }\n", "\n", " ctx.fillRect(px, py, pw, callHeight);\n", " }\n", "\n", " callsDrawn++;\n", " }\n", " }\n", " }\n", " } else {\n", " console.log(\"No feature list\");\n", " }\n", " }\n", "\n", " /**\n", " * Return \"popup data\" for feature @ genomic location. Data is an array of key-value pairs\n", " */\n", " popupData(clickState, featureList) {\n", " if (!featureList) featureList = this.clickedFeatures(clickState);\n", " const genomicLocation = clickState.genomicLocation;\n", " const genomeID = this.browser.genome.id;\n", " const popupData = [];\n", " const sampleInformation = this.browser.sampleInformation;\n", "\n", " for (let variant of featureList) {\n", " if (popupData.length > 0) {\n", " popupData.push('
');\n", " }\n", "\n", " if (\"COLLAPSED\" === this.displayMode) {\n", " Array.prototype.push.apply(popupData, variant.popupData(genomicLocation, this.type));\n", " } else {\n", " const yOffset = clickState.y;\n", " const vGap = this.displayMode === 'EXPANDED' ? this.expandedVGap : this.squishedVGap;\n", "\n", " if (yOffset <= this.variantBandHeight) {\n", " // Variant\n", " const row = Math.floor((yOffset - topMargin) / (this.variantHeight + vGap));\n", "\n", " if (variant.row === row) {\n", " Array.prototype.push.apply(popupData, variant.popupData(genomicLocation, genomeID), this.type);\n", " }\n", " } else {\n", " // Genotype\n", " const callSets = this.callSets;\n", "\n", " if (callSets && variant.calls) {\n", " const callHeight = this.nRows * (\"SQUISHED\" === this.displayMode ? this.squishedCallHeight : this.expandedCallHeight);\n", " const row = Math.floor((yOffset - this.variantBandHeight) / (callHeight + vGap));\n", "\n", " if (row >= 0 && row < callSets.length) {\n", " const cs = callSets[row];\n", " const call = variant.calls[cs.id];\n", " Array.prototype.push.apply(popupData, extractGenotypePopupData(call, variant, genomeID, sampleInformation));\n", " }\n", " }\n", " }\n", " }\n", " }\n", "\n", " return popupData;\n", " /**\n", " * Genotype popup text.\n", " * @param call\n", " * @param variant\n", " * @returns {Array}\n", " */\n", "\n", " function extractGenotypePopupData(call, variant, genomeId, sampleInformation) {\n", " let gt = '';\n", " const altArray = variant.alternateBases.split(\",\");\n", "\n", " for (let allele of call.genotype) {\n", " if ('.' === allele) {\n", " gt += 'No Call';\n", " break;\n", " } else if (allele === 0) {\n", " gt += variant.referenceBases;\n", " } else {\n", " let alt = altArray[allele - 1].replace(\"<\", \"<\");\n", " gt += alt;\n", " }\n", " }\n", "\n", " let popupData = [];\n", "\n", " if (call.callSetName !== undefined) {\n", " popupData.push({\n", " name: 'Name',\n", " value: call.callSetName\n", " });\n", " }\n", "\n", " popupData.push({\n", " name: 'Genotype',\n", " value: gt\n", " });\n", "\n", " if (call.phaseset !== undefined) {\n", " popupData.push({\n", " name: 'Phase set',\n", " value: call.phaseset\n", " });\n", " }\n", "\n", " if (call.genotypeLikelihood !== undefined) {\n", " popupData.push({\n", " name: 'genotypeLikelihood',\n", " value: call.genotypeLikelihood.toString()\n", " });\n", " }\n", "\n", " if (sampleInformation) {\n", " var attr = sampleInformation.getAttributes(call.callSetName);\n", "\n", " if (attr) {\n", " Object.keys(attr).forEach(function (attrName) {\n", " var displayText = attrName.replace(/([A-Z])/g, \" $1\");\n", " displayText = displayText.charAt(0).toUpperCase() + displayText.slice(1);\n", " popupData.push({\n", " name: displayText,\n", " value: attr[attrName]\n", " });\n", " });\n", " }\n", " }\n", "\n", " var infoKeys = Object.keys(call.info);\n", "\n", " if (infoKeys.length) {\n", " popupData.push(\"
\");\n", " }\n", "\n", " infoKeys.forEach(function (key) {\n", " popupData.push({\n", " name: key,\n", " value: call.info[key]\n", " });\n", " });\n", " let cravatLinks = []; // TODO -- where do these get calculated?\n", "\n", " if (cravatLinks.length > 0) {\n", " popupData.push(\"
\");\n", " popupData = popupData.concat(cravatLinks);\n", " }\n", "\n", " return popupData;\n", " }\n", " } // VariantTrack.prototype.contextMenuItemList = function (clickState) {\n", " //\n", " // const self = this;\n", " // const menuItems = [];\n", " //\n", " // const featureList = this.clickedFeatures(clickState);\n", " //\n", " // if (this.callSets && featureList && featureList.length > 0) {\n", " //\n", " // featureList.forEach(function (variant) {\n", " //\n", " // if ('str' === variant.type) {\n", " //\n", " // menuItems.push({\n", " // label: 'Sort by allele length',\n", " // click: function () {\n", " // sortCallSetsByAlleleLength(self.callSets, variant, self.sortDirection);\n", " // self.sortDirection = (self.sortDirection === \"ASC\") ? \"DESC\" : \"ASC\";\n", " // self.trackView.repaintViews();\n", " // }\n", " // });\n", " //\n", " // }\n", " //\n", " // });\n", " // }\n", " //\n", " //\n", " // function sortCallSetsByAlleleLength(callSets, variant, direction) {\n", " // var d = (direction === \"DESC\") ? 1 : -1;\n", " // Object.keys(callSets).forEach(function (property) {\n", " // callSets[property].sort(function (a, b) {\n", " // var aNan = isNaN(variant.calls[a.id].genotype[0]);\n", " // var bNan = isNaN(variant.calls[b.id].genotype[0]);\n", " // if (aNan && bNan) {\n", " // return 0;\n", " // } else if (aNan) {\n", " // return 1;\n", " // } else if (bNan) {\n", " // return -1;\n", " // } else {\n", " // var a0 = getAlleleString(variant.calls[a.id], variant, 0);\n", " // var a1 = getAlleleString(variant.calls[a.id], variant, 1);\n", " // var b0 = getAlleleString(variant.calls[b.id], variant, 0);\n", " // var b1 = getAlleleString(variant.calls[b.id], variant, 1);\n", " // var result = Math.max(b0.length, b1.length) - Math.max(a0.length, a1.length);\n", " // if (result === 0) {\n", " // result = Math.min(b0.length, b1.length) - Math.min(a0.length, a1.length);\n", " // }\n", " // return d * result;\n", " // }\n", " // });\n", " // });\n", " // }\n", " //\n", " //\n", " // return menuItems;\n", " //\n", " // };\n", "\n", "\n", " menuItemList() {\n", " var self = this,\n", " menuItems = [];\n", " menuItems.push({\n", " object: $('
')\n", " });\n", " [\"COLLAPSED\", \"SQUISHED\", \"EXPANDED\"].forEach(function (displayMode) {\n", " var lut = {\n", " \"COLLAPSED\": \"Collapse\",\n", " \"SQUISHED\": \"Squish\",\n", " \"EXPANDED\": \"Expand\"\n", " };\n", " menuItems.push({\n", " object: createCheckbox(lut[displayMode], displayMode === self.displayMode),\n", " click: function () {\n", " self.displayMode = displayMode;\n", " self.trackView.checkContentHeight();\n", " self.trackView.repaint();\n", " }\n", " });\n", " });\n", " return menuItems;\n", " }\n", "\n", " }\n", "\n", " const tracks = {\n", " 'feature': (config, browser) => {\n", " return new FeatureTrack(config, browser);\n", " },\n", " 'wig': (config, browser) => {\n", " return new WigTrack(config, browser);\n", " },\n", " 'variant': (config, browser) => {\n", " return new VariantTrack(config, browser);\n", " }\n", " };\n", "\n", " const addTrack = function (name, track) {\n", " this.tracks[name] = track;\n", " };\n", "\n", " const getTrack = function (name) {\n", " return this.tracks[name];\n", " };\n", "\n", " var TrackFactory = {\n", " tracks,\n", " addTrack,\n", " getTrack\n", " };\n", "\n", " /*\n", " * @author Jim Robinson Dec-2020\n", " */\n", " const igv = {\n", " async createTrack(config, browser) {\n", " // Resolve function and promise urls\n", " let url = await resolveURL(config.url);\n", "\n", " if (isString$2(url)) {\n", " url = url.trim();\n", " }\n", "\n", " if (url) {\n", " if (config.format) {\n", " config.format = config.format.toLowerCase();\n", " } else {\n", " let filename = config.filename;\n", "\n", " if (!filename) {\n", " filename = await getFilename(url);\n", " }\n", "\n", " config.format = inferFileFormat(filename);\n", " }\n", " }\n", "\n", " let type = config.type;\n", "\n", " if (type && \"bedtype\" !== type) {\n", " type = type.toLowerCase();\n", " } else {\n", " type = inferTrackType(config);\n", "\n", " if (\"bedtype\" === type) {\n", " // Bed files must be read to determine track type\n", " const featureSource = FeatureSource(config, browser.genome);\n", " config._featureSource = featureSource; // This is a temp variable, bit of a hack\n", "\n", " const trackType = await featureSource.trackType();\n", "\n", " if (trackType) {\n", " type = trackType;\n", " } else {\n", " type = \"annotation\";\n", " } // Record in config to make type persistent in session\n", "\n", "\n", " config.type = type;\n", " }\n", " }\n", "\n", " let track;\n", "\n", " switch (type) {\n", " case \"annotation\":\n", " case \"genes\":\n", " case \"fusionjuncspan\":\n", " case \"junctions\":\n", " case \"splicejunctions\":\n", " case \"snp\":\n", " track = TrackFactory.getTrack(\"feature\")(config, browser);\n", " break;\n", "\n", " default:\n", " if (TrackFactory.tracks.hasOwnProperty(type)) {\n", " track = TrackFactory.getTrack(type)(config, browser);\n", " } else {\n", " track = undefined;\n", " }\n", "\n", " }\n", "\n", " if (config.roi && track) {\n", " track.roi = [];\n", "\n", " for (let r of config.roi) {\n", " track.roi.push(new ROI(r, browser.genome));\n", " }\n", " }\n", "\n", " return track;\n", " }\n", "\n", " };\n", "\n", " function div(options) {\n", " return create(\"div\", options);\n", " }\n", "\n", " function create(tag, options) {\n", " const elem = document.createElement(tag);\n", "\n", " if (options) {\n", " if (options.class) {\n", " elem.classList.add(options.class);\n", " }\n", "\n", " if (options.id) {\n", " elem.id = options.id;\n", " }\n", "\n", " if (options.style) {\n", " applyStyle(elem, options.style);\n", " }\n", " }\n", "\n", " return elem;\n", " }\n", "\n", " function hide(elem) {\n", " const cssStyle = getComputedStyle(elem);\n", "\n", " if (cssStyle.display !== \"none\") {\n", " elem._initialDisplay = cssStyle.display;\n", " }\n", "\n", " elem.style.display = \"none\";\n", " }\n", "\n", " function show(elem) {\n", " const currentDisplay = getComputedStyle(elem).display;\n", "\n", " if (currentDisplay === \"none\") {\n", " const d = elem._initialDisplay || \"block\";\n", " elem.style.display = d;\n", " }\n", " }\n", "\n", " function offset(elem) {\n", " // Return zeros for disconnected and hidden (display: none) elements (gh-2310)\n", " // Support: IE <=11 only\n", " // Running getBoundingClientRect on a\n", " // disconnected node in IE throws an error\n", " if (!elem.getClientRects().length) {\n", " return {\n", " top: 0,\n", " left: 0\n", " };\n", " } // Get document-relative position by adding viewport scroll to viewport-relative gBCR\n", "\n", "\n", " const rect = elem.getBoundingClientRect();\n", " const win = elem.ownerDocument.defaultView;\n", " return {\n", " top: rect.top + win.pageYOffset,\n", " left: rect.left + win.pageXOffset\n", " };\n", " }\n", "\n", " function pageCoordinates(e) {\n", " if (e.type.startsWith(\"touch\")) {\n", " const touch = e.touches[0];\n", " return {\n", " x: touch.pageX,\n", " y: touch.pageY\n", " };\n", " } else {\n", " return {\n", " x: e.pageX,\n", " y: e.pageY\n", " };\n", " }\n", " }\n", "\n", " function applyStyle(elem, style) {\n", " for (let key of Object.keys(style)) {\n", " elem.style[key] = style[key];\n", " }\n", " }\n", "\n", " function createIcon(name, color) {\n", " return iconMarkup(name, color);\n", " }\n", "\n", " function iconMarkup(name, color) {\n", " color = color || \"currentColor\";\n", " let icon = icons[name];\n", "\n", " if (!icon) {\n", " console.error(`No icon named: ${name}`);\n", " icon = icons[\"question\"];\n", " }\n", "\n", " const svg = document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\");\n", " svg.setAttributeNS(null, 'viewBox', '0 0 ' + icon[0] + ' ' + icon[1]);\n", " const path = document.createElementNS(\"http://www.w3.org/2000/svg\", \"path\");\n", " path.setAttributeNS(null, 'fill', color);\n", " path.setAttributeNS(null, 'd', icon[4]);\n", " svg.appendChild(path);\n", " return svg;\n", " }\n", "\n", " const icons = {\n", " \"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\"],\n", " \"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\"],\n", " \"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\"],\n", " \"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-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\"],\n", " \"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\"],\n", " \"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\"],\n", " \"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\"],\n", " \"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\"],\n", " \"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\"],\n", " \"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\"],\n", " \"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\"],\n", " \"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\"],\n", " \"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\"],\n", " \"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\"],\n", " \"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\"],\n", " \"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\"],\n", " \"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\"],\n", " \"square-full\": [512, 512, [], \"f45c\", \"M512 512H0V0h512v512z\"],\n", " \"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\"],\n", " \"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\"],\n", " \"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\"]\n", " };\n", "\n", " function attachDialogCloseHandlerWithParent(parent, closeHandler) {\n", " var container = document.createElement(\"div\");\n", " parent.appendChild(container);\n", " container.appendChild(createIcon(\"times\"));\n", " container.addEventListener('click', function (e) {\n", " e.preventDefault();\n", " e.stopPropagation();\n", " closeHandler();\n", " });\n", " }\n", " /**\n", " * @fileoverview Zlib namespace. Zlib の仕様に準拠した圧縮は Zlib.Deflate で実装\n", " * されている. これは Inflate との共存を考慮している為.\n", " */\n", "\n", "\n", " const ZLIB_STREAM_RAW_INFLATE_BUFFER_SIZE$1 = 65000;\n", " var Zlib$1 = {\n", " Huffman: {},\n", " Util: {},\n", " CRC32: {}\n", " };\n", " /**\n", " * Compression Method\n", " * @enum {number}\n", " */\n", "\n", " Zlib$1.CompressionMethod = {\n", " DEFLATE: 8,\n", " RESERVED: 15\n", " };\n", " /**\n", " * @param {Object=} opt_params options.\n", " * @constructor\n", " */\n", "\n", " Zlib$1.Zip = function (opt_params) {\n", " opt_params = opt_params || {};\n", " /** @type {Array.<{\n", " * buffer: !(Array.|Uint8Array),\n", " * option: Object,\n", " * compressed: boolean,\n", " * encrypted: boolean,\n", " * size: number,\n", " * crc32: number\n", " * }>} */\n", "\n", " this.files = [];\n", " /** @type {(Array.|Uint8Array)} */\n", "\n", " this.comment = opt_params['comment'];\n", " /** @type {(Array.|Uint8Array)} */\n", "\n", " this.password;\n", " };\n", " /**\n", " * @enum {number}\n", " */\n", "\n", "\n", " Zlib$1.Zip.CompressionMethod = {\n", " STORE: 0,\n", " DEFLATE: 8\n", " };\n", " /**\n", " * @enum {number}\n", " */\n", "\n", " Zlib$1.Zip.OperatingSystem = {\n", " MSDOS: 0,\n", " UNIX: 3,\n", " MACINTOSH: 7\n", " };\n", " /**\n", " * @enum {number}\n", " */\n", "\n", " Zlib$1.Zip.Flags = {\n", " ENCRYPT: 0x0001,\n", " DESCRIPTOR: 0x0008,\n", " UTF8: 0x0800\n", " };\n", " /**\n", " * @type {Array.}\n", " * @const\n", " */\n", "\n", " Zlib$1.Zip.FileHeaderSignature = [0x50, 0x4b, 0x01, 0x02];\n", " /**\n", " * @type {Array.}\n", " * @const\n", " */\n", "\n", " Zlib$1.Zip.LocalFileHeaderSignature = [0x50, 0x4b, 0x03, 0x04];\n", " /**\n", " * @type {Array.}\n", " * @const\n", " */\n", "\n", " Zlib$1.Zip.CentralDirectorySignature = [0x50, 0x4b, 0x05, 0x06];\n", " /**\n", " * @param {Array.|Uint8Array} input\n", " * @param {Object=} opt_params options.\n", " */\n", "\n", " Zlib$1.Zip.prototype.addFile = function (input, opt_params) {\n", " opt_params = opt_params || {};\n", " /** @type {string} */\n", "\n", " opt_params['filename'];\n", " /** @type {boolean} */\n", "\n", " var compressed;\n", " /** @type {number} */\n", "\n", " var size = input.length;\n", " /** @type {number} */\n", "\n", " var crc32 = 0;\n", "\n", " if (input instanceof Array) {\n", " input = new Uint8Array(input);\n", " } // default\n", "\n", "\n", " if (typeof opt_params['compressionMethod'] !== 'number') {\n", " opt_params['compressionMethod'] = Zlib$1.Zip.CompressionMethod.DEFLATE;\n", " } // その場で圧縮する場合\n", "\n", "\n", " if (opt_params['compress']) {\n", " switch (opt_params['compressionMethod']) {\n", " case Zlib$1.Zip.CompressionMethod.STORE:\n", " break;\n", "\n", " case Zlib$1.Zip.CompressionMethod.DEFLATE:\n", " crc32 = Zlib$1.CRC32.calc(input);\n", " input = this.deflateWithOption(input, opt_params);\n", " compressed = true;\n", " break;\n", "\n", " default:\n", " throw new Error('unknown compression method:' + opt_params['compressionMethod']);\n", " }\n", " }\n", "\n", " this.files.push({\n", " buffer: input,\n", " option: opt_params,\n", " compressed: compressed,\n", " encrypted: false,\n", " size: size,\n", " crc32: crc32\n", " });\n", " };\n", " /**\n", " * @param {(Array.|Uint8Array)} password\n", " */\n", "\n", "\n", " Zlib$1.Zip.prototype.setPassword = function (password) {\n", " this.password = password;\n", " };\n", "\n", " Zlib$1.Zip.prototype.compress = function () {\n", " /** @type {Array.<{\n", " * buffer: !(Array.|Uint8Array),\n", " * option: Object,\n", " * compressed: boolean,\n", " * encrypted: boolean,\n", " * size: number,\n", " * crc32: number\n", " * }>} */\n", " var files = this.files;\n", " /** @type {{\n", " * buffer: !(Array.|Uint8Array),\n", " * option: Object,\n", " * compressed: boolean,\n", " * encrypted: boolean,\n", " * size: number,\n", " * crc32: number\n", " * }} */\n", "\n", " var file;\n", " /** @type {!(Array.|Uint8Array)} */\n", "\n", " var output;\n", " /** @type {number} */\n", "\n", " var op1;\n", " /** @type {number} */\n", "\n", " var op2;\n", " /** @type {number} */\n", "\n", " var op3;\n", " /** @type {number} */\n", "\n", " var localFileSize = 0;\n", " /** @type {number} */\n", "\n", " var centralDirectorySize = 0;\n", " /** @type {number} */\n", "\n", " var endOfCentralDirectorySize;\n", " /** @type {number} */\n", "\n", " var offset;\n", " /** @type {number} */\n", "\n", " var needVersion;\n", " /** @type {number} */\n", "\n", " var flags;\n", " /** @type {Zlib.Zip.CompressionMethod} */\n", "\n", " var compressionMethod;\n", " /** @type {Date} */\n", "\n", " var date;\n", " /** @type {number} */\n", "\n", " var crc32;\n", " /** @type {number} */\n", "\n", " var size;\n", " /** @type {number} */\n", "\n", " var plainSize;\n", " /** @type {number} */\n", "\n", " var filenameLength;\n", " /** @type {number} */\n", "\n", " var extraFieldLength;\n", " /** @type {number} */\n", "\n", " var commentLength;\n", " /** @type {(Array.|Uint8Array)} */\n", "\n", " var filename;\n", " /** @type {(Array.|Uint8Array)} */\n", "\n", " var extraField;\n", " /** @type {(Array.|Uint8Array)} */\n", "\n", " var comment;\n", " /** @type {(Array.|Uint8Array)} */\n", "\n", " var buffer;\n", " /** @type {*} */\n", "\n", " var tmp;\n", " /** @type {Array.|Uint32Array|Object} */\n", "\n", " var key;\n", " /** @type {number} */\n", "\n", " var i;\n", " /** @type {number} */\n", "\n", " var il;\n", " /** @type {number} */\n", "\n", " var j;\n", " /** @type {number} */\n", "\n", " var jl; // ファイルの圧縮\n", "\n", " for (i = 0, il = files.length; i < il; ++i) {\n", " file = files[i];\n", " filenameLength = file.option['filename'] ? file.option['filename'].length : 0;\n", " extraFieldLength = file.option['extraField'] ? file.option['extraField'].length : 0;\n", " commentLength = file.option['comment'] ? file.option['comment'].length : 0; // 圧縮されていなかったら圧縮\n", "\n", " if (!file.compressed) {\n", " // 圧縮前に CRC32 の計算をしておく\n", " file.crc32 = Zlib$1.CRC32.calc(file.buffer);\n", "\n", " switch (file.option['compressionMethod']) {\n", " case Zlib$1.Zip.CompressionMethod.STORE:\n", " break;\n", "\n", " case Zlib$1.Zip.CompressionMethod.DEFLATE:\n", " file.buffer = this.deflateWithOption(file.buffer, file.option);\n", " file.compressed = true;\n", " break;\n", "\n", " default:\n", " throw new Error('unknown compression method:' + file.option['compressionMethod']);\n", " }\n", " } // encryption\n", "\n", "\n", " if (file.option['password'] !== void 0 || this.password !== void 0) {\n", " // init encryption\n", " key = this.createEncryptionKey(file.option['password'] || this.password); // add header\n", "\n", " buffer = file.buffer;\n", " {\n", " tmp = new Uint8Array(buffer.length + 12);\n", " tmp.set(buffer, 12);\n", " buffer = tmp;\n", " }\n", "\n", " for (j = 0; j < 12; ++j) {\n", " buffer[j] = this.encode(key, i === 11 ? file.crc32 & 0xff : Math.random() * 256 | 0);\n", " } // data encryption\n", "\n", "\n", " for (jl = buffer.length; j < jl; ++j) {\n", " buffer[j] = this.encode(key, buffer[j]);\n", " }\n", "\n", " file.buffer = buffer;\n", " } // 必要バッファサイズの計算\n", "\n", "\n", " localFileSize += // local file header\n", " 30 + filenameLength + // file data\n", " file.buffer.length;\n", " centralDirectorySize += // file header\n", " 46 + filenameLength + commentLength;\n", " } // end of central directory\n", "\n", "\n", " endOfCentralDirectorySize = 22 + (this.comment ? this.comment.length : 0);\n", " output = new Uint8Array(localFileSize + centralDirectorySize + endOfCentralDirectorySize);\n", " op1 = 0;\n", " op2 = localFileSize;\n", " op3 = op2 + centralDirectorySize; // ファイルの圧縮\n", "\n", " for (i = 0, il = files.length; i < il; ++i) {\n", " file = files[i];\n", " filenameLength = file.option['filename'] ? file.option['filename'].length : 0;\n", " extraFieldLength = 0; // TODO\n", "\n", " commentLength = file.option['comment'] ? file.option['comment'].length : 0; //-------------------------------------------------------------------------\n", " // local file header & file header\n", " //-------------------------------------------------------------------------\n", "\n", " offset = op1; // signature\n", " // local file header\n", "\n", " output[op1++] = Zlib$1.Zip.LocalFileHeaderSignature[0];\n", " output[op1++] = Zlib$1.Zip.LocalFileHeaderSignature[1];\n", " output[op1++] = Zlib$1.Zip.LocalFileHeaderSignature[2];\n", " output[op1++] = Zlib$1.Zip.LocalFileHeaderSignature[3]; // file header\n", "\n", " output[op2++] = Zlib$1.Zip.FileHeaderSignature[0];\n", " output[op2++] = Zlib$1.Zip.FileHeaderSignature[1];\n", " output[op2++] = Zlib$1.Zip.FileHeaderSignature[2];\n", " output[op2++] = Zlib$1.Zip.FileHeaderSignature[3]; // compressor info\n", "\n", " needVersion = 20;\n", " output[op2++] = needVersion & 0xff;\n", " output[op2++] =\n", " /** @type {Zlib.Zip.OperatingSystem} */\n", " file.option['os'] || Zlib$1.Zip.OperatingSystem.MSDOS; // need version\n", "\n", " output[op1++] = output[op2++] = needVersion & 0xff;\n", " output[op1++] = output[op2++] = needVersion >> 8 & 0xff; // general purpose bit flag\n", "\n", " flags = 0;\n", "\n", " if (file.option['password'] || this.password) {\n", " flags |= Zlib$1.Zip.Flags.ENCRYPT;\n", " }\n", "\n", " output[op1++] = output[op2++] = flags & 0xff;\n", " output[op1++] = output[op2++] = flags >> 8 & 0xff; // compression method\n", "\n", " compressionMethod =\n", " /** @type {Zlib.Zip.CompressionMethod} */\n", " file.option['compressionMethod'];\n", " output[op1++] = output[op2++] = compressionMethod & 0xff;\n", " output[op1++] = output[op2++] = compressionMethod >> 8 & 0xff; // date\n", "\n", " date =\n", " /** @type {(Date|undefined)} */\n", " file.option['date'] || new Date();\n", " output[op1++] = output[op2++] = (date.getMinutes() & 0x7) << 5 | (date.getSeconds() / 2 | 0);\n", " output[op1++] = output[op2++] = date.getHours() << 3 | date.getMinutes() >> 3; //\n", "\n", " output[op1++] = output[op2++] = (date.getMonth() + 1 & 0x7) << 5 | date.getDate();\n", " output[op1++] = output[op2++] = (date.getFullYear() - 1980 & 0x7f) << 1 | date.getMonth() + 1 >> 3; // CRC-32\n", "\n", " crc32 = file.crc32;\n", " output[op1++] = output[op2++] = crc32 & 0xff;\n", " output[op1++] = output[op2++] = crc32 >> 8 & 0xff;\n", " output[op1++] = output[op2++] = crc32 >> 16 & 0xff;\n", " output[op1++] = output[op2++] = crc32 >> 24 & 0xff; // compressed size\n", "\n", " size = file.buffer.length;\n", " output[op1++] = output[op2++] = size & 0xff;\n", " output[op1++] = output[op2++] = size >> 8 & 0xff;\n", " output[op1++] = output[op2++] = size >> 16 & 0xff;\n", " output[op1++] = output[op2++] = size >> 24 & 0xff; // uncompressed size\n", "\n", " plainSize = file.size;\n", " output[op1++] = output[op2++] = plainSize & 0xff;\n", " output[op1++] = output[op2++] = plainSize >> 8 & 0xff;\n", " output[op1++] = output[op2++] = plainSize >> 16 & 0xff;\n", " output[op1++] = output[op2++] = plainSize >> 24 & 0xff; // filename length\n", "\n", " output[op1++] = output[op2++] = filenameLength & 0xff;\n", " output[op1++] = output[op2++] = filenameLength >> 8 & 0xff; // extra field length\n", "\n", " output[op1++] = output[op2++] = extraFieldLength & 0xff;\n", " output[op1++] = output[op2++] = extraFieldLength >> 8 & 0xff; // file comment length\n", "\n", " output[op2++] = commentLength & 0xff;\n", " output[op2++] = commentLength >> 8 & 0xff; // disk number start\n", "\n", " output[op2++] = 0;\n", " output[op2++] = 0; // internal file attributes\n", "\n", " output[op2++] = 0;\n", " output[op2++] = 0; // external file attributes\n", "\n", " output[op2++] = 0;\n", " output[op2++] = 0;\n", " output[op2++] = 0;\n", " output[op2++] = 0; // relative offset of local header\n", "\n", " output[op2++] = offset & 0xff;\n", " output[op2++] = offset >> 8 & 0xff;\n", " output[op2++] = offset >> 16 & 0xff;\n", " output[op2++] = offset >> 24 & 0xff; // filename\n", "\n", " filename = file.option['filename'];\n", "\n", " if (filename) {\n", " {\n", " output.set(filename, op1);\n", " output.set(filename, op2);\n", " op1 += filenameLength;\n", " op2 += filenameLength;\n", " }\n", " } // extra field\n", "\n", "\n", " extraField = file.option['extraField'];\n", "\n", " if (extraField) {\n", " {\n", " output.set(extraField, op1);\n", " output.set(extraField, op2);\n", " op1 += extraFieldLength;\n", " op2 += extraFieldLength;\n", " }\n", " } // comment\n", "\n", "\n", " comment = file.option['comment'];\n", "\n", " if (comment) {\n", " {\n", " output.set(comment, op2);\n", " op2 += commentLength;\n", " }\n", " } //-------------------------------------------------------------------------\n", " // file data\n", " //-------------------------------------------------------------------------\n", "\n", "\n", " {\n", " output.set(file.buffer, op1);\n", " op1 += file.buffer.length;\n", " }\n", " } //-------------------------------------------------------------------------\n", " // end of central directory\n", " //-------------------------------------------------------------------------\n", " // signature\n", "\n", "\n", " output[op3++] = Zlib$1.Zip.CentralDirectorySignature[0];\n", " output[op3++] = Zlib$1.Zip.CentralDirectorySignature[1];\n", " output[op3++] = Zlib$1.Zip.CentralDirectorySignature[2];\n", " output[op3++] = Zlib$1.Zip.CentralDirectorySignature[3]; // number of this disk\n", "\n", " output[op3++] = 0;\n", " output[op3++] = 0; // number of the disk with the start of the central directory\n", "\n", " output[op3++] = 0;\n", " output[op3++] = 0; // total number of entries in the central directory on this disk\n", "\n", " output[op3++] = il & 0xff;\n", " output[op3++] = il >> 8 & 0xff; // total number of entries in the central directory\n", "\n", " output[op3++] = il & 0xff;\n", " output[op3++] = il >> 8 & 0xff; // size of the central directory\n", "\n", " output[op3++] = centralDirectorySize & 0xff;\n", " output[op3++] = centralDirectorySize >> 8 & 0xff;\n", " output[op3++] = centralDirectorySize >> 16 & 0xff;\n", " output[op3++] = centralDirectorySize >> 24 & 0xff; // offset of start of central directory with respect to the starting disk number\n", "\n", " output[op3++] = localFileSize & 0xff;\n", " output[op3++] = localFileSize >> 8 & 0xff;\n", " output[op3++] = localFileSize >> 16 & 0xff;\n", " output[op3++] = localFileSize >> 24 & 0xff; // .ZIP file comment length\n", "\n", " commentLength = this.comment ? this.comment.length : 0;\n", " output[op3++] = commentLength & 0xff;\n", " output[op3++] = commentLength >> 8 & 0xff; // .ZIP file comment\n", "\n", " if (this.comment) {\n", " {\n", " output.set(this.comment, op3);\n", " op3 += commentLength;\n", " }\n", " }\n", "\n", " return output;\n", " };\n", " /**\n", " * @param {!(Array.|Uint8Array)} input\n", " * @param {Object=} opt_params options.\n", " * @return {!(Array.|Uint8Array)}\n", " */\n", "\n", "\n", " Zlib$1.Zip.prototype.deflateWithOption = function (input, opt_params) {\n", " /** @type {Zlib.RawDeflate} */\n", " var deflator = new Zlib$1.RawDeflate(input, opt_params['deflateOption']);\n", " return deflator.compress();\n", " };\n", " /**\n", " * @param {(Array.|Uint32Array)} key\n", " * @return {number}\n", " */\n", "\n", "\n", " Zlib$1.Zip.prototype.getByte = function (key) {\n", " /** @type {number} */\n", " var tmp = key[2] & 0xffff | 2;\n", " return tmp * (tmp ^ 1) >> 8 & 0xff;\n", " };\n", " /**\n", " * @param {(Array.|Uint32Array|Object)} key\n", " * @param {number} n\n", " * @return {number}\n", " */\n", "\n", "\n", " Zlib$1.Zip.prototype.encode = function (key, n) {\n", " /** @type {number} */\n", " var tmp = this.getByte(\n", " /** @type {(Array.|Uint32Array)} */\n", " key);\n", " this.updateKeys(\n", " /** @type {(Array.|Uint32Array)} */\n", " key, n);\n", " return tmp ^ n;\n", " };\n", " /**\n", " * @param {(Array.|Uint32Array)} key\n", " * @param {number} n\n", " */\n", "\n", "\n", " Zlib$1.Zip.prototype.updateKeys = function (key, n) {\n", " key[0] = Zlib$1.CRC32.single(key[0], n);\n", " key[1] = (((key[1] + (key[0] & 0xff)) * 20173 >>> 0) * 6681 >>> 0) + 1 >>> 0;\n", " key[2] = Zlib$1.CRC32.single(key[2], key[1] >>> 24);\n", " };\n", " /**\n", " * @param {(Array.|Uint8Array)} password\n", " * @return {!(Array.|Uint32Array|Object)}\n", " */\n", "\n", "\n", " Zlib$1.Zip.prototype.createEncryptionKey = function (password) {\n", " /** @type {!(Array.|Uint32Array)} */\n", " var key = [305419896, 591751049, 878082192];\n", " /** @type {number} */\n", "\n", " var i;\n", " /** @type {number} */\n", "\n", " var il;\n", " {\n", " key = new Uint32Array(key);\n", " }\n", "\n", " for (i = 0, il = password.length; i < il; ++i) {\n", " this.updateKeys(key, password[i] & 0xff);\n", " }\n", "\n", " return key;\n", " };\n", " /**\n", " * build huffman table from length list.\n", " * @param {!(Array.|Uint8Array)} lengths length list.\n", " * @return {!Array} huffman table.\n", " */\n", "\n", "\n", " Zlib$1.Huffman.buildHuffmanTable = function (lengths) {\n", " /** @type {number} length list size. */\n", " var listSize = lengths.length;\n", " /** @type {number} max code length for table size. */\n", "\n", " var maxCodeLength = 0;\n", " /** @type {number} min code length for table size. */\n", "\n", " var minCodeLength = Number.POSITIVE_INFINITY;\n", " /** @type {number} table size. */\n", "\n", " var size;\n", " /** @type {!(Array|Uint8Array)} huffman code table. */\n", "\n", " var table;\n", " /** @type {number} bit length. */\n", "\n", " var bitLength;\n", " /** @type {number} huffman code. */\n", "\n", " var code;\n", " /**\n", " * サイズが 2^maxlength 個のテーブルを埋めるためのスキップ長.\n", " * @type {number} skip length for table filling.\n", " */\n", "\n", " var skip;\n", " /** @type {number} reversed code. */\n", "\n", " var reversed;\n", " /** @type {number} reverse temp. */\n", "\n", " var rtemp;\n", " /** @type {number} loop counter. */\n", "\n", " var i;\n", " /** @type {number} loop limit. */\n", "\n", " var il;\n", " /** @type {number} loop counter. */\n", "\n", " var j;\n", " /** @type {number} table value. */\n", "\n", " var value; // Math.max は遅いので最長の値は for-loop で取得する\n", "\n", " for (i = 0, il = listSize; i < il; ++i) {\n", " if (lengths[i] > maxCodeLength) {\n", " maxCodeLength = lengths[i];\n", " }\n", "\n", " if (lengths[i] < minCodeLength) {\n", " minCodeLength = lengths[i];\n", " }\n", " }\n", "\n", " size = 1 << maxCodeLength;\n", " table = new Uint32Array(size); // ビット長の短い順からハフマン符号を割り当てる\n", "\n", " for (bitLength = 1, code = 0, skip = 2; bitLength <= maxCodeLength;) {\n", " for (i = 0; i < listSize; ++i) {\n", " if (lengths[i] === bitLength) {\n", " // ビットオーダーが逆になるためビット長分並びを反転する\n", " for (reversed = 0, rtemp = code, j = 0; j < bitLength; ++j) {\n", " reversed = reversed << 1 | rtemp & 1;\n", " rtemp >>= 1;\n", " } // 最大ビット長をもとにテーブルを作るため、\n", " // 最大ビット長以外では 0 / 1 どちらでも良い箇所ができる\n", " // そのどちらでも良い場所は同じ値で埋めることで\n", " // 本来のビット長以上のビット数取得しても問題が起こらないようにする\n", "\n", "\n", " value = bitLength << 16 | i;\n", "\n", " for (j = reversed; j < size; j += skip) {\n", " table[j] = value;\n", " }\n", "\n", " ++code;\n", " }\n", " } // 次のビット長へ\n", "\n", "\n", " ++bitLength;\n", " code <<= 1;\n", " skip <<= 1;\n", " }\n", "\n", " return [table, maxCodeLength, minCodeLength];\n", " }; //-----------------------------------------------------------------------------\n", "\n", " /** @define {number} buffer block size. */\n", "\n", "\n", " var ZLIB_RAW_INFLATE_BUFFER_SIZE$1 = 0x8000; // [ 0x8000 >= ZLIB_BUFFER_BLOCK_SIZE ]\n", " //-----------------------------------------------------------------------------\n", "\n", " var buildHuffmanTable$1 = Zlib$1.Huffman.buildHuffmanTable;\n", " /**\n", " * @constructor\n", " * @param {!(Uint8Array|Array.)} input input buffer.\n", " * @param {Object} opt_params option parameter.\n", " *\n", " * opt_params は以下のプロパティを指定する事ができます。\n", " * - index: input buffer の deflate コンテナの開始位置.\n", " * - blockSize: バッファのブロックサイズ.\n", " * - bufferType: Zlib.RawInflate.BufferType の値によってバッファの管理方法を指定する.\n", " * - resize: 確保したバッファが実際の大きさより大きかった場合に切り詰める.\n", " */\n", "\n", " Zlib$1.RawInflate = function (input, opt_params) {\n", " /** @type {!(Array.|Uint8Array)} inflated buffer */\n", " this.buffer;\n", " /** @type {!Array.<(Array.|Uint8Array)>} */\n", "\n", " this.blocks = [];\n", " /** @type {number} block size. */\n", "\n", " this.bufferSize = ZLIB_RAW_INFLATE_BUFFER_SIZE$1;\n", " /** @type {!number} total output buffer pointer. */\n", "\n", " this.totalpos = 0;\n", " /** @type {!number} input buffer pointer. */\n", "\n", " this.ip = 0;\n", " /** @type {!number} bit stream reader buffer. */\n", "\n", " this.bitsbuf = 0;\n", " /** @type {!number} bit stream reader buffer size. */\n", "\n", " this.bitsbuflen = 0;\n", " /** @type {!(Array.|Uint8Array)} input buffer. */\n", "\n", " this.input = new Uint8Array(input);\n", " /** @type {!(Uint8Array|Array.)} output buffer. */\n", "\n", " this.output;\n", " /** @type {!number} output buffer pointer. */\n", "\n", " this.op;\n", " /** @type {boolean} is final block flag. */\n", "\n", " this.bfinal = false;\n", " /** @type {Zlib.RawInflate.BufferType} buffer management. */\n", "\n", " this.bufferType = Zlib$1.RawInflate.BufferType.ADAPTIVE;\n", " /** @type {boolean} resize flag for memory size optimization. */\n", "\n", " this.resize = false; // option parameters\n", "\n", " if (opt_params || !(opt_params = {})) {\n", " if (opt_params['index']) {\n", " this.ip = opt_params['index'];\n", " }\n", "\n", " if (opt_params['bufferSize']) {\n", " this.bufferSize = opt_params['bufferSize'];\n", " }\n", "\n", " if (opt_params['bufferType']) {\n", " this.bufferType = opt_params['bufferType'];\n", " }\n", "\n", " if (opt_params['resize']) {\n", " this.resize = opt_params['resize'];\n", " }\n", " } // initialize\n", "\n", "\n", " switch (this.bufferType) {\n", " case Zlib$1.RawInflate.BufferType.BLOCK:\n", " this.op = Zlib$1.RawInflate.MaxBackwardLength;\n", " this.output = new Uint8Array(Zlib$1.RawInflate.MaxBackwardLength + this.bufferSize + Zlib$1.RawInflate.MaxCopyLength);\n", " break;\n", "\n", " case Zlib$1.RawInflate.BufferType.ADAPTIVE:\n", " this.op = 0;\n", " this.output = new Uint8Array(this.bufferSize);\n", " break;\n", "\n", " default:\n", " throw new Error('invalid inflate mode');\n", " }\n", " };\n", " /**\n", " * @enum {number}\n", " */\n", "\n", "\n", " Zlib$1.RawInflate.BufferType = {\n", " BLOCK: 0,\n", " ADAPTIVE: 1\n", " };\n", " /**\n", " * decompress.\n", " * @return {!(Uint8Array|Array.)} inflated buffer.\n", " */\n", "\n", " Zlib$1.RawInflate.prototype.decompress = function () {\n", " while (!this.bfinal) {\n", " this.parseBlock();\n", " }\n", "\n", " switch (this.bufferType) {\n", " case Zlib$1.RawInflate.BufferType.BLOCK:\n", " return this.concatBufferBlock();\n", "\n", " case Zlib$1.RawInflate.BufferType.ADAPTIVE:\n", " return this.concatBufferDynamic();\n", "\n", " default:\n", " throw new Error('invalid inflate mode');\n", " }\n", " };\n", " /**\n", " * @const\n", " * @type {number} max backward length for LZ77.\n", " */\n", "\n", "\n", " Zlib$1.RawInflate.MaxBackwardLength = 32768;\n", " /**\n", " * @const\n", " * @type {number} max copy length for LZ77.\n", " */\n", "\n", " Zlib$1.RawInflate.MaxCopyLength = 258;\n", " /**\n", " * huffman order\n", " * @const\n", " * @type {!(Array.|Uint8Array)}\n", " */\n", "\n", " Zlib$1.RawInflate.Order = function (table) {\n", " return new Uint16Array(table);\n", " }([16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]);\n", " /**\n", " * huffman length code table.\n", " * @const\n", " * @type {!(Array.|Uint16Array)}\n", " */\n", "\n", "\n", " Zlib$1.RawInflate.LengthCodeTable = function (table) {\n", " return new Uint16Array(table);\n", " }([0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000d, 0x000f, 0x0011, 0x0013, 0x0017, 0x001b, 0x001f, 0x0023, 0x002b, 0x0033, 0x003b, 0x0043, 0x0053, 0x0063, 0x0073, 0x0083, 0x00a3, 0x00c3, 0x00e3, 0x0102, 0x0102, 0x0102]);\n", " /**\n", " * huffman length extra-bits table.\n", " * @const\n", " * @type {!(Array.|Uint8Array)}\n", " */\n", "\n", "\n", " Zlib$1.RawInflate.LengthExtraTable = function (table) {\n", " return new Uint8Array(table);\n", " }([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, 0, 0]);\n", " /**\n", " * huffman dist code table.\n", " * @const\n", " * @type {!(Array.|Uint16Array)}\n", " */\n", "\n", "\n", " Zlib$1.RawInflate.DistCodeTable = function (table) {\n", " return new Uint16Array(table);\n", " }([0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0007, 0x0009, 0x000d, 0x0011, 0x0019, 0x0021, 0x0031, 0x0041, 0x0061, 0x0081, 0x00c1, 0x0101, 0x0181, 0x0201, 0x0301, 0x0401, 0x0601, 0x0801, 0x0c01, 0x1001, 0x1801, 0x2001, 0x3001, 0x4001, 0x6001]);\n", " /**\n", " * huffman dist extra-bits table.\n", " * @const\n", " * @type {!(Array.|Uint8Array)}\n", " */\n", "\n", "\n", " Zlib$1.RawInflate.DistExtraTable = function (table) {\n", " return new Uint8Array(table);\n", " }([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]);\n", " /**\n", " * fixed huffman length code table\n", " * @const\n", " * @type {!Array}\n", " */\n", "\n", "\n", " Zlib$1.RawInflate.FixedLiteralLengthTable = function (table) {\n", " return table;\n", " }(function () {\n", " var lengths = new Uint8Array(288);\n", " var i, il;\n", "\n", " for (i = 0, il = lengths.length; i < il; ++i) {\n", " lengths[i] = i <= 143 ? 8 : i <= 255 ? 9 : i <= 279 ? 7 : 8;\n", " }\n", "\n", " return buildHuffmanTable$1(lengths);\n", " }());\n", " /**\n", " * fixed huffman distance code table\n", " * @const\n", " * @type {!Array}\n", " */\n", "\n", "\n", " Zlib$1.RawInflate.FixedDistanceTable = function (table) {\n", " return table;\n", " }(function () {\n", " var lengths = new Uint8Array(30);\n", " var i, il;\n", "\n", " for (i = 0, il = lengths.length; i < il; ++i) {\n", " lengths[i] = 5;\n", " }\n", "\n", " return buildHuffmanTable$1(lengths);\n", " }());\n", " /**\n", " * parse deflated block.\n", " */\n", "\n", "\n", " Zlib$1.RawInflate.prototype.parseBlock = function () {\n", " /** @type {number} header */\n", " var hdr = this.readBits(3); // BFINAL\n", "\n", " if (hdr & 0x1) {\n", " this.bfinal = true;\n", " } // BTYPE\n", "\n", "\n", " hdr >>>= 1;\n", "\n", " switch (hdr) {\n", " // uncompressed\n", " case 0:\n", " this.parseUncompressedBlock();\n", " break;\n", " // fixed huffman\n", "\n", " case 1:\n", " this.parseFixedHuffmanBlock();\n", " break;\n", " // dynamic huffman\n", "\n", " case 2:\n", " this.parseDynamicHuffmanBlock();\n", " break;\n", " // reserved or other\n", "\n", " default:\n", " throw new Error('unknown BTYPE: ' + hdr);\n", " }\n", " };\n", " /**\n", " * read inflate bits\n", " * @param {number} length bits length.\n", " * @return {number} read bits.\n", " */\n", "\n", "\n", " Zlib$1.RawInflate.prototype.readBits = function (length) {\n", " var bitsbuf = this.bitsbuf;\n", " var bitsbuflen = this.bitsbuflen;\n", " var input = this.input;\n", " var ip = this.ip;\n", " /** @type {number} */\n", "\n", " var inputLength = input.length;\n", " /** @type {number} input and output byte. */\n", "\n", " var octet; // input byte\n", "\n", " if (ip + (length - bitsbuflen + 7 >> 3) >= inputLength) {\n", " throw new Error('input buffer is broken');\n", " } // not enough buffer\n", "\n", "\n", " while (bitsbuflen < length) {\n", " bitsbuf |= input[ip++] << bitsbuflen;\n", " bitsbuflen += 8;\n", " } // output byte\n", "\n", "\n", " octet = bitsbuf &\n", " /* MASK */\n", " (1 << length) - 1;\n", " bitsbuf >>>= length;\n", " bitsbuflen -= length;\n", " this.bitsbuf = bitsbuf;\n", " this.bitsbuflen = bitsbuflen;\n", " this.ip = ip;\n", " return octet;\n", " };\n", " /**\n", " * read huffman code using table\n", " * @param {!(Array.|Uint8Array|Uint16Array)} table huffman code table.\n", " * @return {number} huffman code.\n", " */\n", "\n", "\n", " Zlib$1.RawInflate.prototype.readCodeByTable = function (table) {\n", " var bitsbuf = this.bitsbuf;\n", " var bitsbuflen = this.bitsbuflen;\n", " var input = this.input;\n", " var ip = this.ip;\n", " /** @type {number} */\n", "\n", " var inputLength = input.length;\n", " /** @type {!(Array.|Uint8Array)} huffman code table */\n", "\n", " var codeTable = table[0];\n", " /** @type {number} */\n", "\n", " var maxCodeLength = table[1];\n", " /** @type {number} code length & code (16bit, 16bit) */\n", "\n", " var codeWithLength;\n", " /** @type {number} code bits length */\n", "\n", " var codeLength; // not enough buffer\n", "\n", " while (bitsbuflen < maxCodeLength) {\n", " if (ip >= inputLength) {\n", " break;\n", " }\n", "\n", " bitsbuf |= input[ip++] << bitsbuflen;\n", " bitsbuflen += 8;\n", " } // read max length\n", "\n", "\n", " codeWithLength = codeTable[bitsbuf & (1 << maxCodeLength) - 1];\n", " codeLength = codeWithLength >>> 16;\n", "\n", " if (codeLength > bitsbuflen) {\n", " throw new Error('invalid code length: ' + codeLength);\n", " }\n", "\n", " this.bitsbuf = bitsbuf >> codeLength;\n", " this.bitsbuflen = bitsbuflen - codeLength;\n", " this.ip = ip;\n", " return codeWithLength & 0xffff;\n", " };\n", " /**\n", " * parse uncompressed block.\n", " */\n", "\n", "\n", " Zlib$1.RawInflate.prototype.parseUncompressedBlock = function () {\n", " var input = this.input;\n", " var ip = this.ip;\n", " var output = this.output;\n", " var op = this.op;\n", " /** @type {number} */\n", "\n", " var inputLength = input.length;\n", " /** @type {number} block length */\n", "\n", " var len;\n", " /** @type {number} number for check block length */\n", "\n", " var nlen;\n", " /** @type {number} output buffer length */\n", "\n", " var olength = output.length;\n", " /** @type {number} copy counter */\n", "\n", " var preCopy; // skip buffered header bits\n", "\n", " this.bitsbuf = 0;\n", " this.bitsbuflen = 0; // len\n", "\n", " if (ip + 1 >= inputLength) {\n", " throw new Error('invalid uncompressed block header: LEN');\n", " }\n", "\n", " len = input[ip++] | input[ip++] << 8; // nlen\n", "\n", " if (ip + 1 >= inputLength) {\n", " throw new Error('invalid uncompressed block header: NLEN');\n", " }\n", "\n", " nlen = input[ip++] | input[ip++] << 8; // check len & nlen\n", "\n", " if (len === ~nlen) {\n", " throw new Error('invalid uncompressed block header: length verify');\n", " } // check size\n", "\n", "\n", " if (ip + len > input.length) {\n", " throw new Error('input buffer is broken');\n", " } // expand buffer\n", "\n", "\n", " switch (this.bufferType) {\n", " case Zlib$1.RawInflate.BufferType.BLOCK:\n", " // pre copy\n", " while (op + len > output.length) {\n", " preCopy = olength - op;\n", " len -= preCopy;\n", " {\n", " output.set(input.subarray(ip, ip + preCopy), op);\n", " op += preCopy;\n", " ip += preCopy;\n", " }\n", " this.op = op;\n", " output = this.expandBufferBlock();\n", " op = this.op;\n", " }\n", "\n", " break;\n", "\n", " case Zlib$1.RawInflate.BufferType.ADAPTIVE:\n", " while (op + len > output.length) {\n", " output = this.expandBufferAdaptive({\n", " fixRatio: 2\n", " });\n", " }\n", "\n", " break;\n", "\n", " default:\n", " throw new Error('invalid inflate mode');\n", " } // copy\n", "\n", "\n", " {\n", " output.set(input.subarray(ip, ip + len), op);\n", " op += len;\n", " ip += len;\n", " }\n", " this.ip = ip;\n", " this.op = op;\n", " this.output = output;\n", " };\n", " /**\n", " * parse fixed huffman block.\n", " */\n", "\n", "\n", " Zlib$1.RawInflate.prototype.parseFixedHuffmanBlock = function () {\n", " switch (this.bufferType) {\n", " case Zlib$1.RawInflate.BufferType.ADAPTIVE:\n", " this.decodeHuffmanAdaptive(Zlib$1.RawInflate.FixedLiteralLengthTable, Zlib$1.RawInflate.FixedDistanceTable);\n", " break;\n", "\n", " case Zlib$1.RawInflate.BufferType.BLOCK:\n", " this.decodeHuffmanBlock(Zlib$1.RawInflate.FixedLiteralLengthTable, Zlib$1.RawInflate.FixedDistanceTable);\n", " break;\n", "\n", " default:\n", " throw new Error('invalid inflate mode');\n", " }\n", " };\n", " /**\n", " * parse dynamic huffman block.\n", " */\n", "\n", "\n", " Zlib$1.RawInflate.prototype.parseDynamicHuffmanBlock = function () {\n", " /** @type {number} number of literal and length codes. */\n", " var hlit = this.readBits(5) + 257;\n", " /** @type {number} number of distance codes. */\n", "\n", " var hdist = this.readBits(5) + 1;\n", " /** @type {number} number of code lengths. */\n", "\n", " var hclen = this.readBits(4) + 4;\n", " /** @type {!(Uint8Array|Array.)} code lengths. */\n", "\n", " var codeLengths = new Uint8Array(Zlib$1.RawInflate.Order.length);\n", " /** @type {!Array} code lengths table. */\n", "\n", " var codeLengthsTable;\n", " /** @type {!(Uint8Array|Array.)} literal and length code table. */\n", "\n", " var litlenTable;\n", " /** @type {!(Uint8Array|Array.)} distance code table. */\n", "\n", " var distTable;\n", " /** @type {!(Uint8Array|Array.)} code length table. */\n", "\n", " var lengthTable;\n", " /** @type {number} */\n", "\n", " var code;\n", " /** @type {number} */\n", "\n", " var prev;\n", " /** @type {number} */\n", "\n", " var repeat;\n", " /** @type {number} loop counter. */\n", "\n", " var i;\n", " /** @type {number} loop limit. */\n", "\n", " var il; // decode code lengths\n", "\n", " for (i = 0; i < hclen; ++i) {\n", " codeLengths[Zlib$1.RawInflate.Order[i]] = this.readBits(3);\n", " } // decode length table\n", "\n", "\n", " codeLengthsTable = buildHuffmanTable$1(codeLengths);\n", " lengthTable = new Uint8Array(hlit + hdist);\n", "\n", " for (i = 0, il = hlit + hdist; i < il;) {\n", " code = this.readCodeByTable(codeLengthsTable);\n", "\n", " switch (code) {\n", " case 16:\n", " repeat = 3 + this.readBits(2);\n", "\n", " while (repeat--) {\n", " lengthTable[i++] = prev;\n", " }\n", "\n", " break;\n", "\n", " case 17:\n", " repeat = 3 + this.readBits(3);\n", "\n", " while (repeat--) {\n", " lengthTable[i++] = 0;\n", " }\n", "\n", " prev = 0;\n", " break;\n", "\n", " case 18:\n", " repeat = 11 + this.readBits(7);\n", "\n", " while (repeat--) {\n", " lengthTable[i++] = 0;\n", " }\n", "\n", " prev = 0;\n", " break;\n", "\n", " default:\n", " lengthTable[i++] = code;\n", " prev = code;\n", " break;\n", " }\n", " }\n", "\n", " litlenTable = buildHuffmanTable$1(lengthTable.subarray(0, hlit));\n", " distTable = buildHuffmanTable$1(lengthTable.subarray(hlit));\n", "\n", " switch (this.bufferType) {\n", " case Zlib$1.RawInflate.BufferType.ADAPTIVE:\n", " this.decodeHuffmanAdaptive(litlenTable, distTable);\n", " break;\n", "\n", " case Zlib$1.RawInflate.BufferType.BLOCK:\n", " this.decodeHuffmanBlock(litlenTable, distTable);\n", " break;\n", "\n", " default:\n", " throw new Error('invalid inflate mode');\n", " }\n", " };\n", " /**\n", " * decode huffman code\n", " * @param {!(Array.|Uint16Array)} litlen literal and length code table.\n", " * @param {!(Array.|Uint8Array)} dist distination code table.\n", " */\n", "\n", "\n", " Zlib$1.RawInflate.prototype.decodeHuffmanBlock = function (litlen, dist) {\n", " var output = this.output;\n", " var op = this.op;\n", " this.currentLitlenTable = litlen;\n", " /** @type {number} output position limit. */\n", "\n", " var olength = output.length - Zlib$1.RawInflate.MaxCopyLength;\n", " /** @type {number} huffman code. */\n", "\n", " var code;\n", " /** @type {number} table index. */\n", "\n", " var ti;\n", " /** @type {number} huffman code distination. */\n", "\n", " var codeDist;\n", " /** @type {number} huffman code length. */\n", "\n", " var codeLength;\n", " var lengthCodeTable = Zlib$1.RawInflate.LengthCodeTable;\n", " var lengthExtraTable = Zlib$1.RawInflate.LengthExtraTable;\n", " var distCodeTable = Zlib$1.RawInflate.DistCodeTable;\n", " var distExtraTable = Zlib$1.RawInflate.DistExtraTable;\n", "\n", " while ((code = this.readCodeByTable(litlen)) !== 256) {\n", " // literal\n", " if (code < 256) {\n", " if (op >= olength) {\n", " this.op = op;\n", " output = this.expandBufferBlock();\n", " op = this.op;\n", " }\n", "\n", " output[op++] = code;\n", " continue;\n", " } // length code\n", "\n", "\n", " ti = code - 257;\n", " codeLength = lengthCodeTable[ti];\n", "\n", " if (lengthExtraTable[ti] > 0) {\n", " codeLength += this.readBits(lengthExtraTable[ti]);\n", " } // dist code\n", "\n", "\n", " code = this.readCodeByTable(dist);\n", " codeDist = distCodeTable[code];\n", "\n", " if (distExtraTable[code] > 0) {\n", " codeDist += this.readBits(distExtraTable[code]);\n", " } // lz77 decode\n", "\n", "\n", " if (op >= olength) {\n", " this.op = op;\n", " output = this.expandBufferBlock();\n", " op = this.op;\n", " }\n", "\n", " while (codeLength--) {\n", " output[op] = output[op++ - codeDist];\n", " }\n", " }\n", "\n", " while (this.bitsbuflen >= 8) {\n", " this.bitsbuflen -= 8;\n", " this.ip--;\n", " }\n", "\n", " this.op = op;\n", " };\n", " /**\n", " * decode huffman code (adaptive)\n", " * @param {!(Array.|Uint16Array)} litlen literal and length code table.\n", " * @param {!(Array.|Uint8Array)} dist distination code table.\n", " */\n", "\n", "\n", " Zlib$1.RawInflate.prototype.decodeHuffmanAdaptive = function (litlen, dist) {\n", " var output = this.output;\n", " var op = this.op;\n", " this.currentLitlenTable = litlen;\n", " /** @type {number} output position limit. */\n", "\n", " var olength = output.length;\n", " /** @type {number} huffman code. */\n", "\n", " var code;\n", " /** @type {number} table index. */\n", "\n", " var ti;\n", " /** @type {number} huffman code distination. */\n", "\n", " var codeDist;\n", " /** @type {number} huffman code length. */\n", "\n", " var codeLength;\n", " var lengthCodeTable = Zlib$1.RawInflate.LengthCodeTable;\n", " var lengthExtraTable = Zlib$1.RawInflate.LengthExtraTable;\n", " var distCodeTable = Zlib$1.RawInflate.DistCodeTable;\n", " var distExtraTable = Zlib$1.RawInflate.DistExtraTable;\n", "\n", " while ((code = this.readCodeByTable(litlen)) !== 256) {\n", " // literal\n", " if (code < 256) {\n", " if (op >= olength) {\n", " output = this.expandBufferAdaptive();\n", " olength = output.length;\n", " }\n", "\n", " output[op++] = code;\n", " continue;\n", " } // length code\n", "\n", "\n", " ti = code - 257;\n", " codeLength = lengthCodeTable[ti];\n", "\n", " if (lengthExtraTable[ti] > 0) {\n", " codeLength += this.readBits(lengthExtraTable[ti]);\n", " } // dist code\n", "\n", "\n", " code = this.readCodeByTable(dist);\n", " codeDist = distCodeTable[code];\n", "\n", " if (distExtraTable[code] > 0) {\n", " codeDist += this.readBits(distExtraTable[code]);\n", " } // lz77 decode\n", "\n", "\n", " if (op + codeLength > olength) {\n", " output = this.expandBufferAdaptive();\n", " olength = output.length;\n", " }\n", "\n", " while (codeLength--) {\n", " output[op] = output[op++ - codeDist];\n", " }\n", " }\n", "\n", " while (this.bitsbuflen >= 8) {\n", " this.bitsbuflen -= 8;\n", " this.ip--;\n", " }\n", "\n", " this.op = op;\n", " };\n", " /**\n", " * expand output buffer.\n", " * @param {Object=} opt_param option parameters.\n", " * @return {!(Array.|Uint8Array)} output buffer.\n", " */\n", "\n", "\n", " Zlib$1.RawInflate.prototype.expandBufferBlock = function (opt_param) {\n", " /** @type {!(Array.|Uint8Array)} store buffer. */\n", " var buffer = new Uint8Array(this.op - Zlib$1.RawInflate.MaxBackwardLength);\n", " /** @type {number} backward base point */\n", "\n", " var backward = this.op - Zlib$1.RawInflate.MaxBackwardLength;\n", " var output = this.output; // copy to output buffer\n", "\n", " {\n", " buffer.set(output.subarray(Zlib$1.RawInflate.MaxBackwardLength, buffer.length));\n", " }\n", " this.blocks.push(buffer);\n", " this.totalpos += buffer.length; // copy to backward buffer\n", "\n", " {\n", " output.set(output.subarray(backward, backward + Zlib$1.RawInflate.MaxBackwardLength));\n", " }\n", " this.op = Zlib$1.RawInflate.MaxBackwardLength;\n", " return output;\n", " };\n", " /**\n", " * expand output buffer. (adaptive)\n", " * @param {Object=} opt_param option parameters.\n", " * @return {!(Array.|Uint8Array)} output buffer pointer.\n", " */\n", "\n", "\n", " Zlib$1.RawInflate.prototype.expandBufferAdaptive = function (opt_param) {\n", " /** @type {!(Array.|Uint8Array)} store buffer. */\n", " var buffer;\n", " /** @type {number} expantion ratio. */\n", "\n", " var ratio = this.input.length / this.ip + 1 | 0;\n", " /** @type {number} maximum number of huffman code. */\n", "\n", " var maxHuffCode;\n", " /** @type {number} new output buffer size. */\n", "\n", " var newSize;\n", " /** @type {number} max inflate size. */\n", "\n", " var maxInflateSize;\n", " var input = this.input;\n", " var output = this.output;\n", "\n", " if (opt_param) {\n", " if (typeof opt_param.fixRatio === 'number') {\n", " ratio = opt_param.fixRatio;\n", " }\n", "\n", " if (typeof opt_param.addRatio === 'number') {\n", " ratio += opt_param.addRatio;\n", " }\n", " } // calculate new buffer size\n", "\n", "\n", " if (ratio < 2) {\n", " maxHuffCode = (input.length - this.ip) / this.currentLitlenTable[2];\n", " maxInflateSize = maxHuffCode / 2 * 258 | 0;\n", " newSize = maxInflateSize < output.length ? output.length + maxInflateSize : output.length << 1;\n", " } else {\n", " newSize = output.length * ratio;\n", " } // buffer expantion\n", "\n", "\n", " {\n", " buffer = new Uint8Array(newSize);\n", " buffer.set(output);\n", " }\n", " this.output = buffer;\n", " return this.output;\n", " };\n", " /**\n", " * concat output buffer.\n", " * @return {!(Array.|Uint8Array)} output buffer.\n", " */\n", "\n", "\n", " Zlib$1.RawInflate.prototype.concatBufferBlock = function () {\n", " /** @type {number} buffer pointer. */\n", " var pos = 0;\n", " /** @type {number} buffer pointer. */\n", "\n", " var limit = this.totalpos + (this.op - Zlib$1.RawInflate.MaxBackwardLength);\n", " /** @type {!(Array.|Uint8Array)} output block array. */\n", "\n", " var output = this.output;\n", " /** @type {!Array} blocks array. */\n", "\n", " var blocks = this.blocks;\n", " /** @type {!(Array.|Uint8Array)} output block array. */\n", "\n", " var block;\n", " /** @type {!(Array.|Uint8Array)} output buffer. */\n", "\n", " var buffer = new Uint8Array(limit);\n", " /** @type {number} loop counter. */\n", "\n", " var i;\n", " /** @type {number} loop limiter. */\n", "\n", " var il;\n", " /** @type {number} loop counter. */\n", "\n", " var j;\n", " /** @type {number} loop limiter. */\n", "\n", " var jl; // single buffer\n", "\n", " if (blocks.length === 0) {\n", " return this.output.subarray(Zlib$1.RawInflate.MaxBackwardLength, this.op);\n", " } // copy to buffer\n", "\n", "\n", " for (i = 0, il = blocks.length; i < il; ++i) {\n", " block = blocks[i];\n", "\n", " for (j = 0, jl = block.length; j < jl; ++j) {\n", " buffer[pos++] = block[j];\n", " }\n", " } // current buffer\n", "\n", "\n", " for (i = Zlib$1.RawInflate.MaxBackwardLength, il = this.op; i < il; ++i) {\n", " buffer[pos++] = output[i];\n", " }\n", "\n", " this.blocks = [];\n", " this.buffer = buffer;\n", " return this.buffer;\n", " };\n", " /**\n", " * concat output buffer. (dynamic)\n", " * @return {!(Array.|Uint8Array)} output buffer.\n", " */\n", "\n", "\n", " Zlib$1.RawInflate.prototype.concatBufferDynamic = function () {\n", " /** @type {Array.|Uint8Array} output buffer. */\n", " var buffer;\n", " var op = this.op;\n", " {\n", " if (this.resize) {\n", " buffer = new Uint8Array(op);\n", " buffer.set(this.output.subarray(0, op));\n", " } else {\n", " buffer = this.output.subarray(0, op);\n", " }\n", " }\n", " this.buffer = buffer;\n", " return this.buffer;\n", " };\n", "\n", " var buildHuffmanTable$1 = Zlib$1.Huffman.buildHuffmanTable;\n", " /**\n", " * @param {!(Uint8Array|Array.)} input input buffer.\n", " * @param {number} ip input buffer pointer.\n", " * @param {number=} opt_buffersize buffer block size.\n", " * @constructor\n", " */\n", "\n", " Zlib$1.RawInflateStream = function (input, ip, opt_buffersize) {\n", " /** @type {!Array.<(Array|Uint8Array)>} */\n", " this.blocks = [];\n", " /** @type {number} block size. */\n", "\n", " this.bufferSize = opt_buffersize ? opt_buffersize : ZLIB_STREAM_RAW_INFLATE_BUFFER_SIZE$1;\n", " /** @type {!number} total output buffer pointer. */\n", "\n", " this.totalpos = 0;\n", " /** @type {!number} input buffer pointer. */\n", "\n", " this.ip = ip === void 0 ? 0 : ip;\n", " /** @type {!number} bit stream reader buffer. */\n", "\n", " this.bitsbuf = 0;\n", " /** @type {!number} bit stream reader buffer size. */\n", "\n", " this.bitsbuflen = 0;\n", " /** @type {!(Array|Uint8Array)} input buffer. */\n", "\n", " this.input = new Uint8Array(input);\n", " /** @type {!(Uint8Array|Array)} output buffer. */\n", "\n", " this.output = new Uint8Array(this.bufferSize);\n", " /** @type {!number} output buffer pointer. */\n", "\n", " this.op = 0;\n", " /** @type {boolean} is final block flag. */\n", "\n", " this.bfinal = false;\n", " /** @type {number} uncompressed block length. */\n", "\n", " this.blockLength;\n", " /** @type {boolean} resize flag for memory size optimization. */\n", "\n", " this.resize = false;\n", " /** @type {Array} */\n", "\n", " this.litlenTable;\n", " /** @type {Array} */\n", "\n", " this.distTable;\n", " /** @type {number} */\n", "\n", " this.sp = 0; // stream pointer\n", "\n", " /** @type {Zlib.RawInflateStream.Status} */\n", "\n", " this.status = Zlib$1.RawInflateStream.Status.INITIALIZED; //\n", " // backup\n", " //\n", "\n", " /** @type {!number} */\n", "\n", " this.ip_;\n", " /** @type {!number} */\n", "\n", " this.bitsbuflen_;\n", " /** @type {!number} */\n", "\n", " this.bitsbuf_;\n", " };\n", " /**\n", " * @enum {number}\n", " */\n", "\n", "\n", " Zlib$1.RawInflateStream.BlockType = {\n", " UNCOMPRESSED: 0,\n", " FIXED: 1,\n", " DYNAMIC: 2\n", " };\n", " /**\n", " * @enum {number}\n", " */\n", "\n", " Zlib$1.RawInflateStream.Status = {\n", " INITIALIZED: 0,\n", " BLOCK_HEADER_START: 1,\n", " BLOCK_HEADER_END: 2,\n", " BLOCK_BODY_START: 3,\n", " BLOCK_BODY_END: 4,\n", " DECODE_BLOCK_START: 5,\n", " DECODE_BLOCK_END: 6\n", " };\n", " /**\n", " * decompress.\n", " * @return {!(Uint8Array|Array)} inflated buffer.\n", " */\n", "\n", " Zlib$1.RawInflateStream.prototype.decompress = function (newInput, ip) {\n", " /** @type {boolean} */\n", " var stop = false;\n", "\n", " if (newInput !== void 0) {\n", " this.input = newInput;\n", " }\n", "\n", " if (ip !== void 0) {\n", " this.ip = ip;\n", " } // decompress\n", "\n", "\n", " while (!stop) {\n", " switch (this.status) {\n", " // block header\n", " case Zlib$1.RawInflateStream.Status.INITIALIZED:\n", " case Zlib$1.RawInflateStream.Status.BLOCK_HEADER_START:\n", " if (this.readBlockHeader() < 0) {\n", " stop = true;\n", " }\n", "\n", " break;\n", " // block body\n", "\n", " case Zlib$1.RawInflateStream.Status.BLOCK_HEADER_END:\n", " /* FALLTHROUGH */\n", "\n", " case Zlib$1.RawInflateStream.Status.BLOCK_BODY_START:\n", " switch (this.currentBlockType) {\n", " case Zlib$1.RawInflateStream.BlockType.UNCOMPRESSED:\n", " if (this.readUncompressedBlockHeader() < 0) {\n", " stop = true;\n", " }\n", "\n", " break;\n", "\n", " case Zlib$1.RawInflateStream.BlockType.FIXED:\n", " if (this.parseFixedHuffmanBlock() < 0) {\n", " stop = true;\n", " }\n", "\n", " break;\n", "\n", " case Zlib$1.RawInflateStream.BlockType.DYNAMIC:\n", " if (this.parseDynamicHuffmanBlock() < 0) {\n", " stop = true;\n", " }\n", "\n", " break;\n", " }\n", "\n", " break;\n", " // decode data\n", "\n", " case Zlib$1.RawInflateStream.Status.BLOCK_BODY_END:\n", " case Zlib$1.RawInflateStream.Status.DECODE_BLOCK_START:\n", " switch (this.currentBlockType) {\n", " case Zlib$1.RawInflateStream.BlockType.UNCOMPRESSED:\n", " if (this.parseUncompressedBlock() < 0) {\n", " stop = true;\n", " }\n", "\n", " break;\n", "\n", " case Zlib$1.RawInflateStream.BlockType.FIXED:\n", " /* FALLTHROUGH */\n", "\n", " case Zlib$1.RawInflateStream.BlockType.DYNAMIC:\n", " if (this.decodeHuffman() < 0) {\n", " stop = true;\n", " }\n", "\n", " break;\n", " }\n", "\n", " break;\n", "\n", " case Zlib$1.RawInflateStream.Status.DECODE_BLOCK_END:\n", " if (this.bfinal) {\n", " stop = true;\n", " } else {\n", " this.status = Zlib$1.RawInflateStream.Status.INITIALIZED;\n", " }\n", "\n", " break;\n", " }\n", " }\n", "\n", " return this.concatBuffer();\n", " };\n", " /**\n", " * @const\n", " * @type {number} max backward length for LZ77.\n", " */\n", "\n", "\n", " Zlib$1.RawInflateStream.MaxBackwardLength = 32768;\n", " /**\n", " * @const\n", " * @type {number} max copy length for LZ77.\n", " */\n", "\n", " Zlib$1.RawInflateStream.MaxCopyLength = 258;\n", " /**\n", " * huffman order\n", " * @const\n", " * @type {!(Array.|Uint8Array)}\n", " */\n", "\n", " Zlib$1.RawInflateStream.Order = function (table) {\n", " return new Uint16Array(table);\n", " }([16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]);\n", " /**\n", " * huffman length code table.\n", " * @const\n", " * @type {!(Array.|Uint16Array)}\n", " */\n", "\n", "\n", " Zlib$1.RawInflateStream.LengthCodeTable = function (table) {\n", " return new Uint16Array(table);\n", " }([0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000d, 0x000f, 0x0011, 0x0013, 0x0017, 0x001b, 0x001f, 0x0023, 0x002b, 0x0033, 0x003b, 0x0043, 0x0053, 0x0063, 0x0073, 0x0083, 0x00a3, 0x00c3, 0x00e3, 0x0102, 0x0102, 0x0102]);\n", " /**\n", " * huffman length extra-bits table.\n", " * @const\n", " * @type {!(Array.|Uint8Array)}\n", " */\n", "\n", "\n", " Zlib$1.RawInflateStream.LengthExtraTable = function (table) {\n", " return new Uint8Array(table);\n", " }([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, 0, 0]);\n", " /**\n", " * huffman dist code table.\n", " * @const\n", " * @type {!(Array.|Uint16Array)}\n", " */\n", "\n", "\n", " Zlib$1.RawInflateStream.DistCodeTable = function (table) {\n", " return new Uint16Array(table);\n", " }([0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0007, 0x0009, 0x000d, 0x0011, 0x0019, 0x0021, 0x0031, 0x0041, 0x0061, 0x0081, 0x00c1, 0x0101, 0x0181, 0x0201, 0x0301, 0x0401, 0x0601, 0x0801, 0x0c01, 0x1001, 0x1801, 0x2001, 0x3001, 0x4001, 0x6001]);\n", " /**\n", " * huffman dist extra-bits table.\n", " * @const\n", " * @type {!(Array.|Uint8Array)}\n", " */\n", "\n", "\n", " Zlib$1.RawInflateStream.DistExtraTable = function (table) {\n", " return new Uint8Array(table);\n", " }([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]);\n", " /**\n", " * fixed huffman length code table\n", " * @const\n", " * @type {!Array}\n", " */\n", "\n", "\n", " Zlib$1.RawInflateStream.FixedLiteralLengthTable = function (table) {\n", " return table;\n", " }(function () {\n", " var lengths = new Uint8Array(288);\n", " var i, il;\n", "\n", " for (i = 0, il = lengths.length; i < il; ++i) {\n", " lengths[i] = i <= 143 ? 8 : i <= 255 ? 9 : i <= 279 ? 7 : 8;\n", " }\n", "\n", " return buildHuffmanTable$1(lengths);\n", " }());\n", " /**\n", " * fixed huffman distance code table\n", " * @const\n", " * @type {!Array}\n", " */\n", "\n", "\n", " Zlib$1.RawInflateStream.FixedDistanceTable = function (table) {\n", " return table;\n", " }(function () {\n", " var lengths = new Uint8Array(30);\n", " var i, il;\n", "\n", " for (i = 0, il = lengths.length; i < il; ++i) {\n", " lengths[i] = 5;\n", " }\n", "\n", " return buildHuffmanTable$1(lengths);\n", " }());\n", " /**\n", " * parse deflated block.\n", " */\n", "\n", "\n", " Zlib$1.RawInflateStream.prototype.readBlockHeader = function () {\n", " /** @type {number} header */\n", " var hdr;\n", " this.status = Zlib$1.RawInflateStream.Status.BLOCK_HEADER_START;\n", " this.save_();\n", "\n", " if ((hdr = this.readBits(3)) < 0) {\n", " this.restore_();\n", " return -1;\n", " } // BFINAL\n", "\n", "\n", " if (hdr & 0x1) {\n", " this.bfinal = true;\n", " } // BTYPE\n", "\n", "\n", " hdr >>>= 1;\n", "\n", " switch (hdr) {\n", " case 0:\n", " // uncompressed\n", " this.currentBlockType = Zlib$1.RawInflateStream.BlockType.UNCOMPRESSED;\n", " break;\n", "\n", " case 1:\n", " // fixed huffman\n", " this.currentBlockType = Zlib$1.RawInflateStream.BlockType.FIXED;\n", " break;\n", "\n", " case 2:\n", " // dynamic huffman\n", " this.currentBlockType = Zlib$1.RawInflateStream.BlockType.DYNAMIC;\n", " break;\n", "\n", " default:\n", " // reserved or other\n", " throw new Error('unknown BTYPE: ' + hdr);\n", " }\n", "\n", " this.status = Zlib$1.RawInflateStream.Status.BLOCK_HEADER_END;\n", " };\n", " /**\n", " * read inflate bits\n", " * @param {number} length bits length.\n", " * @return {number} read bits.\n", " */\n", "\n", "\n", " Zlib$1.RawInflateStream.prototype.readBits = function (length) {\n", " var bitsbuf = this.bitsbuf;\n", " var bitsbuflen = this.bitsbuflen;\n", " var input = this.input;\n", " var ip = this.ip;\n", " /** @type {number} input and output byte. */\n", "\n", " var octet; // not enough buffer\n", "\n", " while (bitsbuflen < length) {\n", " // input byte\n", " if (input.length <= ip) {\n", " return -1;\n", " }\n", "\n", " octet = input[ip++]; // concat octet\n", "\n", " bitsbuf |= octet << bitsbuflen;\n", " bitsbuflen += 8;\n", " } // output byte\n", "\n", "\n", " octet = bitsbuf &\n", " /* MASK */\n", " (1 << length) - 1;\n", " bitsbuf >>>= length;\n", " bitsbuflen -= length;\n", " this.bitsbuf = bitsbuf;\n", " this.bitsbuflen = bitsbuflen;\n", " this.ip = ip;\n", " return octet;\n", " };\n", " /**\n", " * read huffman code using table\n", " * @param {Array} table huffman code table.\n", " * @return {number} huffman code.\n", " */\n", "\n", "\n", " Zlib$1.RawInflateStream.prototype.readCodeByTable = function (table) {\n", " var bitsbuf = this.bitsbuf;\n", " var bitsbuflen = this.bitsbuflen;\n", " var input = this.input;\n", " var ip = this.ip;\n", " /** @type {!(Array|Uint8Array)} huffman code table */\n", "\n", " var codeTable = table[0];\n", " /** @type {number} */\n", "\n", " var maxCodeLength = table[1];\n", " /** @type {number} input byte */\n", "\n", " var octet;\n", " /** @type {number} code length & code (16bit, 16bit) */\n", "\n", " var codeWithLength;\n", " /** @type {number} code bits length */\n", "\n", " var codeLength; // not enough buffer\n", "\n", " while (bitsbuflen < maxCodeLength) {\n", " if (input.length <= ip) {\n", " return -1;\n", " }\n", "\n", " octet = input[ip++];\n", " bitsbuf |= octet << bitsbuflen;\n", " bitsbuflen += 8;\n", " } // read max length\n", "\n", "\n", " codeWithLength = codeTable[bitsbuf & (1 << maxCodeLength) - 1];\n", " codeLength = codeWithLength >>> 16;\n", "\n", " if (codeLength > bitsbuflen) {\n", " throw new Error('invalid code length: ' + codeLength);\n", " }\n", "\n", " this.bitsbuf = bitsbuf >> codeLength;\n", " this.bitsbuflen = bitsbuflen - codeLength;\n", " this.ip = ip;\n", " return codeWithLength & 0xffff;\n", " };\n", " /**\n", " * read uncompressed block header\n", " */\n", "\n", "\n", " Zlib$1.RawInflateStream.prototype.readUncompressedBlockHeader = function () {\n", " /** @type {number} block length */\n", " var len;\n", " /** @type {number} number for check block length */\n", "\n", " var nlen;\n", " var input = this.input;\n", " var ip = this.ip;\n", " this.status = Zlib$1.RawInflateStream.Status.BLOCK_BODY_START;\n", "\n", " if (ip + 4 >= input.length) {\n", " return -1;\n", " }\n", "\n", " len = input[ip++] | input[ip++] << 8;\n", " nlen = input[ip++] | input[ip++] << 8; // check len & nlen\n", "\n", " if (len === ~nlen) {\n", " throw new Error('invalid uncompressed block header: length verify');\n", " } // skip buffered header bits\n", "\n", "\n", " this.bitsbuf = 0;\n", " this.bitsbuflen = 0;\n", " this.ip = ip;\n", " this.blockLength = len;\n", " this.status = Zlib$1.RawInflateStream.Status.BLOCK_BODY_END;\n", " };\n", " /**\n", " * parse uncompressed block.\n", " */\n", "\n", "\n", " Zlib$1.RawInflateStream.prototype.parseUncompressedBlock = function () {\n", " var input = this.input;\n", " var ip = this.ip;\n", " var output = this.output;\n", " var op = this.op;\n", " var len = this.blockLength;\n", " this.status = Zlib$1.RawInflateStream.Status.DECODE_BLOCK_START; // copy\n", " // XXX: とりあえず素直にコピー\n", "\n", " while (len--) {\n", " if (op === output.length) {\n", " output = this.expandBuffer({\n", " fixRatio: 2\n", " });\n", " } // not enough input buffer\n", "\n", "\n", " if (ip >= input.length) {\n", " this.ip = ip;\n", " this.op = op;\n", " this.blockLength = len + 1; // コピーしてないので戻す\n", "\n", " return -1;\n", " }\n", "\n", " output[op++] = input[ip++];\n", " }\n", "\n", " if (len < 0) {\n", " this.status = Zlib$1.RawInflateStream.Status.DECODE_BLOCK_END;\n", " }\n", "\n", " this.ip = ip;\n", " this.op = op;\n", " return 0;\n", " };\n", " /**\n", " * parse fixed huffman block.\n", " */\n", "\n", "\n", " Zlib$1.RawInflateStream.prototype.parseFixedHuffmanBlock = function () {\n", " this.status = Zlib$1.RawInflateStream.Status.BLOCK_BODY_START;\n", " this.litlenTable = Zlib$1.RawInflateStream.FixedLiteralLengthTable;\n", " this.distTable = Zlib$1.RawInflateStream.FixedDistanceTable;\n", " this.status = Zlib$1.RawInflateStream.Status.BLOCK_BODY_END;\n", " return 0;\n", " };\n", " /**\n", " * オブジェクトのコンテキストを別のプロパティに退避する.\n", " * @private\n", " */\n", "\n", "\n", " Zlib$1.RawInflateStream.prototype.save_ = function () {\n", " this.ip_ = this.ip;\n", " this.bitsbuflen_ = this.bitsbuflen;\n", " this.bitsbuf_ = this.bitsbuf;\n", " };\n", " /**\n", " * 別のプロパティに退避したコンテキストを復元する.\n", " * @private\n", " */\n", "\n", "\n", " Zlib$1.RawInflateStream.prototype.restore_ = function () {\n", " this.ip = this.ip_;\n", " this.bitsbuflen = this.bitsbuflen_;\n", " this.bitsbuf = this.bitsbuf_;\n", " };\n", " /**\n", " * parse dynamic huffman block.\n", " */\n", "\n", "\n", " Zlib$1.RawInflateStream.prototype.parseDynamicHuffmanBlock = function () {\n", " /** @type {number} number of literal and length codes. */\n", " var hlit;\n", " /** @type {number} number of distance codes. */\n", "\n", " var hdist;\n", " /** @type {number} number of code lengths. */\n", "\n", " var hclen;\n", " /** @type {!(Uint8Array|Array)} code lengths. */\n", "\n", " var codeLengths = new Uint8Array(Zlib$1.RawInflateStream.Order.length);\n", " /** @type {!Array} code lengths table. */\n", "\n", " var codeLengthsTable;\n", " this.status = Zlib$1.RawInflateStream.Status.BLOCK_BODY_START;\n", " this.save_();\n", " hlit = this.readBits(5) + 257;\n", " hdist = this.readBits(5) + 1;\n", " hclen = this.readBits(4) + 4;\n", "\n", " if (hlit < 0 || hdist < 0 || hclen < 0) {\n", " this.restore_();\n", " return -1;\n", " }\n", "\n", " try {\n", " parseDynamicHuffmanBlockImpl.call(this);\n", " } catch (e) {\n", " this.restore_();\n", " return -1;\n", " }\n", "\n", " function parseDynamicHuffmanBlockImpl() {\n", " /** @type {number} */\n", " var bits;\n", " var code;\n", " var prev = 0;\n", " var repeat;\n", " /** @type {!(Uint8Array|Array.)} code length table. */\n", "\n", " var lengthTable;\n", " /** @type {number} loop counter. */\n", "\n", " var i;\n", " /** @type {number} loop limit. */\n", "\n", " var il; // decode code lengths\n", "\n", " for (i = 0; i < hclen; ++i) {\n", " if ((bits = this.readBits(3)) < 0) {\n", " throw new Error('not enough input');\n", " }\n", "\n", " codeLengths[Zlib$1.RawInflateStream.Order[i]] = bits;\n", " } // decode length table\n", "\n", "\n", " codeLengthsTable = buildHuffmanTable$1(codeLengths);\n", " lengthTable = new Uint8Array(hlit + hdist);\n", "\n", " for (i = 0, il = hlit + hdist; i < il;) {\n", " code = this.readCodeByTable(codeLengthsTable);\n", "\n", " if (code < 0) {\n", " throw new Error('not enough input');\n", " }\n", "\n", " switch (code) {\n", " case 16:\n", " if ((bits = this.readBits(2)) < 0) {\n", " throw new Error('not enough input');\n", " }\n", "\n", " repeat = 3 + bits;\n", "\n", " while (repeat--) {\n", " lengthTable[i++] = prev;\n", " }\n", "\n", " break;\n", "\n", " case 17:\n", " if ((bits = this.readBits(3)) < 0) {\n", " throw new Error('not enough input');\n", " }\n", "\n", " repeat = 3 + bits;\n", "\n", " while (repeat--) {\n", " lengthTable[i++] = 0;\n", " }\n", "\n", " prev = 0;\n", " break;\n", "\n", " case 18:\n", " if ((bits = this.readBits(7)) < 0) {\n", " throw new Error('not enough input');\n", " }\n", "\n", " repeat = 11 + bits;\n", "\n", " while (repeat--) {\n", " lengthTable[i++] = 0;\n", " }\n", "\n", " prev = 0;\n", " break;\n", "\n", " default:\n", " lengthTable[i++] = code;\n", " prev = code;\n", " break;\n", " }\n", " }\n", "\n", " this.litlenTable = buildHuffmanTable$1(lengthTable.subarray(0, hlit));\n", " this.distTable = buildHuffmanTable$1(lengthTable.subarray(hlit));\n", " }\n", "\n", " this.status = Zlib$1.RawInflateStream.Status.BLOCK_BODY_END;\n", " return 0;\n", " };\n", " /**\n", " * decode huffman code (dynamic)\n", " * @return {(number|undefined)} -1 is error.\n", " */\n", "\n", "\n", " Zlib$1.RawInflateStream.prototype.decodeHuffman = function () {\n", " var output = this.output;\n", " var op = this.op;\n", " /** @type {number} huffman code. */\n", "\n", " var code;\n", " /** @type {number} table index. */\n", "\n", " var ti;\n", " /** @type {number} huffman code distination. */\n", "\n", " var codeDist;\n", " /** @type {number} huffman code length. */\n", "\n", " var codeLength;\n", " var litlen = this.litlenTable;\n", " var dist = this.distTable;\n", " var olength = output.length;\n", " var bits;\n", " this.status = Zlib$1.RawInflateStream.Status.DECODE_BLOCK_START;\n", "\n", " while (true) {\n", " this.save_();\n", " code = this.readCodeByTable(litlen);\n", "\n", " if (code < 0) {\n", " this.op = op;\n", " this.restore_();\n", " return -1;\n", " }\n", "\n", " if (code === 256) {\n", " break;\n", " } // literal\n", "\n", "\n", " if (code < 256) {\n", " if (op === olength) {\n", " output = this.expandBuffer();\n", " olength = output.length;\n", " }\n", "\n", " output[op++] = code;\n", " continue;\n", " } // length code\n", "\n", "\n", " ti = code - 257;\n", " codeLength = Zlib$1.RawInflateStream.LengthCodeTable[ti];\n", "\n", " if (Zlib$1.RawInflateStream.LengthExtraTable[ti] > 0) {\n", " bits = this.readBits(Zlib$1.RawInflateStream.LengthExtraTable[ti]);\n", "\n", " if (bits < 0) {\n", " this.op = op;\n", " this.restore_();\n", " return -1;\n", " }\n", "\n", " codeLength += bits;\n", " } // dist code\n", "\n", "\n", " code = this.readCodeByTable(dist);\n", "\n", " if (code < 0) {\n", " this.op = op;\n", " this.restore_();\n", " return -1;\n", " }\n", "\n", " codeDist = Zlib$1.RawInflateStream.DistCodeTable[code];\n", "\n", " if (Zlib$1.RawInflateStream.DistExtraTable[code] > 0) {\n", " bits = this.readBits(Zlib$1.RawInflateStream.DistExtraTable[code]);\n", "\n", " if (bits < 0) {\n", " this.op = op;\n", " this.restore_();\n", " return -1;\n", " }\n", "\n", " codeDist += bits;\n", " } // lz77 decode\n", "\n", "\n", " if (op + codeLength >= olength) {\n", " output = this.expandBuffer();\n", " olength = output.length;\n", " }\n", "\n", " while (codeLength--) {\n", " output[op] = output[op++ - codeDist];\n", " } // break\n", "\n", "\n", " if (this.ip === this.input.length) {\n", " this.op = op;\n", " return -1;\n", " }\n", " }\n", "\n", " while (this.bitsbuflen >= 8) {\n", " this.bitsbuflen -= 8;\n", " this.ip--;\n", " }\n", "\n", " this.op = op;\n", " this.status = Zlib$1.RawInflateStream.Status.DECODE_BLOCK_END;\n", " };\n", " /**\n", " * expand output buffer. (dynamic)\n", " * @param {Object=} opt_param option parameters.\n", " * @return {!(Array|Uint8Array)} output buffer pointer.\n", " */\n", "\n", "\n", " Zlib$1.RawInflateStream.prototype.expandBuffer = function (opt_param) {\n", " /** @type {!(Array|Uint8Array)} store buffer. */\n", " var buffer;\n", " /** @type {number} expantion ratio. */\n", "\n", " var ratio = this.input.length / this.ip + 1 | 0;\n", " /** @type {number} maximum number of huffman code. */\n", "\n", " var maxHuffCode;\n", " /** @type {number} new output buffer size. */\n", "\n", " var newSize;\n", " /** @type {number} max inflate size. */\n", "\n", " var maxInflateSize;\n", " var input = this.input;\n", " var output = this.output;\n", "\n", " if (opt_param) {\n", " if (typeof opt_param.fixRatio === 'number') {\n", " ratio = opt_param.fixRatio;\n", " }\n", "\n", " if (typeof opt_param.addRatio === 'number') {\n", " ratio += opt_param.addRatio;\n", " }\n", " } // calculate new buffer size\n", "\n", "\n", " if (ratio < 2) {\n", " maxHuffCode = (input.length - this.ip) / this.litlenTable[2];\n", " maxInflateSize = maxHuffCode / 2 * 258 | 0;\n", " newSize = maxInflateSize < output.length ? output.length + maxInflateSize : output.length << 1;\n", " } else {\n", " newSize = output.length * ratio;\n", " } // buffer expantion\n", "\n", "\n", " {\n", " buffer = new Uint8Array(newSize);\n", " buffer.set(output);\n", " }\n", " this.output = buffer;\n", " return this.output;\n", " };\n", " /**\n", " * concat output buffer. (dynamic)\n", " * @return {!(Array|Uint8Array)} output buffer.\n", " */\n", "\n", "\n", " Zlib$1.RawInflateStream.prototype.concatBuffer = function () {\n", " /** @type {!(Array|Uint8Array)} output buffer. */\n", " var buffer;\n", " /** @type {number} */\n", "\n", " var op = this.op;\n", " /** @type {Uint8Array} */\n", "\n", " var tmp;\n", "\n", " if (this.resize) {\n", " {\n", " buffer = new Uint8Array(this.output.subarray(this.sp, op));\n", " }\n", " } else {\n", " buffer = this.output.subarray(this.sp, op);\n", " }\n", "\n", " this.sp = op; // compaction\n", "\n", " if (op > Zlib$1.RawInflateStream.MaxBackwardLength + this.bufferSize) {\n", " this.op = this.sp = Zlib$1.RawInflateStream.MaxBackwardLength;\n", " {\n", " tmp =\n", " /** @type {Uint8Array} */\n", " this.output;\n", " this.output = new Uint8Array(this.bufferSize + Zlib$1.RawInflateStream.MaxBackwardLength);\n", " this.output.set(tmp.subarray(op - Zlib$1.RawInflateStream.MaxBackwardLength, op));\n", " }\n", " }\n", "\n", " return buffer;\n", " };\n", " /**\n", " * @constructor\n", " * @param {!(Uint8Array|Array)} input deflated buffer.\n", " * @param {Object=} opt_params option parameters.\n", " *\n", " * opt_params は以下のプロパティを指定する事ができます。\n", " * - index: input buffer の deflate コンテナの開始位置.\n", " * - blockSize: バッファのブロックサイズ.\n", " * - verify: 伸張が終わった後 adler-32 checksum の検証を行うか.\n", " * - bufferType: Zlib.Inflate.BufferType の値によってバッファの管理方法を指定する.\n", " * Zlib.Inflate.BufferType は Zlib.RawInflate.BufferType のエイリアス.\n", " */\n", "\n", "\n", " Zlib$1.Inflate = function (input, opt_params) {\n", " /** @type {number} */\n", " var cmf;\n", " /** @type {number} */\n", "\n", " var flg;\n", " /** @type {!(Uint8Array|Array)} */\n", "\n", " this.input = input;\n", " /** @type {number} */\n", "\n", " this.ip = 0;\n", " /** @type {Zlib.RawInflate} */\n", "\n", " this.rawinflate;\n", " /** @type {(boolean|undefined)} verify flag. */\n", "\n", " this.verify; // option parameters\n", "\n", " if (opt_params || !(opt_params = {})) {\n", " if (opt_params['index']) {\n", " this.ip = opt_params['index'];\n", " }\n", "\n", " if (opt_params['verify']) {\n", " this.verify = opt_params['verify'];\n", " }\n", " } // Compression Method and Flags\n", "\n", "\n", " cmf = input[this.ip++];\n", " flg = input[this.ip++]; // compression method\n", "\n", " switch (cmf & 0x0f) {\n", " case Zlib$1.CompressionMethod.DEFLATE:\n", " this.method = Zlib$1.CompressionMethod.DEFLATE;\n", " break;\n", "\n", " default:\n", " throw new Error('unsupported compression method');\n", " } // fcheck\n", "\n", "\n", " if (((cmf << 8) + flg) % 31 !== 0) {\n", " throw new Error('invalid fcheck flag:' + ((cmf << 8) + flg) % 31);\n", " } // fdict (not supported)\n", "\n", "\n", " if (flg & 0x20) {\n", " throw new Error('fdict flag is not supported');\n", " } // RawInflate\n", "\n", "\n", " this.rawinflate = new Zlib$1.RawInflate(input, {\n", " 'index': this.ip,\n", " 'bufferSize': opt_params['bufferSize'],\n", " 'bufferType': opt_params['bufferType'],\n", " 'resize': opt_params['resize']\n", " });\n", " };\n", " /**\n", " * @enum {number}\n", " */\n", "\n", "\n", " Zlib$1.Inflate.BufferType = Zlib$1.RawInflate.BufferType;\n", " /**\n", " * decompress.\n", " * @return {!(Uint8Array|Array)} inflated buffer.\n", " */\n", "\n", " Zlib$1.Inflate.prototype.decompress = function () {\n", " /** @type {!(Array|Uint8Array)} input buffer. */\n", " var input = this.input;\n", " /** @type {!(Uint8Array|Array)} inflated buffer. */\n", "\n", " var buffer;\n", " /** @type {number} adler-32 checksum */\n", "\n", " var adler32;\n", " buffer = this.rawinflate.decompress();\n", " this.ip = this.rawinflate.ip; // verify adler-32\n", "\n", " if (this.verify) {\n", " adler32 = (input[this.ip++] << 24 | input[this.ip++] << 16 | input[this.ip++] << 8 | input[this.ip++]) >>> 0;\n", "\n", " if (adler32 !== Zlib$1.Adler32(buffer)) {\n", " throw new Error('invalid adler-32 checksum');\n", " }\n", " }\n", "\n", " return buffer;\n", " };\n", " /* vim:set expandtab ts=2 sw=2 tw=80: */\n", "\n", " /**\n", " * @param {!(Uint8Array|Array)} input deflated buffer.\n", " * @constructor\n", " */\n", "\n", "\n", " Zlib$1.InflateStream = function (input) {\n", " /** @type {!(Uint8Array|Array)} */\n", " this.input = input === void 0 ? new Uint8Array() : input;\n", " /** @type {number} */\n", "\n", " this.ip = 0;\n", " /** @type {Zlib.RawInflateStream} */\n", "\n", " this.rawinflate = new Zlib$1.RawInflateStream(this.input, this.ip);\n", " /** @type {Zlib.CompressionMethod} */\n", "\n", " this.method;\n", " /** @type {!(Array|Uint8Array)} */\n", "\n", " this.output = this.rawinflate.output;\n", " };\n", " /**\n", " * decompress.\n", " * @return {!(Uint8Array|Array)} inflated buffer.\n", " */\n", "\n", "\n", " Zlib$1.InflateStream.prototype.decompress = function (input) {\n", " /** @type {!(Uint8Array|Array)} inflated buffer. */\n", " var buffer; // 新しい入力を入力バッファに結合する\n", " // XXX Array, Uint8Array のチェックを行うか確認する\n", "\n", " if (input !== void 0) {\n", " {\n", " var tmp = new Uint8Array(this.input.length + input.length);\n", " tmp.set(this.input, 0);\n", " tmp.set(input, this.input.length);\n", " this.input = tmp;\n", " }\n", " }\n", "\n", " if (this.method === void 0) {\n", " if (this.readHeader() < 0) {\n", " return new Uint8Array();\n", " }\n", " }\n", "\n", " buffer = this.rawinflate.decompress(this.input, this.ip);\n", "\n", " if (this.rawinflate.ip !== 0) {\n", " this.input = this.input.subarray(this.rawinflate.ip);\n", " this.ip = 0;\n", " } // verify adler-32\n", "\n", " /*\n", " if (this.verify) {\n", " adler32 =\n", " input[this.ip++] << 24 | input[this.ip++] << 16 |\n", " input[this.ip++] << 8 | input[this.ip++];\n", " if (adler32 !== Zlib.Adler32(buffer)) {\n", " throw new Error('invalid adler-32 checksum');\n", " }\n", " }\n", " */\n", "\n", "\n", " return buffer;\n", " };\n", "\n", " Zlib$1.InflateStream.prototype.readHeader = function () {\n", " var ip = this.ip;\n", " var input = this.input; // Compression Method and Flags\n", "\n", " var cmf = input[ip++];\n", " var flg = input[ip++];\n", "\n", " if (cmf === void 0 || flg === void 0) {\n", " return -1;\n", " } // compression method\n", "\n", "\n", " switch (cmf & 0x0f) {\n", " case Zlib$1.CompressionMethod.DEFLATE:\n", " this.method = Zlib$1.CompressionMethod.DEFLATE;\n", " break;\n", "\n", " default:\n", " throw new Error('unsupported compression method');\n", " } // fcheck\n", "\n", "\n", " if (((cmf << 8) + flg) % 31 !== 0) {\n", " throw new Error('invalid fcheck flag:' + ((cmf << 8) + flg) % 31);\n", " } // fdict (not supported)\n", "\n", "\n", " if (flg & 0x20) {\n", " throw new Error('fdict flag is not supported');\n", " }\n", "\n", " this.ip = ip;\n", " };\n", " /**\n", " * @fileoverview GZIP (RFC1952) 展開コンテナ実装.\n", " */\n", "\n", " /**\n", " * @constructor\n", " * @param {!(Array|Uint8Array)} input input buffer.\n", " * @param {Object=} opt_params option parameters.\n", " */\n", "\n", "\n", " Zlib$1.Gunzip = function (input, opt_params) {\n", " /** @type {!(Array.|Uint8Array)} input buffer. */\n", " this.input = input;\n", " /** @type {number} input buffer pointer. */\n", "\n", " this.ip = 0;\n", " /** @type {Array.} */\n", "\n", " this.member = [];\n", " /** @type {boolean} */\n", "\n", " this.decompressed = false;\n", " };\n", " /**\n", " * @return {Array.}\n", " */\n", "\n", "\n", " Zlib$1.Gunzip.prototype.getMembers = function () {\n", " if (!this.decompressed) {\n", " this.decompress();\n", " }\n", "\n", " return this.member.slice();\n", " };\n", " /**\n", " * inflate gzip data.\n", " * @return {!(Array.|Uint8Array)} inflated buffer.\n", " */\n", "\n", "\n", " Zlib$1.Gunzip.prototype.decompress = function () {\n", " /** @type {number} input length. */\n", " var il = this.input.length;\n", "\n", " while (this.ip < il) {\n", " this.decodeMember();\n", " }\n", "\n", " this.decompressed = true;\n", " return this.concatMember();\n", " };\n", " /**\n", " * decode gzip member.\n", " */\n", "\n", "\n", " Zlib$1.Gunzip.prototype.decodeMember = function () {\n", " /** @type {Zlib.GunzipMember} */\n", " var member = new Zlib$1.GunzipMember();\n", " /** @type {number} */\n", "\n", " var isize;\n", " /** @type {Zlib.RawInflate} RawInflate implementation. */\n", "\n", " var rawinflate;\n", " /** @type {!(Array.|Uint8Array)} inflated data. */\n", "\n", " var inflated;\n", " /** @type {number} inflate size */\n", "\n", " var inflen;\n", " /** @type {number} character code */\n", "\n", " var c;\n", " /** @type {number} character index in string. */\n", "\n", " var ci;\n", " /** @type {Array.} character array. */\n", "\n", " var str;\n", " /** @type {number} modification time. */\n", "\n", " var mtime;\n", " /** @type {number} */\n", "\n", " var crc32;\n", " var input = this.input;\n", " var ip = this.ip;\n", " member.id1 = input[ip++];\n", " member.id2 = input[ip++]; // check signature\n", "\n", " if (member.id1 !== 0x1f || member.id2 !== 0x8b) {\n", " throw new Error('invalid file signature:' + member.id1 + ',' + member.id2);\n", " } // check compression method\n", "\n", "\n", " member.cm = input[ip++];\n", "\n", " switch (member.cm) {\n", " case 8:\n", " /* XXX: use Zlib const */\n", " break;\n", "\n", " default:\n", " throw new Error('unknown compression method: ' + member.cm);\n", " } // flags\n", "\n", "\n", " member.flg = input[ip++]; // modification time\n", "\n", " mtime = input[ip++] | input[ip++] << 8 | input[ip++] << 16 | input[ip++] << 24;\n", " member.mtime = new Date(mtime * 1000); // extra flags\n", "\n", " member.xfl = input[ip++]; // operating system\n", "\n", " member.os = input[ip++]; // extra\n", "\n", " if ((member.flg & Zlib$1.Gzip.FlagsMask.FEXTRA) > 0) {\n", " member.xlen = input[ip++] | input[ip++] << 8;\n", " ip = this.decodeSubField(ip, member.xlen);\n", " } // fname\n", "\n", "\n", " if ((member.flg & Zlib$1.Gzip.FlagsMask.FNAME) > 0) {\n", " for (str = [], ci = 0; (c = input[ip++]) > 0;) {\n", " str[ci++] = String.fromCharCode(c);\n", " }\n", "\n", " member.name = str.join('');\n", " } // fcomment\n", "\n", "\n", " if ((member.flg & Zlib$1.Gzip.FlagsMask.FCOMMENT) > 0) {\n", " for (str = [], ci = 0; (c = input[ip++]) > 0;) {\n", " str[ci++] = String.fromCharCode(c);\n", " }\n", "\n", " member.comment = str.join('');\n", " } // fhcrc\n", "\n", "\n", " if ((member.flg & Zlib$1.Gzip.FlagsMask.FHCRC) > 0) {\n", " member.crc16 = Zlib$1.CRC32.calc(input, 0, ip) & 0xffff;\n", "\n", " if (member.crc16 !== (input[ip++] | input[ip++] << 8)) {\n", " throw new Error('invalid header crc16');\n", " }\n", " } // isize を事前に取得すると展開後のサイズが分かるため、\n", " // inflate処理のバッファサイズが事前に分かり、高速になる\n", "\n", "\n", " isize = input[input.length - 4] | input[input.length - 3] << 8 | input[input.length - 2] << 16 | input[input.length - 1] << 24; // isize の妥当性チェック\n", " // ハフマン符号では最小 2-bit のため、最大で 1/4 になる\n", " // LZ77 符号では 長さと距離 2-Byte で最大 258-Byte を表現できるため、\n", " // 1/128 になるとする\n", " // ここから入力バッファの残りが isize の 512 倍以上だったら\n", " // サイズ指定のバッファ確保は行わない事とする\n", "\n", " if (input.length - ip -\n", " /* CRC-32 */\n", " 4 -\n", " /* ISIZE */\n", " 4 < isize * 512) {\n", " inflen = isize;\n", " } // compressed block\n", "\n", "\n", " rawinflate = new Zlib$1.RawInflate(input, {\n", " 'index': ip,\n", " 'bufferSize': inflen\n", " });\n", " member.data = inflated = rawinflate.decompress();\n", " ip = rawinflate.ip; // crc32\n", "\n", " member.crc32 = crc32 = (input[ip++] | input[ip++] << 8 | input[ip++] << 16 | input[ip++] << 24) >>> 0;\n", "\n", " if (Zlib$1.CRC32.calc(inflated) !== crc32) {\n", " throw new Error('invalid CRC-32 checksum: 0x' + Zlib$1.CRC32.calc(inflated).toString(16) + ' / 0x' + crc32.toString(16));\n", " } // input size\n", "\n", "\n", " member.isize = isize = (input[ip++] | input[ip++] << 8 | input[ip++] << 16 | input[ip++] << 24) >>> 0;\n", "\n", " if ((inflated.length & 0xffffffff) !== isize) {\n", " throw new Error('invalid input size: ' + (inflated.length & 0xffffffff) + ' / ' + isize);\n", " }\n", "\n", " this.member.push(member);\n", " this.ip = ip;\n", " };\n", " /**\n", " * サブフィールドのデコード\n", " * XXX: 現在は何もせずスキップする\n", " */\n", "\n", "\n", " Zlib$1.Gunzip.prototype.decodeSubField = function (ip, length) {\n", " return ip + length;\n", " };\n", " /**\n", " * @return {!(Array.|Uint8Array)}\n", " */\n", "\n", "\n", " Zlib$1.Gunzip.prototype.concatMember = function () {\n", " /** @type {Array.} */\n", " var member = this.member;\n", " /** @type {number} */\n", "\n", " var i;\n", " /** @type {number} */\n", "\n", " var il;\n", " /** @type {number} */\n", "\n", " var p = 0;\n", " /** @type {number} */\n", "\n", " var size = 0;\n", " /** @type {!(Array.|Uint8Array)} */\n", "\n", " var buffer;\n", "\n", " for (i = 0, il = member.length; i < il; ++i) {\n", " size += member[i].data.length;\n", " }\n", "\n", " {\n", " buffer = new Uint8Array(size);\n", "\n", " for (i = 0; i < il; ++i) {\n", " buffer.set(member[i].data, p);\n", " p += member[i].data.length;\n", " }\n", " }\n", " return buffer;\n", " };\n", " /**\n", " * @constructor\n", " */\n", "\n", "\n", " Zlib$1.GunzipMember = function () {\n", " /** @type {number} signature first byte. */\n", " this.id1;\n", " /** @type {number} signature second byte. */\n", "\n", " this.id2;\n", " /** @type {number} compression method. */\n", "\n", " this.cm;\n", " /** @type {number} flags. */\n", "\n", " this.flg;\n", " /** @type {Date} modification time. */\n", "\n", " this.mtime;\n", " /** @type {number} extra flags. */\n", "\n", " this.xfl;\n", " /** @type {number} operating system number. */\n", "\n", " this.os;\n", " /** @type {number} CRC-16 value for FHCRC flag. */\n", "\n", " this.crc16;\n", " /** @type {number} extra length. */\n", "\n", " this.xlen;\n", " /** @type {number} CRC-32 value for verification. */\n", "\n", " this.crc32;\n", " /** @type {number} input size modulo 32 value. */\n", "\n", " this.isize;\n", " /** @type {string} filename. */\n", "\n", " this.name;\n", " /** @type {string} comment. */\n", "\n", " this.comment;\n", " /** @type {!(Uint8Array|Array.)} */\n", "\n", " this.data;\n", " };\n", "\n", " Zlib$1.GunzipMember.prototype.getName = function () {\n", " return this.name;\n", " };\n", "\n", " Zlib$1.GunzipMember.prototype.getData = function () {\n", " return this.data;\n", " };\n", "\n", " Zlib$1.GunzipMember.prototype.getMtime = function () {\n", " return this.mtime;\n", " };\n", " /**\n", " * @fileoverview GZIP (RFC1952) 実装.\n", " */\n", "\n", " /**\n", " * @constructor\n", " * @param {!(Array|Uint8Array)} input input buffer.\n", " * @param {Object=} opt_params option parameters.\n", " */\n", "\n", "\n", " Zlib$1.Gzip = function (input, opt_params) {\n", " /** @type {!(Array.|Uint8Array)} input buffer. */\n", " this.input = input;\n", " /** @type {number} input buffer pointer. */\n", "\n", " this.ip = 0;\n", " /** @type {!(Array.|Uint8Array)} output buffer. */\n", "\n", " this.output;\n", " /** @type {number} output buffer. */\n", "\n", " this.op = 0;\n", " /** @type {!Object} flags option flags. */\n", "\n", " this.flags = {};\n", " /** @type {!string} filename. */\n", "\n", " this.filename;\n", " /** @type {!string} comment. */\n", "\n", " this.comment;\n", " /** @type {!Object} deflate options. */\n", "\n", " this.deflateOptions; // option parameters\n", "\n", " if (opt_params) {\n", " if (opt_params['flags']) {\n", " this.flags = opt_params['flags'];\n", " }\n", "\n", " if (typeof opt_params['filename'] === 'string') {\n", " this.filename = opt_params['filename'];\n", " }\n", "\n", " if (typeof opt_params['comment'] === 'string') {\n", " this.comment = opt_params['comment'];\n", " }\n", "\n", " if (opt_params['deflateOptions']) {\n", " this.deflateOptions = opt_params['deflateOptions'];\n", " }\n", " }\n", "\n", " if (!this.deflateOptions) {\n", " this.deflateOptions = {};\n", " }\n", " };\n", " /**\n", " * @type {number}\n", " * @const\n", " */\n", "\n", "\n", " Zlib$1.Gzip.DefaultBufferSize = 0x8000;\n", " /**\n", " * encode gzip members.\n", " * @return {!(Array|Uint8Array)} gzip binary array.\n", " */\n", "\n", " Zlib$1.Gzip.prototype.compress = function () {\n", " /** @type {number} flags. */\n", " var flg;\n", " /** @type {number} modification time. */\n", "\n", " var mtime;\n", " /** @type {number} CRC-16 value for FHCRC flag. */\n", "\n", " var crc16;\n", " /** @type {number} CRC-32 value for verification. */\n", "\n", " var crc32;\n", " /** @type {!Zlib.RawDeflate} raw deflate object. */\n", "\n", " var rawdeflate;\n", " /** @type {number} character code */\n", "\n", " var c;\n", " /** @type {number} loop counter. */\n", "\n", " var i;\n", " /** @type {number} loop limiter. */\n", "\n", " var il;\n", " /** @type {!(Array|Uint8Array)} output buffer. */\n", "\n", " var output = new Uint8Array(Zlib$1.Gzip.DefaultBufferSize);\n", " /** @type {number} output buffer pointer. */\n", "\n", " var op = 0;\n", " var input = this.input;\n", " var ip = this.ip;\n", " var filename = this.filename;\n", " var comment = this.comment; // check signature\n", "\n", " output[op++] = 0x1f;\n", " output[op++] = 0x8b; // check compression method\n", "\n", " output[op++] = 8;\n", " /* XXX: use Zlib const */\n", " // flags\n", "\n", " flg = 0;\n", " if (this.flags['fname']) flg |= Zlib$1.Gzip.FlagsMask.FNAME;\n", " if (this.flags['fcomment']) flg |= Zlib$1.Gzip.FlagsMask.FCOMMENT;\n", " if (this.flags['fhcrc']) flg |= Zlib$1.Gzip.FlagsMask.FHCRC; // XXX: FTEXT\n", " // XXX: FEXTRA\n", "\n", " output[op++] = flg; // modification time\n", "\n", " mtime = (Date.now ? Date.now() : +new Date()) / 1000 | 0;\n", " output[op++] = mtime & 0xff;\n", " output[op++] = mtime >>> 8 & 0xff;\n", " output[op++] = mtime >>> 16 & 0xff;\n", " output[op++] = mtime >>> 24 & 0xff; // extra flags\n", "\n", " output[op++] = 0; // operating system\n", "\n", " output[op++] = Zlib$1.Gzip.OperatingSystem.UNKNOWN; // extra\n", "\n", " /* NOP */\n", " // fname\n", "\n", " if (this.flags['fname'] !== void 0) {\n", " for (i = 0, il = filename.length; i < il; ++i) {\n", " c = filename.charCodeAt(i);\n", "\n", " if (c > 0xff) {\n", " output[op++] = c >>> 8 & 0xff;\n", " }\n", "\n", " output[op++] = c & 0xff;\n", " }\n", "\n", " output[op++] = 0; // null termination\n", " } // fcomment\n", "\n", "\n", " if (this.flags['comment']) {\n", " for (i = 0, il = comment.length; i < il; ++i) {\n", " c = comment.charCodeAt(i);\n", "\n", " if (c > 0xff) {\n", " output[op++] = c >>> 8 & 0xff;\n", " }\n", "\n", " output[op++] = c & 0xff;\n", " }\n", "\n", " output[op++] = 0; // null termination\n", " } // fhcrc\n", "\n", "\n", " if (this.flags['fhcrc']) {\n", " crc16 = Zlib$1.CRC32.calc(output, 0, op) & 0xffff;\n", " output[op++] = crc16 & 0xff;\n", " output[op++] = crc16 >>> 8 & 0xff;\n", " } // add compress option\n", "\n", "\n", " this.deflateOptions['outputBuffer'] = output;\n", " this.deflateOptions['outputIndex'] = op; // compress\n", "\n", " rawdeflate = new Zlib$1.RawDeflate(input, this.deflateOptions);\n", " output = rawdeflate.compress();\n", " op = rawdeflate.op; // expand buffer\n", "\n", " {\n", " if (op + 8 > output.buffer.byteLength) {\n", " this.output = new Uint8Array(op + 8);\n", " this.output.set(new Uint8Array(output.buffer));\n", " output = this.output;\n", " } else {\n", " output = new Uint8Array(output.buffer);\n", " }\n", " } // crc32\n", "\n", " crc32 = Zlib$1.CRC32.calc(input);\n", " output[op++] = crc32 & 0xff;\n", " output[op++] = crc32 >>> 8 & 0xff;\n", " output[op++] = crc32 >>> 16 & 0xff;\n", " output[op++] = crc32 >>> 24 & 0xff; // input size\n", "\n", " il = input.length;\n", " output[op++] = il & 0xff;\n", " output[op++] = il >>> 8 & 0xff;\n", " output[op++] = il >>> 16 & 0xff;\n", " output[op++] = il >>> 24 & 0xff;\n", " this.ip = ip;\n", "\n", " if (op < output.length) {\n", " this.output = output = output.subarray(0, op);\n", " }\n", "\n", " return output;\n", " };\n", " /** @enum {number} */\n", "\n", "\n", " Zlib$1.Gzip.OperatingSystem = {\n", " FAT: 0,\n", " AMIGA: 1,\n", " VMS: 2,\n", " UNIX: 3,\n", " VM_CMS: 4,\n", " ATARI_TOS: 5,\n", " HPFS: 6,\n", " MACINTOSH: 7,\n", " Z_SYSTEM: 8,\n", " CP_M: 9,\n", " TOPS_20: 10,\n", " NTFS: 11,\n", " QDOS: 12,\n", " ACORN_RISCOS: 13,\n", " UNKNOWN: 255\n", " };\n", " /** @enum {number} */\n", "\n", " Zlib$1.Gzip.FlagsMask = {\n", " FTEXT: 0x01,\n", " FHCRC: 0x02,\n", " FEXTRA: 0x04,\n", " FNAME: 0x08,\n", " FCOMMENT: 0x10\n", " };\n", " /**\n", " * @fileoverview Heap Sort 実装. ハフマン符号化で使用する.\n", " */\n", "\n", " /**\n", " * カスタムハフマン符号で使用するヒープ実装\n", " * @param {number} length ヒープサイズ.\n", " * @constructor\n", " */\n", "\n", " Zlib$1.Heap = function (length) {\n", " this.buffer = new Uint16Array(length * 2);\n", " this.length = 0;\n", " };\n", " /**\n", " * 親ノードの index 取得\n", " * @param {number} index 子ノードの index.\n", " * @return {number} 親ノードの index.\n", " *\n", " */\n", "\n", "\n", " Zlib$1.Heap.prototype.getParent = function (index) {\n", " return ((index - 2) / 4 | 0) * 2;\n", " };\n", " /**\n", " * 子ノードの index 取得\n", " * @param {number} index 親ノードの index.\n", " * @return {number} 子ノードの index.\n", " */\n", "\n", "\n", " Zlib$1.Heap.prototype.getChild = function (index) {\n", " return 2 * index + 2;\n", " };\n", " /**\n", " * Heap に値を追加する\n", " * @param {number} index キー index.\n", " * @param {number} value 値.\n", " * @return {number} 現在のヒープ長.\n", " */\n", "\n", "\n", " Zlib$1.Heap.prototype.push = function (index, value) {\n", " var current,\n", " parent,\n", " heap = this.buffer,\n", " swap;\n", " current = this.length;\n", " heap[this.length++] = value;\n", " heap[this.length++] = index; // ルートノードにたどり着くまで入れ替えを試みる\n", "\n", " while (current > 0) {\n", " parent = this.getParent(current); // 親ノードと比較して親の方が小さければ入れ替える\n", "\n", " if (heap[current] > heap[parent]) {\n", " swap = heap[current];\n", " heap[current] = heap[parent];\n", " heap[parent] = swap;\n", " swap = heap[current + 1];\n", " heap[current + 1] = heap[parent + 1];\n", " heap[parent + 1] = swap;\n", " current = parent; // 入れ替えが必要なくなったらそこで抜ける\n", " } else {\n", " break;\n", " }\n", " }\n", "\n", " return this.length;\n", " };\n", " /**\n", " * Heapから一番大きい値を返す\n", " * @return {{index: number, value: number, length: number}} {index: キーindex,\n", " * value: 値, length: ヒープ長} の Object.\n", " */\n", "\n", "\n", " Zlib$1.Heap.prototype.pop = function () {\n", " var index,\n", " value,\n", " heap = this.buffer,\n", " swap,\n", " current,\n", " parent;\n", " value = heap[0];\n", " index = heap[1]; // 後ろから値を取る\n", "\n", " this.length -= 2;\n", " heap[0] = heap[this.length];\n", " heap[1] = heap[this.length + 1];\n", " parent = 0; // ルートノードから下がっていく\n", "\n", " while (true) {\n", " current = this.getChild(parent); // 範囲チェック\n", "\n", " if (current >= this.length) {\n", " break;\n", " } // 隣のノードと比較して、隣の方が値が大きければ隣を現在ノードとして選択\n", "\n", "\n", " if (current + 2 < this.length && heap[current + 2] > heap[current]) {\n", " current += 2;\n", " } // 親ノードと比較して親の方が小さい場合は入れ替える\n", "\n", "\n", " if (heap[current] > heap[parent]) {\n", " swap = heap[parent];\n", " heap[parent] = heap[current];\n", " heap[current] = swap;\n", " swap = heap[parent + 1];\n", " heap[parent + 1] = heap[current + 1];\n", " heap[current + 1] = swap;\n", " } else {\n", " break;\n", " }\n", "\n", " parent = current;\n", " }\n", "\n", " return {\n", " index: index,\n", " value: value,\n", " length: this.length\n", " };\n", " };\n", " /* vim:set expandtab ts=2 sw=2 tw=80: */\n", "\n", " /**\n", " * @fileoverview Deflate (RFC1951) 符号化アルゴリズム実装.\n", " */\n", "\n", " /**\n", " * Raw Deflate 実装\n", " *\n", " * @constructor\n", " * @param {!(Array.|Uint8Array)} input 符号化する対象のバッファ.\n", " * @param {Object=} opt_params option parameters.\n", " *\n", " * typed array が使用可能なとき、outputBuffer が Array は自動的に Uint8Array に\n", " * 変換されます.\n", " * 別のオブジェクトになるため出力バッファを参照している変数などは\n", " * 更新する必要があります.\n", " */\n", "\n", "\n", " Zlib$1.RawDeflate = function (input, opt_params) {\n", " /** @type {Zlib.RawDeflate.CompressionType} */\n", " this.compressionType = Zlib$1.RawDeflate.CompressionType.DYNAMIC;\n", " /** @type {number} */\n", "\n", " this.lazy = 0;\n", " /** @type {!(Array.|Uint32Array)} */\n", "\n", " this.freqsLitLen;\n", " /** @type {!(Array.|Uint32Array)} */\n", "\n", " this.freqsDist;\n", " /** @type {!(Array.|Uint8Array)} */\n", "\n", " this.input = input instanceof Array ? new Uint8Array(input) : input;\n", " /** @type {!(Array.|Uint8Array)} output output buffer. */\n", "\n", " this.output;\n", " /** @type {number} pos output buffer position. */\n", "\n", " this.op = 0; // option parameters\n", "\n", " if (opt_params) {\n", " if (opt_params['lazy']) {\n", " this.lazy = opt_params['lazy'];\n", " }\n", "\n", " if (typeof opt_params['compressionType'] === 'number') {\n", " this.compressionType = opt_params['compressionType'];\n", " }\n", "\n", " if (opt_params['outputBuffer']) {\n", " this.output = opt_params['outputBuffer'] instanceof Array ? new Uint8Array(opt_params['outputBuffer']) : opt_params['outputBuffer'];\n", " }\n", "\n", " if (typeof opt_params['outputIndex'] === 'number') {\n", " this.op = opt_params['outputIndex'];\n", " }\n", " }\n", "\n", " if (!this.output) {\n", " this.output = new Uint8Array(0x8000);\n", " }\n", " };\n", " /**\n", " * @enum {number}\n", " */\n", "\n", "\n", " Zlib$1.RawDeflate.CompressionType = {\n", " NONE: 0,\n", " FIXED: 1,\n", " DYNAMIC: 2,\n", " RESERVED: 3\n", " };\n", " /**\n", " * LZ77 の最小マッチ長\n", " * @const\n", " * @type {number}\n", " */\n", "\n", " Zlib$1.RawDeflate.Lz77MinLength = 3;\n", " /**\n", " * LZ77 の最大マッチ長\n", " * @const\n", " * @type {number}\n", " */\n", "\n", " Zlib$1.RawDeflate.Lz77MaxLength = 258;\n", " /**\n", " * LZ77 のウィンドウサイズ\n", " * @const\n", " * @type {number}\n", " */\n", "\n", " Zlib$1.RawDeflate.WindowSize = 0x8000;\n", " /**\n", " * 最長の符号長\n", " * @const\n", " * @type {number}\n", " */\n", "\n", " Zlib$1.RawDeflate.MaxCodeLength = 16;\n", " /**\n", " * ハフマン符号の最大数値\n", " * @const\n", " * @type {number}\n", " */\n", "\n", " Zlib$1.RawDeflate.HUFMAX = 286;\n", " /**\n", " * 固定ハフマン符号の符号化テーブル\n", " * @const\n", " * @type {Array.>}\n", " */\n", "\n", " Zlib$1.RawDeflate.FixedHuffmanTable = function () {\n", " var table = [],\n", " i;\n", "\n", " for (i = 0; i < 288; i++) {\n", " switch (true) {\n", " case i <= 143:\n", " table.push([i + 0x030, 8]);\n", " break;\n", "\n", " case i <= 255:\n", " table.push([i - 144 + 0x190, 9]);\n", " break;\n", "\n", " case i <= 279:\n", " table.push([i - 256 + 0x000, 7]);\n", " break;\n", "\n", " case i <= 287:\n", " table.push([i - 280 + 0x0C0, 8]);\n", " break;\n", "\n", " default:\n", " throw 'invalid literal: ' + i;\n", " }\n", " }\n", "\n", " return table;\n", " }();\n", " /**\n", " * DEFLATE ブロックの作成\n", " * @return {!(Array.|Uint8Array)} 圧縮済み byte array.\n", " */\n", "\n", "\n", " Zlib$1.RawDeflate.prototype.compress = function () {\n", " /** @type {!(Array.|Uint8Array)} */\n", " var blockArray;\n", " /** @type {number} */\n", "\n", " var position;\n", " /** @type {number} */\n", "\n", " var length;\n", " var input = this.input; // compression\n", "\n", " switch (this.compressionType) {\n", " case Zlib$1.RawDeflate.CompressionType.NONE:\n", " // each 65535-Byte (length header: 16-bit)\n", " for (position = 0, length = input.length; position < length;) {\n", " blockArray = input.subarray(position, position + 0xffff);\n", " position += blockArray.length;\n", " this.makeNocompressBlock(blockArray, position === length);\n", " }\n", "\n", " break;\n", "\n", " case Zlib$1.RawDeflate.CompressionType.FIXED:\n", " this.output = this.makeFixedHuffmanBlock(input, true);\n", " this.op = this.output.length;\n", " break;\n", "\n", " case Zlib$1.RawDeflate.CompressionType.DYNAMIC:\n", " this.output = this.makeDynamicHuffmanBlock(input, true);\n", " this.op = this.output.length;\n", " break;\n", "\n", " default:\n", " throw 'invalid compression type';\n", " }\n", "\n", " return this.output;\n", " };\n", " /**\n", " * 非圧縮ブロックの作成\n", " * @param {!(Array.|Uint8Array)} blockArray ブロックデータ byte array.\n", " * @param {!boolean} isFinalBlock 最後のブロックならばtrue.\n", " * @return {!(Array.|Uint8Array)} 非圧縮ブロック byte array.\n", " */\n", "\n", "\n", " Zlib$1.RawDeflate.prototype.makeNocompressBlock = function (blockArray, isFinalBlock) {\n", " /** @type {number} */\n", " var bfinal;\n", " /** @type {Zlib.RawDeflate.CompressionType} */\n", "\n", " var btype;\n", " /** @type {number} */\n", "\n", " var len;\n", " /** @type {number} */\n", "\n", " var nlen;\n", " var output = this.output;\n", " var op = this.op; // expand buffer\n", "\n", " {\n", " output = new Uint8Array(this.output.buffer);\n", "\n", " while (output.length <= op + blockArray.length + 5) {\n", " output = new Uint8Array(output.length << 1);\n", " }\n", "\n", " output.set(this.output);\n", " } // header\n", "\n", " bfinal = isFinalBlock ? 1 : 0;\n", " btype = Zlib$1.RawDeflate.CompressionType.NONE;\n", " output[op++] = bfinal | btype << 1; // length\n", "\n", " len = blockArray.length;\n", " nlen = ~len + 0x10000 & 0xffff;\n", " output[op++] = len & 0xff;\n", " output[op++] = len >>> 8 & 0xff;\n", " output[op++] = nlen & 0xff;\n", " output[op++] = nlen >>> 8 & 0xff; // copy buffer\n", "\n", " {\n", " output.set(blockArray, op);\n", " op += blockArray.length;\n", " output = output.subarray(0, op);\n", " }\n", " this.op = op;\n", " this.output = output;\n", " return output;\n", " };\n", " /**\n", " * 固定ハフマンブロックの作成\n", " * @param {!(Array.|Uint8Array)} blockArray ブロックデータ byte array.\n", " * @param {!boolean} isFinalBlock 最後のブロックならばtrue.\n", " * @return {!(Array.|Uint8Array)} 固定ハフマン符号化ブロック byte array.\n", " */\n", "\n", "\n", " Zlib$1.RawDeflate.prototype.makeFixedHuffmanBlock = function (blockArray, isFinalBlock) {\n", " /** @type {Zlib.BitStream} */\n", " var stream = new Zlib$1.BitStream(new Uint8Array(this.output.buffer), this.op);\n", " /** @type {number} */\n", "\n", " var bfinal;\n", " /** @type {Zlib.RawDeflate.CompressionType} */\n", "\n", " var btype;\n", " /** @type {!(Array.|Uint16Array)} */\n", "\n", " var data; // header\n", "\n", " bfinal = isFinalBlock ? 1 : 0;\n", " btype = Zlib$1.RawDeflate.CompressionType.FIXED;\n", " stream.writeBits(bfinal, 1, true);\n", " stream.writeBits(btype, 2, true);\n", " data = this.lz77(blockArray);\n", " this.fixedHuffman(data, stream);\n", " return stream.finish();\n", " };\n", " /**\n", " * 動的ハフマンブロックの作成\n", " * @param {!(Array.|Uint8Array)} blockArray ブロックデータ byte array.\n", " * @param {!boolean} isFinalBlock 最後のブロックならばtrue.\n", " * @return {!(Array.|Uint8Array)} 動的ハフマン符号ブロック byte array.\n", " */\n", "\n", "\n", " Zlib$1.RawDeflate.prototype.makeDynamicHuffmanBlock = function (blockArray, isFinalBlock) {\n", " /** @type {Zlib.BitStream} */\n", " var stream = new Zlib$1.BitStream(new Uint8Array(this.output.buffer), this.op);\n", " /** @type {number} */\n", "\n", " var bfinal;\n", " /** @type {Zlib.RawDeflate.CompressionType} */\n", "\n", " var btype;\n", " /** @type {!(Array.|Uint16Array)} */\n", "\n", " var data;\n", " /** @type {number} */\n", "\n", " var hlit;\n", " /** @type {number} */\n", "\n", " var hdist;\n", " /** @type {number} */\n", "\n", " var hclen;\n", " /** @const @type {Array.} */\n", "\n", " var hclenOrder = [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15];\n", " /** @type {!(Array.|Uint8Array)} */\n", "\n", " var litLenLengths;\n", " /** @type {!(Array.|Uint16Array)} */\n", "\n", " var litLenCodes;\n", " /** @type {!(Array.|Uint8Array)} */\n", "\n", " var distLengths;\n", " /** @type {!(Array.|Uint16Array)} */\n", "\n", " var distCodes;\n", " /** @type {{\n", " * codes: !(Array.|Uint32Array),\n", " * freqs: !(Array.|Uint8Array)\n", " * }} */\n", "\n", " var treeSymbols;\n", " /** @type {!(Array.|Uint8Array)} */\n", "\n", " var treeLengths;\n", " /** @type {Array} */\n", "\n", " var transLengths = new Array(19);\n", " /** @type {!(Array.|Uint16Array)} */\n", "\n", " var treeCodes;\n", " /** @type {number} */\n", "\n", " var code;\n", " /** @type {number} */\n", "\n", " var bitlen;\n", " /** @type {number} */\n", "\n", " var i;\n", " /** @type {number} */\n", "\n", " var il; // header\n", "\n", " bfinal = isFinalBlock ? 1 : 0;\n", " btype = Zlib$1.RawDeflate.CompressionType.DYNAMIC;\n", " stream.writeBits(bfinal, 1, true);\n", " stream.writeBits(btype, 2, true);\n", " data = this.lz77(blockArray); // リテラル・長さ, 距離のハフマン符号と符号長の算出\n", "\n", " litLenLengths = this.getLengths_(this.freqsLitLen, 15);\n", " litLenCodes = this.getCodesFromLengths_(litLenLengths);\n", " distLengths = this.getLengths_(this.freqsDist, 7);\n", " distCodes = this.getCodesFromLengths_(distLengths); // HLIT, HDIST の決定\n", "\n", " for (hlit = 286; hlit > 257 && litLenLengths[hlit - 1] === 0; hlit--) {}\n", "\n", " for (hdist = 30; hdist > 1 && distLengths[hdist - 1] === 0; hdist--) {} // HCLEN\n", "\n", "\n", " treeSymbols = this.getTreeSymbols_(hlit, litLenLengths, hdist, distLengths);\n", " treeLengths = this.getLengths_(treeSymbols.freqs, 7);\n", "\n", " for (i = 0; i < 19; i++) {\n", " transLengths[i] = treeLengths[hclenOrder[i]];\n", " }\n", "\n", " for (hclen = 19; hclen > 4 && transLengths[hclen - 1] === 0; hclen--) {}\n", "\n", " treeCodes = this.getCodesFromLengths_(treeLengths); // 出力\n", "\n", " stream.writeBits(hlit - 257, 5, true);\n", " stream.writeBits(hdist - 1, 5, true);\n", " stream.writeBits(hclen - 4, 4, true);\n", "\n", " for (i = 0; i < hclen; i++) {\n", " stream.writeBits(transLengths[i], 3, true);\n", " } // ツリーの出力\n", "\n", "\n", " for (i = 0, il = treeSymbols.codes.length; i < il; i++) {\n", " code = treeSymbols.codes[i];\n", " stream.writeBits(treeCodes[code], treeLengths[code], true); // extra bits\n", "\n", " if (code >= 16) {\n", " i++;\n", "\n", " switch (code) {\n", " case 16:\n", " bitlen = 2;\n", " break;\n", "\n", " case 17:\n", " bitlen = 3;\n", " break;\n", "\n", " case 18:\n", " bitlen = 7;\n", " break;\n", "\n", " default:\n", " throw 'invalid code: ' + code;\n", " }\n", "\n", " stream.writeBits(treeSymbols.codes[i], bitlen, true);\n", " }\n", " }\n", "\n", " this.dynamicHuffman(data, [litLenCodes, litLenLengths], [distCodes, distLengths], stream);\n", " return stream.finish();\n", " };\n", " /**\n", " * 動的ハフマン符号化(カスタムハフマンテーブル)\n", " * @param {!(Array.|Uint16Array)} dataArray LZ77 符号化済み byte array.\n", " * @param {!Zlib.BitStream} stream 書き込み用ビットストリーム.\n", " * @return {!Zlib.BitStream} ハフマン符号化済みビットストリームオブジェクト.\n", " */\n", "\n", "\n", " Zlib$1.RawDeflate.prototype.dynamicHuffman = function (dataArray, litLen, dist, stream) {\n", " /** @type {number} */\n", " var index;\n", " /** @type {number} */\n", "\n", " var length;\n", " /** @type {number} */\n", "\n", " var literal;\n", " /** @type {number} */\n", "\n", " var code;\n", " /** @type {number} */\n", "\n", " var litLenCodes;\n", " /** @type {number} */\n", "\n", " var litLenLengths;\n", " /** @type {number} */\n", "\n", " var distCodes;\n", " /** @type {number} */\n", "\n", " var distLengths;\n", " litLenCodes = litLen[0];\n", " litLenLengths = litLen[1];\n", " distCodes = dist[0];\n", " distLengths = dist[1]; // 符号を BitStream に書き込んでいく\n", "\n", " for (index = 0, length = dataArray.length; index < length; ++index) {\n", " literal = dataArray[index]; // literal or length\n", "\n", " stream.writeBits(litLenCodes[literal], litLenLengths[literal], true); // 長さ・距離符号\n", "\n", " if (literal > 256) {\n", " // length extra\n", " stream.writeBits(dataArray[++index], dataArray[++index], true); // distance\n", "\n", " code = dataArray[++index];\n", " stream.writeBits(distCodes[code], distLengths[code], true); // distance extra\n", "\n", " stream.writeBits(dataArray[++index], dataArray[++index], true); // 終端\n", " } else if (literal === 256) {\n", " break;\n", " }\n", " }\n", "\n", " return stream;\n", " };\n", " /**\n", " * 固定ハフマン符号化\n", " * @param {!(Array.|Uint16Array)} dataArray LZ77 符号化済み byte array.\n", " * @param {!Zlib.BitStream} stream 書き込み用ビットストリーム.\n", " * @return {!Zlib.BitStream} ハフマン符号化済みビットストリームオブジェクト.\n", " */\n", "\n", "\n", " Zlib$1.RawDeflate.prototype.fixedHuffman = function (dataArray, stream) {\n", " /** @type {number} */\n", " var index;\n", " /** @type {number} */\n", "\n", " var length;\n", " /** @type {number} */\n", "\n", " var literal; // 符号を BitStream に書き込んでいく\n", "\n", " for (index = 0, length = dataArray.length; index < length; index++) {\n", " literal = dataArray[index]; // 符号の書き込み\n", "\n", " Zlib$1.BitStream.prototype.writeBits.apply(stream, Zlib$1.RawDeflate.FixedHuffmanTable[literal]); // 長さ・距離符号\n", "\n", " if (literal > 0x100) {\n", " // length extra\n", " stream.writeBits(dataArray[++index], dataArray[++index], true); // distance\n", "\n", " stream.writeBits(dataArray[++index], 5); // distance extra\n", "\n", " stream.writeBits(dataArray[++index], dataArray[++index], true); // 終端\n", " } else if (literal === 0x100) {\n", " break;\n", " }\n", " }\n", "\n", " return stream;\n", " };\n", " /**\n", " * マッチ情報\n", " * @param {!number} length マッチした長さ.\n", " * @param {!number} backwardDistance マッチ位置との距離.\n", " * @constructor\n", " */\n", "\n", "\n", " Zlib$1.RawDeflate.Lz77Match = function (length, backwardDistance) {\n", " /** @type {number} match length. */\n", " this.length = length;\n", " /** @type {number} backward distance. */\n", "\n", " this.backwardDistance = backwardDistance;\n", " };\n", " /**\n", " * 長さ符号テーブル.\n", " * [コード, 拡張ビット, 拡張ビット長] の配列となっている.\n", " * @const\n", " * @type {!(Array.|Uint32Array)}\n", " */\n", "\n", "\n", " Zlib$1.RawDeflate.Lz77Match.LengthCodeTable = function (table) {\n", " return new Uint32Array(table);\n", " }(function () {\n", " /** @type {!Array} */\n", " var table = [];\n", " /** @type {number} */\n", "\n", " var i;\n", " /** @type {!Array.} */\n", "\n", " var c;\n", "\n", " for (i = 3; i <= 258; i++) {\n", " c = code(i);\n", " table[i] = c[2] << 24 | c[1] << 16 | c[0];\n", " }\n", " /**\n", " * @param {number} length lz77 length.\n", " * @return {!Array.} lz77 codes.\n", " */\n", "\n", "\n", " function code(length) {\n", " switch (true) {\n", " case length === 3:\n", " return [257, length - 3, 0];\n", "\n", " case length === 4:\n", " return [258, length - 4, 0];\n", "\n", " case length === 5:\n", " return [259, length - 5, 0];\n", "\n", " case length === 6:\n", " return [260, length - 6, 0];\n", "\n", " case length === 7:\n", " return [261, length - 7, 0];\n", "\n", " case length === 8:\n", " return [262, length - 8, 0];\n", "\n", " case length === 9:\n", " return [263, length - 9, 0];\n", "\n", " case length === 10:\n", " return [264, length - 10, 0];\n", "\n", " case length <= 12:\n", " return [265, length - 11, 1];\n", "\n", " case length <= 14:\n", " return [266, length - 13, 1];\n", "\n", " case length <= 16:\n", " return [267, length - 15, 1];\n", "\n", " case length <= 18:\n", " return [268, length - 17, 1];\n", "\n", " case length <= 22:\n", " return [269, length - 19, 2];\n", "\n", " case length <= 26:\n", " return [270, length - 23, 2];\n", "\n", " case length <= 30:\n", " return [271, length - 27, 2];\n", "\n", " case length <= 34:\n", " return [272, length - 31, 2];\n", "\n", " case length <= 42:\n", " return [273, length - 35, 3];\n", "\n", " case length <= 50:\n", " return [274, length - 43, 3];\n", "\n", " case length <= 58:\n", " return [275, length - 51, 3];\n", "\n", " case length <= 66:\n", " return [276, length - 59, 3];\n", "\n", " case length <= 82:\n", " return [277, length - 67, 4];\n", "\n", " case length <= 98:\n", " return [278, length - 83, 4];\n", "\n", " case length <= 114:\n", " return [279, length - 99, 4];\n", "\n", " case length <= 130:\n", " return [280, length - 115, 4];\n", "\n", " case length <= 162:\n", " return [281, length - 131, 5];\n", "\n", " case length <= 194:\n", " return [282, length - 163, 5];\n", "\n", " case length <= 226:\n", " return [283, length - 195, 5];\n", "\n", " case length <= 257:\n", " return [284, length - 227, 5];\n", "\n", " case length === 258:\n", " return [285, length - 258, 0];\n", "\n", " default:\n", " throw 'invalid length: ' + length;\n", " }\n", " }\n", "\n", " return table;\n", " }());\n", " /**\n", " * 距離符号テーブル\n", " * @param {!number} dist 距離.\n", " * @return {!Array.} コード、拡張ビット、拡張ビット長の配列.\n", " * @private\n", " */\n", "\n", "\n", " Zlib$1.RawDeflate.Lz77Match.prototype.getDistanceCode_ = function (dist) {\n", " /** @type {!Array.} distance code table. */\n", " var r;\n", "\n", " switch (true) {\n", " case dist === 1:\n", " r = [0, dist - 1, 0];\n", " break;\n", "\n", " case dist === 2:\n", " r = [1, dist - 2, 0];\n", " break;\n", "\n", " case dist === 3:\n", " r = [2, dist - 3, 0];\n", " break;\n", "\n", " case dist === 4:\n", " r = [3, dist - 4, 0];\n", " break;\n", "\n", " case dist <= 6:\n", " r = [4, dist - 5, 1];\n", " break;\n", "\n", " case dist <= 8:\n", " r = [5, dist - 7, 1];\n", " break;\n", "\n", " case dist <= 12:\n", " r = [6, dist - 9, 2];\n", " break;\n", "\n", " case dist <= 16:\n", " r = [7, dist - 13, 2];\n", " break;\n", "\n", " case dist <= 24:\n", " r = [8, dist - 17, 3];\n", " break;\n", "\n", " case dist <= 32:\n", " r = [9, dist - 25, 3];\n", " break;\n", "\n", " case dist <= 48:\n", " r = [10, dist - 33, 4];\n", " break;\n", "\n", " case dist <= 64:\n", " r = [11, dist - 49, 4];\n", " break;\n", "\n", " case dist <= 96:\n", " r = [12, dist - 65, 5];\n", " break;\n", "\n", " case dist <= 128:\n", " r = [13, dist - 97, 5];\n", " break;\n", "\n", " case dist <= 192:\n", " r = [14, dist - 129, 6];\n", " break;\n", "\n", " case dist <= 256:\n", " r = [15, dist - 193, 6];\n", " break;\n", "\n", " case dist <= 384:\n", " r = [16, dist - 257, 7];\n", " break;\n", "\n", " case dist <= 512:\n", " r = [17, dist - 385, 7];\n", " break;\n", "\n", " case dist <= 768:\n", " r = [18, dist - 513, 8];\n", " break;\n", "\n", " case dist <= 1024:\n", " r = [19, dist - 769, 8];\n", " break;\n", "\n", " case dist <= 1536:\n", " r = [20, dist - 1025, 9];\n", " break;\n", "\n", " case dist <= 2048:\n", " r = [21, dist - 1537, 9];\n", " break;\n", "\n", " case dist <= 3072:\n", " r = [22, dist - 2049, 10];\n", " break;\n", "\n", " case dist <= 4096:\n", " r = [23, dist - 3073, 10];\n", " break;\n", "\n", " case dist <= 6144:\n", " r = [24, dist - 4097, 11];\n", " break;\n", "\n", " case dist <= 8192:\n", " r = [25, dist - 6145, 11];\n", " break;\n", "\n", " case dist <= 12288:\n", " r = [26, dist - 8193, 12];\n", " break;\n", "\n", " case dist <= 16384:\n", " r = [27, dist - 12289, 12];\n", " break;\n", "\n", " case dist <= 24576:\n", " r = [28, dist - 16385, 13];\n", " break;\n", "\n", " case dist <= 32768:\n", " r = [29, dist - 24577, 13];\n", " break;\n", "\n", " default:\n", " throw 'invalid distance';\n", " }\n", "\n", " return r;\n", " };\n", " /**\n", " * マッチ情報を LZ77 符号化配列で返す.\n", " * なお、ここでは以下の内部仕様で符号化している\n", " * [ CODE, EXTRA-BIT-LEN, EXTRA, CODE, EXTRA-BIT-LEN, EXTRA ]\n", " * @return {!Array.} LZ77 符号化 byte array.\n", " */\n", "\n", "\n", " Zlib$1.RawDeflate.Lz77Match.prototype.toLz77Array = function () {\n", " /** @type {number} */\n", " var length = this.length;\n", " /** @type {number} */\n", "\n", " var dist = this.backwardDistance;\n", " /** @type {Array} */\n", "\n", " var codeArray = [];\n", " /** @type {number} */\n", "\n", " var pos = 0;\n", " /** @type {!Array.} */\n", "\n", " var code; // length\n", "\n", " code = Zlib$1.RawDeflate.Lz77Match.LengthCodeTable[length];\n", " codeArray[pos++] = code & 0xffff;\n", " codeArray[pos++] = code >> 16 & 0xff;\n", " codeArray[pos++] = code >> 24; // distance\n", "\n", " code = this.getDistanceCode_(dist);\n", " codeArray[pos++] = code[0];\n", " codeArray[pos++] = code[1];\n", " codeArray[pos++] = code[2];\n", " return codeArray;\n", " };\n", " /**\n", " * LZ77 実装\n", " * @param {!(Array.|Uint8Array)} dataArray LZ77 符号化するバイト配列.\n", " * @return {!(Array.|Uint16Array)} LZ77 符号化した配列.\n", " */\n", "\n", "\n", " Zlib$1.RawDeflate.prototype.lz77 = function (dataArray) {\n", " /** @type {number} input position */\n", " var position;\n", " /** @type {number} input length */\n", "\n", " var length;\n", " /** @type {number} loop counter */\n", "\n", " var i;\n", " /** @type {number} loop limiter */\n", "\n", " var il;\n", " /** @type {number} chained-hash-table key */\n", "\n", " var matchKey;\n", " /** @type {Object.>} chained-hash-table */\n", "\n", " var table = {};\n", " /** @const @type {number} */\n", "\n", " var windowSize = Zlib$1.RawDeflate.WindowSize;\n", " /** @type {Array.} match list */\n", "\n", " var matchList;\n", " /** @type {Zlib.RawDeflate.Lz77Match} longest match */\n", "\n", " var longestMatch;\n", " /** @type {Zlib.RawDeflate.Lz77Match} previous longest match */\n", "\n", " var prevMatch;\n", " /** @type {!(Array.|Uint16Array)} lz77 buffer */\n", "\n", " var lz77buf = new Uint16Array(dataArray.length * 2);\n", " /** @type {number} lz77 output buffer pointer */\n", "\n", " var pos = 0;\n", " /** @type {number} lz77 skip length */\n", "\n", " var skipLength = 0;\n", " /** @type {!(Array.|Uint32Array)} */\n", "\n", " var freqsLitLen = new Uint32Array(286);\n", " /** @type {!(Array.|Uint32Array)} */\n", "\n", " var freqsDist = new Uint32Array(30);\n", " /** @type {number} */\n", "\n", " var lazy = this.lazy;\n", " /** @type {*} temporary variable */\n", "\n", " var tmp;\n", " freqsLitLen[256] = 1; // EOB の最低出現回数は 1\n", "\n", " /**\n", " * マッチデータの書き込み\n", " * @param {Zlib.RawDeflate.Lz77Match} match LZ77 Match data.\n", " * @param {!number} offset スキップ開始位置(相対指定).\n", " * @private\n", " */\n", "\n", " function writeMatch(match, offset) {\n", " /** @type {Array.} */\n", " var lz77Array = match.toLz77Array();\n", " /** @type {number} */\n", "\n", " var i;\n", " /** @type {number} */\n", "\n", " var il;\n", "\n", " for (i = 0, il = lz77Array.length; i < il; ++i) {\n", " lz77buf[pos++] = lz77Array[i];\n", " }\n", "\n", " freqsLitLen[lz77Array[0]]++;\n", " freqsDist[lz77Array[3]]++;\n", " skipLength = match.length + offset - 1;\n", " prevMatch = null;\n", " } // LZ77 符号化\n", "\n", "\n", " for (position = 0, length = dataArray.length; position < length; ++position) {\n", " // ハッシュキーの作成\n", " for (matchKey = 0, i = 0, il = Zlib$1.RawDeflate.Lz77MinLength; i < il; ++i) {\n", " if (position + i === length) {\n", " break;\n", " }\n", "\n", " matchKey = matchKey << 8 | dataArray[position + i];\n", " } // テーブルが未定義だったら作成する\n", "\n", "\n", " if (table[matchKey] === void 0) {\n", " table[matchKey] = [];\n", " }\n", "\n", " matchList = table[matchKey]; // skip\n", "\n", " if (skipLength-- > 0) {\n", " matchList.push(position);\n", " continue;\n", " } // マッチテーブルの更新 (最大戻り距離を超えているものを削除する)\n", "\n", "\n", " while (matchList.length > 0 && position - matchList[0] > windowSize) {\n", " matchList.shift();\n", " } // データ末尾でマッチしようがない場合はそのまま流しこむ\n", "\n", "\n", " if (position + Zlib$1.RawDeflate.Lz77MinLength >= length) {\n", " if (prevMatch) {\n", " writeMatch(prevMatch, -1);\n", " }\n", "\n", " for (i = 0, il = length - position; i < il; ++i) {\n", " tmp = dataArray[position + i];\n", " lz77buf[pos++] = tmp;\n", " ++freqsLitLen[tmp];\n", " }\n", "\n", " break;\n", " } // マッチ候補から最長のものを探す\n", "\n", "\n", " if (matchList.length > 0) {\n", " longestMatch = this.searchLongestMatch_(dataArray, position, matchList);\n", "\n", " if (prevMatch) {\n", " // 現在のマッチの方が前回のマッチよりも長い\n", " if (prevMatch.length < longestMatch.length) {\n", " // write previous literal\n", " tmp = dataArray[position - 1];\n", " lz77buf[pos++] = tmp;\n", " ++freqsLitLen[tmp]; // write current match\n", "\n", " writeMatch(longestMatch, 0);\n", " } else {\n", " // write previous match\n", " writeMatch(prevMatch, -1);\n", " }\n", " } else if (longestMatch.length < lazy) {\n", " prevMatch = longestMatch;\n", " } else {\n", " writeMatch(longestMatch, 0);\n", " } // 前回マッチしていて今回マッチがなかったら前回のを採用\n", "\n", " } else if (prevMatch) {\n", " writeMatch(prevMatch, -1);\n", " } else {\n", " tmp = dataArray[position];\n", " lz77buf[pos++] = tmp;\n", " ++freqsLitLen[tmp];\n", " }\n", "\n", " matchList.push(position); // マッチテーブルに現在の位置を保存\n", " } // 終端処理\n", "\n", "\n", " lz77buf[pos++] = 256;\n", " freqsLitLen[256]++;\n", " this.freqsLitLen = freqsLitLen;\n", " this.freqsDist = freqsDist;\n", " return (\n", " /** @type {!(Uint16Array|Array.)} */\n", " lz77buf.subarray(0, pos)\n", " );\n", " };\n", " /**\n", " * マッチした候補の中から最長一致を探す\n", " * @param {!Object} data plain data byte array.\n", " * @param {!number} position plain data byte array position.\n", " * @param {!Array.} matchList 候補となる位置の配列.\n", " * @return {!Zlib.RawDeflate.Lz77Match} 最長かつ最短距離のマッチオブジェクト.\n", " * @private\n", " */\n", "\n", "\n", " Zlib$1.RawDeflate.prototype.searchLongestMatch_ = function (data, position, matchList) {\n", " var match,\n", " currentMatch,\n", " matchMax = 0,\n", " matchLength,\n", " i,\n", " j,\n", " l,\n", " dl = data.length; // 候補を後ろから 1 つずつ絞り込んでゆく\n", "\n", " permatch: for (i = 0, l = matchList.length; i < l; i++) {\n", " match = matchList[l - i - 1];\n", " matchLength = Zlib$1.RawDeflate.Lz77MinLength; // 前回までの最長一致を末尾から一致検索する\n", "\n", " if (matchMax > Zlib$1.RawDeflate.Lz77MinLength) {\n", " for (j = matchMax; j > Zlib$1.RawDeflate.Lz77MinLength; j--) {\n", " if (data[match + j - 1] !== data[position + j - 1]) {\n", " continue permatch;\n", " }\n", " }\n", "\n", " matchLength = matchMax;\n", " } // 最長一致探索\n", "\n", "\n", " while (matchLength < Zlib$1.RawDeflate.Lz77MaxLength && position + matchLength < dl && data[match + matchLength] === data[position + matchLength]) {\n", " ++matchLength;\n", " } // マッチ長が同じ場合は後方を優先\n", "\n", "\n", " if (matchLength > matchMax) {\n", " currentMatch = match;\n", " matchMax = matchLength;\n", " } // 最長が確定したら後の処理は省略\n", "\n", "\n", " if (matchLength === Zlib$1.RawDeflate.Lz77MaxLength) {\n", " break;\n", " }\n", " }\n", "\n", " return new Zlib$1.RawDeflate.Lz77Match(matchMax, position - currentMatch);\n", " };\n", " /**\n", " * Tree-Transmit Symbols の算出\n", " * reference: PuTTY Deflate implementation\n", " * @param {number} hlit HLIT.\n", " * @param {!(Array.|Uint8Array)} litlenLengths リテラルと長さ符号の符号長配列.\n", " * @param {number} hdist HDIST.\n", " * @param {!(Array.|Uint8Array)} distLengths 距離符号の符号長配列.\n", " * @return {{\n", " * codes: !(Array.|Uint32Array),\n", " * freqs: !(Array.|Uint8Array)\n", " * }} Tree-Transmit Symbols.\n", " */\n", "\n", "\n", " Zlib$1.RawDeflate.prototype.getTreeSymbols_ = function (hlit, litlenLengths, hdist, distLengths) {\n", " var src = new Uint32Array(hlit + hdist),\n", " i,\n", " j,\n", " runLength,\n", " l,\n", " result = new Uint32Array(286 + 30),\n", " nResult,\n", " rpt,\n", " freqs = new Uint8Array(19);\n", " j = 0;\n", "\n", " for (i = 0; i < hlit; i++) {\n", " src[j++] = litlenLengths[i];\n", " }\n", "\n", " for (i = 0; i < hdist; i++) {\n", " src[j++] = distLengths[i];\n", " } // 符号化\n", "\n", "\n", " nResult = 0;\n", "\n", " for (i = 0, l = src.length; i < l; i += j) {\n", " // Run Length Encoding\n", " for (j = 1; i + j < l && src[i + j] === src[i]; ++j) {}\n", "\n", " runLength = j;\n", "\n", " if (src[i] === 0) {\n", " // 0 の繰り返しが 3 回未満ならばそのまま\n", " if (runLength < 3) {\n", " while (runLength-- > 0) {\n", " result[nResult++] = 0;\n", " freqs[0]++;\n", " }\n", " } else {\n", " while (runLength > 0) {\n", " // 繰り返しは最大 138 までなので切り詰める\n", " rpt = runLength < 138 ? runLength : 138;\n", "\n", " if (rpt > runLength - 3 && rpt < runLength) {\n", " rpt = runLength - 3;\n", " } // 3-10 回 -> 17\n", "\n", "\n", " if (rpt <= 10) {\n", " result[nResult++] = 17;\n", " result[nResult++] = rpt - 3;\n", " freqs[17]++; // 11-138 回 -> 18\n", " } else {\n", " result[nResult++] = 18;\n", " result[nResult++] = rpt - 11;\n", " freqs[18]++;\n", " }\n", "\n", " runLength -= rpt;\n", " }\n", " }\n", " } else {\n", " result[nResult++] = src[i];\n", " freqs[src[i]]++;\n", " runLength--; // 繰り返し回数が3回未満ならばランレングス符号は要らない\n", "\n", " if (runLength < 3) {\n", " while (runLength-- > 0) {\n", " result[nResult++] = src[i];\n", " freqs[src[i]]++;\n", " } // 3 回以上ならばランレングス符号化\n", "\n", " } else {\n", " while (runLength > 0) {\n", " // runLengthを 3-6 で分割\n", " rpt = runLength < 6 ? runLength : 6;\n", "\n", " if (rpt > runLength - 3 && rpt < runLength) {\n", " rpt = runLength - 3;\n", " }\n", "\n", " result[nResult++] = 16;\n", " result[nResult++] = rpt - 3;\n", " freqs[16]++;\n", " runLength -= rpt;\n", " }\n", " }\n", " }\n", " }\n", "\n", " return {\n", " codes: result.subarray(0, nResult),\n", " freqs: freqs\n", " };\n", " };\n", " /**\n", " * ハフマン符号の長さを取得する\n", " * @param {!(Array.|Uint8Array|Uint32Array)} freqs 出現カウント.\n", " * @param {number} limit 符号長の制限.\n", " * @return {!(Array.|Uint8Array)} 符号長配列.\n", " * @private\n", " */\n", "\n", "\n", " Zlib$1.RawDeflate.prototype.getLengths_ = function (freqs, limit) {\n", " /** @type {number} */\n", " var nSymbols = freqs.length;\n", " /** @type {Zlib.Heap} */\n", "\n", " var heap = new Zlib$1.Heap(2 * Zlib$1.RawDeflate.HUFMAX);\n", " /** @type {!(Array.|Uint8Array)} */\n", "\n", " var length = new Uint8Array(nSymbols);\n", " /** @type {Array} */\n", "\n", " var nodes;\n", " /** @type {!(Array.|Uint32Array)} */\n", "\n", " var values;\n", " /** @type {!(Array.|Uint8Array)} */\n", "\n", " var codeLength;\n", " /** @type {number} */\n", "\n", " var i;\n", " /** @type {number} */\n", "\n", " var il; // ヒープの構築\n", "\n", " for (i = 0; i < nSymbols; ++i) {\n", " if (freqs[i] > 0) {\n", " heap.push(i, freqs[i]);\n", " }\n", " }\n", "\n", " nodes = new Array(heap.length / 2);\n", " values = new Uint32Array(heap.length / 2); // 非 0 の要素が一つだけだった場合は、そのシンボルに符号長 1 を割り当てて終了\n", "\n", " if (nodes.length === 1) {\n", " length[heap.pop().index] = 1;\n", " return length;\n", " } // Reverse Package Merge Algorithm による Canonical Huffman Code の符号長決定\n", "\n", "\n", " for (i = 0, il = heap.length / 2; i < il; ++i) {\n", " nodes[i] = heap.pop();\n", " values[i] = nodes[i].value;\n", " }\n", "\n", " codeLength = this.reversePackageMerge_(values, values.length, limit);\n", "\n", " for (i = 0, il = nodes.length; i < il; ++i) {\n", " length[nodes[i].index] = codeLength[i];\n", " }\n", "\n", " return length;\n", " };\n", " /**\n", " * Reverse Package Merge Algorithm.\n", " * @param {!(Array.|Uint32Array)} freqs sorted probability.\n", " * @param {number} symbols number of symbols.\n", " * @param {number} limit code length limit.\n", " * @return {!(Array.|Uint8Array)} code lengths.\n", " */\n", "\n", "\n", " Zlib$1.RawDeflate.prototype.reversePackageMerge_ = function (freqs, symbols, limit) {\n", " /** @type {!(Array.|Uint16Array)} */\n", " var minimumCost = new Uint16Array(limit);\n", " /** @type {!(Array.|Uint8Array)} */\n", "\n", " var flag = new Uint8Array(limit);\n", " /** @type {!(Array.|Uint8Array)} */\n", "\n", " var codeLength = new Uint8Array(symbols);\n", " /** @type {Array} */\n", "\n", " var value = new Array(limit);\n", " /** @type {Array} */\n", "\n", " var type = new Array(limit);\n", " /** @type {Array.} */\n", "\n", " var currentPosition = new Array(limit);\n", " /** @type {number} */\n", "\n", " var excess = (1 << limit) - symbols;\n", " /** @type {number} */\n", "\n", " var half = 1 << limit - 1;\n", " /** @type {number} */\n", "\n", " var i;\n", " /** @type {number} */\n", "\n", " var j;\n", " /** @type {number} */\n", "\n", " var t;\n", " /** @type {number} */\n", "\n", " var weight;\n", " /** @type {number} */\n", "\n", " var next;\n", " /**\n", " * @param {number} j\n", " */\n", "\n", " function takePackage(j) {\n", " /** @type {number} */\n", " var x = type[j][currentPosition[j]];\n", "\n", " if (x === symbols) {\n", " takePackage(j + 1);\n", " takePackage(j + 1);\n", " } else {\n", " --codeLength[x];\n", " }\n", "\n", " ++currentPosition[j];\n", " }\n", "\n", " minimumCost[limit - 1] = symbols;\n", "\n", " for (j = 0; j < limit; ++j) {\n", " if (excess < half) {\n", " flag[j] = 0;\n", " } else {\n", " flag[j] = 1;\n", " excess -= half;\n", " }\n", "\n", " excess <<= 1;\n", " minimumCost[limit - 2 - j] = (minimumCost[limit - 1 - j] / 2 | 0) + symbols;\n", " }\n", "\n", " minimumCost[0] = flag[0];\n", " value[0] = new Array(minimumCost[0]);\n", " type[0] = new Array(minimumCost[0]);\n", "\n", " for (j = 1; j < limit; ++j) {\n", " if (minimumCost[j] > 2 * minimumCost[j - 1] + flag[j]) {\n", " minimumCost[j] = 2 * minimumCost[j - 1] + flag[j];\n", " }\n", "\n", " value[j] = new Array(minimumCost[j]);\n", " type[j] = new Array(minimumCost[j]);\n", " }\n", "\n", " for (i = 0; i < symbols; ++i) {\n", " codeLength[i] = limit;\n", " }\n", "\n", " for (t = 0; t < minimumCost[limit - 1]; ++t) {\n", " value[limit - 1][t] = freqs[t];\n", " type[limit - 1][t] = t;\n", " }\n", "\n", " for (i = 0; i < limit; ++i) {\n", " currentPosition[i] = 0;\n", " }\n", "\n", " if (flag[limit - 1] === 1) {\n", " --codeLength[0];\n", " ++currentPosition[limit - 1];\n", " }\n", "\n", " for (j = limit - 2; j >= 0; --j) {\n", " i = 0;\n", " weight = 0;\n", " next = currentPosition[j + 1];\n", "\n", " for (t = 0; t < minimumCost[j]; t++) {\n", " weight = value[j + 1][next] + value[j + 1][next + 1];\n", "\n", " if (weight > freqs[i]) {\n", " value[j][t] = weight;\n", " type[j][t] = symbols;\n", " next += 2;\n", " } else {\n", " value[j][t] = freqs[i];\n", " type[j][t] = i;\n", " ++i;\n", " }\n", " }\n", "\n", " currentPosition[j] = 0;\n", "\n", " if (flag[j] === 1) {\n", " takePackage(j);\n", " }\n", " }\n", "\n", " return codeLength;\n", " };\n", " /**\n", " * 符号長配列からハフマン符号を取得する\n", " * reference: PuTTY Deflate implementation\n", " * @param {!(Array.|Uint8Array)} lengths 符号長配列.\n", " * @return {!(Array.|Uint16Array)} ハフマン符号配列.\n", " * @private\n", " */\n", "\n", "\n", " Zlib$1.RawDeflate.prototype.getCodesFromLengths_ = function (lengths) {\n", " var codes = new Uint16Array(lengths.length),\n", " count = [],\n", " startCode = [],\n", " code = 0,\n", " i,\n", " il,\n", " j,\n", " m; // Count the codes of each length.\n", "\n", " for (i = 0, il = lengths.length; i < il; i++) {\n", " count[lengths[i]] = (count[lengths[i]] | 0) + 1;\n", " } // Determine the starting code for each length block.\n", "\n", "\n", " for (i = 1, il = Zlib$1.RawDeflate.MaxCodeLength; i <= il; i++) {\n", " startCode[i] = code;\n", " code += count[i] | 0;\n", " code <<= 1;\n", " } // Determine the code for each symbol. Mirrored, of course.\n", "\n", "\n", " for (i = 0, il = lengths.length; i < il; i++) {\n", " code = startCode[lengths[i]];\n", " startCode[lengths[i]] += 1;\n", " codes[i] = 0;\n", "\n", " for (j = 0, m = lengths[i]; j < m; j++) {\n", " codes[i] = codes[i] << 1 | code & 1;\n", " code >>>= 1;\n", " }\n", " }\n", "\n", " return codes;\n", " };\n", " /**\n", " * @param {!(Array.|Uint8Array)} input input buffer.\n", " * @param {Object=} opt_params options.\n", " * @constructor\n", " */\n", "\n", "\n", " Zlib$1.Unzip = function (input, opt_params) {\n", " opt_params = opt_params || {};\n", " /** @type {!(Array.|Uint8Array)} */\n", "\n", " this.input = input instanceof Array ? new Uint8Array(input) : input;\n", " /** @type {number} */\n", "\n", " this.ip = 0;\n", " /** @type {number} */\n", "\n", " this.eocdrOffset;\n", " /** @type {number} */\n", "\n", " this.numberOfThisDisk;\n", " /** @type {number} */\n", "\n", " this.startDisk;\n", " /** @type {number} */\n", "\n", " this.totalEntriesThisDisk;\n", " /** @type {number} */\n", "\n", " this.totalEntries;\n", " /** @type {number} */\n", "\n", " this.centralDirectorySize;\n", " /** @type {number} */\n", "\n", " this.centralDirectoryOffset;\n", " /** @type {number} */\n", "\n", " this.commentLength;\n", " /** @type {(Array.|Uint8Array)} */\n", "\n", " this.comment;\n", " /** @type {Array.} */\n", "\n", " this.fileHeaderList;\n", " /** @type {Object.} */\n", "\n", " this.filenameToIndex;\n", " /** @type {boolean} */\n", "\n", " this.verify = opt_params['verify'] || false;\n", " /** @type {(Array.|Uint8Array)} */\n", "\n", " this.password = opt_params['password'];\n", " };\n", "\n", " Zlib$1.Unzip.CompressionMethod = Zlib$1.Zip.CompressionMethod;\n", " /**\n", " * @type {Array.}\n", " * @const\n", " */\n", "\n", " Zlib$1.Unzip.FileHeaderSignature = Zlib$1.Zip.FileHeaderSignature;\n", " /**\n", " * @type {Array.}\n", " * @const\n", " */\n", "\n", " Zlib$1.Unzip.LocalFileHeaderSignature = Zlib$1.Zip.LocalFileHeaderSignature;\n", " /**\n", " * @type {Array.}\n", " * @const\n", " */\n", "\n", " Zlib$1.Unzip.CentralDirectorySignature = Zlib$1.Zip.CentralDirectorySignature;\n", " /**\n", " * @param {!(Array.|Uint8Array)} input input buffer.\n", " * @param {number} ip input position.\n", " * @constructor\n", " */\n", "\n", " Zlib$1.Unzip.FileHeader = function (input, ip) {\n", " /** @type {!(Array.|Uint8Array)} */\n", " this.input = input;\n", " /** @type {number} */\n", "\n", " this.offset = ip;\n", " /** @type {number} */\n", "\n", " this.length;\n", " /** @type {number} */\n", "\n", " this.version;\n", " /** @type {number} */\n", "\n", " this.os;\n", " /** @type {number} */\n", "\n", " this.needVersion;\n", " /** @type {number} */\n", "\n", " this.flags;\n", " /** @type {number} */\n", "\n", " this.compression;\n", " /** @type {number} */\n", "\n", " this.time;\n", " /** @type {number} */\n", "\n", " this.date;\n", " /** @type {number} */\n", "\n", " this.crc32;\n", " /** @type {number} */\n", "\n", " this.compressedSize;\n", " /** @type {number} */\n", "\n", " this.plainSize;\n", " /** @type {number} */\n", "\n", " this.fileNameLength;\n", " /** @type {number} */\n", "\n", " this.extraFieldLength;\n", " /** @type {number} */\n", "\n", " this.fileCommentLength;\n", " /** @type {number} */\n", "\n", " this.diskNumberStart;\n", " /** @type {number} */\n", "\n", " this.internalFileAttributes;\n", " /** @type {number} */\n", "\n", " this.externalFileAttributes;\n", " /** @type {number} */\n", "\n", " this.relativeOffset;\n", " /** @type {string} */\n", "\n", " this.filename;\n", " /** @type {!(Array.|Uint8Array)} */\n", "\n", " this.extraField;\n", " /** @type {!(Array.|Uint8Array)} */\n", "\n", " this.comment;\n", " };\n", "\n", " Zlib$1.Unzip.FileHeader.prototype.parse = function () {\n", " /** @type {!(Array.|Uint8Array)} */\n", " var input = this.input;\n", " /** @type {number} */\n", "\n", " var ip = this.offset; // central file header signature\n", "\n", " if (input[ip++] !== Zlib$1.Unzip.FileHeaderSignature[0] || input[ip++] !== Zlib$1.Unzip.FileHeaderSignature[1] || input[ip++] !== Zlib$1.Unzip.FileHeaderSignature[2] || input[ip++] !== Zlib$1.Unzip.FileHeaderSignature[3]) {\n", " throw new Error('invalid file header signature');\n", " } // version made by\n", "\n", "\n", " this.version = input[ip++];\n", " this.os = input[ip++]; // version needed to extract\n", "\n", " this.needVersion = input[ip++] | input[ip++] << 8; // general purpose bit flag\n", "\n", " this.flags = input[ip++] | input[ip++] << 8; // compression method\n", "\n", " this.compression = input[ip++] | input[ip++] << 8; // last mod file time\n", "\n", " this.time = input[ip++] | input[ip++] << 8; //last mod file date\n", "\n", " this.date = input[ip++] | input[ip++] << 8; // crc-32\n", "\n", " this.crc32 = (input[ip++] | input[ip++] << 8 | input[ip++] << 16 | input[ip++] << 24) >>> 0; // compressed size\n", "\n", " this.compressedSize = (input[ip++] | input[ip++] << 8 | input[ip++] << 16 | input[ip++] << 24) >>> 0; // uncompressed size\n", "\n", " this.plainSize = (input[ip++] | input[ip++] << 8 | input[ip++] << 16 | input[ip++] << 24) >>> 0; // file name length\n", "\n", " this.fileNameLength = input[ip++] | input[ip++] << 8; // extra field length\n", "\n", " this.extraFieldLength = input[ip++] | input[ip++] << 8; // file comment length\n", "\n", " this.fileCommentLength = input[ip++] | input[ip++] << 8; // disk number start\n", "\n", " this.diskNumberStart = input[ip++] | input[ip++] << 8; // internal file attributes\n", "\n", " this.internalFileAttributes = input[ip++] | input[ip++] << 8; // external file attributes\n", "\n", " this.externalFileAttributes = input[ip++] | input[ip++] << 8 | input[ip++] << 16 | input[ip++] << 24; // relative offset of local header\n", "\n", " this.relativeOffset = (input[ip++] | input[ip++] << 8 | input[ip++] << 16 | input[ip++] << 24) >>> 0; // file name\n", "\n", " this.filename = String.fromCharCode.apply(null, input.subarray(ip, ip += this.fileNameLength)); // extra field\n", "\n", " this.extraField = input.subarray(ip, ip += this.extraFieldLength); // file comment\n", "\n", " this.comment = input.subarray(ip, ip + this.fileCommentLength);\n", " this.length = ip - this.offset;\n", " };\n", " /**\n", " * @param {!(Array.|Uint8Array)} input input buffer.\n", " * @param {number} ip input position.\n", " * @constructor\n", " */\n", "\n", "\n", " Zlib$1.Unzip.LocalFileHeader = function (input, ip) {\n", " /** @type {!(Array.|Uint8Array)} */\n", " this.input = input;\n", " /** @type {number} */\n", "\n", " this.offset = ip;\n", " /** @type {number} */\n", "\n", " this.length;\n", " /** @type {number} */\n", "\n", " this.needVersion;\n", " /** @type {number} */\n", "\n", " this.flags;\n", " /** @type {number} */\n", "\n", " this.compression;\n", " /** @type {number} */\n", "\n", " this.time;\n", " /** @type {number} */\n", "\n", " this.date;\n", " /** @type {number} */\n", "\n", " this.crc32;\n", " /** @type {number} */\n", "\n", " this.compressedSize;\n", " /** @type {number} */\n", "\n", " this.plainSize;\n", " /** @type {number} */\n", "\n", " this.fileNameLength;\n", " /** @type {number} */\n", "\n", " this.extraFieldLength;\n", " /** @type {string} */\n", "\n", " this.filename;\n", " /** @type {!(Array.|Uint8Array)} */\n", "\n", " this.extraField;\n", " };\n", "\n", " Zlib$1.Unzip.LocalFileHeader.Flags = Zlib$1.Zip.Flags;\n", "\n", " Zlib$1.Unzip.LocalFileHeader.prototype.parse = function () {\n", " /** @type {!(Array.|Uint8Array)} */\n", " var input = this.input;\n", " /** @type {number} */\n", "\n", " var ip = this.offset; // local file header signature\n", "\n", " if (input[ip++] !== Zlib$1.Unzip.LocalFileHeaderSignature[0] || input[ip++] !== Zlib$1.Unzip.LocalFileHeaderSignature[1] || input[ip++] !== Zlib$1.Unzip.LocalFileHeaderSignature[2] || input[ip++] !== Zlib$1.Unzip.LocalFileHeaderSignature[3]) {\n", " throw new Error('invalid local file header signature');\n", " } // version needed to extract\n", "\n", "\n", " this.needVersion = input[ip++] | input[ip++] << 8; // general purpose bit flag\n", "\n", " this.flags = input[ip++] | input[ip++] << 8; // compression method\n", "\n", " this.compression = input[ip++] | input[ip++] << 8; // last mod file time\n", "\n", " this.time = input[ip++] | input[ip++] << 8; //last mod file date\n", "\n", " this.date = input[ip++] | input[ip++] << 8; // crc-32\n", "\n", " this.crc32 = (input[ip++] | input[ip++] << 8 | input[ip++] << 16 | input[ip++] << 24) >>> 0; // compressed size\n", "\n", " this.compressedSize = (input[ip++] | input[ip++] << 8 | input[ip++] << 16 | input[ip++] << 24) >>> 0; // uncompressed size\n", "\n", " this.plainSize = (input[ip++] | input[ip++] << 8 | input[ip++] << 16 | input[ip++] << 24) >>> 0; // file name length\n", "\n", " this.fileNameLength = input[ip++] | input[ip++] << 8; // extra field length\n", "\n", " this.extraFieldLength = input[ip++] | input[ip++] << 8; // file name\n", "\n", " this.filename = String.fromCharCode.apply(null, input.subarray(ip, ip += this.fileNameLength)); // extra field\n", "\n", " this.extraField = input.subarray(ip, ip += this.extraFieldLength);\n", " this.length = ip - this.offset;\n", " };\n", "\n", " Zlib$1.Unzip.prototype.searchEndOfCentralDirectoryRecord = function () {\n", " /** @type {!(Array.|Uint8Array)} */\n", " var input = this.input;\n", " /** @type {number} */\n", "\n", " var ip;\n", "\n", " for (ip = input.length - 12; ip > 0; --ip) {\n", " if (input[ip] === Zlib$1.Unzip.CentralDirectorySignature[0] && input[ip + 1] === Zlib$1.Unzip.CentralDirectorySignature[1] && input[ip + 2] === Zlib$1.Unzip.CentralDirectorySignature[2] && input[ip + 3] === Zlib$1.Unzip.CentralDirectorySignature[3]) {\n", " this.eocdrOffset = ip;\n", " return;\n", " }\n", " }\n", "\n", " throw new Error('End of Central Directory Record not found');\n", " };\n", "\n", " Zlib$1.Unzip.prototype.parseEndOfCentralDirectoryRecord = function () {\n", " /** @type {!(Array.|Uint8Array)} */\n", " var input = this.input;\n", " /** @type {number} */\n", "\n", " var ip;\n", "\n", " if (!this.eocdrOffset) {\n", " this.searchEndOfCentralDirectoryRecord();\n", " }\n", "\n", " ip = this.eocdrOffset; // signature\n", "\n", " if (input[ip++] !== Zlib$1.Unzip.CentralDirectorySignature[0] || input[ip++] !== Zlib$1.Unzip.CentralDirectorySignature[1] || input[ip++] !== Zlib$1.Unzip.CentralDirectorySignature[2] || input[ip++] !== Zlib$1.Unzip.CentralDirectorySignature[3]) {\n", " throw new Error('invalid signature');\n", " } // number of this disk\n", "\n", "\n", " this.numberOfThisDisk = input[ip++] | input[ip++] << 8; // number of the disk with the start of the central directory\n", "\n", " this.startDisk = input[ip++] | input[ip++] << 8; // total number of entries in the central directory on this disk\n", "\n", " this.totalEntriesThisDisk = input[ip++] | input[ip++] << 8; // total number of entries in the central directory\n", "\n", " this.totalEntries = input[ip++] | input[ip++] << 8; // size of the central directory\n", "\n", " this.centralDirectorySize = (input[ip++] | input[ip++] << 8 | input[ip++] << 16 | input[ip++] << 24) >>> 0; // offset of start of central directory with respect to the starting disk number\n", "\n", " this.centralDirectoryOffset = (input[ip++] | input[ip++] << 8 | input[ip++] << 16 | input[ip++] << 24) >>> 0; // .ZIP file comment length\n", "\n", " this.commentLength = input[ip++] | input[ip++] << 8; // .ZIP file comment\n", "\n", " this.comment = input.subarray(ip, ip + this.commentLength);\n", " };\n", "\n", " Zlib$1.Unzip.prototype.parseFileHeader = function () {\n", " /** @type {Array.} */\n", " var filelist = [];\n", " /** @type {Object.} */\n", "\n", " var filetable = {};\n", " /** @type {number} */\n", "\n", " var ip;\n", " /** @type {Zlib.Unzip.FileHeader} */\n", "\n", " var fileHeader;\n", " /*: @type {number} */\n", "\n", " var i;\n", " /*: @type {number} */\n", "\n", " var il;\n", "\n", " if (this.fileHeaderList) {\n", " return;\n", " }\n", "\n", " if (this.centralDirectoryOffset === void 0) {\n", " this.parseEndOfCentralDirectoryRecord();\n", " }\n", "\n", " ip = this.centralDirectoryOffset;\n", "\n", " for (i = 0, il = this.totalEntries; i < il; ++i) {\n", " fileHeader = new Zlib$1.Unzip.FileHeader(this.input, ip);\n", " fileHeader.parse();\n", " ip += fileHeader.length;\n", " filelist[i] = fileHeader;\n", " filetable[fileHeader.filename] = i;\n", " }\n", "\n", " if (this.centralDirectorySize < ip - this.centralDirectoryOffset) {\n", " throw new Error('invalid file header size');\n", " }\n", "\n", " this.fileHeaderList = filelist;\n", " this.filenameToIndex = filetable;\n", " };\n", " /**\n", " * @param {number} index file header index.\n", " * @param {Object=} opt_params\n", " * @return {!(Array.|Uint8Array)} file data.\n", " */\n", "\n", "\n", " Zlib$1.Unzip.prototype.getFileData = function (index, opt_params) {\n", " opt_params = opt_params || {};\n", " /** @type {!(Array.|Uint8Array)} */\n", "\n", " var input = this.input;\n", " /** @type {Array.} */\n", "\n", " var fileHeaderList = this.fileHeaderList;\n", " /** @type {Zlib.Unzip.LocalFileHeader} */\n", "\n", " var localFileHeader;\n", " /** @type {number} */\n", "\n", " var offset;\n", " /** @type {number} */\n", "\n", " var length;\n", " /** @type {!(Array.|Uint8Array)} */\n", "\n", " var buffer;\n", " /** @type {number} */\n", "\n", " var crc32;\n", " /** @type {Array.|Uint32Array|Object} */\n", "\n", " var key;\n", " /** @type {number} */\n", "\n", " var i;\n", " /** @type {number} */\n", "\n", " var il;\n", "\n", " if (!fileHeaderList) {\n", " this.parseFileHeader();\n", " }\n", "\n", " if (fileHeaderList[index] === void 0) {\n", " throw new Error('wrong index');\n", " }\n", "\n", " offset = fileHeaderList[index].relativeOffset;\n", " localFileHeader = new Zlib$1.Unzip.LocalFileHeader(this.input, offset);\n", " localFileHeader.parse();\n", " offset += localFileHeader.length;\n", " length = localFileHeader.compressedSize; // decryption\n", "\n", " if ((localFileHeader.flags & Zlib$1.Unzip.LocalFileHeader.Flags.ENCRYPT) !== 0) {\n", " if (!(opt_params['password'] || this.password)) {\n", " throw new Error('please set password');\n", " }\n", "\n", " key = this.createDecryptionKey(opt_params['password'] || this.password); // encryption header\n", "\n", " for (i = offset, il = offset + 12; i < il; ++i) {\n", " this.decode(key, input[i]);\n", " }\n", "\n", " offset += 12;\n", " length -= 12; // decryption\n", "\n", " for (i = offset, il = offset + length; i < il; ++i) {\n", " input[i] = this.decode(key, input[i]);\n", " }\n", " }\n", "\n", " switch (localFileHeader.compression) {\n", " case Zlib$1.Unzip.CompressionMethod.STORE:\n", " buffer = this.input.subarray(offset, offset + length);\n", " break;\n", "\n", " case Zlib$1.Unzip.CompressionMethod.DEFLATE:\n", " buffer = new Zlib$1.RawInflate(this.input, {\n", " 'index': offset,\n", " 'bufferSize': localFileHeader.plainSize\n", " }).decompress();\n", " break;\n", "\n", " default:\n", " throw new Error('unknown compression type');\n", " }\n", "\n", " if (this.verify) {\n", " crc32 = Zlib$1.CRC32.calc(buffer);\n", "\n", " if (localFileHeader.crc32 !== crc32) {\n", " throw new Error('wrong crc: file=0x' + localFileHeader.crc32.toString(16) + ', data=0x' + crc32.toString(16));\n", " }\n", " }\n", "\n", " return buffer;\n", " };\n", " /**\n", " * @return {Array.}\n", " */\n", "\n", "\n", " Zlib$1.Unzip.prototype.getFilenames = function () {\n", " /** @type {Array.} */\n", " var filenameList = [];\n", " /** @type {number} */\n", "\n", " var i;\n", " /** @type {number} */\n", "\n", " var il;\n", " /** @type {Array.} */\n", "\n", " var fileHeaderList;\n", "\n", " if (!this.fileHeaderList) {\n", " this.parseFileHeader();\n", " }\n", "\n", " fileHeaderList = this.fileHeaderList;\n", "\n", " for (i = 0, il = fileHeaderList.length; i < il; ++i) {\n", " filenameList[i] = fileHeaderList[i].filename;\n", " }\n", "\n", " return filenameList;\n", " };\n", " /**\n", " * @param {string} filename extract filename.\n", " * @param {Object=} opt_params\n", " * @return {!(Array.|Uint8Array)} decompressed data.\n", " */\n", "\n", "\n", " Zlib$1.Unzip.prototype.decompress = function (filename, opt_params) {\n", " /** @type {number} */\n", " var index;\n", "\n", " if (!this.filenameToIndex) {\n", " this.parseFileHeader();\n", " }\n", "\n", " index = this.filenameToIndex[filename];\n", "\n", " if (index === void 0) {\n", " throw new Error(filename + ' not found');\n", " }\n", "\n", " return this.getFileData(index, opt_params);\n", " };\n", " /**\n", " * @param {(Array.|Uint8Array)} password\n", " */\n", "\n", "\n", " Zlib$1.Unzip.prototype.setPassword = function (password) {\n", " this.password = password;\n", " };\n", " /**\n", " * @param {(Array.|Uint32Array|Object)} key\n", " * @param {number} n\n", " * @return {number}\n", " */\n", "\n", "\n", " Zlib$1.Unzip.prototype.decode = function (key, n) {\n", " n ^= this.getByte(\n", " /** @type {(Array.|Uint32Array)} */\n", " key);\n", " this.updateKeys(\n", " /** @type {(Array.|Uint32Array)} */\n", " key, n);\n", " return n;\n", " }; // common method\n", "\n", "\n", " Zlib$1.Unzip.prototype.updateKeys = Zlib$1.Zip.prototype.updateKeys;\n", " Zlib$1.Unzip.prototype.createDecryptionKey = Zlib$1.Zip.prototype.createEncryptionKey;\n", " Zlib$1.Unzip.prototype.getByte = Zlib$1.Zip.prototype.getByte;\n", " /**\n", " * @fileoverview 雑多な関数群をまとめたモジュール実装.\n", " */\n", "\n", " /**\n", " * Byte String から Byte Array に変換.\n", " * @param {!string} str byte string.\n", " * @return {!Array.} byte array.\n", " */\n", "\n", " Zlib$1.Util.stringToByteArray = function (str) {\n", " /** @type {!Array.<(string|number)>} */\n", " var tmp = str.split('');\n", " /** @type {number} */\n", "\n", " var i;\n", " /** @type {number} */\n", "\n", " var il;\n", "\n", " for (i = 0, il = tmp.length; i < il; i++) {\n", " tmp[i] = (tmp[i].charCodeAt(0) & 0xff) >>> 0;\n", " }\n", "\n", " return tmp;\n", " };\n", " /**\n", " * @fileoverview Adler32 checksum 実装.\n", " */\n", "\n", " /**\n", " * Adler32 ハッシュ値の作成\n", " * @param {!(Array|Uint8Array|string)} array 算出に使用する byte array.\n", " * @return {number} Adler32 ハッシュ値.\n", " */\n", "\n", "\n", " Zlib$1.Adler32 = function (array) {\n", " if (typeof array === 'string') {\n", " array = Zlib$1.Util.stringToByteArray(array);\n", " }\n", "\n", " return Zlib$1.Adler32.update(1, array);\n", " };\n", " /**\n", " * Adler32 ハッシュ値の更新\n", " * @param {number} adler 現在のハッシュ値.\n", " * @param {!(Array|Uint8Array)} array 更新に使用する byte array.\n", " * @return {number} Adler32 ハッシュ値.\n", " */\n", "\n", "\n", " Zlib$1.Adler32.update = function (adler, array) {\n", " /** @type {number} */\n", " var s1 = adler & 0xffff;\n", " /** @type {number} */\n", "\n", " var s2 = adler >>> 16 & 0xffff;\n", " /** @type {number} array length */\n", "\n", " var len = array.length;\n", " /** @type {number} loop length (don't overflow) */\n", "\n", " var tlen;\n", " /** @type {number} array index */\n", "\n", " var i = 0;\n", "\n", " while (len > 0) {\n", " tlen = len > Zlib$1.Adler32.OptimizationParameter ? Zlib$1.Adler32.OptimizationParameter : len;\n", " len -= tlen;\n", "\n", " do {\n", " s1 += array[i++];\n", " s2 += s1;\n", " } while (--tlen);\n", "\n", " s1 %= 65521;\n", " s2 %= 65521;\n", " }\n", "\n", " return (s2 << 16 | s1) >>> 0;\n", " };\n", " /**\n", " * Adler32 最適化パラメータ\n", " * 現状では 1024 程度が最適.\n", " * @see http://jsperf.com/adler-32-simple-vs-optimized/3\n", " * @define {number}\n", " */\n", "\n", "\n", " Zlib$1.Adler32.OptimizationParameter = 1024;\n", " /**\n", " * ビットストリーム\n", " * @constructor\n", " * @param {!(Array|Uint8Array)=} buffer output buffer.\n", " * @param {number=} bufferPosition start buffer pointer.\n", " */\n", "\n", " Zlib$1.BitStream = function (buffer, bufferPosition) {\n", " /** @type {number} buffer index. */\n", " this.index = typeof bufferPosition === 'number' ? bufferPosition : 0;\n", " /** @type {number} bit index. */\n", "\n", " this.bitindex = 0;\n", " /** @type {!(Array|Uint8Array)} bit-stream output buffer. */\n", "\n", " this.buffer = buffer instanceof Uint8Array ? buffer : new Uint8Array(Zlib$1.BitStream.DefaultBlockSize); // 入力された index が足りなかったら拡張するが、倍にしてもダメなら不正とする\n", "\n", " if (this.buffer.length * 2 <= this.index) {\n", " throw new Error(\"invalid index\");\n", " } else if (this.buffer.length <= this.index) {\n", " this.expandBuffer();\n", " }\n", " };\n", " /**\n", " * デフォルトブロックサイズ.\n", " * @const\n", " * @type {number}\n", " */\n", "\n", "\n", " Zlib$1.BitStream.DefaultBlockSize = 0x8000;\n", " /**\n", " * expand buffer.\n", " * @return {!(Array|Uint8Array)} new buffer.\n", " */\n", "\n", " Zlib$1.BitStream.prototype.expandBuffer = function () {\n", " /** @type {!(Array|Uint8Array)} old buffer. */\n", " var oldbuf = this.buffer;\n", " /** @type {number} loop limiter. */\n", "\n", " var il = oldbuf.length;\n", " /** @type {!(Array|Uint8Array)} new buffer. */\n", "\n", " var buffer = new Uint8Array(il << 1); // copy buffer\n", "\n", " {\n", " buffer.set(oldbuf);\n", " }\n", " return this.buffer = buffer;\n", " };\n", " /**\n", " * 数値をビットで指定した数だけ書き込む.\n", " * @param {number} number 書き込む数値.\n", " * @param {number} n 書き込むビット数.\n", " * @param {boolean=} reverse 逆順に書き込むならば true.\n", " */\n", "\n", "\n", " Zlib$1.BitStream.prototype.writeBits = function (number, n, reverse) {\n", " var buffer = this.buffer;\n", " var index = this.index;\n", " var bitindex = this.bitindex;\n", " /** @type {number} current octet. */\n", "\n", " var current = buffer[index];\n", " /** @type {number} loop counter. */\n", "\n", " var i;\n", " /**\n", " * 32-bit 整数のビット順を逆にする\n", " * @param {number} n 32-bit integer.\n", " * @return {number} reversed 32-bit integer.\n", " * @private\n", " */\n", "\n", " function rev32_(n) {\n", " return Zlib$1.BitStream.ReverseTable[n & 0xFF] << 24 | Zlib$1.BitStream.ReverseTable[n >>> 8 & 0xFF] << 16 | Zlib$1.BitStream.ReverseTable[n >>> 16 & 0xFF] << 8 | Zlib$1.BitStream.ReverseTable[n >>> 24 & 0xFF];\n", " }\n", "\n", " if (reverse && n > 1) {\n", " number = n > 8 ? rev32_(number) >> 32 - n : Zlib$1.BitStream.ReverseTable[number] >> 8 - n;\n", " } // Byte 境界を超えないとき\n", "\n", "\n", " if (n + bitindex < 8) {\n", " current = current << n | number;\n", " bitindex += n; // Byte 境界を超えるとき\n", " } else {\n", " for (i = 0; i < n; ++i) {\n", " current = current << 1 | number >> n - i - 1 & 1; // next byte\n", "\n", " if (++bitindex === 8) {\n", " bitindex = 0;\n", " buffer[index++] = Zlib$1.BitStream.ReverseTable[current];\n", " current = 0; // expand\n", "\n", " if (index === buffer.length) {\n", " buffer = this.expandBuffer();\n", " }\n", " }\n", " }\n", " }\n", "\n", " buffer[index] = current;\n", " this.buffer = buffer;\n", " this.bitindex = bitindex;\n", " this.index = index;\n", " };\n", " /**\n", " * ストリームの終端処理を行う\n", " * @return {!(Array|Uint8Array)} 終端処理後のバッファを byte array で返す.\n", " */\n", "\n", "\n", " Zlib$1.BitStream.prototype.finish = function () {\n", " var buffer = this.buffer;\n", " var index = this.index;\n", " /** @type {!(Array|Uint8Array)} output buffer. */\n", "\n", " var output; // bitindex が 0 の時は余分に index が進んでいる状態\n", "\n", " if (this.bitindex > 0) {\n", " buffer[index] <<= 8 - this.bitindex;\n", " buffer[index] = Zlib$1.BitStream.ReverseTable[buffer[index]];\n", " index++;\n", " } // array truncation\n", "\n", "\n", " {\n", " output = buffer.subarray(0, index);\n", " }\n", " return output;\n", " };\n", " /**\n", " * 0-255 のビット順を反転したテーブル\n", " * @const\n", " * @type {!(Uint8Array|Array.)}\n", " */\n", "\n", "\n", " Zlib$1.BitStream.ReverseTable = function (table) {\n", " return table;\n", " }(function () {\n", " /** @type {!(Array|Uint8Array)} reverse table. */\n", " var table = new Uint8Array(256);\n", " /** @type {number} loop counter. */\n", "\n", " var i; // generate\n", "\n", " for (i = 0; i < 256; ++i) {\n", " table[i] = function (n) {\n", " var r = n;\n", " var s = 7;\n", "\n", " for (n >>>= 1; n; n >>>= 1) {\n", " r <<= 1;\n", " r |= n & 1;\n", " --s;\n", " }\n", "\n", " return (r << s & 0xff) >>> 0;\n", " }(i);\n", " }\n", "\n", " return table;\n", " }());\n", " /**\n", " * CRC32 ハッシュ値を取得\n", " * @param {!(Array.|Uint8Array)} data data byte array.\n", " * @param {number=} pos data position.\n", " * @param {number=} length data length.\n", " * @return {number} CRC32.\n", " */\n", "\n", "\n", " Zlib$1.CRC32.calc = function (data, pos, length) {\n", " return Zlib$1.CRC32.update(data, 0, pos, length);\n", " };\n", " /**\n", " * CRC32ハッシュ値を更新\n", " * @param {!(Array.|Uint8Array)} data data byte array.\n", " * @param {number} crc CRC32.\n", " * @param {number=} pos data position.\n", " * @param {number=} length data length.\n", " * @return {number} CRC32.\n", " */\n", "\n", "\n", " Zlib$1.CRC32.update = function (data, crc, pos, length) {\n", " var table = Zlib$1.CRC32.Table;\n", " var i = typeof pos === 'number' ? pos : pos = 0;\n", " var il = typeof length === 'number' ? length : data.length;\n", " crc ^= 0xffffffff; // loop unrolling for performance\n", "\n", " for (i = il & 7; i--; ++pos) {\n", " crc = crc >>> 8 ^ table[(crc ^ data[pos]) & 0xff];\n", " }\n", "\n", " for (i = il >> 3; i--; pos += 8) {\n", " crc = crc >>> 8 ^ table[(crc ^ data[pos]) & 0xff];\n", " crc = crc >>> 8 ^ table[(crc ^ data[pos + 1]) & 0xff];\n", " crc = crc >>> 8 ^ table[(crc ^ data[pos + 2]) & 0xff];\n", " crc = crc >>> 8 ^ table[(crc ^ data[pos + 3]) & 0xff];\n", " crc = crc >>> 8 ^ table[(crc ^ data[pos + 4]) & 0xff];\n", " crc = crc >>> 8 ^ table[(crc ^ data[pos + 5]) & 0xff];\n", " crc = crc >>> 8 ^ table[(crc ^ data[pos + 6]) & 0xff];\n", " crc = crc >>> 8 ^ table[(crc ^ data[pos + 7]) & 0xff];\n", " }\n", "\n", " return (crc ^ 0xffffffff) >>> 0;\n", " };\n", " /**\n", " * @param {number} num\n", " * @param {number} crc\n", " * @returns {number}\n", " */\n", "\n", "\n", " Zlib$1.CRC32.single = function (num, crc) {\n", " return (Zlib$1.CRC32.Table[(num ^ crc) & 0xff] ^ num >>> 8) >>> 0;\n", " };\n", " /**\n", " * @type {Array.}\n", " * @const\n", " * @private\n", " */\n", "\n", "\n", " Zlib$1.CRC32.Table_ = [0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d];\n", " /**\n", " * @type {!(Array.|Uint32Array)} CRC-32 Table.\n", " * @const\n", " */\n", "\n", " Zlib$1.CRC32.Table = new Uint32Array(Zlib$1.CRC32.Table_);\n", " /**\n", " * @fileoverview Deflate (RFC1951) 実装.\n", " * Deflateアルゴリズム本体は Zlib.RawDeflate で実装されている.\n", " */\n", "\n", " /**\n", " * Zlib Deflate\n", " * @constructor\n", " * @param {!(Array|Uint8Array)} input 符号化する対象の byte array.\n", " * @param {Object=} opt_params option parameters.\n", " */\n", "\n", " Zlib$1.Deflate = function (input, opt_params) {\n", " /** @type {!(Array|Uint8Array)} */\n", " this.input = input;\n", " /** @type {!(Array|Uint8Array)} */\n", "\n", " this.output = new Uint8Array(Zlib$1.Deflate.DefaultBufferSize);\n", " /** @type {Zlib.Deflate.CompressionType} */\n", "\n", " this.compressionType = Zlib$1.Deflate.CompressionType.DYNAMIC;\n", " /** @type {Zlib.RawDeflate} */\n", "\n", " this.rawDeflate;\n", " /** @type {Object} */\n", "\n", " var rawDeflateOption = {};\n", " /** @type {string} */\n", "\n", " var prop; // option parameters\n", "\n", " if (opt_params || !(opt_params = {})) {\n", " if (typeof opt_params['compressionType'] === 'number') {\n", " this.compressionType = opt_params['compressionType'];\n", " }\n", " } // copy options\n", "\n", "\n", " for (prop in opt_params) {\n", " rawDeflateOption[prop] = opt_params[prop];\n", " } // set raw-deflate output buffer\n", "\n", "\n", " rawDeflateOption['outputBuffer'] = this.output;\n", " this.rawDeflate = new Zlib$1.RawDeflate(this.input, rawDeflateOption);\n", " };\n", " /**\n", " * @const\n", " * @type {number} デフォルトバッファサイズ.\n", " */\n", "\n", "\n", " Zlib$1.Deflate.DefaultBufferSize = 0x8000;\n", " /**\n", " * @enum {number}\n", " */\n", "\n", " Zlib$1.Deflate.CompressionType = Zlib$1.RawDeflate.CompressionType;\n", " /**\n", " * 直接圧縮に掛ける.\n", " * @param {!(Array|Uint8Array)} input target buffer.\n", " * @param {Object=} opt_params option parameters.\n", " * @return {!(Array|Uint8Array)} compressed data byte array.\n", " */\n", "\n", " Zlib$1.Deflate.compress = function (input, opt_params) {\n", " return new Zlib$1.Deflate(input, opt_params).compress();\n", " };\n", " /**\n", " * Deflate Compression.\n", " * @return {!(Array|Uint8Array)} compressed data byte array.\n", " */\n", "\n", "\n", " Zlib$1.Deflate.prototype.compress = function () {\n", " /** @type {Zlib.CompressionMethod} */\n", " var cm;\n", " /** @type {number} */\n", "\n", " var cinfo;\n", " /** @type {number} */\n", "\n", " var cmf;\n", " /** @type {number} */\n", "\n", " var flg;\n", " /** @type {number} */\n", "\n", " var fcheck;\n", " /** @type {number} */\n", "\n", " var fdict;\n", " /** @type {number} */\n", "\n", " var flevel;\n", " /** @type {number} */\n", "\n", " var adler;\n", " /** @type {!(Array|Uint8Array)} */\n", "\n", " var output;\n", " /** @type {number} */\n", "\n", " var pos = 0;\n", " output = this.output; // Compression Method and Flags\n", "\n", " cm = Zlib$1.CompressionMethod.DEFLATE;\n", "\n", " switch (cm) {\n", " case Zlib$1.CompressionMethod.DEFLATE:\n", " cinfo = Math.LOG2E * Math.log(Zlib$1.RawDeflate.WindowSize) - 8;\n", " break;\n", "\n", " default:\n", " throw new Error('invalid compression method');\n", " }\n", "\n", " cmf = cinfo << 4 | cm;\n", " output[pos++] = cmf; // Flags\n", "\n", " fdict = 0;\n", "\n", " switch (cm) {\n", " case Zlib$1.CompressionMethod.DEFLATE:\n", " switch (this.compressionType) {\n", " case Zlib$1.Deflate.CompressionType.NONE:\n", " flevel = 0;\n", " break;\n", "\n", " case Zlib$1.Deflate.CompressionType.FIXED:\n", " flevel = 1;\n", " break;\n", "\n", " case Zlib$1.Deflate.CompressionType.DYNAMIC:\n", " flevel = 2;\n", " break;\n", "\n", " default:\n", " throw new Error('unsupported compression type');\n", " }\n", "\n", " break;\n", "\n", " default:\n", " throw new Error('invalid compression method');\n", " }\n", "\n", " flg = flevel << 6 | fdict << 5;\n", " fcheck = 31 - (cmf * 256 + flg) % 31;\n", " flg |= fcheck;\n", " output[pos++] = flg; // Adler-32 checksum\n", "\n", " adler = Zlib$1.Adler32(this.input);\n", " this.rawDeflate.op = pos;\n", " output = this.rawDeflate.compress();\n", " pos = output.length;\n", " {\n", " // subarray 分を元にもどす\n", " output = new Uint8Array(output.buffer); // expand buffer\n", "\n", " if (output.length <= pos + 4) {\n", " this.output = new Uint8Array(output.length + 4);\n", " this.output.set(output);\n", " output = this.output;\n", " }\n", "\n", " output = output.subarray(0, pos + 4);\n", " } // adler32\n", "\n", " output[pos++] = adler >> 24 & 0xff;\n", " output[pos++] = adler >> 16 & 0xff;\n", " output[pos++] = adler >> 8 & 0xff;\n", " output[pos++] = adler & 0xff;\n", " return output;\n", " };\n", "\n", " if (typeof btoa === 'undefined') {\n", " require('btoa');\n", " }\n", "\n", " if (typeof process === 'object' && typeof window === 'undefined') {\n", " global.atob = function (str) {\n", " return Buffer.from(str, 'base64').toString('binary');\n", " };\n", " }\n", " /**\n", " * Make the target element movable by clicking and dragging on the handle. This is not a general purprose function,\n", " * it makes several options specific to igv dialogs, the primary one being that the\n", " * target is absolutely positioned in pixel coordinates\n", "\n", " */\n", "\n", "\n", " let dragData; // Its assumed we are only dragging one element at a time.\n", "\n", " function makeDraggable(target, handle) {\n", " handle.addEventListener('mousedown', dragStart.bind(target));\n", " }\n", "\n", " function dragStart(event) {\n", " event.stopPropagation();\n", " event.preventDefault();\n", " offset(this);\n", " const dragFunction = drag.bind(this);\n", " const dragEndFunction = dragEnd.bind(this);\n", " const computedStyle = getComputedStyle(this);\n", " const top = parseInt(computedStyle.top.replace(\"px\", \"\"));\n", " const left = parseInt(computedStyle.left.replace(\"px\", \"\"));\n", " dragData = {\n", " dragFunction: dragFunction,\n", " dragEndFunction: dragEndFunction,\n", " screenX: event.screenX,\n", " screenY: event.screenY,\n", " top: top,\n", " left: left\n", " };\n", " document.addEventListener('mousemove', dragFunction);\n", " document.addEventListener('mouseup', dragEndFunction);\n", " document.addEventListener('mouseleave', dragEndFunction);\n", " document.addEventListener('mouseexit', dragEndFunction);\n", " }\n", "\n", " function drag(event) {\n", " if (!dragData) {\n", " return;\n", " }\n", "\n", " event.stopPropagation();\n", " event.preventDefault();\n", " const dx = event.screenX - dragData.screenX;\n", " const dy = event.screenY - dragData.screenY;\n", " this.style.left = `${dragData.left + dx}px`;\n", " this.style.top = `${dragData.top + dy}px`;\n", " }\n", "\n", " function dragEnd(event) {\n", " if (!dragData) {\n", " return;\n", " }\n", "\n", " event.stopPropagation();\n", " event.preventDefault();\n", " const dragFunction = dragData.dragFunction;\n", " const dragEndFunction = dragData.dragEndFunction;\n", " document.removeEventListener('mousemove', dragFunction);\n", " document.removeEventListener('mouseup', dragEndFunction);\n", " document.removeEventListener('mouseleave', dragEndFunction);\n", " document.removeEventListener('mouseexit', dragEndFunction);\n", " dragData = undefined;\n", " }\n", "\n", " const appleCrayonPalette = {\n", " licorice: \"#000000\",\n", " lead: \"#1e1e1e\",\n", " tungsten: \"#3a3a3a\",\n", " iron: \"#545453\",\n", " steel: \"#6e6e6e\",\n", " tin: \"#878687\",\n", " nickel: \"#888787\",\n", " aluminum: \"#a09fa0\",\n", " magnesium: \"#b8b8b8\",\n", " silver: \"#d0d0d0\",\n", " mercury: \"#e8e8e8\",\n", " snow: \"#ffffff\",\n", " //\n", " cayenne: \"#891100\",\n", " mocha: \"#894800\",\n", " aspargus: \"#888501\",\n", " fern: \"#458401\",\n", " clover: \"#028401\",\n", " moss: \"#018448\",\n", " teal: \"#008688\",\n", " ocean: \"#004a88\",\n", " midnight: \"#001888\",\n", " eggplant: \"#491a88\",\n", " plum: \"#891e88\",\n", " maroon: \"#891648\",\n", " //\n", " maraschino: \"#ff2101\",\n", " tangerine: \"#ff8802\",\n", " lemon: \"#fffa03\",\n", " lime: \"#83f902\",\n", " spring: \"#05f802\",\n", " seam_foam: \"#03f987\",\n", " turquoise: \"#00fdff\",\n", " aqua: \"#008cff\",\n", " blueberry: \"#002eff\",\n", " grape: \"#8931ff\",\n", " magenta: \"#ff39ff\",\n", " strawberry: \"#ff2987\",\n", " //\n", " salmon: \"#ff726e\",\n", " cantaloupe: \"#ffce6e\",\n", " banana: \"#fffb6d\",\n", " honeydew: \"#cefa6e\",\n", " flora: \"#68f96e\",\n", " spindrift: \"#68fbd0\",\n", " ice: \"#68fdff\",\n", " sky: \"#6acfff\",\n", " orchid: \"#6e76ff\",\n", " lavender: \"#d278ff\",\n", " bubblegum: \"#ff7aff\",\n", " carnation: \"#ff7fd3\"\n", " }; // The MIT License (MIT)\n", "\n", " /**\n", " * @constructor\n", " * @param {Object} options A set op options to pass to the throttle function\n", " * @param {number} requestsPerSecond The amount of requests per second\n", " * the library will limit to\n", " */\n", "\n", " class Throttle {\n", " constructor(options) {\n", " this.requestsPerSecond = options.requestsPerSecond || 10;\n", " this.lastStartTime = 0;\n", " this.queued = [];\n", " }\n", " /**\n", " * Adds a promise\n", " * @param {Function} async function to be executed\n", " * @param {Object} options A set of options.\n", " * @return {Promise} A promise\n", " */\n", "\n", "\n", " add(asyncFunction, options) {\n", " var self = this;\n", " return new Promise(function (resolve, reject) {\n", " self.queued.push({\n", " resolve: resolve,\n", " reject: reject,\n", " asyncFunction: asyncFunction\n", " });\n", " self.dequeue();\n", " });\n", " }\n", " /**\n", " * Adds all the promises passed as parameters\n", " * @param {Function} promises An array of functions that return a promise\n", " * @param {Object} options A set of options.\n", " * @param {number} options.signal An AbortSignal object that can be used to abort the returned promise\n", " * @param {number} options.weight A \"weight\" of each operation resolving by array of promises\n", " * @return {Promise} A promise that succeeds when all the promises passed as options do\n", " */\n", "\n", "\n", " addAll(promises, options) {\n", " var addedPromises = promises.map(function (promise) {\n", " return this.add(promise, options);\n", " }.bind(this));\n", " return Promise.all(addedPromises);\n", " }\n", "\n", " /**\n", " * Dequeues a promise\n", " * @return {void}\n", " */\n", " dequeue() {\n", " if (this.queued.length > 0) {\n", " var now = new Date(),\n", " inc = 1000 / this.requestsPerSecond + 1,\n", " elapsed = now - this.lastStartTime;\n", "\n", " if (elapsed >= inc) {\n", " this._execute();\n", " } else {\n", " // we have reached the limit, schedule a dequeue operation\n", " setTimeout(function () {\n", " this.dequeue();\n", " }.bind(this), inc - elapsed);\n", " }\n", " }\n", " }\n", " /**\n", " * Executes the promise\n", " * @private\n", " * @return {void}\n", " */\n", "\n", "\n", " async _execute() {\n", " this.lastStartTime = new Date();\n", " var candidate = this.queued.shift();\n", " const f = candidate.asyncFunction;\n", "\n", " try {\n", " const r = await f();\n", " candidate.resolve(r);\n", " } catch (e) {\n", " candidate.reject(e);\n", " }\n", " }\n", "\n", " }\n", " /*\n", " * The MIT License (MIT)\n", " *\n", " * Copyright (c) 2014 Broad Institute\n", " *\n", " * Permission is hereby granted, free of charge, to any person obtaining a copy\n", " * of this software and associated documentation files (the \"Software\"), to deal\n", " * in the Software without restriction, including without limitation the rights\n", " * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n", " * copies of the Software, and to permit persons to whom the Software is\n", " * furnished to do so, subject to the following conditions:\n", " *\n", " * The above copyright notice and this permission notice shall be included in\n", " * all copies or substantial portions of the Software.\n", " *\n", " *\n", " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n", " * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n", " * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n", " * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n", " * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n", " * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n", " * THE SOFTWARE.\n", " */\n", "\n", "\n", " new Throttle({\n", " requestsPerSecond: 8\n", " });\n", "\n", " class Textbox {\n", " constructor({\n", " value,\n", " label,\n", " onchange\n", " }) {\n", " this.elem = div({\n", " class: 'igv-ui-generic-dialog-label-input'\n", " });\n", "\n", " if (label) {\n", " const div$1 = div();\n", " div$1.innerHTML = label;\n", " this.elem.appendChild(div$1);\n", " }\n", "\n", " this.textBox = create('input');\n", "\n", " if (value) {\n", " this.textBox.value = value;\n", " }\n", "\n", " this.elem.appendChild(this.textBox);\n", "\n", " if (onchange) {\n", " this.textBox.addEventListener('change', e => onchange(this.textBox.value));\n", " }\n", " }\n", "\n", " get value() {\n", " return this.textBox.value;\n", " }\n", "\n", " set value(v) {\n", " this.textBox.value = v;\n", " }\n", "\n", " }\n", " /**\n", " * Generic container for UI components\n", " */\n", "\n", "\n", " class Panel {\n", " constructor() {\n", " this.elem = create('div', {\n", " class: 'igv-ui-panel-column'\n", " });\n", " }\n", "\n", " add(component) {\n", " if (component instanceof Node) {\n", " this.elem.append(component);\n", " } else if (typeof component === 'object') {\n", " this.elem.append(component.elem);\n", " } else {\n", " // Assuming a string, possibly html\n", " const wrapper = div();\n", " wrapper.innerHTML = component;\n", " this.elem.append(wrapper);\n", " }\n", " }\n", "\n", " }\n", "\n", " class Dialog {\n", " constructor({\n", " label,\n", " content,\n", " okHandler,\n", " cancelHandler\n", " }) {\n", " const cancel = () => {\n", " hide(this.elem);\n", "\n", " if (typeof cancelHandler === 'function') {\n", " cancelHandler(this);\n", " }\n", " }; // dialog container\n", "\n", "\n", " this.elem = div({\n", " class: 'igv-ui-generic-dialog-container'\n", " }); // dialog header\n", "\n", " const header = div({\n", " class: 'igv-ui-generic-dialog-header'\n", " });\n", " this.elem.appendChild(header);\n", " attachDialogCloseHandlerWithParent(header, cancel); // dialog label\n", "\n", " if (label) {\n", " const labelDiv = div({\n", " class: 'igv-ui-dialog-one-liner'\n", " });\n", " this.elem.appendChild(labelDiv);\n", " labelDiv.innerHTML = label;\n", " } // input container\n", "\n", "\n", " content.elem.style.margin = '8px';\n", " this.elem.appendChild(content.elem); // ok | cancel\n", "\n", " const buttons = div({\n", " class: 'igv-ui-generic-dialog-ok-cancel'\n", " });\n", " this.elem.appendChild(buttons); // ok\n", "\n", " this.ok = div();\n", " buttons.appendChild(this.ok);\n", " this.ok.textContent = 'OK'; // cancel\n", "\n", " this.cancel = div();\n", " buttons.appendChild(this.cancel);\n", " this.cancel.textContent = 'Cancel';\n", " this.ok.addEventListener('click', e => {\n", " hide(this.elem);\n", "\n", " if (typeof okHandler === 'function') {\n", " okHandler(this);\n", " }\n", " });\n", " this.cancel.addEventListener('click', cancel);\n", " makeDraggable(this.elem, header); // Consume all clicks in component\n", "\n", " this.elem.addEventListener('click', e => {\n", " e.preventDefault();\n", " e.stopPropagation();\n", " });\n", " }\n", "\n", " present(options, e) {\n", " this.label.textContent = options.label;\n", " this.input.value = options.value;\n", " this.callback = options.callback;\n", " const page = pageCoordinates(e);\n", " this.clampLocation(page.x, page.y);\n", " show(this.elem);\n", " }\n", "\n", " clampLocation(pageX, pageY) {\n", " let popoverRect = this.elem.getBoundingClientRect();\n", " let parentRect = this.parent.getBoundingClientRect();\n", " const y = Math.min(Math.max(pageY, parentRect.y), parentRect.y + parentRect.height - popoverRect.height);\n", " const x = Math.min(Math.max(pageX, parentRect.x), parentRect.x + parentRect.width - popoverRect.width);\n", " this.elem.style.left = x + \"px\";\n", " this.elem.style.top = y + \"px\";\n", " }\n", "\n", " }\n", "\n", " class DataRangeDialog {\n", " constructor(parent, okHandler) {\n", " const panel = new Panel();\n", " this.minbox = new Textbox({\n", " label: \"Minimum\",\n", " value: \"0\"\n", " });\n", " panel.add(this.minbox);\n", " this.maxbox = new Textbox({\n", " label: \"Maximum\",\n", " value: \"0\"\n", " });\n", " panel.add(this.maxbox);\n", " let callback;\n", "\n", " if (okHandler) {\n", " callback = e => {\n", " okHandler(Number.parseFloat(this.minbox.value), Number.parseFloat(this.maxbox.value));\n", " };\n", " } else {\n", " callback = d => {};\n", " }\n", "\n", " this.dialog = new Dialog({\n", " //label: 'Multi-select',\n", " content: panel,\n", " okHandler: callback\n", " }); // Overide some css styles -- TODO redesign this.\n", "\n", " this.dialog.elem.style.position = \"absolute\";\n", " hide(this.dialog.elem);\n", " parent.appendChild(this.dialog.elem);\n", " }\n", "\n", " show({\n", " min,\n", " max\n", " }) {\n", " if (min !== undefined) this.minbox.value = min.toString();\n", " if (max !== undefined) this.maxbox.value = max.toString();\n", " show(this.dialog.elem);\n", " }\n", "\n", " }\n", "\n", " const httpMessages = {\n", " \"401\": \"Access unauthorized\",\n", " \"403\": \"Access forbidden\",\n", " \"404\": \"Not found\"\n", " };\n", "\n", " class AlertDialog {\n", " constructor(parent) {\n", " // container\n", " this.container = div({\n", " class: \"igv-ui-alert-dialog-container\"\n", " });\n", " parent.appendChild(this.container);\n", " this.container.setAttribute('tabIndex', '-1'); // header\n", "\n", " const header = div();\n", " this.container.appendChild(header);\n", " this.errorHeadline = div();\n", " header.appendChild(this.errorHeadline);\n", " this.errorHeadline.textContent = ''; // body container\n", "\n", " let bodyContainer = div({\n", " id: 'igv-ui-alert-dialog-body'\n", " });\n", " this.container.appendChild(bodyContainer); // body copy\n", "\n", " this.body = div({\n", " id: 'igv-ui-alert-dialog-body-copy'\n", " });\n", " bodyContainer.appendChild(this.body); // ok container\n", "\n", " let ok_container = div();\n", " this.container.appendChild(ok_container); // ok\n", "\n", " this.ok = div();\n", " ok_container.appendChild(this.ok);\n", " this.ok.textContent = 'OK';\n", "\n", " const okHandler = () => {\n", " if (typeof this.callback === 'function') {\n", " this.callback(\"OK\");\n", " this.callback = undefined;\n", " }\n", "\n", " this.body.innerHTML = '';\n", " hide(this.container);\n", " };\n", "\n", " this.ok.addEventListener('click', event => {\n", " event.stopPropagation();\n", " okHandler();\n", " });\n", " this.container.addEventListener('keypress', event => {\n", " event.stopPropagation();\n", "\n", " if ('Enter' === event.key) {\n", " okHandler();\n", " }\n", " });\n", " makeDraggable(this.container, header);\n", " hide(this.container);\n", " }\n", "\n", " present(alert, callback) {\n", " this.errorHeadline.textContent = alert.message ? 'ERROR' : '';\n", " let string = alert.message || alert;\n", "\n", " if (httpMessages.hasOwnProperty(string)) {\n", " string = httpMessages[string];\n", " }\n", "\n", " this.body.innerHTML = string;\n", " this.callback = callback;\n", " show(this.container);\n", " this.container.focus();\n", " }\n", "\n", " }\n", "\n", " let alertDialog;\n", " const Alert$1 = {\n", " init(root) {\n", " if (!alertDialog) {\n", " alertDialog = new AlertDialog(root);\n", " }\n", " },\n", "\n", " presentAlert(alert, callback) {\n", " if (!alertDialog) {\n", " this.init(document.body);\n", " }\n", "\n", " alertDialog.present(alert, callback);\n", " }\n", "\n", " };\n", "\n", " class InputDialog {\n", " constructor(parent) {\n", " this.parent = parent; // dialog container\n", "\n", " this.container = div({\n", " class: 'igv-ui-generic-dialog-container'\n", " });\n", " parent.appendChild(this.container); // const { x, y, width, height } = this.container.getBoundingClientRect();\n", " // console.log(`InputDialog - x ${ x } y ${ y } width ${ width } height ${ height }`)\n", " // dialog header\n", "\n", " const header = div({\n", " class: 'igv-ui-generic-dialog-header'\n", " });\n", " this.container.appendChild(header); // dialog label\n", "\n", " this.label = div({\n", " class: 'igv-ui-generic-dialog-one-liner'\n", " });\n", " this.container.appendChild(this.label);\n", " this.label.text = 'Unlabeled'; // input container\n", "\n", " this.input_container = div({\n", " class: 'igv-ui-generic-dialog-input'\n", " });\n", " this.container.appendChild(this.input_container); //\n", "\n", " this.input = document.createElement(\"input\");\n", " this.input_container.appendChild(this.input); // ok | cancel\n", "\n", " const buttons = div({\n", " class: 'igv-ui-generic-dialog-ok-cancel'\n", " });\n", " this.container.appendChild(buttons); // ok\n", "\n", " this.ok = div();\n", " buttons.appendChild(this.ok);\n", " this.ok.textContent = 'OK'; // cancel\n", "\n", " this.cancel = div();\n", " buttons.appendChild(this.cancel);\n", " this.cancel.textContent = 'Cancel';\n", " hide(this.container);\n", " this.input.addEventListener('keyup', e => {\n", " if (13 === e.keyCode) {\n", " if (typeof this.callback === 'function') {\n", " this.callback(this.input.value);\n", " this.callback = undefined;\n", " }\n", "\n", " this.input.value = undefined;\n", " hide(this.container);\n", " }\n", " });\n", " this.ok.addEventListener('click', () => {\n", " if (typeof this.callback === 'function') {\n", " this.callback(this.input.value);\n", " this.callback = undefined;\n", " }\n", "\n", " this.input.value = undefined;\n", " hide(this.container);\n", " });\n", "\n", " const cancel = () => {\n", " this.input.value = '';\n", " hide(this.container);\n", " };\n", "\n", " this.cancel.addEventListener('click', cancel);\n", " attachDialogCloseHandlerWithParent(header, cancel);\n", " makeDraggable(this.container, header);\n", " }\n", "\n", " present(options, e) {\n", " this.label.textContent = options.label;\n", " this.input.value = options.value;\n", " this.callback = options.callback || options.click;\n", " show(this.container);\n", " const {\n", " x,\n", " y\n", " } = pageCoordinates(e);\n", " this.clampLocation(x, y);\n", " }\n", "\n", " clampLocation(pageX, pageY) {\n", " const {\n", " width: w,\n", " height: h\n", " } = this.container.getBoundingClientRect();\n", " const {\n", " x: px,\n", " y: py,\n", " width: pw,\n", " height: ph\n", " } = this.parent.getBoundingClientRect();\n", " const y = Math.min(Math.max(pageY, py), py + ph - h);\n", " const x = Math.min(Math.max(pageX, px), px + pw - w);\n", " this.container.style.left = `${x}px`;\n", " this.container.style.top = `${y}px`;\n", " }\n", "\n", " }\n", "\n", " class GenericContainer {\n", " constructor({\n", " parent,\n", " top,\n", " left,\n", " width,\n", " height,\n", " border,\n", " closeHandler\n", " }) {\n", " let container = div({\n", " class: 'igv-ui-generic-container'\n", " });\n", " parent.appendChild(container);\n", " hide(container);\n", " this.container = container;\n", "\n", " if (top !== undefined) {\n", " this.container.style.top = `${top}px`;\n", " }\n", "\n", " if (left !== undefined) {\n", " this.container.style.left = `${left}px`;\n", " }\n", "\n", " if (width !== undefined) {\n", " this.container.style.width = `${width}px`;\n", " }\n", "\n", " if (height !== undefined) {\n", " this.container.style.height = `${height}px`;\n", " }\n", "\n", " if (border) {\n", " this.container.style.border = border;\n", " } //\n", " // let bbox = parent.getBoundingClientRect();\n", " // this.origin = {x: bbox.x, y: bbox.y};\n", " // this.container.offset({left: this.origin.x, top: this.origin.y});\n", " // header\n", "\n", "\n", " const header = div();\n", " this.container.appendChild(header); // close button\n", "\n", " attachDialogCloseHandlerWithParent(header, e => {\n", " hide(this.container);\n", "\n", " if (typeof closeHandler === \"function\") {\n", " closeHandler(e);\n", " }\n", " });\n", " makeDraggable(this.container, header);\n", " }\n", "\n", " show() {\n", " show(this.container);\n", " }\n", "\n", " hide() {\n", " hide(this.container);\n", " }\n", "\n", " dispose() {\n", " if (this.container.parent) {\n", " this.container.parent.removeChild(this.container);\n", " }\n", " }\n", "\n", " }\n", "\n", " class ColorPicker extends GenericContainer {\n", " constructor({\n", " parent,\n", " top,\n", " left,\n", " width,\n", " height,\n", " defaultColors,\n", " colorHandler\n", " }) {\n", " super({\n", " parent,\n", " top,\n", " left,\n", " width,\n", " height,\n", " border: '1px solid gray'\n", " });\n", " createColorSwatchSelector(this.container, colorHandler, defaultColors);\n", " }\n", "\n", " }\n", "\n", " const createColorSwatchSelector = (container, colorHandler, defaultColors) => {\n", " const hexColorStrings = Object.values(appleCrayonPalette);\n", "\n", " for (let hexColorString of hexColorStrings) {\n", " const swatch = div({\n", " class: 'igv-ui-color-swatch'\n", " });\n", " container.appendChild(swatch);\n", " decorateSwatch(swatch, hexColorString, colorHandler);\n", " }\n", "\n", " if (defaultColors) {\n", " for (let hexColorString of defaultColors) {\n", " const swatch = div({\n", " class: 'igv-ui-color-swatch'\n", " });\n", " container.appendChild(swatch);\n", " decorateSwatch(swatch, hexColorString, colorHandler);\n", " }\n", " }\n", " };\n", "\n", " const decorateSwatch = (swatch, hexColorString, colorHandler) => {\n", " swatch.style.backgroundColor = hexColorString;\n", " swatch.addEventListener('mouseenter', e => swatch.style.borderColor = hexColorString);\n", " swatch.addEventListener('mouseleave', e => swatch.style.borderColor = 'white');\n", " swatch.addEventListener('click', event => {\n", " event.stopPropagation();\n", " colorHandler(hexColorString);\n", " });\n", " swatch.addEventListener('touchend', event => {\n", " event.stopPropagation();\n", " colorHandler(hexColorString);\n", " });\n", " };\n", "\n", " function embedCSS() {\n", " 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: 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-popover > div:first-child > div {\\n margin-right: 4px;\\n height: 12px;\\n width: 12px;\\n color: #7F7F7F; }\\n .igv-ui-popover > div:first-child > div: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 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 max-width: 384px;\\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;\\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;\\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;\\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';\n", " var style = document.createElement('style');\n", " style.setAttribute('type', 'text/css');\n", " style.innerHTML = css;\n", " document.head.insertBefore(style, document.head.childNodes[document.head.childNodes.length - 1]);\n", " }\n", "\n", " if (typeof document !== 'undefined') {\n", " if (!stylesheetExists(\"igv-ui.css\")) {\n", " // console.log('igv-ui. will call embedCSS() ...');\n", " embedCSS(); // console.log('... done.');\n", " }\n", "\n", " function stylesheetExists(stylesheetName) {\n", " for (let ss of document.styleSheets) {\n", " ss = ss.href ? ss.href.replace(/^.*[\\\\\\/]/, '') : '';\n", "\n", " if (ss === stylesheetName) {\n", " return true;\n", " }\n", " }\n", "\n", " return false;\n", " }\n", " }\n", "\n", " /*\n", " * The MIT License (MIT)\n", " *\n", " * Copyright (c) 2016-2017 The Regents of the University of California\n", " *\n", " * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and\n", " * associated documentation files (the \"Software\"), to deal in the Software without restriction, including\n", " * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n", " * copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the\n", " * following conditions:\n", " *\n", " * The above copyright notice and this permission notice shall be included in all copies or substantial\n", " * portions of the Software.\n", " *\n", " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING\n", " * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n", " * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n", " * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\n", " * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n", " * THE SOFTWARE.\n", " *\n", " */\n", " function isMobile() {\n", " return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);\n", " }\n", "\n", " function throttle(fn, threshhold, scope) {\n", " var last, deferTimer;\n", " threshhold || (threshhold = 200);\n", " return function () {\n", " var context, now, args;\n", " context = scope || this;\n", " now = +new Date();\n", " args = arguments;\n", "\n", " if (last && now < last + threshhold) {\n", " // hold on to it\n", " clearTimeout(deferTimer);\n", " deferTimer = setTimeout(function () {\n", " last = now;\n", " fn.apply(context, args);\n", " }, threshhold);\n", " } else {\n", " last = now;\n", " fn.apply(context, args);\n", " }\n", " };\n", " }\n", "\n", " /*\n", " * The MIT License (MIT)\n", " *\n", " * Copyright (c) 2016-2017 The Regents of the University of California\n", " *\n", " * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and\n", " * associated documentation files (the \"Software\"), to deal in the Software without restriction, including\n", " * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n", " * copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the\n", " * following conditions:\n", " *\n", " * The above copyright notice and this permission notice shall be included in all copies or substantial\n", " * portions of the Software.\n", " *\n", " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING\n", " * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n", " * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n", " * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\n", " * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n", " * THE SOFTWARE.\n", " *\n", " */\n", " const Globals = {};\n", " const Track2DDisplaceModes = {\n", " displayAllMatrix: 'displayAllMatrix',\n", " displayLowerMatrix: 'displayLowerMatrix',\n", " displayUpperMatrix: 'displayUpperMatrix'\n", " };\n", "\n", " /*\n", " * The MIT License (MIT)\n", " *\n", " * Copyright (c) 2016-2017 The Regents of the University of California\n", " *\n", " * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and\n", " * associated documentation files (the \"Software\"), to deal in the Software without restriction, including\n", " * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n", " * copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the\n", " * following conditions:\n", " *\n", " * The above copyright notice and this permission notice shall be included in all copies or substantial\n", " * portions of the Software.\n", " *\n", " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING\n", " * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n", " * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n", " * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\n", " * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n", " * THE SOFTWARE.\n", " *\n", " */\n", "\n", " /**\n", " * @author Jim Robinson\n", " */\n", "\n", " /**\n", " * Barebones event bus.\n", " */\n", " class EventBus {\n", " constructor() {\n", " // Map eventType -> list of subscribers\n", " this.subscribers = {};\n", " this.stack = [];\n", " }\n", "\n", " subscribe(eventType, object) {\n", " var subscriberList = this.subscribers[eventType];\n", "\n", " if (subscriberList == undefined) {\n", " subscriberList = [];\n", " this.subscribers[eventType] = subscriberList;\n", " }\n", "\n", " subscriberList.push(object);\n", " }\n", "\n", " post(event) {\n", " const eventType = event.type;\n", "\n", " if (this._hold) {\n", " this.stack.push(event);\n", " } else {\n", " const subscriberList = this.subscribers[eventType];\n", "\n", " if (subscriberList) {\n", " for (let subscriber of subscriberList) {\n", " if (\"function\" === typeof subscriber.receiveEvent) {\n", " subscriber.receiveEvent(event);\n", " } else if (\"function\" === typeof subscriber) {\n", " subscriber(event);\n", " }\n", " }\n", " }\n", " }\n", " }\n", "\n", " hold() {\n", " this._hold = true;\n", " }\n", "\n", " release() {\n", " this._hold = false;\n", "\n", " for (let event of this.stack) {\n", " this.post(event);\n", " }\n", "\n", " this.stack = [];\n", " }\n", "\n", " } // The global event bus\n", "\n", "\n", " EventBus.globalBus = new EventBus();\n", "\n", " class Track2D {\n", " constructor(config, features) {\n", " this.config = config;\n", " this.name = config.name;\n", " this.featureMap = {};\n", " this.featureCount = 0;\n", " this.isVisible = true;\n", " this.displayMode = Track2DDisplaceModes.displayAllMatrix;\n", "\n", " if (config.color && validateColor(config.color)) {\n", " this.color = this.color = config.color; // If specified, this will override colors of individual records.\n", " }\n", "\n", " this.repColor = features.length > 0 ? features[0].color : \"black\";\n", "\n", " for (let f of features) {\n", " this.featureCount++;\n", " const key = getKey(f.chr1, f.chr2);\n", " let list = this.featureMap[key];\n", "\n", " if (!list) {\n", " list = [];\n", " this.featureMap[key] = list;\n", " }\n", "\n", " list.push(f);\n", " }\n", " }\n", "\n", " static async loadTrack2D(config, genome) {\n", " // if (isString(config.url) && config.url.startsWith(\"https://drive.google.com\")) {\n", " // const json = await google.getDriveFileInfo(config.url)\n", " // config.url = \"https://www.googleapis.com/drive/v3/files/\" + json.id + \"?alt=media\";\n", " // if (!config.filename) {\n", " // config.filename = json.originalFileName || json.name;\n", " // }\n", " // if (!config.name) {\n", " // config.name = json.name || json.originalFileName;\n", " // }\n", " // }\n", " const data = await igvxhr.loadString(config.url, buildOptions(config));\n", " const features = parseData(data, isBedPE(config), genome);\n", " return new Track2D(config, features);\n", " }\n", "\n", " getColor() {\n", " return this.color || this.repColor;\n", " }\n", "\n", " getFeatures(chr1, chr2) {\n", " const key = getKey(chr1, chr2);\n", " return this.featureMap[key];\n", " }\n", "\n", " }\n", "\n", " function isBedPE(config) {\n", " if (typeof config.url === \"string\") {\n", " return config.url.toLowerCase().indexOf(\".bedpe\") > 0;\n", " } else if (typeof config.name === \"string\") {\n", " return config.name.toLowerCase().indexOf(\".bedpe\") > 0;\n", " } else {\n", " return true; // Default\n", " }\n", " }\n", "\n", " function parseData(data, isBedPE, genome) {\n", " if (!data) return null;\n", " const lines = splitLines(data);\n", " const allFeatures = [];\n", " const delimiter = \"\\t\";\n", " const colorColumn = isBedPE ? 10 : 6;\n", " let errorCount = 0;\n", "\n", " for (let line of lines) {\n", " line = line.trim();\n", "\n", " if (line.startsWith(\"#\") || line.startsWith(\"track\") || line.startsWith(\"browser\") || line.length === 0) {\n", " continue;\n", " }\n", "\n", " const tokens = line.split(delimiter);\n", "\n", " if (tokens.length < 6 && errorCount <= 5) {\n", " if (errorCount === 5) {\n", " console.error(\"...\");\n", " } else {\n", " console.error(\"Could not parse line: \" + line);\n", " }\n", "\n", " errorCount++;\n", " continue;\n", " }\n", "\n", " const feature = {\n", " chr1: genome ? genome.getChromosomeName(tokens[0]) : tokens[0],\n", " x1: parseInt(tokens[1]),\n", " x2: parseInt(tokens[2]),\n", " chr2: genome ? genome.getChromosomeName(tokens[3]) : tokens[3],\n", " y1: parseInt(tokens[4]),\n", " y2: parseInt(tokens[5])\n", " };\n", "\n", " if (tokens.length > colorColumn) {\n", " feature.color = \"rgb(\" + tokens[colorColumn] + \")\";\n", " }\n", "\n", " if (!Number.isNaN(feature.x1)) {\n", " allFeatures.push(feature);\n", " }\n", " }\n", "\n", " return allFeatures;\n", " }\n", "\n", " function getKey(chr1, chr2) {\n", " return chr1 > chr2 ? chr2 + \"_\" + chr1 : chr1 + \"_\" + chr2;\n", " }\n", "\n", " function validateColor(str) {\n", " var div = document.createElement(\"div\");\n", " div.style.borderColor = str;\n", " return div.style.borderColor !== \"\";\n", " }\n", "\n", " function buildOptions(config, options) {\n", " const defaultOptions = {\n", " oauthToken: config.oauthToken,\n", " headers: config.headers,\n", " withCredentials: config.withCredentials,\n", " filename: config.filename\n", " };\n", " return Object.assign(defaultOptions, options);\n", " }\n", "\n", " /*\n", " * The MIT License (MIT)\n", " *\n", " * Copyright (c) 2016-2017 The Regents of the University of California\n", " *\n", " * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and\n", " * associated documentation files (the \"Software\"), to deal in the Software without restriction, including\n", " * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n", " * copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the\n", " * following conditions:\n", " *\n", " * The above copyright notice and this permission notice shall be included in all copies or substantial\n", " * portions of the Software.\n", " *\n", " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING\n", " * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n", " * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n", " * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\n", " * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n", " * THE SOFTWARE.\n", " *\n", " */\n", "\n", " class Ruler {\n", " constructor(browser, $parent, axis) {\n", " this.browser = browser;\n", " this.axis = axis;\n", " this.$axis = $parent.find(`div[id$='-axis']`);\n", " this.$canvas = $parent.find(\"canvas\");\n", " this.ctx = this.$canvas.get(0).getContext(\"2d\");\n", " this.ctx.canvas.width = this.$axis.width();\n", " this.ctx.canvas.height = this.$axis.height();\n", " this.$wholeGenomeContainer = $parent.find(\"div[id$='-axis-whole-genome-container']\");\n", "\n", " this.yAxisTransformWithContext = ctx => {\n", " ctx.scale(-1, 1);\n", " ctx.rotate(Math.PI / 2.0);\n", " };\n", "\n", " this.setAxisTransform(axis);\n", " browser.eventBus.subscribe('MapLoad', this);\n", " browser.eventBus.subscribe(\"UpdateContactMapMousePosition\", this);\n", " }\n", "\n", " wholeGenomeLayout($axis, $wholeGenomeContainer, axisName, dataset) {\n", " var self = this,\n", " list,\n", " dimen,\n", " extent,\n", " scraps,\n", " $div,\n", " $firstDiv; // discard current tiles\n", "\n", " $wholeGenomeContainer.empty();\n", " list = dataset.chromosomes.filter(function (chromosome) {\n", " return 'all' !== chromosome.name.toLowerCase();\n", " });\n", " extent = 0; // could use reduce for this\n", "\n", " list.forEach(function (chromosome) {\n", " extent += chromosome.size;\n", " });\n", " dimen = 'x' === axisName ? $axis.width() : $axis.height();\n", " scraps = 0;\n", " this.bboxes = [];\n", " $firstDiv = undefined;\n", " list.forEach(function (chr) {\n", " var size, percentage;\n", " percentage = chr.bpLength / extent;\n", "\n", " if (percentage * dimen < 1.0) {\n", " scraps += percentage;\n", " } else {\n", " $div = $(\"
\", {\n", " class: `${self.axis}-axis-whole-genome-chromosome-container`\n", " });\n", " $wholeGenomeContainer.append($div);\n", " $div.data('label', chr.name); // debug\n", " // $div.get(0).style.backgroundColor = randomRGB(150, 250);\n", "\n", " if (!$firstDiv) {\n", " $firstDiv = $div;\n", " }\n", "\n", " if ('x' === axisName) {\n", " size = Math.round(percentage * dimen);\n", " $div.width(size);\n", " } else {\n", " size = Math.round(percentage * dimen);\n", " $div.height(size);\n", " } // border\n", "\n", "\n", " const $border = $('
');\n", " $div.append($border); // label\n", "\n", " const $label = $('
');\n", " $border.append($label);\n", " $label.text($div.data('label'));\n", " $label.get(0).title = $div.data('label');\n", " decorate.call(self, $div);\n", " }\n", " });\n", " scraps *= dimen;\n", " scraps = Math.floor(scraps);\n", "\n", " if (scraps >= 1) {\n", " const className = self.axis + '-axis-whole-genome-chromosome-container';\n", " $div = $(\"
\", {\n", " class: className\n", " });\n", " $wholeGenomeContainer.append($div);\n", " $div.data('label', '-');\n", " $div.width(scraps); // className = self.axis + '-axis-whole-genome-chromosome';\n", " // $e = $(\"
\", {class: className});\n", " // $div.append($e);\n", " // $e.text($div.data('label'));\n", "\n", " decorate.call(self, $div);\n", " }\n", "\n", " $wholeGenomeContainer.children().each(function (index) {\n", " self.bboxes.push(bbox(axisName, $(this), $firstDiv));\n", " }); // initially hide\n", "\n", " this.hideWholeGenome();\n", "\n", " function decorate($d) {\n", " var self = this;\n", " $d.on('click', function (e) {\n", " var $o;\n", " $o = $(this).first();\n", " self.browser.parseGotoInput($o.text());\n", " self.unhighlightWholeChromosome();\n", " self.otherRuler.unhighlightWholeChromosome();\n", " });\n", " $d.hover(function () {\n", " hoverHandler.call(self, $(this), true);\n", " }, function () {\n", " hoverHandler.call(self, $(this), false);\n", " });\n", " }\n", "\n", " function hoverHandler($e, doHover) {\n", " var target, $target;\n", " target = $e.data('label');\n", " this.otherRuler.$wholeGenomeContainer.children().each(function (index) {\n", " if (target === $(this).data('label')) {\n", " $target = $(this);\n", " }\n", " });\n", "\n", " if (true === doHover) {\n", " $e.addClass('hic-whole-genome-chromosome-highlight');\n", " $target.addClass('hic-whole-genome-chromosome-highlight');\n", " } else {\n", " $e.removeClass('hic-whole-genome-chromosome-highlight');\n", " $target.removeClass('hic-whole-genome-chromosome-highlight');\n", " }\n", " }\n", " }\n", "\n", " hideWholeGenome() {\n", " this.$wholeGenomeContainer.hide();\n", " this.$canvas.show();\n", " }\n", "\n", " showWholeGenome() {\n", " this.$canvas.hide();\n", " this.$wholeGenomeContainer.show();\n", " }\n", "\n", " setAxisTransform(axis) {\n", " this.canvasTransform = 'y' === axis ? this.yAxisTransformWithContext : identityTransformWithContext;\n", " this.labelReflectionTransform = 'y' === axis ? reflectionTransformWithContext : function (context, exe) {};\n", " }\n", "\n", " unhighlightWholeChromosome() {\n", " this.$wholeGenomeContainer.children().removeClass('hic-whole-genome-chromosome-highlight');\n", " }\n", "\n", " receiveEvent(event) {\n", " var offset, $e;\n", "\n", " if ('MapLoad' === event.type) {\n", " this.wholeGenomeLayout(this.$axis, this.$wholeGenomeContainer, this.axis, event.data);\n", " this.update();\n", " } else if ('UpdateContactMapMousePosition' === event.type) {\n", " if (this.bboxes) {\n", " this.unhighlightWholeChromosome();\n", " offset = 'x' === this.axis ? event.data.x : event.data.y;\n", " $e = hitTest(this.bboxes, offset);\n", "\n", " if ($e) {\n", " // console.log(this.axis + ' highlight chr ' + $e.text());\n", " $e.addClass('hic-whole-genome-chromosome-highlight');\n", " }\n", " }\n", " }\n", " }\n", "\n", " locusChange(event) {\n", " this.update();\n", " }\n", "\n", " updateWidthWithCalculation(calc) {\n", " this.$axis.css('width', calc);\n", " this.$canvas.width(this.$axis.width());\n", " this.$canvas.attr('width', this.$axis.width());\n", " this.wholeGenomeLayout(this.$axis, this.$wholeGenomeContainer, this.axis, this.browser.dataset);\n", " this.update();\n", " }\n", "\n", " updateHeight(height) {\n", " this.$canvas.height(height);\n", " this.$canvas.attr('height', height);\n", " this.wholeGenomeLayout(this.$axis, this.$wholeGenomeContainer, this.axis, this.browser.dataset);\n", " this.update();\n", " }\n", "\n", " update() {\n", " var w,\n", " h,\n", " bin,\n", " config = {},\n", " browser = this.browser;\n", "\n", " if (browser.dataset.isWholeGenome(browser.state.chr1)) {\n", " this.showWholeGenome();\n", " return;\n", " }\n", "\n", " this.hideWholeGenome();\n", " identityTransformWithContext(this.ctx);\n", " IGVGraphics.fillRect(this.ctx, 0, 0, this.$canvas.width(), this.$canvas.height(), {\n", " fillStyle: IGVColor.rgbColor(255, 255, 255)\n", " });\n", " this.canvasTransform(this.ctx);\n", " w = 'x' === this.axis ? this.$canvas.width() : this.$canvas.height();\n", " h = 'x' === this.axis ? this.$canvas.height() : this.$canvas.width();\n", " IGVGraphics.fillRect(this.ctx, 0, 0, w, h, {\n", " fillStyle: IGVColor.rgbColor(255, 255, 255)\n", " });\n", " config.bpPerPixel = browser.dataset.bpResolutions[browser.state.zoom] / browser.state.pixelSize;\n", " bin = 'x' === this.axis ? browser.state.x : browser.state.y;\n", " config.bpStart = bin * browser.dataset.bpResolutions[browser.state.zoom];\n", " config.rulerTickMarkReferencePixels = Math.max(Math.max(this.$canvas.width(), this.$canvas.height()), Math.max(this.$otherRulerCanvas.width(), this.$otherRulerCanvas.height()));\n", " config.rulerLengthPixels = w;\n", " config.rulerHeightPixels = h;\n", " config.height = Math.min(this.$canvas.width(), this.$canvas.height());\n", " this.draw(config);\n", " }\n", "\n", " draw(options) {\n", " var fontStyle,\n", " tickSpec,\n", " majorTickSpacing,\n", " nTick,\n", " pixelLast,\n", " pixel,\n", " tickSpacingPixels,\n", " labelWidthPixels,\n", " modulo,\n", " l,\n", " yShim,\n", " tickHeight,\n", " rulerLabel,\n", " chrSize,\n", " chromosomes = this.browser.dataset.chromosomes;\n", " 'x' === this.axis ? chromosomes[this.browser.state.chr1].name : chromosomes[this.browser.state.chr2].name;\n", " chrSize = 'x' === this.axis ? chromosomes[this.browser.state.chr1].size : chromosomes[this.browser.state.chr2].size;\n", "\n", " if (options.chrName === \"all\") ; else {\n", " IGVGraphics.fillRect(this.ctx, 0, 0, options.rulerLengthPixels, options.rulerHeightPixels, {\n", " fillStyle: IGVColor.rgbColor(255, 255, 255)\n", " });\n", " fontStyle = {\n", " textAlign: 'center',\n", " font: '9px PT Sans',\n", " fillStyle: \"rgba(64, 64, 64, 1)\",\n", " strokeStyle: \"rgba(64, 64, 64, 1)\"\n", " };\n", " tickSpec = findSpacing(Math.floor(options.rulerTickMarkReferencePixels * options.bpPerPixel));\n", " majorTickSpacing = tickSpec.majorTick; // Find starting point closest to the current origin\n", "\n", " nTick = Math.floor(options.bpStart / majorTickSpacing) - 1;\n", " pixel = pixelLast = 0;\n", " IGVGraphics.setProperties(this.ctx, fontStyle);\n", " this.ctx.lineWidth = 1.0;\n", " yShim = 1;\n", " tickHeight = 8;\n", "\n", " while (pixel < options.rulerLengthPixels) {\n", " l = Math.floor(nTick * majorTickSpacing);\n", " pixel = Math.round((l - 1 - options.bpStart + 0.5) / options.bpPerPixel);\n", " rulerLabel = formatNumber(l / tickSpec.unitMultiplier, 0) + \" \" + tickSpec.majorUnit;\n", " tickSpacingPixels = Math.abs(pixel - pixelLast);\n", " labelWidthPixels = this.ctx.measureText(rulerLabel).width;\n", "\n", " if (labelWidthPixels > tickSpacingPixels) {\n", " if (tickSpacingPixels < 32) {\n", " modulo = 4;\n", " } else {\n", " modulo = 2;\n", " }\n", " } else {\n", " modulo = 1;\n", " } // modulo = 1;\n", "\n", "\n", " if (0 === nTick % modulo) {\n", " if (Math.floor(pixel * options.bpPerPixel + options.bpStart) < chrSize) {\n", " // console.log(' label delta(' + Math.abs(pixel - pixelLast) + ') modulo(' + modulo + ') bpp(' + options.bpPerPixel + ')');\n", " this.ctx.save();\n", " this.labelReflectionTransform(this.ctx, pixel);\n", " IGVGraphics.fillText(this.ctx, rulerLabel, pixel, options.height - tickHeight / 0.75);\n", " this.ctx.restore();\n", " }\n", " }\n", "\n", " if (Math.floor(pixel * options.bpPerPixel + options.bpStart) < chrSize) {\n", " IGVGraphics.strokeLine(this.ctx, pixel, options.height - tickHeight, pixel, options.height - yShim);\n", " }\n", "\n", " pixelLast = pixel;\n", " nTick++;\n", " } // while (pixel < options.rulerLengthPixels)\n", "\n", "\n", " IGVGraphics.strokeLine(this.ctx, 0, options.height - yShim, options.rulerLengthPixels, options.height - yShim);\n", " }\n", "\n", " function formatNumber(anynum, decimal) {\n", " //decimal - the number of decimals after the digit from 0 to 3\n", " //-- Returns the passed number as a string in the xxx,xxx.xx format.\n", " //anynum = eval(obj.value);\n", " var divider = 10;\n", "\n", " switch (decimal) {\n", " case 0:\n", " divider = 1;\n", " break;\n", "\n", " case 1:\n", " divider = 10;\n", " break;\n", "\n", " case 2:\n", " divider = 100;\n", " break;\n", "\n", " default:\n", " //for 3 decimal places\n", " divider = 1000;\n", " }\n", "\n", " var workNum = Math.abs(Math.round(anynum * divider) / divider);\n", " var workStr = \"\" + workNum;\n", "\n", " if (-1 === workStr.indexOf(\".\")) {\n", " workStr += \".\";\n", " }\n", "\n", " var dStr = workStr.substr(0, workStr.indexOf(\".\"));\n", " var dNum = dStr - 0;\n", " var pStr = workStr.substr(workStr.indexOf(\".\"));\n", "\n", " while (pStr.length - 1 < decimal) {\n", " pStr += \"0\";\n", " }\n", "\n", " if ('.' === pStr) {\n", " pStr = '';\n", " } //--- Adds a comma in the thousands place.\n", "\n", "\n", " if (dNum >= 1000) {\n", " var dLen = dStr.length;\n", " dStr = parseInt(\"\" + dNum / 1000) + \",\" + dStr.substring(dLen - 3, dLen);\n", " } //-- Adds a comma in the millions place.\n", "\n", "\n", " if (dNum >= 1000000) {\n", " dLen = dStr.length;\n", " dStr = parseInt(\"\" + dNum / 1000000) + \",\" + dStr.substring(dLen - 7, dLen);\n", " }\n", "\n", " var retval = dStr + pStr; //-- Put numbers in parentheses if negative.\n", "\n", " if (anynum < 0) {\n", " retval = \"(\" + retval + \")\";\n", " } //You could include a dollar sign in the return value.\n", " //retval = \"$\"+retval\n", "\n", "\n", " return retval;\n", " }\n", " }\n", "\n", " }\n", "\n", " function bbox(axis, $child, $firstChild) {\n", " var delta, size, o, fo;\n", " o = 'x' === axis ? $child.offset().left : $child.offset().top;\n", " fo = 'x' === axis ? $firstChild.offset().left : $firstChild.offset().top;\n", " delta = o - fo;\n", " size = 'x' === axis ? $child.width() : $child.height();\n", " return {\n", " $e: $child,\n", " a: delta,\n", " b: delta + size\n", " };\n", " }\n", "\n", " function hitTest(bboxes, value) {\n", " var $result, success;\n", " success = false;\n", " $result = undefined;\n", " bboxes.forEach(function (bbox) {\n", " if (false === success) {\n", " if (value < bbox.a) ; else if (value > bbox.b) ; else {\n", " $result = bbox.$e;\n", " success = true;\n", " }\n", " }\n", " });\n", " return $result;\n", " }\n", "\n", " function TickSpacing(majorTick, majorUnit, unitMultiplier) {\n", " this.majorTick = majorTick;\n", " this.majorUnit = majorUnit;\n", " this.unitMultiplier = unitMultiplier;\n", " }\n", "\n", " function findSpacing(rulerLengthBP) {\n", " if (rulerLengthBP < 10) {\n", " return new TickSpacing(1, \"\", 1);\n", " } // How many zeroes?\n", "\n", "\n", " var nZeroes = Math.floor(log10(rulerLengthBP));\n", " var majorUnit = \"\";\n", " var unitMultiplier = 1;\n", "\n", " if (nZeroes > 9) {\n", " majorUnit = \"gb\";\n", " unitMultiplier = 1000000000;\n", " }\n", "\n", " if (nZeroes > 6) {\n", " majorUnit = \"mb\";\n", " unitMultiplier = 1000000;\n", " } else if (nZeroes > 3) {\n", " majorUnit = \"kb\";\n", " unitMultiplier = 1000;\n", " }\n", "\n", " var nMajorTicks = rulerLengthBP / Math.pow(10, nZeroes - 1);\n", "\n", " if (nMajorTicks < 25) {\n", " return new TickSpacing(Math.pow(10, nZeroes - 1), majorUnit, unitMultiplier);\n", " } else {\n", " return new TickSpacing(Math.pow(10, nZeroes) / 2, majorUnit, unitMultiplier);\n", " }\n", "\n", " function log10(x) {\n", " var dn = Math.log(10);\n", " return Math.log(x) / dn;\n", " }\n", " }\n", "\n", " function reflectionTransformWithContext(context, exe) {\n", " context.translate(exe, 0);\n", " context.scale(-1, 1);\n", " context.translate(-exe, 0);\n", " }\n", "\n", " function identityTransformWithContext(context) {\n", " // 3x2 matrix. column major. (sx 0 0 sy tx ty).\n", " context.setTransform(1, 0, 0, 1, 0, 0);\n", " }\n", "\n", " /*\n", " * The MIT License (MIT)\n", " *\n", " * Copyright (c) 2014 Broad Institute\n", " *\n", " * Permission is hereby granted, free of charge, to any person obtaining a copy\n", " * of this software and associated documentation files (the \"Software\"), to deal\n", " * in the Software without restriction, including without limitation the rights\n", " * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n", " * copies of the Software, and to permit persons to whom the Software is\n", " * furnished to do so, subject to the following conditions:\n", " *\n", " * The above copyright notice and this permission notice shall be included in\n", " * all copies or substantial portions of the Software.\n", " *\n", " *\n", " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n", " * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n", " * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n", " * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n", " * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n", " * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n", " * THE SOFTWARE.\n", " */\n", "\n", " const trackMenuItemListHelper = (itemList, $popover) => {\n", " var list = [];\n", "\n", " if (itemList.length > 0) {\n", " list = itemList.map(function (item, i) {\n", " let $e; // name and object fields checked for backward compatibility\n", "\n", " if (item.name) {\n", " $e = $('
');\n", " $e.text(item.name);\n", " } else if (item.object) {\n", " $e = $(item.object); // This creates a JQuery object form a dom element, or clones if already a jQuery object\n", " } else if (typeof item.label === 'string') {\n", " $e = $('
');\n", " $e.html(item.label);\n", " } else if (typeof item === 'string') {\n", " if (item.startsWith(\"<\")) {\n", " $e = $(item);\n", " } else {\n", " $e = $(\"
\" + item + \"
\");\n", " }\n", " }\n", "\n", " if (0 === i) {\n", " $e.addClass('igv-track-menu-border-top');\n", " }\n", "\n", " if (item.click) {\n", " $e.on('click', handleClick);\n", " $e.on('touchend', function (e) {\n", " handleClick(e);\n", " });\n", " $e.on('mouseup', function (e) {\n", " e.preventDefault();\n", " e.stopPropagation();\n", " }); // eslint-disable-next-line no-inner-declarations\n", "\n", " function handleClick(e) {\n", " item.click(e);\n", " $popover.hide();\n", " e.preventDefault();\n", " e.stopPropagation();\n", " }\n", " }\n", "\n", " return {\n", " object: $e,\n", " init: item.init || undefined\n", " };\n", " });\n", " }\n", "\n", " return list;\n", " };\n", "\n", " const MenuPopup = function ($parent) {\n", " // popover container\n", " this.$popover = $('
', {\n", " class: 'igv-menu-popup'\n", " });\n", " $parent.append(this.$popover); // popover header\n", "\n", " let $popoverHeader = $('
', {\n", " class: 'igv-menu-popup-header'\n", " });\n", " this.$popover.append($popoverHeader);\n", " attachDialogCloseHandlerWithParent$1($popoverHeader.get(0), () => this.$popover.hide());\n", " this.$popoverContent = $('
');\n", " this.$popover.append(this.$popoverContent);\n", " makeDraggable$1(this.$popover.get(0), $popoverHeader.get(0));\n", " $popoverHeader.on('click.menu-popup-dismiss', function (e) {\n", " e.stopPropagation();\n", " e.preventDefault(); // absorb click to prevent it leaking through to parent DOM element\n", " });\n", " };\n", "\n", " MenuPopup.prototype.presentMenuList = function (dx, dy, list) {\n", " hideAllMenuPopups();\n", "\n", " if (list.length > 0) {\n", " this.$popoverContent.empty();\n", " list = trackMenuItemListHelper(list, this.$popover);\n", "\n", " for (let item of list) {\n", " if (item.init) {\n", " item.init();\n", " }\n", "\n", " let $e = item.object;\n", "\n", " if (0 === list.indexOf(item)) {\n", " $e.removeClass('igv-track-menu-border-top');\n", " }\n", "\n", " if ($e.hasClass('igv-track-menu-border-top') || $e.hasClass('igv-menu-popup-check-container')) ; else if ($e.is('div')) {\n", " $e.addClass('igv-menu-popup-shim');\n", " }\n", "\n", " this.$popoverContent.append($e);\n", " }\n", "\n", " this.$popover.css({\n", " left: dx + 'px',\n", " top: dy + 'px'\n", " });\n", " this.$popover.show();\n", " }\n", " };\n", "\n", " MenuPopup.prototype.presentTrackContextMenu = function (e, menuItems) {\n", " this.$popoverContent.empty();\n", " const menuElements = createMenuElements(menuItems, this.$popover.get(0));\n", "\n", " for (let item of menuElements) {\n", " this.$popoverContent.get(0).appendChild(item.object);\n", " }\n", "\n", " present(e, this.$popover.get(0));\n", " this.$popover.show();\n", " };\n", "\n", " MenuPopup.prototype.dispose = function () {\n", " this.$popover.empty();\n", " this.$popoverContent.empty();\n", " Object.keys(this).forEach(function (key) {\n", " this[key] = undefined;\n", " });\n", " };\n", "\n", " function createMenuElements(itemList, popover) {\n", " return itemList.map(item => {\n", " let elem;\n", "\n", " if (typeof item === 'string' && '
' === item) {\n", " elem = document.createElement('hr');\n", " } else if (typeof item === 'string') {\n", " elem = div$1({\n", " class: 'context-menu'\n", " });\n", " elem.innerHTML = item;\n", " } else if (typeof item === 'Node') {\n", " elem = item;\n", " } else {\n", " if (typeof item.init === 'function') {\n", " item.init();\n", " }\n", "\n", " if (\"checkbox\" === item.type) {\n", " elem = Icon.createCheckbox(\"Show all bases\", item.value);\n", " } else if (\"color\" === item.type) {\n", " const colorPicker = new ColorPicker({\n", " parent: popover.parentElement,\n", " width: 364,\n", " //defaultColor: 'aqua',\n", " colorHandler: color => item.click(color)\n", " });\n", " elem = div$1({\n", " class: 'context-menu'\n", " });\n", "\n", " if (typeof item.label === 'string') {\n", " elem.innerHTML = item.label;\n", " }\n", "\n", " const clickHandler = e => {\n", " colorPicker.show();\n", " hide$1(popover);\n", " e.preventDefault();\n", " e.stopPropagation();\n", " };\n", "\n", " elem.addEventListener('click', clickHandler);\n", " elem.addEventListener('touchend', clickHandler);\n", " elem.addEventListener('mouseup', function (e) {\n", " e.preventDefault();\n", " e.stopPropagation();\n", " });\n", " } else {\n", " elem = div$1({\n", " class: 'context-menu'\n", " });\n", "\n", " if (typeof item.label === 'string') {\n", " elem.innerHTML = item.label;\n", " }\n", " }\n", "\n", " if (item.click && \"color\" !== item.type) {\n", " elem.addEventListener('click', handleClick);\n", " elem.addEventListener('touchend', handleClick);\n", " elem.addEventListener('mouseup', function (e) {\n", " e.preventDefault();\n", " e.stopPropagation();\n", " }); // eslint-disable-next-line no-inner-declarations\n", "\n", " function handleClick(e) {\n", " item.click();\n", " hide$1(popover);\n", " e.preventDefault();\n", " e.stopPropagation();\n", " }\n", " }\n", " }\n", "\n", " return {\n", " object: elem,\n", " init: item.init\n", " };\n", " });\n", " }\n", "\n", " function present(e, popover) {\n", " const {\n", " x,\n", " y\n", " } = translateMouseCoordinates(e, popover.parentNode); // parent bbox\n", "\n", " const {\n", " width\n", " } = popover.parentNode.getBoundingClientRect();\n", " const {\n", " width: w\n", " } = popover.getBoundingClientRect();\n", " const xmax = x + w;\n", " popover.style.left = `${xmax > width ? x - (xmax - width) : x}px`;\n", " popover.style.top = `${y}px`;\n", " }\n", "\n", " const hideAllMenuPopups = () => $('.igv-menu-popup').hide();\n", "\n", " /**\n", " * Created by dat on 4/5/17.\n", " */\n", "\n", " class TrackPair {\n", " constructor(browser, trackHeight, $x_tracks, $y_tracks, track, index) {\n", " this.browser = browser;\n", " this.track = track;\n", " this.x = new TrackRenderer(browser, {\n", " height: trackHeight\n", " }, $x_tracks, track, 'x', index);\n", " this.y = new TrackRenderer(browser, {\n", " width: trackHeight\n", " }, $y_tracks, track, 'y', index);\n", " this.init();\n", " }\n", "\n", " init() {\n", " this.colorPicker = new ColorPicker({\n", " parent: this.x.$viewport[0],\n", " width: 456,\n", " height: undefined,\n", " colorHandler: color => this.setColor(color)\n", " });\n", " this.colorPicker.hide();\n", " this.dataRangeDialog = new DataRangeDialog(this.x.$viewport[0], (min, max) => this.setDataRange(min, max));\n", " this.appendRightHandGutter(this.x.$viewport); // igvjs compatibility\n", "\n", " this.track.trackView = this;\n", " this.track.trackView.trackDiv = this.x.$viewport.get(0);\n", " }\n", "\n", " presentColorPicker() {\n", " const bbox = this.x.trackDiv.getBoundingClientRect();\n", " this.colorPicker.origin = {\n", " x: bbox.x,\n", " y: 0\n", " };\n", " this.colorPicker.$container.offset({\n", " left: this.colorPicker.origin.x,\n", " top: this.colorPicker.origin.y\n", " });\n", " this.colorPicker.$container.show();\n", " }\n", "\n", " setTrackName(name) {\n", " this.track.name = name;\n", " this.x.$label.text(name);\n", " }\n", "\n", " setColor(color) {\n", " this.y.tile = undefined;\n", " this.x.tile = undefined;\n", " this.track.color = color;\n", " this.repaintViews();\n", " }\n", "\n", " dataRange() {\n", " return this.track.dataRange ? this.track.dataRange : undefined;\n", " }\n", "\n", " setDataRange(min, max) {\n", " if (min !== undefined) {\n", " this.track.dataRange.min = min;\n", " this.track.config.min = min;\n", " }\n", "\n", " if (max !== undefined) {\n", " this.track.dataRange.max = max;\n", " this.track.config.max = max;\n", " }\n", "\n", " this.track.autoscale = false;\n", " this.track.config.autoScale = false;\n", " this.y.tile = undefined;\n", " this.x.tile = undefined;\n", " this.repaintViews();\n", " }\n", "\n", " appendRightHandGutter($parent) {\n", " let $div = $('
');\n", " $parent.append($div);\n", " this.createTrackGearPopup($div);\n", " }\n", "\n", " createTrackGearPopup($parent) {\n", " let $container = $(\"
\", {\n", " class: 'igv-trackgear-container'\n", " });\n", " $parent.append($container);\n", " $container.append(createIcon$1('cog'));\n", " this.trackGearPopup = new MenuPopup($parent);\n", " this.trackGearPopup.$popover.hide();\n", " $container.click(e => {\n", " e.preventDefault();\n", " e.stopPropagation();\n", " this.trackGearPopup.presentMenuList(-this.trackGearPopup.$popover.width(), 0, MenuUtils.trackMenuItemList(this));\n", " });\n", " }\n", "\n", " async updateViews() {\n", " if (this.updating) {\n", " this.pending = true;\n", " } else {\n", " try {\n", " this.updating = true;\n", " const genomicStateX = this.browser.genomicState(this.x.axis);\n", " let imageTileX = await this.getTileX(genomicStateX);\n", "\n", " if (imageTileX) {\n", " this.x.drawTile(imageTileX, genomicStateX);\n", " }\n", "\n", " const genomicStateY = this.browser.genomicState(this.y.axis);\n", " let imageTileY = await this.getTileY(genomicStateY);\n", "\n", " if (imageTileY) {\n", " this.y.drawTile(imageTileY, genomicStateY);\n", " }\n", " } finally {\n", " this.updating = false;\n", "\n", " if (this.pending) {\n", " this.pending = false;\n", " this.updateViews();\n", " }\n", " }\n", " }\n", " }\n", " /**\n", " * Repaint current tiles with cached features (due to color, scale, or other visual attribute change)\n", " * @returns {Promise}\n", " */\n", "\n", "\n", " async repaintViews() {\n", " const genomicStateX = this.browser.genomicState(this.x.axis);\n", "\n", " if (this.tileX) {\n", " this.tileX = await this.createImageTile(genomicStateX, this.tileX.features);\n", " this.x.drawTile(this.tileX, genomicStateX);\n", " }\n", "\n", " const genomicStateY = this.browser.genomicState(this.y.axis);\n", "\n", " if (this.tileY) {\n", " this.tileY = await this.createImageTile(genomicStateX, this.tileY.features);\n", " this.y.drawTile(this.tileY, genomicStateY);\n", " }\n", " }\n", "\n", " async getTileX(genomicState) {\n", " const chrName = genomicState.chromosome.name;\n", " const bpPerPixel = genomicState.bpp;\n", "\n", " if (!(this.tileX && this.tileX.containsRange(chrName, genomicState.startBP, genomicState.endBP, bpPerPixel))) {\n", " this.tileX = await this.createImageTile(genomicState);\n", " }\n", "\n", " return this.tileX;\n", " }\n", "\n", " async getTileY(genomicState) {\n", " const chrName = genomicState.chromosome.name;\n", " const bpPerPixel = genomicState.bpp;\n", "\n", " if (this.tileX && this.tileX.containsRange(chrName, genomicState.startBP, genomicState.endBP, bpPerPixel)) {\n", " this.tileY = this.tileX;\n", " } else if (!(this.tileY && this.tileY.containsRange(chrName, genomicState.startBP, genomicState.endBP, bpPerPixel))) {\n", " this.tileY = await this.createImageTile(genomicState);\n", " }\n", "\n", " return this.tileY;\n", " }\n", "\n", " async createImageTile(genomicState, tileFeatures) {\n", " const chrName = genomicState.chromosome.name;\n", " const bpPerPixel = genomicState.bpp;\n", "\n", " if (bpPerPixel * Math.max(this.x.$canvas.width(), this.x.$canvas.height()) > this.track.visibilityWindow) ; else {\n", " // Expand the requested range so we can pan a bit without reloading\n", " const pixelWidth = 3 * this.x.$canvas.width();\n", " const lengthBP = Math.round(bpPerPixel * pixelWidth);\n", " const bpStart = Math.max(0, Math.round(genomicState.startBP - lengthBP / 3));\n", " const bpEnd = bpStart + lengthBP;\n", " const features = tileFeatures || (await this.track.getFeatures(genomicState.chromosome.name, bpStart, bpEnd, bpPerPixel));\n", " const buffer = document.createElement('canvas');\n", " buffer.width = pixelWidth;\n", " buffer.height = this.x.$canvas.height();\n", " const context = buffer.getContext(\"2d\");\n", "\n", " if (features) {\n", " const drawConfiguration = {\n", " features,\n", " context,\n", " pixelWidth,\n", " bpStart,\n", " bpEnd,\n", " bpPerPixel,\n", " genomicState,\n", " pixelHeight: Math.min(buffer.width, buffer.height),\n", " viewportContainerX: (genomicState.startBP - bpStart) / bpPerPixel,\n", " viewportContainerWidth: pixelWidth,\n", " viewportWidth: pixelWidth,\n", " referenceFrame: {}\n", " };\n", "\n", " if (this.track.autoscale || !this.track.dataRange) {\n", " if (typeof this.track.doAutoscale === 'function') {\n", " this.track.doAutoscale(features);\n", " } else {\n", " this.track.dataRange = doAutoscale(features);\n", " }\n", " }\n", "\n", " this.track.draw(drawConfiguration);\n", " } else {\n", " context.clearRect(0, 0, this.$canvas.width(), this.$canvas.height());\n", " }\n", "\n", " this.tile = new Tile(chrName, bpStart, bpEnd, bpPerPixel, buffer, features);\n", " return this.tile;\n", " }\n", " }\n", "\n", " dispose() {\n", " this['x'].dispose();\n", " this['y'].dispose();\n", " }\n", "\n", " }\n", "\n", " class TrackRenderer {\n", " constructor(browser, size, $container, track, axis, order) {\n", " this.browser = browser;\n", " this.track = track;\n", " this.id = `trackRender_${guid()}`;\n", " this.axis = axis;\n", " this.init($container, size, order);\n", " }\n", "\n", " init($container, size, order) {\n", " var self = this; // track canvas container\n", "\n", " this.$viewport = 'x' === this.axis ? $('
') : $('
');\n", "\n", " if (size.width) {\n", " this.$viewport.width(size.width);\n", " }\n", "\n", " if (size.height) {\n", " this.$viewport.height(size.height);\n", " }\n", "\n", " $container.append(this.$viewport);\n", " this.$viewport.css({\n", " order: order\n", " }); // canvas\n", "\n", " this.$canvas = $('');\n", " this.$viewport.append(this.$canvas);\n", " this.ctx = this.$canvas.get(0).getContext(\"2d\");\n", "\n", " if ('x' === this.axis) {\n", " // label\n", " this.$label = $('
');\n", " const str = this.track.name || 'untitled';\n", " this.$label.text(str);\n", " this.$viewport.append(this.$label);\n", "\n", " if (true === self.browser.showTrackLabelAndGutter) {\n", " this.$label.show();\n", " } else {\n", " this.$label.hide();\n", " }\n", "\n", " this.$viewport.on('click', function (e) {\n", " e.preventDefault();\n", " e.stopPropagation();\n", " self.browser.toggleTrackLabelAndGutterState();\n", "\n", " if (true === self.browser.showTrackLabelAndGutter) {\n", " $('.x-track-label').show();\n", " $('.hic-igv-right-hand-gutter').show();\n", " } else {\n", " $('.x-track-label').hide();\n", " $('.hic-igv-right-hand-gutter').hide();\n", " }\n", " });\n", " } // track spinner container\n", "\n", "\n", " this.$spinner = 'x' === this.axis ? $('
') : $('
');\n", " this.$viewport.append(this.$spinner);\n", " this.stopSpinner();\n", " }\n", "\n", " dispose($container, size, order) {\n", " this.tile = undefined;\n", " this.$viewport.remove();\n", " }\n", "\n", " syncCanvas() {\n", " this.$canvas.width(this.$viewport.width());\n", " this.$canvas.attr('width', this.$viewport.width());\n", " this.$canvas.height(this.$viewport.height());\n", " this.$canvas.attr('height', this.$viewport.height());\n", " }\n", "\n", " drawTile(tile, genomicState) {\n", " if (tile) {\n", " this.offsetPixel = Math.round((tile.startBP - genomicState.startBP) / genomicState.bpp);\n", "\n", " if ('x' === this.axis) {\n", " this.ctx.clearRect(0, 0, this.$canvas.width(), this.$canvas.height());\n", " this.ctx.drawImage(tile.buffer, this.offsetPixel, 0);\n", " } else {\n", " this.ctx.setTransform(0, 1, 1, 0, 0, 0);\n", " this.ctx.clearRect(0, 0, this.$canvas.height(), this.$canvas.width());\n", " this.ctx.drawImage(tile.buffer, this.offsetPixel, 0);\n", " }\n", " }\n", " }\n", "\n", " startSpinner() {\n", " this.browser.startSpinner();\n", " }\n", "\n", " stopSpinner() {\n", " this.browser.stopSpinner();\n", " }\n", "\n", " isLoading() {\n", " return !(undefined === this.loading);\n", " }\n", "\n", " }\n", "\n", " class Tile {\n", " constructor(chr, startBP, endBP, bpp, buffer, features) {\n", " this.chr = chr;\n", " this.startBP = startBP;\n", " this.endBP = endBP;\n", " this.bpp = bpp;\n", " this.buffer = buffer;\n", " this.features = features;\n", " }\n", "\n", " containsRange(chr, startBP, endBP, bpp) {\n", " return chr === this.chr && this.bpp === bpp && this.startBP <= startBP && this.endBP >= endBP;\n", " }\n", "\n", " }\n", "\n", " /**\n", " * Created by dat on 4/4/17.\n", " */\n", " // $nav-bar-label-height: 36px;\n", "\n", " const nav_bar_label_height = 36; // $nav-bar-widget-container-height: 36px;\n", "\n", " const nav_bar_widget_container_height = 36; // $nav-bar-widget-container-margin: 4px;\n", "\n", " const nav_bar_widget_container_margin = 4; // $hic-scrollbar-height: 20px;\n", "\n", " const scrollbar_height = 20; // $hic-axis-height: 40px;\n", "\n", " const axis_height = 40; // $track-margin: 2px;\n", "\n", " const track_margin = 2;\n", " const trackHeight = 40;\n", "\n", " class LayoutController {\n", " constructor(browser, $root) {\n", " this.browser = browser;\n", " createNavBar(browser, $root);\n", " this.createAllContainers(browser, $root);\n", " }\n", "\n", " createAllContainers(browser, $root) {\n", " const html_x_track_container = `
`;\n", " $root.append($(html_x_track_container));\n", " this.$x_track_container = $root.find(\"div[id$='x-track-container']\");\n", " this.$track_shim = this.$x_track_container.find(\"div[id$='track-shim']\");\n", " this.$x_tracks = this.$x_track_container.find(\"div[id$='x-tracks']\");\n", " this.$y_track_guide = this.$x_track_container.find(\"div[id$='y-track-guide']\");\n", " const html_content_container = `
`;\n", " this.$content_container = $(html_content_container);\n", " $root.append(this.$content_container);\n", " const html_x_axis_container = `
\n", "
\n", " \n", "
\n", "
\n", "\t
`;\n", " this.$content_container.append($(html_x_axis_container));\n", " const $x_axis_container = this.$content_container.find(\"div[id$='x-axis-container']\");\n", " this.xAxisRuler = new Ruler(browser, $x_axis_container, 'x');\n", " const html_y_tracks_y_axis_viewport_y_scrollbar = `
\n", "\n", "
\n", "
\n", "
\n", " \n", "
\n", " \t\t\t\n", "\t\t\t
\n", "\t\t
\n", "\t\t \n", "
`;\n", " this.$content_container.append($(html_y_tracks_y_axis_viewport_y_scrollbar));\n", " const $y_tracks_y_axis_viewport_y_scrollbar = this.$content_container.find(\"div[id$='-y-tracks-y-axis-viewport-y-scrollbar']\");\n", " this.$y_tracks = $y_tracks_y_axis_viewport_y_scrollbar.find(\"div[id$='-y-tracks']\");\n", " this.$x_track_guide = this.$y_tracks.find(\"div[id$='-x-track-guide']\");\n", " this.yAxisRuler = new Ruler(browser, $y_tracks_y_axis_viewport_y_scrollbar, 'y');\n", " this.xAxisRuler.$otherRulerCanvas = this.yAxisRuler.$canvas;\n", " this.xAxisRuler.otherRuler = this.yAxisRuler;\n", " this.yAxisRuler.$otherRulerCanvas = this.xAxisRuler.$canvas;\n", " this.yAxisRuler.otherRuler = this.xAxisRuler;\n", " const html_viewport = `
\n", "\t\t\t\n", "\t\t\t\n", "\t\t\t
\n", "\t\t\t
\n", "\t\t\t
\n", "\t\t
`;\n", " $y_tracks_y_axis_viewport_y_scrollbar.append($(html_viewport));\n", " const html_y_axis_scrollbar_container = `
\n", "\t\t\t
\n", "\t\t\t\t
\n", "\t\t\t
\n", "\t\t
`;\n", " $y_tracks_y_axis_viewport_y_scrollbar.append($(html_y_axis_scrollbar_container));\n", " const html_x_axis_scrollbar_container = `
\n", "
\n", "
\n", "
\n", "
\n", "
\n", "\t
`;\n", " this.$content_container.append($(html_x_axis_scrollbar_container));\n", " }\n", "\n", " getContactMatrixViewport() {\n", " const $parent = this.$content_container.find(\"div[id$='-y-tracks-y-axis-viewport-y-scrollbar']\");\n", " return $parent.find(\"div[id$='-viewport']\");\n", " }\n", "\n", " getYAxisScrollbarContainer() {\n", " const $parent = this.$content_container.find(\"div[id$='-y-tracks-y-axis-viewport-y-scrollbar']\");\n", " return $parent.find(\"div[id$='-y-axis-scrollbar-container']\");\n", " }\n", "\n", " getXAxisScrollbarContainer() {\n", " return this.$content_container.find(\"div[id$='-x-axis-scrollbar-container']\");\n", " }\n", "\n", " tracksLoaded(tracks) {\n", " this.doLayoutTrackXYPairCount(tracks.length + this.browser.trackPairs.length);\n", " tracks.forEach((track, index) => {\n", " const trackPair = new TrackPair(this.browser, trackHeight, this.$x_tracks, this.$y_tracks, track, index);\n", " this.browser.trackPairs.push(trackPair);\n", " });\n", " }\n", "\n", " removeAllTrackXYPairs() {\n", " if (this.browser.trackPairs.length === 0) {\n", " return;\n", " }\n", "\n", " for (let trackPair of this.browser.trackPairs) {\n", " // discard DOM element's\n", " trackPair.dispose();\n", " }\n", "\n", " this.browser.trackPairs = [];\n", " this.browser.updateLayout();\n", " this.doLayoutTrackXYPairCount(0); // What ???\n", " // [...Array(this.browser.trackPairs.length).keys()].forEach(() => {\n", " //\n", " // // select last track to discard\n", " // let discard = this.browser.trackPairs[this.browser.trackPairs.length - 1];\n", " //\n", " // // discard DOM element's\n", " // discard['x'].$viewport.remove();\n", " // discard['y'].$viewport.remove();\n", " //\n", " // // remove discard from list\n", " // const index = this.browser.trackPairs.indexOf(discard);\n", " // this.browser.trackPairs.splice(index, 1);\n", " //\n", " // discard = undefined;\n", " // this.doLayoutTrackXYPairCount(this.browser.trackPairs.length);\n", " //\n", " // });\n", " }\n", "\n", " removeLastTrackXYPair() {\n", " if (this.browser.trackPairs.length > 0) {\n", " // select last track to dicard\n", " let discard = this.browser.trackPairs[this.browser.trackPairs.length - 1]; // discard DOM element's\n", "\n", " discard['x'].$viewport.remove();\n", " discard['y'].$viewport.remove(); // remove discard from list\n", "\n", " const index = this.browser.trackPairs.indexOf(discard);\n", " this.browser.trackPairs.splice(index, 1);\n", " discard = undefined;\n", " this.doLayoutTrackXYPairCount(this.browser.trackPairs.length);\n", " this.browser.updateLayout();\n", " }\n", " }\n", "\n", " removeTrackXYPair(trackXYPair) {\n", " if (this.browser.trackPairs.length > 0) {\n", " const discard = trackXYPair; // discard DOM element's\n", "\n", " discard['x'].$viewport.remove();\n", " discard['y'].$viewport.remove(); // remove discard from list\n", "\n", " const index = this.browser.trackPairs.indexOf(discard);\n", " this.browser.trackPairs.splice(index, 1);\n", " this.doLayoutTrackXYPairCount(this.browser.trackPairs.length);\n", " this.browser.updateLayout();\n", " }\n", " }\n", "\n", " doLayoutTrackXYPairCount(trackXYPairCount) {\n", " const track_aggregate_height = 0 === trackXYPairCount ? 0 : trackXYPairCount * (trackHeight + track_margin);\n", " let tokens = [getNavbarHeight(), track_aggregate_height].map(number => `${number}px`);\n", " const height_calc = 'calc(100% - (' + tokens.join(' + ') + '))';\n", " tokens = [track_aggregate_height, axis_height, scrollbar_height].map(number => `${number}px`);\n", " const width_calc = 'calc(100% - (' + tokens.join(' + ') + '))'; // x-track container\n", "\n", " this.$x_track_container.height(track_aggregate_height); // track labels\n", "\n", " this.$track_shim.width(track_aggregate_height); // x-tracks\n", "\n", " this.$x_tracks.css('width', width_calc); // content container\n", "\n", " this.$content_container.css('height', height_calc); // x-axis - repaint canvas\n", "\n", " this.xAxisRuler.updateWidthWithCalculation(width_calc); // y-tracks\n", "\n", " this.$y_tracks.width(track_aggregate_height); // y-axis - repaint canvas\n", "\n", " this.yAxisRuler.updateHeight(this.yAxisRuler.$axis.height()); // viewport\n", "\n", " this.browser.contactMatrixView.$viewport.css('width', width_calc); // x-scrollbar\n", "\n", " this.browser.contactMatrixView.scrollbarWidget.$x_axis_scrollbar_container.css('width', width_calc);\n", " }\n", "\n", " doLayoutWithRootContainerSize(size) {\n", " this.browser.$root.width(size.width);\n", " this.browser.$root.height(size.height + getNavbarHeight());\n", " const count = this.browser.trackPairs.length > 0 ? this.browser.trackPairs.length : 0;\n", " this.doLayoutTrackXYPairCount(count);\n", " this.browser.updateLayout();\n", " }\n", "\n", " }\n", "\n", " const getNavbarHeight = () => 2 * (nav_bar_label_height + nav_bar_widget_container_height + 2 * nav_bar_widget_container_margin);\n", "\n", " const getNavbarContainer = browser => browser.$root.find('.hic-navbar-container');\n", "\n", " function createNavBar(browser, $root) {\n", " const $hic_navbar_container = $('
', {\n", " class: 'hic-navbar-container'\n", " });\n", " $root.append($hic_navbar_container);\n", " $hic_navbar_container.on('click', e => {\n", " e.stopPropagation();\n", " e.preventDefault();\n", " setCurrentBrowser(browser);\n", " });\n", " const html_contact_map_hic_nav_bar_map_container = `
\n", "
\n", "
\n", "
\n", " \n", " \n", "
\n", "
`;\n", " $hic_navbar_container.append($(html_contact_map_hic_nav_bar_map_container));\n", " browser.$contactMaplabel = $hic_navbar_container.find(\"div[id$='contact-map-hic-nav-bar-map-label']\");\n", " browser.$menuPresentDismiss = $hic_navbar_container.find('.fa-bars');\n", " browser.$menuPresentDismiss.on('click', e => browser.toggleMenu());\n", " browser.$browser_panel_delete_button = $hic_navbar_container.find('.fa-minus-circle');\n", " browser.$browser_panel_delete_button.on('click', e => deleteBrowser(browser)); // Delete button is only vidible if there is more then one browser\n", "\n", " browser.$browser_panel_delete_button.hide();\n", " const html_control_map_hic_nav_bar_map_container = `
\n", "
\n", "
`;\n", " $hic_navbar_container.append($(html_control_map_hic_nav_bar_map_container));\n", " browser.$controlMaplabel = $hic_navbar_container.find(\"div[id$='control-map-hic-nav-bar-map-label']\");\n", " const html_upper_hic_nav_bar_widget_container = `
`;\n", " $hic_navbar_container.append($(html_upper_hic_nav_bar_widget_container));\n", " const html_lower_hic_nav_bar_widget_container = `
`;\n", " $hic_navbar_container.append($(html_lower_hic_nav_bar_widget_container));\n", " }\n", "\n", " /*\n", " * The MIT License (MIT)\n", " *\n", " * Copyright (c) 2016-2017 The Regents of the University of California\n", " *\n", " * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and\n", " * associated documentation files (the \"Software\"), to deal in the Software without restriction, including\n", " * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n", " * copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the\n", " * following conditions:\n", " *\n", " * The above copyright notice and this permission notice shall be included in all copies or substantial\n", " * portions of the Software.\n", " *\n", " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING\n", " * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n", " * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n", " * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\n", " * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n", " * THE SOFTWARE.\n", " *\n", " */\n", " function HICEvent(type, data, propogate) {\n", " return {\n", " type: type,\n", " data: data || {},\n", " propogate: propogate !== undefined ? propogate : true // Default to true\n", "\n", " };\n", " }\n", "\n", " // from https://github.com/imaya/zlib.js\n", " var Zlib = {\n", " Huffman: {},\n", " Util: {},\n", " CRC32: {}\n", " };\n", " /**\n", " * Compression Method\n", " * @enum {number}\n", " */\n", "\n", " Zlib.CompressionMethod = {\n", " DEFLATE: 8,\n", " RESERVED: 15\n", " };\n", " /**\n", " * @param {Object=} opt_params options.\n", " * @constructor\n", " */\n", "\n", " Zlib.Zip = function (opt_params) {\n", " opt_params = opt_params || {};\n", " /** @type {Array.<{\n", " * buffer: !(Array.|Uint8Array),\n", " * option: Object,\n", " * compressed: boolean,\n", " * encrypted: boolean,\n", " * size: number,\n", " * crc32: number\n", " * }>} */\n", "\n", " this.files = [];\n", " /** @type {(Array.|Uint8Array)} */\n", "\n", " this.comment = opt_params['comment'];\n", " /** @type {(Array.|Uint8Array)} */\n", "\n", " this.password;\n", " };\n", " /**\n", " * @enum {number}\n", " */\n", "\n", "\n", " Zlib.Zip.CompressionMethod = {\n", " STORE: 0,\n", " DEFLATE: 8\n", " };\n", " /**\n", " * @enum {number}\n", " */\n", "\n", " Zlib.Zip.OperatingSystem = {\n", " MSDOS: 0,\n", " UNIX: 3,\n", " MACINTOSH: 7\n", " };\n", " /**\n", " * @enum {number}\n", " */\n", "\n", " Zlib.Zip.Flags = {\n", " ENCRYPT: 0x0001,\n", " DESCRIPTOR: 0x0008,\n", " UTF8: 0x0800\n", " };\n", " /**\n", " * @type {Array.}\n", " * @const\n", " */\n", "\n", " Zlib.Zip.FileHeaderSignature = [0x50, 0x4b, 0x01, 0x02];\n", " /**\n", " * @type {Array.}\n", " * @const\n", " */\n", "\n", " Zlib.Zip.LocalFileHeaderSignature = [0x50, 0x4b, 0x03, 0x04];\n", " /**\n", " * @type {Array.}\n", " * @const\n", " */\n", "\n", " Zlib.Zip.CentralDirectorySignature = [0x50, 0x4b, 0x05, 0x06];\n", " /**\n", " * @param {Array.|Uint8Array} input\n", " * @param {Object=} opt_params options.\n", " */\n", "\n", " Zlib.Zip.prototype.addFile = function (input, opt_params) {\n", " opt_params = opt_params || {};\n", " /** @type {string} */\n", "\n", " opt_params['filename'];\n", " /** @type {boolean} */\n", "\n", " var compressed;\n", " /** @type {number} */\n", "\n", " var size = input.length;\n", " /** @type {number} */\n", "\n", " var crc32 = 0;\n", "\n", " if (input instanceof Array) {\n", " input = new Uint8Array(input);\n", " } // default\n", "\n", "\n", " if (typeof opt_params['compressionMethod'] !== 'number') {\n", " opt_params['compressionMethod'] = Zlib.Zip.CompressionMethod.DEFLATE;\n", " } // その場で圧縮する場合\n", "\n", "\n", " if (opt_params['compress']) {\n", " switch (opt_params['compressionMethod']) {\n", " case Zlib.Zip.CompressionMethod.STORE:\n", " break;\n", "\n", " case Zlib.Zip.CompressionMethod.DEFLATE:\n", " crc32 = Zlib.CRC32.calc(input);\n", " input = this.deflateWithOption(input, opt_params);\n", " compressed = true;\n", " break;\n", "\n", " default:\n", " throw new Error('unknown compression method:' + opt_params['compressionMethod']);\n", " }\n", " }\n", "\n", " this.files.push({\n", " buffer: input,\n", " option: opt_params,\n", " compressed: compressed,\n", " encrypted: false,\n", " size: size,\n", " crc32: crc32\n", " });\n", " };\n", " /**\n", " * @param {(Array.|Uint8Array)} password\n", " */\n", "\n", "\n", " Zlib.Zip.prototype.setPassword = function (password) {\n", " this.password = password;\n", " };\n", "\n", " Zlib.Zip.prototype.compress = function () {\n", " /** @type {Array.<{\n", " * buffer: !(Array.|Uint8Array),\n", " * option: Object,\n", " * compressed: boolean,\n", " * encrypted: boolean,\n", " * size: number,\n", " * crc32: number\n", " * }>} */\n", " var files = this.files;\n", " /** @type {{\n", " * buffer: !(Array.|Uint8Array),\n", " * option: Object,\n", " * compressed: boolean,\n", " * encrypted: boolean,\n", " * size: number,\n", " * crc32: number\n", " * }} */\n", "\n", " var file;\n", " /** @type {!(Array.|Uint8Array)} */\n", "\n", " var output;\n", " /** @type {number} */\n", "\n", " var op1;\n", " /** @type {number} */\n", "\n", " var op2;\n", " /** @type {number} */\n", "\n", " var op3;\n", " /** @type {number} */\n", "\n", " var localFileSize = 0;\n", " /** @type {number} */\n", "\n", " var centralDirectorySize = 0;\n", " /** @type {number} */\n", "\n", " var endOfCentralDirectorySize;\n", " /** @type {number} */\n", "\n", " var offset;\n", " /** @type {number} */\n", "\n", " var needVersion;\n", " /** @type {number} */\n", "\n", " var flags;\n", " /** @type {Zlib.Zip.CompressionMethod} */\n", "\n", " var compressionMethod;\n", " /** @type {Date} */\n", "\n", " var date;\n", " /** @type {number} */\n", "\n", " var crc32;\n", " /** @type {number} */\n", "\n", " var size;\n", " /** @type {number} */\n", "\n", " var plainSize;\n", " /** @type {number} */\n", "\n", " var filenameLength;\n", " /** @type {number} */\n", "\n", " var extraFieldLength;\n", " /** @type {number} */\n", "\n", " var commentLength;\n", " /** @type {(Array.|Uint8Array)} */\n", "\n", " var filename;\n", " /** @type {(Array.|Uint8Array)} */\n", "\n", " var extraField;\n", " /** @type {(Array.|Uint8Array)} */\n", "\n", " var comment;\n", " /** @type {(Array.|Uint8Array)} */\n", "\n", " var buffer;\n", " /** @type {*} */\n", "\n", " var tmp;\n", " /** @type {Array.|Uint32Array|Object} */\n", "\n", " var key;\n", " /** @type {number} */\n", "\n", " var i;\n", " /** @type {number} */\n", "\n", " var il;\n", " /** @type {number} */\n", "\n", " var j;\n", " /** @type {number} */\n", "\n", " var jl; // ファイルの圧縮\n", "\n", " for (i = 0, il = files.length; i < il; ++i) {\n", " file = files[i];\n", " filenameLength = file.option['filename'] ? file.option['filename'].length : 0;\n", " extraFieldLength = file.option['extraField'] ? file.option['extraField'].length : 0;\n", " commentLength = file.option['comment'] ? file.option['comment'].length : 0; // 圧縮されていなかったら圧縮\n", "\n", " if (!file.compressed) {\n", " // 圧縮前に CRC32 の計算をしておく\n", " file.crc32 = Zlib.CRC32.calc(file.buffer);\n", "\n", " switch (file.option['compressionMethod']) {\n", " case Zlib.Zip.CompressionMethod.STORE:\n", " break;\n", "\n", " case Zlib.Zip.CompressionMethod.DEFLATE:\n", " file.buffer = this.deflateWithOption(file.buffer, file.option);\n", " file.compressed = true;\n", " break;\n", "\n", " default:\n", " throw new Error('unknown compression method:' + file.option['compressionMethod']);\n", " }\n", " } // encryption\n", "\n", "\n", " if (file.option['password'] !== void 0 || this.password !== void 0) {\n", " // init encryption\n", " key = this.createEncryptionKey(file.option['password'] || this.password); // add header\n", "\n", " buffer = file.buffer;\n", "\n", " {\n", " tmp = new Uint8Array(buffer.length + 12);\n", " tmp.set(buffer, 12);\n", " buffer = tmp;\n", " }\n", "\n", " for (j = 0; j < 12; ++j) {\n", " buffer[j] = this.encode(key, i === 11 ? file.crc32 & 0xff : Math.random() * 256 | 0);\n", " } // data encryption\n", "\n", "\n", " for (jl = buffer.length; j < jl; ++j) {\n", " buffer[j] = this.encode(key, buffer[j]);\n", " }\n", "\n", " file.buffer = buffer;\n", " } // 必要バッファサイズの計算\n", "\n", "\n", " localFileSize += // local file header\n", " 30 + filenameLength + // file data\n", " file.buffer.length;\n", " centralDirectorySize += // file header\n", " 46 + filenameLength + commentLength;\n", " } // end of central directory\n", "\n", "\n", " endOfCentralDirectorySize = 22 + (this.comment ? this.comment.length : 0);\n", " output = new (Uint8Array )(localFileSize + centralDirectorySize + endOfCentralDirectorySize);\n", " op1 = 0;\n", " op2 = localFileSize;\n", " op3 = op2 + centralDirectorySize; // ファイルの圧縮\n", "\n", " for (i = 0, il = files.length; i < il; ++i) {\n", " file = files[i];\n", " filenameLength = file.option['filename'] ? file.option['filename'].length : 0;\n", " extraFieldLength = 0; // TODO\n", "\n", " commentLength = file.option['comment'] ? file.option['comment'].length : 0; //-------------------------------------------------------------------------\n", " // local file header & file header\n", " //-------------------------------------------------------------------------\n", "\n", " offset = op1; // signature\n", " // local file header\n", "\n", " output[op1++] = Zlib.Zip.LocalFileHeaderSignature[0];\n", " output[op1++] = Zlib.Zip.LocalFileHeaderSignature[1];\n", " output[op1++] = Zlib.Zip.LocalFileHeaderSignature[2];\n", " output[op1++] = Zlib.Zip.LocalFileHeaderSignature[3]; // file header\n", "\n", " output[op2++] = Zlib.Zip.FileHeaderSignature[0];\n", " output[op2++] = Zlib.Zip.FileHeaderSignature[1];\n", " output[op2++] = Zlib.Zip.FileHeaderSignature[2];\n", " output[op2++] = Zlib.Zip.FileHeaderSignature[3]; // compressor info\n", "\n", " needVersion = 20;\n", " output[op2++] = needVersion & 0xff;\n", " output[op2++] =\n", " /** @type {Zlib.Zip.OperatingSystem} */\n", " file.option['os'] || Zlib.Zip.OperatingSystem.MSDOS; // need version\n", "\n", " output[op1++] = output[op2++] = needVersion & 0xff;\n", " output[op1++] = output[op2++] = needVersion >> 8 & 0xff; // general purpose bit flag\n", "\n", " flags = 0;\n", "\n", " if (file.option['password'] || this.password) {\n", " flags |= Zlib.Zip.Flags.ENCRYPT;\n", " }\n", "\n", " output[op1++] = output[op2++] = flags & 0xff;\n", " output[op1++] = output[op2++] = flags >> 8 & 0xff; // compression method\n", "\n", " compressionMethod =\n", " /** @type {Zlib.Zip.CompressionMethod} */\n", " file.option['compressionMethod'];\n", " output[op1++] = output[op2++] = compressionMethod & 0xff;\n", " output[op1++] = output[op2++] = compressionMethod >> 8 & 0xff; // date\n", "\n", " date =\n", " /** @type {(Date|undefined)} */\n", " file.option['date'] || new Date();\n", " output[op1++] = output[op2++] = (date.getMinutes() & 0x7) << 5 | (date.getSeconds() / 2 | 0);\n", " output[op1++] = output[op2++] = date.getHours() << 3 | date.getMinutes() >> 3; //\n", "\n", " output[op1++] = output[op2++] = (date.getMonth() + 1 & 0x7) << 5 | date.getDate();\n", " output[op1++] = output[op2++] = (date.getFullYear() - 1980 & 0x7f) << 1 | date.getMonth() + 1 >> 3; // CRC-32\n", "\n", " crc32 = file.crc32;\n", " output[op1++] = output[op2++] = crc32 & 0xff;\n", " output[op1++] = output[op2++] = crc32 >> 8 & 0xff;\n", " output[op1++] = output[op2++] = crc32 >> 16 & 0xff;\n", " output[op1++] = output[op2++] = crc32 >> 24 & 0xff; // compressed size\n", "\n", " size = file.buffer.length;\n", " output[op1++] = output[op2++] = size & 0xff;\n", " output[op1++] = output[op2++] = size >> 8 & 0xff;\n", " output[op1++] = output[op2++] = size >> 16 & 0xff;\n", " output[op1++] = output[op2++] = size >> 24 & 0xff; // uncompressed size\n", "\n", " plainSize = file.size;\n", " output[op1++] = output[op2++] = plainSize & 0xff;\n", " output[op1++] = output[op2++] = plainSize >> 8 & 0xff;\n", " output[op1++] = output[op2++] = plainSize >> 16 & 0xff;\n", " output[op1++] = output[op2++] = plainSize >> 24 & 0xff; // filename length\n", "\n", " output[op1++] = output[op2++] = filenameLength & 0xff;\n", " output[op1++] = output[op2++] = filenameLength >> 8 & 0xff; // extra field length\n", "\n", " output[op1++] = output[op2++] = extraFieldLength & 0xff;\n", " output[op1++] = output[op2++] = extraFieldLength >> 8 & 0xff; // file comment length\n", "\n", " output[op2++] = commentLength & 0xff;\n", " output[op2++] = commentLength >> 8 & 0xff; // disk number start\n", "\n", " output[op2++] = 0;\n", " output[op2++] = 0; // internal file attributes\n", "\n", " output[op2++] = 0;\n", " output[op2++] = 0; // external file attributes\n", "\n", " output[op2++] = 0;\n", " output[op2++] = 0;\n", " output[op2++] = 0;\n", " output[op2++] = 0; // relative offset of local header\n", "\n", " output[op2++] = offset & 0xff;\n", " output[op2++] = offset >> 8 & 0xff;\n", " output[op2++] = offset >> 16 & 0xff;\n", " output[op2++] = offset >> 24 & 0xff; // filename\n", "\n", " filename = file.option['filename'];\n", "\n", " if (filename) {\n", " {\n", " output.set(filename, op1);\n", " output.set(filename, op2);\n", " op1 += filenameLength;\n", " op2 += filenameLength;\n", " }\n", " } // extra field\n", "\n", "\n", " extraField = file.option['extraField'];\n", "\n", " if (extraField) {\n", " {\n", " output.set(extraField, op1);\n", " output.set(extraField, op2);\n", " op1 += extraFieldLength;\n", " op2 += extraFieldLength;\n", " }\n", " } // comment\n", "\n", "\n", " comment = file.option['comment'];\n", "\n", " if (comment) {\n", " {\n", " output.set(comment, op2);\n", " op2 += commentLength;\n", " }\n", " } //-------------------------------------------------------------------------\n", " // file data\n", " //-------------------------------------------------------------------------\n", "\n", "\n", " {\n", " output.set(file.buffer, op1);\n", " op1 += file.buffer.length;\n", " }\n", " } //-------------------------------------------------------------------------\n", " // end of central directory\n", " //-------------------------------------------------------------------------\n", " // signature\n", "\n", "\n", " output[op3++] = Zlib.Zip.CentralDirectorySignature[0];\n", " output[op3++] = Zlib.Zip.CentralDirectorySignature[1];\n", " output[op3++] = Zlib.Zip.CentralDirectorySignature[2];\n", " output[op3++] = Zlib.Zip.CentralDirectorySignature[3]; // number of this disk\n", "\n", " output[op3++] = 0;\n", " output[op3++] = 0; // number of the disk with the start of the central directory\n", "\n", " output[op3++] = 0;\n", " output[op3++] = 0; // total number of entries in the central directory on this disk\n", "\n", " output[op3++] = il & 0xff;\n", " output[op3++] = il >> 8 & 0xff; // total number of entries in the central directory\n", "\n", " output[op3++] = il & 0xff;\n", " output[op3++] = il >> 8 & 0xff; // size of the central directory\n", "\n", " output[op3++] = centralDirectorySize & 0xff;\n", " output[op3++] = centralDirectorySize >> 8 & 0xff;\n", " output[op3++] = centralDirectorySize >> 16 & 0xff;\n", " output[op3++] = centralDirectorySize >> 24 & 0xff; // offset of start of central directory with respect to the starting disk number\n", "\n", " output[op3++] = localFileSize & 0xff;\n", " output[op3++] = localFileSize >> 8 & 0xff;\n", " output[op3++] = localFileSize >> 16 & 0xff;\n", " output[op3++] = localFileSize >> 24 & 0xff; // .ZIP file comment length\n", "\n", " commentLength = this.comment ? this.comment.length : 0;\n", " output[op3++] = commentLength & 0xff;\n", " output[op3++] = commentLength >> 8 & 0xff; // .ZIP file comment\n", "\n", " if (this.comment) {\n", " {\n", " output.set(this.comment, op3);\n", " op3 += commentLength;\n", " }\n", " }\n", "\n", " return output;\n", " };\n", " /**\n", " * @param {!(Array.|Uint8Array)} input\n", " * @param {Object=} opt_params options.\n", " * @return {!(Array.|Uint8Array)}\n", " */\n", "\n", "\n", " Zlib.Zip.prototype.deflateWithOption = function (input, opt_params) {\n", " /** @type {Zlib.RawDeflate} */\n", " var deflator = new Zlib.RawDeflate(input, opt_params['deflateOption']);\n", " return deflator.compress();\n", " };\n", " /**\n", " * @param {(Array.|Uint32Array)} key\n", " * @return {number}\n", " */\n", "\n", "\n", " Zlib.Zip.prototype.getByte = function (key) {\n", " /** @type {number} */\n", " var tmp = key[2] & 0xffff | 2;\n", " return tmp * (tmp ^ 1) >> 8 & 0xff;\n", " };\n", " /**\n", " * @param {(Array.|Uint32Array|Object)} key\n", " * @param {number} n\n", " * @return {number}\n", " */\n", "\n", "\n", " Zlib.Zip.prototype.encode = function (key, n) {\n", " /** @type {number} */\n", " var tmp = this.getByte(\n", " /** @type {(Array.|Uint32Array)} */\n", " key);\n", " this.updateKeys(\n", " /** @type {(Array.|Uint32Array)} */\n", " key, n);\n", " return tmp ^ n;\n", " };\n", " /**\n", " * @param {(Array.|Uint32Array)} key\n", " * @param {number} n\n", " */\n", "\n", "\n", " Zlib.Zip.prototype.updateKeys = function (key, n) {\n", " key[0] = Zlib.CRC32.single(key[0], n);\n", " key[1] = (((key[1] + (key[0] & 0xff)) * 20173 >>> 0) * 6681 >>> 0) + 1 >>> 0;\n", " key[2] = Zlib.CRC32.single(key[2], key[1] >>> 24);\n", " };\n", " /**\n", " * @param {(Array.|Uint8Array)} password\n", " * @return {!(Array.|Uint32Array|Object)}\n", " */\n", "\n", "\n", " Zlib.Zip.prototype.createEncryptionKey = function (password) {\n", " /** @type {!(Array.|Uint32Array)} */\n", " var key = [305419896, 591751049, 878082192];\n", " /** @type {number} */\n", "\n", " var i;\n", " /** @type {number} */\n", "\n", " var il;\n", "\n", " {\n", " key = new Uint32Array(key);\n", " }\n", "\n", " for (i = 0, il = password.length; i < il; ++i) {\n", " this.updateKeys(key, password[i] & 0xff);\n", " }\n", "\n", " return key;\n", " };\n", " /**\n", " * build huffman table from length list.\n", " * @param {!(Array.|Uint8Array)} lengths length list.\n", " * @return {!Array} huffman table.\n", " */\n", "\n", "\n", " Zlib.Huffman.buildHuffmanTable = function (lengths) {\n", " /** @type {number} length list size. */\n", " var listSize = lengths.length;\n", " /** @type {number} max code length for table size. */\n", "\n", " var maxCodeLength = 0;\n", " /** @type {number} min code length for table size. */\n", "\n", " var minCodeLength = Number.POSITIVE_INFINITY;\n", " /** @type {number} table size. */\n", "\n", " var size;\n", " /** @type {!(Array|Uint8Array)} huffman code table. */\n", "\n", " var table;\n", " /** @type {number} bit length. */\n", "\n", " var bitLength;\n", " /** @type {number} huffman code. */\n", "\n", " var code;\n", " /**\n", " * サイズが 2^maxlength 個のテーブルを埋めるためのスキップ長.\n", " * @type {number} skip length for table filling.\n", " */\n", "\n", " var skip;\n", " /** @type {number} reversed code. */\n", "\n", " var reversed;\n", " /** @type {number} reverse temp. */\n", "\n", " var rtemp;\n", " /** @type {number} loop counter. */\n", "\n", " var i;\n", " /** @type {number} loop limit. */\n", "\n", " var il;\n", " /** @type {number} loop counter. */\n", "\n", " var j;\n", " /** @type {number} table value. */\n", "\n", " var value; // Math.max は遅いので最長の値は for-loop で取得する\n", "\n", " for (i = 0, il = listSize; i < il; ++i) {\n", " if (lengths[i] > maxCodeLength) {\n", " maxCodeLength = lengths[i];\n", " }\n", "\n", " if (lengths[i] < minCodeLength) {\n", " minCodeLength = lengths[i];\n", " }\n", " }\n", "\n", " size = 1 << maxCodeLength;\n", " table = new (Uint32Array )(size); // ビット長の短い順からハフマン符号を割り当てる\n", "\n", " for (bitLength = 1, code = 0, skip = 2; bitLength <= maxCodeLength;) {\n", " for (i = 0; i < listSize; ++i) {\n", " if (lengths[i] === bitLength) {\n", " // ビットオーダーが逆になるためビット長分並びを反転する\n", " for (reversed = 0, rtemp = code, j = 0; j < bitLength; ++j) {\n", " reversed = reversed << 1 | rtemp & 1;\n", " rtemp >>= 1;\n", " } // 最大ビット長をもとにテーブルを作るため、\n", " // 最大ビット長以外では 0 / 1 どちらでも良い箇所ができる\n", " // そのどちらでも良い場所は同じ値で埋めることで\n", " // 本来のビット長以上のビット数取得しても問題が起こらないようにする\n", "\n", "\n", " value = bitLength << 16 | i;\n", "\n", " for (j = reversed; j < size; j += skip) {\n", " table[j] = value;\n", " }\n", "\n", " ++code;\n", " }\n", " } // 次のビット長へ\n", "\n", "\n", " ++bitLength;\n", " code <<= 1;\n", " skip <<= 1;\n", " }\n", "\n", " return [table, maxCodeLength, minCodeLength];\n", " }; //-----------------------------------------------------------------------------\n", "\n", " /** @define {number} buffer block size. */\n", "\n", "\n", " var ZLIB_RAW_INFLATE_BUFFER_SIZE = 0x8000; // [ 0x8000 >= ZLIB_BUFFER_BLOCK_SIZE ]\n", " //-----------------------------------------------------------------------------\n", "\n", " var buildHuffmanTable = Zlib.Huffman.buildHuffmanTable;\n", " /**\n", " * @constructor\n", " * @param {!(Uint8Array|Array.)} input input buffer.\n", " * @param {Object} opt_params option parameter.\n", " *\n", " * opt_params は以下のプロパティを指定する事ができます。\n", " * - index: input buffer の deflate コンテナの開始位置.\n", " * - blockSize: バッファのブロックサイズ.\n", " * - bufferType: Zlib.RawInflate.BufferType の値によってバッファの管理方法を指定する.\n", " * - resize: 確保したバッファが実際の大きさより大きかった場合に切り詰める.\n", " */\n", "\n", " Zlib.RawInflate = function (input, opt_params) {\n", " /** @type {!(Array.|Uint8Array)} inflated buffer */\n", " this.buffer;\n", " /** @type {!Array.<(Array.|Uint8Array)>} */\n", "\n", " this.blocks = [];\n", " /** @type {number} block size. */\n", "\n", " this.bufferSize = ZLIB_RAW_INFLATE_BUFFER_SIZE;\n", " /** @type {!number} total output buffer pointer. */\n", "\n", " this.totalpos = 0;\n", " /** @type {!number} input buffer pointer. */\n", "\n", " this.ip = 0;\n", " /** @type {!number} bit stream reader buffer. */\n", "\n", " this.bitsbuf = 0;\n", " /** @type {!number} bit stream reader buffer size. */\n", "\n", " this.bitsbuflen = 0;\n", " /** @type {!(Array.|Uint8Array)} input buffer. */\n", "\n", " this.input = new Uint8Array(input) ;\n", " /** @type {!(Uint8Array|Array.)} output buffer. */\n", "\n", " this.output;\n", " /** @type {!number} output buffer pointer. */\n", "\n", " this.op;\n", " /** @type {boolean} is final block flag. */\n", "\n", " this.bfinal = false;\n", " /** @type {Zlib.RawInflate.BufferType} buffer management. */\n", "\n", " this.bufferType = Zlib.RawInflate.BufferType.ADAPTIVE;\n", " /** @type {boolean} resize flag for memory size optimization. */\n", "\n", " this.resize = false; // option parameters\n", "\n", " if (opt_params || !(opt_params = {})) {\n", " if (opt_params['index']) {\n", " this.ip = opt_params['index'];\n", " }\n", "\n", " if (opt_params['bufferSize']) {\n", " this.bufferSize = opt_params['bufferSize'];\n", " }\n", "\n", " if (opt_params['bufferType']) {\n", " this.bufferType = opt_params['bufferType'];\n", " }\n", "\n", " if (opt_params['resize']) {\n", " this.resize = opt_params['resize'];\n", " }\n", " } // initialize\n", "\n", "\n", " switch (this.bufferType) {\n", " case Zlib.RawInflate.BufferType.BLOCK:\n", " this.op = Zlib.RawInflate.MaxBackwardLength;\n", " this.output = new (Uint8Array )(Zlib.RawInflate.MaxBackwardLength + this.bufferSize + Zlib.RawInflate.MaxCopyLength);\n", " break;\n", "\n", " case Zlib.RawInflate.BufferType.ADAPTIVE:\n", " this.op = 0;\n", " this.output = new (Uint8Array )(this.bufferSize);\n", " break;\n", "\n", " default:\n", " throw new Error('invalid inflate mode');\n", " }\n", " };\n", " /**\n", " * @enum {number}\n", " */\n", "\n", "\n", " Zlib.RawInflate.BufferType = {\n", " BLOCK: 0,\n", " ADAPTIVE: 1\n", " };\n", " /**\n", " * decompress.\n", " * @return {!(Uint8Array|Array.)} inflated buffer.\n", " */\n", "\n", " Zlib.RawInflate.prototype.decompress = function () {\n", " while (!this.bfinal) {\n", " this.parseBlock();\n", " }\n", "\n", " switch (this.bufferType) {\n", " case Zlib.RawInflate.BufferType.BLOCK:\n", " return this.concatBufferBlock();\n", "\n", " case Zlib.RawInflate.BufferType.ADAPTIVE:\n", " return this.concatBufferDynamic();\n", "\n", " default:\n", " throw new Error('invalid inflate mode');\n", " }\n", " };\n", " /**\n", " * @const\n", " * @type {number} max backward length for LZ77.\n", " */\n", "\n", "\n", " Zlib.RawInflate.MaxBackwardLength = 32768;\n", " /**\n", " * @const\n", " * @type {number} max copy length for LZ77.\n", " */\n", "\n", " Zlib.RawInflate.MaxCopyLength = 258;\n", " /**\n", " * huffman order\n", " * @const\n", " * @type {!(Array.|Uint8Array)}\n", " */\n", "\n", " Zlib.RawInflate.Order = function (table) {\n", " return new Uint16Array(table) ;\n", " }([16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]);\n", " /**\n", " * huffman length code table.\n", " * @const\n", " * @type {!(Array.|Uint16Array)}\n", " */\n", "\n", "\n", " Zlib.RawInflate.LengthCodeTable = function (table) {\n", " return new Uint16Array(table) ;\n", " }([0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000d, 0x000f, 0x0011, 0x0013, 0x0017, 0x001b, 0x001f, 0x0023, 0x002b, 0x0033, 0x003b, 0x0043, 0x0053, 0x0063, 0x0073, 0x0083, 0x00a3, 0x00c3, 0x00e3, 0x0102, 0x0102, 0x0102]);\n", " /**\n", " * huffman length extra-bits table.\n", " * @const\n", " * @type {!(Array.|Uint8Array)}\n", " */\n", "\n", "\n", " Zlib.RawInflate.LengthExtraTable = function (table) {\n", " return new Uint8Array(table) ;\n", " }([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, 0, 0]);\n", " /**\n", " * huffman dist code table.\n", " * @const\n", " * @type {!(Array.|Uint16Array)}\n", " */\n", "\n", "\n", " Zlib.RawInflate.DistCodeTable = function (table) {\n", " return new Uint16Array(table) ;\n", " }([0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0007, 0x0009, 0x000d, 0x0011, 0x0019, 0x0021, 0x0031, 0x0041, 0x0061, 0x0081, 0x00c1, 0x0101, 0x0181, 0x0201, 0x0301, 0x0401, 0x0601, 0x0801, 0x0c01, 0x1001, 0x1801, 0x2001, 0x3001, 0x4001, 0x6001]);\n", " /**\n", " * huffman dist extra-bits table.\n", " * @const\n", " * @type {!(Array.|Uint8Array)}\n", " */\n", "\n", "\n", " Zlib.RawInflate.DistExtraTable = function (table) {\n", " return new Uint8Array(table) ;\n", " }([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]);\n", " /**\n", " * fixed huffman length code table\n", " * @const\n", " * @type {!Array}\n", " */\n", "\n", "\n", " Zlib.RawInflate.FixedLiteralLengthTable = function (table) {\n", " return table;\n", " }(function () {\n", " var lengths = new (Uint8Array )(288);\n", " var i, il;\n", "\n", " for (i = 0, il = lengths.length; i < il; ++i) {\n", " lengths[i] = i <= 143 ? 8 : i <= 255 ? 9 : i <= 279 ? 7 : 8;\n", " }\n", "\n", " return buildHuffmanTable(lengths);\n", " }());\n", " /**\n", " * fixed huffman distance code table\n", " * @const\n", " * @type {!Array}\n", " */\n", "\n", "\n", " Zlib.RawInflate.FixedDistanceTable = function (table) {\n", " return table;\n", " }(function () {\n", " var lengths = new (Uint8Array )(30);\n", " var i, il;\n", "\n", " for (i = 0, il = lengths.length; i < il; ++i) {\n", " lengths[i] = 5;\n", " }\n", "\n", " return buildHuffmanTable(lengths);\n", " }());\n", " /**\n", " * parse deflated block.\n", " */\n", "\n", "\n", " Zlib.RawInflate.prototype.parseBlock = function () {\n", " /** @type {number} header */\n", " var hdr = this.readBits(3); // BFINAL\n", "\n", " if (hdr & 0x1) {\n", " this.bfinal = true;\n", " } // BTYPE\n", "\n", "\n", " hdr >>>= 1;\n", "\n", " switch (hdr) {\n", " // uncompressed\n", " case 0:\n", " this.parseUncompressedBlock();\n", " break;\n", " // fixed huffman\n", "\n", " case 1:\n", " this.parseFixedHuffmanBlock();\n", " break;\n", " // dynamic huffman\n", "\n", " case 2:\n", " this.parseDynamicHuffmanBlock();\n", " break;\n", " // reserved or other\n", "\n", " default:\n", " throw new Error('unknown BTYPE: ' + hdr);\n", " }\n", " };\n", " /**\n", " * read inflate bits\n", " * @param {number} length bits length.\n", " * @return {number} read bits.\n", " */\n", "\n", "\n", " Zlib.RawInflate.prototype.readBits = function (length) {\n", " var bitsbuf = this.bitsbuf;\n", " var bitsbuflen = this.bitsbuflen;\n", " var input = this.input;\n", " var ip = this.ip;\n", " /** @type {number} */\n", "\n", " var inputLength = input.length;\n", " /** @type {number} input and output byte. */\n", "\n", " var octet; // input byte\n", "\n", " if (ip + (length - bitsbuflen + 7 >> 3) >= inputLength) {\n", " throw new Error('input buffer is broken');\n", " } // not enough buffer\n", "\n", "\n", " while (bitsbuflen < length) {\n", " bitsbuf |= input[ip++] << bitsbuflen;\n", " bitsbuflen += 8;\n", " } // output byte\n", "\n", "\n", " octet = bitsbuf &\n", " /* MASK */\n", " (1 << length) - 1;\n", " bitsbuf >>>= length;\n", " bitsbuflen -= length;\n", " this.bitsbuf = bitsbuf;\n", " this.bitsbuflen = bitsbuflen;\n", " this.ip = ip;\n", " return octet;\n", " };\n", " /**\n", " * read huffman code using table\n", " * @param {!(Array.|Uint8Array|Uint16Array)} table huffman code table.\n", " * @return {number} huffman code.\n", " */\n", "\n", "\n", " Zlib.RawInflate.prototype.readCodeByTable = function (table) {\n", " var bitsbuf = this.bitsbuf;\n", " var bitsbuflen = this.bitsbuflen;\n", " var input = this.input;\n", " var ip = this.ip;\n", " /** @type {number} */\n", "\n", " var inputLength = input.length;\n", " /** @type {!(Array.|Uint8Array)} huffman code table */\n", "\n", " var codeTable = table[0];\n", " /** @type {number} */\n", "\n", " var maxCodeLength = table[1];\n", " /** @type {number} code length & code (16bit, 16bit) */\n", "\n", " var codeWithLength;\n", " /** @type {number} code bits length */\n", "\n", " var codeLength; // not enough buffer\n", "\n", " while (bitsbuflen < maxCodeLength) {\n", " if (ip >= inputLength) {\n", " break;\n", " }\n", "\n", " bitsbuf |= input[ip++] << bitsbuflen;\n", " bitsbuflen += 8;\n", " } // read max length\n", "\n", "\n", " codeWithLength = codeTable[bitsbuf & (1 << maxCodeLength) - 1];\n", " codeLength = codeWithLength >>> 16;\n", "\n", " if (codeLength > bitsbuflen) {\n", " throw new Error('invalid code length: ' + codeLength);\n", " }\n", "\n", " this.bitsbuf = bitsbuf >> codeLength;\n", " this.bitsbuflen = bitsbuflen - codeLength;\n", " this.ip = ip;\n", " return codeWithLength & 0xffff;\n", " };\n", " /**\n", " * parse uncompressed block.\n", " */\n", "\n", "\n", " Zlib.RawInflate.prototype.parseUncompressedBlock = function () {\n", " var input = this.input;\n", " var ip = this.ip;\n", " var output = this.output;\n", " var op = this.op;\n", " /** @type {number} */\n", "\n", " var inputLength = input.length;\n", " /** @type {number} block length */\n", "\n", " var len;\n", " /** @type {number} number for check block length */\n", "\n", " var nlen;\n", " /** @type {number} output buffer length */\n", "\n", " var olength = output.length;\n", " /** @type {number} copy counter */\n", "\n", " var preCopy; // skip buffered header bits\n", "\n", " this.bitsbuf = 0;\n", " this.bitsbuflen = 0; // len\n", "\n", " if (ip + 1 >= inputLength) {\n", " throw new Error('invalid uncompressed block header: LEN');\n", " }\n", "\n", " len = input[ip++] | input[ip++] << 8; // nlen\n", "\n", " if (ip + 1 >= inputLength) {\n", " throw new Error('invalid uncompressed block header: NLEN');\n", " }\n", "\n", " nlen = input[ip++] | input[ip++] << 8; // check len & nlen\n", "\n", " if (len === ~nlen) {\n", " throw new Error('invalid uncompressed block header: length verify');\n", " } // check size\n", "\n", "\n", " if (ip + len > input.length) {\n", " throw new Error('input buffer is broken');\n", " } // expand buffer\n", "\n", "\n", " switch (this.bufferType) {\n", " case Zlib.RawInflate.BufferType.BLOCK:\n", " // pre copy\n", " while (op + len > output.length) {\n", " preCopy = olength - op;\n", " len -= preCopy;\n", "\n", " {\n", " output.set(input.subarray(ip, ip + preCopy), op);\n", " op += preCopy;\n", " ip += preCopy;\n", " }\n", "\n", " this.op = op;\n", " output = this.expandBufferBlock();\n", " op = this.op;\n", " }\n", "\n", " break;\n", "\n", " case Zlib.RawInflate.BufferType.ADAPTIVE:\n", " while (op + len > output.length) {\n", " output = this.expandBufferAdaptive({\n", " fixRatio: 2\n", " });\n", " }\n", "\n", " break;\n", "\n", " default:\n", " throw new Error('invalid inflate mode');\n", " } // copy\n", "\n", "\n", " {\n", " output.set(input.subarray(ip, ip + len), op);\n", " op += len;\n", " ip += len;\n", " }\n", "\n", " this.ip = ip;\n", " this.op = op;\n", " this.output = output;\n", " };\n", " /**\n", " * parse fixed huffman block.\n", " */\n", "\n", "\n", " Zlib.RawInflate.prototype.parseFixedHuffmanBlock = function () {\n", " switch (this.bufferType) {\n", " case Zlib.RawInflate.BufferType.ADAPTIVE:\n", " this.decodeHuffmanAdaptive(Zlib.RawInflate.FixedLiteralLengthTable, Zlib.RawInflate.FixedDistanceTable);\n", " break;\n", "\n", " case Zlib.RawInflate.BufferType.BLOCK:\n", " this.decodeHuffmanBlock(Zlib.RawInflate.FixedLiteralLengthTable, Zlib.RawInflate.FixedDistanceTable);\n", " break;\n", "\n", " default:\n", " throw new Error('invalid inflate mode');\n", " }\n", " };\n", " /**\n", " * parse dynamic huffman block.\n", " */\n", "\n", "\n", " Zlib.RawInflate.prototype.parseDynamicHuffmanBlock = function () {\n", " /** @type {number} number of literal and length codes. */\n", " var hlit = this.readBits(5) + 257;\n", " /** @type {number} number of distance codes. */\n", "\n", " var hdist = this.readBits(5) + 1;\n", " /** @type {number} number of code lengths. */\n", "\n", " var hclen = this.readBits(4) + 4;\n", " /** @type {!(Uint8Array|Array.)} code lengths. */\n", "\n", " var codeLengths = new (Uint8Array )(Zlib.RawInflate.Order.length);\n", " /** @type {!Array} code lengths table. */\n", "\n", " var codeLengthsTable;\n", " /** @type {!(Uint8Array|Array.)} literal and length code table. */\n", "\n", " var litlenTable;\n", " /** @type {!(Uint8Array|Array.)} distance code table. */\n", "\n", " var distTable;\n", " /** @type {!(Uint8Array|Array.)} code length table. */\n", "\n", " var lengthTable;\n", " /** @type {number} */\n", "\n", " var code;\n", " /** @type {number} */\n", "\n", " var prev;\n", " /** @type {number} */\n", "\n", " var repeat;\n", " /** @type {number} loop counter. */\n", "\n", " var i;\n", " /** @type {number} loop limit. */\n", "\n", " var il; // decode code lengths\n", "\n", " for (i = 0; i < hclen; ++i) {\n", " codeLengths[Zlib.RawInflate.Order[i]] = this.readBits(3);\n", " }\n", "\n", "\n", " codeLengthsTable = buildHuffmanTable(codeLengths);\n", " lengthTable = new (Uint8Array )(hlit + hdist);\n", "\n", " for (i = 0, il = hlit + hdist; i < il;) {\n", " code = this.readCodeByTable(codeLengthsTable);\n", "\n", " switch (code) {\n", " case 16:\n", " repeat = 3 + this.readBits(2);\n", "\n", " while (repeat--) {\n", " lengthTable[i++] = prev;\n", " }\n", "\n", " break;\n", "\n", " case 17:\n", " repeat = 3 + this.readBits(3);\n", "\n", " while (repeat--) {\n", " lengthTable[i++] = 0;\n", " }\n", "\n", " prev = 0;\n", " break;\n", "\n", " case 18:\n", " repeat = 11 + this.readBits(7);\n", "\n", " while (repeat--) {\n", " lengthTable[i++] = 0;\n", " }\n", "\n", " prev = 0;\n", " break;\n", "\n", " default:\n", " lengthTable[i++] = code;\n", " prev = code;\n", " break;\n", " }\n", " }\n", "\n", " litlenTable = buildHuffmanTable(lengthTable.subarray(0, hlit)) ;\n", " distTable = buildHuffmanTable(lengthTable.subarray(hlit)) ;\n", "\n", " switch (this.bufferType) {\n", " case Zlib.RawInflate.BufferType.ADAPTIVE:\n", " this.decodeHuffmanAdaptive(litlenTable, distTable);\n", " break;\n", "\n", " case Zlib.RawInflate.BufferType.BLOCK:\n", " this.decodeHuffmanBlock(litlenTable, distTable);\n", " break;\n", "\n", " default:\n", " throw new Error('invalid inflate mode');\n", " }\n", " };\n", " /**\n", " * decode huffman code\n", " * @param {!(Array.|Uint16Array)} litlen literal and length code table.\n", " * @param {!(Array.|Uint8Array)} dist distination code table.\n", " */\n", "\n", "\n", " Zlib.RawInflate.prototype.decodeHuffmanBlock = function (litlen, dist) {\n", " var output = this.output;\n", " var op = this.op;\n", " this.currentLitlenTable = litlen;\n", " /** @type {number} output position limit. */\n", "\n", " var olength = output.length - Zlib.RawInflate.MaxCopyLength;\n", " /** @type {number} huffman code. */\n", "\n", " var code;\n", " /** @type {number} table index. */\n", "\n", " var ti;\n", " /** @type {number} huffman code distination. */\n", "\n", " var codeDist;\n", " /** @type {number} huffman code length. */\n", "\n", " var codeLength;\n", " var lengthCodeTable = Zlib.RawInflate.LengthCodeTable;\n", " var lengthExtraTable = Zlib.RawInflate.LengthExtraTable;\n", " var distCodeTable = Zlib.RawInflate.DistCodeTable;\n", " var distExtraTable = Zlib.RawInflate.DistExtraTable;\n", "\n", " while ((code = this.readCodeByTable(litlen)) !== 256) {\n", " // literal\n", " if (code < 256) {\n", " if (op >= olength) {\n", " this.op = op;\n", " output = this.expandBufferBlock();\n", " op = this.op;\n", " }\n", "\n", " output[op++] = code;\n", " continue;\n", " } // length code\n", "\n", "\n", " ti = code - 257;\n", " codeLength = lengthCodeTable[ti];\n", "\n", " if (lengthExtraTable[ti] > 0) {\n", " codeLength += this.readBits(lengthExtraTable[ti]);\n", " } // dist code\n", "\n", "\n", " code = this.readCodeByTable(dist);\n", " codeDist = distCodeTable[code];\n", "\n", " if (distExtraTable[code] > 0) {\n", " codeDist += this.readBits(distExtraTable[code]);\n", " } // lz77 decode\n", "\n", "\n", " if (op >= olength) {\n", " this.op = op;\n", " output = this.expandBufferBlock();\n", " op = this.op;\n", " }\n", "\n", " while (codeLength--) {\n", " output[op] = output[op++ - codeDist];\n", " }\n", " }\n", "\n", " while (this.bitsbuflen >= 8) {\n", " this.bitsbuflen -= 8;\n", " this.ip--;\n", " }\n", "\n", " this.op = op;\n", " };\n", " /**\n", " * decode huffman code (adaptive)\n", " * @param {!(Array.|Uint16Array)} litlen literal and length code table.\n", " * @param {!(Array.|Uint8Array)} dist distination code table.\n", " */\n", "\n", "\n", " Zlib.RawInflate.prototype.decodeHuffmanAdaptive = function (litlen, dist) {\n", " var output = this.output;\n", " var op = this.op;\n", " this.currentLitlenTable = litlen;\n", " /** @type {number} output position limit. */\n", "\n", " var olength = output.length;\n", " /** @type {number} huffman code. */\n", "\n", " var code;\n", " /** @type {number} table index. */\n", "\n", " var ti;\n", " /** @type {number} huffman code distination. */\n", "\n", " var codeDist;\n", " /** @type {number} huffman code length. */\n", "\n", " var codeLength;\n", " var lengthCodeTable = Zlib.RawInflate.LengthCodeTable;\n", " var lengthExtraTable = Zlib.RawInflate.LengthExtraTable;\n", " var distCodeTable = Zlib.RawInflate.DistCodeTable;\n", " var distExtraTable = Zlib.RawInflate.DistExtraTable;\n", "\n", " while ((code = this.readCodeByTable(litlen)) !== 256) {\n", " // literal\n", " if (code < 256) {\n", " if (op >= olength) {\n", " output = this.expandBufferAdaptive();\n", " olength = output.length;\n", " }\n", "\n", " output[op++] = code;\n", " continue;\n", " } // length code\n", "\n", "\n", " ti = code - 257;\n", " codeLength = lengthCodeTable[ti];\n", "\n", " if (lengthExtraTable[ti] > 0) {\n", " codeLength += this.readBits(lengthExtraTable[ti]);\n", " } // dist code\n", "\n", "\n", " code = this.readCodeByTable(dist);\n", " codeDist = distCodeTable[code];\n", "\n", " if (distExtraTable[code] > 0) {\n", " codeDist += this.readBits(distExtraTable[code]);\n", " } // lz77 decode\n", "\n", "\n", " if (op + codeLength > olength) {\n", " output = this.expandBufferAdaptive();\n", " olength = output.length;\n", " }\n", "\n", " while (codeLength--) {\n", " output[op] = output[op++ - codeDist];\n", " }\n", " }\n", "\n", " while (this.bitsbuflen >= 8) {\n", " this.bitsbuflen -= 8;\n", " this.ip--;\n", " }\n", "\n", " this.op = op;\n", " };\n", " /**\n", " * expand output buffer.\n", " * @param {Object=} opt_param option parameters.\n", " * @return {!(Array.|Uint8Array)} output buffer.\n", " */\n", "\n", "\n", " Zlib.RawInflate.prototype.expandBufferBlock = function (opt_param) {\n", " /** @type {!(Array.|Uint8Array)} store buffer. */\n", " var buffer = new (Uint8Array )(this.op - Zlib.RawInflate.MaxBackwardLength);\n", " /** @type {number} backward base point */\n", "\n", " var backward = this.op - Zlib.RawInflate.MaxBackwardLength;\n", " var output = this.output; // copy to output buffer\n", "\n", " {\n", " buffer.set(output.subarray(Zlib.RawInflate.MaxBackwardLength, buffer.length));\n", " }\n", "\n", " this.blocks.push(buffer);\n", " this.totalpos += buffer.length; // copy to backward buffer\n", "\n", " {\n", " output.set(output.subarray(backward, backward + Zlib.RawInflate.MaxBackwardLength));\n", " }\n", "\n", " this.op = Zlib.RawInflate.MaxBackwardLength;\n", " return output;\n", " };\n", " /**\n", " * expand output buffer. (adaptive)\n", " * @param {Object=} opt_param option parameters.\n", " * @return {!(Array.|Uint8Array)} output buffer pointer.\n", " */\n", "\n", "\n", " Zlib.RawInflate.prototype.expandBufferAdaptive = function (opt_param) {\n", " /** @type {!(Array.|Uint8Array)} store buffer. */\n", " var buffer;\n", " /** @type {number} expantion ratio. */\n", "\n", " var ratio = this.input.length / this.ip + 1 | 0;\n", " /** @type {number} maximum number of huffman code. */\n", "\n", " var maxHuffCode;\n", " /** @type {number} new output buffer size. */\n", "\n", " var newSize;\n", " /** @type {number} max inflate size. */\n", "\n", " var maxInflateSize;\n", " var input = this.input;\n", " var output = this.output;\n", "\n", " if (opt_param) {\n", " if (typeof opt_param.fixRatio === 'number') {\n", " ratio = opt_param.fixRatio;\n", " }\n", "\n", " if (typeof opt_param.addRatio === 'number') {\n", " ratio += opt_param.addRatio;\n", " }\n", " } // calculate new buffer size\n", "\n", "\n", " if (ratio < 2) {\n", " maxHuffCode = (input.length - this.ip) / this.currentLitlenTable[2];\n", " maxInflateSize = maxHuffCode / 2 * 258 | 0;\n", " newSize = maxInflateSize < output.length ? output.length + maxInflateSize : output.length << 1;\n", " } else {\n", " newSize = output.length * ratio;\n", " } // buffer expantion\n", "\n", "\n", " {\n", " buffer = new Uint8Array(newSize);\n", " buffer.set(output);\n", " }\n", "\n", " this.output = buffer;\n", " return this.output;\n", " };\n", " /**\n", " * concat output buffer.\n", " * @return {!(Array.|Uint8Array)} output buffer.\n", " */\n", "\n", "\n", " Zlib.RawInflate.prototype.concatBufferBlock = function () {\n", " /** @type {number} buffer pointer. */\n", " var pos = 0;\n", " /** @type {number} buffer pointer. */\n", "\n", " var limit = this.totalpos + (this.op - Zlib.RawInflate.MaxBackwardLength);\n", " /** @type {!(Array.|Uint8Array)} output block array. */\n", "\n", " var output = this.output;\n", " /** @type {!Array} blocks array. */\n", "\n", " var blocks = this.blocks;\n", " /** @type {!(Array.|Uint8Array)} output block array. */\n", "\n", " var block;\n", " /** @type {!(Array.|Uint8Array)} output buffer. */\n", "\n", " var buffer = new (Uint8Array )(limit);\n", " /** @type {number} loop counter. */\n", "\n", " var i;\n", " /** @type {number} loop limiter. */\n", "\n", " var il;\n", " /** @type {number} loop counter. */\n", "\n", " var j;\n", " /** @type {number} loop limiter. */\n", "\n", " var jl; // single buffer\n", "\n", " if (blocks.length === 0) {\n", " return this.output.subarray(Zlib.RawInflate.MaxBackwardLength, this.op) ;\n", " } // copy to buffer\n", "\n", "\n", " for (i = 0, il = blocks.length; i < il; ++i) {\n", " block = blocks[i];\n", "\n", " for (j = 0, jl = block.length; j < jl; ++j) {\n", " buffer[pos++] = block[j];\n", " }\n", " } // current buffer\n", "\n", "\n", " for (i = Zlib.RawInflate.MaxBackwardLength, il = this.op; i < il; ++i) {\n", " buffer[pos++] = output[i];\n", " }\n", "\n", " this.blocks = [];\n", " this.buffer = buffer;\n", " return this.buffer;\n", " };\n", " /**\n", " * concat output buffer. (dynamic)\n", " * @return {!(Array.|Uint8Array)} output buffer.\n", " */\n", "\n", "\n", " Zlib.RawInflate.prototype.concatBufferDynamic = function () {\n", " /** @type {Array.|Uint8Array} output buffer. */\n", " var buffer;\n", " var op = this.op;\n", "\n", " {\n", " if (this.resize) {\n", " buffer = new Uint8Array(op);\n", " buffer.set(this.output.subarray(0, op));\n", " } else {\n", " buffer = this.output.subarray(0, op);\n", " }\n", " }\n", "\n", " this.buffer = buffer;\n", " return this.buffer;\n", " };\n", "\n", " var buildHuffmanTable = Zlib.Huffman.buildHuffmanTable;\n", " /**\n", " * @param {!(Uint8Array|Array.)} input input buffer.\n", " * @param {number} ip input buffer pointer.\n", " * @param {number=} opt_buffersize buffer block size.\n", " * @constructor\n", " */\n", "\n", " Zlib.RawInflateStream = function (input, ip, opt_buffersize) {\n", " /** @type {!Array.<(Array|Uint8Array)>} */\n", " this.blocks = [];\n", " /** @type {number} block size. */\n", "\n", " this.bufferSize = opt_buffersize ? opt_buffersize : ZLIB_STREAM_RAW_INFLATE_BUFFER_SIZE;\n", " /** @type {!number} total output buffer pointer. */\n", "\n", " this.totalpos = 0;\n", " /** @type {!number} input buffer pointer. */\n", "\n", " this.ip = ip === void 0 ? 0 : ip;\n", " /** @type {!number} bit stream reader buffer. */\n", "\n", " this.bitsbuf = 0;\n", " /** @type {!number} bit stream reader buffer size. */\n", "\n", " this.bitsbuflen = 0;\n", " /** @type {!(Array|Uint8Array)} input buffer. */\n", "\n", " this.input = new Uint8Array(input) ;\n", " /** @type {!(Uint8Array|Array)} output buffer. */\n", "\n", " this.output = new (Uint8Array )(this.bufferSize);\n", " /** @type {!number} output buffer pointer. */\n", "\n", " this.op = 0;\n", " /** @type {boolean} is final block flag. */\n", "\n", " this.bfinal = false;\n", " /** @type {number} uncompressed block length. */\n", "\n", " this.blockLength;\n", " /** @type {boolean} resize flag for memory size optimization. */\n", "\n", " this.resize = false;\n", " /** @type {Array} */\n", "\n", " this.litlenTable;\n", " /** @type {Array} */\n", "\n", " this.distTable;\n", " /** @type {number} */\n", "\n", " this.sp = 0; // stream pointer\n", "\n", " /** @type {Zlib.RawInflateStream.Status} */\n", "\n", " this.status = Zlib.RawInflateStream.Status.INITIALIZED; //\n", " // backup\n", " //\n", "\n", " /** @type {!number} */\n", "\n", " this.ip_;\n", " /** @type {!number} */\n", "\n", " this.bitsbuflen_;\n", " /** @type {!number} */\n", "\n", " this.bitsbuf_;\n", " };\n", " /**\n", " * @enum {number}\n", " */\n", "\n", "\n", " Zlib.RawInflateStream.BlockType = {\n", " UNCOMPRESSED: 0,\n", " FIXED: 1,\n", " DYNAMIC: 2\n", " };\n", " /**\n", " * @enum {number}\n", " */\n", "\n", " Zlib.RawInflateStream.Status = {\n", " INITIALIZED: 0,\n", " BLOCK_HEADER_START: 1,\n", " BLOCK_HEADER_END: 2,\n", " BLOCK_BODY_START: 3,\n", " BLOCK_BODY_END: 4,\n", " DECODE_BLOCK_START: 5,\n", " DECODE_BLOCK_END: 6\n", " };\n", " /**\n", " * decompress.\n", " * @return {!(Uint8Array|Array)} inflated buffer.\n", " */\n", "\n", " Zlib.RawInflateStream.prototype.decompress = function (newInput, ip) {\n", " /** @type {boolean} */\n", " var stop = false;\n", "\n", " if (newInput !== void 0) {\n", " this.input = newInput;\n", " }\n", "\n", " if (ip !== void 0) {\n", " this.ip = ip;\n", " } // decompress\n", "\n", "\n", " while (!stop) {\n", " switch (this.status) {\n", " // block header\n", " case Zlib.RawInflateStream.Status.INITIALIZED:\n", " case Zlib.RawInflateStream.Status.BLOCK_HEADER_START:\n", " if (this.readBlockHeader() < 0) {\n", " stop = true;\n", " }\n", "\n", " break;\n", " // block body\n", "\n", " case Zlib.RawInflateStream.Status.BLOCK_HEADER_END:\n", " /* FALLTHROUGH */\n", "\n", " case Zlib.RawInflateStream.Status.BLOCK_BODY_START:\n", " switch (this.currentBlockType) {\n", " case Zlib.RawInflateStream.BlockType.UNCOMPRESSED:\n", " if (this.readUncompressedBlockHeader() < 0) {\n", " stop = true;\n", " }\n", "\n", " break;\n", "\n", " case Zlib.RawInflateStream.BlockType.FIXED:\n", " if (this.parseFixedHuffmanBlock() < 0) {\n", " stop = true;\n", " }\n", "\n", " break;\n", "\n", " case Zlib.RawInflateStream.BlockType.DYNAMIC:\n", " if (this.parseDynamicHuffmanBlock() < 0) {\n", " stop = true;\n", " }\n", "\n", " break;\n", " }\n", "\n", " break;\n", " // decode data\n", "\n", " case Zlib.RawInflateStream.Status.BLOCK_BODY_END:\n", " case Zlib.RawInflateStream.Status.DECODE_BLOCK_START:\n", " switch (this.currentBlockType) {\n", " case Zlib.RawInflateStream.BlockType.UNCOMPRESSED:\n", " if (this.parseUncompressedBlock() < 0) {\n", " stop = true;\n", " }\n", "\n", " break;\n", "\n", " case Zlib.RawInflateStream.BlockType.FIXED:\n", " /* FALLTHROUGH */\n", "\n", " case Zlib.RawInflateStream.BlockType.DYNAMIC:\n", " if (this.decodeHuffman() < 0) {\n", " stop = true;\n", " }\n", "\n", " break;\n", " }\n", "\n", " break;\n", "\n", " case Zlib.RawInflateStream.Status.DECODE_BLOCK_END:\n", " if (this.bfinal) {\n", " stop = true;\n", " } else {\n", " this.status = Zlib.RawInflateStream.Status.INITIALIZED;\n", " }\n", "\n", " break;\n", " }\n", " }\n", "\n", " return this.concatBuffer();\n", " };\n", " /**\n", " * @const\n", " * @type {number} max backward length for LZ77.\n", " */\n", "\n", "\n", " Zlib.RawInflateStream.MaxBackwardLength = 32768;\n", " /**\n", " * @const\n", " * @type {number} max copy length for LZ77.\n", " */\n", "\n", " Zlib.RawInflateStream.MaxCopyLength = 258;\n", " /**\n", " * huffman order\n", " * @const\n", " * @type {!(Array.|Uint8Array)}\n", " */\n", "\n", " Zlib.RawInflateStream.Order = function (table) {\n", " return new Uint16Array(table) ;\n", " }([16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]);\n", " /**\n", " * huffman length code table.\n", " * @const\n", " * @type {!(Array.|Uint16Array)}\n", " */\n", "\n", "\n", " Zlib.RawInflateStream.LengthCodeTable = function (table) {\n", " return new Uint16Array(table) ;\n", " }([0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000d, 0x000f, 0x0011, 0x0013, 0x0017, 0x001b, 0x001f, 0x0023, 0x002b, 0x0033, 0x003b, 0x0043, 0x0053, 0x0063, 0x0073, 0x0083, 0x00a3, 0x00c3, 0x00e3, 0x0102, 0x0102, 0x0102]);\n", " /**\n", " * huffman length extra-bits table.\n", " * @const\n", " * @type {!(Array.|Uint8Array)}\n", " */\n", "\n", "\n", " Zlib.RawInflateStream.LengthExtraTable = function (table) {\n", " return new Uint8Array(table) ;\n", " }([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, 0, 0]);\n", " /**\n", " * huffman dist code table.\n", " * @const\n", " * @type {!(Array.|Uint16Array)}\n", " */\n", "\n", "\n", " Zlib.RawInflateStream.DistCodeTable = function (table) {\n", " return new Uint16Array(table) ;\n", " }([0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0007, 0x0009, 0x000d, 0x0011, 0x0019, 0x0021, 0x0031, 0x0041, 0x0061, 0x0081, 0x00c1, 0x0101, 0x0181, 0x0201, 0x0301, 0x0401, 0x0601, 0x0801, 0x0c01, 0x1001, 0x1801, 0x2001, 0x3001, 0x4001, 0x6001]);\n", " /**\n", " * huffman dist extra-bits table.\n", " * @const\n", " * @type {!(Array.|Uint8Array)}\n", " */\n", "\n", "\n", " Zlib.RawInflateStream.DistExtraTable = function (table) {\n", " return new Uint8Array(table) ;\n", " }([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]);\n", " /**\n", " * fixed huffman length code table\n", " * @const\n", " * @type {!Array}\n", " */\n", "\n", "\n", " Zlib.RawInflateStream.FixedLiteralLengthTable = function (table) {\n", " return table;\n", " }(function () {\n", " var lengths = new (Uint8Array )(288);\n", " var i, il;\n", "\n", " for (i = 0, il = lengths.length; i < il; ++i) {\n", " lengths[i] = i <= 143 ? 8 : i <= 255 ? 9 : i <= 279 ? 7 : 8;\n", " }\n", "\n", " return buildHuffmanTable(lengths);\n", " }());\n", " /**\n", " * fixed huffman distance code table\n", " * @const\n", " * @type {!Array}\n", " */\n", "\n", "\n", " Zlib.RawInflateStream.FixedDistanceTable = function (table) {\n", " return table;\n", " }(function () {\n", " var lengths = new (Uint8Array )(30);\n", " var i, il;\n", "\n", " for (i = 0, il = lengths.length; i < il; ++i) {\n", " lengths[i] = 5;\n", " }\n", "\n", " return buildHuffmanTable(lengths);\n", " }());\n", " /**\n", " * parse deflated block.\n", " */\n", "\n", "\n", " Zlib.RawInflateStream.prototype.readBlockHeader = function () {\n", " /** @type {number} header */\n", " var hdr;\n", " this.status = Zlib.RawInflateStream.Status.BLOCK_HEADER_START;\n", " this.save_();\n", "\n", " if ((hdr = this.readBits(3)) < 0) {\n", " this.restore_();\n", " return -1;\n", " } // BFINAL\n", "\n", "\n", " if (hdr & 0x1) {\n", " this.bfinal = true;\n", " } // BTYPE\n", "\n", "\n", " hdr >>>= 1;\n", "\n", " switch (hdr) {\n", " case 0:\n", " // uncompressed\n", " this.currentBlockType = Zlib.RawInflateStream.BlockType.UNCOMPRESSED;\n", " break;\n", "\n", " case 1:\n", " // fixed huffman\n", " this.currentBlockType = Zlib.RawInflateStream.BlockType.FIXED;\n", " break;\n", "\n", " case 2:\n", " // dynamic huffman\n", " this.currentBlockType = Zlib.RawInflateStream.BlockType.DYNAMIC;\n", " break;\n", "\n", " default:\n", " // reserved or other\n", " throw new Error('unknown BTYPE: ' + hdr);\n", " }\n", "\n", " this.status = Zlib.RawInflateStream.Status.BLOCK_HEADER_END;\n", " };\n", " /**\n", " * read inflate bits\n", " * @param {number} length bits length.\n", " * @return {number} read bits.\n", " */\n", "\n", "\n", " Zlib.RawInflateStream.prototype.readBits = function (length) {\n", " var bitsbuf = this.bitsbuf;\n", " var bitsbuflen = this.bitsbuflen;\n", " var input = this.input;\n", " var ip = this.ip;\n", " /** @type {number} input and output byte. */\n", "\n", " var octet; // not enough buffer\n", "\n", " while (bitsbuflen < length) {\n", " // input byte\n", " if (input.length <= ip) {\n", " return -1;\n", " }\n", "\n", " octet = input[ip++]; // concat octet\n", "\n", " bitsbuf |= octet << bitsbuflen;\n", " bitsbuflen += 8;\n", " } // output byte\n", "\n", "\n", " octet = bitsbuf &\n", " /* MASK */\n", " (1 << length) - 1;\n", " bitsbuf >>>= length;\n", " bitsbuflen -= length;\n", " this.bitsbuf = bitsbuf;\n", " this.bitsbuflen = bitsbuflen;\n", " this.ip = ip;\n", " return octet;\n", " };\n", " /**\n", " * read huffman code using table\n", " * @param {Array} table huffman code table.\n", " * @return {number} huffman code.\n", " */\n", "\n", "\n", " Zlib.RawInflateStream.prototype.readCodeByTable = function (table) {\n", " var bitsbuf = this.bitsbuf;\n", " var bitsbuflen = this.bitsbuflen;\n", " var input = this.input;\n", " var ip = this.ip;\n", " /** @type {!(Array|Uint8Array)} huffman code table */\n", "\n", " var codeTable = table[0];\n", " /** @type {number} */\n", "\n", " var maxCodeLength = table[1];\n", " /** @type {number} input byte */\n", "\n", " var octet;\n", " /** @type {number} code length & code (16bit, 16bit) */\n", "\n", " var codeWithLength;\n", " /** @type {number} code bits length */\n", "\n", " var codeLength; // not enough buffer\n", "\n", " while (bitsbuflen < maxCodeLength) {\n", " if (input.length <= ip) {\n", " return -1;\n", " }\n", "\n", " octet = input[ip++];\n", " bitsbuf |= octet << bitsbuflen;\n", " bitsbuflen += 8;\n", " } // read max length\n", "\n", "\n", " codeWithLength = codeTable[bitsbuf & (1 << maxCodeLength) - 1];\n", " codeLength = codeWithLength >>> 16;\n", "\n", " if (codeLength > bitsbuflen) {\n", " throw new Error('invalid code length: ' + codeLength);\n", " }\n", "\n", " this.bitsbuf = bitsbuf >> codeLength;\n", " this.bitsbuflen = bitsbuflen - codeLength;\n", " this.ip = ip;\n", " return codeWithLength & 0xffff;\n", " };\n", " /**\n", " * read uncompressed block header\n", " */\n", "\n", "\n", " Zlib.RawInflateStream.prototype.readUncompressedBlockHeader = function () {\n", " /** @type {number} block length */\n", " var len;\n", " /** @type {number} number for check block length */\n", "\n", " var nlen;\n", " var input = this.input;\n", " var ip = this.ip;\n", " this.status = Zlib.RawInflateStream.Status.BLOCK_BODY_START;\n", "\n", " if (ip + 4 >= input.length) {\n", " return -1;\n", " }\n", "\n", " len = input[ip++] | input[ip++] << 8;\n", " nlen = input[ip++] | input[ip++] << 8; // check len & nlen\n", "\n", " if (len === ~nlen) {\n", " throw new Error('invalid uncompressed block header: length verify');\n", " } // skip buffered header bits\n", "\n", "\n", " this.bitsbuf = 0;\n", " this.bitsbuflen = 0;\n", " this.ip = ip;\n", " this.blockLength = len;\n", " this.status = Zlib.RawInflateStream.Status.BLOCK_BODY_END;\n", " };\n", " /**\n", " * parse uncompressed block.\n", " */\n", "\n", "\n", " Zlib.RawInflateStream.prototype.parseUncompressedBlock = function () {\n", " var input = this.input;\n", " var ip = this.ip;\n", " var output = this.output;\n", " var op = this.op;\n", " var len = this.blockLength;\n", " this.status = Zlib.RawInflateStream.Status.DECODE_BLOCK_START; // copy\n", " // XXX: とりあえず素直にコピー\n", "\n", " while (len--) {\n", " if (op === output.length) {\n", " output = this.expandBuffer({\n", " fixRatio: 2\n", " });\n", " } // not enough input buffer\n", "\n", "\n", " if (ip >= input.length) {\n", " this.ip = ip;\n", " this.op = op;\n", " this.blockLength = len + 1; // コピーしてないので戻す\n", "\n", " return -1;\n", " }\n", "\n", " output[op++] = input[ip++];\n", " }\n", "\n", " if (len < 0) {\n", " this.status = Zlib.RawInflateStream.Status.DECODE_BLOCK_END;\n", " }\n", "\n", " this.ip = ip;\n", " this.op = op;\n", " return 0;\n", " };\n", " /**\n", " * parse fixed huffman block.\n", " */\n", "\n", "\n", " Zlib.RawInflateStream.prototype.parseFixedHuffmanBlock = function () {\n", " this.status = Zlib.RawInflateStream.Status.BLOCK_BODY_START;\n", " this.litlenTable = Zlib.RawInflateStream.FixedLiteralLengthTable;\n", " this.distTable = Zlib.RawInflateStream.FixedDistanceTable;\n", " this.status = Zlib.RawInflateStream.Status.BLOCK_BODY_END;\n", " return 0;\n", " };\n", " /**\n", " * オブジェクトのコンテキストを別のプロパティに退避する.\n", " * @private\n", " */\n", "\n", "\n", " Zlib.RawInflateStream.prototype.save_ = function () {\n", " this.ip_ = this.ip;\n", " this.bitsbuflen_ = this.bitsbuflen;\n", " this.bitsbuf_ = this.bitsbuf;\n", " };\n", " /**\n", " * 別のプロパティに退避したコンテキストを復元する.\n", " * @private\n", " */\n", "\n", "\n", " Zlib.RawInflateStream.prototype.restore_ = function () {\n", " this.ip = this.ip_;\n", " this.bitsbuflen = this.bitsbuflen_;\n", " this.bitsbuf = this.bitsbuf_;\n", " };\n", " /**\n", " * parse dynamic huffman block.\n", " */\n", "\n", "\n", " Zlib.RawInflateStream.prototype.parseDynamicHuffmanBlock = function () {\n", " /** @type {number} number of literal and length codes. */\n", " var hlit;\n", " /** @type {number} number of distance codes. */\n", "\n", " var hdist;\n", " /** @type {number} number of code lengths. */\n", "\n", " var hclen;\n", " /** @type {!(Uint8Array|Array)} code lengths. */\n", "\n", " var codeLengths = new (Uint8Array )(Zlib.RawInflateStream.Order.length);\n", " /** @type {!Array} code lengths table. */\n", "\n", " var codeLengthsTable;\n", " this.status = Zlib.RawInflateStream.Status.BLOCK_BODY_START;\n", " this.save_();\n", " hlit = this.readBits(5) + 257;\n", " hdist = this.readBits(5) + 1;\n", " hclen = this.readBits(4) + 4;\n", "\n", " if (hlit < 0 || hdist < 0 || hclen < 0) {\n", " this.restore_();\n", " return -1;\n", " }\n", "\n", " try {\n", " parseDynamicHuffmanBlockImpl.call(this);\n", " } catch (e) {\n", " this.restore_();\n", " return -1;\n", " }\n", "\n", " function parseDynamicHuffmanBlockImpl() {\n", " /** @type {number} */\n", " var bits;\n", " var code;\n", " var prev = 0;\n", " var repeat;\n", " /** @type {!(Uint8Array|Array.)} code length table. */\n", "\n", " var lengthTable;\n", " /** @type {number} loop counter. */\n", "\n", " var i;\n", " /** @type {number} loop limit. */\n", "\n", " var il; // decode code lengths\n", "\n", " for (i = 0; i < hclen; ++i) {\n", " if ((bits = this.readBits(3)) < 0) {\n", " throw new Error('not enough input');\n", " }\n", "\n", " codeLengths[Zlib.RawInflateStream.Order[i]] = bits;\n", " } // decode length table\n", "\n", "\n", " codeLengthsTable = buildHuffmanTable(codeLengths);\n", " lengthTable = new (Uint8Array )(hlit + hdist);\n", "\n", " for (i = 0, il = hlit + hdist; i < il;) {\n", " code = this.readCodeByTable(codeLengthsTable);\n", "\n", " if (code < 0) {\n", " throw new Error('not enough input');\n", " }\n", "\n", " switch (code) {\n", " case 16:\n", " if ((bits = this.readBits(2)) < 0) {\n", " throw new Error('not enough input');\n", " }\n", "\n", " repeat = 3 + bits;\n", "\n", " while (repeat--) {\n", " lengthTable[i++] = prev;\n", " }\n", "\n", " break;\n", "\n", " case 17:\n", " if ((bits = this.readBits(3)) < 0) {\n", " throw new Error('not enough input');\n", " }\n", "\n", " repeat = 3 + bits;\n", "\n", " while (repeat--) {\n", " lengthTable[i++] = 0;\n", " }\n", "\n", " prev = 0;\n", " break;\n", "\n", " case 18:\n", " if ((bits = this.readBits(7)) < 0) {\n", " throw new Error('not enough input');\n", " }\n", "\n", " repeat = 11 + bits;\n", "\n", " while (repeat--) {\n", " lengthTable[i++] = 0;\n", " }\n", "\n", " prev = 0;\n", " break;\n", "\n", " default:\n", " lengthTable[i++] = code;\n", " prev = code;\n", " break;\n", " }\n", " } // literal and length code\n", " this.litlenTable = buildHuffmanTable(lengthTable.subarray(0, hlit)) ;\n", " this.distTable = buildHuffmanTable(lengthTable.subarray(hlit)) ;\n", " }\n", "\n", " this.status = Zlib.RawInflateStream.Status.BLOCK_BODY_END;\n", " return 0;\n", " };\n", " /**\n", " * decode huffman code (dynamic)\n", " * @return {(number|undefined)} -1 is error.\n", " */\n", "\n", "\n", " Zlib.RawInflateStream.prototype.decodeHuffman = function () {\n", " var output = this.output;\n", " var op = this.op;\n", " /** @type {number} huffman code. */\n", "\n", " var code;\n", " /** @type {number} table index. */\n", "\n", " var ti;\n", " /** @type {number} huffman code distination. */\n", "\n", " var codeDist;\n", " /** @type {number} huffman code length. */\n", "\n", " var codeLength;\n", " var litlen = this.litlenTable;\n", " var dist = this.distTable;\n", " var olength = output.length;\n", " var bits;\n", " this.status = Zlib.RawInflateStream.Status.DECODE_BLOCK_START;\n", "\n", " while (true) {\n", " this.save_();\n", " code = this.readCodeByTable(litlen);\n", "\n", " if (code < 0) {\n", " this.op = op;\n", " this.restore_();\n", " return -1;\n", " }\n", "\n", " if (code === 256) {\n", " break;\n", " } // literal\n", "\n", "\n", " if (code < 256) {\n", " if (op === olength) {\n", " output = this.expandBuffer();\n", " olength = output.length;\n", " }\n", "\n", " output[op++] = code;\n", " continue;\n", " } // length code\n", "\n", "\n", " ti = code - 257;\n", " codeLength = Zlib.RawInflateStream.LengthCodeTable[ti];\n", "\n", " if (Zlib.RawInflateStream.LengthExtraTable[ti] > 0) {\n", " bits = this.readBits(Zlib.RawInflateStream.LengthExtraTable[ti]);\n", "\n", " if (bits < 0) {\n", " this.op = op;\n", " this.restore_();\n", " return -1;\n", " }\n", "\n", " codeLength += bits;\n", " } // dist code\n", "\n", "\n", " code = this.readCodeByTable(dist);\n", "\n", " if (code < 0) {\n", " this.op = op;\n", " this.restore_();\n", " return -1;\n", " }\n", "\n", " codeDist = Zlib.RawInflateStream.DistCodeTable[code];\n", "\n", " if (Zlib.RawInflateStream.DistExtraTable[code] > 0) {\n", " bits = this.readBits(Zlib.RawInflateStream.DistExtraTable[code]);\n", "\n", " if (bits < 0) {\n", " this.op = op;\n", " this.restore_();\n", " return -1;\n", " }\n", "\n", " codeDist += bits;\n", " } // lz77 decode\n", "\n", "\n", " if (op + codeLength >= olength) {\n", " output = this.expandBuffer();\n", " olength = output.length;\n", " }\n", "\n", " while (codeLength--) {\n", " output[op] = output[op++ - codeDist];\n", " } // break\n", "\n", "\n", " if (this.ip === this.input.length) {\n", " this.op = op;\n", " return -1;\n", " }\n", " }\n", "\n", " while (this.bitsbuflen >= 8) {\n", " this.bitsbuflen -= 8;\n", " this.ip--;\n", " }\n", "\n", " this.op = op;\n", " this.status = Zlib.RawInflateStream.Status.DECODE_BLOCK_END;\n", " };\n", " /**\n", " * expand output buffer. (dynamic)\n", " * @param {Object=} opt_param option parameters.\n", " * @return {!(Array|Uint8Array)} output buffer pointer.\n", " */\n", "\n", "\n", " Zlib.RawInflateStream.prototype.expandBuffer = function (opt_param) {\n", " /** @type {!(Array|Uint8Array)} store buffer. */\n", " var buffer;\n", " /** @type {number} expantion ratio. */\n", "\n", " var ratio = this.input.length / this.ip + 1 | 0;\n", " /** @type {number} maximum number of huffman code. */\n", "\n", " var maxHuffCode;\n", " /** @type {number} new output buffer size. */\n", "\n", " var newSize;\n", " /** @type {number} max inflate size. */\n", "\n", " var maxInflateSize;\n", " var input = this.input;\n", " var output = this.output;\n", "\n", " if (opt_param) {\n", " if (typeof opt_param.fixRatio === 'number') {\n", " ratio = opt_param.fixRatio;\n", " }\n", "\n", " if (typeof opt_param.addRatio === 'number') {\n", " ratio += opt_param.addRatio;\n", " }\n", " } // calculate new buffer size\n", "\n", "\n", " if (ratio < 2) {\n", " maxHuffCode = (input.length - this.ip) / this.litlenTable[2];\n", " maxInflateSize = maxHuffCode / 2 * 258 | 0;\n", " newSize = maxInflateSize < output.length ? output.length + maxInflateSize : output.length << 1;\n", " } else {\n", " newSize = output.length * ratio;\n", " } // buffer expantion\n", "\n", "\n", " {\n", " buffer = new Uint8Array(newSize);\n", " buffer.set(output);\n", " }\n", "\n", " this.output = buffer;\n", " return this.output;\n", " };\n", " /**\n", " * concat output buffer. (dynamic)\n", " * @return {!(Array|Uint8Array)} output buffer.\n", " */\n", "\n", "\n", " Zlib.RawInflateStream.prototype.concatBuffer = function () {\n", " /** @type {!(Array|Uint8Array)} output buffer. */\n", " var buffer;\n", " /** @type {number} */\n", "\n", " var op = this.op;\n", " /** @type {Uint8Array} */\n", "\n", " var tmp;\n", "\n", " if (this.resize) {\n", " {\n", " buffer = new Uint8Array(this.output.subarray(this.sp, op));\n", " }\n", " } else {\n", " buffer = this.output.subarray(this.sp, op) ;\n", " }\n", "\n", " this.sp = op; // compaction\n", "\n", " if (op > Zlib.RawInflateStream.MaxBackwardLength + this.bufferSize) {\n", " this.op = this.sp = Zlib.RawInflateStream.MaxBackwardLength;\n", "\n", " {\n", " tmp =\n", " /** @type {Uint8Array} */\n", " this.output;\n", " this.output = new Uint8Array(this.bufferSize + Zlib.RawInflateStream.MaxBackwardLength);\n", " this.output.set(tmp.subarray(op - Zlib.RawInflateStream.MaxBackwardLength, op));\n", " }\n", " }\n", "\n", " return buffer;\n", " };\n", " /**\n", " * @constructor\n", " * @param {!(Uint8Array|Array)} input deflated buffer.\n", " * @param {Object=} opt_params option parameters.\n", " *\n", " * opt_params は以下のプロパティを指定する事ができます。\n", " * - index: input buffer の deflate コンテナの開始位置.\n", " * - blockSize: バッファのブロックサイズ.\n", " * - verify: 伸張が終わった後 adler-32 checksum の検証を行うか.\n", " * - bufferType: Zlib.Inflate.BufferType の値によってバッファの管理方法を指定する.\n", " * Zlib.Inflate.BufferType は Zlib.RawInflate.BufferType のエイリアス.\n", " */\n", "\n", "\n", " Zlib.Inflate = function (input, opt_params) {\n", " /** @type {number} */\n", "\n", " var cmf;\n", " /** @type {number} */\n", "\n", " var flg;\n", " /** @type {!(Uint8Array|Array)} */\n", "\n", " this.input = input;\n", " /** @type {number} */\n", "\n", " this.ip = 0;\n", " /** @type {Zlib.RawInflate} */\n", "\n", " this.rawinflate;\n", " /** @type {(boolean|undefined)} verify flag. */\n", "\n", " this.verify; // option parameters\n", "\n", " if (opt_params || !(opt_params = {})) {\n", " if (opt_params['index']) {\n", " this.ip = opt_params['index'];\n", " }\n", "\n", " if (opt_params['verify']) {\n", " this.verify = opt_params['verify'];\n", " }\n", " } // Compression Method and Flags\n", "\n", "\n", " cmf = input[this.ip++];\n", " flg = input[this.ip++]; // compression method\n", "\n", " switch (cmf & 0x0f) {\n", " case Zlib.CompressionMethod.DEFLATE:\n", " this.method = Zlib.CompressionMethod.DEFLATE;\n", " break;\n", "\n", " default:\n", " throw new Error('unsupported compression method');\n", " } // fcheck\n", "\n", "\n", " if (((cmf << 8) + flg) % 31 !== 0) {\n", " throw new Error('invalid fcheck flag:' + ((cmf << 8) + flg) % 31);\n", " } // fdict (not supported)\n", "\n", "\n", " if (flg & 0x20) {\n", " throw new Error('fdict flag is not supported');\n", " } // RawInflate\n", "\n", "\n", " this.rawinflate = new Zlib.RawInflate(input, {\n", " 'index': this.ip,\n", " 'bufferSize': opt_params['bufferSize'],\n", " 'bufferType': opt_params['bufferType'],\n", " 'resize': opt_params['resize']\n", " });\n", " };\n", " /**\n", " * @enum {number}\n", " */\n", "\n", "\n", " Zlib.Inflate.BufferType = Zlib.RawInflate.BufferType;\n", " /**\n", " * decompress.\n", " * @return {!(Uint8Array|Array)} inflated buffer.\n", " */\n", "\n", " Zlib.Inflate.prototype.decompress = function () {\n", " /** @type {!(Array|Uint8Array)} input buffer. */\n", " var input = this.input;\n", " /** @type {!(Uint8Array|Array)} inflated buffer. */\n", "\n", " var buffer;\n", " /** @type {number} adler-32 checksum */\n", "\n", " var adler32;\n", " buffer = this.rawinflate.decompress();\n", " this.ip = this.rawinflate.ip; // verify adler-32\n", "\n", " if (this.verify) {\n", " adler32 = (input[this.ip++] << 24 | input[this.ip++] << 16 | input[this.ip++] << 8 | input[this.ip++]) >>> 0;\n", "\n", " if (adler32 !== Zlib.Adler32(buffer)) {\n", " throw new Error('invalid adler-32 checksum');\n", " }\n", " }\n", "\n", " return buffer;\n", " };\n", " /* vim:set expandtab ts=2 sw=2 tw=80: */\n", "\n", " /**\n", " * @param {!(Uint8Array|Array)} input deflated buffer.\n", " * @constructor\n", " */\n", "\n", "\n", " Zlib.InflateStream = function (input) {\n", " /** @type {!(Uint8Array|Array)} */\n", " this.input = input === void 0 ? new (Uint8Array )() : input;\n", " /** @type {number} */\n", "\n", " this.ip = 0;\n", " /** @type {Zlib.RawInflateStream} */\n", "\n", " this.rawinflate = new Zlib.RawInflateStream(this.input, this.ip);\n", " /** @type {Zlib.CompressionMethod} */\n", "\n", " this.method;\n", " /** @type {!(Array|Uint8Array)} */\n", "\n", " this.output = this.rawinflate.output;\n", " };\n", " /**\n", " * decompress.\n", " * @return {!(Uint8Array|Array)} inflated buffer.\n", " */\n", "\n", "\n", " Zlib.InflateStream.prototype.decompress = function (input) {\n", " /** @type {!(Uint8Array|Array)} inflated buffer. */\n", " var buffer;\n", " // XXX Array, Uint8Array のチェックを行うか確認する\n", "\n", " if (input !== void 0) {\n", " {\n", " var tmp = new Uint8Array(this.input.length + input.length);\n", " tmp.set(this.input, 0);\n", " tmp.set(input, this.input.length);\n", " this.input = tmp;\n", " }\n", " }\n", "\n", " if (this.method === void 0) {\n", " if (this.readHeader() < 0) {\n", " return new (Uint8Array )();\n", " }\n", " }\n", "\n", " buffer = this.rawinflate.decompress(this.input, this.ip);\n", "\n", " if (this.rawinflate.ip !== 0) {\n", " this.input = this.input.subarray(this.rawinflate.ip) ;\n", " this.ip = 0;\n", " } // verify adler-32\n", "\n", " /*\n", " if (this.verify) {\n", " adler32 =\n", " input[this.ip++] << 24 | input[this.ip++] << 16 |\n", " input[this.ip++] << 8 | input[this.ip++];\n", " if (adler32 !== Zlib.Adler32(buffer)) {\n", " throw new Error('invalid adler-32 checksum');\n", " }\n", " }\n", " */\n", "\n", "\n", " return buffer;\n", " };\n", "\n", " Zlib.InflateStream.prototype.readHeader = function () {\n", " var ip = this.ip;\n", " var input = this.input; // Compression Method and Flags\n", "\n", " var cmf = input[ip++];\n", " var flg = input[ip++];\n", "\n", " if (cmf === void 0 || flg === void 0) {\n", " return -1;\n", " } // compression method\n", "\n", "\n", " switch (cmf & 0x0f) {\n", " case Zlib.CompressionMethod.DEFLATE:\n", " this.method = Zlib.CompressionMethod.DEFLATE;\n", " break;\n", "\n", " default:\n", " throw new Error('unsupported compression method');\n", " } // fcheck\n", "\n", "\n", " if (((cmf << 8) + flg) % 31 !== 0) {\n", " throw new Error('invalid fcheck flag:' + ((cmf << 8) + flg) % 31);\n", " } // fdict (not supported)\n", "\n", "\n", " if (flg & 0x20) {\n", " throw new Error('fdict flag is not supported');\n", " }\n", "\n", " this.ip = ip;\n", " };\n", " /**\n", " * @fileoverview GZIP (RFC1952) 展開コンテナ実装.\n", " */\n", "\n", " /**\n", " * @constructor\n", " * @param {!(Array|Uint8Array)} input input buffer.\n", " * @param {Object=} opt_params option parameters.\n", " */\n", "\n", "\n", " Zlib.Gunzip = function (input, opt_params) {\n", " /** @type {!(Array.|Uint8Array)} input buffer. */\n", " this.input = input;\n", " /** @type {number} input buffer pointer. */\n", "\n", " this.ip = 0;\n", " /** @type {Array.} */\n", "\n", " this.member = [];\n", " /** @type {boolean} */\n", "\n", " this.decompressed = false;\n", " };\n", " /**\n", " * @return {Array.}\n", " */\n", "\n", "\n", " Zlib.Gunzip.prototype.getMembers = function () {\n", " if (!this.decompressed) {\n", " this.decompress();\n", " }\n", "\n", " return this.member.slice();\n", " };\n", " /**\n", " * inflate gzip data.\n", " * @return {!(Array.|Uint8Array)} inflated buffer.\n", " */\n", "\n", "\n", " Zlib.Gunzip.prototype.decompress = function () {\n", " /** @type {number} input length. */\n", " var il = this.input.length;\n", "\n", " while (this.ip < il) {\n", " this.decodeMember();\n", " }\n", "\n", " this.decompressed = true;\n", " return this.concatMember();\n", " };\n", " /**\n", " * decode gzip member.\n", " */\n", "\n", "\n", " Zlib.Gunzip.prototype.decodeMember = function () {\n", " /** @type {Zlib.GunzipMember} */\n", " var member = new Zlib.GunzipMember();\n", " /** @type {number} */\n", "\n", " var isize;\n", " /** @type {Zlib.RawInflate} RawInflate implementation. */\n", "\n", " var rawinflate;\n", " /** @type {!(Array.|Uint8Array)} inflated data. */\n", "\n", " var inflated;\n", " /** @type {number} inflate size */\n", "\n", " var inflen;\n", " /** @type {number} character code */\n", "\n", " var c;\n", " /** @type {number} character index in string. */\n", "\n", " var ci;\n", " /** @type {Array.} character array. */\n", "\n", " var str;\n", " /** @type {number} modification time. */\n", "\n", " var mtime;\n", " /** @type {number} */\n", "\n", " var crc32;\n", " var input = this.input;\n", " var ip = this.ip;\n", " member.id1 = input[ip++];\n", " member.id2 = input[ip++]; // check signature\n", "\n", " if (member.id1 !== 0x1f || member.id2 !== 0x8b) {\n", " throw new Error('invalid file signature:' + member.id1 + ',' + member.id2);\n", " } // check compression method\n", "\n", "\n", " member.cm = input[ip++];\n", "\n", " switch (member.cm) {\n", " case 8:\n", " /* XXX: use Zlib const */\n", " break;\n", "\n", " default:\n", " throw new Error('unknown compression method: ' + member.cm);\n", " } // flags\n", "\n", "\n", " member.flg = input[ip++]; // modification time\n", "\n", " mtime = input[ip++] | input[ip++] << 8 | input[ip++] << 16 | input[ip++] << 24;\n", " member.mtime = new Date(mtime * 1000); // extra flags\n", "\n", " member.xfl = input[ip++]; // operating system\n", "\n", " member.os = input[ip++]; // extra\n", "\n", " if ((member.flg & Zlib.Gzip.FlagsMask.FEXTRA) > 0) {\n", " member.xlen = input[ip++] | input[ip++] << 8;\n", " ip = this.decodeSubField(ip, member.xlen);\n", " } // fname\n", "\n", "\n", " if ((member.flg & Zlib.Gzip.FlagsMask.FNAME) > 0) {\n", " for (str = [], ci = 0; (c = input[ip++]) > 0;) {\n", " str[ci++] = String.fromCharCode(c);\n", " }\n", "\n", " member.name = str.join('');\n", " } // fcomment\n", "\n", "\n", " if ((member.flg & Zlib.Gzip.FlagsMask.FCOMMENT) > 0) {\n", " for (str = [], ci = 0; (c = input[ip++]) > 0;) {\n", " str[ci++] = String.fromCharCode(c);\n", " }\n", "\n", " member.comment = str.join('');\n", " } // fhcrc\n", "\n", "\n", " if ((member.flg & Zlib.Gzip.FlagsMask.FHCRC) > 0) {\n", " member.crc16 = Zlib.CRC32.calc(input, 0, ip) & 0xffff;\n", "\n", " if (member.crc16 !== (input[ip++] | input[ip++] << 8)) {\n", " throw new Error('invalid header crc16');\n", " }\n", " } // isize を事前に取得すると展開後のサイズが分かるため、\n", " // inflate処理のバッファサイズが事前に分かり、高速になる\n", "\n", "\n", " isize = input[input.length - 4] | input[input.length - 3] << 8 | input[input.length - 2] << 16 | input[input.length - 1] << 24; // isize の妥当性チェック\n", " // ハフマン符号では最小 2-bit のため、最大で 1/4 になる\n", " // LZ77 符号では 長さと距離 2-Byte で最大 258-Byte を表現できるため、\n", " // 1/128 になるとする\n", " // ここから入力バッファの残りが isize の 512 倍以上だったら\n", " // サイズ指定のバッファ確保は行わない事とする\n", "\n", " if (input.length - ip -\n", " /* CRC-32 */\n", " 4 -\n", " /* ISIZE */\n", " 4 < isize * 512) {\n", " inflen = isize;\n", " } // compressed block\n", "\n", "\n", " rawinflate = new Zlib.RawInflate(input, {\n", " 'index': ip,\n", " 'bufferSize': inflen\n", " });\n", " member.data = inflated = rawinflate.decompress();\n", " ip = rawinflate.ip; // crc32\n", "\n", " member.crc32 = crc32 = (input[ip++] | input[ip++] << 8 | input[ip++] << 16 | input[ip++] << 24) >>> 0;\n", "\n", " if (Zlib.CRC32.calc(inflated) !== crc32) {\n", " throw new Error('invalid CRC-32 checksum: 0x' + Zlib.CRC32.calc(inflated).toString(16) + ' / 0x' + crc32.toString(16));\n", " } // input size\n", "\n", "\n", " member.isize = isize = (input[ip++] | input[ip++] << 8 | input[ip++] << 16 | input[ip++] << 24) >>> 0;\n", "\n", " if ((inflated.length & 0xffffffff) !== isize) {\n", " throw new Error('invalid input size: ' + (inflated.length & 0xffffffff) + ' / ' + isize);\n", " }\n", "\n", " this.member.push(member);\n", " this.ip = ip;\n", " };\n", " /**\n", " * サブフィールドのデコード\n", " * XXX: 現在は何もせずスキップする\n", " */\n", "\n", "\n", " Zlib.Gunzip.prototype.decodeSubField = function (ip, length) {\n", " return ip + length;\n", " };\n", " /**\n", " * @return {!(Array.|Uint8Array)}\n", " */\n", "\n", "\n", " Zlib.Gunzip.prototype.concatMember = function () {\n", " /** @type {Array.} */\n", " var member = this.member;\n", " /** @type {number} */\n", "\n", " var i;\n", " /** @type {number} */\n", "\n", " var il;\n", " /** @type {number} */\n", "\n", " var p = 0;\n", " /** @type {number} */\n", "\n", " var size = 0;\n", " /** @type {!(Array.|Uint8Array)} */\n", "\n", " var buffer;\n", "\n", " for (i = 0, il = member.length; i < il; ++i) {\n", " size += member[i].data.length;\n", " }\n", "\n", " {\n", " buffer = new Uint8Array(size);\n", "\n", " for (i = 0; i < il; ++i) {\n", " buffer.set(member[i].data, p);\n", " p += member[i].data.length;\n", " }\n", " }\n", "\n", " return buffer;\n", " };\n", " /**\n", " * @constructor\n", " */\n", "\n", "\n", " Zlib.GunzipMember = function () {\n", " /** @type {number} signature first byte. */\n", " this.id1;\n", " /** @type {number} signature second byte. */\n", "\n", " this.id2;\n", " /** @type {number} compression method. */\n", "\n", " this.cm;\n", " /** @type {number} flags. */\n", "\n", " this.flg;\n", " /** @type {Date} modification time. */\n", "\n", " this.mtime;\n", " /** @type {number} extra flags. */\n", "\n", " this.xfl;\n", " /** @type {number} operating system number. */\n", "\n", " this.os;\n", " /** @type {number} CRC-16 value for FHCRC flag. */\n", "\n", " this.crc16;\n", " /** @type {number} extra length. */\n", "\n", " this.xlen;\n", " /** @type {number} CRC-32 value for verification. */\n", "\n", " this.crc32;\n", " /** @type {number} input size modulo 32 value. */\n", "\n", " this.isize;\n", " /** @type {string} filename. */\n", "\n", " this.name;\n", " /** @type {string} comment. */\n", "\n", " this.comment;\n", " /** @type {!(Uint8Array|Array.)} */\n", "\n", " this.data;\n", " };\n", "\n", " Zlib.GunzipMember.prototype.getName = function () {\n", " return this.name;\n", " };\n", "\n", " Zlib.GunzipMember.prototype.getData = function () {\n", " return this.data;\n", " };\n", "\n", " Zlib.GunzipMember.prototype.getMtime = function () {\n", " return this.mtime;\n", " };\n", " /**\n", " * @fileoverview GZIP (RFC1952) 実装.\n", " */\n", "\n", " /**\n", " * @constructor\n", " * @param {!(Array|Uint8Array)} input input buffer.\n", " * @param {Object=} opt_params option parameters.\n", " */\n", "\n", "\n", " Zlib.Gzip = function (input, opt_params) {\n", " /** @type {!(Array.|Uint8Array)} input buffer. */\n", " this.input = input;\n", " /** @type {number} input buffer pointer. */\n", "\n", " this.ip = 0;\n", " /** @type {!(Array.|Uint8Array)} output buffer. */\n", "\n", " this.output;\n", " /** @type {number} output buffer. */\n", "\n", " this.op = 0;\n", " /** @type {!Object} flags option flags. */\n", "\n", " this.flags = {};\n", " /** @type {!string} filename. */\n", "\n", " this.filename;\n", " /** @type {!string} comment. */\n", "\n", " this.comment;\n", " /** @type {!Object} deflate options. */\n", "\n", " this.deflateOptions; // option parameters\n", "\n", " if (opt_params) {\n", " if (opt_params['flags']) {\n", " this.flags = opt_params['flags'];\n", " }\n", "\n", " if (typeof opt_params['filename'] === 'string') {\n", " this.filename = opt_params['filename'];\n", " }\n", "\n", " if (typeof opt_params['comment'] === 'string') {\n", " this.comment = opt_params['comment'];\n", " }\n", "\n", " if (opt_params['deflateOptions']) {\n", " this.deflateOptions = opt_params['deflateOptions'];\n", " }\n", " }\n", "\n", " if (!this.deflateOptions) {\n", " this.deflateOptions = {};\n", " }\n", " };\n", " /**\n", " * @type {number}\n", " * @const\n", " */\n", "\n", "\n", " Zlib.Gzip.DefaultBufferSize = 0x8000;\n", " /**\n", " * encode gzip members.\n", " * @return {!(Array|Uint8Array)} gzip binary array.\n", " */\n", "\n", " Zlib.Gzip.prototype.compress = function () {\n", " /** @type {number} flags. */\n", " var flg;\n", " /** @type {number} modification time. */\n", "\n", " var mtime;\n", " /** @type {number} CRC-16 value for FHCRC flag. */\n", "\n", " var crc16;\n", " /** @type {number} CRC-32 value for verification. */\n", "\n", " var crc32;\n", " /** @type {!Zlib.RawDeflate} raw deflate object. */\n", "\n", " var rawdeflate;\n", " /** @type {number} character code */\n", "\n", " var c;\n", " /** @type {number} loop counter. */\n", "\n", " var i;\n", " /** @type {number} loop limiter. */\n", "\n", " var il;\n", " /** @type {!(Array|Uint8Array)} output buffer. */\n", "\n", " var output = new (Uint8Array )(Zlib.Gzip.DefaultBufferSize);\n", " /** @type {number} output buffer pointer. */\n", "\n", " var op = 0;\n", " var input = this.input;\n", " var ip = this.ip;\n", " var filename = this.filename;\n", " var comment = this.comment; // check signature\n", "\n", " output[op++] = 0x1f;\n", " output[op++] = 0x8b; // check compression method\n", "\n", " output[op++] = 8;\n", " /* XXX: use Zlib const */\n", " // flags\n", "\n", " flg = 0;\n", " if (this.flags['fname']) flg |= Zlib.Gzip.FlagsMask.FNAME;\n", " if (this.flags['fcomment']) flg |= Zlib.Gzip.FlagsMask.FCOMMENT;\n", " if (this.flags['fhcrc']) flg |= Zlib.Gzip.FlagsMask.FHCRC; // XXX: FTEXT\n", " // XXX: FEXTRA\n", "\n", " output[op++] = flg; // modification time\n", "\n", " mtime = (Date.now ? Date.now() : +new Date()) / 1000 | 0;\n", " output[op++] = mtime & 0xff;\n", " output[op++] = mtime >>> 8 & 0xff;\n", " output[op++] = mtime >>> 16 & 0xff;\n", " output[op++] = mtime >>> 24 & 0xff; // extra flags\n", "\n", " output[op++] = 0; // operating system\n", "\n", " output[op++] = Zlib.Gzip.OperatingSystem.UNKNOWN; // extra\n", "\n", " /* NOP */\n", " // fname\n", "\n", " if (this.flags['fname'] !== void 0) {\n", " for (i = 0, il = filename.length; i < il; ++i) {\n", " c = filename.charCodeAt(i);\n", "\n", " if (c > 0xff) {\n", " output[op++] = c >>> 8 & 0xff;\n", " }\n", "\n", " output[op++] = c & 0xff;\n", " }\n", "\n", " output[op++] = 0; // null termination\n", " } // fcomment\n", "\n", "\n", " if (this.flags['comment']) {\n", " for (i = 0, il = comment.length; i < il; ++i) {\n", " c = comment.charCodeAt(i);\n", "\n", " if (c > 0xff) {\n", " output[op++] = c >>> 8 & 0xff;\n", " }\n", "\n", " output[op++] = c & 0xff;\n", " }\n", "\n", " output[op++] = 0; // null termination\n", " } // fhcrc\n", "\n", "\n", " if (this.flags['fhcrc']) {\n", " crc16 = Zlib.CRC32.calc(output, 0, op) & 0xffff;\n", " output[op++] = crc16 & 0xff;\n", " output[op++] = crc16 >>> 8 & 0xff;\n", " } // add compress option\n", "\n", "\n", " this.deflateOptions['outputBuffer'] = output;\n", " this.deflateOptions['outputIndex'] = op; // compress\n", "\n", " rawdeflate = new Zlib.RawDeflate(input, this.deflateOptions);\n", " output = rawdeflate.compress();\n", " op = rawdeflate.op; // expand buffer\n", "\n", " {\n", " if (op + 8 > output.buffer.byteLength) {\n", " this.output = new Uint8Array(op + 8);\n", " this.output.set(new Uint8Array(output.buffer));\n", " output = this.output;\n", " } else {\n", " output = new Uint8Array(output.buffer);\n", " }\n", " } // crc32\n", "\n", "\n", " crc32 = Zlib.CRC32.calc(input);\n", " output[op++] = crc32 & 0xff;\n", " output[op++] = crc32 >>> 8 & 0xff;\n", " output[op++] = crc32 >>> 16 & 0xff;\n", " output[op++] = crc32 >>> 24 & 0xff; // input size\n", "\n", " il = input.length;\n", " output[op++] = il & 0xff;\n", " output[op++] = il >>> 8 & 0xff;\n", " output[op++] = il >>> 16 & 0xff;\n", " output[op++] = il >>> 24 & 0xff;\n", " this.ip = ip;\n", "\n", " if (op < output.length) {\n", " this.output = output = output.subarray(0, op);\n", " }\n", "\n", " return output;\n", " };\n", " /** @enum {number} */\n", "\n", "\n", " Zlib.Gzip.OperatingSystem = {\n", " FAT: 0,\n", " AMIGA: 1,\n", " VMS: 2,\n", " UNIX: 3,\n", " VM_CMS: 4,\n", " ATARI_TOS: 5,\n", " HPFS: 6,\n", " MACINTOSH: 7,\n", " Z_SYSTEM: 8,\n", " CP_M: 9,\n", " TOPS_20: 10,\n", " NTFS: 11,\n", " QDOS: 12,\n", " ACORN_RISCOS: 13,\n", " UNKNOWN: 255\n", " };\n", " /** @enum {number} */\n", "\n", " Zlib.Gzip.FlagsMask = {\n", " FTEXT: 0x01,\n", " FHCRC: 0x02,\n", " FEXTRA: 0x04,\n", " FNAME: 0x08,\n", " FCOMMENT: 0x10\n", " };\n", " /**\n", " * @fileoverview Heap Sort 実装. ハフマン符号化で使用する.\n", " */\n", "\n", " /**\n", " * カスタムハフマン符号で使用するヒープ実装\n", " * @param {number} length ヒープサイズ.\n", " * @constructor\n", " */\n", "\n", " Zlib.Heap = function (length) {\n", " this.buffer = new (Uint16Array )(length * 2);\n", " this.length = 0;\n", " };\n", " /**\n", " * 親ノードの index 取得\n", " * @param {number} index 子ノードの index.\n", " * @return {number} 親ノードの index.\n", " *\n", " */\n", "\n", "\n", " Zlib.Heap.prototype.getParent = function (index) {\n", " return ((index - 2) / 4 | 0) * 2;\n", " };\n", " /**\n", " * 子ノードの index 取得\n", " * @param {number} index 親ノードの index.\n", " * @return {number} 子ノードの index.\n", " */\n", "\n", "\n", " Zlib.Heap.prototype.getChild = function (index) {\n", " return 2 * index + 2;\n", " };\n", " /**\n", " * Heap に値を追加する\n", " * @param {number} index キー index.\n", " * @param {number} value 値.\n", " * @return {number} 現在のヒープ長.\n", " */\n", "\n", "\n", " Zlib.Heap.prototype.push = function (index, value) {\n", " var current,\n", " parent,\n", " heap = this.buffer,\n", " swap;\n", " current = this.length;\n", " heap[this.length++] = value;\n", " heap[this.length++] = index; // ルートノードにたどり着くまで入れ替えを試みる\n", "\n", " while (current > 0) {\n", " parent = this.getParent(current); // 親ノードと比較して親の方が小さければ入れ替える\n", "\n", " if (heap[current] > heap[parent]) {\n", " swap = heap[current];\n", " heap[current] = heap[parent];\n", " heap[parent] = swap;\n", " swap = heap[current + 1];\n", " heap[current + 1] = heap[parent + 1];\n", " heap[parent + 1] = swap;\n", " current = parent; // 入れ替えが必要なくなったらそこで抜ける\n", " } else {\n", " break;\n", " }\n", " }\n", "\n", " return this.length;\n", " };\n", " /**\n", " * Heapから一番大きい値を返す\n", " * @return {{index: number, value: number, length: number}} {index: キーindex,\n", " * value: 値, length: ヒープ長} の Object.\n", " */\n", "\n", "\n", " Zlib.Heap.prototype.pop = function () {\n", " var index,\n", " value,\n", " heap = this.buffer,\n", " swap,\n", " current,\n", " parent;\n", " value = heap[0];\n", " index = heap[1]; // 後ろから値を取る\n", "\n", " this.length -= 2;\n", " heap[0] = heap[this.length];\n", " heap[1] = heap[this.length + 1];\n", " parent = 0; // ルートノードから下がっていく\n", "\n", " while (true) {\n", " current = this.getChild(parent); // 範囲チェック\n", "\n", " if (current >= this.length) {\n", " break;\n", " } // 隣のノードと比較して、隣の方が値が大きければ隣を現在ノードとして選択\n", "\n", "\n", " if (current + 2 < this.length && heap[current + 2] > heap[current]) {\n", " current += 2;\n", " } // 親ノードと比較して親の方が小さい場合は入れ替える\n", "\n", "\n", " if (heap[current] > heap[parent]) {\n", " swap = heap[parent];\n", " heap[parent] = heap[current];\n", " heap[current] = swap;\n", " swap = heap[parent + 1];\n", " heap[parent + 1] = heap[current + 1];\n", " heap[current + 1] = swap;\n", " } else {\n", " break;\n", " }\n", "\n", " parent = current;\n", " }\n", "\n", " return {\n", " index: index,\n", " value: value,\n", " length: this.length\n", " };\n", " };\n", " /* vim:set expandtab ts=2 sw=2 tw=80: */\n", "\n", " /**\n", " * @fileoverview Deflate (RFC1951) 符号化アルゴリズム実装.\n", " */\n", "\n", " /**\n", " * Raw Deflate 実装\n", " *\n", " * @constructor\n", " * @param {!(Array.|Uint8Array)} input 符号化する対象のバッファ.\n", " * @param {Object=} opt_params option parameters.\n", " *\n", " * typed array が使用可能なとき、outputBuffer が Array は自動的に Uint8Array に\n", " * 変換されます.\n", " * 別のオブジェクトになるため出力バッファを参照している変数などは\n", " * 更新する必要があります.\n", " */\n", "\n", "\n", " Zlib.RawDeflate = function (input, opt_params) {\n", " /** @type {Zlib.RawDeflate.CompressionType} */\n", " this.compressionType = Zlib.RawDeflate.CompressionType.DYNAMIC;\n", " /** @type {number} */\n", "\n", " this.lazy = 0;\n", " /** @type {!(Array.|Uint32Array)} */\n", "\n", " this.freqsLitLen;\n", " /** @type {!(Array.|Uint32Array)} */\n", "\n", " this.freqsDist;\n", " /** @type {!(Array.|Uint8Array)} */\n", "\n", " this.input = input instanceof Array ? new Uint8Array(input) : input;\n", " /** @type {!(Array.|Uint8Array)} output output buffer. */\n", "\n", " this.output;\n", " /** @type {number} pos output buffer position. */\n", "\n", " this.op = 0; // option parameters\n", "\n", " if (opt_params) {\n", " if (opt_params['lazy']) {\n", " this.lazy = opt_params['lazy'];\n", " }\n", "\n", " if (typeof opt_params['compressionType'] === 'number') {\n", " this.compressionType = opt_params['compressionType'];\n", " }\n", "\n", " if (opt_params['outputBuffer']) {\n", " this.output = opt_params['outputBuffer'] instanceof Array ? new Uint8Array(opt_params['outputBuffer']) : opt_params['outputBuffer'];\n", " }\n", "\n", " if (typeof opt_params['outputIndex'] === 'number') {\n", " this.op = opt_params['outputIndex'];\n", " }\n", " }\n", "\n", " if (!this.output) {\n", " this.output = new (Uint8Array )(0x8000);\n", " }\n", " };\n", " /**\n", " * @enum {number}\n", " */\n", "\n", "\n", " Zlib.RawDeflate.CompressionType = {\n", " NONE: 0,\n", " FIXED: 1,\n", " DYNAMIC: 2,\n", " RESERVED: 3\n", " };\n", " /**\n", " * LZ77 の最小マッチ長\n", " * @const\n", " * @type {number}\n", " */\n", "\n", " Zlib.RawDeflate.Lz77MinLength = 3;\n", " /**\n", " * LZ77 の最大マッチ長\n", " * @const\n", " * @type {number}\n", " */\n", "\n", " Zlib.RawDeflate.Lz77MaxLength = 258;\n", " /**\n", " * LZ77 のウィンドウサイズ\n", " * @const\n", " * @type {number}\n", " */\n", "\n", " Zlib.RawDeflate.WindowSize = 0x8000;\n", " /**\n", " * 最長の符号長\n", " * @const\n", " * @type {number}\n", " */\n", "\n", " Zlib.RawDeflate.MaxCodeLength = 16;\n", " /**\n", " * ハフマン符号の最大数値\n", " * @const\n", " * @type {number}\n", " */\n", "\n", " Zlib.RawDeflate.HUFMAX = 286;\n", " /**\n", " * 固定ハフマン符号の符号化テーブル\n", " * @const\n", " * @type {Array.>}\n", " */\n", "\n", " Zlib.RawDeflate.FixedHuffmanTable = function () {\n", " var table = [],\n", " i;\n", "\n", " for (i = 0; i < 288; i++) {\n", " switch (true) {\n", " case i <= 143:\n", " table.push([i + 0x030, 8]);\n", " break;\n", "\n", " case i <= 255:\n", " table.push([i - 144 + 0x190, 9]);\n", " break;\n", "\n", " case i <= 279:\n", " table.push([i - 256 + 0x000, 7]);\n", " break;\n", "\n", " case i <= 287:\n", " table.push([i - 280 + 0x0C0, 8]);\n", " break;\n", "\n", " default:\n", " throw 'invalid literal: ' + i;\n", " }\n", " }\n", "\n", " return table;\n", " }();\n", " /**\n", " * DEFLATE ブロックの作成\n", " * @return {!(Array.|Uint8Array)} 圧縮済み byte array.\n", " */\n", "\n", "\n", " Zlib.RawDeflate.prototype.compress = function () {\n", " /** @type {!(Array.|Uint8Array)} */\n", " var blockArray;\n", " /** @type {number} */\n", "\n", " var position;\n", " /** @type {number} */\n", "\n", " var length;\n", " var input = this.input; // compression\n", "\n", " switch (this.compressionType) {\n", " case Zlib.RawDeflate.CompressionType.NONE:\n", " // each 65535-Byte (length header: 16-bit)\n", " for (position = 0, length = input.length; position < length;) {\n", " blockArray = input.subarray(position, position + 0xffff) ;\n", " position += blockArray.length;\n", " this.makeNocompressBlock(blockArray, position === length);\n", " }\n", "\n", " break;\n", "\n", " case Zlib.RawDeflate.CompressionType.FIXED:\n", " this.output = this.makeFixedHuffmanBlock(input, true);\n", " this.op = this.output.length;\n", " break;\n", "\n", " case Zlib.RawDeflate.CompressionType.DYNAMIC:\n", " this.output = this.makeDynamicHuffmanBlock(input, true);\n", " this.op = this.output.length;\n", " break;\n", "\n", " default:\n", " throw 'invalid compression type';\n", " }\n", "\n", " return this.output;\n", " };\n", " /**\n", " * 非圧縮ブロックの作成\n", " * @param {!(Array.|Uint8Array)} blockArray ブロックデータ byte array.\n", " * @param {!boolean} isFinalBlock 最後のブロックならばtrue.\n", " * @return {!(Array.|Uint8Array)} 非圧縮ブロック byte array.\n", " */\n", "\n", "\n", " Zlib.RawDeflate.prototype.makeNocompressBlock = function (blockArray, isFinalBlock) {\n", " /** @type {number} */\n", " var bfinal;\n", " /** @type {Zlib.RawDeflate.CompressionType} */\n", "\n", " var btype;\n", " /** @type {number} */\n", "\n", " var len;\n", " /** @type {number} */\n", "\n", " var nlen;\n", " var output = this.output;\n", " var op = this.op; // expand buffer\n", "\n", " {\n", " output = new Uint8Array(this.output.buffer);\n", "\n", " while (output.length <= op + blockArray.length + 5) {\n", " output = new Uint8Array(output.length << 1);\n", " }\n", "\n", " output.set(this.output);\n", " } // header\n", "\n", "\n", " bfinal = isFinalBlock ? 1 : 0;\n", " btype = Zlib.RawDeflate.CompressionType.NONE;\n", " output[op++] = bfinal | btype << 1; // length\n", "\n", " len = blockArray.length;\n", " nlen = ~len + 0x10000 & 0xffff;\n", " output[op++] = len & 0xff;\n", " output[op++] = len >>> 8 & 0xff;\n", " output[op++] = nlen & 0xff;\n", " output[op++] = nlen >>> 8 & 0xff; // copy buffer\n", "\n", " {\n", " output.set(blockArray, op);\n", " op += blockArray.length;\n", " output = output.subarray(0, op);\n", " }\n", "\n", " this.op = op;\n", " this.output = output;\n", " return output;\n", " };\n", " /**\n", " * 固定ハフマンブロックの作成\n", " * @param {!(Array.|Uint8Array)} blockArray ブロックデータ byte array.\n", " * @param {!boolean} isFinalBlock 最後のブロックならばtrue.\n", " * @return {!(Array.|Uint8Array)} 固定ハフマン符号化ブロック byte array.\n", " */\n", "\n", "\n", " Zlib.RawDeflate.prototype.makeFixedHuffmanBlock = function (blockArray, isFinalBlock) {\n", " /** @type {Zlib.BitStream} */\n", " var stream = new Zlib.BitStream(new Uint8Array(this.output.buffer) , this.op);\n", " /** @type {number} */\n", "\n", " var bfinal;\n", " /** @type {Zlib.RawDeflate.CompressionType} */\n", "\n", " var btype;\n", " /** @type {!(Array.|Uint16Array)} */\n", "\n", " var data; // header\n", "\n", " bfinal = isFinalBlock ? 1 : 0;\n", " btype = Zlib.RawDeflate.CompressionType.FIXED;\n", " stream.writeBits(bfinal, 1, true);\n", " stream.writeBits(btype, 2, true);\n", " data = this.lz77(blockArray);\n", " this.fixedHuffman(data, stream);\n", " return stream.finish();\n", " };\n", " /**\n", " * 動的ハフマンブロックの作成\n", " * @param {!(Array.|Uint8Array)} blockArray ブロックデータ byte array.\n", " * @param {!boolean} isFinalBlock 最後のブロックならばtrue.\n", " * @return {!(Array.|Uint8Array)} 動的ハフマン符号ブロック byte array.\n", " */\n", "\n", "\n", " Zlib.RawDeflate.prototype.makeDynamicHuffmanBlock = function (blockArray, isFinalBlock) {\n", " /** @type {Zlib.BitStream} */\n", " var stream = new Zlib.BitStream(new Uint8Array(this.output.buffer) , this.op);\n", " /** @type {number} */\n", "\n", " var bfinal;\n", " /** @type {Zlib.RawDeflate.CompressionType} */\n", "\n", " var btype;\n", " /** @type {!(Array.|Uint16Array)} */\n", "\n", " var data;\n", " /** @type {number} */\n", "\n", " var hlit;\n", " /** @type {number} */\n", "\n", " var hdist;\n", " /** @type {number} */\n", "\n", " var hclen;\n", " /** @const @type {Array.} */\n", "\n", " var hclenOrder = [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15];\n", " /** @type {!(Array.|Uint8Array)} */\n", "\n", " var litLenLengths;\n", " /** @type {!(Array.|Uint16Array)} */\n", "\n", " var litLenCodes;\n", " /** @type {!(Array.|Uint8Array)} */\n", "\n", " var distLengths;\n", " /** @type {!(Array.|Uint16Array)} */\n", "\n", " var distCodes;\n", " /** @type {{\n", " * codes: !(Array.|Uint32Array),\n", " * freqs: !(Array.|Uint8Array)\n", " * }} */\n", "\n", " var treeSymbols;\n", " /** @type {!(Array.|Uint8Array)} */\n", "\n", " var treeLengths;\n", " /** @type {Array} */\n", "\n", " var transLengths = new Array(19);\n", " /** @type {!(Array.|Uint16Array)} */\n", "\n", " var treeCodes;\n", " /** @type {number} */\n", "\n", " var code;\n", " /** @type {number} */\n", "\n", " var bitlen;\n", " /** @type {number} */\n", "\n", " var i;\n", " /** @type {number} */\n", "\n", " var il; // header\n", "\n", " bfinal = isFinalBlock ? 1 : 0;\n", " btype = Zlib.RawDeflate.CompressionType.DYNAMIC;\n", " stream.writeBits(bfinal, 1, true);\n", " stream.writeBits(btype, 2, true);\n", " data = this.lz77(blockArray); // リテラル・長さ, 距離のハフマン符号と符号長の算出\n", "\n", " litLenLengths = this.getLengths_(this.freqsLitLen, 15);\n", " litLenCodes = this.getCodesFromLengths_(litLenLengths);\n", " distLengths = this.getLengths_(this.freqsDist, 7);\n", " distCodes = this.getCodesFromLengths_(distLengths); // HLIT, HDIST の決定\n", "\n", " for (hlit = 286; hlit > 257 && litLenLengths[hlit - 1] === 0; hlit--) {}\n", "\n", " for (hdist = 30; hdist > 1 && distLengths[hdist - 1] === 0; hdist--) {} // HCLEN\n", "\n", "\n", " treeSymbols = this.getTreeSymbols_(hlit, litLenLengths, hdist, distLengths);\n", " treeLengths = this.getLengths_(treeSymbols.freqs, 7);\n", "\n", " for (i = 0; i < 19; i++) {\n", " transLengths[i] = treeLengths[hclenOrder[i]];\n", " }\n", "\n", " for (hclen = 19; hclen > 4 && transLengths[hclen - 1] === 0; hclen--) {}\n", "\n", " treeCodes = this.getCodesFromLengths_(treeLengths); // 出力\n", "\n", " stream.writeBits(hlit - 257, 5, true);\n", " stream.writeBits(hdist - 1, 5, true);\n", " stream.writeBits(hclen - 4, 4, true);\n", "\n", " for (i = 0; i < hclen; i++) {\n", " stream.writeBits(transLengths[i], 3, true);\n", " } // ツリーの出力\n", "\n", "\n", " for (i = 0, il = treeSymbols.codes.length; i < il; i++) {\n", " code = treeSymbols.codes[i];\n", " stream.writeBits(treeCodes[code], treeLengths[code], true); // extra bits\n", "\n", " if (code >= 16) {\n", " i++;\n", "\n", " switch (code) {\n", " case 16:\n", " bitlen = 2;\n", " break;\n", "\n", " case 17:\n", " bitlen = 3;\n", " break;\n", "\n", " case 18:\n", " bitlen = 7;\n", " break;\n", "\n", " default:\n", " throw 'invalid code: ' + code;\n", " }\n", "\n", " stream.writeBits(treeSymbols.codes[i], bitlen, true);\n", " }\n", " }\n", "\n", " this.dynamicHuffman(data, [litLenCodes, litLenLengths], [distCodes, distLengths], stream);\n", " return stream.finish();\n", " };\n", " /**\n", " * 動的ハフマン符号化(カスタムハフマンテーブル)\n", " * @param {!(Array.|Uint16Array)} dataArray LZ77 符号化済み byte array.\n", " * @param {!Zlib.BitStream} stream 書き込み用ビットストリーム.\n", " * @return {!Zlib.BitStream} ハフマン符号化済みビットストリームオブジェクト.\n", " */\n", "\n", "\n", " Zlib.RawDeflate.prototype.dynamicHuffman = function (dataArray, litLen, dist, stream) {\n", " /** @type {number} */\n", " var index;\n", " /** @type {number} */\n", "\n", " var length;\n", " /** @type {number} */\n", "\n", " var literal;\n", " /** @type {number} */\n", "\n", " var code;\n", " /** @type {number} */\n", "\n", " var litLenCodes;\n", " /** @type {number} */\n", "\n", " var litLenLengths;\n", " /** @type {number} */\n", "\n", " var distCodes;\n", " /** @type {number} */\n", "\n", " var distLengths;\n", " litLenCodes = litLen[0];\n", " litLenLengths = litLen[1];\n", " distCodes = dist[0];\n", " distLengths = dist[1]; // 符号を BitStream に書き込んでいく\n", "\n", " for (index = 0, length = dataArray.length; index < length; ++index) {\n", " literal = dataArray[index]; // literal or length\n", "\n", " stream.writeBits(litLenCodes[literal], litLenLengths[literal], true); // 長さ・距離符号\n", "\n", " if (literal > 256) {\n", " // length extra\n", " stream.writeBits(dataArray[++index], dataArray[++index], true); // distance\n", "\n", " code = dataArray[++index];\n", " stream.writeBits(distCodes[code], distLengths[code], true); // distance extra\n", "\n", " stream.writeBits(dataArray[++index], dataArray[++index], true); // 終端\n", " } else if (literal === 256) {\n", " break;\n", " }\n", " }\n", "\n", " return stream;\n", " };\n", " /**\n", " * 固定ハフマン符号化\n", " * @param {!(Array.|Uint16Array)} dataArray LZ77 符号化済み byte array.\n", " * @param {!Zlib.BitStream} stream 書き込み用ビットストリーム.\n", " * @return {!Zlib.BitStream} ハフマン符号化済みビットストリームオブジェクト.\n", " */\n", "\n", "\n", " Zlib.RawDeflate.prototype.fixedHuffman = function (dataArray, stream) {\n", " /** @type {number} */\n", " var index;\n", " /** @type {number} */\n", "\n", " var length;\n", " /** @type {number} */\n", "\n", " var literal; // 符号を BitStream に書き込んでいく\n", "\n", " for (index = 0, length = dataArray.length; index < length; index++) {\n", " literal = dataArray[index]; // 符号の書き込み\n", "\n", " Zlib.BitStream.prototype.writeBits.apply(stream, Zlib.RawDeflate.FixedHuffmanTable[literal]); // 長さ・距離符号\n", "\n", " if (literal > 0x100) {\n", " // length extra\n", " stream.writeBits(dataArray[++index], dataArray[++index], true); // distance\n", "\n", " stream.writeBits(dataArray[++index], 5); // distance extra\n", "\n", " stream.writeBits(dataArray[++index], dataArray[++index], true); // 終端\n", " } else if (literal === 0x100) {\n", " break;\n", " }\n", " }\n", "\n", " return stream;\n", " };\n", " /**\n", " * マッチ情報\n", " * @param {!number} length マッチした長さ.\n", " * @param {!number} backwardDistance マッチ位置との距離.\n", " * @constructor\n", " */\n", "\n", "\n", " Zlib.RawDeflate.Lz77Match = function (length, backwardDistance) {\n", " /** @type {number} match length. */\n", " this.length = length;\n", " /** @type {number} backward distance. */\n", "\n", " this.backwardDistance = backwardDistance;\n", " };\n", " /**\n", " * 長さ符号テーブル.\n", " * [コード, 拡張ビット, 拡張ビット長] の配列となっている.\n", " * @const\n", " * @type {!(Array.|Uint32Array)}\n", " */\n", "\n", "\n", " Zlib.RawDeflate.Lz77Match.LengthCodeTable = function (table) {\n", " return new Uint32Array(table) ;\n", " }(function () {\n", " /** @type {!Array} */\n", " var table = [];\n", " /** @type {number} */\n", "\n", " var i;\n", " /** @type {!Array.} */\n", "\n", " var c;\n", "\n", " for (i = 3; i <= 258; i++) {\n", " c = code(i);\n", " table[i] = c[2] << 24 | c[1] << 16 | c[0];\n", " }\n", " /**\n", " * @param {number} length lz77 length.\n", " * @return {!Array.} lz77 codes.\n", " */\n", "\n", "\n", " function code(length) {\n", " switch (true) {\n", " case length === 3:\n", " return [257, length - 3, 0];\n", "\n", " case length === 4:\n", " return [258, length - 4, 0];\n", "\n", " case length === 5:\n", " return [259, length - 5, 0];\n", "\n", " case length === 6:\n", " return [260, length - 6, 0];\n", "\n", " case length === 7:\n", " return [261, length - 7, 0];\n", "\n", " case length === 8:\n", " return [262, length - 8, 0];\n", "\n", " case length === 9:\n", " return [263, length - 9, 0];\n", "\n", " case length === 10:\n", " return [264, length - 10, 0];\n", "\n", " case length <= 12:\n", " return [265, length - 11, 1];\n", "\n", " case length <= 14:\n", " return [266, length - 13, 1];\n", "\n", " case length <= 16:\n", " return [267, length - 15, 1];\n", "\n", " case length <= 18:\n", " return [268, length - 17, 1];\n", "\n", " case length <= 22:\n", " return [269, length - 19, 2];\n", "\n", " case length <= 26:\n", " return [270, length - 23, 2];\n", "\n", " case length <= 30:\n", " return [271, length - 27, 2];\n", "\n", " case length <= 34:\n", " return [272, length - 31, 2];\n", "\n", " case length <= 42:\n", " return [273, length - 35, 3];\n", "\n", " case length <= 50:\n", " return [274, length - 43, 3];\n", "\n", " case length <= 58:\n", " return [275, length - 51, 3];\n", "\n", " case length <= 66:\n", " return [276, length - 59, 3];\n", "\n", " case length <= 82:\n", " return [277, length - 67, 4];\n", "\n", " case length <= 98:\n", " return [278, length - 83, 4];\n", "\n", " case length <= 114:\n", " return [279, length - 99, 4];\n", "\n", " case length <= 130:\n", " return [280, length - 115, 4];\n", "\n", " case length <= 162:\n", " return [281, length - 131, 5];\n", "\n", " case length <= 194:\n", " return [282, length - 163, 5];\n", "\n", " case length <= 226:\n", " return [283, length - 195, 5];\n", "\n", " case length <= 257:\n", " return [284, length - 227, 5];\n", "\n", " case length === 258:\n", " return [285, length - 258, 0];\n", "\n", " default:\n", " throw 'invalid length: ' + length;\n", " }\n", " }\n", "\n", " return table;\n", " }());\n", " /**\n", " * 距離符号テーブル\n", " * @param {!number} dist 距離.\n", " * @return {!Array.} コード、拡張ビット、拡張ビット長の配列.\n", " * @private\n", " */\n", "\n", "\n", " Zlib.RawDeflate.Lz77Match.prototype.getDistanceCode_ = function (dist) {\n", " /** @type {!Array.} distance code table. */\n", " var r;\n", "\n", " switch (true) {\n", " case dist === 1:\n", " r = [0, dist - 1, 0];\n", " break;\n", "\n", " case dist === 2:\n", " r = [1, dist - 2, 0];\n", " break;\n", "\n", " case dist === 3:\n", " r = [2, dist - 3, 0];\n", " break;\n", "\n", " case dist === 4:\n", " r = [3, dist - 4, 0];\n", " break;\n", "\n", " case dist <= 6:\n", " r = [4, dist - 5, 1];\n", " break;\n", "\n", " case dist <= 8:\n", " r = [5, dist - 7, 1];\n", " break;\n", "\n", " case dist <= 12:\n", " r = [6, dist - 9, 2];\n", " break;\n", "\n", " case dist <= 16:\n", " r = [7, dist - 13, 2];\n", " break;\n", "\n", " case dist <= 24:\n", " r = [8, dist - 17, 3];\n", " break;\n", "\n", " case dist <= 32:\n", " r = [9, dist - 25, 3];\n", " break;\n", "\n", " case dist <= 48:\n", " r = [10, dist - 33, 4];\n", " break;\n", "\n", " case dist <= 64:\n", " r = [11, dist - 49, 4];\n", " break;\n", "\n", " case dist <= 96:\n", " r = [12, dist - 65, 5];\n", " break;\n", "\n", " case dist <= 128:\n", " r = [13, dist - 97, 5];\n", " break;\n", "\n", " case dist <= 192:\n", " r = [14, dist - 129, 6];\n", " break;\n", "\n", " case dist <= 256:\n", " r = [15, dist - 193, 6];\n", " break;\n", "\n", " case dist <= 384:\n", " r = [16, dist - 257, 7];\n", " break;\n", "\n", " case dist <= 512:\n", " r = [17, dist - 385, 7];\n", " break;\n", "\n", " case dist <= 768:\n", " r = [18, dist - 513, 8];\n", " break;\n", "\n", " case dist <= 1024:\n", " r = [19, dist - 769, 8];\n", " break;\n", "\n", " case dist <= 1536:\n", " r = [20, dist - 1025, 9];\n", " break;\n", "\n", " case dist <= 2048:\n", " r = [21, dist - 1537, 9];\n", " break;\n", "\n", " case dist <= 3072:\n", " r = [22, dist - 2049, 10];\n", " break;\n", "\n", " case dist <= 4096:\n", " r = [23, dist - 3073, 10];\n", " break;\n", "\n", " case dist <= 6144:\n", " r = [24, dist - 4097, 11];\n", " break;\n", "\n", " case dist <= 8192:\n", " r = [25, dist - 6145, 11];\n", " break;\n", "\n", " case dist <= 12288:\n", " r = [26, dist - 8193, 12];\n", " break;\n", "\n", " case dist <= 16384:\n", " r = [27, dist - 12289, 12];\n", " break;\n", "\n", " case dist <= 24576:\n", " r = [28, dist - 16385, 13];\n", " break;\n", "\n", " case dist <= 32768:\n", " r = [29, dist - 24577, 13];\n", " break;\n", "\n", " default:\n", " throw 'invalid distance';\n", " }\n", "\n", " return r;\n", " };\n", " /**\n", " * マッチ情報を LZ77 符号化配列で返す.\n", " * なお、ここでは以下の内部仕様で符号化している\n", " * [ CODE, EXTRA-BIT-LEN, EXTRA, CODE, EXTRA-BIT-LEN, EXTRA ]\n", " * @return {!Array.} LZ77 符号化 byte array.\n", " */\n", "\n", "\n", " Zlib.RawDeflate.Lz77Match.prototype.toLz77Array = function () {\n", " /** @type {number} */\n", " var length = this.length;\n", " /** @type {number} */\n", "\n", " var dist = this.backwardDistance;\n", " /** @type {Array} */\n", "\n", " var codeArray = [];\n", " /** @type {number} */\n", "\n", " var pos = 0;\n", " /** @type {!Array.} */\n", "\n", " var code; // length\n", "\n", " code = Zlib.RawDeflate.Lz77Match.LengthCodeTable[length];\n", " codeArray[pos++] = code & 0xffff;\n", " codeArray[pos++] = code >> 16 & 0xff;\n", " codeArray[pos++] = code >> 24; // distance\n", "\n", " code = this.getDistanceCode_(dist);\n", " codeArray[pos++] = code[0];\n", " codeArray[pos++] = code[1];\n", " codeArray[pos++] = code[2];\n", " return codeArray;\n", " };\n", " /**\n", " * LZ77 実装\n", " * @param {!(Array.|Uint8Array)} dataArray LZ77 符号化するバイト配列.\n", " * @return {!(Array.|Uint16Array)} LZ77 符号化した配列.\n", " */\n", "\n", "\n", " Zlib.RawDeflate.prototype.lz77 = function (dataArray) {\n", " /** @type {number} input position */\n", " var position;\n", " /** @type {number} input length */\n", "\n", " var length;\n", " /** @type {number} loop counter */\n", "\n", " var i;\n", " /** @type {number} loop limiter */\n", "\n", " var il;\n", " /** @type {number} chained-hash-table key */\n", "\n", " var matchKey;\n", " /** @type {Object.>} chained-hash-table */\n", "\n", " var table = {};\n", " /** @const @type {number} */\n", "\n", " var windowSize = Zlib.RawDeflate.WindowSize;\n", " /** @type {Array.} match list */\n", "\n", " var matchList;\n", " /** @type {Zlib.RawDeflate.Lz77Match} longest match */\n", "\n", " var longestMatch;\n", " /** @type {Zlib.RawDeflate.Lz77Match} previous longest match */\n", "\n", " var prevMatch;\n", " /** @type {!(Array.|Uint16Array)} lz77 buffer */\n", "\n", " var lz77buf = new Uint16Array(dataArray.length * 2) ;\n", " /** @type {number} lz77 output buffer pointer */\n", "\n", " var pos = 0;\n", " /** @type {number} lz77 skip length */\n", "\n", " var skipLength = 0;\n", " /** @type {!(Array.|Uint32Array)} */\n", "\n", " var freqsLitLen = new (Uint32Array )(286);\n", " /** @type {!(Array.|Uint32Array)} */\n", "\n", " var freqsDist = new (Uint32Array )(30);\n", " /** @type {number} */\n", "\n", " var lazy = this.lazy;\n", " /** @type {*} temporary variable */\n", "\n", " var tmp; // 初期化\n", "\n", " freqsLitLen[256] = 1; // EOB の最低出現回数は 1\n", "\n", " /**\n", " * マッチデータの書き込み\n", " * @param {Zlib.RawDeflate.Lz77Match} match LZ77 Match data.\n", " * @param {!number} offset スキップ開始位置(相対指定).\n", " * @private\n", " */\n", "\n", " function writeMatch(match, offset) {\n", " /** @type {Array.} */\n", " var lz77Array = match.toLz77Array();\n", " /** @type {number} */\n", "\n", " var i;\n", " /** @type {number} */\n", "\n", " var il;\n", "\n", " for (i = 0, il = lz77Array.length; i < il; ++i) {\n", " lz77buf[pos++] = lz77Array[i];\n", " }\n", "\n", " freqsLitLen[lz77Array[0]]++;\n", " freqsDist[lz77Array[3]]++;\n", " skipLength = match.length + offset - 1;\n", " prevMatch = null;\n", " } // LZ77 符号化\n", "\n", "\n", " for (position = 0, length = dataArray.length; position < length; ++position) {\n", " // ハッシュキーの作成\n", " for (matchKey = 0, i = 0, il = Zlib.RawDeflate.Lz77MinLength; i < il; ++i) {\n", " if (position + i === length) {\n", " break;\n", " }\n", "\n", " matchKey = matchKey << 8 | dataArray[position + i];\n", " } // テーブルが未定義だったら作成する\n", "\n", "\n", " if (table[matchKey] === void 0) {\n", " table[matchKey] = [];\n", " }\n", "\n", " matchList = table[matchKey]; // skip\n", "\n", " if (skipLength-- > 0) {\n", " matchList.push(position);\n", " continue;\n", " } // マッチテーブルの更新 (最大戻り距離を超えているものを削除する)\n", "\n", "\n", " while (matchList.length > 0 && position - matchList[0] > windowSize) {\n", " matchList.shift();\n", " } // データ末尾でマッチしようがない場合はそのまま流しこむ\n", "\n", "\n", " if (position + Zlib.RawDeflate.Lz77MinLength >= length) {\n", " if (prevMatch) {\n", " writeMatch(prevMatch, -1);\n", " }\n", "\n", " for (i = 0, il = length - position; i < il; ++i) {\n", " tmp = dataArray[position + i];\n", " lz77buf[pos++] = tmp;\n", " ++freqsLitLen[tmp];\n", " }\n", "\n", " break;\n", " } // マッチ候補から最長のものを探す\n", "\n", "\n", " if (matchList.length > 0) {\n", " longestMatch = this.searchLongestMatch_(dataArray, position, matchList);\n", "\n", " if (prevMatch) {\n", " // 現在のマッチの方が前回のマッチよりも長い\n", " if (prevMatch.length < longestMatch.length) {\n", " // write previous literal\n", " tmp = dataArray[position - 1];\n", " lz77buf[pos++] = tmp;\n", " ++freqsLitLen[tmp]; // write current match\n", "\n", " writeMatch(longestMatch, 0);\n", " } else {\n", " // write previous match\n", " writeMatch(prevMatch, -1);\n", " }\n", " } else if (longestMatch.length < lazy) {\n", " prevMatch = longestMatch;\n", " } else {\n", " writeMatch(longestMatch, 0);\n", " } // 前回マッチしていて今回マッチがなかったら前回のを採用\n", "\n", " } else if (prevMatch) {\n", " writeMatch(prevMatch, -1);\n", " } else {\n", " tmp = dataArray[position];\n", " lz77buf[pos++] = tmp;\n", " ++freqsLitLen[tmp];\n", " }\n", "\n", " matchList.push(position); // マッチテーブルに現在の位置を保存\n", " } // 終端処理\n", "\n", "\n", " lz77buf[pos++] = 256;\n", " freqsLitLen[256]++;\n", " this.freqsLitLen = freqsLitLen;\n", " this.freqsDist = freqsDist;\n", " return (\n", " /** @type {!(Uint16Array|Array.)} */\n", " lz77buf.subarray(0, pos) \n", " );\n", " };\n", " /**\n", " * マッチした候補の中から最長一致を探す\n", " * @param {!Object} data plain data byte array.\n", " * @param {!number} position plain data byte array position.\n", " * @param {!Array.} matchList 候補となる位置の配列.\n", " * @return {!Zlib.RawDeflate.Lz77Match} 最長かつ最短距離のマッチオブジェクト.\n", " * @private\n", " */\n", "\n", "\n", " Zlib.RawDeflate.prototype.searchLongestMatch_ = function (data, position, matchList) {\n", " var match,\n", " currentMatch,\n", " matchMax = 0,\n", " matchLength,\n", " i,\n", " j,\n", " l,\n", " dl = data.length; // 候補を後ろから 1 つずつ絞り込んでゆく\n", "\n", " permatch: for (i = 0, l = matchList.length; i < l; i++) {\n", " match = matchList[l - i - 1];\n", " matchLength = Zlib.RawDeflate.Lz77MinLength; // 前回までの最長一致を末尾から一致検索する\n", "\n", " if (matchMax > Zlib.RawDeflate.Lz77MinLength) {\n", " for (j = matchMax; j > Zlib.RawDeflate.Lz77MinLength; j--) {\n", " if (data[match + j - 1] !== data[position + j - 1]) {\n", " continue permatch;\n", " }\n", " }\n", "\n", " matchLength = matchMax;\n", " } // 最長一致探索\n", "\n", "\n", " while (matchLength < Zlib.RawDeflate.Lz77MaxLength && position + matchLength < dl && data[match + matchLength] === data[position + matchLength]) {\n", " ++matchLength;\n", " } // マッチ長が同じ場合は後方を優先\n", "\n", "\n", " if (matchLength > matchMax) {\n", " currentMatch = match;\n", " matchMax = matchLength;\n", " } // 最長が確定したら後の処理は省略\n", "\n", "\n", " if (matchLength === Zlib.RawDeflate.Lz77MaxLength) {\n", " break;\n", " }\n", " }\n", "\n", " return new Zlib.RawDeflate.Lz77Match(matchMax, position - currentMatch);\n", " };\n", " /**\n", " * Tree-Transmit Symbols の算出\n", " * reference: PuTTY Deflate implementation\n", " * @param {number} hlit HLIT.\n", " * @param {!(Array.|Uint8Array)} litlenLengths リテラルと長さ符号の符号長配列.\n", " * @param {number} hdist HDIST.\n", " * @param {!(Array.|Uint8Array)} distLengths 距離符号の符号長配列.\n", " * @return {{\n", " * codes: !(Array.|Uint32Array),\n", " * freqs: !(Array.|Uint8Array)\n", " * }} Tree-Transmit Symbols.\n", " */\n", "\n", "\n", " Zlib.RawDeflate.prototype.getTreeSymbols_ = function (hlit, litlenLengths, hdist, distLengths) {\n", " var src = new (Uint32Array )(hlit + hdist),\n", " i,\n", " j,\n", " runLength,\n", " l,\n", " result = new (Uint32Array )(286 + 30),\n", " nResult,\n", " rpt,\n", " freqs = new (Uint8Array )(19);\n", " j = 0;\n", "\n", " for (i = 0; i < hlit; i++) {\n", " src[j++] = litlenLengths[i];\n", " }\n", "\n", " for (i = 0; i < hdist; i++) {\n", " src[j++] = distLengths[i];\n", " } // 初期化\n", "\n", "\n", " nResult = 0;\n", "\n", " for (i = 0, l = src.length; i < l; i += j) {\n", " // Run Length Encoding\n", " for (j = 1; i + j < l && src[i + j] === src[i]; ++j) {}\n", "\n", " runLength = j;\n", "\n", " if (src[i] === 0) {\n", " // 0 の繰り返しが 3 回未満ならばそのまま\n", " if (runLength < 3) {\n", " while (runLength-- > 0) {\n", " result[nResult++] = 0;\n", " freqs[0]++;\n", " }\n", " } else {\n", " while (runLength > 0) {\n", " // 繰り返しは最大 138 までなので切り詰める\n", " rpt = runLength < 138 ? runLength : 138;\n", "\n", " if (rpt > runLength - 3 && rpt < runLength) {\n", " rpt = runLength - 3;\n", " } // 3-10 回 -> 17\n", "\n", "\n", " if (rpt <= 10) {\n", " result[nResult++] = 17;\n", " result[nResult++] = rpt - 3;\n", " freqs[17]++; // 11-138 回 -> 18\n", " } else {\n", " result[nResult++] = 18;\n", " result[nResult++] = rpt - 11;\n", " freqs[18]++;\n", " }\n", "\n", " runLength -= rpt;\n", " }\n", " }\n", " } else {\n", " result[nResult++] = src[i];\n", " freqs[src[i]]++;\n", " runLength--; // 繰り返し回数が3回未満ならばランレングス符号は要らない\n", "\n", " if (runLength < 3) {\n", " while (runLength-- > 0) {\n", " result[nResult++] = src[i];\n", " freqs[src[i]]++;\n", " } // 3 回以上ならばランレングス符号化\n", "\n", " } else {\n", " while (runLength > 0) {\n", " // runLengthを 3-6 で分割\n", " rpt = runLength < 6 ? runLength : 6;\n", "\n", " if (rpt > runLength - 3 && rpt < runLength) {\n", " rpt = runLength - 3;\n", " }\n", "\n", " result[nResult++] = 16;\n", " result[nResult++] = rpt - 3;\n", " freqs[16]++;\n", " runLength -= rpt;\n", " }\n", " }\n", " }\n", " }\n", "\n", " return {\n", " codes: result.subarray(0, nResult) ,\n", " freqs: freqs\n", " };\n", " };\n", " /**\n", " * ハフマン符号の長さを取得する\n", " * @param {!(Array.|Uint8Array|Uint32Array)} freqs 出現カウント.\n", " * @param {number} limit 符号長の制限.\n", " * @return {!(Array.|Uint8Array)} 符号長配列.\n", " * @private\n", " */\n", "\n", "\n", " Zlib.RawDeflate.prototype.getLengths_ = function (freqs, limit) {\n", " /** @type {number} */\n", " var nSymbols = freqs.length;\n", " /** @type {Zlib.Heap} */\n", "\n", " var heap = new Zlib.Heap(2 * Zlib.RawDeflate.HUFMAX);\n", " /** @type {!(Array.|Uint8Array)} */\n", "\n", " var length = new (Uint8Array )(nSymbols);\n", " /** @type {Array} */\n", "\n", " var nodes;\n", " /** @type {!(Array.|Uint32Array)} */\n", "\n", " var values;\n", " /** @type {!(Array.|Uint8Array)} */\n", "\n", " var codeLength;\n", " /** @type {number} */\n", "\n", " var i;\n", " /** @type {number} */\n", "\n", " var il; // 配列の初期化\n", "\n", "\n", " for (i = 0; i < nSymbols; ++i) {\n", " if (freqs[i] > 0) {\n", " heap.push(i, freqs[i]);\n", " }\n", " }\n", "\n", " nodes = new Array(heap.length / 2);\n", " values = new (Uint32Array )(heap.length / 2); // 非 0 の要素が一つだけだった場合は、そのシンボルに符号長 1 を割り当てて終了\n", "\n", " if (nodes.length === 1) {\n", " length[heap.pop().index] = 1;\n", " return length;\n", " } // Reverse Package Merge Algorithm による Canonical Huffman Code の符号長決定\n", "\n", "\n", " for (i = 0, il = heap.length / 2; i < il; ++i) {\n", " nodes[i] = heap.pop();\n", " values[i] = nodes[i].value;\n", " }\n", "\n", " codeLength = this.reversePackageMerge_(values, values.length, limit);\n", "\n", " for (i = 0, il = nodes.length; i < il; ++i) {\n", " length[nodes[i].index] = codeLength[i];\n", " }\n", "\n", " return length;\n", " };\n", " /**\n", " * Reverse Package Merge Algorithm.\n", " * @param {!(Array.|Uint32Array)} freqs sorted probability.\n", " * @param {number} symbols number of symbols.\n", " * @param {number} limit code length limit.\n", " * @return {!(Array.|Uint8Array)} code lengths.\n", " */\n", "\n", "\n", " Zlib.RawDeflate.prototype.reversePackageMerge_ = function (freqs, symbols, limit) {\n", " /** @type {!(Array.|Uint16Array)} */\n", " var minimumCost = new (Uint16Array )(limit);\n", " /** @type {!(Array.|Uint8Array)} */\n", "\n", " var flag = new (Uint8Array )(limit);\n", " /** @type {!(Array.|Uint8Array)} */\n", "\n", " var codeLength = new (Uint8Array )(symbols);\n", " /** @type {Array} */\n", "\n", " var value = new Array(limit);\n", " /** @type {Array} */\n", "\n", " var type = new Array(limit);\n", " /** @type {Array.} */\n", "\n", " var currentPosition = new Array(limit);\n", " /** @type {number} */\n", "\n", " var excess = (1 << limit) - symbols;\n", " /** @type {number} */\n", "\n", " var half = 1 << limit - 1;\n", " /** @type {number} */\n", "\n", " var i;\n", " /** @type {number} */\n", "\n", " var j;\n", " /** @type {number} */\n", "\n", " var t;\n", " /** @type {number} */\n", "\n", " var weight;\n", " /** @type {number} */\n", "\n", " var next;\n", " /**\n", " * @param {number} j\n", " */\n", "\n", " function takePackage(j) {\n", " /** @type {number} */\n", " var x = type[j][currentPosition[j]];\n", "\n", " if (x === symbols) {\n", " takePackage(j + 1);\n", " takePackage(j + 1);\n", " } else {\n", " --codeLength[x];\n", " }\n", "\n", " ++currentPosition[j];\n", " }\n", "\n", " minimumCost[limit - 1] = symbols;\n", "\n", " for (j = 0; j < limit; ++j) {\n", " if (excess < half) {\n", " flag[j] = 0;\n", " } else {\n", " flag[j] = 1;\n", " excess -= half;\n", " }\n", "\n", " excess <<= 1;\n", " minimumCost[limit - 2 - j] = (minimumCost[limit - 1 - j] / 2 | 0) + symbols;\n", " }\n", "\n", " minimumCost[0] = flag[0];\n", " value[0] = new Array(minimumCost[0]);\n", " type[0] = new Array(minimumCost[0]);\n", "\n", " for (j = 1; j < limit; ++j) {\n", " if (minimumCost[j] > 2 * minimumCost[j - 1] + flag[j]) {\n", " minimumCost[j] = 2 * minimumCost[j - 1] + flag[j];\n", " }\n", "\n", " value[j] = new Array(minimumCost[j]);\n", " type[j] = new Array(minimumCost[j]);\n", " }\n", "\n", " for (i = 0; i < symbols; ++i) {\n", " codeLength[i] = limit;\n", " }\n", "\n", " for (t = 0; t < minimumCost[limit - 1]; ++t) {\n", " value[limit - 1][t] = freqs[t];\n", " type[limit - 1][t] = t;\n", " }\n", "\n", " for (i = 0; i < limit; ++i) {\n", " currentPosition[i] = 0;\n", " }\n", "\n", " if (flag[limit - 1] === 1) {\n", " --codeLength[0];\n", " ++currentPosition[limit - 1];\n", " }\n", "\n", " for (j = limit - 2; j >= 0; --j) {\n", " i = 0;\n", " weight = 0;\n", " next = currentPosition[j + 1];\n", "\n", " for (t = 0; t < minimumCost[j]; t++) {\n", " weight = value[j + 1][next] + value[j + 1][next + 1];\n", "\n", " if (weight > freqs[i]) {\n", " value[j][t] = weight;\n", " type[j][t] = symbols;\n", " next += 2;\n", " } else {\n", " value[j][t] = freqs[i];\n", " type[j][t] = i;\n", " ++i;\n", " }\n", " }\n", "\n", " currentPosition[j] = 0;\n", "\n", " if (flag[j] === 1) {\n", " takePackage(j);\n", " }\n", " }\n", "\n", " return codeLength;\n", " };\n", " /**\n", " * 符号長配列からハフマン符号を取得する\n", " * reference: PuTTY Deflate implementation\n", " * @param {!(Array.|Uint8Array)} lengths 符号長配列.\n", " * @return {!(Array.|Uint16Array)} ハフマン符号配列.\n", " * @private\n", " */\n", "\n", "\n", " Zlib.RawDeflate.prototype.getCodesFromLengths_ = function (lengths) {\n", " var codes = new (Uint16Array )(lengths.length),\n", " count = [],\n", " startCode = [],\n", " code = 0,\n", " i,\n", " il,\n", " j,\n", " m; // Count the codes of each length.\n", "\n", " for (i = 0, il = lengths.length; i < il; i++) {\n", " count[lengths[i]] = (count[lengths[i]] | 0) + 1;\n", " } // Determine the starting code for each length block.\n", "\n", "\n", " for (i = 1, il = Zlib.RawDeflate.MaxCodeLength; i <= il; i++) {\n", " startCode[i] = code;\n", " code += count[i] | 0;\n", " code <<= 1;\n", " } // Determine the code for each symbol. Mirrored, of course.\n", "\n", "\n", " for (i = 0, il = lengths.length; i < il; i++) {\n", " code = startCode[lengths[i]];\n", " startCode[lengths[i]] += 1;\n", " codes[i] = 0;\n", "\n", " for (j = 0, m = lengths[i]; j < m; j++) {\n", " codes[i] = codes[i] << 1 | code & 1;\n", " code >>>= 1;\n", " }\n", " }\n", "\n", " return codes;\n", " };\n", " /**\n", " * @param {!(Array.|Uint8Array)} input input buffer.\n", " * @param {Object=} opt_params options.\n", " * @constructor\n", " */\n", "\n", "\n", " Zlib.Unzip = function (input, opt_params) {\n", " opt_params = opt_params || {};\n", " /** @type {!(Array.|Uint8Array)} */\n", "\n", " this.input = input instanceof Array ? new Uint8Array(input) : input;\n", " /** @type {number} */\n", "\n", " this.ip = 0;\n", " /** @type {number} */\n", "\n", " this.eocdrOffset;\n", " /** @type {number} */\n", "\n", " this.numberOfThisDisk;\n", " /** @type {number} */\n", "\n", " this.startDisk;\n", " /** @type {number} */\n", "\n", " this.totalEntriesThisDisk;\n", " /** @type {number} */\n", "\n", " this.totalEntries;\n", " /** @type {number} */\n", "\n", " this.centralDirectorySize;\n", " /** @type {number} */\n", "\n", " this.centralDirectoryOffset;\n", " /** @type {number} */\n", "\n", " this.commentLength;\n", " /** @type {(Array.|Uint8Array)} */\n", "\n", " this.comment;\n", " /** @type {Array.} */\n", "\n", " this.fileHeaderList;\n", " /** @type {Object.} */\n", "\n", " this.filenameToIndex;\n", " /** @type {boolean} */\n", "\n", " this.verify = opt_params['verify'] || false;\n", " /** @type {(Array.|Uint8Array)} */\n", "\n", " this.password = opt_params['password'];\n", " };\n", "\n", " Zlib.Unzip.CompressionMethod = Zlib.Zip.CompressionMethod;\n", " /**\n", " * @type {Array.}\n", " * @const\n", " */\n", "\n", " Zlib.Unzip.FileHeaderSignature = Zlib.Zip.FileHeaderSignature;\n", " /**\n", " * @type {Array.}\n", " * @const\n", " */\n", "\n", " Zlib.Unzip.LocalFileHeaderSignature = Zlib.Zip.LocalFileHeaderSignature;\n", " /**\n", " * @type {Array.}\n", " * @const\n", " */\n", "\n", " Zlib.Unzip.CentralDirectorySignature = Zlib.Zip.CentralDirectorySignature;\n", " /**\n", " * @param {!(Array.|Uint8Array)} input input buffer.\n", " * @param {number} ip input position.\n", " * @constructor\n", " */\n", "\n", " Zlib.Unzip.FileHeader = function (input, ip) {\n", " /** @type {!(Array.|Uint8Array)} */\n", " this.input = input;\n", " /** @type {number} */\n", "\n", " this.offset = ip;\n", " /** @type {number} */\n", "\n", " this.length;\n", " /** @type {number} */\n", "\n", " this.version;\n", " /** @type {number} */\n", "\n", " this.os;\n", " /** @type {number} */\n", "\n", " this.needVersion;\n", " /** @type {number} */\n", "\n", " this.flags;\n", " /** @type {number} */\n", "\n", " this.compression;\n", " /** @type {number} */\n", "\n", " this.time;\n", " /** @type {number} */\n", "\n", " this.date;\n", " /** @type {number} */\n", "\n", " this.crc32;\n", " /** @type {number} */\n", "\n", " this.compressedSize;\n", " /** @type {number} */\n", "\n", " this.plainSize;\n", " /** @type {number} */\n", "\n", " this.fileNameLength;\n", " /** @type {number} */\n", "\n", " this.extraFieldLength;\n", " /** @type {number} */\n", "\n", " this.fileCommentLength;\n", " /** @type {number} */\n", "\n", " this.diskNumberStart;\n", " /** @type {number} */\n", "\n", " this.internalFileAttributes;\n", " /** @type {number} */\n", "\n", " this.externalFileAttributes;\n", " /** @type {number} */\n", "\n", " this.relativeOffset;\n", " /** @type {string} */\n", "\n", " this.filename;\n", " /** @type {!(Array.|Uint8Array)} */\n", "\n", " this.extraField;\n", " /** @type {!(Array.|Uint8Array)} */\n", "\n", " this.comment;\n", " };\n", "\n", " Zlib.Unzip.FileHeader.prototype.parse = function () {\n", " /** @type {!(Array.|Uint8Array)} */\n", " var input = this.input;\n", " /** @type {number} */\n", "\n", " var ip = this.offset; // central file header signature\n", "\n", " if (input[ip++] !== Zlib.Unzip.FileHeaderSignature[0] || input[ip++] !== Zlib.Unzip.FileHeaderSignature[1] || input[ip++] !== Zlib.Unzip.FileHeaderSignature[2] || input[ip++] !== Zlib.Unzip.FileHeaderSignature[3]) {\n", " throw new Error('invalid file header signature');\n", " } // version made by\n", "\n", "\n", " this.version = input[ip++];\n", " this.os = input[ip++]; // version needed to extract\n", "\n", " this.needVersion = input[ip++] | input[ip++] << 8; // general purpose bit flag\n", "\n", " this.flags = input[ip++] | input[ip++] << 8; // compression method\n", "\n", " this.compression = input[ip++] | input[ip++] << 8; // last mod file time\n", "\n", " this.time = input[ip++] | input[ip++] << 8; //last mod file date\n", "\n", " this.date = input[ip++] | input[ip++] << 8; // crc-32\n", "\n", " this.crc32 = (input[ip++] | input[ip++] << 8 | input[ip++] << 16 | input[ip++] << 24) >>> 0; // compressed size\n", "\n", " this.compressedSize = (input[ip++] | input[ip++] << 8 | input[ip++] << 16 | input[ip++] << 24) >>> 0; // uncompressed size\n", "\n", " this.plainSize = (input[ip++] | input[ip++] << 8 | input[ip++] << 16 | input[ip++] << 24) >>> 0; // file name length\n", "\n", " this.fileNameLength = input[ip++] | input[ip++] << 8; // extra field length\n", "\n", " this.extraFieldLength = input[ip++] | input[ip++] << 8; // file comment length\n", "\n", " this.fileCommentLength = input[ip++] | input[ip++] << 8; // disk number start\n", "\n", " this.diskNumberStart = input[ip++] | input[ip++] << 8; // internal file attributes\n", "\n", " this.internalFileAttributes = input[ip++] | input[ip++] << 8; // external file attributes\n", "\n", " this.externalFileAttributes = input[ip++] | input[ip++] << 8 | input[ip++] << 16 | input[ip++] << 24; // relative offset of local header\n", "\n", " this.relativeOffset = (input[ip++] | input[ip++] << 8 | input[ip++] << 16 | input[ip++] << 24) >>> 0; // file name\n", "\n", " this.filename = String.fromCharCode.apply(null, input.subarray(ip, ip += this.fileNameLength) ); // extra field\n", "\n", " this.extraField = input.subarray(ip, ip += this.extraFieldLength) ; // file comment\n", "\n", " this.comment = input.subarray(ip, ip + this.fileCommentLength) ;\n", " this.length = ip - this.offset;\n", " };\n", " /**\n", " * @param {!(Array.|Uint8Array)} input input buffer.\n", " * @param {number} ip input position.\n", " * @constructor\n", " */\n", "\n", "\n", " Zlib.Unzip.LocalFileHeader = function (input, ip) {\n", " /** @type {!(Array.|Uint8Array)} */\n", " this.input = input;\n", " /** @type {number} */\n", "\n", " this.offset = ip;\n", " /** @type {number} */\n", "\n", " this.length;\n", " /** @type {number} */\n", "\n", " this.needVersion;\n", " /** @type {number} */\n", "\n", " this.flags;\n", " /** @type {number} */\n", "\n", " this.compression;\n", " /** @type {number} */\n", "\n", " this.time;\n", " /** @type {number} */\n", "\n", " this.date;\n", " /** @type {number} */\n", "\n", " this.crc32;\n", " /** @type {number} */\n", "\n", " this.compressedSize;\n", " /** @type {number} */\n", "\n", " this.plainSize;\n", " /** @type {number} */\n", "\n", " this.fileNameLength;\n", " /** @type {number} */\n", "\n", " this.extraFieldLength;\n", " /** @type {string} */\n", "\n", " this.filename;\n", " /** @type {!(Array.|Uint8Array)} */\n", "\n", " this.extraField;\n", " };\n", "\n", " Zlib.Unzip.LocalFileHeader.Flags = Zlib.Zip.Flags;\n", "\n", " Zlib.Unzip.LocalFileHeader.prototype.parse = function () {\n", " /** @type {!(Array.|Uint8Array)} */\n", " var input = this.input;\n", " /** @type {number} */\n", "\n", " var ip = this.offset; // local file header signature\n", "\n", " if (input[ip++] !== Zlib.Unzip.LocalFileHeaderSignature[0] || input[ip++] !== Zlib.Unzip.LocalFileHeaderSignature[1] || input[ip++] !== Zlib.Unzip.LocalFileHeaderSignature[2] || input[ip++] !== Zlib.Unzip.LocalFileHeaderSignature[3]) {\n", " throw new Error('invalid local file header signature');\n", " } // version needed to extract\n", "\n", "\n", " this.needVersion = input[ip++] | input[ip++] << 8; // general purpose bit flag\n", "\n", " this.flags = input[ip++] | input[ip++] << 8; // compression method\n", "\n", " this.compression = input[ip++] | input[ip++] << 8; // last mod file time\n", "\n", " this.time = input[ip++] | input[ip++] << 8; //last mod file date\n", "\n", " this.date = input[ip++] | input[ip++] << 8; // crc-32\n", "\n", " this.crc32 = (input[ip++] | input[ip++] << 8 | input[ip++] << 16 | input[ip++] << 24) >>> 0; // compressed size\n", "\n", " this.compressedSize = (input[ip++] | input[ip++] << 8 | input[ip++] << 16 | input[ip++] << 24) >>> 0; // uncompressed size\n", "\n", " this.plainSize = (input[ip++] | input[ip++] << 8 | input[ip++] << 16 | input[ip++] << 24) >>> 0; // file name length\n", "\n", " this.fileNameLength = input[ip++] | input[ip++] << 8; // extra field length\n", "\n", " this.extraFieldLength = input[ip++] | input[ip++] << 8; // file name\n", "\n", " this.filename = String.fromCharCode.apply(null, input.subarray(ip, ip += this.fileNameLength) ); // extra field\n", "\n", " this.extraField = input.subarray(ip, ip += this.extraFieldLength) ;\n", " this.length = ip - this.offset;\n", " };\n", "\n", " Zlib.Unzip.prototype.searchEndOfCentralDirectoryRecord = function () {\n", " /** @type {!(Array.|Uint8Array)} */\n", " var input = this.input;\n", " /** @type {number} */\n", "\n", " var ip;\n", "\n", " for (ip = input.length - 12; ip > 0; --ip) {\n", " if (input[ip] === Zlib.Unzip.CentralDirectorySignature[0] && input[ip + 1] === Zlib.Unzip.CentralDirectorySignature[1] && input[ip + 2] === Zlib.Unzip.CentralDirectorySignature[2] && input[ip + 3] === Zlib.Unzip.CentralDirectorySignature[3]) {\n", " this.eocdrOffset = ip;\n", " return;\n", " }\n", " }\n", "\n", " throw new Error('End of Central Directory Record not found');\n", " };\n", "\n", " Zlib.Unzip.prototype.parseEndOfCentralDirectoryRecord = function () {\n", " /** @type {!(Array.|Uint8Array)} */\n", " var input = this.input;\n", " /** @type {number} */\n", "\n", " var ip;\n", "\n", " if (!this.eocdrOffset) {\n", " this.searchEndOfCentralDirectoryRecord();\n", " }\n", "\n", " ip = this.eocdrOffset; // signature\n", "\n", " if (input[ip++] !== Zlib.Unzip.CentralDirectorySignature[0] || input[ip++] !== Zlib.Unzip.CentralDirectorySignature[1] || input[ip++] !== Zlib.Unzip.CentralDirectorySignature[2] || input[ip++] !== Zlib.Unzip.CentralDirectorySignature[3]) {\n", " throw new Error('invalid signature');\n", " } // number of this disk\n", "\n", "\n", " this.numberOfThisDisk = input[ip++] | input[ip++] << 8; // number of the disk with the start of the central directory\n", "\n", " this.startDisk = input[ip++] | input[ip++] << 8; // total number of entries in the central directory on this disk\n", "\n", " this.totalEntriesThisDisk = input[ip++] | input[ip++] << 8; // total number of entries in the central directory\n", "\n", " this.totalEntries = input[ip++] | input[ip++] << 8; // size of the central directory\n", "\n", " this.centralDirectorySize = (input[ip++] | input[ip++] << 8 | input[ip++] << 16 | input[ip++] << 24) >>> 0; // offset of start of central directory with respect to the starting disk number\n", "\n", " this.centralDirectoryOffset = (input[ip++] | input[ip++] << 8 | input[ip++] << 16 | input[ip++] << 24) >>> 0; // .ZIP file comment length\n", "\n", " this.commentLength = input[ip++] | input[ip++] << 8; // .ZIP file comment\n", "\n", " this.comment = input.subarray(ip, ip + this.commentLength) ;\n", " };\n", "\n", " Zlib.Unzip.prototype.parseFileHeader = function () {\n", " /** @type {Array.} */\n", " var filelist = [];\n", " /** @type {Object.} */\n", "\n", " var filetable = {};\n", " /** @type {number} */\n", "\n", " var ip;\n", " /** @type {Zlib.Unzip.FileHeader} */\n", "\n", " var fileHeader;\n", " /*: @type {number} */\n", "\n", " var i;\n", " /*: @type {number} */\n", "\n", " var il;\n", "\n", " if (this.fileHeaderList) {\n", " return;\n", " }\n", "\n", " if (this.centralDirectoryOffset === void 0) {\n", " this.parseEndOfCentralDirectoryRecord();\n", " }\n", "\n", " ip = this.centralDirectoryOffset;\n", "\n", " for (i = 0, il = this.totalEntries; i < il; ++i) {\n", " fileHeader = new Zlib.Unzip.FileHeader(this.input, ip);\n", " fileHeader.parse();\n", " ip += fileHeader.length;\n", " filelist[i] = fileHeader;\n", " filetable[fileHeader.filename] = i;\n", " }\n", "\n", " if (this.centralDirectorySize < ip - this.centralDirectoryOffset) {\n", " throw new Error('invalid file header size');\n", " }\n", "\n", " this.fileHeaderList = filelist;\n", " this.filenameToIndex = filetable;\n", " };\n", " /**\n", " * @param {number} index file header index.\n", " * @param {Object=} opt_params\n", " * @return {!(Array.|Uint8Array)} file data.\n", " */\n", "\n", "\n", " Zlib.Unzip.prototype.getFileData = function (index, opt_params) {\n", " opt_params = opt_params || {};\n", " /** @type {!(Array.|Uint8Array)} */\n", "\n", " var input = this.input;\n", " /** @type {Array.} */\n", "\n", " var fileHeaderList = this.fileHeaderList;\n", " /** @type {Zlib.Unzip.LocalFileHeader} */\n", "\n", " var localFileHeader;\n", " /** @type {number} */\n", "\n", " var offset;\n", " /** @type {number} */\n", "\n", " var length;\n", " /** @type {!(Array.|Uint8Array)} */\n", "\n", " var buffer;\n", " /** @type {number} */\n", "\n", " var crc32;\n", " /** @type {Array.|Uint32Array|Object} */\n", "\n", " var key;\n", " /** @type {number} */\n", "\n", " var i;\n", " /** @type {number} */\n", "\n", " var il;\n", "\n", " if (!fileHeaderList) {\n", " this.parseFileHeader();\n", " }\n", "\n", " if (fileHeaderList[index] === void 0) {\n", " throw new Error('wrong index');\n", " }\n", "\n", " offset = fileHeaderList[index].relativeOffset;\n", " localFileHeader = new Zlib.Unzip.LocalFileHeader(this.input, offset);\n", " localFileHeader.parse();\n", " offset += localFileHeader.length;\n", " length = localFileHeader.compressedSize; // decryption\n", "\n", " if ((localFileHeader.flags & Zlib.Unzip.LocalFileHeader.Flags.ENCRYPT) !== 0) {\n", " if (!(opt_params['password'] || this.password)) {\n", " throw new Error('please set password');\n", " }\n", "\n", " key = this.createDecryptionKey(opt_params['password'] || this.password); // encryption header\n", "\n", " for (i = offset, il = offset + 12; i < il; ++i) {\n", " this.decode(key, input[i]);\n", " }\n", "\n", " offset += 12;\n", " length -= 12; // decryption\n", "\n", " for (i = offset, il = offset + length; i < il; ++i) {\n", " input[i] = this.decode(key, input[i]);\n", " }\n", " }\n", "\n", " switch (localFileHeader.compression) {\n", " case Zlib.Unzip.CompressionMethod.STORE:\n", " buffer = this.input.subarray(offset, offset + length) ;\n", " break;\n", "\n", " case Zlib.Unzip.CompressionMethod.DEFLATE:\n", " buffer = new Zlib.RawInflate(this.input, {\n", " 'index': offset,\n", " 'bufferSize': localFileHeader.plainSize\n", " }).decompress();\n", " break;\n", "\n", " default:\n", " throw new Error('unknown compression type');\n", " }\n", "\n", " if (this.verify) {\n", " crc32 = Zlib.CRC32.calc(buffer);\n", "\n", " if (localFileHeader.crc32 !== crc32) {\n", " throw new Error('wrong crc: file=0x' + localFileHeader.crc32.toString(16) + ', data=0x' + crc32.toString(16));\n", " }\n", " }\n", "\n", " return buffer;\n", " };\n", " /**\n", " * @return {Array.}\n", " */\n", "\n", "\n", " Zlib.Unzip.prototype.getFilenames = function () {\n", " /** @type {Array.} */\n", " var filenameList = [];\n", " /** @type {number} */\n", "\n", " var i;\n", " /** @type {number} */\n", "\n", " var il;\n", " /** @type {Array.} */\n", "\n", " var fileHeaderList;\n", "\n", " if (!this.fileHeaderList) {\n", " this.parseFileHeader();\n", " }\n", "\n", " fileHeaderList = this.fileHeaderList;\n", "\n", " for (i = 0, il = fileHeaderList.length; i < il; ++i) {\n", " filenameList[i] = fileHeaderList[i].filename;\n", " }\n", "\n", " return filenameList;\n", " };\n", " /**\n", " * @param {string} filename extract filename.\n", " * @param {Object=} opt_params\n", " * @return {!(Array.|Uint8Array)} decompressed data.\n", " */\n", "\n", "\n", " Zlib.Unzip.prototype.decompress = function (filename, opt_params) {\n", " /** @type {number} */\n", " var index;\n", "\n", " if (!this.filenameToIndex) {\n", " this.parseFileHeader();\n", " }\n", "\n", " index = this.filenameToIndex[filename];\n", "\n", " if (index === void 0) {\n", " throw new Error(filename + ' not found');\n", " }\n", "\n", " return this.getFileData(index, opt_params);\n", " };\n", " /**\n", " * @param {(Array.|Uint8Array)} password\n", " */\n", "\n", "\n", " Zlib.Unzip.prototype.setPassword = function (password) {\n", " this.password = password;\n", " };\n", " /**\n", " * @param {(Array.|Uint32Array|Object)} key\n", " * @param {number} n\n", " * @return {number}\n", " */\n", "\n", "\n", " Zlib.Unzip.prototype.decode = function (key, n) {\n", " n ^= this.getByte(\n", " /** @type {(Array.|Uint32Array)} */\n", " key);\n", " this.updateKeys(\n", " /** @type {(Array.|Uint32Array)} */\n", " key, n);\n", " return n;\n", " }; // common method\n", "\n", "\n", " Zlib.Unzip.prototype.updateKeys = Zlib.Zip.prototype.updateKeys;\n", " Zlib.Unzip.prototype.createDecryptionKey = Zlib.Zip.prototype.createEncryptionKey;\n", " Zlib.Unzip.prototype.getByte = Zlib.Zip.prototype.getByte;\n", " /**\n", " * @fileoverview 雑多な関数群をまとめたモジュール実装.\n", " */\n", "\n", " /**\n", " * Byte String から Byte Array に変換.\n", " * @param {!string} str byte string.\n", " * @return {!Array.} byte array.\n", " */\n", "\n", " Zlib.Util.stringToByteArray = function (str) {\n", " /** @type {!Array.<(string|number)>} */\n", " var tmp = str.split('');\n", " /** @type {number} */\n", "\n", " var i;\n", " /** @type {number} */\n", "\n", " var il;\n", "\n", " for (i = 0, il = tmp.length; i < il; i++) {\n", " tmp[i] = (tmp[i].charCodeAt(0) & 0xff) >>> 0;\n", " }\n", "\n", " return tmp;\n", " };\n", " /**\n", " * @fileoverview Adler32 checksum 実装.\n", " */\n", "\n", " /**\n", " * Adler32 ハッシュ値の作成\n", " * @param {!(Array|Uint8Array|string)} array 算出に使用する byte array.\n", " * @return {number} Adler32 ハッシュ値.\n", " */\n", "\n", "\n", " Zlib.Adler32 = function (array) {\n", " if (typeof array === 'string') {\n", " array = Zlib.Util.stringToByteArray(array);\n", " }\n", "\n", " return Zlib.Adler32.update(1, array);\n", " };\n", " /**\n", " * Adler32 ハッシュ値の更新\n", " * @param {number} adler 現在のハッシュ値.\n", " * @param {!(Array|Uint8Array)} array 更新に使用する byte array.\n", " * @return {number} Adler32 ハッシュ値.\n", " */\n", "\n", "\n", " Zlib.Adler32.update = function (adler, array) {\n", " /** @type {number} */\n", " var s1 = adler & 0xffff;\n", " /** @type {number} */\n", "\n", " var s2 = adler >>> 16 & 0xffff;\n", " /** @type {number} array length */\n", "\n", " var len = array.length;\n", " /** @type {number} loop length (don't overflow) */\n", "\n", " var tlen;\n", " /** @type {number} array index */\n", "\n", " var i = 0;\n", "\n", " while (len > 0) {\n", " tlen = len > Zlib.Adler32.OptimizationParameter ? Zlib.Adler32.OptimizationParameter : len;\n", " len -= tlen;\n", "\n", " do {\n", " s1 += array[i++];\n", " s2 += s1;\n", " } while (--tlen);\n", "\n", " s1 %= 65521;\n", " s2 %= 65521;\n", " }\n", "\n", " return (s2 << 16 | s1) >>> 0;\n", " };\n", " /**\n", " * Adler32 最適化パラメータ\n", " * 現状では 1024 程度が最適.\n", " * @see http://jsperf.com/adler-32-simple-vs-optimized/3\n", " * @define {number}\n", " */\n", "\n", "\n", " Zlib.Adler32.OptimizationParameter = 1024;\n", " /**\n", " * ビットストリーム\n", " * @constructor\n", " * @param {!(Array|Uint8Array)=} buffer output buffer.\n", " * @param {number=} bufferPosition start buffer pointer.\n", " */\n", "\n", " Zlib.BitStream = function (buffer, bufferPosition) {\n", " /** @type {number} buffer index. */\n", " this.index = typeof bufferPosition === 'number' ? bufferPosition : 0;\n", " /** @type {number} bit index. */\n", "\n", " this.bitindex = 0;\n", " /** @type {!(Array|Uint8Array)} bit-stream output buffer. */\n", "\n", " this.buffer = buffer instanceof (Uint8Array ) ? buffer : new (Uint8Array )(Zlib.BitStream.DefaultBlockSize); // 入力された index が足りなかったら拡張するが、倍にしてもダメなら不正とする\n", "\n", " if (this.buffer.length * 2 <= this.index) {\n", " throw new Error(\"invalid index\");\n", " } else if (this.buffer.length <= this.index) {\n", " this.expandBuffer();\n", " }\n", " };\n", " /**\n", " * デフォルトブロックサイズ.\n", " * @const\n", " * @type {number}\n", " */\n", "\n", "\n", " Zlib.BitStream.DefaultBlockSize = 0x8000;\n", " /**\n", " * expand buffer.\n", " * @return {!(Array|Uint8Array)} new buffer.\n", " */\n", "\n", " Zlib.BitStream.prototype.expandBuffer = function () {\n", " /** @type {!(Array|Uint8Array)} old buffer. */\n", " var oldbuf = this.buffer;\n", " /** @type {number} loop limiter. */\n", "\n", " var il = oldbuf.length;\n", " /** @type {!(Array|Uint8Array)} new buffer. */\n", "\n", " var buffer = new (Uint8Array )(il << 1); // copy buffer\n", "\n", " {\n", " buffer.set(oldbuf);\n", " }\n", "\n", " return this.buffer = buffer;\n", " };\n", " /**\n", " * 数値をビットで指定した数だけ書き込む.\n", " * @param {number} number 書き込む数値.\n", " * @param {number} n 書き込むビット数.\n", " * @param {boolean=} reverse 逆順に書き込むならば true.\n", " */\n", "\n", "\n", " Zlib.BitStream.prototype.writeBits = function (number, n, reverse) {\n", " var buffer = this.buffer;\n", " var index = this.index;\n", " var bitindex = this.bitindex;\n", " /** @type {number} current octet. */\n", "\n", " var current = buffer[index];\n", " /** @type {number} loop counter. */\n", "\n", " var i;\n", " /**\n", " * 32-bit 整数のビット順を逆にする\n", " * @param {number} n 32-bit integer.\n", " * @return {number} reversed 32-bit integer.\n", " * @private\n", " */\n", "\n", " function rev32_(n) {\n", " return Zlib.BitStream.ReverseTable[n & 0xFF] << 24 | Zlib.BitStream.ReverseTable[n >>> 8 & 0xFF] << 16 | Zlib.BitStream.ReverseTable[n >>> 16 & 0xFF] << 8 | Zlib.BitStream.ReverseTable[n >>> 24 & 0xFF];\n", " }\n", "\n", " if (reverse && n > 1) {\n", " number = n > 8 ? rev32_(number) >> 32 - n : Zlib.BitStream.ReverseTable[number] >> 8 - n;\n", " } // Byte 境界を超えないとき\n", "\n", "\n", " if (n + bitindex < 8) {\n", " current = current << n | number;\n", " bitindex += n; // Byte 境界を超えるとき\n", " } else {\n", " for (i = 0; i < n; ++i) {\n", " current = current << 1 | number >> n - i - 1 & 1; // next byte\n", "\n", " if (++bitindex === 8) {\n", " bitindex = 0;\n", " buffer[index++] = Zlib.BitStream.ReverseTable[current];\n", " current = 0; // expand\n", "\n", " if (index === buffer.length) {\n", " buffer = this.expandBuffer();\n", " }\n", " }\n", " }\n", " }\n", "\n", " buffer[index] = current;\n", " this.buffer = buffer;\n", " this.bitindex = bitindex;\n", " this.index = index;\n", " };\n", " /**\n", " * ストリームの終端処理を行う\n", " * @return {!(Array|Uint8Array)} 終端処理後のバッファを byte array で返す.\n", " */\n", "\n", "\n", " Zlib.BitStream.prototype.finish = function () {\n", " var buffer = this.buffer;\n", " var index = this.index;\n", " /** @type {!(Array|Uint8Array)} output buffer. */\n", "\n", " var output; // bitindex が 0 の時は余分に index が進んでいる状態\n", "\n", " if (this.bitindex > 0) {\n", " buffer[index] <<= 8 - this.bitindex;\n", " buffer[index] = Zlib.BitStream.ReverseTable[buffer[index]];\n", " index++;\n", " } // array truncation\n", "\n", "\n", " {\n", " output = buffer.subarray(0, index);\n", " }\n", "\n", " return output;\n", " };\n", " /**\n", " * 0-255 のビット順を反転したテーブル\n", " * @const\n", " * @type {!(Uint8Array|Array.)}\n", " */\n", "\n", "\n", " Zlib.BitStream.ReverseTable = function (table) {\n", " return table;\n", " }(function () {\n", " /** @type {!(Array|Uint8Array)} reverse table. */\n", " var table = new (Uint8Array )(256);\n", " /** @type {number} loop counter. */\n", "\n", " var i; // generate\n", "\n", " for (i = 0; i < 256; ++i) {\n", " table[i] = function (n) {\n", " var r = n;\n", " var s = 7;\n", "\n", " for (n >>>= 1; n; n >>>= 1) {\n", " r <<= 1;\n", " r |= n & 1;\n", " --s;\n", " }\n", "\n", " return (r << s & 0xff) >>> 0;\n", " }(i);\n", " }\n", "\n", " return table;\n", " }());\n", " /**\n", " * CRC32 ハッシュ値を取得\n", " * @param {!(Array.|Uint8Array)} data data byte array.\n", " * @param {number=} pos data position.\n", " * @param {number=} length data length.\n", " * @return {number} CRC32.\n", " */\n", "\n", " Zlib.CRC32.calc = function (data, pos, length) {\n", " return Zlib.CRC32.update(data, 0, pos, length);\n", " };\n", " /**\n", " * CRC32ハッシュ値を更新\n", " * @param {!(Array.|Uint8Array)} data data byte array.\n", " * @param {number} crc CRC32.\n", " * @param {number=} pos data position.\n", " * @param {number=} length data length.\n", " * @return {number} CRC32.\n", " */\n", "\n", "\n", " Zlib.CRC32.update = function (data, crc, pos, length) {\n", " var table = Zlib.CRC32.Table;\n", " var i = typeof pos === 'number' ? pos : pos = 0;\n", " var il = typeof length === 'number' ? length : data.length;\n", " crc ^= 0xffffffff; // loop unrolling for performance\n", "\n", " for (i = il & 7; i--; ++pos) {\n", " crc = crc >>> 8 ^ table[(crc ^ data[pos]) & 0xff];\n", " }\n", "\n", " for (i = il >> 3; i--; pos += 8) {\n", " crc = crc >>> 8 ^ table[(crc ^ data[pos]) & 0xff];\n", " crc = crc >>> 8 ^ table[(crc ^ data[pos + 1]) & 0xff];\n", " crc = crc >>> 8 ^ table[(crc ^ data[pos + 2]) & 0xff];\n", " crc = crc >>> 8 ^ table[(crc ^ data[pos + 3]) & 0xff];\n", " crc = crc >>> 8 ^ table[(crc ^ data[pos + 4]) & 0xff];\n", " crc = crc >>> 8 ^ table[(crc ^ data[pos + 5]) & 0xff];\n", " crc = crc >>> 8 ^ table[(crc ^ data[pos + 6]) & 0xff];\n", " crc = crc >>> 8 ^ table[(crc ^ data[pos + 7]) & 0xff];\n", " }\n", "\n", " return (crc ^ 0xffffffff) >>> 0;\n", " };\n", " /**\n", " * @param {number} num\n", " * @param {number} crc\n", " * @returns {number}\n", " */\n", "\n", "\n", " Zlib.CRC32.single = function (num, crc) {\n", " return (Zlib.CRC32.Table[(num ^ crc) & 0xff] ^ num >>> 8) >>> 0;\n", " };\n", " /**\n", " * @type {Array.}\n", " * @const\n", " * @private\n", " */\n", "\n", "\n", " Zlib.CRC32.Table_ = [0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d];\n", " /**\n", " * @type {!(Array.|Uint32Array)} CRC-32 Table.\n", " * @const\n", " */\n", "\n", " Zlib.CRC32.Table = new Uint32Array(Zlib.CRC32.Table_) ;\n", " /**\n", " * @fileoverview Deflate (RFC1951) 実装.\n", " * Deflateアルゴリズム本体は Zlib.RawDeflate で実装されている.\n", " */\n", "\n", " /**\n", " * Zlib Deflate\n", " * @constructor\n", " * @param {!(Array|Uint8Array)} input 符号化する対象の byte array.\n", " * @param {Object=} opt_params option parameters.\n", " */\n", "\n", " Zlib.Deflate = function (input, opt_params) {\n", " /** @type {!(Array|Uint8Array)} */\n", " this.input = input;\n", " /** @type {!(Array|Uint8Array)} */\n", "\n", " this.output = new (Uint8Array )(Zlib.Deflate.DefaultBufferSize);\n", " /** @type {Zlib.Deflate.CompressionType} */\n", "\n", " this.compressionType = Zlib.Deflate.CompressionType.DYNAMIC;\n", " /** @type {Zlib.RawDeflate} */\n", "\n", " this.rawDeflate;\n", " /** @type {Object} */\n", "\n", " var rawDeflateOption = {};\n", " /** @type {string} */\n", "\n", " var prop; // option parameters\n", "\n", " if (opt_params || !(opt_params = {})) {\n", " if (typeof opt_params['compressionType'] === 'number') {\n", " this.compressionType = opt_params['compressionType'];\n", " }\n", " } // copy options\n", "\n", "\n", " for (prop in opt_params) {\n", " rawDeflateOption[prop] = opt_params[prop];\n", " } // set raw-deflate output buffer\n", "\n", "\n", " rawDeflateOption['outputBuffer'] = this.output;\n", " this.rawDeflate = new Zlib.RawDeflate(this.input, rawDeflateOption);\n", " };\n", " /**\n", " * @const\n", " * @type {number} デフォルトバッファサイズ.\n", " */\n", "\n", "\n", " Zlib.Deflate.DefaultBufferSize = 0x8000;\n", " /**\n", " * @enum {number}\n", " */\n", "\n", " Zlib.Deflate.CompressionType = Zlib.RawDeflate.CompressionType;\n", " /**\n", " * 直接圧縮に掛ける.\n", " * @param {!(Array|Uint8Array)} input target buffer.\n", " * @param {Object=} opt_params option parameters.\n", " * @return {!(Array|Uint8Array)} compressed data byte array.\n", " */\n", "\n", " Zlib.Deflate.compress = function (input, opt_params) {\n", " return new Zlib.Deflate(input, opt_params).compress();\n", " };\n", " /**\n", " * Deflate Compression.\n", " * @return {!(Array|Uint8Array)} compressed data byte array.\n", " */\n", "\n", "\n", " Zlib.Deflate.prototype.compress = function () {\n", " /** @type {Zlib.CompressionMethod} */\n", " var cm;\n", " /** @type {number} */\n", "\n", " var cinfo;\n", " /** @type {number} */\n", "\n", " var cmf;\n", " /** @type {number} */\n", "\n", " var flg;\n", " /** @type {number} */\n", "\n", " var fcheck;\n", " /** @type {number} */\n", "\n", " var fdict;\n", " /** @type {number} */\n", "\n", " var flevel;\n", " /** @type {number} */\n", "\n", " var adler;\n", " /** @type {!(Array|Uint8Array)} */\n", "\n", " var output;\n", " /** @type {number} */\n", "\n", " var pos = 0;\n", " output = this.output; // Compression Method and Flags\n", "\n", " cm = Zlib.CompressionMethod.DEFLATE;\n", "\n", " switch (cm) {\n", " case Zlib.CompressionMethod.DEFLATE:\n", " cinfo = Math.LOG2E * Math.log(Zlib.RawDeflate.WindowSize) - 8;\n", " break;\n", "\n", " default:\n", " throw new Error('invalid compression method');\n", " }\n", "\n", " cmf = cinfo << 4 | cm;\n", " output[pos++] = cmf; // Flags\n", "\n", " fdict = 0;\n", "\n", " switch (cm) {\n", " case Zlib.CompressionMethod.DEFLATE:\n", " switch (this.compressionType) {\n", " case Zlib.Deflate.CompressionType.NONE:\n", " flevel = 0;\n", " break;\n", "\n", " case Zlib.Deflate.CompressionType.FIXED:\n", " flevel = 1;\n", " break;\n", "\n", " case Zlib.Deflate.CompressionType.DYNAMIC:\n", " flevel = 2;\n", " break;\n", "\n", " default:\n", " throw new Error('unsupported compression type');\n", " }\n", "\n", " break;\n", "\n", " default:\n", " throw new Error('invalid compression method');\n", " }\n", "\n", " flg = flevel << 6 | fdict << 5;\n", " fcheck = 31 - (cmf * 256 + flg) % 31;\n", " flg |= fcheck;\n", " output[pos++] = flg; // Adler-32 checksum\n", "\n", " adler = Zlib.Adler32(this.input);\n", " this.rawDeflate.op = pos;\n", " output = this.rawDeflate.compress();\n", " pos = output.length;\n", "\n", " {\n", " // subarray 分を元にもどす\n", " output = new Uint8Array(output.buffer); // expand buffer\n", "\n", " if (output.length <= pos + 4) {\n", " this.output = new Uint8Array(output.length + 4);\n", " this.output.set(output);\n", " output = this.output;\n", " }\n", "\n", " output = output.subarray(0, pos + 4);\n", " } // adler32\n", "\n", "\n", " output[pos++] = adler >> 24 & 0xff;\n", " output[pos++] = adler >> 16 & 0xff;\n", " output[pos++] = adler >> 8 & 0xff;\n", " output[pos++] = adler & 0xff;\n", " return output;\n", " };\n", "\n", " const isNode$3 = typeof process !== 'undefined' && process.versions != null && process.versions.node != null;\n", " const crossFetch = isNode$3 ? require(\"node-fetch\") : fetch;\n", "\n", " class BrowserLocalFile {\n", " constructor(blob) {\n", " this.file = blob;\n", " }\n", "\n", " async read(position, length) {\n", " const file = this.file;\n", "\n", " if (position !== undefined) {\n", " return file.slice(position, position + length).arrayBuffer();\n", " } else {\n", " return file.arrayBuffer();\n", " }\n", " }\n", "\n", " }\n", "\n", " const isNode$2 = typeof process !== 'undefined' && process.versions != null && process.versions.node != null;\n", " let fs;\n", " let fsOpen;\n", " let fsRead;\n", "\n", " if (isNode$2) {\n", " const util = require('util');\n", "\n", " fs = require('fs');\n", " fsOpen = fs && util.promisify(fs.open);\n", " fsRead = fs && util.promisify(fs.read);\n", " }\n", "\n", " class NodeLocalFile {\n", " constructor(args) {\n", " this.path = args.path;\n", " }\n", "\n", " async read(position, length) {\n", " const buffer = Buffer.alloc(length);\n", " const fd = await fsOpen(this.path, 'r');\n", " const result = await fsRead(fd, buffer, 0, length, position);\n", " fs.close(fd, function (error) {// TODO Do something with error\n", " }); //TODO -- compare result.bytesRead with length\n", "\n", " const b = result.buffer;\n", " const arrayBuffer = b.buffer.slice(b.byteOffset, b.byteOffset + b.byteLength);\n", " return arrayBuffer;\n", " }\n", "\n", " }\n", "\n", " const isNode$1 = typeof process !== 'undefined' && process.versions != null && process.versions.node != null;\n", "\n", " class RemoteFile {\n", " constructor(args) {\n", " this.config = args;\n", " this.url = mapUrl(args.path || args.url);\n", " }\n", "\n", " async read(position, length) {\n", " length = Math.ceil(length);\n", " const headers = this.config.headers || {};\n", " const rangeString = \"bytes=\" + position + \"-\" + (position + length - 1);\n", " headers['Range'] = rangeString;\n", " let url = this.url.slice(); // slice => copy\n", "\n", " if (isNode$1) {\n", " headers['User-Agent'] = 'straw';\n", " } else {\n", " if (this.config.oauthToken) {\n", " const token = resolveToken(this.config.oauthToken);\n", " headers['Authorization'] = `Bearer ${token}`;\n", " }\n", "\n", " navigator.vendor.indexOf(\"Apple\") == 0 && /\\sSafari\\//.test(navigator.userAgent);\n", " const isChrome = navigator.userAgent.indexOf('Chrome') > -1;\n", " const isAmazonV4Signed = this.url.indexOf(\"X-Amz-Signature\") > -1;\n", "\n", " if (isChrome && !isAmazonV4Signed) {\n", " url = addParameter(url, \"randomSeed\", Math.random().toString(36));\n", " }\n", " }\n", "\n", " if (this.config.apiKey) {\n", " url = addParameter(url, \"key\", this.config.apiKey);\n", " }\n", "\n", " const response = await crossFetch(url, {\n", " method: 'GET',\n", " headers: headers,\n", " redirect: 'follow',\n", " mode: 'cors'\n", " });\n", " const status = response.status;\n", "\n", " if (status >= 400) {\n", " console.error(`${status} ${this.config.url}`);\n", " const err = Error(response.statusText);\n", " err.code = status;\n", " throw err;\n", " } else {\n", " return response.arrayBuffer();\n", " }\n", " /**\n", " * token can be a string, a function that returns a string, or a function that returns a Promise for a string\n", " * @param token\n", " * @returns {Promise<*>}\n", " */\n", "\n", "\n", " async function resolveToken(token) {\n", " if (typeof token === 'function') {\n", " return await Promise.resolve(token()); // Normalize the result to a promise, since we don't know what the function returns\n", " } else {\n", " return token;\n", " }\n", " }\n", " }\n", "\n", " }\n", "\n", " function mapUrl(url) {\n", " if (url.includes(\"//www.dropbox.com\")) {\n", " return url.replace(\"//www.dropbox.com\", \"//dl.dropboxusercontent.com\");\n", " } else if (url.startsWith(\"ftp://ftp.ncbi.nlm.nih.gov\")) {\n", " return url.replace(\"ftp://\", \"https://\");\n", " } else {\n", " return url;\n", " }\n", " }\n", "\n", " function addParameter(url, name, value) {\n", " const paramSeparator = url.includes(\"?\") ? \"&\" : \"?\";\n", " return url + paramSeparator + name + \"=\" + value;\n", " }\n", "\n", " class ThrottledFile {\n", " constructor(file, rateLimiter) {\n", " this.file = file;\n", " this.rateLimiter = rateLimiter;\n", " }\n", "\n", " async read(position, length) {\n", " const file = this.file;\n", " const rateLimiter = this.rateLimiter;\n", " return new Promise(function (fulfill, reject) {\n", " rateLimiter.limiter(async function (f) {\n", " try {\n", " const result = await f.read(position, length);\n", " fulfill(result);\n", " } catch (e) {\n", " reject(e);\n", " }\n", " })(file);\n", " });\n", " }\n", "\n", " }\n", "\n", " class RateLimiter {\n", " constructor(wait) {\n", " this.wait = wait === undefined ? 100 : wait;\n", " this.isCalled = false;\n", " this.calls = [];\n", " }\n", "\n", " limiter(fn) {\n", " const self = this;\n", "\n", " let caller = function () {\n", " if (self.calls.length && !self.isCalled) {\n", " self.isCalled = true;\n", " self.calls.shift().call();\n", " setTimeout(function () {\n", " self.isCalled = false;\n", " caller();\n", " }, self.wait);\n", " }\n", " };\n", "\n", " return function () {\n", " self.calls.push(fn.bind(this, ...arguments));\n", " caller();\n", " };\n", " }\n", "\n", " }\n", "\n", " class BufferedFile {\n", " constructor(args) {\n", " this.file = args.file;\n", " this.size = args.size || 64000;\n", " this.position = 0;\n", " this.bufferStart = 0;\n", " this.bufferLength = 0;\n", " this.buffer = undefined;\n", " }\n", "\n", " async read(position, length) {\n", " const start = position;\n", " const end = position + length;\n", " const bufferStart = this.bufferStart;\n", " const bufferEnd = this.bufferStart + this.bufferLength;\n", "\n", " if (length > this.size) {\n", " // Request larger than max buffer size, pass through to underlying file\n", " //console.log(\"0\")\n", " this.buffer = undefined;\n", " this.bufferStart = 0;\n", " this.bufferLength = 0;\n", " return this.file.read(position, length);\n", " }\n", "\n", " if (start >= bufferStart && end <= bufferEnd) {\n", " // Request within buffer bounds\n", " //console.log(\"1\")\n", " const sliceStart = start - bufferStart;\n", " const sliceEnd = sliceStart + length;\n", " return this.buffer.slice(sliceStart, sliceEnd);\n", " } else if (start < bufferStart && end > bufferStart) {\n", " // Overlap left, here for completness but this is an unexpected case in straw. We don't adjust the buffer.\n", " //console.log(\"2\")\n", " const l1 = bufferStart - start;\n", " const a1 = await this.file.read(position, l1);\n", " const l2 = length - l1;\n", "\n", " if (l2 > 0) {\n", " //this.buffer = await this.file.read(bufferStart, this.size)\n", " const a2 = this.buffer.slice(0, l2);\n", " return concatBuffers(a1, a2);\n", " } else {\n", " return a1;\n", " }\n", " } else if (start < bufferEnd && end > bufferEnd) {\n", " // Overlap right\n", " // console.log(\"3\")\n", " const l1 = bufferEnd - start;\n", " const sliceStart = this.bufferLength - l1;\n", " const a1 = this.buffer.slice(sliceStart, this.bufferLength);\n", " const l2 = length - l1;\n", "\n", " if (l2 > 0) {\n", " try {\n", " this.buffer = await this.file.read(bufferEnd, this.size);\n", " this.bufferStart = bufferEnd;\n", " this.bufferLength = this.buffer.byteLength;\n", " const a2 = this.buffer.slice(0, l2);\n", " return concatBuffers(a1, a2);\n", " } catch (e) {\n", " // A \"unsatisfiable range\" error is expected here if we overlap past the end of file\n", " if (e.code && e.code === 416) {\n", " return a1;\n", " } else {\n", " throw e;\n", " }\n", " }\n", " } else {\n", " return a1;\n", " }\n", " } else {\n", " // No overlap with buffer\n", " // console.log(\"4\")\n", " this.buffer = await this.file.read(position, this.size);\n", " this.bufferStart = position;\n", " this.bufferLength = this.buffer.byteLength;\n", " return this.buffer.slice(0, length);\n", " }\n", " }\n", "\n", " }\n", " /**\n", " * concatenates 2 array buffers.\n", " * Credit: https://gist.github.com/72lions/4528834\n", " *\n", " * @private\n", " * @param {ArrayBuffers} buffer1 The first buffer.\n", " * @param {ArrayBuffers} buffer2 The second buffer.\n", " * @return {ArrayBuffers} The new ArrayBuffer created out of the two.\n", " */\n", "\n", "\n", " var concatBuffers = function (buffer1, buffer2) {\n", " var tmp = new Uint8Array(buffer1.byteLength + buffer2.byteLength);\n", " tmp.set(new Uint8Array(buffer1), 0);\n", " tmp.set(new Uint8Array(buffer2), buffer1.byteLength);\n", " return tmp.buffer;\n", " };\n", "\n", " // TODO -- big endian\n", " const BinaryParser = function (dataView, littleEndian) {\n", " this.littleEndian = littleEndian !== undefined ? littleEndian : true;\n", " this.position = 0;\n", " this.view = dataView;\n", " this.length = dataView.byteLength;\n", " };\n", "\n", " BinaryParser.prototype.available = function () {\n", " return this.length - this.position;\n", " };\n", "\n", " BinaryParser.prototype.remLength = function () {\n", " return this.length - this.position;\n", " };\n", "\n", " BinaryParser.prototype.hasNext = function () {\n", " return this.position < this.length - 1;\n", " };\n", "\n", " BinaryParser.prototype.getByte = function () {\n", " var retValue = this.view.getUint8(this.position, this.littleEndian);\n", " this.position++;\n", " return retValue;\n", " };\n", "\n", " BinaryParser.prototype.getShort = function () {\n", " var retValue = this.view.getInt16(this.position, this.littleEndian);\n", " this.position += 2;\n", " return retValue;\n", " };\n", "\n", " BinaryParser.prototype.getUShort = function () {\n", " // var byte1 = this.getByte(),\n", " // byte2 = this.getByte(),\n", " // retValue = ((byte2 << 24 >>> 16) + (byte1 << 24 >>> 24));\n", " // return retValue;\n", " //\n", " var retValue = this.view.getUint16(this.position, this.littleEndian);\n", " this.position += 2;\n", " return retValue;\n", " };\n", "\n", " BinaryParser.prototype.getInt = function () {\n", " var retValue = this.view.getInt32(this.position, this.littleEndian);\n", " this.position += 4;\n", " return retValue;\n", " };\n", "\n", " BinaryParser.prototype.getUInt = function () {\n", " var retValue = this.view.getUint32(this.position, this.littleEndian);\n", " this.position += 4;\n", " return retValue;\n", " };\n", "\n", " BinaryParser.prototype.getLong = function () {\n", " // DataView doesn't support long. So we'll try manually\n", " var b = [];\n", " b[0] = this.view.getUint8(this.position);\n", " b[1] = this.view.getUint8(this.position + 1);\n", " b[2] = this.view.getUint8(this.position + 2);\n", " b[3] = this.view.getUint8(this.position + 3);\n", " b[4] = this.view.getUint8(this.position + 4);\n", " b[5] = this.view.getUint8(this.position + 5);\n", " b[6] = this.view.getUint8(this.position + 6);\n", " b[7] = this.view.getUint8(this.position + 7);\n", " var value = 0;\n", "\n", " if (this.littleEndian) {\n", " for (var i = b.length - 1; i >= 0; i--) {\n", " value = value * 256 + b[i];\n", " }\n", " } else {\n", " for (var i = 0; i < b.length; i++) {\n", " value = value * 256 + b[i];\n", " }\n", " }\n", "\n", " this.position += 8;\n", " return value;\n", " };\n", "\n", " BinaryParser.prototype.getString = function (len) {\n", " var s = \"\";\n", " var c;\n", "\n", " while ((c = this.view.getUint8(this.position++)) != 0) {\n", " s += String.fromCharCode(c);\n", " if (len && s.length == len) break;\n", " }\n", "\n", " return s;\n", " };\n", "\n", " BinaryParser.prototype.getFixedLengthString = function (len) {\n", " var s = \"\";\n", " var i;\n", " var c;\n", "\n", " for (i = 0; i < len; i++) {\n", " c = this.view.getUint8(this.position++);\n", "\n", " if (c > 0) {\n", " s += String.fromCharCode(c);\n", " }\n", " }\n", "\n", " return s;\n", " };\n", "\n", " BinaryParser.prototype.getFixedLengthTrimmedString = function (len) {\n", " var s = \"\";\n", " var i;\n", " var c;\n", "\n", " for (i = 0; i < len; i++) {\n", " c = this.view.getUint8(this.position++);\n", "\n", " if (c > 32) {\n", " s += String.fromCharCode(c);\n", " }\n", " }\n", "\n", " return s;\n", " };\n", "\n", " BinaryParser.prototype.getFloat = function () {\n", " var retValue = this.view.getFloat32(this.position, this.littleEndian);\n", " this.position += 4;\n", " return retValue;\n", " };\n", "\n", " BinaryParser.prototype.getDouble = function () {\n", " var retValue = this.view.getFloat64(this.position, this.littleEndian);\n", " this.position += 8;\n", " return retValue;\n", " };\n", "\n", " BinaryParser.prototype.skip = function (n) {\n", " this.position += n;\n", " return this.position;\n", " };\n", " /**\n", " * Return a bgzip (bam and tabix) virtual pointer\n", " * TODO -- why isn't 8th byte used ?\n", " * @returns {*}\n", " */\n", "\n", "\n", " BinaryParser.prototype.getVPointer = function () {\n", " var position = this.position,\n", " offset = this.view.getUint8(position + 1) << 8 | this.view.getUint8(position),\n", " byte6 = (this.view.getUint8(position + 6) & 0xff) * 0x100000000,\n", " byte5 = (this.view.getUint8(position + 5) & 0xff) * 0x1000000,\n", " byte4 = (this.view.getUint8(position + 4) & 0xff) * 0x10000,\n", " byte3 = (this.view.getUint8(position + 3) & 0xff) * 0x100,\n", " byte2 = this.view.getUint8(position + 2) & 0xff,\n", " block = byte6 + byte5 + byte4 + byte3 + byte2;\n", " this.position += 8; // if (block == 0 && offset == 0) {\n", " // return null;\n", " // } else {\n", "\n", " return new VPointer(block, offset); // }\n", " };\n", "\n", " function VPointer(block, offset) {\n", " this.block = block;\n", " this.offset = offset;\n", " }\n", "\n", " VPointer.prototype.isLessThan = function (vp) {\n", " return this.block < vp.block || this.block === vp.block && this.offset < vp.offset;\n", " };\n", "\n", " VPointer.prototype.isGreaterThan = function (vp) {\n", " return this.block > vp.block || this.block === vp.block && this.offset > vp.offset;\n", " };\n", "\n", " VPointer.prototype.print = function () {\n", " return \"\" + this.block + \":\" + this.offset;\n", " };\n", "\n", " class MatrixZoomData {\n", " constructor(chr1, chr2) {\n", " this.chr1 = chr1; // chromosome index\n", "\n", " this.chr2 = chr2;\n", " }\n", "\n", " getKey() {\n", " return this.chr1.name + \"_\" + this.chr2.name + \"_\" + this.zoom.unit + \"_\" + this.zoom.binSize;\n", " }\n", "\n", " getBlockNumbers(region1, region2, version) {\n", " // Verify region chromosomes and swap if neccessary\n", " if (region1.chr == this.chr2 && region2.chr === this.chr1) {\n", " const tmp = region1;\n", " region1 = region2;\n", " region2 = tmp;\n", " }\n", "\n", " const sameChr = this.chr1 === this.chr2;\n", " const binsize = this.zoom.binSize;\n", " const blockBinCount = this.blockBinCount;\n", " const blockColumnCount = this.blockColumnCount;\n", " return version < 9 || !sameChr ? getBlockNumbersV8() : getBlockNumbersV9();\n", "\n", " function getBlockNumbersV8() {\n", " const x1 = region1.start / binsize;\n", " const x2 = region1.end / binsize;\n", " const y1 = region2.start / binsize;\n", " const y2 = region2.end / binsize;\n", " const col1 = Math.floor(x1 / blockBinCount);\n", " const col2 = Math.floor((x2 - 1) / blockBinCount);\n", " const row1 = Math.floor(y1 / blockBinCount);\n", " const row2 = Math.floor((y2 - 1) / blockBinCount);\n", " const blockNumbers = [];\n", "\n", " for (let row = row1; row <= row2; row++) {\n", " for (let column = col1; column <= col2; column++) {\n", " let blockNumber;\n", "\n", " if (sameChr && row < column) {\n", " blockNumber = column * blockColumnCount + row;\n", " } else {\n", " blockNumber = row * blockColumnCount + column;\n", " }\n", "\n", " if (!blockNumbers.includes(blockNumber)) {\n", " // possible from transposition\n", " blockNumbers.push(blockNumber);\n", " }\n", " }\n", " }\n", "\n", " return blockNumbers;\n", " }\n", "\n", " function getBlockNumbersV9() {\n", " const binX1 = region1.start / binsize;\n", " const binX2 = region1.end / binsize;\n", " const binY1 = region2.start / binsize;\n", " const binY2 = region2.end / binsize; // PAD = positionAlongDiagonal (~projected)\n", " // Depth is axis perpendicular to diagonal; nearer means closer to diagonal\n", "\n", " const translatedLowerPAD = Math.floor((binX1 + binY1) / 2 / blockBinCount);\n", " const translatedHigherPAD = Math.floor((binX2 + binY2) / 2 / blockBinCount);\n", " const translatedNearerDepth = Math.floor(Math.log2(1 + Math.abs(binX1 - binY2) / Math.sqrt(2) / blockBinCount));\n", " const translatedFurtherDepth = Math.floor(Math.log2(1 + Math.abs(binX2 - binY1) / Math.sqrt(2) / blockBinCount)); // because code above assume above diagonal; but we could be below diagonal\n", "\n", " const containsDiagonal = (binX2 - binY1) * (binX1 - binY2) < 0; // i.e. sign of (x-y) opposite on 2 corners\n", "\n", " const nearerDepth = containsDiagonal ? 0 : Math.min(translatedNearerDepth, translatedFurtherDepth);\n", " const furtherDepth = Math.max(translatedNearerDepth, translatedFurtherDepth);\n", " const blockNumbers = [];\n", "\n", " for (let depth = nearerDepth; depth <= furtherDepth; depth++) {\n", " for (let pad = translatedLowerPAD; pad <= translatedHigherPAD; pad++) {\n", " const block_number = depth * blockColumnCount + pad;\n", " blockNumbers.push(block_number);\n", " }\n", " }\n", "\n", " return blockNumbers;\n", " }\n", " }\n", "\n", " static parseMatrixZoomData(chr1, chr2, dis) {\n", " const zd = new MatrixZoomData(chr1, chr2);\n", " const unit = dis.getString();\n", " const zoomIndex = dis.getInt();\n", " const sumCounts = dis.getFloat();\n", " const occupiedCellCount = dis.getFloat();\n", " const stdDev = dis.getFloat();\n", " const percent95 = dis.getFloat();\n", " const binSize = dis.getInt();\n", " zd.blockBinCount = dis.getInt();\n", " zd.blockColumnCount = dis.getInt();\n", " const nBlocks = dis.getInt();\n", " zd.zoom = {\n", " index: zoomIndex,\n", " unit: unit,\n", " binSize: binSize\n", " };\n", " zd.blockIndex = new StaticBlockIndex(nBlocks, dis);\n", " const nBins1 = chr1.size / binSize;\n", " const nBins2 = chr2.size / binSize;\n", " const avgCount = sumCounts / nBins1 / nBins2; // <= trying to avoid overflows\n", "\n", " zd.averageCount = avgCount;\n", " zd.sumCounts = sumCounts;\n", " zd.stdDev = stdDev;\n", " zd.occupiedCellCount = occupiedCellCount;\n", " zd.percent95 = percent95;\n", " return zd;\n", " }\n", "\n", " }\n", "\n", " class StaticBlockIndex {\n", " constructor(nBlocks, dis) {\n", " this.blockIndex = {};\n", "\n", " while (nBlocks-- > 0) {\n", " const blockNumber = dis.getInt();\n", " const filePosition = dis.getLong();\n", " const size = dis.getInt();\n", " this.blockIndex[blockNumber] = {\n", " filePosition,\n", " size\n", " };\n", " }\n", " }\n", "\n", " getBlockIndexEntry(blockNumber) {\n", " return this.blockIndex[blockNumber];\n", " }\n", "\n", " }\n", "\n", " class Matrix {\n", " constructor(chr1, chr2, zoomDataList) {\n", " this.chr1 = chr1;\n", " this.chr2 = chr2;\n", " this.bpZoomData = [];\n", " this.fragZoomData = [];\n", "\n", " for (let zd of zoomDataList) {\n", " if (zd.zoom.unit === \"BP\") {\n", " this.bpZoomData.push(zd);\n", " } else {\n", " this.fragZoomData.push(zd);\n", " }\n", " }\n", " }\n", " /**\n", " * Find the best zoom level for the given bin size\n", " * @param binSize\n", " * @param unit\n", " * @returns {number}\n", " */\n", "\n", "\n", " findZoomForResolution(binSize, unit) {\n", " const zdArray = \"FRAG\" === unit ? this.fragZoomData : this.bpZoomData;\n", "\n", " for (let i = 1; i < zdArray.length; i++) {\n", " var zd = zdArray[i];\n", "\n", " if (zd.zoom.binSize < binSize) {\n", " return i - 1;\n", " }\n", " }\n", "\n", " return zdArray.length - 1;\n", " }\n", " /**\n", " * Fetch zoom data by bin size. If no matching level exists return undefined.\n", " *\n", " * @param unit\n", " * @param binSize\n", " * @param zoom\n", " * @returns {undefined|*}\n", " */\n", "\n", "\n", " getZoomData(binSize, unit) {\n", " unit = unit || \"BP\";\n", " const zdArray = unit === \"BP\" ? this.bpZoomData : this.fragZoomData;\n", "\n", " for (let i = 0; i < zdArray.length; i++) {\n", " var zd = zdArray[i];\n", "\n", " if (binSize === zd.zoom.binSize) {\n", " return zd;\n", " }\n", " }\n", "\n", " return undefined;\n", " }\n", " /**\n", " * Return zoom data by resolution index.\n", " * @param index\n", " * @param unit\n", " * @returns {*}\n", " */\n", "\n", "\n", " getZoomDataByIndex(index, unit) {\n", " const zdArray = \"FRAG\" === unit ? this.fragZoomData : this.bpZoomData;\n", " return zdArray[index];\n", " }\n", "\n", " static getKey(chrIdx1, chrIdx2) {\n", " if (chrIdx1 > chrIdx2) {\n", " const tmp = chrIdx1;\n", " chrIdx1 = chrIdx2;\n", " chrIdx2 = tmp;\n", " }\n", "\n", " return `${chrIdx1}_${chrIdx2}`;\n", " }\n", "\n", " static parseMatrix(data, chromosomes) {\n", " const dis = new BinaryParser(new DataView(data));\n", " const c1 = dis.getInt(); // Should equal chrIdx1\n", "\n", " const c2 = dis.getInt(); // Should equal chrIdx2\n", " // TODO validate this\n", "\n", " const chr1 = chromosomes[c1];\n", " const chr2 = chromosomes[c2]; // # of resolution levels (bp and frags)\n", "\n", " let nResolutions = dis.getInt();\n", " const zdList = [];\n", "\n", " while (nResolutions-- > 0) {\n", " const zd = MatrixZoomData.parseMatrixZoomData(chr1, chr2, dis);\n", " zdList.push(zd);\n", " }\n", "\n", " return new Matrix(c1, c2, zdList);\n", " }\n", "\n", " }\n", "\n", " class ContactRecord {\n", " constructor(bin1, bin2, counts) {\n", " this.bin1 = bin1;\n", " this.bin2 = bin2;\n", " this.counts = counts;\n", " }\n", "\n", " getKey() {\n", " return \"\" + this.bin1 + \"_\" + this.bin2;\n", " }\n", "\n", " }\n", "\n", " class LRU {\n", " constructor(max = 10) {\n", " this.max = max;\n", " this.map = new Map();\n", " }\n", "\n", " get(key) {\n", " let item = this.map.get(key);\n", "\n", " if (item) {\n", " // refresh key\n", " this.map.delete(key);\n", " this.map.set(key, item);\n", " }\n", "\n", " return item;\n", " }\n", "\n", " set(key, val) {\n", " // refresh key\n", " if (this.map.has(key)) this.map.delete(key); // evict oldest\n", " else if (this.map.size === this.max) {\n", " this.map.delete(this.first());\n", " }\n", " this.map.set(key, val);\n", " }\n", "\n", " has(key) {\n", " return this.map.has(key);\n", " }\n", "\n", " clear() {\n", " this.map.clear();\n", " }\n", "\n", " first() {\n", " return this.map.keys().next().value;\n", " }\n", "\n", " } //ref https://stackoverflow.com/questions/996505/lru-cache-implementation-in-javascript\n", "\n", " /*\n", " * The MIT License (MIT)\n", " *\n", " * Copyright (c) 2016-2017 The Regents of the University of California\n", " *\n", " * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and\n", " * associated documentation files (the \"Software\"), to deal in the Software without restriction, including\n", " * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n", " * copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the\n", " * following conditions:\n", " *\n", " * The above copyright notice and this permission notice shall be included in all copies or substantial\n", " * portions of the Software.\n", " *\n", " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING\n", " * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n", " * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n", " * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\n", " * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n", " * THE SOFTWARE.\n", " *\n", " */\n", " const DOUBLE$1 = 8;\n", "\n", " class NormalizationVector {\n", " constructor(file, filePosition, nValues, dataType) {\n", " this.file = file;\n", " this.filePosition = filePosition;\n", " this.nValues = nValues;\n", " this.dataType = dataType;\n", " this.cache = undefined;\n", " }\n", "\n", " async getValues(start, end) {\n", " if (!this.cache || start < this.cache.start || end > this.cache.end) {\n", " const adjustedStart = Math.max(0, start - 1000);\n", " const adjustedEnd = Math.min(this.nValues, end + 1000);\n", " const startPosition = this.filePosition + adjustedStart * this.dataType;\n", " const n = adjustedEnd - adjustedStart;\n", " const sizeInBytes = n * this.dataType;\n", " const data = await this.file.read(startPosition, sizeInBytes);\n", "\n", " if (!data) {\n", " return undefined;\n", " }\n", "\n", " const parser = new BinaryParser(new DataView(data));\n", " const values = [];\n", "\n", " for (let i = 0; i < n; i++) {\n", " values[i] = this.dataType === DOUBLE$1 ? parser.getDouble() : parser.getFloat();\n", " }\n", "\n", " this.cache = {\n", " start: adjustedStart,\n", " end: adjustedEnd,\n", " values: values\n", " };\n", " }\n", "\n", " const sliceStart = start - this.cache.start;\n", " const sliceEnd = sliceStart + (end - start);\n", " return this.cache.values.slice(sliceStart, sliceEnd);\n", " }\n", "\n", " getKey() {\n", " return NormalizationVector.getKey(this.type, this.chrIdx, this.unit, this.resolution);\n", " }\n", "\n", " static getNormalizationVectorKey(type, chrIdx, unit, resolution) {\n", " return type + \"_\" + chrIdx + \"_\" + unit + \"_\" + resolution;\n", " }\n", "\n", " }\n", "\n", " const isNode = typeof process !== 'undefined' && process.versions != null && process.versions.node != null;\n", " const Short_MIN_VALUE = -32768;\n", " const DOUBLE = 8;\n", " const FLOAT = 4;\n", " const INT = 4;\n", " const GoogleRateLimiter = new RateLimiter(100);\n", "\n", " class HicFile {\n", " constructor(args) {\n", " this.config = args;\n", " this.loadFragData = args.loadFragData;\n", " this.fragmentSitesCache = {};\n", " this.normVectorCache = new LRU(10);\n", " this.normalizationTypes = ['NONE'];\n", " this.matrixCache = new LRU(10);\n", " this.blockCache = new BlockCache(); // args may specify an io.File object, a local path (Node only), or a url\n", "\n", " if (args.file) {\n", " this.file = args.file;\n", " } else if (args.blob) {\n", " this.file = new BrowserLocalFile(args.blob);\n", " } else if (args.url || args.path && !isNode) {\n", " this.url = args.url || this.path;\n", " this.remote = true; // Google drive must be rate limited. Perhaps all remote files should be rate limited?\n", "\n", " const remoteFile = new RemoteFile(args);\n", "\n", " if (isGoogleDrive(this.url)) {\n", " this.file = new ThrottledFile(remoteFile, GoogleRateLimiter);\n", " } else {\n", " this.file = remoteFile;\n", " }\n", " } else if (args.path) {\n", " // path argument, assumed local file\n", " this.file = new NodeLocalFile({\n", " path: args.path\n", " });\n", " } else {\n", " throw Error(\"Arguments must include file, blob, url, or path\");\n", " }\n", " }\n", "\n", " async init() {\n", " if (this.initialized) {\n", " return;\n", " } else {\n", " await this.readHeaderAndFooter(); // Footer is read with header\n", " //await this.readFooter()\n", "\n", " this.initialized = true;\n", " }\n", " }\n", "\n", " async getVersion() {\n", " if (this.version === undefined) {\n", " const data = await this.file.read(0, 128);\n", "\n", " if (!data) {\n", " return undefined;\n", " }\n", "\n", " const binaryParser = new BinaryParser(new DataView(data));\n", " this.magic = binaryParser.getString();\n", " this.version = binaryParser.getInt();\n", " return this.version;\n", " } else {\n", " return this.version;\n", " }\n", " }\n", "\n", " async getMetaData() {\n", " await this.init();\n", " return this.meta;\n", " }\n", "\n", " async readHeaderAndFooter() {\n", " // Read initial fields magic, version, and footer position\n", " let data = await this.file.read(0, 16);\n", "\n", " if (!data || data.byteLength === 0) {\n", " throw Error(\"File content is empty\");\n", " }\n", "\n", " let binaryParser = new BinaryParser(new DataView(data));\n", " this.magic = binaryParser.getString();\n", " this.version = binaryParser.getInt();\n", "\n", " if (this.version < 5) {\n", " throw Error(\"Unsupported hic version: \" + this.version);\n", " }\n", "\n", " this.footerPosition = binaryParser.getLong(); // Read footer and determine file position for body section (i.e. end of header)\n", "\n", " await this.readFooter();\n", " const bodyPostion = Object.values(this.masterIndex).reduce((min, currentValue) => {\n", " return Math.min(min, currentValue.start);\n", " }, Number.MAX_VALUE);\n", " const remainingSize = bodyPostion - 16;\n", " data = await this.file.read(16, remainingSize);\n", " binaryParser = new BinaryParser(new DataView(data));\n", " this.genomeId = binaryParser.getString();\n", "\n", " if (this.version >= 9) {\n", " this.normVectorIndexPosition = binaryParser.getLong();\n", " this.normVectorIndexSize = binaryParser.getLong();\n", " }\n", "\n", " this.attributes = {};\n", " let nAttributes = binaryParser.getInt();\n", "\n", " while (nAttributes-- > 0) {\n", " this.attributes[binaryParser.getString()] = binaryParser.getString();\n", " }\n", "\n", " this.chromosomes = [];\n", " this.chromosomeIndexMap = {};\n", " let nChrs = binaryParser.getInt();\n", " let i = 0;\n", "\n", " while (nChrs-- > 0) {\n", " const chr = {\n", " index: i,\n", " name: binaryParser.getString(),\n", " size: this.version < 9 ? binaryParser.getInt() : binaryParser.getLong()\n", " };\n", "\n", " if (chr.name.toLowerCase() === \"all\") {\n", " this.wholeGenomeChromosome = chr;\n", " this.wholeGenomeResolution = Math.round(chr.size * (1000 / 500)); // Hardcoded in juicer\n", " }\n", "\n", " this.chromosomes.push(chr);\n", " this.chromosomeIndexMap[chr.name] = chr.index;\n", " i++;\n", " }\n", "\n", " this.bpResolutions = [];\n", " let nBpResolutions = binaryParser.getInt();\n", "\n", " while (nBpResolutions-- > 0) {\n", " this.bpResolutions.push(binaryParser.getInt());\n", " }\n", "\n", " if (this.loadFragData) {\n", " this.fragResolutions = [];\n", " let nFragResolutions = binaryParser.getInt();\n", "\n", " if (nFragResolutions > 0) {\n", " while (nFragResolutions-- > 0) {\n", " this.fragResolutions.push(binaryParser.getInt());\n", " } // this.sites = [];\n", " // for(let i=0; i 0) {\n", " const key = binaryParser.getString();\n", " const pos = binaryParser.getLong();\n", " const size = binaryParser.getInt();\n", " this.masterIndex[key] = {\n", " start: pos,\n", " size: size\n", " };\n", " }\n", "\n", " this.expectedValueVectors = {}; // Expected values\n", " // const nExpValues = binaryParser.readInt();\n", " // while (nExpValues-- > 0) {\n", " // type = \"NONE\";\n", " // unit = binaryParser.getString();\n", " // binSize = binaryParser.getInt();\n", " // nValues = binaryParser.getInt();\n", " // values = [];\n", " // while (nValues-- > 0) {\n", " // values.push(binaryParser.getDouble());\n", " // }\n", " //\n", " // nChrScaleFactors = binaryParser.getInt();\n", " // normFactors = {};\n", " // while (nChrScaleFactors-- > 0) {\n", " // normFactors[binaryParser.getInt()] = binaryParser.getDouble();\n", " // }\n", " //\n", " // // key = unit + \"_\" + binSize + \"_\" + type;\n", " // // NOT USED YET SO DON'T STORE\n", " // // dataset.expectedValueVectors[key] =\n", " // // new ExpectedValueFunction(type, unit, binSize, values, normFactors);\n", " // }\n", " // normalized expected values start after expected value. Add 4 for\n", "\n", " if (this.version > 5) {\n", " const skip = this.version < 9 ? 4 : 8;\n", " this.normExpectedValueVectorsPosition = this.footerPosition + skip + nBytes;\n", " }\n", "\n", " return this;\n", " }\n", "\n", " async printIndexStats() {\n", " let totalSize = 0;\n", " let maxSize = 0;\n", " let maxKey;\n", " await await this.init();\n", "\n", " for (let key of Object.keys(this.masterIndex)) {\n", " const entry = this.masterIndex[key]; // console.log(`${key}\\t${entry.start}\\t${entry.size}`)\n", "\n", " totalSize += entry.size;\n", "\n", " if (entry.size > maxSize) {\n", " maxSize = entry.size;\n", " maxKey = key;\n", " }\n", " } // console.log(`Total size = ${totalSize}`);\n", "\n", "\n", " console.log(`${maxSize} ${maxKey} ${this.config.url}`);\n", " }\n", "\n", " async getMatrix(chrIdx1, chrIdx2) {\n", " const key = Matrix.getKey(chrIdx1, chrIdx2);\n", "\n", " if (this.matrixCache.has(key)) {\n", " return this.matrixCache.get(key);\n", " } else {\n", " const matrix = await this.readMatrix(chrIdx1, chrIdx2);\n", " this.matrixCache.set(key, matrix);\n", " return matrix;\n", " }\n", " }\n", "\n", " async readMatrix(chrIdx1, chrIdx2) {\n", " await this.init();\n", "\n", " if (chrIdx1 > chrIdx2) {\n", " const tmp = chrIdx1;\n", " chrIdx1 = chrIdx2;\n", " chrIdx2 = tmp;\n", " }\n", "\n", " const key = Matrix.getKey(chrIdx1, chrIdx2);\n", " const idx = this.masterIndex[key];\n", "\n", " if (!idx) {\n", " return undefined;\n", " }\n", "\n", " const data = await this.file.read(idx.start, idx.size);\n", "\n", " if (!data) {\n", " return undefined;\n", " }\n", "\n", " return Matrix.parseMatrix(data, this.chromosomes);\n", " }\n", "\n", " async getContactRecords(normalization, region1, region2, units, binsize, allRecords = false) {\n", " await this.init();\n", " const idx1 = this.chromosomeIndexMap[this.getFileChrName(region1.chr)];\n", " const idx2 = this.chromosomeIndexMap[this.getFileChrName(region2.chr)];\n", " const transpose = idx1 > idx2 || idx1 === idx2 && region1.start >= region2.end;\n", "\n", " if (transpose) {\n", " const tmp = region1;\n", " region1 = region2;\n", " region2 = tmp;\n", " }\n", "\n", " const blocks = await this.getBlocks(region1, region2, units, binsize);\n", "\n", " if (!blocks || blocks.length === 0) {\n", " return [];\n", " }\n", "\n", " const contactRecords = [];\n", " const x1 = region1.start / binsize;\n", " const x2 = region1.end / binsize;\n", " const y1 = region2.start / binsize;\n", " const y2 = region2.end / binsize;\n", " const nvX1 = Math.floor(x1);\n", " const nvX2 = Math.ceil(x2);\n", " const nvY1 = Math.floor(y1);\n", " const nvY2 = Math.ceil(y2);\n", "\n", " for (let block of blocks) {\n", " if (block) {\n", " // An undefined block is most likely caused by a base pair range outside the chromosome\n", " let normVector1;\n", " let normVector2;\n", " let isNorm = normalization && normalization !== \"NONE\";\n", " const chr1 = this.getFileChrName(region1.chr);\n", " const chr2 = this.getFileChrName(region2.chr);\n", "\n", " if (isNorm) {\n", " const nv1 = await this.getNormalizationVector(normalization, chr1, units, binsize);\n", " const nv2 = chr1 === chr2 ? nv1 : await this.getNormalizationVector(normalization, chr2, units, binsize);\n", "\n", " if (nv1 && nv2) {\n", " normVector1 = await nv1.getValues(nvX1, nvX2);\n", " normVector2 = await nv2.getValues(nvY1, nvY2);\n", " } else {\n", " isNorm = false; // Raise message and switch pulldown\n", " }\n", " }\n", "\n", " for (let rec of block.records) {\n", " if (allRecords || rec.bin1 >= x1 && rec.bin1 < x2 && rec.bin2 >= y1 && rec.bin2 < y2) {\n", " if (isNorm) {\n", " const x = rec.bin1;\n", " const y = rec.bin2;\n", " const nvnv = normVector1[x - nvX1] * normVector2[y - nvY1];\n", "\n", " if (nvnv !== 0 && !isNaN(nvnv)) {\n", " const counts = rec.counts / nvnv;\n", " contactRecords.push(new ContactRecord(x, y, counts));\n", " }\n", " } else {\n", " contactRecords.push(rec);\n", " }\n", " }\n", " }\n", " }\n", " }\n", "\n", " return contactRecords;\n", " }\n", "\n", " async getBlocks(region1, region2, unit, binSize) {\n", " await this.init();\n", " const chr1 = this.getFileChrName(region1.chr);\n", " const chr2 = this.getFileChrName(region2.chr);\n", " const idx1 = this.chromosomeIndexMap[chr1];\n", " const idx2 = this.chromosomeIndexMap[chr2];\n", "\n", " if (idx1 === undefined) {\n", " console.log(\"No chromosome named: \" + region1.chr);\n", " return [];\n", " }\n", "\n", " if (idx2 === undefined) {\n", " console.log(\"No chromosome named: \" + region2.chr);\n", " return [];\n", " }\n", "\n", " const matrix = await this.getMatrix(idx1, idx2);\n", "\n", " if (!matrix) {\n", " console.log(\"No matrix for \" + region1.chr + \"-\" + region2.chr);\n", " return [];\n", " }\n", "\n", " const zd = matrix.getZoomData(binSize, unit);\n", "\n", " if (!zd) {\n", " let msg = `No data avalailble for resolution: ${binSize} for map ${region1.chr}-${region2.chr}`;\n", " throw new Error(msg);\n", " }\n", "\n", " const blockNumbers = zd.getBlockNumbers(region1, region2, this.version);\n", " const blocks = [];\n", " const blockNumbersToQuery = [];\n", "\n", " for (let num of blockNumbers) {\n", " if (this.blockCache.has(binSize, num)) {\n", " blocks.push(this.blockCache.get(binSize, num));\n", " } else {\n", " blockNumbersToQuery.push(num);\n", " }\n", " }\n", "\n", " const promises = blockNumbersToQuery.map(blockNumber => this.readBlock(blockNumber, zd));\n", " const newBlocks = await Promise.all(promises);\n", "\n", " for (let block of newBlocks) {\n", " if (block) {\n", " this.blockCache.set(binSize, block.blockNumber, block);\n", " }\n", " }\n", "\n", " return blocks.concat(newBlocks);\n", " }\n", "\n", " async readBlock(blockNumber, zd) {\n", " const idx = await zd.blockIndex.getBlockIndexEntry(blockNumber);\n", "\n", " if (!idx) {\n", " return undefined;\n", " } else {\n", " let data = await this.file.read(idx.filePosition, idx.size);\n", "\n", " if (!data) {\n", " return undefined;\n", " }\n", "\n", " const inflate = new Zlib.Inflate(new Uint8Array(data));\n", " const plain = inflate.decompress(); //var plain = zlib.inflateSync(Buffer.from(data)) //.decompress();\n", "\n", " data = plain.buffer;\n", " const parser = new BinaryParser(new DataView(data));\n", " const nRecords = parser.getInt();\n", " const records = [];\n", "\n", " if (this.version < 7) {\n", " for (let i = 0; i < nRecords; i++) {\n", " const binX = parser.getInt();\n", " const binY = parser.getInt();\n", " const counts = parser.getFloat();\n", " records.push(new ContactRecord(binX, binY, counts));\n", " }\n", " } else {\n", " const binXOffset = parser.getInt();\n", " const binYOffset = parser.getInt();\n", " const useFloatContact = parser.getByte() === 1;\n", " const useIntXPos = this.version < 9 ? false : parser.getByte() == 1;\n", " const useIntYPos = this.version < 9 ? false : parser.getByte() == 1;\n", " const type = parser.getByte();\n", "\n", " if (type === 1) {\n", " // List-of-rows representation\n", " const rowCount = useIntYPos ? parser.getInt() : parser.getShort();\n", "\n", " for (let i = 0; i < rowCount; i++) {\n", " const dy = useIntYPos ? parser.getInt() : parser.getShort();\n", " const binY = binYOffset + dy;\n", " const colCount = useIntXPos ? parser.getInt() : parser.getShort();\n", "\n", " for (let j = 0; j < colCount; j++) {\n", " const dx = useIntXPos ? parser.getInt() : parser.getShort();\n", " const binX = binXOffset + dx;\n", " const counts = useFloatContact ? parser.getFloat() : parser.getShort();\n", " records.push(new ContactRecord(binX, binY, counts));\n", " }\n", " }\n", " } else if (type == 2) {\n", " const nPts = parser.getInt();\n", " const w = parser.getShort();\n", "\n", " for (let i = 0; i < nPts; i++) {\n", " //int idx = (p.y - binOffset2) * w + (p.x - binOffset1);\n", " const row = Math.floor(i / w);\n", " const col = i - row * w;\n", " const bin1 = binXOffset + col;\n", " const bin2 = binYOffset + row;\n", "\n", " if (useFloatContact) {\n", " const counts = parser.getFloat();\n", "\n", " if (!isNaN(counts)) {\n", " records.push(new ContactRecord(bin1, bin2, counts));\n", " }\n", " } else {\n", " const counts = parser.getShort();\n", "\n", " if (counts != Short_MIN_VALUE) {\n", " records.push(new ContactRecord(bin1, bin2, counts));\n", " }\n", " }\n", " }\n", " } else {\n", " throw new Error(\"Unknown block type: \" + type);\n", " }\n", " }\n", "\n", " return new Block(blockNumber, zd, records, idx);\n", " }\n", " }\n", "\n", " async hasNormalizationVector(type, chr, unit, binSize) {\n", " await this.init();\n", " let chrIdx;\n", "\n", " if (Number.isInteger(chr)) {\n", " chrIdx = chr;\n", " } else {\n", " const canonicalName = this.getFileChrName(chr);\n", " chrIdx = this.chromosomeIndexMap[canonicalName];\n", " }\n", "\n", " const key = getNormalizationVectorKey(type, chrIdx, unit.toString(), binSize);\n", " const normVectorIndex = await this.getNormVectorIndex();\n", " return normVectorIndex && normVectorIndex[key];\n", " }\n", "\n", " async getNormalizationVector(type, chr, unit, binSize) {\n", " await this.init();\n", " let chrIdx;\n", "\n", " if (Number.isInteger(chr)) {\n", " chrIdx = chr;\n", " } else {\n", " const canonicalName = this.getFileChrName(chr);\n", " chrIdx = this.chromosomeIndexMap[canonicalName];\n", " }\n", "\n", " const key = getNormalizationVectorKey(type, chrIdx, unit.toString(), binSize);\n", "\n", " if (this.normVectorCache.has(key)) {\n", " return this.normVectorCache.get(key);\n", " }\n", "\n", " const normVectorIndex = await this.getNormVectorIndex();\n", "\n", " if (!normVectorIndex) {\n", " console.log(\"Normalization vectors not present in this file\");\n", " return undefined;\n", " }\n", "\n", " const idx = normVectorIndex[key];\n", "\n", " if (!idx) {\n", " // TODO -- alert in browsers\n", " console.log(\"Normalization option \" + type + \" not available at this resolution\");\n", " return undefined;\n", " }\n", "\n", " const data = await this.file.read(idx.filePosition, 8);\n", "\n", " if (!data) {\n", " return undefined;\n", " }\n", "\n", " const parser = new BinaryParser(new DataView(data));\n", " const nValues = this.version < 9 ? parser.getInt() : parser.getLong();\n", " const dataType = this.version < 9 ? DOUBLE : FLOAT;\n", " const filePosition = this.version < 9 ? idx.filePosition + 4 : idx.filePosition + 8;\n", " const nv = new NormalizationVector(this.file, filePosition, nValues, dataType);\n", " this.normVectorCache.set(key, nv);\n", " return nv;\n", " }\n", "\n", " async getNormVectorIndex() {\n", " if (this.version < 6) {\n", " return undefined;\n", " }\n", "\n", " if (!this.normVectorIndex) {\n", " // If nvi is not supplied, try reading from remote lambda service\n", " if (!this.config.nvi && this.remote && this.url) {\n", " const url = new URL(this.url);\n", " const key = encodeURIComponent(url.hostname + url.pathname);\n", " const nviResponse = await crossFetch('https://t5dvc6kn3f.execute-api.us-east-1.amazonaws.com/dev/nvi/' + key);\n", "\n", " if (nviResponse.status === 200) {\n", " const nvi = await nviResponse.text();\n", "\n", " if (nvi) {\n", " this.config.nvi = nvi;\n", " }\n", " }\n", " }\n", "\n", " if (this.config.nvi) {\n", " const nviArray = decodeURIComponent(this.config.nvi).split(\",\");\n", " const range = {\n", " start: parseInt(nviArray[0]),\n", " size: parseInt(nviArray[1])\n", " };\n", " return this.readNormVectorIndex(range);\n", " } else {\n", " try {\n", " await this.readNormExpectedValuesAndNormVectorIndex();\n", " return this.normVectorIndex;\n", " } catch (e) {\n", " if (e.code === \"416\" || e.code === 416) {\n", " // This is expected if file does not contain norm vectors\n", " this.normExpectedValueVectorsPosition = undefined;\n", " } else {\n", " console.error(e);\n", " }\n", " }\n", " }\n", " }\n", "\n", " return this.normVectorIndex;\n", " }\n", "\n", " async getNormalizationOptions() {\n", " // Normalization options are computed as a side effect of loading the index. A bit\n", " // ugly but alternatives are worse.\n", " await this.getNormVectorIndex();\n", " return this.normalizationTypes;\n", " }\n", " /**\n", " * Return a promise to load the normalization vector index\n", " *\n", " * @param dataset\n", " * @param range -- file range {position, size}\n", " * @returns Promise for the normalization vector index\n", " */\n", "\n", "\n", " async readNormVectorIndex(range) {\n", " await this.init();\n", " this.normalizationVectorIndexRange = range;\n", " const data = await this.file.read(range.start, range.size);\n", " const binaryParser = new BinaryParser(new DataView(data));\n", " this.normVectorIndex = {};\n", " let nEntries = binaryParser.getInt();\n", "\n", " while (nEntries-- > 0) {\n", " this.parseNormVectorEntry(binaryParser);\n", " }\n", "\n", " return this.normVectorIndex;\n", " }\n", " /**\n", " * This function is used when the position of the norm vector index is unknown. We must read through the expected\n", " * values to find the index\n", " *\n", " * @param dataset\n", " * @returns {Promise}\n", " */\n", "\n", "\n", " async readNormExpectedValuesAndNormVectorIndex() {\n", " await this.init();\n", "\n", " if (this.normExpectedValueVectorsPosition === undefined) {\n", " return;\n", " }\n", "\n", " const nviStart = await this.skipExpectedValues(this.normExpectedValueVectorsPosition);\n", " let byteCount = INT;\n", " let data = await this.file.read(nviStart, INT);\n", "\n", " if (data.byteLength === 0) {\n", " // This is possible if there are no norm vectors. Its a legal v8 file, though uncommon\n", " return;\n", " }\n", "\n", " const binaryParser = new BinaryParser(new DataView(data));\n", " const nEntries = binaryParser.getInt();\n", " const sizeEstimate = nEntries * 30;\n", " const range = {\n", " start: nviStart + byteCount,\n", " size: sizeEstimate\n", " };\n", " data = await this.file.read(range.start, range.size);\n", " this.normalizedExpectedValueVectors = {};\n", " this.normVectorIndex = {}; // Recursively process entries\n", "\n", " await processEntries.call(this, nEntries, data);\n", " this.config.nvi = nviStart.toString() + \",\" + byteCount;\n", "\n", " async function processEntries(nEntries, data) {\n", " const binaryParser = new BinaryParser(new DataView(data));\n", "\n", " while (nEntries-- > 0) {\n", " if (binaryParser.available() < 100) {\n", " nEntries++; // Reset counter as entry is not processed\n", "\n", " byteCount += binaryParser.position;\n", " const sizeEstimate = Math.max(1000, nEntries * 30);\n", " const range = {\n", " start: nviStart + byteCount,\n", " size: sizeEstimate\n", " };\n", " const data = await this.file.read(range.start, range.size);\n", " return processEntries.call(this, nEntries, data);\n", " }\n", "\n", " this.parseNormVectorEntry(binaryParser);\n", " }\n", "\n", " byteCount += binaryParser.position;\n", " }\n", " }\n", " /**\n", " * This function is used when the position of the norm vector index is unknown. We must read through the\n", " * normalized expected values to find the index\n", " *\n", " * @param dataset\n", " * @returns {Promise}\n", " */\n", "\n", "\n", " async skipExpectedValues(start) {\n", " const version = this.version;\n", " const file = new BufferedFile({\n", " file: this.file,\n", " size: 256000\n", " });\n", " const range = {\n", " start: start,\n", " size: INT\n", " };\n", " const data = await file.read(range.start, range.size);\n", " const binaryParser = new BinaryParser(new DataView(data));\n", " const nEntries = binaryParser.getInt(); // Total # of expected value chunks\n", "\n", " if (nEntries === 0) {\n", " return start + INT;\n", " } else {\n", " return parseNext(start + INT, nEntries);\n", " } // Skip 4 bytes for int\n", "\n", "\n", " async function parseNext(start, nEntries) {\n", " let range = {\n", " start: start,\n", " size: 500\n", " };\n", " let chunkSize = 0;\n", " let p0 = start;\n", " let data = await file.read(range.start, range.size);\n", " let binaryParser = new BinaryParser(new DataView(data));\n", " binaryParser.getString(); // type\n", "\n", " binaryParser.getString(); // unit\n", "\n", " binaryParser.getInt(); // binSize\n", "\n", " const nValues = version < 9 ? binaryParser.getInt() : binaryParser.getLong();\n", " chunkSize += binaryParser.position + nValues * (version < 9 ? DOUBLE : FLOAT);\n", " range = {\n", " start: start + chunkSize,\n", " size: INT\n", " };\n", " data = await file.read(range.start, range.size);\n", " binaryParser = new BinaryParser(new DataView(data));\n", " const nChrScaleFactors = binaryParser.getInt();\n", " chunkSize += INT + nChrScaleFactors * (INT + (version < 9 ? DOUBLE : FLOAT));\n", " nEntries--;\n", "\n", " if (nEntries === 0) {\n", " return p0 + chunkSize;\n", " } else {\n", " return parseNext(p0 + chunkSize, nEntries);\n", " }\n", " }\n", " }\n", "\n", " getZoomIndexForBinSize(binSize, unit) {\n", " unit = unit || \"BP\";\n", " let resolutionArray;\n", "\n", " if (unit === \"BP\") {\n", " resolutionArray = this.bpResolutions;\n", " } else if (unit === \"FRAG\") {\n", " resolutionArray = this.fragResolutions;\n", " } else {\n", " throw new Error(\"Invalid unit: \" + unit);\n", " }\n", "\n", " for (let i = 0; i < resolutionArray.length; i++) {\n", " if (resolutionArray[i] === binSize) return i;\n", " }\n", "\n", " return -1;\n", " }\n", "\n", " parseNormVectorEntry(binaryParser) {\n", " const type = binaryParser.getString(); //15\n", "\n", " const chrIdx = binaryParser.getInt(); //4\n", "\n", " const unit = binaryParser.getString(); //3\n", "\n", " const binSize = binaryParser.getInt(); //4\n", "\n", " const filePosition = binaryParser.getLong(); //8\n", "\n", " const sizeInBytes = this.version < 9 ? binaryParser.getInt() : binaryParser.getLong(); //4:8\n", "\n", " const key = type + \"_\" + chrIdx + \"_\" + unit + \"_\" + binSize; // TODO -- why does this not work? NormalizationVector.getNormalizationVectorKey(type, chrIdx, unit, binSize);\n", "\n", " if (!this.normalizationTypes.includes(type)) {\n", " this.normalizationTypes.push(type);\n", " }\n", "\n", " this.normVectorIndex[key] = {\n", " filePosition: filePosition,\n", " size: sizeInBytes\n", " };\n", " }\n", "\n", " getFileChrName(chrAlias) {\n", " if (this.chrAliasTable.hasOwnProperty(chrAlias)) {\n", " return this.chrAliasTable[chrAlias];\n", " } else {\n", " return chrAlias;\n", " }\n", " } // NOTE sties are not currently used\n", " // async getSites(chrName) {\n", " // let sites = this.fragmentSitesCache[chrName];\n", " // if (!sites) {\n", " // if (this.fragmentSitesIndex) {\n", " // const entry = self.fragmentSitesIndex[chrName];\n", " // if (entry && entry.nSites > 0) {\n", " // sites = await this.readSites(entry.position, entry.nSites)\n", " // this.fragmentSitesCache[chrName] = sites;\n", " // }\n", " // }\n", " // }\n", " // return sites;\n", " // }\n", " //\n", "\n", "\n", " }\n", "\n", " function getNormalizationVectorKey(type, chrIdx, unit, resolution) {\n", " return type + \"_\" + chrIdx + \"_\" + unit + \"_\" + resolution;\n", " }\n", "\n", " function isGoogleDrive(url) {\n", " return url.indexOf(\"drive.google.com\") >= 0 || url.indexOf(\"www.googleapis.com/drive\") > 0;\n", " }\n", "\n", " class Block {\n", " constructor(blockNumber, zoomData, records, idx) {\n", " this.blockNumber = blockNumber;\n", " this.zoomData = zoomData;\n", " this.records = records;\n", " this.idx = idx;\n", " }\n", "\n", " }\n", "\n", " class BlockCache {\n", " constructor() {\n", " this.resolution = undefined;\n", " this.map = new LRU(6);\n", " }\n", "\n", " set(resolution, key, value) {\n", " if (this.resolution !== resolution) {\n", " this.map.clear();\n", " }\n", "\n", " this.resolution = resolution;\n", " this.map.set(key, value);\n", " }\n", "\n", " get(resolution, key) {\n", " return this.resolution === resolution ? this.map.get(key) : undefined;\n", " }\n", "\n", " has(resolution, key) {\n", " return this.resolution === resolution && this.map.has(key);\n", " }\n", "\n", " }\n", "\n", " class Straw {\n", " constructor(config) {\n", " this.config = config;\n", " this.hicFile = new HicFile(config);\n", " }\n", "\n", " async getMetaData() {\n", " return await this.hicFile.getMetaData();\n", " } //straw [:x1:x2] [:y1:y2] \n", "\n", "\n", " async getContactRecords(normalization, region1, region2, units, binsize) {\n", " return this.hicFile.getContactRecords(normalization, region1, region2, units, binsize);\n", " }\n", "\n", " async getNormalizationOptions() {\n", " return this.hicFile.getNormalizationOptions();\n", " }\n", "\n", " async getNVI() {\n", " await this.hicFile.getNormVectorIndex();\n", " return this.hicFile.config.nvi;\n", " }\n", "\n", " async printIndexStats() {\n", " await this.hicFile.printIndexStats();\n", " }\n", "\n", " getFileChrName(chrAlias) {\n", " if (this.hicFile.chrAliasTable.hasOwnProperty(chrAlias)) {\n", " return this.hicFile.chrAliasTable[chrAlias];\n", " } else {\n", " return chrAlias;\n", " }\n", " }\n", "\n", " }\n", "\n", " /*\n", " * @author Jim Robinson Dec-2020\n", " */\n", "\n", " class IGVRemoteFile {\n", " constructor(args) {\n", " this.config = args;\n", " this.url = args.path || args.url;\n", " }\n", "\n", " async read(position, length) {\n", " const range = {\n", " start: position,\n", " size: length\n", " };\n", " return igvxhr.loadArrayBuffer(this.url, {\n", " range\n", " });\n", " }\n", "\n", " }\n", "\n", " /*\n", " * The MIT License (MIT)\n", " *\n", " * Copyright (c) 2016-2020 The Regents of the University of California\n", " *\n", " * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and\n", " * associated documentation files (the \"Software\"), to deal in the Software without restriction, including\n", " * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n", " * copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the\n", " * following conditions:\n", " *\n", " * The above copyright notice and this permission notice shall be included in all copies or substantial\n", " * portions of the Software.\n", " *\n", " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING\n", " * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n", " * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n", " * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\n", " * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n", " * THE SOFTWARE.\n", " *\n", " */\n", " const knownGenomes = {\n", " \"hg19\": [249250621, 243199373, 198022430],\n", " \"hg38\": [248956422, 242193529, 198295559],\n", " \"mm10\": [195471971, 182113224, 160039680],\n", " \"mm9\": [197195432, 181748087, 159599783],\n", " \"dm6\": [23513712, 25286936, 28110227]\n", " };\n", "\n", " class Dataset {\n", " constructor(config) {\n", " this.straw = new Straw(config);\n", " }\n", "\n", " async init() {\n", " this.hicFile = this.straw.hicFile;\n", " await this.hicFile.init();\n", " this.normalizationTypes = ['NONE'];\n", " this.genomeId = this.hicFile.genomeId;\n", " this.chromosomes = this.hicFile.chromosomes;\n", " this.bpResolutions = this.hicFile.bpResolutions;\n", " this.wholeGenomeChromosome = this.hicFile.wholeGenomeChromosome;\n", " this.wholeGenomeResolution = this.hicFile.wholeGenomeResolution; // Attempt to determine genomeId if not recognized\n", " // if (!Object.keys(knownGenomes).includes(this.genomeId)) {\n", "\n", " const tmp = matchGenome(this.chromosomes);\n", " if (tmp) this.genomeId = tmp; // }\n", " }\n", "\n", " async getContactRecords(normalization, region1, region2, units, binsize) {\n", " return this.straw.getContactRecords(normalization, region1, region2, units, binsize);\n", " }\n", "\n", " async hasNormalizationVector(type, chr, unit, binSize) {\n", " return this.straw.hicFile.hasNormalizationVector(type, chr, unit, binSize);\n", " }\n", "\n", " clearCaches() {\n", " this.colorScaleCache = {};\n", " }\n", "\n", " async getMatrix(chr1, chr2) {\n", " return this.hicFile.getMatrix(chr1, chr2);\n", " }\n", "\n", " getZoomIndexForBinSize(binSize, unit) {\n", " var i, resolutionArray;\n", " unit = unit || \"BP\";\n", "\n", " if (unit === \"BP\") {\n", " resolutionArray = this.bpResolutions;\n", " } else if (unit === \"FRAG\") {\n", " resolutionArray = this.fragResolutions;\n", " } else {\n", " throw new Error(\"Invalid unit: \" + unit);\n", " }\n", "\n", " for (i = 0; i < resolutionArray.length; i++) {\n", " if (resolutionArray[i] === binSize) return i;\n", " }\n", "\n", " return -1;\n", " }\n", "\n", " getBinSizeForZoomIndex(zoomIndex, unit) {\n", " var resolutionArray;\n", " unit = unit || \"BP\";\n", "\n", " if (unit === \"BP\") {\n", " resolutionArray = this.bpResolutions;\n", " } else if (unit === \"FRAG\") {\n", " resolutionArray = this.fragResolutions;\n", " } else {\n", " throw new Error(\"Invalid unit: \" + unit);\n", " }\n", "\n", " return resolutionArray[zoomIndex];\n", " }\n", "\n", " getChrIndexFromName(chrName) {\n", " var i;\n", "\n", " for (i = 0; i < this.chromosomes.length; i++) {\n", " if (chrName === this.chromosomes[i].name) return i;\n", " }\n", "\n", " return undefined;\n", " }\n", "\n", " compareChromosomes(otherDataset) {\n", " const chrs = this.chromosomes;\n", " const otherChrs = otherDataset.chromosomes;\n", "\n", " if (chrs.length !== otherChrs.length) {\n", " return false;\n", " }\n", "\n", " for (let i = 0; i < chrs.length; i++) {\n", " if (chrs[i].size !== otherChrs[i].size) {\n", " return false;\n", " }\n", " }\n", "\n", " return true;\n", " }\n", "\n", " isWholeGenome(chrIndex) {\n", " return this.wholeGenomeChromosome != null && this.wholeGenomeChromosome.index === chrIndex;\n", " }\n", "\n", " async getNormVectorIndex() {\n", " return this.hicFile.getNormVectorIndex();\n", " }\n", "\n", " async getNormalizationOptions() {\n", " return this.hicFile.getNormalizationOptions();\n", " }\n", " /**\n", " * Compare 2 datasets for compatibility. Compatibility is defined as from the same assembly, even if\n", " * different IDs are used (e.g. GRCh38 vs hg38).\n", " *\n", " * Trust the ID for well-known assemblies (hg19, etc). However, for others compare chromosome lengths\n", " * as its been observed that uniqueness of ID is not guaranteed.\n", " *\n", " * @param d1\n", " * @param d2\n", " */\n", "\n", "\n", " isCompatible(d2) {\n", " const id1 = this.genomeId;\n", " const id2 = d2.genomeId;\n", " return (id1 === \"hg38\" || id1 === \"GRCh38\") && (id2 === \"hg38\" || id2 === \"GRCh38\") || (id1 === \"hg19\" || id1 === \"GRCh37\") && (id2 === \"hg19\" || id2 === \"GRCh37\") || (id1 === \"mm10\" || id1 === \"GRCm38\") && (id2 === \"mm10\" || id2 === \"GRCm38\") || this.compareChromosomes(d2);\n", " }\n", "\n", " static async loadDataset(config) {\n", " // If this is a local file, use the \"blob\" field for straw\n", " if (isFile(config.url)) {\n", " config.blob = config.url;\n", " delete config.url;\n", " } else {\n", " // If this is a google url, add api KEY\n", " if (isGoogleURL(config.url)) {\n", " if (isGoogleDriveURL(config.url)) {\n", " config.url = driveDownloadURL(config.url);\n", " }\n", "\n", " const copy = Object.assign({}, config);\n", " config.file = new IGVRemoteFile(copy);\n", " }\n", " }\n", "\n", " const dataset = new Dataset(config);\n", " await dataset.init();\n", " dataset.url = config.url;\n", " return dataset;\n", " }\n", "\n", " }\n", "\n", " function matchGenome(chromosomes) {\n", " if (chromosomes.length < 4) return undefined;\n", " const keys = Object.keys(knownGenomes); // Find a candidate\n", "\n", " let candidate;\n", "\n", " for (let chr of chromosomes) {\n", " for (let key of keys) {\n", " if (knownGenomes[key].includes(chr.size)) {\n", " candidate = key;\n", " break;\n", " }\n", " }\n", " } // Confirm candidate\n", "\n", "\n", " if (candidate) {\n", " const chrSizes = new Set(chromosomes.map(chr => chr.size));\n", "\n", " for (let sz of knownGenomes[candidate]) {\n", " if (!chrSizes.has(sz)) {\n", " return undefined;\n", " }\n", " }\n", "\n", " return candidate;\n", " } else {\n", " return undefined;\n", " }\n", " }\n", "\n", " /*\n", " * The MIT License (MIT)\n", " *\n", " * Copyright (c) 2016-2017 The Regents of the University of California\n", " *\n", " * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and\n", " * associated documentation files (the \"Software\"), to deal in the Software without restriction, including\n", " * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n", " * copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the\n", " * following conditions:\n", " *\n", " * The above copyright notice and this permission notice shall be included in all copies or substantial\n", " * portions of the Software.\n", " *\n", " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING\n", " * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n", " * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n", " * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\n", " * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n", " * THE SOFTWARE.\n", " *\n", " */\n", "\n", " /**\n", " * @author Jim Robinson\n", " */\n", "\n", " /**\n", " *\n", " * @param id\n", " * @param chromosomes -- an array of hic.Chromosome objects.\n", " * @constructor\n", " */\n", " class Genome {\n", " constructor(id, chromosomes) {\n", " this.id = id;\n", " this.chromosomes = chromosomes;\n", " this.wgChromosomeNames = [];\n", " this.chromosomeLookupTable = {}; // Alias for size for igv compatibility\n", "\n", " this.genomeLength = 0;\n", "\n", " for (let c of this.chromosomes) {\n", " c.bpLength = c.size;\n", "\n", " if ('all' !== c.name.toLowerCase()) {\n", " this.genomeLength += c.size;\n", " this.wgChromosomeNames.push(c.name);\n", " }\n", " }\n", " /**\n", " * Maps chr aliases to the offical name. Deals with\n", " * 1 <-> chr1, chrM <-> MT, IV <-> chr4, etc.\n", " * @param str\n", " */\n", "\n", "\n", " var chrAliasTable = {}; // The standard mappings\n", "\n", " for (let chromosome of chromosomes) {\n", " const name = chromosome.name;\n", "\n", " if (name.startsWith(\"arm_\")) {\n", " //Special rule for aidenlab ad-hoc names for dMel\n", " const officialName = name.substring(4);\n", " chrAliasTable[officialName] = name;\n", " chrAliasTable[\"chr\" + officialName] = name;\n", " } else {\n", " const alias = name.startsWith(\"chr\") ? name.substring(3) : \"chr\" + name;\n", " chrAliasTable[alias] = name;\n", " if (name === \"chrM\") chrAliasTable[\"MT\"] = \"chrM\";\n", " if (name === \"MT\") chrAliasTable[\"chrmM\"] = \"MT\";\n", " }\n", "\n", " this.chromosomeLookupTable[name.toLowerCase()] = chromosome;\n", " }\n", "\n", " this.chrAliasTable = chrAliasTable;\n", " }\n", "\n", " getChromosomeName(str) {\n", " var chr = this.chrAliasTable[str];\n", " return chr ? chr : str;\n", " }\n", "\n", " getChromosome(str) {\n", " var chrname = this.getChromosomeName(str).toLowerCase();\n", " return this.chromosomeLookupTable[chrname];\n", " }\n", "\n", " /**\n", " * Return the genome coordinate for the give chromosome and position.\n", " */\n", " getGenomeCoordinate(chr, bp) {\n", " return this.getCumulativeOffset(chr.name) + bp;\n", " }\n", "\n", " getChromsosomeForCoordinate(bp) {\n", " var i = 0,\n", " offset = 0,\n", " l;\n", "\n", " for (i = 1; i < this.chromosomes.length; i++) {\n", " l = this.chromosomes[i].size;\n", " if (offset + l > bp) return this.chromosomes[i];\n", " offset += l;\n", " }\n", "\n", " return this.chromosomes[this.chromosomes.length - 1];\n", " }\n", " /**\n", " * Return the offset in genome coordinates (kb) of the start of the given chromosome\n", " */\n", "\n", "\n", " getCumulativeOffset(chr) {\n", " const queryChr = this.getChromosomeName(chr);\n", "\n", " if (this.cumulativeOffsets === undefined) {\n", " computeCumulativeOffsets.call(this);\n", " }\n", "\n", " return this.cumulativeOffsets[queryChr];\n", " } // Required for igv.js\n", "\n", "\n", " getGenomeLength() {\n", " return this.genomeLength;\n", " }\n", "\n", " }\n", "\n", " function computeCumulativeOffsets() {\n", " const cumulativeOffsets = {};\n", " let offset = 0; // Skip first chromosome (its chr all).\n", "\n", " for (let chromosome of this.chromosomes) {\n", " if (chromosome.name === 'all') continue;\n", " cumulativeOffsets[chromosome.name] = Math.floor(offset);\n", " offset += chromosome.size;\n", " }\n", "\n", " this.cumulativeOffsets = cumulativeOffsets;\n", " }\n", "\n", " /*\n", " * The MIT License (MIT)\n", " *\n", " * Copyright (c) 2016-2017 The Regents of the University of California\n", " *\n", " * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and\n", " * associated documentation files (the \"Software\"), to deal in the Software without restriction, including\n", " * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n", " * copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the\n", " * following conditions:\n", " *\n", " * The above copyright notice and this permission notice shall be included in all copies or substantial\n", " * portions of the Software.\n", " *\n", " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING\n", " * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n", " * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n", " * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\n", " * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n", " * THE SOFTWARE.\n", " *\n", " */\n", "\n", " class State {\n", " constructor(chr1, chr2, zoom, x, y, width, height, pixelSize, normalization) {\n", " if (Number.isNaN(pixelSize)) {\n", " pixelSize = 1;\n", " }\n", "\n", " if (chr1 !== undefined) {\n", " if (chr1 <= chr2) {\n", " this.chr1 = chr1;\n", " this.chr2 = chr2;\n", " this.x = x;\n", " this.y = y;\n", " } else {\n", " // Transpose\n", " this.chr1 = chr2;\n", " this.chr2 = chr1;\n", " this.x = y;\n", " this.y = x;\n", " }\n", "\n", " this.zoom = zoom;\n", " this.pixelSize = pixelSize;\n", " this.width = width;\n", " this.height = height;\n", "\n", " if (\"undefined\" === normalization) {\n", " console.log(\"No normalization defined !!!\");\n", " normalization = undefined;\n", " }\n", "\n", " this.normalization = normalization;\n", " }\n", " }\n", "\n", " stringify() {\n", " if (this.normalization) {\n", " return `${this.chr1},${this.chr2},${this.zoom},${this.x},${this.y},${this.width},${this.height},${this.pixelSize},${this.normalization}`;\n", " } else {\n", " return `${this.chr1},${this.chr2},${this.zoom},${this.x},${this.y},${this.width},${this.height},${this.pixelSize}`;\n", " }\n", " }\n", "\n", " clone() {\n", " return Object.assign(new State(), this);\n", " }\n", "\n", " equals(state) {\n", " var s1 = JSON.stringify(this);\n", " var s2 = JSON.stringify(state);\n", " return s1 === s2;\n", " }\n", "\n", " static parse(string) {\n", " const tokens = string.split(\",\");\n", "\n", " if (tokens.length <= 7) {\n", " // Backwards compatibility\n", " return new State(parseInt(tokens[0]), // chr1\n", " parseInt(tokens[1]), // chr2\n", " parseFloat(tokens[2]), // zoom\n", " parseFloat(tokens[3]), // x\n", " parseFloat(tokens[4]), // y\n", " defaultSize.width, // width\n", " defaultSize.height, // height\n", " parseFloat(tokens[5]), // pixelSize\n", " tokens.length > 6 ? tokens[6] : \"NONE\" // normalization\n", " );\n", " } else {\n", " return new State(parseInt(tokens[0]), // chr1\n", " parseInt(tokens[1]), // chr2\n", " parseFloat(tokens[2]), // zoom\n", " parseFloat(tokens[3]), // x\n", " parseFloat(tokens[4]), // y\n", " parseInt(tokens[5]), // width\n", " parseInt(tokens[6]), // height\n", " parseFloat(tokens[7]), // pixelSize\n", " tokens.length > 8 ? tokens[8] : \"NONE\" // normalization\n", " );\n", " }\n", " }\n", "\n", " static default(configOrUndefined) {\n", " if (configOrUndefined) {\n", " return new State(0, 0, 0, 0, 0, configOrUndefined.width, configOrUndefined.height, 1, \"NONE\");\n", " } else {\n", " return new State(0, 0, 0, 0, 0, defaultSize.width, defaultSize.height, 1, \"NONE\");\n", " }\n", " }\n", "\n", " }\n", "\n", " /*\n", " * The MIT License (MIT)\n", " *\n", " * Copyright (c) 2016-2017 The Regents of the University of California\n", " *\n", " * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and\n", " * associated documentation files (the \"Software\"), to deal in the Software without restriction, including\n", " * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n", " * copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the\n", " * following conditions:\n", " *\n", " * The above copyright notice and this permission notice shall be included in all copies or substantial\n", " * portions of the Software.\n", " *\n", " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING\n", " * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n", " * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n", " * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\n", " * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n", " * THE SOFTWARE.\n", " *\n", " */\n", "\n", " async function geneSearch(genomeId, featureName) {\n", " // Hardcode this for now\n", " const searchServiceURL = \"https://portals.broadinstitute.org/webservices/igv/locus?genome=\" + genomeId + \"&name=\" + featureName;\n", " const data = await igvxhr.loadString(searchServiceURL);\n", " var results = parseSearchResults(data);\n", "\n", " if (results.length === 0) {\n", " //alert('No feature found with name \"' + feature + '\"');\n", " return undefined;\n", " } else {\n", " // Just take first result for now\n", " return results[0];\n", " }\n", " }\n", "\n", " function parseSearchResults(data) {\n", " const lines = splitLines(data);\n", " const linesTrimmed = [];\n", " const results = [];\n", "\n", " for (let item of lines) {\n", " if (\"\" === item) ; else {\n", " linesTrimmed.push(item);\n", " }\n", " }\n", "\n", " for (let line of linesTrimmed) {\n", " // Example result - EGFR\tchr7:55,086,724-55,275,031\trefseq\n", " const tokens = line.split(\"\\t\");\n", "\n", " if (tokens.length >= 3) {\n", " results.push(tokens[1]);\n", " }\n", " }\n", "\n", " return results;\n", " }\n", "\n", " /*\n", " * The MIT License (MIT)\n", " *\n", " * Copyright (c) 2016-2017 The Regents of the University of California\n", " *\n", " * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and\n", " * associated documentation files (the \"Software\"), to deal in the Software without restriction, including\n", " * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n", " * copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the\n", " * following conditions:\n", " *\n", " * The above copyright notice and this permission notice shall be included in all copies or substantial\n", " * portions of the Software.\n", " *\n", " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING\n", " * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n", " * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n", " * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\n", " * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n", " * THE SOFTWARE.\n", " *\n", " */\n", "\n", " class LocusGoto {\n", " constructor(browser, $hic_navbar_container) {\n", " this.browser = browser;\n", " const $parent = $hic_navbar_container.find(\"div[id$='upper-hic-nav-bar-widget-container']\");\n", " this.$container = $(\"
\", {\n", " class: 'hic-chromosome-goto-container',\n", " title: 'Chromosome Goto'\n", " });\n", " $parent.append(this.$container);\n", " this.$resolution_selector = $('');\n", " this.$container.append(this.$resolution_selector);\n", " this.$resolution_selector.on('change', function (e) {\n", " browser.parseGotoInput($(this).val());\n", " $(this).blur();\n", " });\n", " this.browser.eventBus.subscribe(\"LocusChange\", this);\n", " }\n", "\n", " receiveEvent(event) {\n", " if (event.type === \"LocusChange\") {\n", " let xy;\n", " const state = event.data.state || this.browser.state;\n", " const isWholeGenome = this.browser.dataset.isWholeGenome(state.chr1);\n", "\n", " if (isWholeGenome) {\n", " xy = 'All';\n", " } else {\n", " const chr1 = this.browser.dataset.chromosomes[state.chr1];\n", " const chr2 = this.browser.dataset.chromosomes[state.chr2];\n", " const bpPerBin = this.browser.dataset.bpResolutions[state.zoom];\n", " const dimensionsPixels = this.browser.contactMatrixView.getViewDimensions();\n", " const pixelsPerBin = state.pixelSize;\n", " const startBP1 = 1 + Math.round(state.x * bpPerBin);\n", " const startBP2 = 1 + Math.round(state.y * bpPerBin);\n", " const endBP1 = Math.min(chr1.size, Math.round(dimensionsPixels.width / pixelsPerBin * bpPerBin) + startBP1 - 1);\n", " const endBP2 = Math.min(chr2.size, Math.round(dimensionsPixels.height / pixelsPerBin * bpPerBin) + startBP2 - 1);\n", " xy = chr1.name + \":\" + numberFormatter(startBP1) + \"-\" + numberFormatter(endBP1) + \" \" + chr2.name + \":\" + numberFormatter(startBP2) + \"-\" + numberFormatter(endBP2);\n", " }\n", "\n", " this.$resolution_selector.val(xy);\n", " }\n", " }\n", "\n", " }\n", "\n", " /*\n", " * The MIT License (MIT)\n", " *\n", " * Copyright (c) 2016-2017 The Regents of the University of California\n", " *\n", " * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and\n", " * associated documentation files (the \"Software\"), to deal in the Software without restriction, including\n", " * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n", " * copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the\n", " * following conditions:\n", " *\n", " * The above copyright notice and this permission notice shall be included in all copies or substantial\n", " * portions of the Software.\n", " *\n", " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING\n", " * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n", " * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n", " * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\n", " * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n", " * THE SOFTWARE.\n", " *\n", " */\n", "\n", " class ResolutionSelector {\n", " constructor(browser, $hic_navbar_container) {\n", " this.browser = browser;\n", " const $parent = $hic_navbar_container.find(\"div[id$='upper-hic-nav-bar-widget-container']\");\n", " this.$container = $(\"
\", {\n", " class: 'hic-resolution-selector-container',\n", " title: 'Resolution'\n", " });\n", " $parent.append(this.$container); // label container\n", "\n", " this.$label_container = $('
');\n", " this.$container.append(this.$label_container); // Resolution (kb)\n", "\n", " this.$label = $(\"
\");\n", " this.$label_container.append(this.$label);\n", " this.$label.text('Resolution (kb)');\n", " this.$label.hide(); // lock/unlock\n", "\n", " this.$resolution_lock = $('');\n", " this.$label_container.append(this.$resolution_lock);\n", " this.$label_container.on('click', () => {\n", " this.browser.resolutionLocked = !this.browser.resolutionLocked;\n", " this.setResolutionLock(this.browser.resolutionLocked);\n", " });\n", " this.$resolution_selector = $('', {\n", " 'type': 'text',\n", " 'placeholder': '',\n", " 'title': 'color scale input'\n", " });\n", " this.$container.append(this.$high_colorscale_input);\n", " this.$high_colorscale_input.on('change', function (e) {\n", " var numeric;\n", " numeric = numberUnFormatter($(this).val());\n", "\n", " if (isNaN(numeric)) ; else {\n", " browser.setColorScaleThreshold(numeric);\n", " }\n", " }); // threshold -\n", "\n", " let $fa = $(\"\", {\n", " class: 'fa fa-minus',\n", " 'aria-hidden': 'true',\n", " 'title': 'negative threshold'\n", " });\n", " $fa.on('click', () => this.$high_colorscale_input.val(updateThreshold(browser, 0.5)));\n", " this.$container.append($fa); // threshold +\n", "\n", " $fa = $(\"\", {\n", " class: 'fa fa-plus',\n", " 'aria-hidden': 'true',\n", " 'title': 'positive threshold'\n", " });\n", " $fa.on('click', () => this.$high_colorscale_input.val(updateThreshold(browser, 2.0)));\n", " this.$container.append($fa);\n", "\n", " const handleColorScaleEvent = event => {\n", " if (event.data instanceof ColorScale) {\n", " const {\n", " threshold\n", " } = event.data;\n", " this.$high_colorscale_input.val(threshold);\n", " paintSwatch(this.$plusButton, event.data);\n", " } else if (event.data instanceof RatioColorScale) {\n", " const {\n", " threshold,\n", " negativeScale,\n", " positiveScale\n", " } = event.data;\n", " this.$high_colorscale_input.val(threshold);\n", " paintSwatch(this.$minusButton, negativeScale);\n", " paintSwatch(this.$plusButton, positiveScale);\n", " }\n", " };\n", "\n", " this.browser.eventBus.subscribe(\"ColorScale\", handleColorScaleEvent);\n", "\n", " const handleDisplayModeEvent = event => {\n", " if (\"AOB\" === event.data || \"BOA\" === event.data) {\n", " this.$minusButton.show();\n", " const {\n", " negativeScale,\n", " positiveScale\n", " } = this.browser.contactMatrixView.ratioColorScale;\n", " paintSwatch(this.$minusButton, negativeScale);\n", " paintSwatch(this.$plusButton, positiveScale);\n", " } else {\n", " this.$minusButton.hide();\n", " paintSwatch(this.$plusButton, this.browser.contactMatrixView.colorScale);\n", " }\n", " };\n", "\n", " this.browser.eventBus.subscribe(\"DisplayMode\", handleDisplayModeEvent);\n", " this.browser.eventBus.subscribe(\"MapLoad\", ignore => {\n", " paintSwatch(this.$mapBackgroundColorpickerButton, this.browser.contactMatrixView.backgroundColor);\n", " });\n", " }\n", "\n", " }\n", "\n", " function paintSwatch($swatch, _ref) {\n", " let {\n", " r,\n", " g,\n", " b\n", " } = _ref;\n", " $swatch.get(0).style.backgroundColor = IGVColor.rgbToHex(IGVColor.rgbColor(r, g, b));\n", " }\n", "\n", " const updateThreshold = (browser, scaleFactor) => {\n", " const colorScale = browser.getColorScale();\n", " browser.setColorScaleThreshold(colorScale.getThreshold() * scaleFactor);\n", " return numberFormatter(colorScale.getThreshold());\n", " };\n", "\n", " function createColorPicker(browser, $parent, type) {\n", " let defaultColors;\n", " let colorHandler;\n", "\n", " if (undefined === type) {\n", " const {\n", " r,\n", " g,\n", " b\n", " } = ContactMatrixView.defaultBackgroundColor;\n", " defaultColors = [IGVColor.rgbToHex(IGVColor.rgbColor(r, g, b))];\n", "\n", " colorHandler = hexString => {\n", " $parent.get(0).style.backgroundColor = hexString;\n", " const [r, g, b] = IGVColor.hexToRgb(hexString).split('(').pop().split(')').shift().split(',').map(str => parseInt(str, 10));\n", " browser.contactMatrixView.setBackgroundColor({\n", " r,\n", " g,\n", " b\n", " });\n", " };\n", " } else {\n", " defaultColors = [defaultRatioColorScaleConfig.negative, defaultRatioColorScaleConfig.positive].map(_ref2 => {\n", " let {\n", " r,\n", " g,\n", " b\n", " } = _ref2;\n", " return IGVColor.rgbToHex(IGVColor.rgbColor(r, g, b));\n", " });\n", "\n", " colorHandler = hexString => {\n", " $parent.get(0).style.backgroundColor = hexString;\n", " const [r, g, b] = IGVColor.hexToRgb(hexString).split('(').pop().split(')').shift().split(',').map(str => parseInt(str, 10));\n", " browser.getColorScale().setColorComponents({\n", " r,\n", " g,\n", " b\n", " }, type);\n", " browser.repaintMatrix();\n", " };\n", " }\n", "\n", " const config = {\n", " parent: $parent.get(0),\n", " top: 64,\n", " left: 64,\n", " width: 432,\n", " defaultColors,\n", " colorHandler\n", " };\n", " return new ColorPicker(config);\n", " }\n", "\n", " function presentColorPicker(presentable, hideableA, hideableB) {\n", " hideableA.hide();\n", " hideableB.hide();\n", " presentable.show();\n", " }\n", "\n", " function colorSwatch(rgbString) {\n", " const swatch = div$1({\n", " class: 'igv-ui-color-swatch'\n", " });\n", " swatch.style.backgroundColor = IGVColor.rgbToHex(rgbString);\n", " return $(swatch);\n", " }\n", "\n", " /*\n", " * The MIT License (MIT)\n", " *\n", " * Copyright (c) 2016-2017 The Regents of the University of California\n", " *\n", " * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and\n", " * associated documentation files (the \"Software\"), to deal in the Software without restriction, including\n", " * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n", " * copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the\n", " * following conditions:\n", " *\n", " * The above copyright notice and this permission notice shall be included in all copies or substantial\n", " * portions of the Software.\n", " *\n", " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING\n", " * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n", " * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n", " * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\n", " * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n", " * THE SOFTWARE.\n", " *\n", " */\n", "\n", " class ControlMapWidget {\n", " constructor(browser, $hic_navbar_container) {\n", " this.browser = browser;\n", " const $parent = $hic_navbar_container.find(\"div[id$='lower-hic-nav-bar-widget-container']\");\n", " this.$container = $('
');\n", " this.$container.hide();\n", " $parent.append(this.$container); // select\n", "\n", " this.$select = $('');\n", " this.$normalization_selector.attr('name', 'normalization_selector');\n", " this.$normalization_selector.on('change', () => {\n", " this.browser.setNormalization(this.$normalization_selector.val());\n", " });\n", " this.$container.append(this.$normalization_selector);\n", " this.$spinner = $('
');\n", " this.$spinner.text('Loading ...');\n", " this.$container.append(this.$spinner);\n", " this.$spinner.hide();\n", " this.browser.eventBus.subscribe(\"MapLoad\", this);\n", " this.browser.eventBus.subscribe(\"NormVectorIndexLoad\", this);\n", " this.browser.eventBus.subscribe(\"NormalizationFileLoad\", this);\n", " this.browser.eventBus.subscribe(\"NormalizationExternalChange\", this);\n", " }\n", "\n", " startNotReady() {\n", " this.$normalization_selector.hide();\n", " this.$spinner.show();\n", " }\n", "\n", " stopNotReady() {\n", " this.$spinner.hide();\n", " this.$normalization_selector.show();\n", " }\n", "\n", " receiveEvent(event) {\n", " if (\"NormVectorIndexLoad\" === event.type) {\n", " updateOptions.call(this); // TODO -- end norm widget \"not ready\" state\n", "\n", " this.stopNotReady();\n", " } else if (\"NormalizationFileLoad\" === event.type) {\n", " if (event.data === \"start\") {\n", " this.startNotReady();\n", " } else {\n", " this.stopNotReady();\n", " }\n", " } else if (\"NormalizationExternalChange\" === event.type) {\n", " this.$normalization_selector.find('option').filter(function (index) {\n", " var s1 = this.value;\n", " var s2 = event.data;\n", " return s1 === s2;\n", " }).prop('selected', true);\n", " }\n", "\n", " async function updateOptions() {\n", " const norm = this.browser.state.normalization;\n", " const normalizationTypes = await this.browser.getNormalizationOptions();\n", "\n", " if (normalizationTypes) {\n", " const elements = normalizationTypes.map(function (normalization) {\n", " const label = labels[normalization] || normalization;\n", " const isSelected = norm === normalization;\n", " const titleString = label === undefined ? '' : ' title = \"' + label + '\" ';\n", " const valueString = ' value=' + normalization + (isSelected ? ' selected' : '');\n", " const labelPresentation = '   ' + label + '   ';\n", " return '' + labelPresentation + '';\n", " });\n", " this.$normalization_selector.empty();\n", " this.$normalization_selector.append(elements.join(''));\n", " }\n", " }\n", " }\n", "\n", " }\n", "\n", " /*\n", " * The MIT License (MIT)\n", " *\n", " * Copyright (c) 2016-2017 The Regents of the University of California\n", " *\n", " * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and\n", " * associated documentation files (the \"Software\"), to deal in the Software without restriction, including\n", " * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n", " * copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the\n", " * following conditions:\n", " *\n", " * The above copyright notice and this permission notice shall be included in all copies or substantial\n", " * portions of the Software.\n", " *\n", " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING\n", " * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n", " * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n", " * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\n", " * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n", " * THE SOFTWARE.\n", " *\n", " */\n", "\n", " /**\n", " * Created by dat on 3/22/17.\n", " */\n", " class ChromosomeSelectorWidget {\n", " constructor(browser, $container) {\n", " this.browser = browser;\n", " this.$x_axis_selector = $container.find(\"select[name='x-axis-selector']\");\n", " this.$y_axis_selector = $container.find(\"select[name='y-axis-selector']\");\n", " this.$x_axis_selector.on('change', () => {\n", " const str = this.$x_axis_selector.val();\n", "\n", " if (0 === parseInt(str, 10)) {\n", " this.$y_axis_selector.val(str);\n", " } else if (0 === parseInt(this.$y_axis_selector.val(), 10)) {\n", " this.$y_axis_selector.val(str);\n", " }\n", " });\n", " this.$y_axis_selector.on('change', () => {\n", " const str = this.$y_axis_selector.val();\n", "\n", " if (0 === parseInt(str, 10)) {\n", " this.$x_axis_selector.val(str);\n", " } else if (0 === parseInt(this.$x_axis_selector.val(), 10)) {\n", " this.$x_axis_selector.val(str);\n", " }\n", " });\n", " this.$y_axis_selector.next('div').on('click', async () => {\n", " const chr1Index = parseInt(this.$x_axis_selector.find('option:selected').val(), 10);\n", " const chr2Index = parseInt(this.$y_axis_selector.find('option:selected').val(), 10);\n", " await browser.setChromosomes(chr1Index, chr2Index);\n", " });\n", " this.dataLoadConfig = {\n", " receiveEvent: event => {\n", " if (event.type === \"MapLoad\") {\n", " this.respondToDataLoadWithDataset(event.data);\n", " }\n", " }\n", " };\n", " browser.eventBus.subscribe(\"MapLoad\", this.dataLoadConfig);\n", " this.locusChangeConfig = {\n", " receiveEvent: event => {\n", " if (event.type === \"LocusChange\") {\n", " this.respondToLocusChangeWithState(event.data.state);\n", " }\n", " }\n", " };\n", " browser.eventBus.subscribe(\"LocusChange\", this.locusChangeConfig);\n", " }\n", "\n", " respondToDataLoadWithDataset(dataset) {\n", " var elements, str, $xFound, $yFound;\n", " this.$x_axis_selector.empty();\n", " this.$y_axis_selector.empty();\n", " elements = dataset.chromosomes.map((_ref, index) => {\n", " let {\n", " name\n", " } = _ref;\n", " return ``;\n", " });\n", " this.$x_axis_selector.append(elements.join(''));\n", " this.$y_axis_selector.append(elements.join(''));\n", " str = 'option[value=' + this.browser.state.chr1.toString() + ']';\n", " $xFound = this.$x_axis_selector.find(str);\n", " $xFound.prop('selected', true);\n", " str = 'option[value=' + this.browser.state.chr2.toString() + ']';\n", " $yFound = this.$y_axis_selector.find(str);\n", " $yFound.prop('selected', true);\n", " }\n", "\n", " respondToLocusChangeWithState(state) {\n", " var ssx,\n", " ssy,\n", " $xFound,\n", " $yFound;\n", " $xFound = this.$x_axis_selector.find('option');\n", " $yFound = this.$y_axis_selector.find('option'); // this happens when the first dataset is loaded.\n", "\n", " if (0 === $xFound.length || 0 === $yFound.length) {\n", " return;\n", " }\n", "\n", " $xFound = this.$x_axis_selector.find('option:selected');\n", " $yFound = this.$y_axis_selector.find('option:selected');\n", " $xFound.prop('selected', false);\n", " $yFound.prop('selected', false); // chr1 = parseInt($xFound.val(), 10);\n", " // chr2 = parseInt($yFound.val(), 10);\n", " // // It is the pair of chromosomes that is important, 1-2 == 2-1, so update only if the pair does not match\n", " // if (false === ((chr1 === state.chr1 && chr2 === state.chr2) || (chr1 === state.chr2 && chr2 === state.chr1))) {\n", " // ssx = 'option[value=' + state.chr1.toString() + ']';\n", " // this.$x_axis_selector.find(ssx).attr('selected', 'selected');\n", " //\n", " // ssx = 'option[value=' + state.chr2.toString() + ']';\n", " // this.$y_axis_selector.find(ssx).attr('selected', 'selected');\n", " // }\n", "\n", " ssx = 'option[value=' + state.chr1.toString() + ']';\n", " ssy = 'option[value=' + state.chr2.toString() + ']';\n", " this.$x_axis_selector.find(ssx).prop('selected', true);\n", " this.$y_axis_selector.find(ssy).prop('selected', true);\n", " }\n", "\n", " }\n", "\n", " /*\n", " * The MIT License (MIT)\n", " *\n", " * Copyright (c) 2016-2017 The Regents of the University of California\n", " *\n", " * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and\n", " * associated documentation files (the \"Software\"), to deal in the Software without restriction, including\n", " * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n", " * copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the\n", " * following conditions:\n", " *\n", " * The above copyright notice and this permission notice shall be included in all copies or substantial\n", " * portions of the Software.\n", " *\n", " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING\n", " * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n", " * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n", " * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\n", " * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n", " * THE SOFTWARE.\n", " *\n", " */\n", "\n", " class AnnotationWidget {\n", " constructor(browser, $container, _ref, trackListRetrievalCallback) {\n", " let {\n", " title,\n", " alertMessage\n", " } = _ref;\n", " this.browser = browser;\n", " this.trackListRetrievalCallback = trackListRetrievalCallback;\n", " annotationPresentationButton.call(this, $container, alertMessage);\n", " annotationPanel.call(this, this.browser.$root, title);\n", " }\n", "\n", " updateBody(tracks) {\n", " var self = this,\n", " trackPairs,\n", " isTrack2D,\n", " zi;\n", " self.$annotationPanel.find('.hic-annotation-row-container').remove();\n", " isTrack2D = tracks[0] instanceof Track2D;\n", "\n", " if (isTrack2D) {\n", " // Reverse list to present layers in \"z\" order.\n", " for (zi = tracks.length - 1; zi >= 0; zi--) {\n", " annotationPanelRow.call(self, self.$annotationPanel, tracks[zi]);\n", " }\n", " } else {\n", " trackPairs = tracks;\n", "\n", " for (let trackRenderer of trackPairs) {\n", " annotationPanelRow.call(self, self.$annotationPanel, trackRenderer);\n", " }\n", " }\n", " }\n", "\n", " }\n", "\n", " function annotationPresentationButton($parent, alertMessage) {\n", " const $button = $parent.find(\"button\");\n", " $button.on('click', () => {\n", " const list = this.trackListRetrievalCallback();\n", "\n", " if (list.length > 0) {\n", " this.updateBody(this.trackListRetrievalCallback());\n", " this.$annotationPanel.toggle();\n", " } else {\n", " Alert$1.presentAlert(alertMessage);\n", " }\n", "\n", " this.browser.hideMenu();\n", " });\n", " }\n", "\n", " function annotationPanel($parent, title) {\n", " var self = this,\n", " $panel_header,\n", " $div,\n", " $fa;\n", " this.$annotationPanel = $('
', {\n", " class: 'hic-annotation-panel-container'\n", " });\n", " $parent.append(this.$annotationPanel); // close button container\n", "\n", " $panel_header = $('
', {\n", " class: 'hic-annotation-panel-header'\n", " });\n", " this.$annotationPanel.append($panel_header); // panel title\n", "\n", " $div = $('
');\n", " $div.text(title);\n", " $panel_header.append($div); // close button\n", "\n", " $div = $('
', {\n", " class: 'hic-menu-close-button'\n", " });\n", " $panel_header.append($div);\n", " $fa = $(\"\", {\n", " class: 'fa fa-times'\n", " });\n", " $div.append($fa);\n", " $fa.on('click', function (e) {\n", " self.$annotationPanel.toggle();\n", " }); // TODO: Continue changes for load functions added to side panel\n", " // load container\n", " // $load_container = $('
', { class:'hic-annotation-panel-load-container' });\n", " // this.$annotationPanel.append($load_container);\n", " //\n", " // // Load\n", " // $div = $('
');\n", " // $load_container.append($div);\n", " // $div.text('Load:');\n", " //\n", " // // Blah\n", " // $div = $('
');\n", " // $load_container.append($div);\n", " // $div.text('Blah');\n", " //this.$annotationPanel.draggable();\n", "\n", " makeDraggable$1(this.$annotationPanel.get(0), $panel_header.get(0));\n", " this.$annotationPanel.hide();\n", " }\n", "\n", " function annotationPanelRow($container, track) {\n", " var self = this,\n", " $colorpickerContainer,\n", " $colorpickerButton,\n", " $row_container,\n", " $row,\n", " $hideShowTrack,\n", " $deleteTrack,\n", " $upTrack,\n", " $downTrack,\n", " $e,\n", " $o,\n", " hidden_color = '#f7f7f7',\n", " str,\n", " isTrack2D,\n", " trackList,\n", " xyTrackRendererPair,\n", " trackRenderer,\n", " track1D,\n", " index,\n", " upp,\n", " dwn;\n", " isTrack2D = track instanceof Track2D;\n", " trackList = this.trackListRetrievalCallback();\n", "\n", " if (false === isTrack2D) {\n", " xyTrackRendererPair = track;\n", " track1D = xyTrackRendererPair.x.track;\n", " trackRenderer = xyTrackRendererPair.x.track.trackView;\n", " } // row container\n", "\n", "\n", " $row_container = $('
', {\n", " class: 'hic-annotation-row-container'\n", " });\n", " $container.append($row_container); // one row\n", "\n", " $row = $('
', {\n", " class: 'hic-annotation-modal-row'\n", " });\n", " $row_container.append($row); // track name\n", "\n", " $e = $(\"
\");\n", " $e.text(isTrack2D ? track.config.name : track1D.config.name);\n", " $row.append($e); // track hide/show\n", "\n", " if (isTrack2D) {\n", " str = true === track.isVisible ? 'fa fa-eye fa-lg' : 'fa fa-eye-slash fa-lg';\n", " $hideShowTrack = $(\"\", {\n", " class: str,\n", " 'aria-hidden': 'true'\n", " });\n", " $row.append($hideShowTrack);\n", " $hideShowTrack.on('click', function (e) {\n", " if ($hideShowTrack.hasClass('fa-eye')) {\n", " $hideShowTrack.addClass('fa-eye-slash');\n", " $hideShowTrack.removeClass('fa-eye');\n", " track.isVisible = false;\n", " } else {\n", " $hideShowTrack.addClass('fa-eye');\n", " $hideShowTrack.removeClass('fa-eye-slash');\n", " track.isVisible = true;\n", " }\n", "\n", " self.browser.contactMatrixView.clearImageCaches();\n", " self.browser.contactMatrixView.update();\n", " });\n", " }\n", "\n", " if (isTrack2D) {\n", " // matrix diagonal widget\n", " const $matrix_diagonal_div = $('
', {\n", " class: 'matrix-diagonal-widget-container matrix-diagonal-widget-all'\n", " });\n", " $row.append($matrix_diagonal_div);\n", " $matrix_diagonal_div.on('click.matrix_diagonal_div', e => {\n", " e.preventDefault();\n", " matrixDiagionalWidgetHandler($matrix_diagonal_div, track);\n", " });\n", " } // color swatch selector button\n", "\n", "\n", " $colorpickerButton = annotationColorSwatch(isTrack2D ? track.getColor() : track1D.color);\n", " $row.append($colorpickerButton); // color swatch selector\n", "\n", " $colorpickerContainer = createAnnotationPanelColorpickerContainer($row_container, {\n", " width: 29 * 24 + 1 + 1\n", " }, function () {\n", " $row.next('.hic-color-swatch-container').toggle();\n", " });\n", " $colorpickerButton.on('click', function (e) {\n", " $row.next('.hic-color-swatch-container').toggle();\n", " });\n", " $colorpickerContainer.hide();\n", "\n", " const colorHandler = color => {\n", " var $swatch;\n", " $swatch = $row.find('.fa-square');\n", " $swatch.css({\n", " 'color': color\n", " });\n", "\n", " if (isTrack2D) {\n", " track.color = color;\n", " self.browser.eventBus.post(HICEvent('TrackState2D', track));\n", " } else {\n", " trackRenderer.setColor(color);\n", " }\n", " };\n", "\n", " createColorSwatchSelector($colorpickerContainer.get(0), colorHandler); // track up/down\n", "\n", " $e = $('
', {\n", " class: 'up-down-arrow-container'\n", " });\n", " $row.append($e);\n", " $upTrack = $(\"\", {\n", " class: 'fa fa-arrow-up',\n", " 'aria-hidden': 'true'\n", " });\n", " $e.append($upTrack);\n", " $downTrack = $(\"\", {\n", " class: 'fa fa-arrow-down',\n", " 'aria-hidden': 'true'\n", " });\n", " $e.append($downTrack);\n", "\n", " if (1 === trackList.length) {\n", " $upTrack.css('color', hidden_color);\n", " $downTrack.css('color', hidden_color);\n", " } else if (track === trackList[0]) {\n", " $o = isTrack2D ? $downTrack : $upTrack;\n", " $o.css('color', hidden_color);\n", " } else if (track === trackList[trackList.length - 1]) {\n", " $o = isTrack2D ? $upTrack : $downTrack;\n", " $o.css('color', hidden_color);\n", " }\n", "\n", " index = trackList.indexOf(track);\n", "\n", " upp = function (e) {\n", " track = trackList[index + 1];\n", " trackList[index + 1] = trackList[index];\n", " trackList[index] = track;\n", "\n", " if (isTrack2D) {\n", " self.browser.eventBus.post(HICEvent('TrackState2D', trackList));\n", " self.updateBody(trackList);\n", " } else {\n", " self.browser.updateLayout();\n", " self.updateBody(trackList);\n", " }\n", " };\n", "\n", " dwn = function (e) {\n", " track = trackList[index - 1];\n", " trackList[index - 1] = trackList[index];\n", " trackList[index] = track;\n", "\n", " if (isTrack2D) {\n", " self.browser.eventBus.post(HICEvent('TrackState2D', trackList));\n", " self.updateBody(trackList);\n", " } else {\n", " self.browser.updateLayout();\n", " self.updateBody(trackList);\n", " }\n", " };\n", "\n", " $upTrack.on('click', isTrack2D ? upp : dwn);\n", " $downTrack.on('click', isTrack2D ? dwn : upp); // track delete\n", "\n", " $deleteTrack = $(\"\", {\n", " class: 'fa fa-trash-o fa-lg',\n", " 'aria-hidden': 'true'\n", " });\n", " $row.append($deleteTrack);\n", " $deleteTrack.on('click', function (e) {\n", " var index;\n", "\n", " if (isTrack2D) {\n", " index = trackList.indexOf(track);\n", " trackList.splice(index, 1);\n", " self.browser.contactMatrixView.clearImageCaches();\n", " self.browser.contactMatrixView.update();\n", " self.browser.eventBus.post(HICEvent('TrackLoad2D', trackList));\n", " } else {\n", " self.browser.layoutController.removeTrackXYPair(trackRenderer.trackRenderPair);\n", " }\n", "\n", " self.updateBody(trackList);\n", " });\n", " }\n", "\n", " function matrixDiagionalWidgetHandler($icon, track2D) {\n", " if ($icon.hasClass('matrix-diagonal-widget-all')) {\n", " $icon.removeClass('matrix-diagonal-widget-all');\n", " $icon.addClass('matrix-diagonal-widget-lower');\n", " track2D.displayMode = Track2DDisplaceModes.displayLowerMatrix;\n", " } else if ($icon.hasClass('matrix-diagonal-widget-lower')) {\n", " $icon.removeClass('matrix-diagonal-widget-lower');\n", " $icon.addClass('matrix-diagonal-widget-upper');\n", " track2D.displayMode = Track2DDisplaceModes.displayUpperMatrix;\n", " } else if ($icon.hasClass('matrix-diagonal-widget-upper')) {\n", " $icon.removeClass('matrix-diagonal-widget-upper');\n", " $icon.addClass('matrix-diagonal-widget-all');\n", " track2D.displayMode = Track2DDisplaceModes.displayAllMatrix;\n", " } else {\n", " $icon.addClass('matrix-diagonal-widget-all');\n", " track2D.displayMode = Track2DDisplaceModes.displayAllMatrix;\n", " }\n", " }\n", "\n", " function annotationColorSwatch(rgbString) {\n", " var $swatch, $fa;\n", " $swatch = $('
', {\n", " class: 'igv-color-swatch'\n", " });\n", " $fa = $('', {\n", " class: 'fa fa-square fa-lg',\n", " 'aria-hidden': 'true'\n", " });\n", " $swatch.append($fa);\n", " $fa.css({\n", " color: rgbString\n", " });\n", " return $swatch;\n", " }\n", "\n", " function createAnnotationPanelColorpickerContainer($parent, config, closeHandler) {\n", " var $container, $header, $fa;\n", " $container = $('
', {\n", " class: 'hic-color-swatch-container'\n", " });\n", " $parent.append($container); // width\n", "\n", " if (config && config.width) {\n", " $container.width(config.width);\n", " } // height\n", "\n", "\n", " if (config && config.height) {\n", " $container.height(config.height);\n", " } // header\n", "\n", "\n", " $header = $('
');\n", " $container.append($header); // close button\n", "\n", " $fa = $(\"\", {\n", " class: 'fa fa-times'\n", " });\n", " $header.append($fa);\n", " $fa.on('click', function (e) {\n", " closeHandler();\n", " });\n", " return $container;\n", " }\n", "\n", " /*\n", " * The MIT License (MIT)\n", " *\n", " * Copyright (c) 2016-2017 The Regents of the University of California\n", " *\n", " * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and\n", " * associated documentation files (the \"Software\"), to deal in the Software without restriction, including\n", " * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n", " * copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the\n", " * following conditions:\n", " *\n", " * The above copyright notice and this permission notice shall be included in all copies or substantial\n", " * portions of the Software.\n", " *\n", " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING\n", " * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n", " * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n", " * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\n", " * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n", " * THE SOFTWARE.\n", " *\n", " */\n", "\n", " /**\n", " * Created by dat on 3/14/17.\n", " */\n", " class SweepZoom {\n", " constructor(browser, $target) {\n", " this.browser = browser;\n", " this.$target = $target;\n", " this.$rulerSweeper = $target.find(\"div[id$='-sweep-zoom-container']\");\n", " this.$rulerSweeper.hide();\n", " this.sweepRect = {};\n", " }\n", "\n", " initialize(pageCoords) {\n", " this.anchor = pageCoords;\n", " this.coordinateFrame = this.$rulerSweeper.parent().offset();\n", " this.aspectRatio = this.$target.width() / this.$target.height();\n", " this.sweepRect.x = {\n", " x: pageCoords.x,\n", " y: pageCoords.y,\n", " width: 1,\n", " height: 1\n", " };\n", " this.clipped = {\n", " value: false\n", " };\n", " }\n", "\n", " update(pageCoords) {\n", " var anchor = this.anchor,\n", " dx = Math.abs(pageCoords.x - anchor.x),\n", " dy = Math.abs(pageCoords.y - anchor.y); // Adjust deltas to conform to aspect ratio\n", "\n", " if (dx / dy > this.aspectRatio) {\n", " dy = dx / this.aspectRatio;\n", " } else {\n", " dx = dy * this.aspectRatio;\n", " }\n", "\n", " this.sweepRect.width = dx;\n", " this.sweepRect.height = dy;\n", " this.sweepRect.x = anchor.x < pageCoords.x ? anchor.x : anchor.x - dx;\n", " this.sweepRect.y = anchor.y < pageCoords.y ? anchor.y : anchor.y - dy;\n", " this.$rulerSweeper.width(this.sweepRect.width);\n", " this.$rulerSweeper.height(this.sweepRect.height);\n", " this.$rulerSweeper.offset({\n", " left: this.sweepRect.x,\n", " top: this.sweepRect.y\n", " });\n", " this.$rulerSweeper.show();\n", " }\n", "\n", " commit() {\n", " this.$rulerSweeper.hide();\n", " const state = this.browser.state; // bp-per-bin\n", "\n", " const resolution = this.browser.resolution(); // Convert page -> offset coordinates\n", "\n", " const posX = this.sweepRect.x - this.$target.offset().left;\n", " const posY = this.sweepRect.y - this.$target.offset().top; // bp = ((bin + pixel/pixel-per-bin) / bp-per-bin)\n", "\n", " const x = (state.x + posX / state.pixelSize) * resolution;\n", " const y = (state.y + posY / state.pixelSize) * resolution; // bp = ((bin + pixel/pixel-per-bin) / bp-per-bin)\n", "\n", " const width = this.sweepRect.width / state.pixelSize * resolution;\n", " const height = this.sweepRect.height / state.pixelSize * resolution; // bp = bp + bp\n", "\n", " const xMax = x + width;\n", " const yMax = y + height;\n", " const minimumResolution = this.browser.dataset.bpResolutions[this.browser.dataset.bpResolutions.length - 1];\n", " this.browser.goto(state.chr1, x, xMax, state.chr2, y, yMax, minimumResolution);\n", " }\n", "\n", " }\n", "\n", " /*\n", " * The MIT License (MIT)\n", " *\n", " * Copyright (c) 2016-2017 The Regents of the University of California\n", " *\n", " * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and\n", " * associated documentation files (the \"Software\"), to deal in the Software without restriction, including\n", " * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n", " * copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the\n", " * following conditions:\n", " *\n", " * The above copyright notice and this permission notice shall be included in all copies or substantial\n", " * portions of the Software.\n", " *\n", " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING\n", " * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n", " * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n", " * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\n", " * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n", " * THE SOFTWARE.\n", " *\n", " */\n", " class ScrollbarWidget {\n", " constructor(browser, $x_axis_scrollbar_container, $y_axis_scrollbar_container) {\n", " this.browser = browser;\n", " this.isDragging = false; // x-axis\n", "\n", " this.$x_axis_scrollbar_container = $x_axis_scrollbar_container;\n", " this.$x_axis_scrollbar = this.$x_axis_scrollbar_container.find(\"div[id$='-x-axis-scrollbar']\");\n", " this.$x_label = this.$x_axis_scrollbar.find('div');\n", " this.$x_label.text(''); // y-axis\n", "\n", " this.$y_axis_scrollbar_container = $y_axis_scrollbar_container;\n", " this.$y_axis_scrollbar = this.$y_axis_scrollbar_container.find(\"div[id$='-y-axis-scrollbar']\");\n", " this.$y_label = this.$y_axis_scrollbar.find('.scrollbar-label-rotation-in-place');\n", " this.$y_label.text('');\n", " this.browser.eventBus.subscribe(\"LocusChange\", this);\n", " }\n", "\n", " css2Bin(chromosome, $element, attribute) {\n", " var numer, denom, percentage;\n", " numer = $element.css(attribute).slice(0, -2);\n", " denom = $element.parent().css('left' === attribute ? 'width' : 'height').slice(0, -2);\n", " percentage = parseInt(numer, 10) / parseInt(denom, 10);\n", " return percentage * chromosome.size / this.browser.dataset.bpResolutions[this.browser.state.zoom];\n", " }\n", "\n", " receiveEvent(event) {\n", " var self = this,\n", " chromosomeLengthsBin,\n", " chromosomeLengthsPixel,\n", " pixels,\n", " bins,\n", " percentage,\n", " percentages;\n", "\n", " if (!this.isDragging && event.type === \"LocusChange\") {\n", " var state = event.data.state,\n", " dataset = self.browser.dataset;\n", "\n", " if (0 === state.chr1) {\n", " this.$x_axis_scrollbar.hide();\n", " this.$y_axis_scrollbar.hide();\n", " } else {\n", " this.$x_axis_scrollbar.show();\n", " this.$y_axis_scrollbar.show();\n", " this.$x_axis_scrollbar_container.show();\n", " this.$y_axis_scrollbar_container.show();\n", " const {\n", " chr1,\n", " chr2,\n", " zoom,\n", " pixelSize,\n", " x,\n", " y\n", " } = state; // bp / bp-per-bin -> bin\n", "\n", " chromosomeLengthsBin = [chr1, chr2].map(chr => {\n", " return dataset.chromosomes[chr].size / dataset.bpResolutions[zoom];\n", " });\n", " chromosomeLengthsPixel = chromosomeLengthsBin.map(bin => bin * pixelSize);\n", " pixels = [this.browser.contactMatrixView.getViewDimensions().width, this.browser.contactMatrixView.getViewDimensions().height]; // pixel / pixel-per-bin -> bin\n", "\n", " bins = [pixels[0] / pixelSize, pixels[pixels.length - 1] / pixelSize]; // bin / bin -> percentage\n", "\n", " percentages = bins.map((bin, i) => {\n", " const binPercentage = Math.min(bin, chromosomeLengthsBin[i]) / chromosomeLengthsBin[i];\n", " const pixelPercentage = Math.min(chromosomeLengthsPixel[i], pixels[i]) / pixels[i];\n", " return Math.max(1, Math.round(100 * binPercentage * pixelPercentage));\n", " });\n", " this.$x_axis_scrollbar.css('width', `${percentages[0]}%`);\n", " this.$y_axis_scrollbar.css('height', `${percentages[percentages.length - 1]}%`); // bin / bin -> percentage\n", "\n", " percentage = Math.round(100 * x / chromosomeLengthsBin[0]);\n", " this.$x_axis_scrollbar.css('left', `${percentage}%`); // bin / bin -> percentage\n", "\n", " percentage = Math.round(100 * y / chromosomeLengthsBin[chromosomeLengthsBin.length - 1]);\n", " this.$y_axis_scrollbar.css('top', `${percentage}%`);\n", " this.$x_label.text(dataset.chromosomes[chr1].name);\n", " this.$y_label.text(dataset.chromosomes[chr2].name);\n", " }\n", " }\n", " }\n", "\n", " }\n", "\n", " /*\n", " * The MIT License (MIT)\n", " *\n", " * Copyright (c) 2016-2017 The Regents of the University of California\n", " *\n", " * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and\n", " * associated documentation files (the \"Software\"), to deal in the Software without restriction, including\n", " * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n", " * copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the\n", " * following conditions:\n", " *\n", " * The above copyright notice and this permission notice shall be included in all copies or substantial\n", " * portions of the Software.\n", " *\n", " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING\n", " * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n", " * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n", " * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\n", " * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n", " * THE SOFTWARE.\n", " *\n", " */\n", " const DEFAULT_PIXEL_SIZE = 1;\n", " const MAX_PIXEL_SIZE = 12;\n", " const DEFAULT_ANNOTATION_COLOR$1 = \"rgb(22, 129, 198)\";\n", "\n", " class HICBrowser {\n", " constructor($app_container, config) {\n", " this.config = config;\n", " this.figureMode = config.figureMode || config.miniMode; // Mini mode for backward compatibility\n", "\n", " this.resolutionLocked = false;\n", " this.eventBus = new EventBus();\n", " this.showTrackLabelAndGutter = true;\n", " this.id = `browser_${guid()}`;\n", " this.trackPairs = [];\n", " this.tracks2D = [];\n", " this.normVectorFiles = [];\n", " this.synchable = config.synchable !== false;\n", " this.synchedBrowsers = [];\n", " this.isMobile = isMobile();\n", " this.$root = $('
');\n", "\n", " if (config.width) {\n", " this.$root.css(\"width\", String(config.width));\n", " }\n", "\n", " if (config.height) {\n", " this.$root.css(\"height\", String(config.height + getNavbarHeight()));\n", " }\n", "\n", " $app_container.append(this.$root);\n", " this.layoutController = new LayoutController(this, this.$root); // nav bar related objects\n", "\n", " this.locusGoto = new LocusGoto(this, getNavbarContainer(this));\n", " this.resolutionSelector = new ResolutionSelector(this, getNavbarContainer(this));\n", " this.resolutionSelector.setResolutionLock(this.resolutionLocked);\n", " this.colorscaleWidget = new ColorScaleWidget(this, getNavbarContainer(this));\n", " this.controlMapWidget = new ControlMapWidget(this, getNavbarContainer(this));\n", " this.normalizationSelector = new NormalizationWidget(this, getNavbarContainer(this));\n", " this.inputDialog = new InputDialog($app_container.get(0), this); // contact map container related objects\n", "\n", " const sweepZoom = new SweepZoom(this, this.layoutController.getContactMatrixViewport());\n", " const scrollbarWidget = new ScrollbarWidget(this, this.layoutController.getXAxisScrollbarContainer(), this.layoutController.getYAxisScrollbarContainer());\n", " const colorScale = new ColorScale(defaultColorScaleConfig);\n", " const ratioColorScale = new RatioColorScale(defaultRatioColorScaleConfig.threshold);\n", " ratioColorScale.setColorComponents(defaultRatioColorScaleConfig.negative, '-');\n", " ratioColorScale.setColorComponents(defaultRatioColorScaleConfig.positive, '+');\n", " const backgroundColor = config.backgroundColor || ContactMatrixView.defaultBackgroundColor;\n", " this.contactMatrixView = new ContactMatrixView(this, this.layoutController.getContactMatrixViewport(), sweepZoom, scrollbarWidget, colorScale, ratioColorScale, backgroundColor);\n", " this.$menu = this.createMenu(this.$root);\n", " this.$menu.hide();\n", " this.chromosomeSelector = new ChromosomeSelectorWidget(this, this.$menu.find('.hic-chromosome-selector-widget-container'));\n", " const annotation2DWidgetConfig = {\n", " title: '2D Annotations',\n", " alertMessage: 'No 2D annotations currently loaded for this map'\n", " };\n", " this.annotation2DWidget = new AnnotationWidget(this, this.$menu.find(\".hic-annotation-presentation-button-container\"), annotation2DWidgetConfig, () => this.tracks2D); // prevent user interaction during lengthy data loads\n", "\n", " this.$user_interaction_shield = $('
', {\n", " class: 'hic-root-prevent-interaction'\n", " });\n", " this.$root.append(this.$user_interaction_shield);\n", " this.$user_interaction_shield.hide();\n", " this.hideCrosshairs(); //this.eventBus.subscribe(\"LocusChange\", this);\n", " }\n", "\n", " async init(config) {\n", " this.state = config.state ? config.state : State.default();\n", " this.pending = new Map();\n", " this.eventBus.hold();\n", " this.contactMatrixView.disableUpdates = true;\n", "\n", " try {\n", " this.contactMatrixView.startSpinner();\n", " this.$user_interaction_shield.show(); // if (!config.name) config.name = await extractName(config)\n", " // const prefix = hasControl ? \"A: \" : \"\";\n", " // browser.$contactMaplabel.text(prefix + config.name);\n", " // browser.$contactMaplabel.attr('title', config.name);\n", "\n", " await this.loadHicFile(config, true);\n", "\n", " if (config.controlUrl) {\n", " await this.loadHicControlFile({\n", " url: config.controlUrl,\n", " name: config.controlName,\n", " nvi: config.controlNvi,\n", " isControl: true\n", " }, true);\n", " }\n", "\n", " if (config.cycle) {\n", " config.displayMode = \"A\";\n", " }\n", "\n", " if (config.displayMode) {\n", " this.contactMatrixView.displayMode = config.displayMode;\n", " this.eventBus.post({\n", " type: \"DisplayMode\",\n", " data: config.displayMode\n", " });\n", " }\n", "\n", " if (config.colorScale) {\n", " // This must be done after dataset load\n", " this.contactMatrixView.setColorScale(config.colorScale);\n", " this.eventBus.post({\n", " type: \"ColorScale\",\n", " data: this.contactMatrixView.getColorScale()\n", " });\n", " }\n", "\n", " if (config.locus) {\n", " await this.parseGotoInput(config.locus);\n", " }\n", "\n", " var promises = [];\n", "\n", " if (config.tracks) {\n", " promises.push(this.loadTracks(config.tracks));\n", " }\n", "\n", " if (config.normVectorFiles) {\n", " config.normVectorFiles.forEach(function (nv) {\n", " promises.push(this.loadNormalizationFile(nv));\n", " });\n", " }\n", "\n", " await Promise.all(promises);\n", " const tmp = this.contactMatrixView.colorScaleThresholdCache;\n", " this.eventBus.release();\n", " this.contactMatrixView.colorScaleThresholdCache = tmp;\n", "\n", " if (config.cycle) {\n", " this.controlMapWidget.toggleDisplayModeCycle();\n", " } else {\n", " await this.update();\n", " }\n", " } finally {\n", " this.contactMatrixView.stopSpinner();\n", " this.$user_interaction_shield.hide();\n", " this.contactMatrixView.disableUpdates = false;\n", " this.contactMatrixView.update();\n", " }\n", " }\n", "\n", " createMenu($root) {\n", " const html = `
\n", "
\n", " \n", "
\n", "\t
\n", "\t\t
Chromosomes
\n", "
\n", " \n", " \n", "
\n", "
\n", "\t
\n", "\t
\n", "\t\t \n", "\t
\n", "
`;\n", " $root.append($(html));\n", " const $menu = $root.find(\".hic-menu\");\n", " const $fa = $root.find(\".fa-times\");\n", " $fa.on('click', () => this.toggleMenu());\n", " return $menu;\n", " }\n", "\n", " toggleTrackLabelAndGutterState() {\n", " this.showTrackLabelAndGutter = !this.showTrackLabelAndGutter;\n", " }\n", "\n", " toggleMenu() {\n", " if (this.$menu.is(':visible')) {\n", " this.hideMenu();\n", " } else {\n", " this.showMenu();\n", " }\n", " }\n", "\n", " showMenu() {\n", " this.$menu.show();\n", " }\n", "\n", " hideMenu() {\n", " this.$menu.hide();\n", " }\n", "\n", " startSpinner() {\n", " this.contactMatrixView.startSpinner();\n", " }\n", "\n", " stopSpinner() {\n", " this.contactMatrixView.stopSpinner();\n", " }\n", "\n", " async setDisplayMode(mode) {\n", " await this.contactMatrixView.setDisplayMode(mode);\n", " this.eventBus.post(HICEvent(\"DisplayMode\", mode));\n", " }\n", "\n", " getDisplayMode() {\n", " return this.contactMatrixView ? this.contactMatrixView.displayMode : undefined;\n", " }\n", "\n", " toggleDisplayMode() {\n", " this.controlMapWidget.toggleDisplayMode();\n", " }\n", "\n", " async getNormalizationOptions() {\n", " if (!this.dataset) return [];\n", " const baseOptions = await this.dataset.getNormalizationOptions();\n", "\n", " if (this.controlDataset) {\n", " let controlOptions = await this.controlDataset.getNormalizationOptions();\n", " controlOptions = new Set(controlOptions);\n", " return baseOptions.filter(base => controlOptions.has(base));\n", " } else {\n", " return baseOptions;\n", " }\n", " }\n", " /**\n", " * Return usable resolutions, that is the union of resolutions between dataset and controlDataset.\n", " * @returns {{index: *, binSize: *}[]|Array}\n", " */\n", "\n", "\n", " getResolutions() {\n", " if (!this.dataset) return [];\n", " const baseResolutions = this.dataset.bpResolutions.map(function (resolution, index) {\n", " return {\n", " index: index,\n", " binSize: resolution\n", " };\n", " });\n", "\n", " if (this.controlDataset) {\n", " let controlResolutions = new Set(this.controlDataset.bpResolutions);\n", " return baseResolutions.filter(base => controlResolutions.has(base.binSize));\n", " } else {\n", " return baseResolutions;\n", " }\n", " }\n", "\n", " isWholeGenome() {\n", " return this.dataset && this.state && this.dataset.isWholeGenome(this.state.chr1);\n", " }\n", "\n", " getColorScale() {\n", " if (!this.contactMatrixView) return undefined;\n", "\n", " switch (this.getDisplayMode()) {\n", " case 'AOB':\n", " case 'BOA':\n", " return this.contactMatrixView.ratioColorScale;\n", "\n", " case 'AMB':\n", " return this.contactMatrixView.diffColorScale;\n", "\n", " default:\n", " return this.contactMatrixView.colorScale;\n", " }\n", " }\n", "\n", " setColorScaleThreshold(threshold) {\n", " this.contactMatrixView.setColorScaleThreshold(threshold);\n", " }\n", "\n", " updateCrosshairs(_ref) {\n", " let {\n", " x,\n", " y,\n", " xNormalized,\n", " yNormalized\n", " } = _ref;\n", " const xGuide = y < 0 ? {\n", " left: 0\n", " } : {\n", " top: y,\n", " left: 0\n", " };\n", " this.contactMatrixView.$x_guide.css(xGuide);\n", " this.layoutController.$x_track_guide.css(xGuide);\n", " const yGuide = x < 0 ? {\n", " top: 0\n", " } : {\n", " top: 0,\n", " left: x\n", " };\n", " this.contactMatrixView.$y_guide.css(yGuide);\n", " this.layoutController.$y_track_guide.css(yGuide);\n", "\n", " if (this.customCrosshairsHandler) {\n", " const {\n", " x: stateX,\n", " y: stateY,\n", " pixelSize\n", " } = this.state;\n", " const resolution = this.resolution();\n", " const xBP = (stateX + x / pixelSize) * resolution;\n", " const yBP = (stateY + y / pixelSize) * resolution;\n", " let {\n", " startBP: startXBP,\n", " endBP: endXBP\n", " } = this.genomicState('x');\n", " let {\n", " startBP: startYBP,\n", " endBP: endYBP\n", " } = this.genomicState('y');\n", " this.customCrosshairsHandler({\n", " xBP,\n", " yBP,\n", " startXBP,\n", " startYBP,\n", " endXBP,\n", " endYBP,\n", " interpolantX: xNormalized,\n", " interpolantY: yNormalized\n", " });\n", " }\n", " }\n", "\n", " setCustomCrosshairsHandler(crosshairsHandler) {\n", " this.customCrosshairsHandler = crosshairsHandler;\n", " }\n", "\n", " hideCrosshairs() {\n", " this.contactMatrixView.$x_guide.hide();\n", " this.layoutController.$x_track_guide.hide();\n", " this.contactMatrixView.$y_guide.hide();\n", " this.layoutController.$y_track_guide.hide();\n", " }\n", "\n", " showCrosshairs() {\n", " this.contactMatrixView.$x_guide.show();\n", " this.layoutController.$x_track_guide.show();\n", " this.contactMatrixView.$y_guide.show();\n", " this.layoutController.$y_track_guide.show();\n", " }\n", "\n", " genomicState(axis) {\n", " let width = this.contactMatrixView.getViewDimensions().width;\n", " let resolution = this.dataset.bpResolutions[this.state.zoom];\n", " const bpp = this.dataset.chromosomes[this.state.chr1].name.toLowerCase() === \"all\" ? this.genome.getGenomeLength() / width : resolution / this.state.pixelSize;\n", " const gs = {\n", " bpp: bpp\n", " };\n", "\n", " if (axis === \"x\") {\n", " gs.chromosome = this.dataset.chromosomes[this.state.chr1];\n", " gs.startBP = this.state.x * resolution;\n", " gs.endBP = gs.startBP + bpp * width;\n", " } else {\n", " gs.chromosome = this.dataset.chromosomes[this.state.chr2];\n", " gs.startBP = this.state.y * resolution;\n", " gs.endBP = gs.startBP + bpp * this.contactMatrixView.getViewDimensions().height;\n", " }\n", "\n", " return gs;\n", " }\n", " /**\n", " * Load a list of 1D genome tracks (wig, etc).\n", " *\n", " * NOTE: public API function\n", " *\n", " * @param configs\n", " */\n", "\n", "\n", " async loadTracks(configs) {\n", " // If loading a single track remember its name, for error message\n", " const errorPrefix = 1 === configs.length ? \"Error loading track \" + configs[0].name : \"Error loading tracks\";\n", "\n", " try {\n", " this.contactMatrixView.startSpinner();\n", " const tracks = [];\n", " const promises2D = [];\n", "\n", " for (let config of\n", " /*trackConfigurations*/\n", " configs) {\n", " const fileName = isFile(config.url) ? config.url.name : await getFilenameExtended(config.url);\n", "\n", " if (!config.format) {\n", " config.format = inferFileFormat(fileName);\n", " }\n", "\n", " if (\"annotation\" === config.type && config.color === DEFAULT_ANNOTATION_COLOR$1) {\n", " delete config.color;\n", " }\n", "\n", " if (config.max === undefined) {\n", " config.autoscale = true;\n", " } // config.height = (\"annotation\" === config.type) ? annotationTrackHeight : wigTrackHeight;\n", "\n", "\n", " config.height = trackHeight;\n", "\n", " if (undefined === config.format || \"bedpe\" === config.format || \"interact\" === config.format) {\n", " // Assume this is a 2D track\n", " promises2D.push(Track2D.loadTrack2D(config, this.genome));\n", " } else {\n", " const track = await igv.createTrack(config, this);\n", " tracks.push(track);\n", " }\n", " }\n", "\n", " if (tracks.length > 0) {\n", " this.layoutController.tracksLoaded(tracks);\n", " const $gear_container = $('.hic-igv-right-hand-gutter');\n", "\n", " if (true === this.showTrackLabelAndGutter) {\n", " $gear_container.show();\n", " } else {\n", " $gear_container.hide();\n", " }\n", "\n", " await this.updateLayout();\n", " }\n", "\n", " if (promises2D.length > 0) {\n", " const tracks2D = await Promise.all(promises2D);\n", "\n", " if (tracks2D && tracks2D.length > 0) {\n", " this.tracks2D = this.tracks2D.concat(tracks2D);\n", " this.eventBus.post(HICEvent(\"TrackLoad2D\", this.tracks2D));\n", " }\n", " }\n", " } catch (error) {\n", " presentError(errorPrefix, error);\n", " console.error(error);\n", " } finally {\n", " this.contactMatrixView.stopSpinner();\n", " }\n", " }\n", "\n", " async loadNormalizationFile(url) {\n", " if (!this.dataset) return;\n", " this.eventBus.post(HICEvent(\"NormalizationFileLoad\", \"start\"));\n", " const normVectors = await this.dataset.hicFile.readNormalizationVectorFile(url, this.dataset.chromosomes);\n", "\n", " for (let type of normVectors['types']) {\n", " if (!this.dataset.normalizationTypes) {\n", " this.dataset.normalizationTypes = [];\n", " }\n", "\n", " if (!this.dataset.normalizationTypes.includes(type)) {\n", " this.dataset.normalizationTypes.push(type);\n", " }\n", "\n", " this.eventBus.post(HICEvent(\"NormVectorIndexLoad\", this.dataset));\n", " }\n", "\n", " return normVectors;\n", " }\n", " /**\n", " * Render the XY pair of tracks.\n", " *\n", " * @param xy\n", " */\n", "\n", "\n", " async renderTrackXY(xy) {\n", " try {\n", " this.startSpinner();\n", " await xy.updateViews();\n", " } finally {\n", " this.stopSpinner();\n", " }\n", " }\n", "\n", " reset() {\n", " this.layoutController.removeAllTrackXYPairs();\n", " this.contactMatrixView.clearImageCaches();\n", " this.tracks2D = [];\n", " this.tracks = [];\n", " this.$contactMaplabel.text(\"\");\n", " this.$contactMaplabel.attr('title', \"\");\n", " this.$controlMaplabel.text(\"\");\n", " this.$controlMaplabel.attr('title', \"\");\n", " this.dataset = undefined;\n", " this.controlDataset = undefined;\n", " this.unsyncSelf();\n", " }\n", "\n", " clearSession() {\n", " // Clear current datasets.\n", " this.dataset = undefined;\n", " this.controlDataset = undefined;\n", " this.setDisplayMode('A');\n", " this.unsyncSelf();\n", " }\n", " /**\n", " * Remove reference to self from all synchedBrowsers lists.\n", " */\n", "\n", "\n", " unsyncSelf() {\n", " const allBrowsers = getAllBrowsers();\n", "\n", " for (let b of allBrowsers) {\n", " b.unsync(this);\n", " }\n", " }\n", " /**\n", " * Remove the reference browser from this collection of synched browsers\n", " * @param browser\n", " */\n", "\n", "\n", " unsync(browser) {\n", " this.synchedBrowsers = this.synchedBrowsers.filter(b => b != browser);\n", " }\n", " /**\n", " * Load a .hic file\n", " *\n", " * NOTE: public API function\n", " *\n", " * @return a promise for a dataset\n", " * @param config\n", " * @param noUpdates\n", " */\n", "\n", "\n", " async loadHicFile(config, noUpdates) {\n", " if (!config.url) {\n", " console.log(\"No .hic url specified\");\n", " return undefined;\n", " }\n", "\n", " this.clearSession();\n", "\n", " try {\n", " this.contactMatrixView.startSpinner();\n", "\n", " if (!noUpdates) {\n", " this.$user_interaction_shield.show();\n", " }\n", "\n", " const name = extractName(config);\n", " const prefix = this.controlDataset ? \"A: \" : \"\";\n", " this.$contactMaplabel.text(prefix + name);\n", " this.$contactMaplabel.attr('title', name);\n", " config.name = name;\n", " this.dataset = await Dataset.loadDataset(config);\n", " this.dataset.name = name;\n", " const previousGenomeId = this.genome ? this.genome.id : undefined;\n", " this.genome = new Genome(this.dataset.genomeId, this.dataset.chromosomes); // TODO -- this is not going to work with browsers on different assemblies on the same page.\n", " //igv.browser.genome = this.genome;\n", "\n", " if (this.genome.id !== previousGenomeId) {\n", " EventBus.globalBus.post(HICEvent(\"GenomeChange\", this.genome.id));\n", " }\n", "\n", " this.eventBus.post(HICEvent(\"MapLoad\", this.dataset));\n", "\n", " if (config.state) {\n", " if (!config.state.hasOwnProperty(\"chr1\")) {\n", " config.state = State.parse(config.state);\n", " }\n", "\n", " await this.setState(config.state);\n", " } else if (config.synchState && this.canBeSynched(config.synchState)) {\n", " this.syncState(config.synchState);\n", " } else {\n", " await this.setState(State.default(this.config));\n", " } // Initiate loading of the norm vector index, but don't block if the \"nvi\" parameter is not available.\n", " // Let it load in the background\n", "\n", "\n", " const eventBus = this.eventBus; // If nvi is not supplied, try reading it from remote lambda service\n", "\n", " if (!config.nvi && typeof config.url === \"string\") {\n", " const url = new URL(config.url);\n", " const key = encodeURIComponent(url.hostname + url.pathname);\n", " const nviResponse = await fetch('https://t5dvc6kn3f.execute-api.us-east-1.amazonaws.com/dev/nvi/' + key);\n", "\n", " if (nviResponse.status === 200) {\n", " const nvi = await nviResponse.text();\n", "\n", " if (nvi) {\n", " config.nvi = nvi;\n", " }\n", " }\n", " }\n", "\n", " if (config.nvi) {\n", " await this.dataset.getNormVectorIndex(config);\n", " eventBus.post(HICEvent(\"NormVectorIndexLoad\", this.dataset));\n", " } else {\n", " const dataset = this.dataset;\n", " dataset.getNormVectorIndex(config).then(function (normVectorIndex) {\n", " if (!config.isControl) {\n", " eventBus.post(HICEvent(\"NormVectorIndexLoad\", dataset));\n", " }\n", " });\n", " }\n", "\n", " syncBrowsers(); // Find a browser to sync with, if any\n", "\n", " const compatibleBrowsers = getAllBrowsers().filter(b => b != this && b.dataset && b.dataset.isCompatible(this.dataset));\n", "\n", " if (compatibleBrowsers.length > 0) {\n", " this.syncState(compatibleBrowsers[0].getSyncState());\n", " }\n", " } catch (error) {\n", " this.$contactMaplabel.text('');\n", " this.$contactMaplabel.attr('');\n", " config.name = name;\n", " throw error;\n", " } finally {\n", " this.stopSpinner();\n", "\n", " if (!noUpdates) {\n", " this.$user_interaction_shield.hide();\n", " }\n", " }\n", " }\n", " /**\n", " * Load a .hic file for a control map\n", " *\n", " * NOTE: public API function\n", " *\n", " * @return a promise for a dataset\n", " * @param config\n", " */\n", "\n", "\n", " async loadHicControlFile(config, noUpdates) {\n", " try {\n", " this.$user_interaction_shield.show();\n", " this.contactMatrixView.startSpinner();\n", " this.controlUrl = config.url;\n", " const name = extractName(config);\n", " config.name = name;\n", " const controlDataset = await Dataset.loadDataset(config);\n", " controlDataset.name = name;\n", "\n", " if (!this.dataset || this.dataset.isCompatible(controlDataset)) {\n", " this.controlDataset = controlDataset;\n", "\n", " if (this.dataset) {\n", " this.$contactMaplabel.text(\"A: \" + this.dataset.name);\n", " }\n", "\n", " this.$controlMaplabel.text(\"B: \" + controlDataset.name);\n", " this.$controlMaplabel.attr('title', controlDataset.name); //For the control dataset, block until the norm vector index is loaded\n", "\n", " await controlDataset.getNormVectorIndex(config);\n", " this.eventBus.post(HICEvent(\"ControlMapLoad\", this.controlDataset));\n", "\n", " if (!noUpdates) {\n", " this.update();\n", " }\n", " } else {\n", " Alert$1.presentAlert('\"B\" map genome (' + controlDataset.genomeId + ') does not match \"A\" map genome (' + this.genome.id + ')');\n", " }\n", " } finally {\n", " this.$user_interaction_shield.hide();\n", " this.stopSpinner();\n", " }\n", " }\n", "\n", " async parseGotoInput(string) {\n", " let xLocus;\n", " let yLocus;\n", " const loci = string.split(' ');\n", "\n", " if (loci.length === 1) {\n", " xLocus = this.parseLocusString(loci[0]);\n", " yLocus = xLocus;\n", " } else {\n", " xLocus = this.parseLocusString(loci[0]);\n", " yLocus = this.parseLocusString(loci[1]);\n", " if (yLocus === undefined) yLocus = xLocus;\n", " }\n", "\n", " if (xLocus === undefined) {\n", " // Try a gene name search.\n", " const result = await geneSearch(this.genome.id, loci[0].trim());\n", "\n", " if (result) {\n", " Globals.selectedGene = loci[0].trim();\n", " xLocus = this.parseLocusString(result);\n", " yLocus = xLocus;\n", " this.state.selectedGene = Globals.selectedGene;\n", " this.goto(xLocus.chr, xLocus.start, xLocus.end, yLocus.chr, yLocus.start, yLocus.end, 5000);\n", " } else {\n", " alert('No feature found with name \"' + loci[0] + '\"');\n", " }\n", " } else {\n", " if (xLocus.wholeChr && yLocus.wholeChr) {\n", " await this.setChromosomes(xLocus.chr, yLocus.chr);\n", " } else {\n", " this.goto(xLocus.chr, xLocus.start, xLocus.end, yLocus.chr, yLocus.start, yLocus.end);\n", " }\n", " }\n", " }\n", "\n", " /**\n", " * Find the closest matching zoom index (index into the dataset resolutions array) for the target resolution.\n", " *\n", " * resolutionAraay can be either\n", " * (1) an array of bin sizes\n", " * (2) an array of objects with index and bin size\n", " * @param targetResolution\n", " * @param resolutionArray\n", " * @returns {number}\n", " */\n", " findMatchingZoomIndex(targetResolution, resolutionArray) {\n", " const isObject = resolutionArray.length > 0 && resolutionArray[0].index !== undefined;\n", "\n", " for (let z = resolutionArray.length - 1; z > 0; z--) {\n", " const binSize = isObject ? resolutionArray[z].binSize : resolutionArray[z];\n", " const index = isObject ? resolutionArray[z].index : z;\n", "\n", " if (binSize >= targetResolution) {\n", " return index;\n", " }\n", " }\n", "\n", " return 0;\n", " }\n", "\n", " parseLocusString(locus) {\n", " const locusObject = {};\n", " const parts = locus.trim().split(':');\n", " const chromosome = this.genome.getChromosome(parts[0].toLowerCase());\n", "\n", " if (!chromosome) {\n", " return undefined;\n", " } else {\n", " locusObject.chr = chromosome.index;\n", " }\n", "\n", " if (parts.length === 1) {\n", " // Chromosome name only\n", " locusObject.start = 0;\n", " locusObject.end = this.dataset.chromosomes[locusObject.chr].size;\n", " locusObject.wholeChr = true;\n", " } else {\n", " const extent = parts[1].split(\"-\");\n", " let numeric = extent[0].replace(/\\,/g, '');\n", " locusObject.start = isNaN(numeric) ? undefined : parseInt(numeric, 10) - 1;\n", "\n", " if (extent.length == 2) {\n", " numeric = extent[1].replace(/\\,/g, '');\n", " locusObject.end = isNaN(numeric) ? undefined : parseInt(numeric, 10);\n", " }\n", " }\n", "\n", " return locusObject;\n", " }\n", "\n", " /**\n", " * @param scaleFactor Values range from greater then 1 to decimal values less then one\n", " * Value > 1 are magnification (zoom in)\n", " * Decimal values (.9, .75, .25, etc.) are minification (zoom out)\n", " * @param anchorPx -- anchor position in pixels (should not move after transformation)\n", " * @param anchorPy\n", " */\n", " async pinchZoom(anchorPx, anchorPy, scaleFactor) {\n", " if (this.state.chr1 === 0) {\n", " await this.zoomAndCenter(1, anchorPx, anchorPy);\n", " } else {\n", " try {\n", " this.startSpinner();\n", " const bpResolutions = this.getResolutions();\n", " const currentResolution = bpResolutions[this.state.zoom];\n", " let newBinSize;\n", " let newZoom;\n", " let newPixelSize;\n", " let zoomChanged;\n", "\n", " if (this.resolutionLocked || this.state.zoom === bpResolutions.length - 1 && scaleFactor > 1 || this.state.zoom === 0 && scaleFactor < 1) {\n", " // Can't change resolution level, must adjust pixel size\n", " newBinSize = currentResolution.binSize;\n", " newPixelSize = Math.min(MAX_PIXEL_SIZE, this.state.pixelSize * scaleFactor);\n", " newZoom = this.state.zoom;\n", " zoomChanged = false;\n", " } else {\n", " const targetBinSize = currentResolution.binSize / this.state.pixelSize / scaleFactor;\n", " newZoom = this.findMatchingZoomIndex(targetBinSize, bpResolutions);\n", " newBinSize = bpResolutions[newZoom].binSize;\n", " zoomChanged = newZoom !== this.state.zoom;\n", " newPixelSize = Math.min(MAX_PIXEL_SIZE, newBinSize / targetBinSize);\n", " }\n", "\n", " const z = await this.minZoom(this.state.chr1, this.state.chr2);\n", "\n", " if (!this.resolutionLocked && scaleFactor < 1 && newZoom < z) {\n", " // Zoom out to whole genome\n", " this.setChromosomes(0, 0);\n", " } else {\n", " const minPS = await this.minPixelSize(this.state.chr1, this.state.chr2, newZoom);\n", " const state = this.state;\n", " newPixelSize = Math.max(newPixelSize, minPS); // Genomic anchor -- this position should remain at anchorPx, anchorPy after state change\n", "\n", " const gx = (state.x + anchorPx / state.pixelSize) * currentResolution.binSize;\n", " const gy = (state.y + anchorPy / state.pixelSize) * currentResolution.binSize;\n", " state.x = gx / newBinSize - anchorPx / newPixelSize;\n", " state.y = gy / newBinSize - anchorPy / newPixelSize;\n", " state.zoom = newZoom;\n", " state.pixelSize = newPixelSize;\n", " this.clamp();\n", " this.contactMatrixView.zoomIn(anchorPx, anchorPy, 1 / scaleFactor);\n", " let event = HICEvent(\"LocusChange\", {\n", " state: state,\n", " resolutionChanged: zoomChanged,\n", " chrChanged: false\n", " });\n", " this.update(event); //this.eventBus.post(event);\n", " }\n", " } finally {\n", " this.stopSpinner();\n", " }\n", " }\n", " } // TODO -- apparently not used. Where is this handled?\n", " // async wheelClickZoom(direction, centerPX, centerPY) {\n", " // if (this.resolutionLocked || this.state.chr1 === 0) { // Resolution locked OR whole genome view\n", " // this.zoomAndCenter(direction, centerPX, centerPY);\n", " // } else {\n", " // const z = await minZoom.call(this, this.state.chr1, this.state.chr2)\n", " // var newZoom = this.state.zoom + direction;\n", " // if (direction < 0 && newZoom < z) {\n", " // this.setChromosomes(0, 0);\n", " // } else {\n", " // this.zoomAndCenter(direction, centerPX, centerPY);\n", " // }\n", " //\n", " // }\n", " // }\n", " // Zoom in response to a double-click\n", "\n", " /**\n", " * Zoom and center on bins at given screen coordinates. Supports double-click zoom, pinch zoom.\n", " * @param direction\n", " * @param centerPX screen coordinate to center on\n", " * @param centerPY screen coordinate to center on\n", " * @returns {Promise}\n", " */\n", "\n", "\n", " async zoomAndCenter(direction, centerPX, centerPY) {\n", " if (!this.dataset) return;\n", "\n", " if (this.dataset.isWholeGenome(this.state.chr1) && direction > 0) {\n", " // jump from whole genome to chromosome\n", " const genomeCoordX = centerPX * this.dataset.wholeGenomeResolution / this.state.pixelSize;\n", " const genomeCoordY = centerPY * this.dataset.wholeGenomeResolution / this.state.pixelSize;\n", " const chrX = this.genome.getChromsosomeForCoordinate(genomeCoordX);\n", " const chrY = this.genome.getChromsosomeForCoordinate(genomeCoordY);\n", " this.setChromosomes(chrX.index, chrY.index);\n", " } else {\n", " const resolutions = this.getResolutions();\n", " const viewDimensions = this.contactMatrixView.getViewDimensions();\n", " const dx = centerPX === undefined ? 0 : centerPX - viewDimensions.width / 2;\n", " const dy = centerPY === undefined ? 0 : centerPY - viewDimensions.height / 2;\n", " this.state.x += dx / this.state.pixelSize;\n", " this.state.y += dy / this.state.pixelSize;\n", "\n", " if (this.resolutionLocked || direction > 0 && this.state.zoom === resolutions[resolutions.length - 1].index || direction < 0 && this.state.zoom === resolutions[0].index) {\n", " const minPS = await this.minPixelSize(this.state.chr1, this.state.chr2, this.state.zoom);\n", " const state = this.state;\n", " const newPixelSize = Math.max(Math.min(MAX_PIXEL_SIZE, state.pixelSize * (direction > 0 ? 2 : 0.5)), minPS);\n", " const shiftRatio = (newPixelSize - state.pixelSize) / newPixelSize;\n", " state.pixelSize = newPixelSize;\n", " state.x += shiftRatio * (viewDimensions.width / state.pixelSize);\n", " state.y += shiftRatio * (viewDimensions.height / state.pixelSize);\n", " this.clamp();\n", " let event = HICEvent(\"LocusChange\", {\n", " state: state,\n", " resolutionChanged: false,\n", " chrChanged: false\n", " });\n", " this.update(event); //this.eventBus.post(event);\n", " } else {\n", " let i;\n", "\n", " for (i = 0; i < resolutions.length; i++) {\n", " if (this.state.zoom === resolutions[i].index) break;\n", " }\n", "\n", " if (i !== undefined) {\n", " const newZoom = resolutions[i + direction].index;\n", " this.setZoom(newZoom);\n", " }\n", " }\n", " }\n", " }\n", " /**\n", " * Set the current zoom state and opctionally center over supplied coordinates.\n", " * @param zoom - index to the datasets resolution array (dataset.bpResolutions)\n", " * @returns {Promise}\n", " */\n", "\n", "\n", " async setZoom(zoom) {\n", " try {\n", " // Shift x,y to maintain center, if possible\n", " const bpResolutions = this.dataset.bpResolutions;\n", " const currentResolution = bpResolutions[this.state.zoom];\n", " const viewDimensions = this.contactMatrixView.getViewDimensions();\n", " const xCenter = this.state.x + viewDimensions.width / (2 * this.state.pixelSize); // center in bins\n", "\n", " const yCenter = this.state.y + viewDimensions.height / (2 * this.state.pixelSize); // center in bins\n", "\n", " const newResolution = bpResolutions[zoom];\n", " const newXCenter = xCenter * (currentResolution / newResolution);\n", " const newYCenter = yCenter * (currentResolution / newResolution);\n", " const minPS = await this.minPixelSize(this.state.chr1, this.state.chr2, zoom);\n", " const state = this.state;\n", " const newPixelSize = Math.max(DEFAULT_PIXEL_SIZE, minPS);\n", " const zoomChanged = state.zoom !== zoom;\n", " state.zoom = zoom;\n", " state.x = Math.max(0, newXCenter - viewDimensions.width / (2 * newPixelSize));\n", " state.y = Math.max(0, newYCenter - viewDimensions.height / (2 * newPixelSize));\n", " state.pixelSize = newPixelSize;\n", " this.clamp();\n", " await this.contactMatrixView.zoomIn();\n", " let event = HICEvent(\"LocusChange\", {\n", " state: state,\n", " resolutionChanged: zoomChanged,\n", " chrChanged: false\n", " });\n", " this.update(event); //this.eventBus.post(event);\n", " } finally {// this.stopSpinner()\n", " }\n", " }\n", "\n", " async setChromosomes(chr1, chr2) {\n", " try {\n", " this.startSpinner();\n", " const z = await this.minZoom(chr1, chr2);\n", " this.state.chr1 = Math.min(chr1, chr2);\n", " this.state.chr2 = Math.max(chr1, chr2);\n", " this.state.x = 0;\n", " this.state.y = 0;\n", " this.state.zoom = z;\n", " const minPS = await this.minPixelSize(this.state.chr1, this.state.chr2, this.state.zoom);\n", " this.state.pixelSize = Math.min(100, Math.max(DEFAULT_PIXEL_SIZE, minPS));\n", " let event = HICEvent(\"LocusChange\", {\n", " state: this.state,\n", " resolutionChanged: true,\n", " chrChanged: true\n", " });\n", " this.update(event); //this.eventBus.post(event);\n", " } finally {\n", " this.stopSpinner();\n", " }\n", " }\n", " /**\n", " * Called on loading tracks\n", " * @returns {Promise}\n", " */\n", "\n", "\n", " async updateLayout() {\n", " this.clamp();\n", " this.trackPairs.forEach(function (xyTrackRenderPair, index) {\n", " sync(xyTrackRenderPair.x, index);\n", " sync(xyTrackRenderPair.y, index);\n", " });\n", "\n", " function sync(trackRenderer, index) {\n", " trackRenderer.$viewport.css({\n", " order: index\n", " });\n", " trackRenderer.syncCanvas();\n", " }\n", "\n", " this.layoutController.xAxisRuler.update();\n", " this.layoutController.yAxisRuler.update();\n", " await this.update();\n", " }\n", " /**\n", " * Set the matrix state. Used to restore state from a bookmark\n", " * @param state browser state\n", " */\n", "\n", "\n", " async setState(state) {\n", " const chrChanged = !this.state || this.state.chr1 !== state.chr1 || this.state.chr2 !== state.chr2;\n", " this.state = state; // Possibly adjust pixel size\n", "\n", " const minPS = await this.minPixelSize(this.state.chr1, this.state.chr2, this.state.zoom);\n", " this.state.pixelSize = Math.max(state.pixelSize, minPS);\n", " let hicEvent = new HICEvent(\"LocusChange\", {\n", " state: this.state,\n", " resolutionChanged: true,\n", " chrChanged: chrChanged\n", " });\n", " this.update(hicEvent);\n", " this.eventBus.post(hicEvent);\n", " }\n", " /**\n", " * Return a modified state object used for synching. Other datasets might have different chromosome ordering\n", " * and resolution arrays\n", " */\n", "\n", "\n", " getSyncState() {\n", " return {\n", " chr1Name: this.dataset.chromosomes[this.state.chr1].name,\n", " chr2Name: this.dataset.chromosomes[this.state.chr2].name,\n", " binSize: this.dataset.bpResolutions[this.state.zoom],\n", " binX: this.state.x,\n", " // TODO -- tranlsate to lower right corner\n", " binY: this.state.y,\n", " pixelSize: this.state.pixelSize\n", " };\n", " }\n", " /**\n", " * Return true if this browser can be synched to the given state\n", " * @param syncState\n", " */\n", "\n", "\n", " canBeSynched(syncState) {\n", " if (false === this.synchable) return false; // Explicitly not synchable\n", "\n", " return this.dataset && this.dataset.getChrIndexFromName(syncState.chr1Name) !== undefined && this.dataset.getChrIndexFromName(syncState.chr2Name) !== undefined;\n", " }\n", " /**\n", " * Used to synch state with other browsers\n", " * @param state browser state\n", " */\n", "\n", "\n", " syncState(syncState) {\n", " if (!syncState || false === this.synchable) return;\n", " if (!this.dataset) return;\n", " var chr1 = this.genome.getChromosome(syncState.chr1Name),\n", " chr2 = this.genome.getChromosome(syncState.chr2Name),\n", " zoom = this.dataset.getZoomIndexForBinSize(syncState.binSize, \"BP\"),\n", " x = syncState.binX,\n", " y = syncState.binY,\n", " pixelSize = syncState.pixelSize;\n", "\n", " if (!(chr1 && chr2)) {\n", " return; // Can't be synched.\n", " }\n", "\n", " if (zoom === undefined) {\n", " // Get the closest zoom available and adjust pixel size. TODO -- cache this somehow\n", " zoom = this.findMatchingZoomIndex(syncState.binSize, this.dataset.bpResolutions); // Compute equivalent in basepairs / pixel\n", "\n", " pixelSize = syncState.pixelSize / syncState.binSize * this.dataset.bpResolutions[zoom]; // Translate bins so that origin is unchanged in basepairs\n", "\n", " x = syncState.binX / syncState.pixelSize * pixelSize;\n", " y = syncState.binY / syncState.pixelSize * pixelSize;\n", "\n", " if (pixelSize > MAX_PIXEL_SIZE) {\n", " console.log(\"Cannot synch map \" + this.dataset.name + \" (resolution \" + syncState.binSize + \" not available)\");\n", " return;\n", " }\n", " }\n", "\n", " const zoomChanged = this.state.zoom !== zoom;\n", " const chrChanged = this.state.chr1 !== chr1.index || this.state.chr2 !== chr2.index;\n", " this.state.chr1 = chr1.index;\n", " this.state.chr2 = chr2.index;\n", " this.state.zoom = zoom;\n", " this.state.x = x;\n", " this.state.y = y;\n", " this.state.pixelSize = pixelSize;\n", " let event = HICEvent(\"LocusChange\", {\n", " state: this.state,\n", " resolutionChanged: zoomChanged,\n", " chrChanged: chrChanged\n", " }, false);\n", " this.update(event); //this.eventBus.post(event);\n", " }\n", "\n", " setNormalization(normalization) {\n", " this.state.normalization = normalization;\n", " this.eventBus.post(HICEvent(\"NormalizationChange\", this.state.normalization));\n", " }\n", "\n", " shiftPixels(dx, dy) {\n", " if (!this.dataset) return;\n", " this.state.x += dx / this.state.pixelSize;\n", " this.state.y += dy / this.state.pixelSize;\n", " this.clamp();\n", " const locusChangeEvent = HICEvent(\"LocusChange\", {\n", " state: this.state,\n", " resolutionChanged: false,\n", " dragging: true,\n", " chrChanged: false\n", " });\n", " locusChangeEvent.dragging = true;\n", " this.update(locusChangeEvent);\n", " this.eventBus.post(locusChangeEvent);\n", " }\n", "\n", " goto(chr1, bpX, bpXMax, chr2, bpY, bpYMax, minResolution) {\n", " const viewDimensions = this.contactMatrixView.getViewDimensions();\n", " const bpResolutions = this.getResolutions();\n", " const currentResolution = bpResolutions[this.state.zoom].binSize;\n", " const viewWidth = viewDimensions.width;\n", "\n", " if (!bpXMax) {\n", " bpX = Math.max(0, bpX - Math.floor(viewWidth * currentResolution / 2));\n", " bpXMax = bpX + viewWidth * currentResolution;\n", " }\n", "\n", " if (!bpYMax) {\n", " bpY = Math.max(0, bpY - Math.floor(viewDimensions.height * currentResolution / 2));\n", " bpYMax = bpY + viewDimensions.height * currentResolution;\n", " }\n", "\n", " let targetResolution = Math.max((bpXMax - bpX) / viewDimensions.width, (bpYMax - bpY) / viewDimensions.height);\n", "\n", " if (minResolution && targetResolution < minResolution) {\n", " const maxExtent = viewWidth * minResolution;\n", " const xCenter = (bpX + bpXMax) / 2;\n", " const yCenter = (bpY + bpYMax) / 2;\n", " bpX = Math.max(xCenter - maxExtent / 2);\n", " bpY = Math.max(0, yCenter - maxExtent / 2);\n", " targetResolution = minResolution;\n", " }\n", "\n", " let zoomChanged;\n", " let newZoom;\n", "\n", " if (true === this.resolutionLocked && minResolution === undefined) {\n", " zoomChanged = false;\n", " newZoom = this.state.zoom;\n", " } else {\n", " newZoom = this.findMatchingZoomIndex(targetResolution, bpResolutions);\n", " zoomChanged = newZoom !== this.state.zoom;\n", " }\n", "\n", " const newResolution = bpResolutions[newZoom].binSize;\n", " const newPixelSize = Math.min(MAX_PIXEL_SIZE, Math.max(1, newResolution / targetResolution));\n", " const newXBin = bpX / newResolution;\n", " const newYBin = bpY / newResolution;\n", " const chrChanged = !this.state || this.state.chr1 !== chr1 || this.state.chr2 !== chr2;\n", " this.state.chr1 = chr1;\n", " this.state.chr2 = chr2;\n", " this.state.zoom = newZoom;\n", " this.state.x = newXBin;\n", " this.state.y = newYBin;\n", " this.state.pixelSize = newPixelSize;\n", " this.contactMatrixView.clearImageCaches();\n", " let event = HICEvent(\"LocusChange\", {\n", " state: this.state,\n", " resolutionChanged: zoomChanged,\n", " chrChanged: chrChanged\n", " });\n", " this.update(event); //this.eventBus.post(event);\n", " }\n", "\n", " clamp() {\n", " var viewDimensions = this.contactMatrixView.getViewDimensions(),\n", " chr1Length = this.dataset.chromosomes[this.state.chr1].size,\n", " chr2Length = this.dataset.chromosomes[this.state.chr2].size,\n", " binSize = this.dataset.bpResolutions[this.state.zoom],\n", " maxX = chr1Length / binSize - viewDimensions.width / this.state.pixelSize,\n", " maxY = chr2Length / binSize - viewDimensions.height / this.state.pixelSize; // Negative maxX, maxY indicates pixelSize is not enough to fill view. In this case we clamp x, y to 0,0\n", "\n", " maxX = Math.max(0, maxX);\n", " maxY = Math.max(0, maxY);\n", " this.state.x = Math.min(Math.max(0, this.state.x), maxX);\n", " this.state.y = Math.min(Math.max(0, this.state.y), maxY);\n", " }\n", "\n", " receiveEvent(event) {// if (\"LocusChange\" === event.type) {\n", " // if (event.propogate) {\n", " // for (let browser of this.synchedBrowsers) {\n", " // browser.syncState(this.getSyncState());\n", " // }\n", " // }\n", " // this.update(event);\n", " // }\n", " }\n", " /**\n", " * Update the maps and tracks. This method can be called from the browser event thread repeatedly, for example\n", " * while mouse dragging. If called while an update is in progress queue the event for processing later. It\n", " * is only neccessary to queue the most recent recently received event, so a simple instance variable will suffice\n", " * for the queue.\n", " *\n", " * @param event\n", " */\n", "\n", "\n", " async update(event) {\n", " if (this.updating) {\n", " const type = event ? event.type : \"NONE\";\n", " this.pending.set(type, event);\n", " } else {\n", " this.updating = true;\n", "\n", " try {\n", " this.startSpinner();\n", "\n", " if (event !== undefined && \"LocusChange\" === event.type) {\n", " this.layoutController.xAxisRuler.locusChange(event);\n", " this.layoutController.yAxisRuler.locusChange(event);\n", " }\n", "\n", " const promises = [];\n", "\n", " for (let xyTrackRenderPair of this.trackPairs) {\n", " promises.push(this.renderTrackXY(xyTrackRenderPair));\n", " }\n", "\n", " promises.push(this.contactMatrixView.update(event));\n", " await Promise.all(promises);\n", "\n", " if (event && event.propogate) {\n", " let syncState1 = this.getSyncState();\n", "\n", " for (let browser of this.synchedBrowsers) {\n", " browser.syncState(syncState1);\n", " }\n", " }\n", " } finally {\n", " this.updating = false;\n", "\n", " if (this.pending.size > 0) {\n", " const events = [];\n", "\n", " for (let [k, v] of this.pending) {\n", " events.push(v);\n", " }\n", "\n", " this.pending.clear();\n", "\n", " for (let e of events) {\n", " this.update(e);\n", " }\n", " }\n", "\n", " if (event) {\n", " // possibly, unless update was called from an event post (infinite loop)\n", " this.eventBus.post(event);\n", " }\n", "\n", " this.stopSpinner();\n", " }\n", " }\n", " }\n", "\n", " repaintMatrix() {\n", " this.contactMatrixView.imageTileCache = {};\n", " this.contactMatrixView.initialImage = undefined;\n", " this.contactMatrixView.update();\n", " }\n", "\n", " resolution() {\n", " return this.dataset.bpResolutions[this.state.zoom];\n", " }\n", "\n", " toJSON() {\n", " if (!(this.dataset && this.dataset.url)) return \"{}\"; // URL is required\n", "\n", " const jsonOBJ = {};\n", " jsonOBJ.backgroundColor = this.contactMatrixView.stringifyBackgroundColor();\n", " jsonOBJ.url = this.dataset.url;\n", "\n", " if (this.dataset.name) {\n", " jsonOBJ.name = this.dataset.name;\n", " }\n", "\n", " jsonOBJ.state = this.state.stringify();\n", " jsonOBJ.colorScale = this.contactMatrixView.getColorScale().stringify();\n", "\n", " if (Globals.selectedGene) {\n", " jsonOBJ.selectedGene = Globals.selectedGene;\n", " }\n", "\n", " let nviString = getNviString(this.dataset);\n", "\n", " if (nviString) {\n", " jsonOBJ.nvi = nviString;\n", " }\n", "\n", " if (this.controlDataset) {\n", " jsonOBJ.controlUrl = this.controlUrl;\n", "\n", " if (this.controlDataset.name) {\n", " jsonOBJ.controlName = this.controlDataset.name;\n", " }\n", "\n", " const displayMode = this.getDisplayMode();\n", "\n", " if (displayMode) {\n", " jsonOBJ.displayMode = this.getDisplayMode();\n", " }\n", "\n", " nviString = getNviString(this.controlDataset);\n", "\n", " if (nviString) {\n", " jsonOBJ.controlNvi = nviString;\n", " }\n", "\n", " if (this.controlMapWidget.getDisplayModeCycle() !== undefined) {\n", " jsonOBJ.cycle = true;\n", " }\n", " }\n", "\n", " if (this.trackPairs.length > 0 || this.tracks2D.length > 0) {\n", " let tracks = [];\n", " jsonOBJ.tracks = tracks;\n", "\n", " for (let trackRenderer of this.trackPairs) {\n", " const track = trackRenderer.x.track;\n", " const config = track.config;\n", "\n", " if (typeof config.url === \"string\") {\n", " const t = {\n", " url: config.url\n", " };\n", "\n", " if (track.name) {\n", " t.name = track.name;\n", " }\n", "\n", " if (track.dataRange) {\n", " t.min = track.dataRange.min;\n", " t.max = track.dataRange.max;\n", " }\n", "\n", " if (track.color) {\n", " t.color = track.color;\n", " }\n", "\n", " tracks.push(t);\n", " }\n", " }\n", "\n", " for (let track of this.tracks2D) {\n", " var config = track.config;\n", "\n", " if (typeof config.url === \"string\") {\n", " const t = {\n", " url: config.url\n", " };\n", "\n", " if (track.name) {\n", " t.name = track.name;\n", " }\n", "\n", " if (track.color) {\n", " t.color = track.color;\n", " }\n", "\n", " tracks.push(t);\n", " }\n", " }\n", " }\n", "\n", " return jsonOBJ;\n", " }\n", "\n", " async minZoom(chr1, chr2) {\n", " const viewDimensions = this.contactMatrixView.getViewDimensions();\n", " const chromosome1 = this.dataset.chromosomes[chr1];\n", " const chromosome2 = this.dataset.chromosomes[chr2];\n", " const chr1Length = chromosome1.size;\n", " const chr2Length = chromosome2.size;\n", " const binSize = Math.max(chr1Length / viewDimensions.width, chr2Length / viewDimensions.height);\n", " const matrix = await this.dataset.getMatrix(chr1, chr2);\n", "\n", " if (!matrix) {\n", " throw new Error(`Data not avaiable for chromosomes ${chromosome1.name} - ${chromosome2.name}`);\n", " }\n", "\n", " return matrix.findZoomForResolution(binSize);\n", " }\n", "\n", " async minPixelSize(chr1, chr2, z) {\n", " const viewDimensions = this.contactMatrixView.getViewDimensions();\n", " const chr1Length = this.dataset.chromosomes[chr1].size;\n", " const chr2Length = this.dataset.chromosomes[chr2].size;\n", " const matrix = await this.dataset.getMatrix(chr1, chr2);\n", " const zd = matrix.getZoomDataByIndex(z, \"BP\");\n", " const binSize = zd.zoom.binSize;\n", " const nBins1 = chr1Length / binSize;\n", " const nBins2 = chr2Length / binSize;\n", " return Math.min(viewDimensions.width / nBins1, viewDimensions.height / nBins2);\n", " }\n", "\n", " }\n", "\n", " function extractName(config) {\n", " if (config.name === undefined) {\n", " const urlOrFile = config.url;\n", "\n", " if (isFile(urlOrFile)) {\n", " return urlOrFile.name;\n", " } else {\n", " const str = urlOrFile.split('?').shift();\n", " const idx = urlOrFile.lastIndexOf(\"/\");\n", " return idx > 0 ? str.substring(idx + 1) : str;\n", " }\n", " } else {\n", " return config.name;\n", " }\n", " }\n", "\n", " function getNviString(dataset) {\n", " return dataset.hicFile.config.nvi; // if (dataset.hicFile.normalizationVectorIndexRange) {\n", " // var range = dataset.hicFile.normalizationVectorIndexRange,\n", " // nviString = String(range.start) + \",\" + String(range.size);\n", " // return nviString\n", " // } else {\n", " // return undefined;\n", " // }\n", " } // parseUri 1.2.2\n", "\n", " function presentError(prefix, error) {\n", " const httpMessages = {\n", " \"401\": \"Access unauthorized\",\n", " \"403\": \"Access forbidden\",\n", " \"404\": \"Not found\"\n", " };\n", " var msg = error.message;\n", "\n", " if (httpMessages.hasOwnProperty(msg)) {\n", " msg = httpMessages[msg];\n", " }\n", "\n", " Alert$1.presentAlert(prefix + \": \" + msg);\n", " }\n", "\n", " /*\n", " * @author Jim Robinson Dec-2020\n", " */\n", " const defaultSize = {\n", " width: 640,\n", " height: 640\n", " };\n", " let allBrowsers = [];\n", " let currentBrowser;\n", "\n", " async function createBrowser(hic_container, config, callback) {\n", " const $hic_container = $(hic_container);\n", " setDefaults(config);\n", "\n", " if (isString$2(config.state)) {\n", " config.state = State.parse(config.state);\n", " }\n", "\n", " if (isString$2(config.colorScale)) {\n", " config.colorScale = ColorScale.parse(config.colorScale);\n", " }\n", "\n", " if (isString$2(config.backgroundColor)) {\n", " config.backgroundColor = ContactMatrixView.parseBackgroundColor(config.backgroundColor);\n", " }\n", "\n", " const browser = new HICBrowser($hic_container, config);\n", " await browser.init(config);\n", "\n", " if (typeof callback === \"function\") {\n", " callback();\n", " }\n", "\n", " allBrowsers.push(browser);\n", " setCurrentBrowser(browser);\n", "\n", " if (allBrowsers.length > 1) {\n", " allBrowsers.forEach(function (b) {\n", " b.$browser_panel_delete_button.show();\n", " });\n", " }\n", "\n", " return browser;\n", " }\n", " /**\n", " * Create multiple browsers, maintaining order specified in configList. Called from restore session\n", " *\n", " * @param hic_container\n", " * @param configList\n", " */\n", "\n", "\n", " async function createBrowserList(hic_container, session) {\n", " const $hic_container = $(hic_container);\n", " const configList = session.browsers || [session];\n", " allBrowsers = [];\n", " const initPromises = [];\n", "\n", " for (let config of configList) {\n", " setDefaults(config);\n", "\n", " if (isString$2(config.state)) {\n", " config.state = State.parse(config.state);\n", " }\n", "\n", " if (isString$2(config.colorScale)) {\n", " config.colorScale = ColorScale.parse(config.colorScale);\n", " }\n", "\n", " if (isString$2(config.backgroundColor)) {\n", " config.backgroundColor = ContactMatrixView.parseBackgroundColor(config.backgroundColor);\n", " }\n", "\n", " if (false === session.syncDatasets) {\n", " config.synchable = false;\n", " }\n", "\n", " const browser = new HICBrowser($hic_container, config);\n", " allBrowsers.push(browser);\n", " initPromises.push(browser.init(config));\n", " }\n", "\n", " await Promise.all(initPromises);\n", " setCurrentBrowser(allBrowsers[0]);\n", "\n", " if (allBrowsers.length > 1) {\n", " allBrowsers.forEach(function (b) {\n", " b.$browser_panel_delete_button.show();\n", " });\n", " }\n", " }\n", "\n", " function deleteAllBrowsers() {\n", " for (let b of allBrowsers) {\n", " b.$root.remove();\n", " }\n", "\n", " allBrowsers = [];\n", " }\n", "\n", " function setCurrentBrowser(browser) {\n", " // unselect current browser\n", " if (undefined === browser) {\n", " if (currentBrowser) {\n", " currentBrowser.$root.removeClass('hic-root-selected');\n", " }\n", "\n", " currentBrowser = browser;\n", " return;\n", " }\n", "\n", " if (browser !== currentBrowser) {\n", " if (currentBrowser) {\n", " currentBrowser.$root.removeClass('hic-root-selected');\n", " }\n", "\n", " browser.$root.addClass('hic-root-selected');\n", " currentBrowser = browser;\n", " EventBus.globalBus.post(HICEvent(\"BrowserSelect\", browser));\n", " }\n", " }\n", "\n", " function deleteBrowser(browser) {\n", " browser.unsyncSelf();\n", " browser.$root.remove();\n", " allBrowsers = allBrowsers.filter(b => b != browser);\n", "\n", " if (allBrowsers.length <= 1) {\n", " allBrowsers.forEach(function (b) {\n", " b.$browser_panel_delete_button.hide();\n", " });\n", " }\n", " }\n", "\n", " function getCurrentBrowser() {\n", " return currentBrowser;\n", " }\n", "\n", " function syncBrowsers(browsers) {\n", " const synchableBrowsers = (browsers || allBrowsers).filter(b => false !== b.synchable && b.dataset !== undefined); // Sync compatible maps only\n", "\n", " for (let b1 of synchableBrowsers) {\n", " for (let b2 of synchableBrowsers) {\n", " if (b1 === b2) continue;\n", "\n", " if (b1.dataset.isCompatible(b2.dataset)) {\n", " b1.synchedBrowsers.push(b2);\n", " b2.synchedBrowsers.push(b1);\n", " }\n", " }\n", " }\n", " }\n", "\n", " function getAllBrowsers() {\n", " return allBrowsers;\n", " } // Set default values for config properties\n", "\n", "\n", " function setDefaults(config) {\n", " if (config.state) {\n", " if (isString$2(config.state)) {\n", " config.state = State.parse(config.state);\n", " } else {\n", " // copy\n", " config.state = new State(config.state.chr1, config.state.chr2, config.state.zoom, config.state.x, config.state.y, config.width, config.height, config.state.pixelSize, config.state.normalization);\n", " }\n", " }\n", "\n", " if (config.figureMode === true) {\n", " config.showLocusGoto = false;\n", " config.showHicContactMapLabel = false;\n", " config.showChromosomeSelector = false;\n", " } else {\n", " if (undefined === config.width) {\n", " config.width = config.state ? config.state.width : defaultSize.width;\n", " }\n", "\n", " if (undefined === config.height) {\n", " config.height = config.state ? config.state.height : defaultSize.height;\n", " }\n", "\n", " if (undefined === config.showLocusGoto) {\n", " config.showLocusGoto = true;\n", " }\n", "\n", " if (undefined === config.showHicContactMapLabel) {\n", " config.showHicContactMapLabel = true;\n", " }\n", "\n", " if (undefined === config.showChromosomeSelector) {\n", " config.showChromosomeSelector = true;\n", " }\n", " }\n", " } // mock igv browser objects for igv.js compatibility\n", "\n", " const version = \"2.2.0\";\n", " //, commit}\n", "\n", " function toJSON() {\n", " const jsonOBJ = {};\n", " const browserJson = [];\n", " const allBrowsers = getAllBrowsers();\n", "\n", " for (let browser of allBrowsers) {\n", " browserJson.push(browser.toJSON());\n", " }\n", "\n", " jsonOBJ.browsers = browserJson;\n", "\n", " if (Globals.selectedGene) {\n", " jsonOBJ[\"selectedGene\"] = Globals.selectedGene;\n", " }\n", "\n", " const captionDiv = document.getElementById('hic-caption');\n", "\n", " if (captionDiv) {\n", " var captionText = captionDiv.textContent;\n", "\n", " if (captionText) {\n", " captionText = captionText.trim();\n", "\n", " if (captionText) {\n", " jsonOBJ.caption = captionText;\n", " }\n", " }\n", " }\n", "\n", " return jsonOBJ;\n", " }\n", "\n", " function compressedSession() {\n", " const jsonString = JSON.stringify(toJSON());\n", " return `session=blob:${compressString(jsonString)}`;\n", " }\n", "\n", " async function restoreSession(container, session) {\n", " deleteAllBrowsers();\n", "\n", " if (session.hasOwnProperty(\"selectedGene\")) {\n", " Globals.selectedGene = session.selectedGene;\n", " }\n", "\n", " if (session.hasOwnProperty(\"caption\")) {\n", " const captionText = session.caption;\n", " var captionDiv = document.getElementById(\"hic-caption\");\n", "\n", " if (captionDiv) {\n", " captionDiv.textContent = captionText;\n", " }\n", " }\n", "\n", " await createBrowserList(container, session);\n", "\n", " if (false !== session.syncDatasets) {\n", " syncBrowsers();\n", " }\n", " }\n", "\n", " /*\n", " * The MIT License (MIT)\n", " *\n", " * Copyright (c) 2016-2017 The Regents of the University of California\n", " *\n", " * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and\n", " * associated documentation files (the \"Software\"), to deal in the Software without restriction, including\n", " * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n", " * copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the\n", " * following conditions:\n", " *\n", " * The above copyright notice and this permission notice shall be included in all copies or substantial\n", " * portions of the Software.\n", " *\n", " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING\n", " * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n", " * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n", " * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\n", " * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n", " * THE SOFTWARE.\n", " *\n", " */\n", " const DEFAULT_ANNOTATION_COLOR = \"rgb(22, 129, 198)\";\n", " const urlShortcuts = {\n", " \"*s3e/\": \"https://hicfiles.s3.amazonaws.com/external/\",\n", " \"*s3/\": \"https://hicfiles.s3.amazonaws.com/\",\n", " \"*s3e_/\": \"http://hicfiles.s3.amazonaws.com/external/\",\n", " \"*s3_/\": \"http://hicfiles.s3.amazonaws.com/\",\n", " \"*enc/\": \"https://www.encodeproject.org/files/\"\n", " };\n", "\n", " async function extractConfig(queryString) {\n", " let query = extractQuery(queryString);\n", " let sessionConfig;\n", "\n", " if (query.hasOwnProperty(\"session\")) {\n", " if (query.session.startsWith(\"blob:\") || query.session.startsWith(\"data:\")) {\n", " sessionConfig = JSON.parse(uncompressString(query.session.substr(5)));\n", " }\n", " }\n", "\n", " if (query.hasOwnProperty(\"juiceboxURL\")) {\n", " const jbURL = await expandURL(query[\"juiceboxURL\"]); // Legacy bitly urls\n", "\n", " query = extractQuery(jbURL);\n", " }\n", "\n", " if (query.hasOwnProperty(\"juicebox\") || query.hasOwnProperty(\"juiceboxData\")) {\n", " let q;\n", "\n", " if (query.hasOwnProperty(\"juiceboxData\")) {\n", " q = uncompressString(query[\"juiceboxData\"]);\n", " } else {\n", " q = query[\"juicebox\"];\n", "\n", " if (q.startsWith(\"%7B\")) {\n", " q = decodeURIComponent(q);\n", " }\n", " }\n", "\n", " q = q.substr(1, q.length - 2); // Strip leading and trailing bracket\n", "\n", " const parts = q.split(\"},{\");\n", " const browsers = [];\n", "\n", " for (let p of parts) {\n", " const qObj = extractQuery(decodeURIComponent(p));\n", " browsers.push(decodeQuery(qObj));\n", " }\n", "\n", " sessionConfig = {\n", " browsers\n", " };\n", " } // Try query parameter style\n", "\n", "\n", " const uriDecode = true;\n", " const queryConfig = decodeQuery(query, uriDecode);\n", "\n", " if (queryConfig.url) {\n", " sessionConfig = queryConfig;\n", " } // Fix certain defaults\n", "\n", "\n", " if (sessionConfig) {\n", " if (sessionConfig.browsers) {\n", " for (let b of sessionConfig.browsers) {\n", " fixDefaults(b);\n", " }\n", " } else {\n", " fixDefaults(sessionConfig);\n", " }\n", " }\n", "\n", " return sessionConfig;\n", " }\n", "\n", " function fixDefaults(browserConfig) {\n", " if (browserConfig.tracks) {\n", " for (let t of browserConfig.tracks) {\n", " if (t.color === DEFAULT_ANNOTATION_COLOR) {\n", " delete t.color;\n", " }\n", "\n", " if (t.min !== undefined && Number.isNaN(t.min)) {\n", " delete t.min;\n", " }\n", "\n", " if (t.max !== undefined && Number.isNaN(t.max)) {\n", " delete t.max;\n", " }\n", "\n", " t.displayMode = \"COLLAPSED\";\n", " }\n", " }\n", " }\n", " /**\n", " * Extend config properties with query parameters\n", " *\n", " * @param query\n", " * @param config\n", " */\n", "\n", "\n", " function decodeQuery(query, uriDecode) {\n", " const config = {};\n", " let hicUrl = query[\"hicUrl\"];\n", " const name = query[\"name\"];\n", " let stateString = query[\"state\"];\n", " let colorScale = query[\"colorScale\"];\n", " let trackString = query[\"tracks\"];\n", " const selectedGene = query[\"selectedGene\"];\n", " const nvi = query[\"nvi\"];\n", " let controlUrl = query[\"controlUrl\"];\n", " const controlName = query[\"controlName\"];\n", " const displayMode = query[\"displayMode\"];\n", " const controlNvi = query[\"controlNvi\"];\n", " const cycle = query[\"cycle\"];\n", "\n", " if (hicUrl) {\n", " hicUrl = paramDecode(hicUrl, uriDecode);\n", " Object.keys(urlShortcuts).forEach(function (key) {\n", " var value = urlShortcuts[key];\n", " if (hicUrl.startsWith(key)) hicUrl = hicUrl.replace(key, value);\n", " });\n", " config.url = hicUrl;\n", " }\n", "\n", " if (name) {\n", " config.name = paramDecode(name, uriDecode);\n", " }\n", "\n", " if (controlUrl) {\n", " controlUrl = paramDecode(controlUrl, uriDecode);\n", " Object.keys(urlShortcuts).forEach(function (key) {\n", " var value = urlShortcuts[key];\n", " if (controlUrl.startsWith(key)) controlUrl = controlUrl.replace(key, value);\n", " });\n", " config.controlUrl = controlUrl;\n", " }\n", "\n", " if (controlName) {\n", " config.controlName = paramDecode(controlName, uriDecode);\n", " }\n", "\n", " if (stateString) {\n", " stateString = paramDecode(stateString, uriDecode);\n", " config.state = State.parse(stateString);\n", " }\n", "\n", " if (colorScale) {\n", " colorScale = paramDecode(colorScale, uriDecode);\n", " config.colorScale = ColorScale.parse(colorScale);\n", " }\n", "\n", " if (displayMode) {\n", " config.displayMode = paramDecode(displayMode, uriDecode);\n", " }\n", "\n", " if (trackString) {\n", " trackString = paramDecode(trackString, uriDecode);\n", " config.tracks = destringifyTracksV0(trackString); // If an oAuth token is provided append it to track configs.\n", "\n", " if (config.tracks && config.oauthToken) {\n", " config.tracks.forEach(function (t) {\n", " t.oauthToken = config.oauthToken;\n", " });\n", " }\n", " }\n", "\n", " if (selectedGene) {\n", " Globals.selectedGene = selectedGene;\n", " }\n", "\n", " config.cycle = cycle;\n", "\n", " if (nvi) {\n", " config.nvi = paramDecode(nvi, uriDecode);\n", " }\n", "\n", " if (controlNvi) {\n", " config.controlNvi = paramDecode(controlNvi, uriDecode);\n", " }\n", "\n", " return config;\n", "\n", " function destringifyTracksV0(tracks) {\n", " const trackStringList = tracks.split(\"|||\");\n", " const configList = [];\n", "\n", " for (let trackString of trackStringList) {\n", " const tokens = trackString.split(\"|\");\n", " const color = tokens.pop();\n", " let url = tokens.length > 1 ? tokens[0] : trackString;\n", "\n", " if (url && url.trim().length > 0 && \"undefined\" !== url) {\n", " const keys = Object.keys(urlShortcuts);\n", "\n", " for (let key of keys) {\n", " var value = urlShortcuts[key];\n", "\n", " if (url.startsWith(key)) {\n", " url = url.replace(key, value);\n", " break;\n", " }\n", " }\n", "\n", " const trackConfig = {\n", " url: url\n", " };\n", "\n", " if (tokens.length > 1) {\n", " trackConfig.name = replaceAll(tokens[1], \"$\", \"|\");\n", " }\n", "\n", " if (tokens.length > 2) {\n", " const dataRangeString = tokens[2];\n", "\n", " if (dataRangeString.startsWith(\"-\")) {\n", " const r = dataRangeString.substring(1).split(\"-\");\n", " trackConfig.min = -parseFloat(r[0]);\n", " trackConfig.max = parseFloat(r[1]);\n", " } else {\n", " const r = dataRangeString.split(\"-\");\n", " trackConfig.min = parseFloat(r[0]);\n", " trackConfig.max = parseFloat(r[1]);\n", " }\n", " }\n", "\n", " if (color) {\n", " trackConfig.color = color;\n", " }\n", "\n", " configList.push(trackConfig);\n", " }\n", " }\n", "\n", " return configList;\n", " }\n", " }\n", "\n", " function paramDecode(str, uriDecode) {\n", " if (uriDecode) {\n", " return decodeURIComponent(str); // Still more backward compatibility\n", " } else {\n", " var s = replaceAll(str, '%26', '&');\n", " s = replaceAll(s, '%20', ' ');\n", " s = replaceAll(s, '+', ' ');\n", " s = replaceAll(s, \"%7C\", \"|\");\n", " s = replaceAll(s, \"%23\", \"#\");\n", " s = replaceAll(s, \"%3F\", \"?\");\n", " s = replaceAll(s, \"%3D\", \"=\");\n", " return s;\n", " }\n", " }\n", "\n", " function replaceAll(str, target, replacement) {\n", " return str.split(target).join(replacement);\n", " }\n", "\n", " function extractQuery(uri) {\n", " var i1, i2, i, j, s, query, tokens;\n", " query = {};\n", " i1 = uri.indexOf(\"?\");\n", " i2 = uri.lastIndexOf(\"#\");\n", " const i3 = uri.indexOf(\"=\");\n", " if (i1 > i3) i1 = -1;\n", " if (i2 < 0) i2 = uri.length;\n", "\n", " for (i = i1 + 1; i < i2;) {\n", " j = uri.indexOf(\"&\", i);\n", " if (j < 0) j = i2;\n", " s = uri.substring(i, j);\n", " tokens = s.split(\"=\", 2);\n", "\n", " if (tokens.length === 2) {\n", " query[tokens[0]] = tokens[1];\n", " }\n", "\n", " i = j + 1;\n", " }\n", "\n", " return query;\n", " }\n", " /**\n", " * Expand legacy bitly URLs\n", " * @param url\n", " * @returns {Promise<*>}\n", " */\n", "\n", "\n", " async function expandURL(url) {\n", " const endpoint = `https://api-ssl.bitly.com/v4/expand`;\n", " const id = url.startsWith(\"http://\") ? url.substring(7) : url.substring(8);\n", " const message = {\n", " \"bitlink_id\": id\n", " };\n", " const response = await fetch(endpoint, {\n", " method: 'POST',\n", " // or 'PUT'\n", " headers: {\n", " 'Content-Type': 'application/json',\n", " 'Authorization': `Bearer ${btoa(\"ëtá¾´ãÎtsß\u001AéÆºÙçµóf¸í¿9sn\u001D", "éÝz\")}`\n", " },\n", " body: JSON.stringify(message)\n", " });\n", "\n", " if (!response.ok) {\n", " throw new Error(`Network error (${response.status}): ${response.statusText}`);\n", " }\n", "\n", " const json = await response.json();\n", " let longUrl = json.long_url; // Fix some Bitly \"normalization\"\n", "\n", " longUrl = longUrl.replace(\"{\", \"%7B\").replace(\"}\", \"%7D\");\n", " return longUrl;\n", " }\n", "\n", " /*\n", " * The MIT License (MIT)\n", " *\n", " * Copyright (c) 2016-2017 The Regents of the University of California\n", " *\n", " * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and\n", " * associated documentation files (the \"Software\"), to deal in the Software without restriction, including\n", " * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n", " * copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the\n", " * following conditions:\n", " *\n", " * The above copyright notice and this permission notice shall be included in all copies or substantial\n", " * portions of the Software.\n", " *\n", " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING\n", " * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n", " * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n", " * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\n", " * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n", " * THE SOFTWARE.\n", " *\n", " */\n", "\n", " async function init(container, config) {\n", " Alert$1.init(container);\n", "\n", " if (false !== config.queryParametersSupported) {\n", " const queryConfig = await extractConfig(window.location.href);\n", "\n", " if (queryConfig) {\n", " config = queryConfig;\n", " }\n", " }\n", "\n", " await restoreSession(container, config); // Return the currently selected browser for backward compatibility with \"createBrowser\"\n", "\n", " return getCurrentBrowser();\n", " }\n", "\n", " /*\n", " * The MIT License (MIT)\n", " *\n", " * Copyright (c) 2016-2017 The Regents of the University of California\n", " *\n", " * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and\n", " * associated documentation files (the \"Software\"), to deal in the Software without restriction, including\n", " * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n", " * copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the\n", " * following conditions:\n", " *\n", " * The above copyright notice and this permission notice shall be included in all copies or substantial\n", " * portions of the Software.\n", " *\n", " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING\n", " * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n", " * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n", " * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\n", " * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n", " * THE SOFTWARE.\n", " *\n", " */\n", " var index = {\n", " version,\n", " init,\n", " toJSON,\n", " restoreSession,\n", " compressedSession,\n", " createBrowser,\n", " getCurrentBrowser,\n", " setCurrentBrowser,\n", " getAllBrowsers,\n", " igvxhr,\n", " EventBus\n", " };\n", "\n", " return index;\n", "\n", "}));\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "/**\n", " * Global handler for juicebox messages. Messages have the form\n", " * {\n", " * command -- the command to execute\n", " * id -- the id of the juicebox browser, if applicable\n", " * data -- any data needed for the command\n", " * }\n", " */\n", "\n", "// Use a self-evaluating function to keep variables in this file scope, with the execption of the global handler\n", "\n", "(function () {\n", "\n", " console.log(\"Installing juicebox.JuiceboxMessageHandler\")\n", "\n", " class MessageHandler {\n", "\n", " constructor() {\n", " this.browserCache = new Map()\n", " this.messageQueue = new Queue()\n", " }\n", "\n", " on(msg) {\n", " console.log(`Message received ${msg}`)\n", " this.messageQueue.enqueue(msg)\n", " this.processQueue()\n", " }\n", "\n", " async processQueue() {\n", " if (!this.processing) {\n", " this.processing = true\n", " while (!this.messageQueue.isEmpty()) {\n", " const msg = this.messageQueue.dequeue()\n", " const command = msg.command\n", " const id = msg.id\n", " const data = msg.data\n", " const browser = this.browserCache.get(id)\n", " try {\n", " switch (command) {\n", " case \"createBrowser\":\n", " var div = document.getElementById(id) // <= created from python\n", "\n", " data.url = convert(data.url)\n", " if (data.tracks) {\n", " for (let t of data.tracks) {\n", " t.url = convert(t.url)\n", " t.indexURL = convert(t.indexURL)\n", " }\n", " }\n", " const newBrowser = await juicebox.createBrowser(div, data)\n", " this.browserCache.set(id, newBrowser)\n", " break\n", "\n", " case \"loadMap\":\n", " data.url = convert(data.url)\n", " await browser.loadHicFile(data)\n", " break\n", "\n", " case \"loadTrack\":\n", " data.url = convert(data.url)\n", " data.indexURL = convert(data.indexURL)\n", " await browser.loadTracks([data])\n", " break\n", "\n", " case \"loadTrackList\":\n", " for (let t of data) {\n", " t.url = convert(t.url)\n", " t.indexURL = convert(t.indexURL)\n", " }\n", " await browser.loadTracks(data)\n", " break\n", "\n", " default:\n", " console.error(\"Unrecognized method: \" + msg.command)\n", " }\n", " } catch (e) {\n", " console.error(e)\n", " }\n", " }\n", " this.processing = false\n", " }\n", " }\n", " }\n", "\n", " /**\n", " * Potentially convert a path to a local File-like object.\n", " * @param path\n", " * @returns {*}\n", " */\n", " function convert(path) {\n", " if (!path ||\n", " path.startsWith(\"https://\") || path.startsWith(\"http://\") || path.startsWith(\"gs://\") || path.startsWith(\"data:\")) {\n", " return path\n", " } else {\n", " // Try to create a notebook file. If no notebook file implementation is available for the kernel in\n", " // use (e.g. JupyterLab) just return 'path'\n", " const nbFile = juicebox.createNotebookLocalFile({path})\n", " return nbFile || path\n", " }\n", " }\n", "\n", "\n", " class Queue {\n", " constructor() {\n", " this.elements = []\n", " }\n", "\n", " enqueue(e) {\n", " this.elements.push(e)\n", " }\n", "\n", " dequeue() {\n", " return this.elements.shift()\n", " }\n", "\n", " isEmpty() {\n", " return this.elements.length == 0\n", " }\n", "\n", " peek() {\n", " return !this.isEmpty() ? this.elements[0] : undefined\n", " }\n", "\n", " length() {\n", " return this.elements.length\n", " }\n", " }\n", "\n", " window.juicebox.JuiceboxMessageHandler = new MessageHandler()\n", "\n", " console.log(\"JuiceboxMessageHandler installed\")\n", "\n", "})()\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "/**\n", " * Mock objects to emulate the browser \"File\" class for use with Jupyter and Colab notebooks. These objects delegate\n", " * actual file reading to python.\n", " */\n", "\n", "// Use a self-evaluating function to keep variables in this file scope\n", "\n", "(function () {\n", "\n", " const isColab = () => window.google !== undefined && window.google.colab\n", " const isNotebook = () => window.Jupyter !== undefined\n", "\n", " juicebox.createNotebookLocalFile = function (options) {\n", " if (isColab()) {\n", " return new ColabLocalFile(options)\n", " } else if (isNotebook()) {\n", " return new JupyterLocalFile(options)\n", " }\n", " }\n", "\n", "\n", " // Start up a Comm object if in a Jupyter environment (i.e. not Colab).\n", " let comm\n", " const pendingRequests = new Map()\n", " if (isNotebook()) {\n", " console.log('registering comm')\n", " comm = Jupyter.notebook.kernel.comm_manager.new_comm('file_request', {})\n", " // Register a handler\n", " comm.on_msg(function (msg) {\n", " const id = msg.content.data.id\n", " const data = msg.content.data.data\n", " pendingRequests.set(id, data)\n", " })\n", " }\n", "\n", " /**\n", " * Emulates a browser \"File\" for Jupyter notebooks. File reading is delegated to python via Comms messaging.\n", " * Polling is used to synchronize the async message passing.\n", " *\n", " * NOTE: This will not work for JupyterLab\n", " */\n", " class JupyterLocalFile {\n", "\n", " constructor({path, name, start, end}) {\n", " this.path = path\n", " this.name = name || path\n", " this.start = start\n", " this.end = end\n", " }\n", "\n", " /**\n", " * Returns a new Blob object containing the data in the specified range of bytes of the blob on which it's called.\n", " * @param start An index into the Blob indicating the first byte to include in the new Blob\n", " * @param end An index into the Blob indicating the first byte that will *not* be included in the new Blob\n", " * @param contentType\n", " * @returns {*}\n", " */\n", " slice(start, end) {\n", " return new JupyterLocalFile({path: this.path, name: this.name, start, end})\n", " }\n", "\n", " /**\n", " * Returns a promise that resolves with an ArrayBuffer containing the entire contents of the Blob as binary data.\n", " *\n", " * @returns {Promise<*>}\n", " */\n", " async arrayBuffer() {\n", "\n", " const id = uniqueID()\n", " const path = this.path\n", " const promise = new Promise((resolve, reject) => {\n", " let count = 0\n", "\n", " function poll() {\n", "\n", " if (count > 100) {\n", "\n", " console.error(`error reading ${path}: timed out`)\n", " reject(`timed out`)\n", " }\n", "\n", " count++\n", " if (pendingRequests.has(id)) {\n", " const data = pendingRequests.get(id)\n", " const dataString = atob(data)\n", " const bytes = new Uint8Array(dataString.length)\n", " for (var i = 0; i < dataString.length; i++) {\n", " bytes[i] = dataString.charCodeAt(i)\n", " }\n", " pendingRequests.delete(id)\n", " resolve(bytes.buffer)\n", " } else {\n", " setTimeout(poll, 100)\n", " }\n", " }\n", "\n", " poll()\n", " })\n", "\n", " const msg = (this.start === undefined) ?\n", " {id: id, 'path': this.path, 'method': 'arrayBuffer'} :\n", " {id: id, 'path': this.path, 'method': 'arrayBuffer', 'start': this.start, 'end': this.end}\n", "\n", " comm.send(msg)\n", "\n", " return promise\n", " }\n", "\n", " /**\n", " * Returns a promise that resolves with a USVString containing the entire contents of the Blob interpreted as UTF-8 text.\n", " *\n", " * @returns {Promise}\n", " */\n", " async text() {\n", " throw Error(\"text not implemented\")\n", " }\n", "\n", " stream() {\n", " throw Error(\"stream not implemented\")\n", " }\n", " }\n", "\n", " /**\n", " * Emulates a browser \"File\" for Colab environments.\n", " */\n", " class ColabLocalFile {\n", "\n", " constructor({path, name, start, end}) {\n", " this.path = path\n", " this.name = name || path\n", " this.start = start\n", " this.end = end\n", " }\n", "\n", " /**\n", " * Returns a new Blob object containing the data in the specified range of bytes of the blob on which it's called.\n", " * @param start An index into the Blob indicating the first byte to include in the new Blob\n", " * @param end An index into the Blob indicating the first byte that will *not* be included in the new Blob\n", " * @param contentType\n", " * @returns {*}\n", " */\n", " slice(start, end) {\n", " return new ColabLocalFile({path: this.path, name: this.name, start, end})\n", " }\n", "\n", " /**\n", " * Returns a promise that resolves with an ArrayBuffer containing the entire contents of the Blob as\n", " * binary data.\n", " */\n", " async arrayBuffer() {\n", "\n", " const args = (this.start === undefined) ?\n", " [this.path] :\n", " [this.path, this.start.toString(), this.end.toString()]\n", "\n", " const result = await google.colab.kernel.invokeFunction(\n", " 'ReadFile', // The callback name.\n", " args, // The arguments.\n", " {}) // kwargs\n", " const data = result.data[\"text/plain\"]\n", " const dataString = atob(data.substring(2, data.length - 1))\n", " const bytes = new Uint8Array(dataString.length)\n", " for (var i = 0; i < dataString.length; i++) {\n", " bytes[i] = dataString.charCodeAt(i)\n", " }\n", " return bytes.buffer\n", " }\n", "\n", " /**\n", " * Returns a promise that resolves with a USVString containing the entire contents of the Blob interpreted as UTF-8 text.\n", " *\n", " * @returns {Promise}\n", " */\n", " async text() {\n", " throw Error(\"text not implemented\")\n", " }\n", "\n", " stream() {\n", " throw Error(\"stream not implemented\")\n", " }\n", " }\n", "\n", " let counter = 0\n", "\n", " function uniqueID() {\n", " return `${Math.random()}-${counter++}`\n", " }\n", "\n", "})()" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "window.juicebox.JuiceboxMessageHandler.on({\"id\": \"jb_1076659\", \"command\": \"createBrowser\", \"data\": {\"name\": \"GM12878\", \"url\": \"/Users/dat/JuiceboxDevelopment/test_data/intra_nofrag_30.hic\", \"tracks\": [{\"url\": \"/Users/dat/IGVDevelopment/test_data/WIG/ENCFF001EQU.bigWig\", \"type\": \"wig\", \"name\": \"CTCF\", \"color\": \"rgb(22, 129, 198)\"}], \"id\": \"jb_1076659\"}})" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "import juicebox\n", "\n", "juicebox.init()\n", "b = juicebox.Browser(\n", " {\n", " \"name\": \"GM12878\",\n", " \"url\": \"/Users/dat/JuiceboxDevelopment/test_data/intra_nofrag_30.hic\",\n", " \"tracks\": [\n", " {\n", " \"url\": \"/Users/dat/IGVDevelopment/test_data/WIG/ENCFF001EQU.bigWig\",\n", " \"type\": \"wig\",\n", " \"name\": \"CTCF\",\n", " \"color\": \"rgb(22, 129, 198)\"\n", " }\n", " ]\n", " }\n", "\n", ")\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Load a map and track dynamically" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import juicebox\n", "\n", "\n", "juicebox.init()\n", "\n", "b = juicebox.Browser({})\n", "\n", "b.load_map({\n", " \"name\": \"GM12878\",\n", " \"url\": \"/Volumes/GoogleDrive/Shared drives/IGV/TestData/juicebox/HCT-116_Untreated.hic\"\n", "})\n", "\n", "b.load_track({\n", " \"url\": \"/Volumes/GoogleDrive/Shared drives/IGV/TestData/juicebox/CTCF_Untreated.bw\",\n", " \"type\": \"wig\",\n", " \"name\": \"CTCF\",\n", " \"color\": \"rgb(22, 129, 198)\"\n", "})\n" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.9.1" } }, "nbformat": 4, "nbformat_minor": 2 }