igv 2.10.5 → 2.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/igv.js CHANGED
@@ -7205,7 +7205,7 @@
7205
7205
  }
7206
7206
  }
7207
7207
 
7208
- function guid$1() {
7208
+ function guid$2() {
7209
7209
  return ("0000" + (Math.random() * Math.pow(36, 4) << 0).toString(36)).slice(-4);
7210
7210
  }
7211
7211
 
@@ -7840,7 +7840,7 @@
7840
7840
 
7841
7841
 
7842
7842
  function getFilename$1(urlOrFile) {
7843
- if (isFile(urlOrFile)) {
7843
+ if (urlOrFile.name !== undefined) {
7844
7844
  return urlOrFile.name;
7845
7845
  } else if (isString$3(urlOrFile)) {
7846
7846
  let index = urlOrFile.lastIndexOf("/");
@@ -7858,15 +7858,18 @@
7858
7858
  }
7859
7859
  }
7860
7860
  /**
7861
- * Test if object is a File or File-like object by testing for the "name" property. This is not a robust test,
7862
- * but the purpose is to distinguish the object from url strings
7861
+ * Test if object is a File or File-like object.
7863
7862
  *
7864
7863
  * @param object
7865
7864
  */
7866
7865
 
7867
7866
 
7868
7867
  function isFile(object) {
7869
- return object !== undefined && (object instanceof File || typeof object !== "function" && object.hasOwnProperty("name") && object.hasOwnProperty("size") && object.hasOwnProperty("type"));
7868
+ if (!object) {
7869
+ return false;
7870
+ }
7871
+
7872
+ return typeof object !== 'function' && (object instanceof File || object.hasOwnProperty("name") && typeof object.slice === 'function' && typeof object.arrayBuffer === 'function');
7870
7873
  }
7871
7874
 
7872
7875
  const isFilePath = isFile; // deprecated
@@ -17441,8 +17444,6 @@
17441
17444
 
17442
17445
 
17443
17446
  async function fetchGoogleAccessToken(url) {
17444
- console.log("Fetch token for " + url);
17445
-
17446
17447
  if (isInitialized()) {
17447
17448
  const scope = getScopeForURL(url);
17448
17449
  const googleToken = await getAccessToken(scope);
@@ -18859,12 +18860,12 @@
18859
18860
  this.errorHeadline.textContent = ''; // body container
18860
18861
 
18861
18862
  let bodyContainer = div({
18862
- id: 'igv-ui-alert-dialog-body'
18863
+ class: 'igv-ui-alert-dialog-body'
18863
18864
  });
18864
18865
  this.container.appendChild(bodyContainer); // body copy
18865
18866
 
18866
18867
  this.body = div({
18867
- id: 'igv-ui-alert-dialog-body-copy'
18868
+ class: 'igv-ui-alert-dialog-body-copy'
18868
18869
  });
18869
18870
  bodyContainer.appendChild(this.body); // ok container
18870
18871
 
@@ -19384,7 +19385,7 @@
19384
19385
  }
19385
19386
 
19386
19387
  function embedCSS$2() {
19387
- var css = '.igv-ui-popover {\n cursor: default;\n position: absolute;\n z-index: 2048;\n border-color: #7F7F7F;\n border-radius: 4px;\n border-style: solid;\n border-width: 1px;\n font-family: \"Open Sans\", sans-serif;\n font-size: small;\n background-color: white; }\n .igv-ui-popover > div:first-child {\n display: flex;\n flex-direction: row;\n flex-wrap: nowrap;\n justify-content: space-between;\n align-items: center;\n width: 100%;\n height: 24px;\n cursor: move;\n border-top-left-radius: 4px;\n border-top-right-radius: 4px;\n border-bottom-color: #7F7F7F;\n border-bottom-style: solid;\n border-bottom-width: thin;\n background-color: #eee; }\n .igv-ui-popover > div:first-child > div:first-child {\n margin-left: 4px; }\n .igv-ui-popover > div:first-child > div:last-child {\n margin-right: 4px;\n height: 12px;\n width: 12px;\n color: #7F7F7F; }\n .igv-ui-popover > div:first-child > div:last-child:hover {\n cursor: pointer;\n color: #444; }\n .igv-ui-popover > div:last-child {\n overflow-y: auto;\n overflow-x: hidden;\n max-height: 400px;\n max-width: 800px;\n background-color: white; }\n .igv-ui-popover > div:last-child > div {\n -webkit-user-select: all;\n /* Chrome/Safari */\n -moz-user-select: all;\n /* Firefox */\n margin-left: 4px;\n margin-right: 4px;\n min-width: 220px;\n overflow-x: hidden;\n text-overflow: ellipsis;\n white-space: nowrap; }\n .igv-ui-popover > div:last-child > div > span {\n font-weight: bolder; }\n .igv-ui-popover > div:last-child hr {\n width: 100%; }\n\n.igv-ui-alert-dialog-container {\n box-sizing: content-box;\n position: absolute;\n z-index: 2048;\n top: 50%;\n left: 50%;\n width: 400px;\n height: 200px;\n border-color: #7F7F7F;\n border-radius: 4px;\n border-style: solid;\n border-width: thin;\n outline: none;\n font-family: \"Open Sans\", sans-serif;\n font-size: 15px;\n font-weight: 400;\n background-color: white;\n display: flex;\n flex-flow: column;\n flex-wrap: nowrap;\n justify-content: space-between;\n align-items: center; }\n .igv-ui-alert-dialog-container > div:first-child {\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: center;\n width: 100%;\n height: 24px;\n cursor: move;\n border-top-left-radius: 4px;\n border-top-right-radius: 4px;\n border-bottom-color: #7F7F7F;\n border-bottom-style: solid;\n border-bottom-width: thin;\n background-color: #eee; }\n .igv-ui-alert-dialog-container > div:first-child div:first-child {\n padding-left: 8px; }\n .igv-ui-alert-dialog-container #igv-ui-alert-dialog-body {\n color: #373737;\n width: 100%;\n height: calc(100% - 24px - 64px);\n overflow-y: scroll; }\n .igv-ui-alert-dialog-container #igv-ui-alert-dialog-body #igv-ui-alert-dialog-body-copy {\n cursor: pointer;\n margin: 16px;\n width: auto;\n height: auto;\n overflow-wrap: break-word;\n word-break: break-word;\n background-color: white;\n border: unset; }\n .igv-ui-alert-dialog-container > div:last-child {\n width: 100%;\n margin-bottom: 10px;\n background-color: white;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: center;\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';
19388
+ var css = '.igv-ui-popover {\n cursor: default;\n position: absolute;\n z-index: 2048;\n border-color: #7F7F7F;\n border-radius: 4px;\n border-style: solid;\n border-width: 1px;\n font-family: \"Open Sans\", sans-serif;\n font-size: small;\n background-color: white; }\n .igv-ui-popover > div:first-child {\n display: flex;\n flex-direction: row;\n flex-wrap: nowrap;\n justify-content: space-between;\n align-items: center;\n width: 100%;\n height: 24px;\n cursor: move;\n border-top-left-radius: 4px;\n border-top-right-radius: 4px;\n border-bottom-color: #7F7F7F;\n border-bottom-style: solid;\n border-bottom-width: thin;\n background-color: #eee; }\n .igv-ui-popover > div:first-child > div:first-child {\n margin-left: 4px; }\n .igv-ui-popover > div:first-child > div:last-child {\n margin-right: 4px;\n height: 12px;\n width: 12px;\n color: #7F7F7F; }\n .igv-ui-popover > div:first-child > div:last-child:hover {\n cursor: pointer;\n color: #444; }\n .igv-ui-popover > div:last-child {\n overflow-y: auto;\n overflow-x: hidden;\n max-height: 400px;\n max-width: 800px;\n background-color: white; }\n .igv-ui-popover > div:last-child > div {\n -webkit-user-select: all;\n /* Chrome/Safari */\n -moz-user-select: all;\n /* Firefox */\n margin-left: 4px;\n margin-right: 4px;\n min-width: 220px;\n overflow-x: hidden;\n text-overflow: ellipsis;\n white-space: nowrap; }\n .igv-ui-popover > div:last-child > div > span {\n font-weight: bolder; }\n .igv-ui-popover > div:last-child hr {\n width: 100%; }\n\n.igv-ui-alert-dialog-container {\n box-sizing: content-box;\n position: absolute;\n z-index: 2048;\n top: 50%;\n left: 50%;\n width: 400px;\n height: 200px;\n border-color: #7F7F7F;\n border-radius: 4px;\n border-style: solid;\n border-width: thin;\n outline: none;\n font-family: \"Open Sans\", sans-serif;\n font-size: 15px;\n font-weight: 400;\n background-color: white;\n display: flex;\n flex-flow: column;\n flex-wrap: nowrap;\n justify-content: space-between;\n align-items: center; }\n .igv-ui-alert-dialog-container > div:first-child {\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: center;\n width: 100%;\n height: 24px;\n cursor: move;\n border-top-left-radius: 4px;\n border-top-right-radius: 4px;\n border-bottom-color: #7F7F7F;\n border-bottom-style: solid;\n border-bottom-width: thin;\n background-color: #eee; }\n .igv-ui-alert-dialog-container > div:first-child div:first-child {\n padding-left: 8px; }\n .igv-ui-alert-dialog-container .igv-ui-alert-dialog-body {\n color: #373737;\n width: 100%;\n height: calc(100% - 24px - 64px);\n overflow-y: scroll; }\n .igv-ui-alert-dialog-container .igv-ui-alert-dialog-body .igv-ui-alert-dialog-body-copy {\n cursor: pointer;\n margin: 16px;\n width: auto;\n height: auto;\n overflow-wrap: break-word;\n word-break: break-word;\n -webkit-user-select: all;\n -moz-user-select: all;\n -ms-user-select: all;\n user-select: all;\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';
19388
19389
  var style = document.createElement('style');
19389
19390
  style.setAttribute('type', 'text/css');
19390
19391
  style.innerHTML = css;
@@ -20082,6 +20083,209 @@
20082
20083
  }
20083
20084
  }
20084
20085
 
20086
+ /*
20087
+ * The MIT License (MIT)
20088
+ *
20089
+ * Copyright (c) 2014 Broad Institute
20090
+ *
20091
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
20092
+ * of this software and associated documentation files (the "Software"), to deal
20093
+ * in the Software without restriction, including without limitation the rights
20094
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
20095
+ * copies of the Software, and to permit persons to whom the Software is
20096
+ * furnished to do so, subject to the following conditions:
20097
+ *
20098
+ * The above copyright notice and this permission notice shall be included in
20099
+ * all copies or substantial portions of the Software.
20100
+ *
20101
+ *
20102
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20103
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20104
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20105
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20106
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20107
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20108
+ * THE SOFTWARE.
20109
+ */
20110
+ /**
20111
+ * Test if the given value is a string or number. Not using typeof as it fails on boxed primitives.
20112
+ *
20113
+ * @param value
20114
+ * @returns boolean
20115
+ */
20116
+
20117
+
20118
+ function isSimpleType(value) {
20119
+ const simpleTypes = new Set(["boolean", "number", "string", "symbol"]);
20120
+ const valueType = typeof value;
20121
+ return value !== undefined && (simpleTypes.has(valueType) || value.substring || value.toFixed);
20122
+ }
20123
+
20124
+ function buildOptions(config, options) {
20125
+ var defaultOptions = {
20126
+ oauthToken: config.oauthToken,
20127
+ headers: config.headers,
20128
+ withCredentials: config.withCredentials,
20129
+ filename: config.filename
20130
+ };
20131
+ return Object.assign(defaultOptions, options);
20132
+ }
20133
+ /**
20134
+ * isMobile test from http://detectmobilebrowsers.com
20135
+ * TODO -- improve UI design so this isn't neccessary
20136
+ * @returns {boolean}
20137
+ */
20138
+ // igv.isMobile = function () {
20139
+ //
20140
+ // const a = (navigator.userAgent || navigator.vendor || window.opera);
20141
+ // 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) ||
20142
+ // /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)))
20143
+ //
20144
+ // }
20145
+
20146
+
20147
+ const doAutoscale = function (features) {
20148
+ var min, max;
20149
+
20150
+ if (features.length > 0) {
20151
+ min = Number.MAX_VALUE;
20152
+ max = -Number.MAX_VALUE;
20153
+ features.forEach(function (f) {
20154
+ if (!Number.isNaN(f.value)) {
20155
+ min = Math.min(min, f.value);
20156
+ max = Math.max(max, f.value);
20157
+ }
20158
+ }); // Insure we have a zero baseline
20159
+
20160
+ if (max > 0) min = Math.min(0, min);
20161
+ if (max < 0) max = 0;
20162
+ } else {
20163
+ // No features -- default
20164
+ min = 0;
20165
+ max = 100;
20166
+ }
20167
+
20168
+ return {
20169
+ min: min,
20170
+ max: max
20171
+ };
20172
+ };
20173
+
20174
+ const validateLocusExtent = function (chromosomeLengthBP, extent, minimumBP) {
20175
+ let ss = extent.start;
20176
+ let ee = extent.end;
20177
+
20178
+ if (undefined === ee) {
20179
+ ss -= minimumBP / 2;
20180
+ ee = ss + minimumBP;
20181
+
20182
+ if (ee > chromosomeLengthBP) {
20183
+ ee = chromosomeLengthBP;
20184
+ ss = ee - minimumBP;
20185
+ } else if (ss < 0) {
20186
+ ss = 0;
20187
+ ee = minimumBP;
20188
+ }
20189
+ } else if (ee - ss < minimumBP) {
20190
+ const center = (ee + ss) / 2;
20191
+
20192
+ if (center - minimumBP / 2 < 0) {
20193
+ ss = 0;
20194
+ ee = ss + minimumBP;
20195
+ } else if (center + minimumBP / 2 > chromosomeLengthBP) {
20196
+ ee = chromosomeLengthBP;
20197
+ ss = ee - minimumBP;
20198
+ } else {
20199
+ ss = center - minimumBP / 2;
20200
+ ee = ss + minimumBP;
20201
+ }
20202
+ }
20203
+
20204
+ extent.start = Math.ceil(ss);
20205
+ extent.end = Math.floor(ee);
20206
+ };
20207
+ /*!
20208
+ * is-number <https://github.com/jonschlinkert/is-number>
20209
+ *
20210
+ * Copyright (c) 2014-present, Jon Schlinkert.
20211
+ * Released under the MIT License.
20212
+ */
20213
+
20214
+
20215
+ const isNumber = function (num) {
20216
+ if (typeof num === 'number') {
20217
+ return num - num === 0;
20218
+ }
20219
+
20220
+ if (typeof num === 'string' && num.trim() !== '') {
20221
+ return Number.isFinite ? Number.isFinite(+num) : isFinite(+num);
20222
+ }
20223
+
20224
+ return false;
20225
+ };
20226
+
20227
+ async function getFilename(url) {
20228
+ if (isString$3(url) && url.startsWith("https://drive.google.com")) {
20229
+ // This will fail if Google API key is not defined
20230
+ if (getApiKey() === undefined) {
20231
+ throw Error("Google drive is referenced, but API key is not defined. An API key is required for Google Drive access");
20232
+ }
20233
+
20234
+ const json = await getDriveFileInfo(url);
20235
+ return json.originalFileName || json.name;
20236
+ } else {
20237
+ return getFilename$1(url);
20238
+ }
20239
+ }
20240
+
20241
+ function prettyBasePairNumber(raw) {
20242
+ var denom, units, value, floored;
20243
+
20244
+ if (raw > 1e7) {
20245
+ denom = 1e6;
20246
+ units = " mb";
20247
+ } else if (raw > 1e4) {
20248
+ denom = 1e3;
20249
+ units = " kb";
20250
+ value = raw / denom;
20251
+ floored = Math.floor(value);
20252
+ return numberFormatter$1(floored) + units;
20253
+ } else {
20254
+ return numberFormatter$1(raw) + " bp";
20255
+ }
20256
+
20257
+ value = raw / denom;
20258
+ floored = Math.floor(value);
20259
+ return floored.toString() + units;
20260
+ }
20261
+
20262
+ function isDataURL(obj) {
20263
+ return isString$3(obj) && obj.startsWith("data:");
20264
+ }
20265
+
20266
+ function createColumn(columnContainer, className) {
20267
+ const column = div$1({
20268
+ class: className
20269
+ });
20270
+ columnContainer.appendChild(column);
20271
+ }
20272
+
20273
+ function insertElementBefore(element, referenceNode) {
20274
+ referenceNode.parentNode.insertBefore(element, referenceNode);
20275
+ }
20276
+
20277
+ function insertElementAfter(element, referenceNode) {
20278
+ referenceNode.parentNode.insertBefore(element, referenceNode.nextSibling);
20279
+ }
20280
+ /**
20281
+ * Test to see if page is loaded in a secure context, that is by https or is localhost.
20282
+ */
20283
+
20284
+
20285
+ function isSecureContext() {
20286
+ return window.location.protocol === "https:" || window.location.hostname === "localhost";
20287
+ }
20288
+
20085
20289
  /*
20086
20290
  * The MIT License (MIT)
20087
20291
  *
@@ -20446,7 +20650,7 @@
20446
20650
 
20447
20651
  class Viewport {
20448
20652
  constructor(trackView, viewportColumn, referenceFrame, width) {
20449
- this.guid = guid$1();
20653
+ this.guid = guid$2();
20450
20654
  this.trackView = trackView;
20451
20655
  this.referenceFrame = referenceFrame;
20452
20656
  this.browser = trackView.browser;
@@ -22357,12 +22561,13 @@
22357
22561
  * THE SOFTWARE.
22358
22562
  */
22359
22563
  const splitLines$3 = splitLines$5;
22360
- const reservedProperties = new Set(['fastaURL', 'indexURL', 'cytobandURL', 'indexed']);
22564
+ const reservedProperties = new Set(['fastaURL', 'indexURL', 'compressedIndexURL', 'cytobandURL', 'indexed']);
22361
22565
 
22362
22566
  class FastaSequence {
22363
22567
  constructor(reference) {
22364
22568
  this.file = reference.fastaURL;
22365
22569
  this.indexFile = reference.indexURL || reference.indexFile || this.file + ".fai";
22570
+ this.compressedIndexFile = reference.compressedIndexURL || false;
22366
22571
  this.withCredentials = reference.withCredentials;
22367
22572
  this.chromosomeNames = [];
22368
22573
  this.chromosomes = {};
@@ -22443,15 +22648,233 @@
22443
22648
 
22444
22649
  return this.index;
22445
22650
  }
22651
+ } //Code is losely based on https://github.com/GMOD/bgzf-filehandle
22652
+ //Reworked however in orde to work with the igvxhr interface for loading files
22653
+ //Additionally, replaced calls to the Long.js interface with standard JS calls for ArrayBuffers and the associated views
22654
+ //
22655
+ //The compressed index is an array of blocks, with each block being a pair: compressed-position & uncompressed-position (both in bytes)
22656
+
22657
+
22658
+ async getCompressedIndex() {
22659
+ const GZI_NUM_BYTES_OFFSET = 8;
22660
+ const GZI_NUM_BYTES_BLOCK = 8;
22661
+
22662
+ if (this.compressedIndex) {
22663
+ return this.compressedIndex;
22664
+ }
22665
+
22666
+ if (!this.compressedIndexFile) {
22667
+ this.compressedIndex = [];
22668
+ return this.compressedIndex;
22669
+ } //In contrast to the 'normal' reference (for which the index is chromosome based), this index is block-based
22670
+ //As such there is not need to make it a hash. An array is sufficient.
22671
+
22672
+
22673
+ this.compressedIndex = [];
22674
+ const gziData = await igvxhr.loadArrayBuffer(this.compressedIndexFile, buildOptions(this.config));
22675
+ const givenFileSize = gziData.byteLength;
22676
+
22677
+ if (givenFileSize < GZI_NUM_BYTES_OFFSET) {
22678
+ console.log("Cannot parse GZI index file: length (" + givenFileSize + " bytes) is insufficient to determine content of index.");
22679
+ return this.compressedIndex;
22680
+ } //First 8 bytes are a little endian unsigned bigint (64bit), indicating the number of blocks in the index.
22681
+
22682
+
22683
+ const numBlocksBuffer = gziData.slice(0, GZI_NUM_BYTES_OFFSET);
22684
+ const numBlocks = Number(new DataView(numBlocksBuffer).getBigUint64(0, true)); //The remainder of the gzi content are pairs of little endian unsigned bigint (64bit) numbers.
22685
+ //The first of the pair is the compressed position of a block
22686
+ //The second of the pair is the uncompressed position of a block
22687
+ //Sanity check:
22688
+ //Is the size of the array-buffer (of the entire file) correct with regards to the number of blocks detailled by the first 8 bytes of the file?
22689
+ //Total file-size should be:
22690
+ // 8 + 2*(num_entries*8) bytes, with the first 8 bytes indicating the number of entries
22691
+
22692
+ const expectedFileSize = GZI_NUM_BYTES_OFFSET + numBlocks * 2 * GZI_NUM_BYTES_BLOCK;
22693
+
22694
+ if (givenFileSize != expectedFileSize) {
22695
+ console.log("Incorrect file size of reference genome index. Expected : " + expectedFileSize + ". Received : " + givenFileSize);
22696
+ return this.compressedIndex;
22697
+ } //Push the first block to the index: the first block always has positions 0 for both the compressed and uncompressed file
22698
+
22699
+
22700
+ this.compressedIndex.push([0, 0]); //Further process all the blocks of the GZI index, and keep them in memory
22701
+
22702
+ for (let blockNumber = 0; blockNumber < numBlocks; blockNumber++) {
22703
+ const bufferBlockStart = GZI_NUM_BYTES_OFFSET + blockNumber * 2 * GZI_NUM_BYTES_BLOCK;
22704
+ const bufferBlockEnd = GZI_NUM_BYTES_OFFSET + blockNumber * 2 * GZI_NUM_BYTES_BLOCK + 2 * GZI_NUM_BYTES_BLOCK;
22705
+ const bufferBlock = gziData.slice(bufferBlockStart, bufferBlockEnd);
22706
+ const viewBlock = new DataView(bufferBlock);
22707
+ const compressedPosition = Number(viewBlock.getBigUint64(0, true)); //First 8 bytes
22708
+
22709
+ const uncompressedPosition = Number(viewBlock.getBigUint64(GZI_NUM_BYTES_BLOCK, true)); //Last 8 bytes
22710
+
22711
+ this.compressedIndex.push([compressedPosition, uncompressedPosition]);
22712
+ }
22713
+
22714
+ return this.compressedIndex;
22715
+ } //The Fasta-index gives a byte-position of the chromosomal sequences within the FASTA file.
22716
+ //These locations need to be remapped to the locations within the zipped reference genome, using the GZI index
22717
+ //This function provides this functionality by
22718
+ //1) taking the indicated start/stop byte locations within the UNCOMPRESSED FASTA file
22719
+ //2) remapping these byte locations to the correct blocks (and associated positions) within the COMPRESSED FASTA file
22720
+ //Subsequently, the calling method can then extract the correct blocks from the compressed FASTA files and uncompressed the data
22721
+
22722
+
22723
+ async getRelevantCompressedBlockNumbers(queryPositionStart, queryPositionEnd) {
22724
+ const UNCOMPRESSED_POSITION = 1; //Fallback for impossible values
22725
+
22726
+ if (queryPositionStart < 0 || queryPositionEnd < 0 || queryPositionEnd < queryPositionStart) {
22727
+ console.log("Incompatible query positions for reference-genome. Start:" + queryPositionStart + " | End:" + queryPositionEnd);
22728
+ return [];
22729
+ } //Ensure compressed index is loaded
22730
+
22731
+
22732
+ await this.getCompressedIndex();
22733
+ let result = []; //Now search for the correct block-numbers (going from 0 to length(compressed-index)) which overlap with the provided byte-positions
22734
+
22735
+ const lowestBlockNumber = 0;
22736
+ const highestBlockNumber = this.compressedIndex.length - 1; //Failsafe if for some reason the compressed index wasn't loaded or doesn't contain any data
22737
+
22738
+ if (this.compressedIndex.length == 0) {
22739
+ console.log("Compressed index does not contain any content");
22740
+ return [];
22741
+ } //Failsafe: if the queryPositionStart is greater than the uncompressed-position of the final block,
22742
+ //then this final block is the only possible result
22743
+
22744
+
22745
+ if (queryPositionStart > this.compressedIndex[highestBlockNumber][UNCOMPRESSED_POSITION]) {
22746
+ return [highestBlockNumber];
22747
+ } //Rather than doing a linear search over all blocks, a binary search is done for speed considerations
22748
+ //We are searching for the highest block number for which its position is smaller than the query start position
22749
+ //Afterwards we will simply expand the blocks until the entire query range is covered
22750
+
22751
+
22752
+ let searchLow = lowestBlockNumber;
22753
+ let searchHigh = highestBlockNumber;
22754
+ let searchPosition = Math.floor(this.compressedIndex.length / 2);
22755
+ let maxIterations = this.compressedIndex.length + 1;
22756
+ let solutionFound = false; //instead of doing a while(true), this for-loop prevents eternal loops in case of issues
22757
+
22758
+ for (let iteration = 0; iteration < maxIterations; iteration++) {
22759
+ const searchUncompressedPosition = this.compressedIndex[searchPosition][UNCOMPRESSED_POSITION];
22760
+ const nextSearchUncompressedPosition = searchPosition < this.compressedIndex.length - 1 ? this.compressedIndex[searchPosition + 1][UNCOMPRESSED_POSITION] : Infinity; //The query position lies within the current search block
22761
+
22762
+ if (searchUncompressedPosition <= queryPositionStart && nextSearchUncompressedPosition > queryPositionStart) {
22763
+ solutionFound = true;
22764
+ break; //searchPosition is the correct block number index
22765
+ } //Current block lies before the query position
22766
+ else if (searchUncompressedPosition < queryPositionStart) {
22767
+ searchLow = searchPosition + 1;
22768
+ } //Current block lies after the query position
22769
+ else {
22770
+ searchHigh = searchPosition - 1;
22771
+ }
22772
+
22773
+ searchPosition = Math.ceil((searchHigh - searchLow) / 2) + searchLow;
22774
+ } //If for some reason the binary search did not reveal a correct block index, then we return the empty result
22775
+
22776
+
22777
+ if (!solutionFound) {
22778
+ console.log("No blocks within compressed index found that correspond with query positions " + queryPositionStart + "," + queryPositionEnd);
22779
+ console.log(this.compressedIndex);
22780
+ return [];
22781
+ } //Now extend the result by adding additional blocks until the entire query range is covered
22782
+
22783
+
22784
+ result.push(searchPosition);
22785
+
22786
+ for (let blockIndex = searchPosition + 1; blockIndex < this.compressedIndex.length; blockIndex++) {
22787
+ result.push(blockIndex);
22788
+ const blockUncompressedPosition = this.compressedIndex[blockIndex][UNCOMPRESSED_POSITION];
22789
+
22790
+ if (blockUncompressedPosition >= queryPositionEnd) {
22791
+ break;
22792
+ }
22793
+ } //It is possible that the query end position lies AFTER the start of the final block
22794
+ //If this is the case, we add a 'fake' negative index which will be interpreted by the loadAndUncompressBlocks method as an indicator
22795
+ //to read until the end of the file
22796
+
22797
+
22798
+ const finalRelevantBlock = result[result.length - 1];
22799
+ const finalIndexBlock = this.compressedIndex.length - 1;
22800
+
22801
+ if (finalRelevantBlock === finalIndexBlock && this.compressedIndex[finalRelevantBlock][UNCOMPRESSED_POSITION] < queryPositionEnd) {
22802
+ result.push(-1);
22803
+ }
22804
+
22805
+ return result;
22806
+ } //Load the content from the blockIndices.
22807
+ //This is done on a per-block basis
22808
+ //Content of the first block will be trimmed in order to match the expected offset
22809
+
22810
+
22811
+ async loadAndUncompressBlocks(blockIndices, startByte) {
22812
+ const COMPRESSED_POSITION = 0;
22813
+ const UNCOMPRESSED_POSITION = 1; //Normally the compressed index should already exist, we're just makeing sure here
22814
+
22815
+ await this.getCompressedIndex();
22816
+
22817
+ if (blockIndices.length == 0) {
22818
+ return "";
22819
+ } //Storing data in seperate array with indices in order to assert order due to async behaviour of loops
22820
+
22821
+
22822
+ let resultCache = Array(blockIndices.length - 1);
22823
+
22824
+ for (let i = 0; i < blockIndices.length - 1; i++) {
22825
+ const currentBlockNumber = blockIndices[i];
22826
+ const currentBlockInfo = this.compressedIndex[currentBlockNumber];
22827
+ const currentBlockCompressedPosition = currentBlockInfo[COMPRESSED_POSITION];
22828
+ const nextBlockNumber = blockIndices[i + 1];
22829
+ let compressedBytes = [];
22830
+
22831
+ if (nextBlockNumber != -1) {
22832
+ //default : read current entire block only
22833
+ const nextBlockInfo = this.compressedIndex[nextBlockNumber];
22834
+ const nextBlockCompressedPosition = nextBlockInfo[COMPRESSED_POSITION];
22835
+ const compressedLength = nextBlockCompressedPosition - currentBlockCompressedPosition;
22836
+ compressedBytes = await igvxhr.loadArrayBuffer(this.file, buildOptions(this.config, {
22837
+ range: {
22838
+ start: currentBlockCompressedPosition,
22839
+ size: compressedLength
22840
+ }
22841
+ }));
22842
+ } else {
22843
+ // special case for query within final block: read until the end of the file
22844
+ compressedBytes = await igvxhr.loadArrayBuffer(this.file, buildOptions(this.config, {
22845
+ range: {
22846
+ start: currentBlockCompressedPosition
22847
+ }
22848
+ }));
22849
+ } //now unzip the compressed bytes, and store them in the resultCache
22850
+
22851
+
22852
+ const uncompressedBytes = await unbgzf(compressedBytes);
22853
+ resultCache[i] = uncompressedBytes;
22854
+ } //Iterate over the result cache, create sequences from the data, and create a full sequence string from the data
22855
+
22856
+
22857
+ let result = "";
22858
+
22859
+ for (let i = 0; i < resultCache.length; i++) {
22860
+ for (let j = 0; j < resultCache[i].length; j++) {
22861
+ const c = String.fromCharCode(resultCache[i][j]);
22862
+ result = result + c;
22863
+ }
22864
+ } //postprocess this data: because entire blocks are read we need to remove the first N bases of the first used block,
22865
+ //which are not included in the original query positions
22866
+
22867
+
22868
+ const firstBlockInfo = this.compressedIndex[blockIndices[0]];
22869
+ const offset = startByte - firstBlockInfo[UNCOMPRESSED_POSITION];
22870
+ result = result.substring(offset);
22871
+ return result;
22446
22872
  }
22447
22873
 
22448
22874
  async readSequence(chr, qstart, qend) {
22449
- // let offset;
22450
- // let start;
22451
- // let end;
22452
- // let basesPerLine;
22453
- // let nEndBytes;
22454
22875
  await this.getIndex();
22876
+ await this.getCompressedIndex(); //This will work even if no compressed index file is set
22877
+
22455
22878
  const idxEntry = this.index[chr];
22456
22879
 
22457
22880
  if (!idxEntry) {
@@ -22459,60 +22882,77 @@
22459
22882
 
22460
22883
  this.interval = new GenomicInterval(chr, qstart, qend, null);
22461
22884
  return null;
22462
- } else {
22463
- const start = Math.max(0, qstart); // qstart should never be < 0
22464
-
22465
- const end = Math.min(idxEntry.size, qend);
22466
- const bytesPerLine = idxEntry.bytesPerLine;
22467
- const basesPerLine = idxEntry.basesPerLine;
22468
- const position = idxEntry.position;
22469
- const nEndBytes = bytesPerLine - basesPerLine;
22470
- const startLine = Math.floor(start / basesPerLine);
22471
- const endLine = Math.floor(end / basesPerLine);
22472
- const base0 = startLine * basesPerLine; // Base at beginning of start line
22473
-
22474
- const offset = start - base0;
22475
- const startByte = position + startLine * bytesPerLine + offset;
22476
- const base1 = endLine * basesPerLine;
22477
- const offset1 = end - base1;
22478
- const endByte = position + endLine * bytesPerLine + offset1 - 1;
22479
- const byteCount = endByte - startByte + 1;
22480
- let allBytes;
22481
-
22482
- if (byteCount <= 0) {
22483
- console.error("No sequence for " + chr + ":" + qstart + "-" + qend);
22484
- } else {
22485
- allBytes = await igvxhr.load(this.file, buildOptions(this.config, {
22486
- range: {
22487
- start: startByte,
22488
- size: byteCount
22489
- }
22490
- }));
22491
- }
22885
+ }
22492
22886
 
22493
- if (!allBytes) {
22494
- return null;
22495
- } else {
22496
- let nBases,
22497
- seqBytes = "",
22498
- srcPos = 0,
22499
- allBytesLength = allBytes.length;
22887
+ const start = Math.max(0, qstart); // qstart should never be < 0
22500
22888
 
22501
- if (offset > 0) {
22502
- nBases = Math.min(end - start, basesPerLine - offset);
22503
- seqBytes += allBytes.substr(srcPos, nBases);
22504
- srcPos += nBases + nEndBytes;
22505
- }
22889
+ const end = Math.min(idxEntry.size, qend);
22890
+ const bytesPerLine = idxEntry.bytesPerLine;
22891
+ const basesPerLine = idxEntry.basesPerLine;
22892
+ const position = idxEntry.position;
22893
+ const nEndBytes = bytesPerLine - basesPerLine;
22894
+ const startLine = Math.floor(start / basesPerLine);
22895
+ const endLine = Math.floor(end / basesPerLine);
22896
+ const base0 = startLine * basesPerLine; // Base at beginning of start line
22506
22897
 
22507
- while (srcPos < allBytesLength) {
22508
- nBases = Math.min(basesPerLine, allBytesLength - srcPos);
22509
- seqBytes += allBytes.substr(srcPos, nBases);
22510
- srcPos += nBases + nEndBytes;
22898
+ const offset = start - base0;
22899
+ const startByte = position + startLine * bytesPerLine + offset;
22900
+ const base1 = endLine * basesPerLine;
22901
+ const offset1 = end - base1;
22902
+ const endByte = position + endLine * bytesPerLine + offset1 - 1;
22903
+ const byteCount = endByte - startByte + 1;
22904
+
22905
+ if (byteCount <= 0) {
22906
+ console.error("No sequence for " + chr + ":" + qstart + "-" + qend);
22907
+ return null;
22908
+ } //If the compressed index file is set, then we are dealing with a compressed genome sequence
22909
+ //The selection of startByte/endByte is done for the non-compressed genome sequence.
22910
+ //These need to be 'converted' to the correct byte positions in the compressed genome sequence,
22911
+ //by making use of the compressed index (GZI file)
22912
+
22913
+
22914
+ let allBytes;
22915
+
22916
+ if (!this.compressedIndexFile) {
22917
+ allBytes = await igvxhr.load(this.file, buildOptions(this.config, {
22918
+ range: {
22919
+ start: startByte,
22920
+ size: byteCount
22511
22921
  }
22922
+ }));
22923
+ } else {
22924
+ let relevantBlockIndices = await this.getRelevantCompressedBlockNumbers(startByte, endByte);
22512
22925
 
22513
- return seqBytes;
22926
+ if (relevantBlockIndices.length === 0) {
22927
+ console.log("No blocks in the compressed index that correspond with the requested byte positions (" + startByte + "," + endByte + ")");
22928
+ return null;
22514
22929
  }
22930
+
22931
+ allBytes = await this.loadAndUncompressBlocks(relevantBlockIndices, startByte);
22515
22932
  }
22933
+
22934
+ if (!allBytes) {
22935
+ return null;
22936
+ }
22937
+
22938
+ let nBases,
22939
+ seqBytes = "",
22940
+ srcPos = 0,
22941
+ allBytesLength = allBytes.length;
22942
+
22943
+ if (offset > 0) {
22944
+ nBases = Math.min(end - start, basesPerLine - offset);
22945
+ seqBytes += allBytes.substr(srcPos, nBases);
22946
+ srcPos += nBases + nEndBytes;
22947
+ }
22948
+
22949
+ while (srcPos < allBytesLength) {
22950
+ nBases = Math.min(basesPerLine, allBytesLength - srcPos);
22951
+ seqBytes += allBytes.substr(srcPos, nBases);
22952
+ srcPos += nBases + nEndBytes;
22953
+ }
22954
+
22955
+ return seqBytes;
22516
22956
  }
22517
22957
 
22518
22958
  }
@@ -22620,7 +23060,7 @@
22620
23060
  }
22621
23061
  };
22622
23062
 
22623
- const _version = "2.10.5";
23063
+ const _version = "2.11.0";
22624
23064
 
22625
23065
  function version$1() {
22626
23066
  return _version;
@@ -23130,7 +23570,9 @@
23130
23570
  }
23131
23571
 
23132
23572
  stopSpinner() {
23133
- this.$spinner.hide();
23573
+ if (this.$spinner) {
23574
+ this.$spinner.hide();
23575
+ }
23134
23576
  }
23135
23577
 
23136
23578
  checkZoomIn() {
@@ -23439,7 +23881,7 @@
23439
23881
  const context = new ctx(config);
23440
23882
  const str = (this.trackView.track.name || this.trackView.track.id).replace(/\W/g, '');
23441
23883
  const index = this.browser.referenceFrameList.indexOf(this.referenceFrame);
23442
- const id = `${str}_referenceFrame_${index}_guid_${guid$1()}`;
23884
+ const id = `${str}_referenceFrame_${index}_guid_${guid$2()}`;
23443
23885
  this.drawSVGWithContext(context, width, height, id, 0, 0, 0);
23444
23886
  const svg = context.getSerializedSvg(true);
23445
23887
  const data = URL.createObjectURL(new Blob([svg], {
@@ -23463,7 +23905,7 @@
23463
23905
 
23464
23906
  const str = (this.trackView.track.name || this.trackView.track.id).replace(/\W/g, '');
23465
23907
  const index = this.browser.referenceFrameList.indexOf(this.referenceFrame);
23466
- const id = `${str}_referenceFrame_${index}_guid_${guid$1()}`;
23908
+ const id = `${str}_referenceFrame_${index}_guid_${guid$2()}`;
23467
23909
  const {
23468
23910
  top: yScrollDelta
23469
23911
  } = this.$content.position();
@@ -23487,7 +23929,7 @@
23487
23929
 
23488
23930
  renderTrackLabelSVG(context, tx, ty, width, height) {
23489
23931
  const str = (this.trackView.track.name || this.trackView.track.id).replace(/\W/g, '');
23490
- const id = `${str}_track_label_guid_${guid$1()}`;
23932
+ const id = `${str}_track_label_guid_${guid$2()}`;
23491
23933
  context.saveWithTranslationAndClipRect(id, tx, ty, width, height, 0);
23492
23934
  context.fillStyle = "white";
23493
23935
  context.fillRect(0, 0, width, height);
@@ -23778,24 +24220,16 @@
23778
24220
  str = track.description();
23779
24221
  } else if (track.description) {
23780
24222
  str = `<div>${track.description}</div>`;
23781
- } else {
23782
- if (track.url) {
23783
- if (isFile(track.url)) {
23784
- str = `<div><b>Filename: </b>${track.url.name}`;
23785
- } else {
23786
- str = `<div><b>URL: </b>${track.url}`;
23787
- }
23788
- } else {
23789
- str = track.name;
23790
- }
23791
24223
  }
23792
24224
 
23793
- if (this.popover) {
23794
- this.popover.dispose();
23795
- }
24225
+ if (str) {
24226
+ if (this.popover) {
24227
+ this.popover.dispose();
24228
+ }
23796
24229
 
23797
- this.popover = new Popover(this.browser.columnContainer, track.name || 'unnamed');
23798
- this.popover.presentContentWithEvent(event, str);
24230
+ this.popover = new Popover(this.browser.columnContainer, track.name || '');
24231
+ this.popover.presentContentWithEvent(event, str);
24232
+ }
23799
24233
  }
23800
24234
  }
23801
24235
 
@@ -24090,18 +24524,6 @@
24090
24524
  return this;
24091
24525
  }() || Function('return this')();
24092
24526
 
24093
- var FunctionPrototype$2 = Function.prototype;
24094
- var bind$2 = FunctionPrototype$2.bind;
24095
- var call$2 = FunctionPrototype$2.call;
24096
- var callBind = bind$2 && bind$2.bind(call$2);
24097
- var functionUncurryThis = bind$2 ? function (fn) {
24098
- return fn && callBind(call$2, fn);
24099
- } : function (fn) {
24100
- return fn && function () {
24101
- return call$2.apply(fn, arguments);
24102
- };
24103
- };
24104
-
24105
24527
  var fails = function (exec) {
24106
24528
  try {
24107
24529
  return !!exec();
@@ -24110,69 +24532,114 @@
24110
24532
  }
24111
24533
  };
24112
24534
 
24535
+ var functionBindNative = !fails(function () {
24536
+ var test = function () {
24537
+ /* empty */
24538
+ }.bind(); // eslint-disable-next-line no-prototype-builtins -- safe
24539
+
24540
+
24541
+ return typeof test != 'function' || test.hasOwnProperty('prototype');
24542
+ });
24543
+
24544
+ var call$2 = Function.prototype.call;
24545
+ var functionCall = functionBindNative ? call$2.bind(call$2) : function () {
24546
+ return call$2.apply(call$2, arguments);
24547
+ };
24548
+
24549
+ // eslint-disable-next-line es/no-typed-arrays -- safe
24550
+ var arrayBufferNative = typeof ArrayBuffer != 'undefined' && typeof DataView != 'undefined';
24551
+
24552
+ var descriptors = !fails(function () {
24553
+ // eslint-disable-next-line es/no-object-defineproperty -- required for testing
24554
+ return Object.defineProperty({}, 1, {
24555
+ get: function () {
24556
+ return 7;
24557
+ }
24558
+ })[1] != 7;
24559
+ });
24560
+
24113
24561
  // `IsCallable` abstract operation
24114
24562
  // https://tc39.es/ecma262/#sec-iscallable
24115
24563
  var isCallable = function (argument) {
24116
24564
  return typeof argument == 'function';
24117
24565
  };
24118
24566
 
24119
- var String$4 = global$1.String;
24567
+ var isObject = function (it) {
24568
+ return typeof it == 'object' ? it !== null : isCallable(it);
24569
+ };
24120
24570
 
24121
- var tryToString = function (argument) {
24122
- try {
24123
- return String$4(argument);
24124
- } catch (error) {
24125
- return 'Object';
24126
- }
24571
+ var FunctionPrototype$2 = Function.prototype;
24572
+ var bind$1 = FunctionPrototype$2.bind;
24573
+ var call$1 = FunctionPrototype$2.call;
24574
+ var uncurryThis = functionBindNative && bind$1.bind(call$1, call$1);
24575
+ var functionUncurryThis = functionBindNative ? function (fn) {
24576
+ return fn && uncurryThis(fn);
24577
+ } : function (fn) {
24578
+ return fn && function () {
24579
+ return call$1.apply(fn, arguments);
24580
+ };
24127
24581
  };
24128
24582
 
24129
- var TypeError$9 = global$1.TypeError; // `Assert: IsCallable(argument) is true`
24583
+ var TypeError$a = global$1.TypeError; // `RequireObjectCoercible` abstract operation
24584
+ // https://tc39.es/ecma262/#sec-requireobjectcoercible
24130
24585
 
24131
- var aCallable = function (argument) {
24132
- if (isCallable(argument)) return argument;
24133
- throw TypeError$9(tryToString(argument) + ' is not a function');
24586
+ var requireObjectCoercible = function (it) {
24587
+ if (it == undefined) throw TypeError$a("Can't call method on " + it);
24588
+ return it;
24134
24589
  };
24135
24590
 
24136
- var ceil = Math.ceil;
24137
- var floor$1 = Math.floor; // `ToIntegerOrInfinity` abstract operation
24138
- // https://tc39.es/ecma262/#sec-tointegerorinfinity
24139
-
24140
- var toIntegerOrInfinity = function (argument) {
24141
- var number = +argument; // eslint-disable-next-line no-self-compare -- safe
24591
+ var Object$5 = global$1.Object; // `ToObject` abstract operation
24592
+ // https://tc39.es/ecma262/#sec-toobject
24142
24593
 
24143
- return number !== number || number === 0 ? 0 : (number > 0 ? floor$1 : ceil)(number);
24594
+ var toObject = function (argument) {
24595
+ return Object$5(requireObjectCoercible(argument));
24144
24596
  };
24145
24597
 
24146
- var max$1 = Math.max;
24147
- var min$1 = Math.min; // Helper for a popular repeating case of the spec:
24148
- // Let integer be ? ToInteger(index).
24149
- // If integer < 0, let result be max((length + integer), 0); else let result be min(integer, length).
24598
+ var hasOwnProperty = functionUncurryThis({}.hasOwnProperty); // `HasOwnProperty` abstract operation
24599
+ // https://tc39.es/ecma262/#sec-hasownproperty
24150
24600
 
24151
- var toAbsoluteIndex = function (index, length) {
24152
- var integer = toIntegerOrInfinity(index);
24153
- return integer < 0 ? max$1(integer + length, 0) : min$1(integer, length);
24601
+ var hasOwnProperty_1 = Object.hasOwn || function hasOwn(it, key) {
24602
+ return hasOwnProperty(toObject(it), key);
24154
24603
  };
24155
24604
 
24156
- var min = Math.min; // `ToLength` abstract operation
24157
- // https://tc39.es/ecma262/#sec-tolength
24605
+ var defineProperty$1 = Object.defineProperty;
24158
24606
 
24159
- var toLength = function (argument) {
24160
- return argument > 0 ? min(toIntegerOrInfinity(argument), 0x1FFFFFFFFFFFFF) : 0; // 2 ** 53 - 1 == 9007199254740991
24607
+ var setGlobal = function (key, value) {
24608
+ try {
24609
+ defineProperty$1(global$1, key, {
24610
+ value: value,
24611
+ configurable: true,
24612
+ writable: true
24613
+ });
24614
+ } catch (error) {
24615
+ global$1[key] = value;
24616
+ }
24617
+
24618
+ return value;
24161
24619
  };
24162
24620
 
24163
- // https://tc39.es/ecma262/#sec-lengthofarraylike
24621
+ var SHARED = '__core-js_shared__';
24622
+ var store$1 = global$1[SHARED] || setGlobal(SHARED, {});
24623
+ var sharedStore = store$1;
24164
24624
 
24165
- var lengthOfArrayLike = function (obj) {
24166
- return toLength(obj.length);
24167
- };
24625
+ var shared = createCommonjsModule(function (module) {
24626
+ (module.exports = function (key, value) {
24627
+ return sharedStore[key] || (sharedStore[key] = value !== undefined ? value : {});
24628
+ })('versions', []).push({
24629
+ version: '3.21.1',
24630
+ mode: 'global',
24631
+ copyright: '© 2014-2022 Denis Pushkarev (zloirock.ru)',
24632
+ license: 'https://github.com/zloirock/core-js/blob/v3.21.1/LICENSE',
24633
+ source: 'https://github.com/zloirock/core-js'
24634
+ });
24635
+ });
24168
24636
 
24169
- var call$1 = Function.prototype.call;
24170
- var functionCall = call$1.bind ? call$1.bind(call$1) : function () {
24171
- return call$1.apply(call$1, arguments);
24172
- };
24637
+ var id = 0;
24638
+ var postfix = Math.random();
24639
+ var toString$1 = functionUncurryThis(1.0.toString);
24173
24640
 
24174
- var isObject = function (it) {
24175
- return typeof it == 'object' ? it !== null : isCallable(it);
24641
+ var uid = function (key) {
24642
+ return 'Symbol(' + (key === undefined ? '' : key) + ')_' + toString$1(++id + postfix, 36);
24176
24643
  };
24177
24644
 
24178
24645
  var aFunction = function (argument) {
@@ -24183,8 +24650,6 @@
24183
24650
  return arguments.length < 2 ? aFunction(global$1[namespace]) : global$1[namespace] && global$1[namespace][method];
24184
24651
  };
24185
24652
 
24186
- var objectIsPrototypeOf = functionUncurryThis({}.isPrototypeOf);
24187
-
24188
24653
  var engineUserAgent = getBuiltIn('navigator', 'userAgent') || '';
24189
24654
 
24190
24655
  var process$2 = global$1.process;
@@ -24226,111 +24691,143 @@
24226
24691
  /* eslint-disable es/no-symbol -- required for testing */
24227
24692
  var useSymbolAsUid = nativeSymbol && !Symbol.sham && typeof Symbol.iterator == 'symbol';
24228
24693
 
24229
- var Object$5 = global$1.Object;
24230
- var isSymbol = useSymbolAsUid ? function (it) {
24231
- return typeof it == 'symbol';
24232
- } : function (it) {
24233
- var $Symbol = getBuiltIn('Symbol');
24234
- return isCallable($Symbol) && objectIsPrototypeOf($Symbol.prototype, Object$5(it));
24235
- };
24694
+ var WellKnownSymbolsStore = shared('wks');
24695
+ var Symbol$1 = global$1.Symbol;
24696
+ var symbolFor = Symbol$1 && Symbol$1['for'];
24697
+ var createWellKnownSymbol = useSymbolAsUid ? Symbol$1 : Symbol$1 && Symbol$1.withoutSetter || uid;
24236
24698
 
24237
- // https://tc39.es/ecma262/#sec-getmethod
24699
+ var wellKnownSymbol = function (name) {
24700
+ if (!hasOwnProperty_1(WellKnownSymbolsStore, name) || !(nativeSymbol || typeof WellKnownSymbolsStore[name] == 'string')) {
24701
+ var description = 'Symbol.' + name;
24238
24702
 
24239
- var getMethod = function (V, P) {
24240
- var func = V[P];
24241
- return func == null ? undefined : aCallable(func);
24703
+ if (nativeSymbol && hasOwnProperty_1(Symbol$1, name)) {
24704
+ WellKnownSymbolsStore[name] = Symbol$1[name];
24705
+ } else if (useSymbolAsUid && symbolFor) {
24706
+ WellKnownSymbolsStore[name] = symbolFor(description);
24707
+ } else {
24708
+ WellKnownSymbolsStore[name] = createWellKnownSymbol(description);
24709
+ }
24710
+ }
24711
+
24712
+ return WellKnownSymbolsStore[name];
24242
24713
  };
24243
24714
 
24244
- var TypeError$8 = global$1.TypeError; // `OrdinaryToPrimitive` abstract operation
24245
- // https://tc39.es/ecma262/#sec-ordinarytoprimitive
24715
+ var TO_STRING_TAG$2 = wellKnownSymbol('toStringTag');
24716
+ var test = {};
24717
+ test[TO_STRING_TAG$2] = 'z';
24718
+ var toStringTagSupport = String(test) === '[object z]';
24246
24719
 
24247
- var ordinaryToPrimitive = function (input, pref) {
24248
- var fn, val;
24249
- if (pref === 'string' && isCallable(fn = input.toString) && !isObject(val = functionCall(fn, input))) return val;
24250
- if (isCallable(fn = input.valueOf) && !isObject(val = functionCall(fn, input))) return val;
24251
- if (pref !== 'string' && isCallable(fn = input.toString) && !isObject(val = functionCall(fn, input))) return val;
24252
- throw TypeError$8("Can't convert object to primitive value");
24720
+ var toString = functionUncurryThis({}.toString);
24721
+ var stringSlice = functionUncurryThis(''.slice);
24722
+
24723
+ var classofRaw = function (it) {
24724
+ return stringSlice(toString(it), 8, -1);
24253
24725
  };
24254
24726
 
24255
- var defineProperty$1 = Object.defineProperty;
24727
+ var TO_STRING_TAG$1 = wellKnownSymbol('toStringTag');
24728
+ var Object$4 = global$1.Object; // ES3 wrong here
24256
24729
 
24257
- var setGlobal = function (key, value) {
24730
+ var CORRECT_ARGUMENTS = classofRaw(function () {
24731
+ return arguments;
24732
+ }()) == 'Arguments'; // fallback for IE11 Script Access Denied error
24733
+
24734
+ var tryGet = function (it, key) {
24258
24735
  try {
24259
- defineProperty$1(global$1, key, {
24260
- value: value,
24261
- configurable: true,
24262
- writable: true
24263
- });
24736
+ return it[key];
24264
24737
  } catch (error) {
24265
- global$1[key] = value;
24738
+ /* empty */
24266
24739
  }
24740
+ }; // getting tag from ES6+ `Object.prototype.toString`
24267
24741
 
24268
- return value;
24742
+
24743
+ var classof = toStringTagSupport ? classofRaw : function (it) {
24744
+ var O, tag, result;
24745
+ return it === undefined ? 'Undefined' : it === null ? 'Null' // @@toStringTag case
24746
+ : typeof (tag = tryGet(O = Object$4(it), TO_STRING_TAG$1)) == 'string' ? tag // builtinTag case
24747
+ : CORRECT_ARGUMENTS ? classofRaw(O) // ES3 arguments fallback
24748
+ : (result = classofRaw(O)) == 'Object' && isCallable(O.callee) ? 'Arguments' : result;
24269
24749
  };
24270
24750
 
24271
- var SHARED = '__core-js_shared__';
24272
- var store$1 = global$1[SHARED] || setGlobal(SHARED, {});
24273
- var sharedStore = store$1;
24751
+ var String$4 = global$1.String;
24274
24752
 
24275
- var shared = createCommonjsModule(function (module) {
24276
- (module.exports = function (key, value) {
24277
- return sharedStore[key] || (sharedStore[key] = value !== undefined ? value : {});
24278
- })('versions', []).push({
24279
- version: '3.19.3',
24280
- mode: 'global',
24281
- copyright: '© 2021 Denis Pushkarev (zloirock.ru)'
24282
- });
24283
- });
24753
+ var tryToString = function (argument) {
24754
+ try {
24755
+ return String$4(argument);
24756
+ } catch (error) {
24757
+ return 'Object';
24758
+ }
24759
+ };
24284
24760
 
24285
- var TypeError$7 = global$1.TypeError; // `RequireObjectCoercible` abstract operation
24286
- // https://tc39.es/ecma262/#sec-requireobjectcoercible
24761
+ var document$1 = global$1.document; // typeof document.createElement is 'object' in old IE
24287
24762
 
24288
- var requireObjectCoercible = function (it) {
24289
- if (it == undefined) throw TypeError$7("Can't call method on " + it);
24290
- return it;
24763
+ var EXISTS$1 = isObject(document$1) && isObject(document$1.createElement);
24764
+
24765
+ var documentCreateElement = function (it) {
24766
+ return EXISTS$1 ? document$1.createElement(it) : {};
24291
24767
  };
24292
24768
 
24293
- var Object$4 = global$1.Object; // `ToObject` abstract operation
24294
- // https://tc39.es/ecma262/#sec-toobject
24769
+ var ie8DomDefine = !descriptors && !fails(function () {
24770
+ // eslint-disable-next-line es/no-object-defineproperty -- required for testing
24771
+ return Object.defineProperty(documentCreateElement('div'), 'a', {
24772
+ get: function () {
24773
+ return 7;
24774
+ }
24775
+ }).a != 7;
24776
+ });
24295
24777
 
24296
- var toObject = function (argument) {
24297
- return Object$4(requireObjectCoercible(argument));
24778
+ // https://bugs.chromium.org/p/v8/issues/detail?id=3334
24779
+
24780
+ var v8PrototypeDefineBug = descriptors && fails(function () {
24781
+ // eslint-disable-next-line es/no-object-defineproperty -- required for testing
24782
+ return Object.defineProperty(function () {
24783
+ /* empty */
24784
+ }, 'prototype', {
24785
+ value: 42,
24786
+ writable: false
24787
+ }).prototype != 42;
24788
+ });
24789
+
24790
+ var String$3 = global$1.String;
24791
+ var TypeError$9 = global$1.TypeError; // `Assert: Type(argument) is Object`
24792
+
24793
+ var anObject = function (argument) {
24794
+ if (isObject(argument)) return argument;
24795
+ throw TypeError$9(String$3(argument) + ' is not an object');
24298
24796
  };
24299
24797
 
24300
- var hasOwnProperty = functionUncurryThis({}.hasOwnProperty); // `HasOwnProperty` abstract operation
24301
- // https://tc39.es/ecma262/#sec-hasownproperty
24798
+ var objectIsPrototypeOf = functionUncurryThis({}.isPrototypeOf);
24302
24799
 
24303
- var hasOwnProperty_1 = Object.hasOwn || function hasOwn(it, key) {
24304
- return hasOwnProperty(toObject(it), key);
24800
+ var Object$3 = global$1.Object;
24801
+ var isSymbol = useSymbolAsUid ? function (it) {
24802
+ return typeof it == 'symbol';
24803
+ } : function (it) {
24804
+ var $Symbol = getBuiltIn('Symbol');
24805
+ return isCallable($Symbol) && objectIsPrototypeOf($Symbol.prototype, Object$3(it));
24305
24806
  };
24306
24807
 
24307
- var id = 0;
24308
- var postfix = Math.random();
24309
- var toString$1 = functionUncurryThis(1.0.toString);
24808
+ var TypeError$8 = global$1.TypeError; // `Assert: IsCallable(argument) is true`
24310
24809
 
24311
- var uid = function (key) {
24312
- return 'Symbol(' + (key === undefined ? '' : key) + ')_' + toString$1(++id + postfix, 36);
24810
+ var aCallable = function (argument) {
24811
+ if (isCallable(argument)) return argument;
24812
+ throw TypeError$8(tryToString(argument) + ' is not a function');
24313
24813
  };
24314
24814
 
24315
- var WellKnownSymbolsStore = shared('wks');
24316
- var Symbol$1 = global$1.Symbol;
24317
- var symbolFor = Symbol$1 && Symbol$1['for'];
24318
- var createWellKnownSymbol = useSymbolAsUid ? Symbol$1 : Symbol$1 && Symbol$1.withoutSetter || uid;
24815
+ // https://tc39.es/ecma262/#sec-getmethod
24319
24816
 
24320
- var wellKnownSymbol = function (name) {
24321
- if (!hasOwnProperty_1(WellKnownSymbolsStore, name) || !(nativeSymbol || typeof WellKnownSymbolsStore[name] == 'string')) {
24322
- var description = 'Symbol.' + name;
24817
+ var getMethod = function (V, P) {
24818
+ var func = V[P];
24819
+ return func == null ? undefined : aCallable(func);
24820
+ };
24323
24821
 
24324
- if (nativeSymbol && hasOwnProperty_1(Symbol$1, name)) {
24325
- WellKnownSymbolsStore[name] = Symbol$1[name];
24326
- } else if (useSymbolAsUid && symbolFor) {
24327
- WellKnownSymbolsStore[name] = symbolFor(description);
24328
- } else {
24329
- WellKnownSymbolsStore[name] = createWellKnownSymbol(description);
24330
- }
24331
- }
24822
+ var TypeError$7 = global$1.TypeError; // `OrdinaryToPrimitive` abstract operation
24823
+ // https://tc39.es/ecma262/#sec-ordinarytoprimitive
24332
24824
 
24333
- return WellKnownSymbolsStore[name];
24825
+ var ordinaryToPrimitive = function (input, pref) {
24826
+ var fn, val;
24827
+ if (pref === 'string' && isCallable(fn = input.toString) && !isObject(val = functionCall(fn, input))) return val;
24828
+ if (isCallable(fn = input.valueOf) && !isObject(val = functionCall(fn, input))) return val;
24829
+ if (pref !== 'string' && isCallable(fn = input.toString) && !isObject(val = functionCall(fn, input))) return val;
24830
+ throw TypeError$7("Can't convert object to primitive value");
24334
24831
  };
24335
24832
 
24336
24833
  var TypeError$6 = global$1.TypeError;
@@ -24360,46 +24857,36 @@
24360
24857
  return isSymbol(key) ? key : key + '';
24361
24858
  };
24362
24859
 
24363
- var descriptors = !fails(function () {
24364
- // eslint-disable-next-line es/no-object-defineproperty -- required for testing
24365
- return Object.defineProperty({}, 1, {
24366
- get: function () {
24367
- return 7;
24368
- }
24369
- })[1] != 7;
24370
- });
24860
+ var TypeError$5 = global$1.TypeError; // eslint-disable-next-line es/no-object-defineproperty -- safe
24371
24861
 
24372
- var document$1 = global$1.document; // typeof document.createElement is 'object' in old IE
24862
+ var $defineProperty = Object.defineProperty; // eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
24373
24863
 
24374
- var EXISTS$1 = isObject(document$1) && isObject(document$1.createElement);
24375
-
24376
- var documentCreateElement = function (it) {
24377
- return EXISTS$1 ? document$1.createElement(it) : {};
24378
- };
24379
-
24380
- var ie8DomDefine = !descriptors && !fails(function () {
24381
- // eslint-disable-next-line es/no-object-defineproperty -- requied for testing
24382
- return Object.defineProperty(documentCreateElement('div'), 'a', {
24383
- get: function () {
24384
- return 7;
24385
- }
24386
- }).a != 7;
24387
- });
24388
-
24389
- var String$3 = global$1.String;
24390
- var TypeError$5 = global$1.TypeError; // `Assert: Type(argument) is Object`
24864
+ var $getOwnPropertyDescriptor$1 = Object.getOwnPropertyDescriptor;
24865
+ var ENUMERABLE = 'enumerable';
24866
+ var CONFIGURABLE$1 = 'configurable';
24867
+ var WRITABLE = 'writable'; // `Object.defineProperty` method
24868
+ // https://tc39.es/ecma262/#sec-object.defineproperty
24391
24869
 
24392
- var anObject = function (argument) {
24393
- if (isObject(argument)) return argument;
24394
- throw TypeError$5(String$3(argument) + ' is not an object');
24395
- };
24870
+ var f$4 = descriptors ? v8PrototypeDefineBug ? function defineProperty(O, P, Attributes) {
24871
+ anObject(O);
24872
+ P = toPropertyKey(P);
24873
+ anObject(Attributes);
24396
24874
 
24397
- var TypeError$4 = global$1.TypeError; // eslint-disable-next-line es/no-object-defineproperty -- safe
24875
+ if (typeof O === 'function' && P === 'prototype' && 'value' in Attributes && WRITABLE in Attributes && !Attributes[WRITABLE]) {
24876
+ var current = $getOwnPropertyDescriptor$1(O, P);
24398
24877
 
24399
- var $defineProperty = Object.defineProperty; // `Object.defineProperty` method
24400
- // https://tc39.es/ecma262/#sec-object.defineproperty
24878
+ if (current && current[WRITABLE]) {
24879
+ O[P] = Attributes.value;
24880
+ Attributes = {
24881
+ configurable: CONFIGURABLE$1 in Attributes ? Attributes[CONFIGURABLE$1] : current[CONFIGURABLE$1],
24882
+ enumerable: ENUMERABLE in Attributes ? Attributes[ENUMERABLE] : current[ENUMERABLE],
24883
+ writable: false
24884
+ };
24885
+ }
24886
+ }
24401
24887
 
24402
- var f$4 = descriptors ? $defineProperty : function defineProperty(O, P, Attributes) {
24888
+ return $defineProperty(O, P, Attributes);
24889
+ } : $defineProperty : function defineProperty(O, P, Attributes) {
24403
24890
  anObject(O);
24404
24891
  P = toPropertyKey(P);
24405
24892
  anObject(Attributes);
@@ -24408,7 +24895,7 @@
24408
24895
  } catch (error) {
24409
24896
  /* empty */
24410
24897
  }
24411
- if ('get' in Attributes || 'set' in Attributes) throw TypeError$4('Accessors not supported');
24898
+ if ('get' in Attributes || 'set' in Attributes) throw TypeError$5('Accessors not supported');
24412
24899
  if ('value' in Attributes) O[P] = Attributes.value;
24413
24900
  return O;
24414
24901
  };
@@ -24425,107 +24912,6 @@
24425
24912
  };
24426
24913
  };
24427
24914
 
24428
- var createProperty = function (object, key, value) {
24429
- var propertyKey = toPropertyKey(key);
24430
- if (propertyKey in object) objectDefineProperty.f(object, propertyKey, createPropertyDescriptor(0, value));else object[propertyKey] = value;
24431
- };
24432
-
24433
- var Array$2 = global$1.Array;
24434
- var max = Math.max;
24435
-
24436
- var arraySliceSimple = function (O, start, end) {
24437
- var length = lengthOfArrayLike(O);
24438
- var k = toAbsoluteIndex(start, length);
24439
- var fin = toAbsoluteIndex(end === undefined ? length : end, length);
24440
- var result = Array$2(max(fin - k, 0));
24441
-
24442
- for (var n = 0; k < fin; k++, n++) createProperty(result, n, O[k]);
24443
-
24444
- result.length = n;
24445
- return result;
24446
- };
24447
-
24448
- var floor = Math.floor;
24449
-
24450
- var mergeSort = function (array, comparefn) {
24451
- var length = array.length;
24452
- var middle = floor(length / 2);
24453
- return length < 8 ? insertionSort(array, comparefn) : merge(array, mergeSort(arraySliceSimple(array, 0, middle), comparefn), mergeSort(arraySliceSimple(array, middle), comparefn), comparefn);
24454
- };
24455
-
24456
- var insertionSort = function (array, comparefn) {
24457
- var length = array.length;
24458
- var i = 1;
24459
- var element, j;
24460
-
24461
- while (i < length) {
24462
- j = i;
24463
- element = array[i];
24464
-
24465
- while (j && comparefn(array[j - 1], element) > 0) {
24466
- array[j] = array[--j];
24467
- }
24468
-
24469
- if (j !== i++) array[j] = element;
24470
- }
24471
-
24472
- return array;
24473
- };
24474
-
24475
- var merge = function (array, left, right, comparefn) {
24476
- var llength = left.length;
24477
- var rlength = right.length;
24478
- var lindex = 0;
24479
- var rindex = 0;
24480
-
24481
- while (lindex < llength || rindex < rlength) {
24482
- array[lindex + rindex] = lindex < llength && rindex < rlength ? comparefn(left[lindex], right[rindex]) <= 0 ? left[lindex++] : right[rindex++] : lindex < llength ? left[lindex++] : right[rindex++];
24483
- }
24484
-
24485
- return array;
24486
- };
24487
-
24488
- var arraySort = mergeSort;
24489
-
24490
- // eslint-disable-next-line es/no-typed-arrays -- safe
24491
- var arrayBufferNative = typeof ArrayBuffer != 'undefined' && typeof DataView != 'undefined';
24492
-
24493
- var TO_STRING_TAG$2 = wellKnownSymbol('toStringTag');
24494
- var test = {};
24495
- test[TO_STRING_TAG$2] = 'z';
24496
- var toStringTagSupport = String(test) === '[object z]';
24497
-
24498
- var toString = functionUncurryThis({}.toString);
24499
- var stringSlice = functionUncurryThis(''.slice);
24500
-
24501
- var classofRaw = function (it) {
24502
- return stringSlice(toString(it), 8, -1);
24503
- };
24504
-
24505
- var TO_STRING_TAG$1 = wellKnownSymbol('toStringTag');
24506
- var Object$3 = global$1.Object; // ES3 wrong here
24507
-
24508
- var CORRECT_ARGUMENTS = classofRaw(function () {
24509
- return arguments;
24510
- }()) == 'Arguments'; // fallback for IE11 Script Access Denied error
24511
-
24512
- var tryGet = function (it, key) {
24513
- try {
24514
- return it[key];
24515
- } catch (error) {
24516
- /* empty */
24517
- }
24518
- }; // getting tag from ES6+ `Object.prototype.toString`
24519
-
24520
-
24521
- var classof = toStringTagSupport ? classofRaw : function (it) {
24522
- var O, tag, result;
24523
- return it === undefined ? 'Undefined' : it === null ? 'Null' // @@toStringTag case
24524
- : typeof (tag = tryGet(O = Object$3(it), TO_STRING_TAG$1)) == 'string' ? tag // builtinTag case
24525
- : CORRECT_ARGUMENTS ? classofRaw(O) // ES3 arguments fallback
24526
- : (result = classofRaw(O)) == 'Object' && isCallable(O.callee) ? 'Arguments' : result;
24527
- };
24528
-
24529
24915
  var createNonEnumerableProperty = descriptors ? function (object, key, value) {
24530
24916
  return objectDefineProperty.f(object, key, createPropertyDescriptor(1, value));
24531
24917
  } : function (object, key, value) {
@@ -24555,7 +24941,7 @@
24555
24941
  var hiddenKeys$1 = {};
24556
24942
 
24557
24943
  var OBJECT_ALREADY_INITIALIZED = 'Object already initialized';
24558
- var TypeError$3 = global$1.TypeError;
24944
+ var TypeError$4 = global$1.TypeError;
24559
24945
  var WeakMap = global$1.WeakMap;
24560
24946
  var set$1, get, has;
24561
24947
 
@@ -24568,7 +24954,7 @@
24568
24954
  var state;
24569
24955
 
24570
24956
  if (!isObject(it) || (state = get(it)).type !== TYPE) {
24571
- throw TypeError$3('Incompatible receiver, ' + TYPE + ' required');
24957
+ throw TypeError$4('Incompatible receiver, ' + TYPE + ' required');
24572
24958
  }
24573
24959
 
24574
24960
  return state;
@@ -24582,7 +24968,7 @@
24582
24968
  var wmset = functionUncurryThis(store.set);
24583
24969
 
24584
24970
  set$1 = function (it, metadata) {
24585
- if (wmhas(store, it)) throw new TypeError$3(OBJECT_ALREADY_INITIALIZED);
24971
+ if (wmhas(store, it)) throw new TypeError$4(OBJECT_ALREADY_INITIALIZED);
24586
24972
  metadata.facade = it;
24587
24973
  wmset(store, it, metadata);
24588
24974
  return metadata;
@@ -24600,7 +24986,7 @@
24600
24986
  hiddenKeys$1[STATE] = true;
24601
24987
 
24602
24988
  set$1 = function (it, metadata) {
24603
- if (hasOwnProperty_1(it, STATE)) throw new TypeError$3(OBJECT_ALREADY_INITIALIZED);
24989
+ if (hasOwnProperty_1(it, STATE)) throw new TypeError$4(OBJECT_ALREADY_INITIALIZED);
24604
24990
  metadata.facade = it;
24605
24991
  createNonEnumerableProperty(it, STATE, metadata);
24606
24992
  return metadata;
@@ -24710,11 +25096,11 @@
24710
25096
  };
24711
25097
 
24712
25098
  var String$2 = global$1.String;
24713
- var TypeError$2 = global$1.TypeError;
25099
+ var TypeError$3 = global$1.TypeError;
24714
25100
 
24715
25101
  var aPossiblePrototype = function (argument) {
24716
25102
  if (typeof argument == 'object' || isCallable(argument)) return argument;
24717
- throw TypeError$2("Can't set " + String$2(argument) + ' as a prototype');
25103
+ throw TypeError$3("Can't set " + String$2(argument) + ' as a prototype');
24718
25104
  };
24719
25105
 
24720
25106
  /* eslint-disable no-proto -- safe */
@@ -24745,20 +25131,20 @@
24745
25131
  }() : undefined);
24746
25132
 
24747
25133
  var defineProperty = objectDefineProperty.f;
24748
- var Int8Array = global$1.Int8Array;
24749
- var Int8ArrayPrototype = Int8Array && Int8Array.prototype;
24750
- var Uint8ClampedArray = global$1.Uint8ClampedArray;
24751
- var Uint8ClampedArrayPrototype = Uint8ClampedArray && Uint8ClampedArray.prototype;
24752
- var TypedArray = Int8Array && objectGetPrototypeOf(Int8Array);
24753
- var TypedArrayPrototype = Int8ArrayPrototype && objectGetPrototypeOf(Int8ArrayPrototype);
25134
+ var Int8Array$1 = global$1.Int8Array;
25135
+ var Int8ArrayPrototype$1 = Int8Array$1 && Int8Array$1.prototype;
25136
+ var Uint8ClampedArray$1 = global$1.Uint8ClampedArray;
25137
+ var Uint8ClampedArrayPrototype = Uint8ClampedArray$1 && Uint8ClampedArray$1.prototype;
25138
+ var TypedArray = Int8Array$1 && objectGetPrototypeOf(Int8Array$1);
25139
+ var TypedArrayPrototype = Int8ArrayPrototype$1 && objectGetPrototypeOf(Int8ArrayPrototype$1);
24754
25140
  var ObjectPrototype = Object.prototype;
24755
- var TypeError$1 = global$1.TypeError;
25141
+ var TypeError$2 = global$1.TypeError;
24756
25142
  var TO_STRING_TAG = wellKnownSymbol('toStringTag');
24757
25143
  var TYPED_ARRAY_TAG = uid('TYPED_ARRAY_TAG');
24758
25144
  var TYPED_ARRAY_CONSTRUCTOR = uid('TYPED_ARRAY_CONSTRUCTOR'); // Fixing native typed arrays in Opera Presto crashes the browser, see #595
24759
25145
 
24760
25146
  var NATIVE_ARRAY_BUFFER_VIEWS = arrayBufferNative && !!objectSetPrototypeOf && classof(global$1.opera) !== 'Opera';
24761
- var TYPED_ARRAY_TAG_REQIRED = false;
25147
+ var TYPED_ARRAY_TAG_REQUIRED = false;
24762
25148
  var NAME, Constructor, Prototype;
24763
25149
  var TypedArrayConstructorsList = {
24764
25150
  Int8Array: 1,
@@ -24790,27 +25176,32 @@
24790
25176
 
24791
25177
  var aTypedArray$1 = function (it) {
24792
25178
  if (isTypedArray(it)) return it;
24793
- throw TypeError$1('Target is not a typed array');
25179
+ throw TypeError$2('Target is not a typed array');
24794
25180
  };
24795
25181
 
24796
25182
  var aTypedArrayConstructor = function (C) {
24797
25183
  if (isCallable(C) && (!objectSetPrototypeOf || objectIsPrototypeOf(TypedArray, C))) return C;
24798
- throw TypeError$1(tryToString(C) + ' is not a typed array constructor');
25184
+ throw TypeError$2(tryToString(C) + ' is not a typed array constructor');
24799
25185
  };
24800
25186
 
24801
- var exportTypedArrayMethod$1 = function (KEY, property, forced) {
25187
+ var exportTypedArrayMethod$1 = function (KEY, property, forced, options) {
24802
25188
  if (!descriptors) return;
24803
25189
  if (forced) for (var ARRAY in TypedArrayConstructorsList) {
24804
25190
  var TypedArrayConstructor = global$1[ARRAY];
24805
25191
  if (TypedArrayConstructor && hasOwnProperty_1(TypedArrayConstructor.prototype, KEY)) try {
24806
25192
  delete TypedArrayConstructor.prototype[KEY];
24807
25193
  } catch (error) {
24808
- /* empty */
25194
+ // old WebKit bug - some methods are non-configurable
25195
+ try {
25196
+ TypedArrayConstructor.prototype[KEY] = property;
25197
+ } catch (error2) {
25198
+ /* empty */
25199
+ }
24809
25200
  }
24810
25201
  }
24811
25202
 
24812
25203
  if (!TypedArrayPrototype[KEY] || forced) {
24813
- redefine(TypedArrayPrototype, KEY, forced ? property : NATIVE_ARRAY_BUFFER_VIEWS && Int8ArrayPrototype[KEY] || property);
25204
+ redefine(TypedArrayPrototype, KEY, forced ? property : NATIVE_ARRAY_BUFFER_VIEWS && Int8ArrayPrototype$1[KEY] || property, options);
24814
25205
  }
24815
25206
  };
24816
25207
 
@@ -24863,7 +25254,7 @@
24863
25254
  if (!NATIVE_ARRAY_BUFFER_VIEWS || !isCallable(TypedArray) || TypedArray === Function.prototype) {
24864
25255
  // eslint-disable-next-line no-shadow -- safe
24865
25256
  TypedArray = function TypedArray() {
24866
- throw TypeError$1('Incorrect invocation');
25257
+ throw TypeError$2('Incorrect invocation');
24867
25258
  };
24868
25259
 
24869
25260
  if (NATIVE_ARRAY_BUFFER_VIEWS) for (NAME in TypedArrayConstructorsList) {
@@ -24884,7 +25275,7 @@
24884
25275
  }
24885
25276
 
24886
25277
  if (descriptors && !hasOwnProperty_1(TypedArrayPrototype, TO_STRING_TAG)) {
24887
- TYPED_ARRAY_TAG_REQIRED = true;
25278
+ TYPED_ARRAY_TAG_REQUIRED = true;
24888
25279
  defineProperty(TypedArrayPrototype, TO_STRING_TAG, {
24889
25280
  get: function () {
24890
25281
  return isObject(this) ? this[TYPED_ARRAY_TAG] : undefined;
@@ -24899,7 +25290,7 @@
24899
25290
  var arrayBufferViewCore = {
24900
25291
  NATIVE_ARRAY_BUFFER_VIEWS: NATIVE_ARRAY_BUFFER_VIEWS,
24901
25292
  TYPED_ARRAY_CONSTRUCTOR: TYPED_ARRAY_CONSTRUCTOR,
24902
- TYPED_ARRAY_TAG: TYPED_ARRAY_TAG_REQIRED && TYPED_ARRAY_TAG,
25293
+ TYPED_ARRAY_TAG: TYPED_ARRAY_TAG_REQUIRED && TYPED_ARRAY_TAG,
24903
25294
  aTypedArray: aTypedArray$1,
24904
25295
  aTypedArrayConstructor: aTypedArrayConstructor,
24905
25296
  exportTypedArrayMethod: exportTypedArrayMethod$1,
@@ -24910,69 +25301,83 @@
24910
25301
  TypedArrayPrototype: TypedArrayPrototype
24911
25302
  };
24912
25303
 
24913
- var firefox = engineUserAgent.match(/firefox\/(\d+)/i);
24914
- var engineFfVersion = !!firefox && +firefox[1];
25304
+ var ceil = Math.ceil;
25305
+ var floor = Math.floor; // `ToIntegerOrInfinity` abstract operation
25306
+ // https://tc39.es/ecma262/#sec-tointegerorinfinity
24915
25307
 
24916
- var engineIsIeOrEdge = /MSIE|Trident/.test(engineUserAgent);
25308
+ var toIntegerOrInfinity = function (argument) {
25309
+ var number = +argument; // eslint-disable-next-line no-self-compare -- safe
24917
25310
 
24918
- var webkit = engineUserAgent.match(/AppleWebKit\/(\d+)\./);
24919
- var engineWebkitVersion = !!webkit && +webkit[1];
25311
+ return number !== number || number === 0 ? 0 : (number > 0 ? floor : ceil)(number);
25312
+ };
24920
25313
 
24921
- var Array$1 = global$1.Array;
24922
- var aTypedArray = arrayBufferViewCore.aTypedArray;
24923
- var exportTypedArrayMethod = arrayBufferViewCore.exportTypedArrayMethod;
24924
- var Uint16Array$1 = global$1.Uint16Array;
24925
- var un$Sort = Uint16Array$1 && functionUncurryThis(Uint16Array$1.prototype.sort); // WebKit
24926
-
24927
- var ACCEPT_INCORRECT_ARGUMENTS = !!un$Sort && !(fails(function () {
24928
- un$Sort(new Uint16Array$1(2), null);
24929
- }) && fails(function () {
24930
- un$Sort(new Uint16Array$1(2), {});
24931
- }));
24932
- var STABLE_SORT = !!un$Sort && !fails(function () {
24933
- // feature detection can be too slow, so check engines versions
24934
- if (engineV8Version) return engineV8Version < 74;
24935
- if (engineFfVersion) return engineFfVersion < 67;
24936
- if (engineIsIeOrEdge) return true;
24937
- if (engineWebkitVersion) return engineWebkitVersion < 602;
24938
- var array = new Uint16Array$1(516);
24939
- var expected = Array$1(516);
24940
- var index, mod;
24941
-
24942
- for (index = 0; index < 516; index++) {
24943
- mod = index % 4;
24944
- array[index] = 515 - index;
24945
- expected[index] = index - 2 * mod + 3;
24946
- }
24947
-
24948
- un$Sort(array, function (a, b) {
24949
- return (a / 4 | 0) - (b / 4 | 0);
24950
- });
25314
+ var min$1 = Math.min; // `ToLength` abstract operation
25315
+ // https://tc39.es/ecma262/#sec-tolength
24951
25316
 
24952
- for (index = 0; index < 516; index++) {
24953
- if (array[index] !== expected[index]) return true;
24954
- }
24955
- });
25317
+ var toLength = function (argument) {
25318
+ return argument > 0 ? min$1(toIntegerOrInfinity(argument), 0x1FFFFFFFFFFFFF) : 0; // 2 ** 53 - 1 == 9007199254740991
25319
+ };
25320
+
25321
+ // https://tc39.es/ecma262/#sec-lengthofarraylike
24956
25322
 
24957
- var getSortCompare = function (comparefn) {
24958
- return function (x, y) {
24959
- if (comparefn !== undefined) return +comparefn(x, y) || 0; // eslint-disable-next-line no-self-compare -- NaN check
25323
+ var lengthOfArrayLike = function (obj) {
25324
+ return toLength(obj.length);
25325
+ };
24960
25326
 
24961
- if (y !== y) return -1; // eslint-disable-next-line no-self-compare -- NaN check
25327
+ var RangeError$3 = global$1.RangeError;
24962
25328
 
24963
- if (x !== x) return 1;
24964
- if (x === 0 && y === 0) return 1 / x > 0 && 1 / y < 0 ? 1 : -1;
24965
- return x > y;
24966
- };
24967
- }; // `%TypedArray%.prototype.sort` method
24968
- // https://tc39.es/ecma262/#sec-%typedarray%.prototype.sort
25329
+ var toPositiveInteger = function (it) {
25330
+ var result = toIntegerOrInfinity(it);
25331
+ if (result < 0) throw RangeError$3("The argument can't be less than 0");
25332
+ return result;
25333
+ };
24969
25334
 
25335
+ var RangeError$2 = global$1.RangeError;
24970
25336
 
24971
- exportTypedArrayMethod('sort', function sort(comparefn) {
24972
- if (comparefn !== undefined) aCallable(comparefn);
24973
- if (STABLE_SORT) return un$Sort(this, comparefn);
24974
- return arraySort(aTypedArray(this), getSortCompare(comparefn));
24975
- }, !STABLE_SORT || ACCEPT_INCORRECT_ARGUMENTS);
25337
+ var toOffset = function (it, BYTES) {
25338
+ var offset = toPositiveInteger(it);
25339
+ if (offset % BYTES) throw RangeError$2('Wrong offset');
25340
+ return offset;
25341
+ };
25342
+
25343
+ var RangeError$1 = global$1.RangeError;
25344
+ var Int8Array = global$1.Int8Array;
25345
+ var Int8ArrayPrototype = Int8Array && Int8Array.prototype;
25346
+ var $set = Int8ArrayPrototype && Int8ArrayPrototype.set;
25347
+ var aTypedArray = arrayBufferViewCore.aTypedArray;
25348
+ var exportTypedArrayMethod = arrayBufferViewCore.exportTypedArrayMethod;
25349
+ var WORKS_WITH_OBJECTS_AND_GEERIC_ON_TYPED_ARRAYS = !fails(function () {
25350
+ // eslint-disable-next-line es/no-typed-arrays -- required for testing
25351
+ var array = new Uint8ClampedArray(2);
25352
+ functionCall($set, array, {
25353
+ length: 1,
25354
+ 0: 3
25355
+ }, 1);
25356
+ return array[1] !== 3;
25357
+ }); // https://bugs.chromium.org/p/v8/issues/detail?id=11294 and other
25358
+
25359
+ var TO_OBJECT_BUG = WORKS_WITH_OBJECTS_AND_GEERIC_ON_TYPED_ARRAYS && arrayBufferViewCore.NATIVE_ARRAY_BUFFER_VIEWS && fails(function () {
25360
+ var array = new Int8Array(2);
25361
+ array.set(1);
25362
+ array.set('2', 1);
25363
+ return array[0] !== 0 || array[1] !== 2;
25364
+ }); // `%TypedArray%.prototype.set` method
25365
+ // https://tc39.es/ecma262/#sec-%typedarray%.prototype.set
25366
+
25367
+ exportTypedArrayMethod('set', function set(arrayLike
25368
+ /* , offset */
25369
+ ) {
25370
+ aTypedArray(this);
25371
+ var offset = toOffset(arguments.length > 1 ? arguments[1] : undefined, 1);
25372
+ var src = toObject(arrayLike);
25373
+ if (WORKS_WITH_OBJECTS_AND_GEERIC_ON_TYPED_ARRAYS) return functionCall($set, this, src, offset);
25374
+ var length = this.length;
25375
+ var len = lengthOfArrayLike(src);
25376
+ var index = 0;
25377
+ if (len + offset > length) throw RangeError$1('Wrong length');
25378
+
25379
+ while (index < len) this[offset + index] = src[index++];
25380
+ }, !WORKS_WITH_OBJECTS_AND_GEERIC_ON_TYPED_ARRAYS || TO_OBJECT_BUG);
24976
25381
 
24977
25382
  /*
24978
25383
  * The MIT License (MIT)
@@ -28578,6 +28983,16 @@
28578
28983
  f: f$2
28579
28984
  };
28580
28985
 
28986
+ var max = Math.max;
28987
+ var min = Math.min; // Helper for a popular repeating case of the spec:
28988
+ // Let integer be ? ToInteger(index).
28989
+ // If integer < 0, let result be max((length + integer), 0); else let result be min(integer, length).
28990
+
28991
+ var toAbsoluteIndex = function (index, length) {
28992
+ var integer = toIntegerOrInfinity(index);
28993
+ return integer < 0 ? max(integer + length, 0) : min(integer, length);
28994
+ };
28995
+
28581
28996
  var createMethod = function (IS_INCLUDES) {
28582
28997
  return function ($this, el, fromIndex) {
28583
28998
  var O = toIndexedObject($this);
@@ -28654,14 +29069,17 @@
28654
29069
  return getOwnPropertySymbols ? concat(keys, getOwnPropertySymbols(it)) : keys;
28655
29070
  };
28656
29071
 
28657
- var copyConstructorProperties = function (target, source) {
29072
+ var copyConstructorProperties = function (target, source, exceptions) {
28658
29073
  var keys = ownKeys(source);
28659
29074
  var defineProperty = objectDefineProperty.f;
28660
29075
  var getOwnPropertyDescriptor = objectGetOwnPropertyDescriptor.f;
28661
29076
 
28662
29077
  for (var i = 0; i < keys.length; i++) {
28663
29078
  var key = keys[i];
28664
- if (!hasOwnProperty_1(target, key)) defineProperty(target, key, getOwnPropertyDescriptor(source, key));
29079
+
29080
+ if (!hasOwnProperty_1(target, key) && !(exceptions && hasOwnProperty_1(exceptions, key))) {
29081
+ defineProperty(target, key, getOwnPropertyDescriptor(source, key));
29082
+ }
28665
29083
  }
28666
29084
  };
28667
29085
 
@@ -28739,10 +29157,9 @@
28739
29157
 
28740
29158
  var FunctionPrototype = Function.prototype;
28741
29159
  var apply = FunctionPrototype.apply;
28742
- var bind$1 = FunctionPrototype.bind;
28743
29160
  var call = FunctionPrototype.call; // eslint-disable-next-line es/no-reflect -- safe
28744
29161
 
28745
- var functionApply = typeof Reflect == 'object' && Reflect.apply || (bind$1 ? call.bind(apply) : function () {
29162
+ var functionApply = typeof Reflect == 'object' && Reflect.apply || (functionBindNative ? call.bind(apply) : function () {
28746
29163
  return call.apply(apply, arguments);
28747
29164
  });
28748
29165
 
@@ -28750,7 +29167,7 @@
28750
29167
 
28751
29168
  var functionBindContext = function (fn, that) {
28752
29169
  aCallable(fn);
28753
- return that === undefined ? fn : bind ? bind(fn, that) : function
29170
+ return that === undefined ? fn : functionBindNative ? bind(fn, that) : function
28754
29171
  /* ...args */
28755
29172
  () {
28756
29173
  return fn.apply(that, arguments);
@@ -28761,6 +29178,13 @@
28761
29178
 
28762
29179
  var arraySlice = functionUncurryThis([].slice);
28763
29180
 
29181
+ var TypeError$1 = global$1.TypeError;
29182
+
29183
+ var validateArgumentsLength = function (passed, required) {
29184
+ if (passed < required) throw TypeError$1('Not enough arguments');
29185
+ return passed;
29186
+ };
29187
+
28764
29188
  var engineIsIos = /(?:ipad|iphone|ipod).*applewebkit/i.test(engineUserAgent);
28765
29189
 
28766
29190
  var engineIsNode = classofRaw(global$1.process) == 'process';
@@ -28809,11 +29233,13 @@
28809
29233
 
28810
29234
 
28811
29235
  if (!set || !clear) {
28812
- set = function setImmediate(fn) {
29236
+ set = function setImmediate(handler) {
29237
+ validateArgumentsLength(arguments.length, 1);
29238
+ var fn = isCallable(handler) ? handler : Function$1(handler);
28813
29239
  var args = arraySlice(arguments, 1);
28814
29240
 
28815
29241
  queue[++counter] = function () {
28816
- functionApply(isCallable(fn) ? fn : Function$1(fn), undefined, args);
29242
+ functionApply(fn, undefined, args);
28817
29243
  };
28818
29244
 
28819
29245
  defer(counter);
@@ -45114,7 +45540,6 @@
45114
45540
  this.config = config;
45115
45541
  this.url = config.url;
45116
45542
  this.type = config.type;
45117
- this.description = config.description;
45118
45543
  this.supportHiDPI = config.supportHiDPI === undefined ? true : config.supportHiDPI;
45119
45544
 
45120
45545
  if (config.name || config.label) {
@@ -45150,6 +45575,15 @@
45150
45575
  this.onclick = config.onclick;
45151
45576
  config.onclick = undefined; // functions cannot be saved in sessions, clear it here.
45152
45577
  }
45578
+
45579
+ if (config.description) {
45580
+ // Override description -- displayed when clicking on track label. Convert to function if neccessary
45581
+ if (typeof config.description === 'function') {
45582
+ this.description = config.description;
45583
+ } else {
45584
+ this.description = () => config.description;
45585
+ }
45586
+ }
45153
45587
  }
45154
45588
 
45155
45589
  get name() {
@@ -45197,7 +45631,7 @@
45197
45631
 
45198
45632
  const value = this[key];
45199
45633
 
45200
- if (value && (isSimpleType(value) || typeof value === "boolean")) {
45634
+ if (value && (isSimpleType(value) || typeof value === "boolean" || key === "metadata")) {
45201
45635
  state[key] = value;
45202
45636
  }
45203
45637
  }
@@ -45212,16 +45646,19 @@
45212
45646
 
45213
45647
 
45214
45648
  for (let key of Object.keys(state)) {
45215
- if (typeof state[key] === 'function') {
45649
+ const value = state[key];
45650
+
45651
+ if (typeof value === 'function') {
45216
45652
  throw Error(`Property '${key}' of track '${this.name} is a function. Functions cannot be saved in sessions.`);
45217
45653
  }
45218
45654
 
45219
- if (isFile(state[key])) {
45655
+ if (value instanceof File) {
45656
+ // Test specifically for File. Other types of File-like objects might be savable
45220
45657
  const str = `Track ${this.name} is a local file. Sessions cannot be saved with local file references.`;
45221
45658
  throw Error(str);
45222
45659
  }
45223
45660
 
45224
- if (state[key] instanceof Promise) {
45661
+ if (value instanceof Promise) {
45225
45662
  throw Error(`Property '${key}' of track '${this.name} is a Promise. Promises cannot be saved in sessions.`);
45226
45663
  }
45227
45664
  }
@@ -45502,6 +45939,54 @@
45502
45939
  });
45503
45940
  return data;
45504
45941
  }
45942
+ /**
45943
+ * Default track description -- displayed on click of track label. This can be overriden in the track
45944
+ * configuration, or in subclasses.
45945
+ */
45946
+
45947
+
45948
+ description() {
45949
+ const wrapKeyValue = (k, v) => `<div class="igv-track-label-popup-shim"><b>${k}: </b>${v}</div>`;
45950
+
45951
+ let str = '<div class="igv-track-label-popup">';
45952
+
45953
+ if (this.url) {
45954
+ if (isFile(this.url)) {
45955
+ str += wrapKeyValue('Filename', this.url.name);
45956
+ } else {
45957
+ str += wrapKeyValue('URL', this.url);
45958
+ }
45959
+ } else {
45960
+ str = this.name;
45961
+ }
45962
+
45963
+ if (this.config) {
45964
+ if (this.config.metadata) {
45965
+ for (let key of Object.keys(this.config.metadata)) {
45966
+ const value = this.config.metadata[key];
45967
+ str += wrapKeyValue(key, value);
45968
+ }
45969
+ } // Add any config properties that are capitalized
45970
+
45971
+
45972
+ for (let key of Object.keys(this.config)) {
45973
+ if (key.startsWith("_")) continue; // transient property
45974
+
45975
+ let first = key.substr(0, 1);
45976
+
45977
+ if (first !== first.toLowerCase()) {
45978
+ const value = this.config[key];
45979
+
45980
+ if (value && isSimpleType(value)) {
45981
+ str += wrapKeyValue(key, value);
45982
+ }
45983
+ }
45984
+ }
45985
+ }
45986
+
45987
+ str += '</div>';
45988
+ return str;
45989
+ }
45505
45990
 
45506
45991
  static getCravatLink(chr, position, ref, alt, genomeID) {
45507
45992
  if ("hg38" === genomeID || "GRCh38" === genomeID) {
@@ -45540,6 +46025,7 @@
45540
46025
  return;
45541
46026
  }
45542
46027
 
46028
+ let flipAxis = undefined === this.flipAxis ? false : this.flipAxis;
45543
46029
  IGVGraphics.fillRect(ctx, 0, 0, pixelWidth, pixelHeight, {
45544
46030
  'fillStyle': "rgb(255, 255, 255)"
45545
46031
  });
@@ -45555,7 +46041,7 @@
45555
46041
  }; // tick
45556
46042
 
45557
46043
  IGVGraphics.strokeLine(ctx, x1, y1, x2, y2, font);
45558
- IGVGraphics.fillText(ctx, prettyPrint(this.dataRange.max), x1 + 4, y1 + 12, font); //shim = 0.25 * 0.125;
46044
+ IGVGraphics.fillText(ctx, prettyPrint(flipAxis ? this.dataRange.min : this.dataRange.max), x1 + 4, y1 + 12, font); //shim = 0.25 * 0.125;
45559
46045
 
45560
46046
  y1 = y2 = (1.0 - shim) * pixelHeight;
45561
46047
  b = {
@@ -45564,7 +46050,7 @@
45564
46050
  }; // tick
45565
46051
 
45566
46052
  IGVGraphics.strokeLine(ctx, x1, y1, x2, y2, font);
45567
- IGVGraphics.fillText(ctx, prettyPrint(this.dataRange.min), x1 + 4, y1 - 4, font);
46053
+ IGVGraphics.fillText(ctx, prettyPrint(flipAxis ? this.dataRange.max : this.dataRange.min), x1 + 4, y1 - 4, font);
45568
46054
  IGVGraphics.strokeLine(ctx, a.x, a.y, b.x, b.y, font);
45569
46055
 
45570
46056
  function prettyPrint(number) {
@@ -47239,6 +47725,77 @@
47239
47725
  "chr48": "rgb(20, 255, 177)"
47240
47726
  };
47241
47727
 
47728
+ class ChordSetManager {
47729
+ constructor(config) {
47730
+ this.tracks = [];
47731
+ this.chordSets = [];
47732
+ }
47733
+
47734
+ addChordSet(chordSet) {
47735
+ // If a chord set with this name exists replace it (same track, same region)
47736
+ this.chordSets = this.chordSets.filter(g => g.name !== chordSet.name);
47737
+ this.chordSets.push(chordSet);
47738
+ let track = this.tracks.find(t => chordSet.trackName === t.name);
47739
+
47740
+ if (track) {
47741
+ track.chordSets = track.chordSets.filter(cs => cs.name !== chordSet.name);
47742
+ track.chordSets.push(chordSet);
47743
+ }
47744
+
47745
+ if (!track) {
47746
+ track = new IGVTrack(chordSet);
47747
+ this.tracks.push(track);
47748
+ }
47749
+ }
47750
+
47751
+ clearChords() {
47752
+ this.tracks = [];
47753
+ this.chordSets = [];
47754
+ }
47755
+
47756
+ getTrack(name) {
47757
+ return this.tracks.find(t => name === t.name);
47758
+ }
47759
+
47760
+ getChordset(name) {
47761
+ return this.chordSets.find(cs => name === cs.name);
47762
+ }
47763
+
47764
+ }
47765
+
47766
+ class IGVTrack {
47767
+ constructor(chordSet) {
47768
+ this.name = chordSet.trackName;
47769
+ this.color = chordSet.trackColor;
47770
+ this.visible = true;
47771
+ this.chordSets = [chordSet];
47772
+ this.id = guid$1();
47773
+ }
47774
+
47775
+ get chords() {
47776
+ if (this.chordSets.length === 1) {
47777
+ return this.chordSets[0].chords;
47778
+ }
47779
+
47780
+ const chords = [];
47781
+
47782
+ for (let cs of this.chordSets) {
47783
+ for (let c of cs.chords) {
47784
+ chords.push(c);
47785
+ }
47786
+ }
47787
+
47788
+ return chords;
47789
+ }
47790
+
47791
+ }
47792
+
47793
+ function guid$1() {
47794
+ return ("0000" + (Math.random() * Math.pow(36, 4) << 0).toString(36)).slice(-4);
47795
+ }
47796
+
47797
+ const EXP5 = Math.exp(5);
47798
+
47242
47799
  class CircularView {
47243
47800
  static isInstalled() {
47244
47801
  return window["JBrowseReactCircularGenomeView"] !== undefined && window["React"] !== undefined && window["ReactDOM"] !== undefined;
@@ -47260,13 +47817,16 @@
47260
47817
  this.config = config;
47261
47818
 
47262
47819
  if (CircularView.isInstalled()) {
47263
- this.parent = parent; // wrapper for toolbar and circular-view container
47820
+ this.parent = parent;
47821
+ this.groupByTrack = config.groupByTrack === true;
47822
+ this.chordManager = new ChordSetManager(config); // wrapper for toolbar and circular-view container
47264
47823
 
47265
47824
  const wrapper = document.createElement('div');
47266
47825
  wrapper.className = 'igv-circview-container';
47267
47826
  parent.appendChild(wrapper); // toolbar
47268
47827
 
47269
- this.createToolbarAndTrackPanel(wrapper); // circular view container
47828
+ this.createControls(wrapper);
47829
+ this.resetControlPanel(); // circular view container
47270
47830
 
47271
47831
  const element = document.createElement('div');
47272
47832
  element.className = 'igv-circview-circular-genome-view';
@@ -47277,7 +47837,6 @@
47277
47837
  this.setAssembly(config.assembly);
47278
47838
  }
47279
47839
 
47280
- this.tracks = config.tracks || [];
47281
47840
  this.width = config.width || 500;
47282
47841
  this.height = config.height || 500;
47283
47842
  this.setSize(this.width, this.height);
@@ -47286,41 +47845,40 @@
47286
47845
  }
47287
47846
  }
47288
47847
 
47289
- createToolbarAndTrackPanel(parent) {
47290
- let element; // toolbar
47291
-
47292
- element = document.createElement('div');
47293
- element.className = 'igv-circview-toolbar';
47294
- parent.appendChild(element);
47295
- this.toolbar = element; // track panel
47848
+ createControls(parent) {
47849
+ // toolbar
47850
+ const toolbarDiv = document.createElement('div');
47851
+ toolbarDiv.className = 'igv-circview-toolbar';
47852
+ parent.appendChild(toolbarDiv);
47853
+ this.toolbar = toolbarDiv; // control panel
47296
47854
 
47297
- element = document.createElement('div');
47298
- element.className = 'igv-circview-track-panel';
47299
- parent.appendChild(element);
47300
- this.trackPanel = element;
47301
- this.trackPanel.style.display = 'none'; // toolbar button container - Track Options - Clear All
47855
+ const controlPanelDiv = document.createElement('div');
47856
+ controlPanelDiv.className = 'igv-circview-track-panel';
47857
+ parent.appendChild(controlPanelDiv);
47858
+ this.controlPanel = controlPanelDiv;
47859
+ this.controlPanel.style.display = 'none'; // toolbar button container - Track Options - Clear All
47302
47860
 
47303
- let buttonContainer = document.createElement('div');
47861
+ const buttonContainer = document.createElement('div');
47304
47862
  buttonContainer.className = 'igv-circview-toolbar-button-container';
47305
- this.toolbar.appendChild(buttonContainer); // Track Options
47863
+ this.toolbar.appendChild(buttonContainer); // Show Controls
47306
47864
 
47307
- this.trackPanelPresentationButton = document.createElement('div');
47308
- this.trackPanelPresentationButton.className = 'igv-circview-button';
47309
- buttonContainer.appendChild(this.trackPanelPresentationButton);
47310
- this.trackPanelPresentationButton.innerText = 'none' === this.trackPanel.style.display ? 'Show Track Options' : 'Hide Track Options';
47311
- this.trackPanelPresentationButton.addEventListener('click', event => {
47312
- const trackPanelRows = this.trackPanel.querySelectorAll('div');
47865
+ this.showControlsButton = document.createElement('div');
47866
+ this.showControlsButton.className = 'igv-circview-button';
47867
+ buttonContainer.appendChild(this.showControlsButton);
47868
+ this.showControlsButton.innerText = 'none' === this.controlPanel.style.display ? 'Show Controls' : 'Hide Controls';
47869
+ this.showControlsButton.addEventListener('click', event => {
47870
+ const trackPanelRows = this.controlPanel.querySelectorAll('div');
47313
47871
 
47314
47872
  if (trackPanelRows.length > 0) {
47315
- if ('none' === this.trackPanel.style.display) {
47316
- this.trackPanel.style.display = 'flex';
47317
- event.target.innerText = 'Hide Track Options';
47873
+ if ('none' === this.controlPanel.style.display) {
47874
+ this.controlPanel.style.display = 'flex';
47875
+ event.target.innerText = 'Hide Controls';
47318
47876
  } else {
47319
- this.trackPanel.style.display = 'none';
47320
- event.target.innerText = 'Show Track Options';
47877
+ this.controlPanel.style.display = 'none';
47878
+ event.target.innerText = 'Show Controls';
47321
47879
  }
47322
47880
  }
47323
- }); // Clear All Chords
47881
+ }); // Clear All
47324
47882
 
47325
47883
  let button = document.createElement('div');
47326
47884
  button.className = 'igv-circview-button';
@@ -47328,11 +47886,7 @@
47328
47886
  button.innerText = 'Clear All';
47329
47887
  button.addEventListener('click', () => {
47330
47888
  this.clearChords();
47331
- }); // toolbar button container - Close Window
47332
-
47333
- buttonContainer = document.createElement('div');
47334
- buttonContainer.className = 'igv-circview-toolbar-button-container';
47335
- this.toolbar.appendChild(buttonContainer); // Close Window
47889
+ }); // Close
47336
47890
 
47337
47891
  if (false !== this.config.showCloseButton) {
47338
47892
  button = document.createElement('div');
@@ -47345,51 +47899,114 @@
47345
47899
  }
47346
47900
  }
47347
47901
 
47348
- addToTrackPanel(track) {
47349
- // single track row - container for hide-button | color-picker-swatch | track-name
47902
+ resetControlPanel() {
47903
+ this.controlPanel.innerHTML = '';
47904
+ this.controlPanel.appendChild(this.createGroupByCB());
47905
+ const chordSets = this.groupByTrack ? this.chordManager.tracks : this.chordManager.chordSets;
47906
+
47907
+ for (let cs of chordSets) {
47908
+ this.addToControlPanel(cs);
47909
+ }
47910
+ }
47911
+
47912
+ createGroupByCB() {
47913
+ const groupByCB = document.createElement('input');
47914
+ groupByCB.type = 'checkbox';
47915
+ groupByCB.id = 'groupByCB';
47916
+ groupByCB.style.width = '1.4em';
47917
+ groupByCB.style.height = '1.4em';
47918
+ groupByCB.checked = this.groupByTrack;
47919
+
47920
+ groupByCB.onclick = evt => {
47921
+ this.groupByTrack = evt.target.checked;
47922
+ this.resetControlPanel();
47923
+ this.render();
47924
+ };
47925
+
47926
+ const groupByLabel = document.createElement('label');
47927
+ groupByLabel.for = 'groupByCB';
47928
+ groupByLabel.innerText = 'Group by track';
47929
+ groupByLabel.style.color = 'black';
47930
+ groupByLabel.style.paddingLeft = '10px';
47350
47931
  const trackPanelRow = document.createElement('div');
47351
- this.trackPanel.appendChild(trackPanelRow);
47352
- let element; // track hide|show
47353
-
47354
- element = document.createElement('div');
47355
- element.className = 'igv-circview-button';
47356
- trackPanelRow.appendChild(element);
47357
- element.innerText = true === track.visible ? 'Hide' : 'Show';
47358
- element.addEventListener('click', event => {
47359
- if (true === track.visible) {
47360
- this.hideTrack(track.id);
47932
+ trackPanelRow.style.width = '100%';
47933
+ trackPanelRow.style.paddingTop = '5px';
47934
+ trackPanelRow.style.paddingBottom = '5px';
47935
+ trackPanelRow.style.background = 'rgb(216, 230, 234)';
47936
+ trackPanelRow.appendChild(groupByCB);
47937
+ trackPanelRow.appendChild(groupByLabel);
47938
+ return trackPanelRow;
47939
+ }
47940
+
47941
+ addToControlPanel(chordSet) {
47942
+ // single track row - container for hide-button | color-picker-swatch | track-name
47943
+ const row = document.createElement('div');
47944
+ this.controlPanel.appendChild(row); // track hide|show
47945
+
47946
+ const hideShowButton = document.createElement('div');
47947
+ hideShowButton.className = 'igv-circview-button';
47948
+ row.appendChild(hideShowButton);
47949
+ hideShowButton.innerText = true === chordSet.visible ? 'Hide' : 'Show';
47950
+ hideShowButton.addEventListener('click', event => {
47951
+ if (true === chordSet.visible) {
47952
+ this.hideTrack(chordSet.name);
47361
47953
  event.target.innerText = "Show";
47362
47954
  } else {
47363
- this.showTrack(track.id);
47955
+ this.showTrack(chordSet.name);
47364
47956
  event.target.innerText = "Hide";
47365
47957
  }
47366
- }); // track color
47958
+ }); // The alpha range slider. Create this here so we can reference it from the color picker
47959
+
47960
+ const alphaSlider = document.createElement('input');
47367
47961
 
47368
- element.clientHeight;
47369
- const pickerButton = document.createElement('div');
47370
- pickerButton.className = 'igv-circview-button';
47371
- pickerButton.innerHTML = '&nbsp;&nbsp;&nbsp;&nbsp;'; // <- important for button to size properly
47962
+ const valueToAlpha = value => Math.exp(value / 200) / EXP5;
47372
47963
 
47373
- trackPanelRow.appendChild(pickerButton);
47374
- pickerButton.style.backgroundColor = setAlpha(track.color, 1);
47964
+ const alphaToValue = alpha => 200 * Math.log(alpha * EXP5); // color
47965
+
47966
+
47967
+ const colorPickerButton = document.createElement('div');
47968
+ colorPickerButton.className = 'igv-circview-button';
47969
+ colorPickerButton.innerHTML = '&nbsp;&nbsp;&nbsp;&nbsp;'; // <- important for button to size properly
47970
+
47971
+ row.appendChild(colorPickerButton);
47972
+ colorPickerButton.style.backgroundColor = setAlpha(chordSet.color, 1);
47375
47973
  const pickerConfig = {
47376
- parent: pickerButton,
47974
+ parent: colorPickerButton,
47377
47975
  popup: 'right',
47378
47976
  editorFormat: 'rgb',
47379
- color: track.color,
47977
+ color: chordSet.color,
47380
47978
  onChange: ({
47381
47979
  rgbaString
47382
47980
  }) => {
47383
- pickerButton.style.backgroundColor = setAlpha(rgbaString, 1);
47384
- this.setTrackColor(track.id, rgbaString);
47981
+ colorPickerButton.style.backgroundColor = setAlpha(rgbaString, 1);
47982
+ this.setTrackColor(chordSet.name, rgbaString);
47983
+ alphaSlider.value = alphaToValue(getAlpha(chordSet.color));
47385
47984
  }
47386
47985
  };
47387
- new Picker(pickerConfig); // track name
47986
+ const picker = new Picker(pickerConfig); // alpha transparency
47987
+
47988
+ alphaSlider.setAttribute('title', 'Adjust transparency of arcs');
47989
+ alphaSlider.type = 'range'; //alphaSlider.className = 'igv-circview-alpha-slider'
47990
+
47991
+ alphaSlider.style.width = '100px';
47992
+ alphaSlider.style.marginRight = '10px';
47993
+ alphaSlider.setAttribute('class', 'range');
47994
+ alphaSlider.setAttribute('min', '0');
47995
+ alphaSlider.setAttribute('max', '1000');
47996
+ alphaSlider.value = alphaToValue(getAlpha(chordSet.color));
47997
+
47998
+ alphaSlider.oninput = () => {
47999
+ const v = valueToAlpha(alphaSlider.value);
48000
+ this.setTrackColor(chordSet.name, setAlpha(chordSet.color, v));
48001
+ picker.setColor(chordSet.color);
48002
+ };
47388
48003
 
47389
- element = document.createElement('div');
47390
- element.style.color = 'black';
47391
- trackPanelRow.appendChild(element);
47392
- element.innerText = element.title = track.name;
48004
+ row.appendChild(alphaSlider); // track name
48005
+
48006
+ const trackNameDive = document.createElement('div');
48007
+ trackNameDive.style.color = 'black';
48008
+ row.appendChild(trackNameDive);
48009
+ trackNameDive.innerText = trackNameDive.title = chordSet.name;
47393
48010
  }
47394
48011
  /**
47395
48012
  * Reset view with a new set of chromosomes.
@@ -47403,7 +48020,7 @@
47403
48020
  return;
47404
48021
  }
47405
48022
 
47406
- this.tracks = [];
48023
+ this.chordManager.clearChords();
47407
48024
  this.genomeId = igvGenome.id;
47408
48025
  this.chrNames = new Set(igvGenome.chromosomes.map(chr => shortChrName$1(chr.name)));
47409
48026
  const regions = [];
@@ -47461,35 +48078,20 @@
47461
48078
 
47462
48079
 
47463
48080
  addChords(newChords, options = {}) {
47464
- const name = options.track || options.name || "*";
47465
- let track = this.tracks.find(t => name === t.name); // Override track options or create new track
47466
-
47467
- if (track) {
47468
- if (options.color) {
47469
- track.color = options.color;
47470
- }
47471
- } else {
47472
- track = {
47473
- name,
47474
- chords: [],
47475
- color: options.color || "black",
47476
- visible: true,
47477
- id: options.id || guid()
47478
- };
47479
- this.tracks.push(track);
47480
- this.addToTrackPanel(track);
47481
- } // Append chords to track
47482
-
47483
-
47484
- const currentIDs = new Set(track.chords.map(c => c.uniqueId));
47485
-
47486
- for (let c of newChords) {
47487
- if (!currentIDs.has(c.uniqueId) && this.chrNames.has(shortChrName$1(c.refName)) && this.chrNames.has(shortChrName$1(c.mate.refName))) {
47488
- track.chords.push(c);
47489
- currentIDs.add(c.uniqueId);
47490
- }
47491
- }
47492
-
48081
+ const tmp = options.track || options.name || "*";
48082
+ const trackName = tmp.split(' ')[0].replaceAll("%20", " ");
48083
+ const chordSetName = tmp.replaceAll("%20", " ");
48084
+ const chordSet = {
48085
+ name: chordSetName,
48086
+ trackName: trackName,
48087
+ chords: newChords,
48088
+ color: options.color || "black",
48089
+ trackColor: options.trackColor || options.color || "black",
48090
+ visible: true,
48091
+ id: options.id || guid()
48092
+ };
48093
+ this.chordManager.addChordSet(chordSet);
48094
+ this.resetControlPanel();
47493
48095
  this.render();
47494
48096
  }
47495
48097
  /**
@@ -47517,8 +48119,9 @@
47517
48119
  }
47518
48120
 
47519
48121
  clearChords() {
47520
- this.tracks = [];
47521
- this.trackPanel.innerHTML = '';
48122
+ //this.tracks = []
48123
+ this.chordManager.clearChords();
48124
+ this.resetControlPanel();
47522
48125
  this.render();
47523
48126
  }
47524
48127
 
@@ -47564,8 +48167,8 @@
47564
48167
  this.parent.style.display = isVisible ? 'block' : 'none';
47565
48168
  }
47566
48169
 
47567
- hideTrack(trackID) {
47568
- let track = this.tracks.find(t => trackID === t.id);
48170
+ hideTrack(trackName) {
48171
+ let track = this.getTrack(trackName);
47569
48172
 
47570
48173
  if (track) {
47571
48174
  track.visible = false;
@@ -47575,24 +48178,32 @@
47575
48178
  }
47576
48179
  }
47577
48180
 
47578
- showTrack(trackID) {
47579
- let idx = this.tracks.findIndex(t => trackID === t.id);
48181
+ showTrack(trackName) {
48182
+ let track = this.getTrack(trackName);
47580
48183
 
47581
- if (idx >= 0) {
47582
- const track = this.tracks[idx];
48184
+ if (track) {
47583
48185
  track.visible = true;
47584
- this.tracks.splice(idx, 1); // Change z-order
47585
-
47586
- this.tracks.push(track);
47587
48186
  this.render();
47588
48187
  } else {
47589
- console.warn(`No track with name: ${name}`);
47590
- }
47591
- } // TODO -- remove corresponding row from track panel
48188
+ console.warn(`No track with name: ${trackName}`);
48189
+ }
48190
+ } // showTrack(trackID) {
48191
+ // let idx = this.tracks.findIndex(t => trackID === t.id)
48192
+ // if (idx >= 0) {
48193
+ // const track = this.tracks[idx]
48194
+ // track.visible = true
48195
+ // this.tracks.splice(idx, 1) // Change z-order
48196
+ // this.tracks.push(track)
48197
+ // this.render()
48198
+ // } else {
48199
+ // console.warn(`No track with name: ${name}`)
48200
+ // }
48201
+ // }
48202
+ // TODO -- remove corresponding row from track panel
47592
48203
 
47593
48204
 
47594
48205
  deleteTrack(trackID) {
47595
- let idx = this.tracks.findIndex(t => trackID === t.id);
48206
+ let idx = this.tracks.findIndex(t => trackID === t.name);
47596
48207
 
47597
48208
  if (idx >= 0) {
47598
48209
  this.tracks.splice(idx, 1);
@@ -47601,12 +48212,12 @@
47601
48212
  this.render();
47602
48213
  }
47603
48214
 
47604
- getTrack(trackID) {
47605
- return this.tracks.find(t => trackID === t.id);
48215
+ getTrack(name) {
48216
+ return this.groupByTrack ? this.chordManager.getTrack(name) : this.chordManager.getChordset(name);
47606
48217
  }
47607
48218
 
47608
- setTrackColor(trackID, color) {
47609
- const t = this.getTrack(trackID);
48219
+ setTrackColor(name, color) {
48220
+ const t = this.getTrack(name);
47610
48221
 
47611
48222
  if (t) {
47612
48223
  t.color = color;
@@ -47633,22 +48244,22 @@
47633
48244
  } = JBrowseReactCircularGenomeView; // Remove all children from possible previous renders. React might do this for us when we render, but just in case.
47634
48245
 
47635
48246
  ReactDOM.unmountComponentAtNode(this.container);
47636
- const visibleTracks = this.tracks.filter(t => false !== t.visible);
48247
+ const visibleChordSets = (this.groupByTrack ? this.chordManager.tracks : this.chordManager.chordSets).filter(t => t.visible);
47637
48248
  const jbrowseTracks = [];
47638
48249
  const colors = [];
47639
48250
 
47640
- for (let trackConfig of visibleTracks) {
48251
+ for (let chordSet of visibleChordSets) {
47641
48252
  jbrowseTracks.push({
47642
- trackId: trackConfig.id,
47643
- name: trackConfig.name,
48253
+ trackId: chordSet.id,
48254
+ name: chordSet.name,
47644
48255
  assemblyNames: ['forIGV'],
47645
48256
  type: 'VariantTrack',
47646
48257
  adapter: {
47647
48258
  type: 'FromConfigAdapter',
47648
- features: trackConfig.chords
48259
+ features: chordSet.chords
47649
48260
  }
47650
48261
  });
47651
- colors.push(trackConfig.color);
48262
+ colors.push(chordSet.color);
47652
48263
  }
47653
48264
 
47654
48265
  this.viewState = createViewState({
@@ -47656,7 +48267,7 @@
47656
48267
  tracks: jbrowseTracks
47657
48268
  }); // Set view colors
47658
48269
 
47659
- for (let i = 0; i < visibleTracks.length; i++) {
48270
+ for (let i = 0; i < visibleChordSets.length; i++) {
47660
48271
  this.viewState.config.tracks[i].displays[0].renderer.strokeColor.set(colors[i]); //this.viewState.config.tracks[i].displays[0].renderer.strokeColor.set("jexl:get(feature, 'color') || 'black'");
47661
48272
  //this.viewState.config.tracks[i].displays[0].renderer.strokeColorSelected.set("jexl:get(feature, 'highlightColor') || 'red'");
47662
48273
  }
@@ -47666,12 +48277,13 @@
47666
48277
  });
47667
48278
  this.setSize(this.width, this.height);
47668
48279
  ReactDOM.render(this.element, this.container);
48280
+ const onChordClick = this.config.onChordClick || defaultOnChordClick;
47669
48281
 
47670
- for (let i = 0; i < visibleTracks.length; i++) {
48282
+ for (let i = 0; i < visibleChordSets.length; i++) {
47671
48283
  this.viewState.session.view.showTrack(this.viewState.config.tracks[i].trackId);
47672
48284
 
47673
- if (this.config.onChordClick) {
47674
- this.viewState.pluginManager.jexl.addFunction('onChordClick', this.config.onChordClick);
48285
+ if (onChordClick) {
48286
+ this.viewState.pluginManager.jexl.addFunction('onChordClick', onChordClick);
47675
48287
  this.viewState.config.tracks[i].displays[0].onChordClick.set('jexl:onChordClick(feature, track, pluginManager)');
47676
48288
  }
47677
48289
  }
@@ -47685,16 +48297,28 @@
47685
48297
  return `${a},${b},${c},${alpha})`;
47686
48298
  }
47687
48299
 
48300
+ function getAlpha(rgba) {
48301
+ if (rgba.startsWith("rgba(")) {
48302
+ return Number(rgba.split(',')[3].replace(')', ''));
48303
+ } else {
48304
+ return 1;
48305
+ }
48306
+ }
48307
+
47688
48308
  function shortChrName$1(chrName) {
47689
48309
  return chrName.startsWith("chr") ? chrName.substring(3) : chrName;
47690
48310
  }
47691
48311
 
48312
+ function defaultOnChordClick(feature, chordTrack, pluginManager) {
48313
+ console.log(feature);
48314
+ }
48315
+
47692
48316
  function guid() {
47693
48317
  return ("0000" + (Math.random() * Math.pow(36, 4) << 0).toString(36)).slice(-4);
47694
48318
  }
47695
48319
 
47696
48320
  function embedCSS$1() {
47697
- const css = '.igv-circview-container {\n z-index: 2048;\n position: absolute;\n width: fit-content;\n height: fit-content;\n box-sizing: content-box;\n color: dimgray;\n font-family: \"Open Sans\", sans-serif;\n font-size: 12px;\n background-color: white;\n border-color: dimgray;\n border-style: solid;\n border-width: thin;\n display: flex;\n flex-direction: column;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: flex-start; }\n\n.igv-circview-toolbar {\n position: relative;\n width: 100%;\n height: 32px;\n background-color: lightgrey;\n border-bottom-style: solid;\n border-bottom-color: dimgray;\n border-bottom-width: thin;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: space-between;\n align-items: center; }\n\n.igv-circview-toolbar-button-container {\n height: 100%;\n width: fit-content;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: center; }\n .igv-circview-toolbar-button-container > div {\n margin: 4px; }\n\n.igv-circview-track-panel {\n z-index: 1024;\n position: absolute;\n top: 33px;\n left: 0;\n width: 100%;\n height: fit-content;\n border-bottom-style: solid;\n border-bottom-color: dimgray;\n border-bottom-width: thin;\n background-color: white;\n display: flex;\n flex-flow: column;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: flex-start; }\n .igv-circview-track-panel > div {\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: center; }\n .igv-circview-track-panel > div > div {\n margin: 4px; }\n\n.igv-circview-swatch-button {\n cursor: pointer;\n padding: 5px;\n width: 8px;\n height: 8px;\n border: 1px solid #8d8b8b;\n border-radius: 16px; }\n\n.igv-circview-button {\n cursor: pointer;\n padding: 5px;\n color: #444;\n vertical-align: middle;\n text-align: center;\n font-family: \"Open Sans\", sans-serif;\n font-size: 12px;\n border: 1px solid #8d8b8b;\n border-radius: 4px;\n background: #efefef;\n box-shadow: 0 0 5px -1px rgba(0, 0, 0, 0.2); }\n\n.igv-circview-button:hover {\n background: #efefef;\n box-shadow: 0 0 5px -1px rgba(0, 0, 0, 0.6); }\n\n.igv-circview-button:active {\n color: #007bff;\n box-shadow: 0 0 5px -1px rgba(0, 0, 0, 0.6); }\n\n/*# sourceMappingURL=circular-view.css.map */\n';
48321
+ const css = '.igv-circview-container {\n z-index: 2048;\n position: absolute;\n width: fit-content;\n height: fit-content;\n box-sizing: content-box;\n color: dimgray;\n font-family: \"Open Sans\", sans-serif;\n font-size: 12px;\n background-color: white;\n border-color: dimgray;\n border-style: solid;\n border-width: thin;\n display: flex;\n flex-direction: column;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: flex-start;\n}\n\n.igv-circview-toolbar {\n position: relative;\n width: 100%;\n height: 32px;\n background-color: lightgrey;\n border-bottom-style: solid;\n border-bottom-color: dimgray;\n border-bottom-width: thin;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: space-between;\n align-items: center;\n}\n\n.igv-circview-toolbar-button-container {\n height: 100%;\n width: fit-content;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: center;\n}\n.igv-circview-toolbar-button-container > div {\n margin: 4px;\n}\n\n.igv-circview-track-panel {\n z-index: 1024;\n position: absolute;\n top: 33px;\n left: 0;\n width: 100%;\n height: fit-content;\n border-bottom-style: solid;\n border-bottom-color: dimgray;\n border-bottom-width: thin;\n background-color: white;\n display: flex;\n flex-flow: column;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: flex-start;\n}\n.igv-circview-track-panel > div {\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: center;\n}\n.igv-circview-track-panel > div > div {\n margin: 4px;\n}\n\n.igv-circview-swatch-button {\n cursor: pointer;\n padding: 5px;\n width: 8px;\n height: 8px;\n border: 1px solid #8d8b8b;\n border-radius: 16px;\n}\n\n.igv-circview-button {\n cursor: pointer;\n padding: 5px;\n color: #444;\n vertical-align: middle;\n text-align: center;\n font-family: \"Open Sans\", sans-serif;\n font-size: 12px;\n border: 1px solid #8d8b8b;\n border-radius: 4px;\n background: #efefef;\n box-shadow: 0 0 5px -1px rgba(0, 0, 0, 0.2);\n}\n\n.igv-circview-button:hover {\n background: #efefef;\n box-shadow: 0 0 5px -1px rgba(0, 0, 0, 0.6);\n}\n\n.igv-circview-button:active {\n color: #007bff;\n box-shadow: 0 0 5px -1px rgba(0, 0, 0, 0.6);\n}\n\n/*# sourceMappingURL=circular-view.css.map */\n';
47698
48322
  const style = document.createElement('style');
47699
48323
  style.setAttribute('type', 'text/css');
47700
48324
  style.innerHTML = css;
@@ -49069,54 +49693,56 @@
49069
49693
  const showSoftClips = this.parent.showSoftClips;
49070
49694
  const clickedAlignment = typeof clickedObject.alignmentContaining === 'function' ? clickedObject.alignmentContaining(clickState.genomicLocation, showSoftClips) : clickedObject;
49071
49695
 
49072
- if (clickedAlignment.isPaired() && clickedAlignment.isMateMapped()) {
49073
- list.push({
49074
- label: 'View mate in split screen',
49075
- click: () => {
49076
- if (clickedAlignment.mate) {
49077
- const referenceFrame = clickState.viewport.referenceFrame;
49078
-
49079
- if (this.browser.genome.getChromosome(clickedAlignment.mate.chr)) {
49080
- this.highlightedAlignmentReadNamed = clickedAlignment.readName;
49081
- this.browser.presentMultiLocusPanel(clickedAlignment, referenceFrame);
49082
- } else {
49083
- Alert.presentAlert(`Reference does not contain chromosome: ${clickedAlignment.mate.chr}`);
49696
+ if (clickedAlignment) {
49697
+ if (clickedAlignment.isPaired() && clickedAlignment.isMateMapped()) {
49698
+ list.push({
49699
+ label: 'View mate in split screen',
49700
+ click: () => {
49701
+ if (clickedAlignment.mate) {
49702
+ const referenceFrame = clickState.viewport.referenceFrame;
49703
+
49704
+ if (this.browser.genome.getChromosome(clickedAlignment.mate.chr)) {
49705
+ this.highlightedAlignmentReadNamed = clickedAlignment.readName;
49706
+ this.browser.presentMultiLocusPanel(clickedAlignment, referenceFrame);
49707
+ } else {
49708
+ Alert.presentAlert(`Reference does not contain chromosome: ${clickedAlignment.mate.chr}`);
49709
+ }
49084
49710
  }
49085
- }
49086
- },
49087
- init: undefined
49088
- });
49089
- }
49090
-
49091
- list.push({
49092
- label: 'View read sequence',
49093
- click: () => {
49094
- const alignment = clickedAlignment;
49095
- if (!alignment) return;
49096
- const seqstring = alignment.seq; //.map(b => String.fromCharCode(b)).join("");
49097
-
49098
- if (!seqstring || "*" === seqstring) {
49099
- Alert.presentAlert("Read sequence: *");
49100
- } else {
49101
- Alert.presentAlert(seqstring);
49102
- }
49711
+ },
49712
+ init: undefined
49713
+ });
49103
49714
  }
49104
- });
49105
49715
 
49106
- if (isSecureContext()) {
49107
49716
  list.push({
49108
- label: 'Copy read sequence',
49717
+ label: 'View read sequence',
49109
49718
  click: () => {
49110
49719
  const alignment = clickedAlignment;
49111
49720
  if (!alignment) return;
49112
49721
  const seqstring = alignment.seq; //.map(b => String.fromCharCode(b)).join("");
49113
49722
 
49114
- navigator.clipboard.writeText(seqstring);
49723
+ if (!seqstring || "*" === seqstring) {
49724
+ Alert.presentAlert("Read sequence: *");
49725
+ } else {
49726
+ Alert.presentAlert(seqstring);
49727
+ }
49115
49728
  }
49116
49729
  });
49117
- }
49118
49730
 
49119
- list.push('<hr/>');
49731
+ if (isSecureContext()) {
49732
+ list.push({
49733
+ label: 'Copy read sequence',
49734
+ click: () => {
49735
+ const alignment = clickedAlignment;
49736
+ if (!alignment) return;
49737
+ const seqstring = alignment.seq; //.map(b => String.fromCharCode(b)).join("");
49738
+
49739
+ navigator.clipboard.writeText(seqstring);
49740
+ }
49741
+ });
49742
+ }
49743
+
49744
+ list.push('<hr/>');
49745
+ }
49120
49746
  } // Experimental JBrowse feature
49121
49747
 
49122
49748
 
@@ -49382,14 +50008,14 @@
49382
50008
  chrColorMap[chr] = color;
49383
50009
  return color;
49384
50010
  } else {
49385
- const color = IGVColor.randomRGB();
50011
+ const color = IGVColor.randomRGB(0, 255);
49386
50012
  chrColorMap[chr] = color;
49387
50013
  return color;
49388
50014
  }
49389
50015
  }
49390
50016
  const chrColorMap = {
49391
50017
  "chrX": "rgb(204, 153, 0)",
49392
- "chrY": "rgb(153, 204, 0",
50018
+ "chrY": "rgb(153, 204, 0)",
49393
50019
  "chrUn": "rgb(50, 50, 50)",
49394
50020
  "chr1": "rgb(80, 80, 255)",
49395
50021
  "chrI": "rgb(139, 155, 187)",
@@ -49626,6 +50252,65 @@
49626
50252
 
49627
50253
  }
49628
50254
 
50255
+ const viewportColumnManager = {
50256
+ createColumns: (columnContainer, count) => {
50257
+ for (let i = 0; i < count; i++) {
50258
+ if (0 === i) {
50259
+ createColumn(columnContainer, 'igv-column');
50260
+ } else {
50261
+ columnContainer.appendChild(div$1({
50262
+ class: 'igv-column-shim'
50263
+ }));
50264
+ createColumn(columnContainer, 'igv-column');
50265
+ }
50266
+ }
50267
+ },
50268
+ removeColumnAtIndex: (i, column) => {
50269
+ const shim = 0 === i ? column.nextElementSibling : column.previousElementSibling;
50270
+ column.remove();
50271
+ shim.remove();
50272
+ },
50273
+ insertAfter: referenceElement => {
50274
+ const shim = div$1({
50275
+ class: 'igv-column-shim'
50276
+ });
50277
+ insertElementAfter(shim, referenceElement);
50278
+ const column = div$1({
50279
+ class: 'igv-column'
50280
+ });
50281
+ insertElementAfter(column, shim);
50282
+ return column;
50283
+ },
50284
+ insertBefore: (referenceElement, count) => {
50285
+ for (let i = 0; i < count; i++) {
50286
+ const column = div$1({
50287
+ class: 'igv-column'
50288
+ });
50289
+ insertElementBefore(column, referenceElement);
50290
+
50291
+ if (count > 1 && i > 0) {
50292
+ const columnShim = div$1({
50293
+ class: 'igv-column-shim'
50294
+ });
50295
+ insertElementBefore(columnShim, column);
50296
+ }
50297
+ }
50298
+ },
50299
+ indexOfColumn: (columnContainer, column) => {
50300
+ const allColumns = columnContainer.querySelectorAll('.igv-column');
50301
+
50302
+ for (let i = 0; i < allColumns.length; i++) {
50303
+ const c = allColumns[i];
50304
+
50305
+ if (c === column) {
50306
+ return i;
50307
+ }
50308
+ }
50309
+
50310
+ return undefined;
50311
+ }
50312
+ };
50313
+
49629
50314
  /*
49630
50315
  * The MIT License (MIT)
49631
50316
  *
@@ -49670,26 +50355,47 @@
49670
50355
  }
49671
50356
 
49672
50357
  addMouseHandlers() {
50358
+ this.addBrowserObserver();
49673
50359
  this.addViewportClickHandler(this.$viewport.get(0));
49674
50360
  }
49675
50361
 
49676
50362
  removeMouseHandlers() {
50363
+ this.removeBrowserObserver();
49677
50364
  this.removeViewportClickHandler(this.$viewport.get(0));
49678
50365
  }
49679
50366
 
49680
- addViewportClickHandler(viewport) {
49681
- this.boundClickHandler = clickHandler.bind(this);
49682
- viewport.addEventListener('click', this.boundClickHandler);
50367
+ addBrowserObserver() {
50368
+ function observerHandler(referenceFrameList) {
50369
+ const column = this.$viewport.get(0).parentElement;
50370
+
50371
+ if (null !== column) {
50372
+ const index = viewportColumnManager.indexOfColumn(this.browser.columnContainer, column); // console.log(`ideogram-viewport - locus-change-handler index(${ index }) ${ referenceFrameList[ index ].getLocusString() } ${ Date.now() } `)
50373
+
50374
+ this.update(this.ideogram_ctx, this.$viewport.width(), this.$viewport.height(), referenceFrameList[index]);
50375
+ }
50376
+ }
50377
+
50378
+ this.boundObserverHandler = observerHandler.bind(this);
50379
+ this.browser.on('locuschange', this.boundObserverHandler);
50380
+ }
50381
+
50382
+ removeBrowserObserver() {
50383
+ this.browser.off('locuschange', this.boundObserverHandler);
50384
+ }
49683
50385
 
50386
+ addViewportClickHandler(viewport) {
49684
50387
  function clickHandler(event) {
50388
+ const column = viewport.parentElement;
50389
+ const index = viewportColumnManager.indexOfColumn(this.browser.columnContainer, column);
50390
+ const referenceFrame = this.browser.referenceFrameList[index];
49685
50391
  const {
49686
50392
  xNormalized,
49687
50393
  width
49688
50394
  } = translateMouseCoordinates$1(event, this.ideogram_ctx.canvas);
49689
50395
  const {
49690
50396
  bpLength
49691
- } = this.browser.genome.getChromosome(this.referenceFrame.chr);
49692
- const locusLength = this.referenceFrame.bpPerPixel * width;
50397
+ } = this.browser.genome.getChromosome(referenceFrame.chr);
50398
+ const locusLength = referenceFrame.bpPerPixel * width;
49693
50399
  const chrCoveragePercentage = locusLength / bpLength;
49694
50400
  let xPercentage = xNormalized;
49695
50401
 
@@ -49703,11 +50409,14 @@
49703
50409
 
49704
50410
  const ss = Math.round((xPercentage - chrCoveragePercentage / 2.0) * bpLength);
49705
50411
  const ee = Math.round((xPercentage + chrCoveragePercentage / 2.0) * bpLength);
49706
- this.referenceFrame.start = ss;
49707
- this.referenceFrame.end = ee;
49708
- this.referenceFrame.bpPerPixel = (ee - ss) / width;
49709
- this.browser.updateViews(this.referenceFrame, this.browser.trackViews, true);
50412
+ referenceFrame.start = ss;
50413
+ referenceFrame.end = ee;
50414
+ referenceFrame.bpPerPixel = (ee - ss) / width;
50415
+ this.browser.updateViews(referenceFrame, this.browser.trackViews, true);
49710
50416
  }
50417
+
50418
+ this.boundClickHandler = clickHandler.bind(this);
50419
+ viewport.addEventListener('click', this.boundClickHandler);
49711
50420
  }
49712
50421
 
49713
50422
  removeViewportClickHandler(viewport) {
@@ -49729,23 +50438,14 @@
49729
50438
  context.restore();
49730
50439
  }
49731
50440
 
49732
- async repaint() {
49733
- this.draw({
49734
- referenceFrame: this.referenceFrame
49735
- });
49736
- }
49737
-
49738
- draw(_ref) {
49739
- let {
49740
- referenceFrame
49741
- } = _ref;
50441
+ update(context, pixelWidth, pixelHeight, referenceFrame) {
49742
50442
  this.$canvas.hide();
49743
- IGVGraphics.configureHighDPICanvas(this.ideogram_ctx, this.$viewport.width(), this.$viewport.height());
50443
+ IGVGraphics.configureHighDPICanvas(context, pixelWidth, pixelHeight);
49744
50444
  this.trackView.track.draw({
49745
- context: this.ideogram_ctx,
50445
+ context,
49746
50446
  referenceFrame,
49747
- pixelWidth: this.$viewport.width(),
49748
- pixelHeight: this.$viewport.height()
50447
+ pixelWidth,
50448
+ pixelHeight
49749
50449
  });
49750
50450
  }
49751
50451
 
@@ -49779,176 +50479,6 @@
49779
50479
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
49780
50480
  * THE SOFTWARE.
49781
50481
  */
49782
- /**
49783
- * Test if the given value is a string or number. Not using typeof as it fails on boxed primitives.
49784
- *
49785
- * @param value
49786
- * @returns boolean
49787
- */
49788
-
49789
-
49790
- function isSimpleType(value) {
49791
- const simpleTypes = new Set(["boolean", "number", "string", "symbol"]);
49792
- const valueType = typeof value;
49793
- return value !== undefined && (simpleTypes.has(valueType) || value.substring || value.toFixed);
49794
- }
49795
-
49796
- function buildOptions(config, options) {
49797
- var defaultOptions = {
49798
- oauthToken: config.oauthToken,
49799
- headers: config.headers,
49800
- withCredentials: config.withCredentials,
49801
- filename: config.filename
49802
- };
49803
- return Object.assign(defaultOptions, options);
49804
- }
49805
- /**
49806
- * isMobile test from http://detectmobilebrowsers.com
49807
- * TODO -- improve UI design so this isn't neccessary
49808
- * @returns {boolean}
49809
- */
49810
- // igv.isMobile = function () {
49811
- //
49812
- // const a = (navigator.userAgent || navigator.vendor || window.opera);
49813
- // 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) ||
49814
- // /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)))
49815
- //
49816
- // }
49817
-
49818
-
49819
- const doAutoscale = function (features) {
49820
- var min, max;
49821
-
49822
- if (features.length > 0) {
49823
- min = Number.MAX_VALUE;
49824
- max = -Number.MAX_VALUE;
49825
- features.forEach(function (f) {
49826
- if (!Number.isNaN(f.value)) {
49827
- min = Math.min(min, f.value);
49828
- max = Math.max(max, f.value);
49829
- }
49830
- }); // Insure we have a zero baseline
49831
-
49832
- if (max > 0) min = Math.min(0, min);
49833
- if (max < 0) max = 0;
49834
- } else {
49835
- // No features -- default
49836
- min = 0;
49837
- max = 100;
49838
- }
49839
-
49840
- return {
49841
- min: min,
49842
- max: max
49843
- };
49844
- };
49845
-
49846
- const validateLocusExtent = function (chromosomeLengthBP, extent, minimumBP) {
49847
- let ss = extent.start;
49848
- let ee = extent.end;
49849
-
49850
- if (undefined === ee) {
49851
- ss -= minimumBP / 2;
49852
- ee = ss + minimumBP;
49853
-
49854
- if (ee > chromosomeLengthBP) {
49855
- ee = chromosomeLengthBP;
49856
- ss = ee - minimumBP;
49857
- } else if (ss < 0) {
49858
- ss = 0;
49859
- ee = minimumBP;
49860
- }
49861
- } else if (ee - ss < minimumBP) {
49862
- const center = (ee + ss) / 2;
49863
-
49864
- if (center - minimumBP / 2 < 0) {
49865
- ss = 0;
49866
- ee = ss + minimumBP;
49867
- } else if (center + minimumBP / 2 > chromosomeLengthBP) {
49868
- ee = chromosomeLengthBP;
49869
- ss = ee - minimumBP;
49870
- } else {
49871
- ss = center - minimumBP / 2;
49872
- ee = ss + minimumBP;
49873
- }
49874
- }
49875
-
49876
- extent.start = Math.ceil(ss);
49877
- extent.end = Math.floor(ee);
49878
- };
49879
- /*!
49880
- * is-number <https://github.com/jonschlinkert/is-number>
49881
- *
49882
- * Copyright (c) 2014-present, Jon Schlinkert.
49883
- * Released under the MIT License.
49884
- */
49885
-
49886
-
49887
- const isNumber = function (num) {
49888
- if (typeof num === 'number') {
49889
- return num - num === 0;
49890
- }
49891
-
49892
- if (typeof num === 'string' && num.trim() !== '') {
49893
- return Number.isFinite ? Number.isFinite(+num) : isFinite(+num);
49894
- }
49895
-
49896
- return false;
49897
- };
49898
-
49899
- async function getFilename(url) {
49900
- if (isString$3(url) && url.startsWith("https://drive.google.com")) {
49901
- // This will fail if Google API key is not defined
49902
- if (getApiKey() === undefined) {
49903
- throw Error("Google drive is referenced, but API key is not defined. An API key is required for Google Drive access");
49904
- }
49905
-
49906
- const json = await getDriveFileInfo(url);
49907
- return json.originalFileName || json.name;
49908
- } else {
49909
- return getFilename$1(url);
49910
- }
49911
- }
49912
-
49913
- function prettyBasePairNumber(raw) {
49914
- var denom, units, value, floored;
49915
-
49916
- if (raw > 1e7) {
49917
- denom = 1e6;
49918
- units = " mb";
49919
- } else if (raw > 1e4) {
49920
- denom = 1e3;
49921
- units = " kb";
49922
- value = raw / denom;
49923
- floored = Math.floor(value);
49924
- return numberFormatter$1(floored) + units;
49925
- } else {
49926
- return numberFormatter$1(raw) + " bp";
49927
- }
49928
-
49929
- value = raw / denom;
49930
- floored = Math.floor(value);
49931
- return floored.toString() + units;
49932
- }
49933
-
49934
- function isDataURL(obj) {
49935
- return isString$3(obj) && obj.startsWith("data:");
49936
- }
49937
-
49938
- function createColumn(columnContainer, className) {
49939
- const column = div$1({
49940
- class: className
49941
- });
49942
- columnContainer.appendChild(column);
49943
- }
49944
-
49945
- function insertElementBefore(element, referenceNode) {
49946
- referenceNode.parentNode.insertBefore(element, referenceNode);
49947
- }
49948
-
49949
- function insertElementAfter(element, referenceNode) {
49950
- referenceNode.parentNode.insertBefore(element, referenceNode.nextSibling);
49951
- }
49952
50482
 
49953
50483
  function createViewport(trackView, column, referenceFrame, width) {
49954
50484
  if ('ruler' === trackView.track.type) {
@@ -49959,14 +50489,6 @@
49959
50489
  return new TrackViewport(trackView, column, referenceFrame, width);
49960
50490
  }
49961
50491
  }
49962
- /**
49963
- * Test to see if page is loaded in a secure context, that is by https or is localhost.
49964
- */
49965
-
49966
-
49967
- function isSecureContext() {
49968
- return window.location.protocol === "https:" || window.location.hostname === "localhost";
49969
- }
49970
50492
 
49971
50493
  const maxFontSize = 10;
49972
50494
  const fontConfigureTemplate = {
@@ -49979,7 +50501,7 @@
49979
50501
 
49980
50502
  class SampleNameViewport {
49981
50503
  constructor(trackView, column, unused, width) {
49982
- this.guid = guid$1();
50504
+ this.guid = guid$2();
49983
50505
  this.trackView = trackView;
49984
50506
  this.browser = trackView.browser;
49985
50507
  this.viewport = div$1({
@@ -50099,7 +50621,7 @@
50099
50621
  height
50100
50622
  } = this.viewport.getBoundingClientRect();
50101
50623
  const str = (this.trackView.track.name || this.trackView.track.id).replace(/\W/g, '');
50102
- const id = `${str}_sample_names_guid_${guid$1()}`;
50624
+ const id = `${str}_sample_names_guid_${guid$2()}`;
50103
50625
  context.saveWithTranslationAndClipRect(id, deltaX, deltaY + yScrollDelta, width, height, -yScrollDelta);
50104
50626
  this.draw({
50105
50627
  context,
@@ -50488,7 +51010,7 @@
50488
51010
 
50489
51011
  class TrackView {
50490
51012
  constructor(browser, columnContainer, track) {
50491
- this.namespace = `trackview-${guid$1()}`;
51013
+ this.namespace = `trackview-${guid$2()}`;
50492
51014
  this.browser = browser;
50493
51015
  this.track = track;
50494
51016
  track.trackView = this;
@@ -50811,12 +51333,14 @@
50811
51333
 
50812
51334
  for (let viewport of reloadableViewports) {
50813
51335
  await viewport.loadFeatures();
50814
- } // Very special case for variant tracks in multilocus view. The # of rows to allocate to the variant (site)
51336
+ }
51337
+
51338
+ if (this.disposed) return; // Track was removed during load
51339
+ // Very special case for variant tracks in multilocus view. The # of rows to allocate to the variant (site)
50815
51340
  // section depends on data from all the views. We only need to adjust this however if any data was loaded
50816
51341
  // (i.e. reloadableViewports.length > 0)
50817
51342
 
50818
-
50819
- if (typeof this.track.variantRowCount === 'function' && reloadableViewports.length > 0) {
51343
+ if (this.track && typeof this.track.variantRowCount === 'function' && reloadableViewports.length > 0) {
50820
51344
  let maxRow = 0;
50821
51345
 
50822
51346
  for (let viewport of this.viewports) {
@@ -50836,8 +51360,6 @@
50836
51360
  }
50837
51361
  }
50838
51362
 
50839
- if (this.disposed) return; // Track was removed during load
50840
-
50841
51363
  if (this.track.autoscale) {
50842
51364
  let allFeatures = [];
50843
51365
 
@@ -51246,7 +51768,7 @@
51246
51768
  height
51247
51769
  } = axisCanvas.getBoundingClientRect();
51248
51770
  const str = (track.name || track.id).replace(/\W/g, '');
51249
- const id = `${str}_axis_guid_${guid$1()}`;
51771
+ const id = `${str}_axis_guid_${guid$2()}`;
51250
51772
  context.saveWithTranslationAndClipRect(id, deltaX, y + deltaY, width, height, 0);
51251
51773
  track.paintAxis(context, width, height);
51252
51774
  context.restore();
@@ -51521,6 +52043,13 @@
51521
52043
  value: this.source
51522
52044
  });
51523
52045
 
52046
+ if (this.score !== undefined) {
52047
+ pd.push({
52048
+ name: 'Score',
52049
+ value: this.score
52050
+ });
52051
+ }
52052
+
51524
52053
  if (this.attributeString) {
51525
52054
  const atts = parseAttributeString(this.attributeString, this.delim);
51526
52055
 
@@ -51790,7 +52319,7 @@
51790
52319
  chr: tokens[0],
51791
52320
  start: parseInt(tokens[3]) - 1,
51792
52321
  end: parseInt(tokens[4]),
51793
- score: "." === tokens[5] ? 0 : Number(tokens[5]),
52322
+ score: "." === tokens[5] ? undefined : Number(tokens[5]),
51794
52323
  strand: tokens[6],
51795
52324
  phase: "." === tokens[7] ? 0 : parseInt(tokens[7]),
51796
52325
  attributeString: tokens[8],
@@ -53209,268 +53738,34 @@
53209
53738
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
53210
53739
  * THE SOFTWARE.
53211
53740
  */
53212
- const knownAltBases = new Set(["A", "C", "T", "G"].map(c => c.charCodeAt(0)));
53741
+ /**
53742
+ * Create a variant from an array of tokens representing a line in a "VCF" file
53743
+ * @param tokens
53744
+ */
53213
53745
 
53214
53746
  function createVCFVariant(tokens) {
53215
- return new Variant(tokens);
53216
- }
53747
+ const variant = new Variant();
53748
+ variant.chr = tokens[0]; // TODO -- use genome aliases
53217
53749
 
53218
- class Variant {
53219
- constructor(tokens) {
53220
- this.chr = tokens[0]; // TODO -- use genome aliases
53221
-
53222
- this.pos = parseInt(tokens[1]);
53223
- this.names = tokens[2]; // id in VCF
53750
+ variant.pos = parseInt(tokens[1]);
53751
+ variant.names = tokens[2]; // id in VCF
53224
53752
 
53225
- this.referenceBases = tokens[3];
53226
- this.alternateBases = tokens[4];
53227
- this.quality = tokens[5];
53228
- this.filter = tokens[6];
53229
- this.info = getInfoObject(tokens[7]);
53230
- this.init();
53231
- }
53232
-
53233
- init() {
53234
- const ref = this.referenceBases;
53235
- const altBases = this.alternateBases;
53236
-
53237
- if (this.info) {
53238
- if (this.info["VT"]) {
53239
- this.type = this.info["VT"];
53240
- } else if (this.info["SVTYPE"]) {
53241
- this.type = "SV";
53242
- } else if (this.info["PERIOD"]) {
53243
- this.type = "STR";
53244
- }
53245
- }
53246
-
53247
- if (this.type === undefined) {
53248
- this.type = determineType(ref, altBases);
53249
- }
53250
-
53251
- if (this.type === "NONVARIANT") {
53252
- this.heterozygosity = 0;
53253
- } // Determine start/end coordinates -- these are the coordinates representing the actual variant,
53254
- // not the leading or trailing reference
53255
-
53256
-
53257
- if (this.info["END"]) {
53258
- this.start = this.pos - 1;
53259
-
53260
- if (this.info["CHR2"] && this.info["CHR2"] !== this.chr) {
53261
- this.end = this.start + 1;
53262
- } else {
53263
- this.end = Number.parseInt(this.info["END"]);
53264
- }
53265
- } else {
53266
- if (this.type === "NONVARIANT") {
53267
- this.start = this.pos - 1; // convert to 0-based coordinate convention
53268
-
53269
- this.end = this.start + ref.length;
53270
- } else {
53271
- const altTokens = altBases.split(",").filter(token => token.length > 0);
53272
- this.alleles = [];
53273
- this.start = undefined;
53274
- this.end = undefined;
53275
-
53276
- for (let alt of altTokens) {
53277
- this.alleles.push(alt); // We don't yet handle SV and other special alt representations
53278
-
53279
- if ("SV" !== this.type && isKnownAlt(alt)) {
53280
- let altLength = alt.length;
53281
- let lengthOnRef = ref.length;
53282
- const lmin = Math.min(altLength, lengthOnRef); // Trim off matching bases. Try first match, then right -> left, then any remaining left -> right
53283
-
53284
- let s = 0;
53285
-
53286
- while (s < lmin && ref.charCodeAt(s) === alt.charCodeAt(s)) {
53287
- s++;
53288
- altLength--;
53289
- lengthOnRef--;
53290
- } // right -> left from end
53291
-
53292
-
53293
- while (altLength > 0 && lengthOnRef > 0) {
53294
- const altIdx = s + altLength - 1;
53295
- const refIdx = s + lengthOnRef - 1;
53296
-
53297
- if (alt.charCodeAt(altIdx) === ref.charCodeAt(refIdx)) {
53298
- altLength--;
53299
- lengthOnRef--;
53300
- } else {
53301
- break;
53302
- }
53303
- } // if any remaining, left -> right
53304
-
53305
-
53306
- while (altLength > 0 && lengthOnRef > 0) {
53307
- const altIdx = s;
53308
- const refIdx = s;
53309
-
53310
- if (alt.charCodeAt(altIdx) === ref.charCodeAt(refIdx)) {
53311
- s++;
53312
- altLength--;
53313
- lengthOnRef--;
53314
- } else {
53315
- break;
53316
- }
53317
- }
53318
-
53319
- const alleleStart = this.pos + s - 1; // -1 for zero based coordinates
53320
-
53321
- const alleleEnd = alleleStart + lengthOnRef;
53322
- this.start = this.start === undefined ? alleleStart : Math.min(this.start, alleleStart);
53323
- this.end = this.end === undefined ? alleleEnd : Math.max(this.end, alleleEnd);
53324
- }
53325
- } // Default to single base representation @ position for variant types not otherwise handled
53326
-
53327
-
53328
- if (this.start === undefined) {
53329
- this.start = this.pos - 1;
53330
- this.end = this.pos;
53331
- }
53332
- }
53333
- }
53334
- }
53335
-
53336
- popupData(genomicLocation, genomeId) {
53337
- const posString = `${numberFormatter$1(this.pos)}`;
53338
- const locString = this.start === this.end ? `${numberFormatter$1(this.start)} | ${numberFormatter$1(this.start + 1)}` : `${numberFormatter$1(this.start + 1)}-${numberFormatter$1(this.end)}`;
53339
- const fields = [{
53340
- name: "Chr",
53341
- value: this.chr
53342
- }, {
53343
- name: "Pos",
53344
- value: posString
53345
- }, {
53346
- name: "Loc",
53347
- value: locString
53348
- }, {
53349
- name: "Names",
53350
- value: this.names ? this.names : ""
53351
- }, {
53352
- name: "Ref",
53353
- value: this.referenceBases
53354
- }, {
53355
- name: "Alt",
53356
- value: this.alternateBases.replace("<", "&lt;")
53357
- }, {
53358
- name: "Qual",
53359
- value: this.quality
53360
- }, {
53361
- name: "Filter",
53362
- value: this.filter
53363
- }];
53364
-
53365
- if ("SNP" === this.type) {
53366
- let ref = this.referenceBases;
53367
-
53368
- if (ref.length === 1) {
53369
- let altArray = this.alternateBases.split(",");
53370
-
53371
- for (let alt of altArray) {
53372
- if (alt.length === 1) {
53373
- let l = TrackBase.getCravatLink(this.chr, this.pos, ref, alt, genomeId);
53374
-
53375
- if (l) {
53376
- fields.push('<hr/>');
53377
- fields.push({
53378
- html: l
53379
- });
53380
- }
53381
- }
53382
- }
53383
- }
53384
- }
53385
-
53386
- if (this.hasOwnProperty("heterozygosity")) {
53387
- fields.push({
53388
- name: "Heterozygosity",
53389
- value: this.heterozygosity
53390
- });
53391
- }
53392
-
53393
- if (this.info) {
53394
- fields.push({
53395
- html: '<hr style="border-top: dotted 1px;border-color: #c9c3ba" />'
53396
- });
53397
-
53398
- for (let key of Object.keys(this.info)) {
53399
- fields.push({
53400
- name: key,
53401
- value: arrayToString(decodeURIComponent(this.info[key]))
53402
- });
53403
- }
53404
- }
53405
-
53406
- return fields;
53407
- }
53408
-
53409
- isRefBlock() {
53410
- return "NONVARIANT" === this.type;
53411
- }
53412
-
53413
- }
53414
-
53415
- function getInfoObject(infoStr) {
53416
- var info = {};
53753
+ variant.referenceBases = tokens[3];
53754
+ variant.alternateBases = tokens[4];
53755
+ variant.quality = tokens[5];
53756
+ variant.filter = tokens[6];
53757
+ variant.info = {};
53758
+ const infoStr = tokens[7];
53417
53759
 
53418
53760
  if (infoStr) {
53419
- infoStr.split(';').forEach(function (elem) {
53761
+ for (let elem of infoStr.split(';')) {
53420
53762
  var element = elem.split('=');
53421
- info[element[0]] = element[1];
53422
- });
53423
- }
53424
-
53425
- return info;
53426
- }
53427
-
53428
- function isKnownAlt(alt) {
53429
- for (let i = 0; i < alt.length; i++) {
53430
- if (!knownAltBases.has(alt.charCodeAt(i))) {
53431
- return false;
53432
- }
53433
- }
53434
-
53435
- return true;
53436
- }
53437
-
53438
- function determineType(ref, altAlleles) {
53439
- const refLength = ref.length;
53440
-
53441
- if (altAlleles === undefined) {
53442
- return "UNKNOWN";
53443
- } else if (altAlleles.trim().length === 0 || altAlleles === "<NON_REF>" || altAlleles === "<*>" || altAlleles === ".") {
53444
- return "NONVARIANT";
53445
- } else {
53446
- const alleles = altAlleles.split(",");
53447
- const types = alleles.map(function (a) {
53448
- if (refLength === 1 && a.length === 1) {
53449
- return "SNP";
53450
- } else {
53451
- return "<NON_REF>" === a ? "NONVARIANT" : "OTHER";
53452
- }
53453
- });
53454
- let type = types[0];
53455
-
53456
- for (let t of types) {
53457
- if (t !== type) {
53458
- return "MIXED";
53459
- }
53763
+ variant.info[element[0]] = element[1];
53460
53764
  }
53461
-
53462
- return type;
53463
53765
  }
53464
- }
53465
53766
 
53466
- function arrayToString(value, delim) {
53467
- if (delim === undefined) delim = ",";
53468
-
53469
- if (!Array.isArray(value)) {
53470
- return value;
53471
- }
53472
-
53473
- return value.join(delim);
53767
+ variant.init();
53768
+ return variant;
53474
53769
  }
53475
53770
  /**
53476
53771
  * @deprecated - the GA4GH API has been deprecated. This code no longer maintained.
@@ -53532,6 +53827,239 @@
53532
53827
  return variant;
53533
53828
  }
53534
53829
 
53830
+ class Variant {
53831
+ init() {
53832
+ const ref = this.referenceBases;
53833
+ const altBases = this.alternateBases;
53834
+
53835
+ if (this.info) {
53836
+ if (this.info["VT"]) {
53837
+ this.type = this.info["VT"];
53838
+ } else if (this.info["SVTYPE"]) {
53839
+ this.type = "SV";
53840
+ } else if (this.info["PERIOD"]) {
53841
+ this.type = "STR";
53842
+ }
53843
+ }
53844
+
53845
+ if (this.type === undefined) {
53846
+ this.type = determineType(ref, altBases);
53847
+ }
53848
+
53849
+ if (this.type === "NONVARIANT") {
53850
+ this.heterozygosity = 0;
53851
+ } // Determine start/end coordinates -- these are the coordinates representing the actual variant,
53852
+ // not the leading or trailing reference
53853
+
53854
+
53855
+ if (this.info["END"]) {
53856
+ this.start = this.pos - 1;
53857
+
53858
+ if (this.info["CHR2"] && this.info["CHR2"] !== this.chr) {
53859
+ this.end = this.start + 1;
53860
+ } else {
53861
+ this.end = Number.parseInt(this.info["END"]);
53862
+ }
53863
+ } else {
53864
+ if (this.type === "NONVARIANT") {
53865
+ this.start = this.pos - 1; // convert to 0-based coordinate convention
53866
+
53867
+ this.end = this.start + ref.length;
53868
+ } else {
53869
+ const altTokens = altBases.split(",").filter(token => token.length > 0);
53870
+ this.alleles = [];
53871
+ this.start = undefined;
53872
+ this.end = undefined;
53873
+
53874
+ for (let alt of altTokens) {
53875
+ this.alleles.push(alt); // We don't yet handle SV and other special alt representations
53876
+
53877
+ if ("SV" !== this.type && isKnownAlt(alt)) {
53878
+ let altLength = alt.length;
53879
+ let lengthOnRef = ref.length;
53880
+ const lmin = Math.min(altLength, lengthOnRef); // Trim off matching bases. Try first match, then right -> left, then any remaining left -> right
53881
+
53882
+ let s = 0;
53883
+
53884
+ while (s < lmin && ref.charCodeAt(s) === alt.charCodeAt(s)) {
53885
+ s++;
53886
+ altLength--;
53887
+ lengthOnRef--;
53888
+ } // right -> left from end
53889
+
53890
+
53891
+ while (altLength > 0 && lengthOnRef > 0) {
53892
+ const altIdx = s + altLength - 1;
53893
+ const refIdx = s + lengthOnRef - 1;
53894
+
53895
+ if (alt.charCodeAt(altIdx) === ref.charCodeAt(refIdx)) {
53896
+ altLength--;
53897
+ lengthOnRef--;
53898
+ } else {
53899
+ break;
53900
+ }
53901
+ } // if any remaining, left -> right
53902
+
53903
+
53904
+ while (altLength > 0 && lengthOnRef > 0) {
53905
+ const altIdx = s;
53906
+ const refIdx = s;
53907
+
53908
+ if (alt.charCodeAt(altIdx) === ref.charCodeAt(refIdx)) {
53909
+ s++;
53910
+ altLength--;
53911
+ lengthOnRef--;
53912
+ } else {
53913
+ break;
53914
+ }
53915
+ }
53916
+
53917
+ const alleleStart = this.pos + s - 1; // -1 for zero based coordinates
53918
+
53919
+ const alleleEnd = alleleStart + lengthOnRef;
53920
+ this.start = this.start === undefined ? alleleStart : Math.min(this.start, alleleStart);
53921
+ this.end = this.end === undefined ? alleleEnd : Math.max(this.end, alleleEnd);
53922
+ }
53923
+ } // Default to single base representation @ position for variant types not otherwise handled
53924
+
53925
+
53926
+ if (this.start === undefined) {
53927
+ this.start = this.pos - 1;
53928
+ this.end = this.pos;
53929
+ }
53930
+ }
53931
+ }
53932
+ }
53933
+
53934
+ popupData(genomicLocation, genomeId) {
53935
+ const posString = `${numberFormatter$1(this.pos)}`;
53936
+ const locString = this.start === this.end ? `${numberFormatter$1(this.start)} | ${numberFormatter$1(this.start + 1)}` : `${numberFormatter$1(this.start + 1)}-${numberFormatter$1(this.end)}`;
53937
+ const fields = [{
53938
+ name: "Chr",
53939
+ value: this.chr
53940
+ }, {
53941
+ name: "Pos",
53942
+ value: posString
53943
+ }, {
53944
+ name: "Loc",
53945
+ value: locString
53946
+ }, {
53947
+ name: "Names",
53948
+ value: this.names ? this.names : ""
53949
+ }, {
53950
+ name: "Ref",
53951
+ value: this.referenceBases
53952
+ }, {
53953
+ name: "Alt",
53954
+ value: this.alternateBases.replace("<", "&lt;")
53955
+ }, {
53956
+ name: "Qual",
53957
+ value: this.quality
53958
+ }, {
53959
+ name: "Filter",
53960
+ value: this.filter
53961
+ }];
53962
+
53963
+ if ("SNP" === this.type) {
53964
+ let ref = this.referenceBases;
53965
+
53966
+ if (ref.length === 1) {
53967
+ let altArray = this.alternateBases.split(",");
53968
+
53969
+ for (let alt of altArray) {
53970
+ if (alt.length === 1) {
53971
+ let l = TrackBase.getCravatLink(this.chr, this.pos, ref, alt, genomeId);
53972
+
53973
+ if (l) {
53974
+ fields.push('<hr/>');
53975
+ fields.push({
53976
+ html: l
53977
+ });
53978
+ }
53979
+ }
53980
+ }
53981
+ }
53982
+ }
53983
+
53984
+ if (this.hasOwnProperty("heterozygosity")) {
53985
+ fields.push({
53986
+ name: "Heterozygosity",
53987
+ value: this.heterozygosity
53988
+ });
53989
+ }
53990
+
53991
+ if (this.info) {
53992
+ fields.push({
53993
+ html: '<hr style="border-top: dotted 1px;border-color: #c9c3ba" />'
53994
+ });
53995
+
53996
+ for (let key of Object.keys(this.info)) {
53997
+ fields.push({
53998
+ name: key,
53999
+ value: arrayToString(decodeURIComponent(this.info[key]))
54000
+ });
54001
+ }
54002
+ }
54003
+
54004
+ return fields;
54005
+ }
54006
+
54007
+ isRefBlock() {
54008
+ return "NONVARIANT" === this.type;
54009
+ }
54010
+
54011
+ }
54012
+
54013
+ const knownAltBases = new Set(["A", "C", "T", "G"].map(c => c.charCodeAt(0)));
54014
+
54015
+ function isKnownAlt(alt) {
54016
+ for (let i = 0; i < alt.length; i++) {
54017
+ if (!knownAltBases.has(alt.charCodeAt(i))) {
54018
+ return false;
54019
+ }
54020
+ }
54021
+
54022
+ return true;
54023
+ }
54024
+
54025
+ function determineType(ref, altAlleles) {
54026
+ const refLength = ref.length;
54027
+
54028
+ if (altAlleles === undefined) {
54029
+ return "UNKNOWN";
54030
+ } else if (altAlleles.trim().length === 0 || altAlleles === "<NON_REF>" || altAlleles === "<*>" || altAlleles === ".") {
54031
+ return "NONVARIANT";
54032
+ } else {
54033
+ const alleles = altAlleles.split(",");
54034
+ const types = alleles.map(function (a) {
54035
+ if (refLength === 1 && a.length === 1) {
54036
+ return "SNP";
54037
+ } else {
54038
+ return "<NON_REF>" === a ? "NONVARIANT" : "OTHER";
54039
+ }
54040
+ });
54041
+ let type = types[0];
54042
+
54043
+ for (let t of types) {
54044
+ if (t !== type) {
54045
+ return "MIXED";
54046
+ }
54047
+ }
54048
+
54049
+ return type;
54050
+ }
54051
+ }
54052
+
54053
+ function arrayToString(value, delim) {
54054
+ if (delim === undefined) delim = ",";
54055
+
54056
+ if (!Array.isArray(value)) {
54057
+ return value;
54058
+ }
54059
+
54060
+ return value.join(delim);
54061
+ }
54062
+
53535
54063
  /*
53536
54064
  * The MIT License (MIT)
53537
54065
  *
@@ -53669,6 +54197,7 @@
53669
54197
  if (tokens.length === nExpectedColumns) {
53670
54198
  const variant = createVCFVariant(tokens);
53671
54199
  variant.header = this.header; // Keep a pointer to the header to interpret fields for popup text
54200
+ //variant.line = line // Uncomment for debugging
53672
54201
 
53673
54202
  allFeatures.push(variant);
53674
54203
 
@@ -55771,6 +56300,7 @@
55771
56300
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
55772
56301
  * THE SOFTWARE.
55773
56302
  */
56303
+ const DEFAULT_MAX_WG_COUNT = 10000;
55774
56304
  /**
55775
56305
  * feature source for "bed like" files (tab or whitespace delimited files with 1 feature per line: bed, gff, vcf, etc)
55776
56306
  *
@@ -55783,6 +56313,7 @@
55783
56313
  this.config = config || {};
55784
56314
  this.genome = genome;
55785
56315
  this.sourceType = config.sourceType === undefined ? "file" : config.sourceType;
56316
+ this.maxWGCount = config.maxWGCount || DEFAULT_MAX_WG_COUNT;
55786
56317
  const queryableFormats = new Set(["bigwig", "bw", "bigbed", "bb", "tdf"]);
55787
56318
 
55788
56319
  if (config.features && Array.isArray(config.features)) {
@@ -56005,9 +56536,22 @@
56005
56536
 
56006
56537
 
56007
56538
  getWGFeatures(allFeatures) {
56539
+ const makeWGFeature = f => {
56540
+ const wg = Object.assign({}, f);
56541
+ wg.chr = "all";
56542
+ wg.start = genome.getGenomeCoordinate(f.chr, f.start);
56543
+ wg.end = genome.getGenomeCoordinate(f.chr, f.end);
56544
+ wg._f = f; // Don't draw exons in whole genome view
56545
+
56546
+ if (wg["exons"]) delete wg["exons"];
56547
+ return wg;
56548
+ };
56549
+
56008
56550
  const genome = this.genome;
56009
56551
  const wgChromosomeNames = new Set(genome.wgChromosomeNames);
56010
56552
  const wgFeatures = [];
56553
+ let count = 0;
56554
+ const max = this.maxWGCount;
56011
56555
 
56012
56556
  for (let c of genome.wgChromosomeNames) {
56013
56557
  const features = allFeatures[c];
@@ -56017,15 +56561,20 @@
56017
56561
  let queryChr = genome.getChromosomeName(f.chr);
56018
56562
 
56019
56563
  if (wgChromosomeNames.has(queryChr)) {
56020
- const wg = Object.assign({}, f);
56021
- wg.chr = "all";
56022
- wg.start = genome.getGenomeCoordinate(f.chr, f.start);
56023
- wg.end = genome.getGenomeCoordinate(f.chr, f.end);
56024
- wg._f = f; // Don't draw exons in whole genome view
56025
-
56026
- if (wg["exons"]) delete wg["exons"];
56027
- wgFeatures.push(wg);
56564
+ if (wgFeatures.length < max) {
56565
+ wgFeatures.push(makeWGFeature(f));
56566
+ } else {
56567
+ //Reservoir sampling
56568
+ const samplingProb = max / (count + 1);
56569
+
56570
+ if (Math.random() < samplingProb) {
56571
+ const idx = Math.floor(Math.random() * (max - 1));
56572
+ wgFeatures[idx] = makeWGFeature(f);
56573
+ }
56574
+ }
56028
56575
  }
56576
+
56577
+ count++;
56029
56578
  }
56030
56579
  }
56031
56580
  }
@@ -58648,7 +59197,7 @@
58648
59197
  desc += "</html>";
58649
59198
  return desc;
58650
59199
  } else {
58651
- return this.name;
59200
+ return super.description();
58652
59201
  }
58653
59202
  }
58654
59203
 
@@ -58726,8 +59275,12 @@
58726
59275
  const format = config.format ? config.format.toLowerCase() : config.format;
58727
59276
 
58728
59277
  if ("bigwig" === format) {
59278
+ this.flipAxis = config.flipAxis ? config.flipAxis : false;
59279
+ this.logScale = config.logScale ? config.logScale : false;
58729
59280
  this.featureSource = new BWSource(config, this.browser.genome);
58730
59281
  } else if ("tdf" === format) {
59282
+ this.flipAxis = config.flipAxis ? config.flipAxis : false;
59283
+ this.logScale = config.logScale ? config.logScale : false;
58731
59284
  this.featureSource = new TDFSource(config, this.browser.genome);
58732
59285
  } else {
58733
59286
  this.featureSource = FeatureSource(config, this.browser.genome);
@@ -58783,7 +59336,20 @@
58783
59336
  }
58784
59337
 
58785
59338
  menuItemList() {
58786
- return MenuUtils.numericDataMenuItems(this.trackView);
59339
+ let items = [];
59340
+
59341
+ if (this.flipAxis !== undefined) {
59342
+ items.push({
59343
+ label: "Flip y-axis",
59344
+ click: () => {
59345
+ this.flipAxis = !this.flipAxis;
59346
+ this.trackView.repaintViews();
59347
+ }
59348
+ });
59349
+ }
59350
+
59351
+ items = items.concat(MenuUtils.numericDataMenuItems(this.trackView));
59352
+ return items;
58787
59353
  }
58788
59354
 
58789
59355
  async getHeader() {
@@ -58792,6 +59358,28 @@
58792
59358
  }
58793
59359
 
58794
59360
  return this.header;
59361
+ } // TODO: refactor to igvUtils.js
59362
+
59363
+
59364
+ getScaleFactor(min, max, height, logScale) {
59365
+ const scale = logScale ? height / (Math.log10(max + 1) - (min <= 0 ? 0 : Math.log10(min + 1))) : height / (max - min);
59366
+ return scale;
59367
+ }
59368
+
59369
+ computeYPixelValue(yValue, yScaleFactor) {
59370
+ return (this.flipAxis ? yValue - this.dataRange.min : this.dataRange.max - yValue) * yScaleFactor;
59371
+ }
59372
+
59373
+ computeYPixelValueInLogScale(yValue, yScaleFactor) {
59374
+ let maxValue = this.dataRange.max;
59375
+ let minValue = this.dataRange.min;
59376
+ if (maxValue <= 0) return 0; // TODO:
59377
+
59378
+ if (minValue <= -1) minValue = 0;
59379
+ minValue = minValue <= 0 ? 0 : Math.log10(minValue + 1);
59380
+ maxValue = Math.log10(maxValue + 1);
59381
+ yValue = Math.log10(yValue + 1);
59382
+ return (this.flipAxis ? yValue - minValue : maxValue - yValue) * yScaleFactor;
58795
59383
  }
58796
59384
 
58797
59385
  draw(options) {
@@ -58800,7 +59388,7 @@
58800
59388
  const bpPerPixel = options.bpPerPixel;
58801
59389
  const bpStart = options.bpStart;
58802
59390
  const pixelWidth = options.pixelWidth;
58803
- const pixelHeight = options.pixelHeight;
59391
+ options.pixelHeight;
58804
59392
  const bpEnd = bpStart + pixelWidth * bpPerPixel + 1;
58805
59393
  let lastPixelEnd = -1;
58806
59394
  let lastValue = -1;
@@ -58812,16 +59400,16 @@
58812
59400
  baselineColor = IGVColor.addAlpha(posColor, 0.1);
58813
59401
  }
58814
59402
 
58815
- const yScale = yValue => {
58816
- return (this.dataRange.max - yValue) / (this.dataRange.max - this.dataRange.min) * pixelHeight;
58817
- };
59403
+ const scaleFactor = this.getScaleFactor(this.dataRange.min, this.dataRange.max, options.pixelHeight, this.logScale);
59404
+
59405
+ const yScale = yValue => this.logScale ? this.computeYPixelValueInLogScale(yValue, scaleFactor) : this.computeYPixelValue(yValue, scaleFactor);
58818
59406
 
58819
59407
  if (features && features.length > 0) {
58820
59408
  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
58821
59409
  // nothing to paint.
58822
59410
 
58823
59411
  if (this.dataRange.max > this.dataRange.min) {
58824
- const y0 = this.dataRange.min == 0 ? pixelHeight : yScale(0);
59412
+ const y0 = yScale(0);
58825
59413
 
58826
59414
  for (let f of features) {
58827
59415
  if (f.end < bpStart) continue;
@@ -58843,11 +59431,6 @@
58843
59431
  });
58844
59432
  } else {
58845
59433
  let height = y - y0;
58846
-
58847
- if (Math.abs(height) < 1) {
58848
- height = height < 0 ? -1 : 1;
58849
- }
58850
-
58851
59434
  const pixelEnd = x + width;
58852
59435
 
58853
59436
  if (pixelEnd > lastPixelEnd || f.value >= 0 && f.value > lastValue || f.value < 0 && f.value < lastNegValue) {
@@ -58946,6 +59529,19 @@
58946
59529
  dispose() {
58947
59530
  this.trackView = undefined;
58948
59531
  }
59532
+ /**
59533
+ * Return the current state of the track. Used to create sessions and bookmarks.
59534
+ *
59535
+ * @returns {*|{}}
59536
+ */
59537
+
59538
+
59539
+ getState() {
59540
+ const config = super.getState();
59541
+ if (this.flipAxis !== undefined) config.flipAxis = this.flipAxis;
59542
+ if (this.logScale !== undefined) config.logScale = this.logScale;
59543
+ return config;
59544
+ }
58949
59545
 
58950
59546
  }
58951
59547
 
@@ -59104,9 +59700,12 @@
59104
59700
  this.explicitSamples = true;
59105
59701
  } // this.featureSource = config.sourceType === "bigquery" ?
59106
59702
  // new igv.BigQueryFeatureSource(this.config) :
59703
+ // Disable whole genome downsampling unless explicitly.
59107
59704
 
59108
59705
 
59109
- this.featureSource = FeatureSource(this.config, this.browser.genome);
59706
+ const configCopy = Object.assign({}, this.config);
59707
+ configCopy.maxWGCount = configCopy.maxWGCount || Number.MAX_SAFE_INTEGER;
59708
+ this.featureSource = FeatureSource(configCopy, this.browser.genome);
59110
59709
  this.initialSort = config.sort;
59111
59710
  }
59112
59711
 
@@ -59736,6 +60335,23 @@
59736
60335
  * THE SOFTWARE.
59737
60336
  */
59738
60337
 
60338
+ function getArcType(config) {
60339
+ if (!config.arcType) {
60340
+ return "nested";
60341
+ }
60342
+
60343
+ switch (config.arcType) {
60344
+ case "chiapet":
60345
+ return "inView";
60346
+
60347
+ case "chiapetoutbound":
60348
+ return "partialInView";
60349
+
60350
+ default:
60351
+ return config.arcType;
60352
+ }
60353
+ }
60354
+
59739
60355
  class InteractionTrack extends TrackBase {
59740
60356
  constructor(config, browser) {
59741
60357
  super(config, browser);
@@ -59747,7 +60363,7 @@
59747
60363
  this.sinTheta = Math.sin(this.theta);
59748
60364
  this.cosTheta = Math.cos(this.theta);
59749
60365
  this.height = config.height || 250;
59750
- this.arcType = config.arcType || "nested"; // nested | proportional
60366
+ this.arcType = getArcType(config); // nested | proportional | inView | partialInView
59751
60367
 
59752
60368
  this.arcOrientation = config.arcOrientation === undefined ? true : config.arcOrientation; // true for up, false for down
59753
60369
 
@@ -59755,7 +60371,13 @@
59755
60371
  this.blockHeight = config.blockHeight || 3;
59756
60372
  this.thickness = config.thickness || 1;
59757
60373
  this.color = config.color || "rgb(180,25,137)";
59758
- this.alpha = config.alpha || 0.15;
60374
+ this.alpha = config.alpha || 0.02; // was: 0.15
60375
+
60376
+ this.painter = {
60377
+ flipAxis: !this.arcOrientation,
60378
+ dataRange: this.dataRange,
60379
+ paintAxis: paintAxis
60380
+ };
59759
60381
 
59760
60382
  if (config.valueColumn) {
59761
60383
  this.valueColumn = config.valueColumn;
@@ -59823,6 +60445,8 @@
59823
60445
  draw(options) {
59824
60446
  if (this.arcType === "proportional") {
59825
60447
  this.drawProportional(options);
60448
+ } else if (this.arcType === "inView" || this.arcType === "partialInView") {
60449
+ this.drawProportional(options);
59826
60450
  } else {
59827
60451
  this.drawNested(options);
59828
60452
  }
@@ -59850,6 +60474,8 @@
59850
60474
  ctx.textAlign = "center";
59851
60475
 
59852
60476
  for (let feature of featureList) {
60477
+ // Reset transient property drawState. An undefined value => feature has not been drawn.
60478
+ feature.drawState = undefined;
59853
60479
  let color = feature.color || this.color;
59854
60480
 
59855
60481
  if (color && this.config.useScore) {
@@ -59928,8 +60554,9 @@
59928
60554
  }
59929
60555
 
59930
60556
  const otherChr = feature.chr === feature.chr1 ? feature.chr2 : feature.chr1;
59931
- ctx.strokeStyle = color;
59932
- ctx.fillStyle = color;
60557
+ ctx.strokeStyle = color; // get a sense of trans "spread"
60558
+
60559
+ ctx.fillStyle = getAlphaColor(getChrColor(otherChr), 0.5); // ctx.fillStyle = color
59933
60560
 
59934
60561
  if (direction) {
59935
60562
  // UP
@@ -59978,49 +60605,90 @@
59978
60605
  }
59979
60606
  }
59980
60607
 
60608
+ getScaleFactor(min, max, height, logScale) {
60609
+ const scale = logScale ? height / (Math.log10(max + 1) - (min <= 0 ? 0 : Math.log10(min + 1))) : height / (max - min);
60610
+ return scale;
60611
+ }
60612
+
59981
60613
  drawProportional(options) {
59982
60614
  const ctx = options.context;
59983
60615
  const pixelWidth = options.pixelWidth;
59984
60616
  const pixelHeight = options.pixelHeight;
59985
60617
  const bpPerPixel = options.bpPerPixel;
59986
60618
  const bpStart = options.bpStart;
59987
- const xScale = bpPerPixel; // SVG output for proportional arcs are currently not supported because "ellipse" is not implemented
59988
- // if(typeof ctx.ellipse !== 'function') {
59989
- // Alert.presentAlert("SVG output of proportional arcs is currently not supported.")
59990
- // return;
59991
- // }
59992
-
60619
+ const xScale = bpPerPixel;
60620
+ const refStart = options.referenceFrame.start;
60621
+ const refEnd = options.referenceFrame.end;
59993
60622
  IGVGraphics.fillRect(ctx, 0, options.pixelTop, pixelWidth, pixelHeight, {
59994
60623
  'fillStyle': "rgb(255, 255, 255)"
59995
60624
  });
59996
60625
  const featureList = options.features;
59997
60626
 
59998
60627
  if (featureList && featureList.length > 0) {
59999
- const yScale = this.logScale ? options.pixelHeight / Math.log10(this.dataRange.max + 1) : options.pixelHeight / (this.dataRange.max - this.dataRange.min);
60628
+ // we use the min as a filter but not moving the axis
60629
+
60630
+ const effectiveMin = 0;
60631
+ const yScale = this.getScaleFactor(effectiveMin, this.dataRange.max, options.pixelHeight - 1, this.logScale);
60000
60632
  const y = this.arcOrientation ? options.pixelHeight : 0;
60001
60633
 
60002
60634
  for (let feature of featureList) {
60635
+ // Reset transient property drawState. An undefined value => feature has not been drawn.
60636
+ feature.drawState = undefined;
60003
60637
  const value = this.valueColumn ? feature[this.valueColumn] : feature.score;
60004
60638
  if (value === undefined || Number.isNaN(value)) continue;
60005
- const radiusY = this.logScale ? Math.log10(value + 1) * yScale : value * yScale;
60639
+ const radiusY = Math.round((this.logScale ? Math.log10(value + 1) : value) * yScale);
60006
60640
 
60007
60641
  if (feature.chr1 === feature.chr2 || feature.chr === 'all') {
60008
60642
  const {
60009
60643
  m1,
60010
60644
  m2
60011
60645
  } = getMidpoints(feature, this.browser.genome);
60012
- let pixelStart = (m1 - bpStart) / xScale;
60013
- let pixelEnd = (m2 - bpStart) / xScale;
60646
+ let pixelStart = Math.round((m1 - bpStart) / xScale);
60647
+ let pixelEnd = Math.round((m2 - bpStart) / xScale);
60014
60648
  let w = pixelEnd - pixelStart;
60015
60649
 
60016
60650
  if (w < 3) {
60017
60651
  w = 3;
60018
60652
  pixelStart--;
60653
+ } // Various filters
60654
+
60655
+
60656
+ if (value < this.dataRange.min || value > this.dataRange.max) continue;
60657
+
60658
+ if ("proportional" !== this.arcType) {
60659
+ const showOutbound = this.arcType === "partialInView";
60660
+ const within = m1 >= refStart && m2 <= refEnd;
60661
+ let outBound = false;
60662
+ let inBound = false;
60663
+
60664
+ if (!within && showOutbound) {
60665
+ outBound = refStart <= m1 && m1 <= refEnd;
60666
+ if (!outBound) inBound = refStart <= m2 && m2 <= refEnd;
60667
+ }
60668
+
60669
+ if (!(within || outBound || inBound)) continue;
60019
60670
  }
60020
60671
 
60021
- if (pixelEnd < 0 || pixelStart > pixelWidth || value < this.dataRange.min) continue;
60022
60672
  const radiusX = w / 2;
60023
60673
  const xc = pixelStart + w / 2;
60674
+ feature.drawState = {
60675
+ xc,
60676
+ yc: y,
60677
+ radiusX,
60678
+ radiusY
60679
+ }; // const arcKey = ((pixelStart << 16) | pixelEnd)
60680
+ // let arc = arcCaches.get(arcKey)
60681
+ // if (arc !== undefined) {
60682
+ // if (arc.has(radiusY)) {
60683
+ // continue
60684
+ // }
60685
+ // arc.add(radiusY)
60686
+ // } else {
60687
+ // let arcHeights = new Set()
60688
+ // arcHeights.add(radiusY)
60689
+ // arcCaches.set(arcKey, arcHeights)
60690
+ // }
60691
+
60024
60692
  const counterClockwise = this.arcOrientation ? true : false;
60025
60693
  const color = feature.color || this.color;
60026
60694
  ctx.strokeStyle = color;
@@ -60034,17 +60702,6 @@
60034
60702
  ctx.stroke();
60035
60703
  }
60036
60704
 
60037
- if (this.showBlocks && feature.chr !== 'all') {
60038
- ctx.fillStyle = color;
60039
- const s1 = (feature.start1 - bpStart) / xScale;
60040
- const e1 = (feature.end1 - bpStart) / xScale;
60041
- const s2 = (feature.start2 - bpStart) / xScale;
60042
- const e2 = (feature.end2 - bpStart) / xScale;
60043
- const hb = this.arcOrientation ? -this.blockHeight : this.blockHeight;
60044
- ctx.fillRect(s1, y, e1 - s1, hb);
60045
- ctx.fillRect(s2, y, e2 - s2, hb);
60046
- }
60047
-
60048
60705
  if (this.alpha) {
60049
60706
  ctx.fillStyle = getAlphaColor(color, this.alpha);
60050
60707
 
@@ -60055,16 +60712,21 @@
60055
60712
  }
60056
60713
  }
60057
60714
 
60058
- feature.drawState = {
60059
- xc,
60060
- yc: y,
60061
- radiusX,
60062
- radiusY
60063
- };
60715
+ if (this.showBlocks && feature.chr !== 'all') {
60716
+ ctx.fillStyle = color;
60717
+ const s1 = (feature.start1 - bpStart) / xScale;
60718
+ const e1 = (feature.end1 - bpStart) / xScale;
60719
+ const s2 = (feature.start2 - bpStart) / xScale;
60720
+ const e2 = (feature.end2 - bpStart) / xScale;
60721
+ const hb = this.arcOrientation ? -this.blockHeight : this.blockHeight;
60722
+ ctx.fillRect(s1, y, e1 - s1, hb);
60723
+ ctx.fillRect(s2, y, e2 - s2, hb);
60724
+ }
60064
60725
  } else {
60726
+ // Inter chromosome
60065
60727
  let pixelStart = Math.round((feature.start - bpStart) / xScale);
60066
60728
  let pixelEnd = Math.round((feature.end - bpStart) / xScale);
60067
- if (pixelEnd < 0 || pixelStart > pixelWidth || value < this.dataRange.min) continue;
60729
+ if (pixelEnd < 0 || pixelStart > pixelWidth || value < this.dataRange.min || value > this.dataRange.max) continue;
60068
60730
  const h = Math.min(radiusY, this.height - 13); // Leave room for text
60069
60731
 
60070
60732
  let w = pixelEnd - pixelStart;
@@ -60076,7 +60738,9 @@
60076
60738
 
60077
60739
  const otherChr = feature.chr === feature.chr1 ? feature.chr2 : feature.chr1;
60078
60740
  ctx.font = "8px sans-serif";
60079
- ctx.textAlign = "center";
60741
+ ctx.textAlign = "center"; // get a sense of trans "spread"
60742
+
60743
+ ctx.fillStyle = getAlphaColor(getChrColor(otherChr), 0.5);
60080
60744
 
60081
60745
  if (this.arcOrientation) {
60082
60746
  // UP
@@ -60104,6 +60768,32 @@
60104
60768
  }
60105
60769
  }
60106
60770
 
60771
+ clearAxis(ctx, pixelWidth, pixelHeight) {
60772
+ IGVGraphics.fillRect(ctx, 0, 0, pixelWidth, pixelHeight, {
60773
+ 'fillStyle': "rgb(255, 255, 255)"
60774
+ });
60775
+ }
60776
+
60777
+ paintAxis(ctx, pixelWidth, pixelHeight) {
60778
+ // dataRane is interpreted differently for interactino tracks -- all arcs are drawn from "zero", irrespective of dataRange.min
60779
+ const axisRange = {
60780
+ min: 0,
60781
+ max: this.dataRange.max
60782
+ };
60783
+
60784
+ if (this.arcType === "proportional") {
60785
+ this.painter.flipAxis = !this.arcOrientation;
60786
+ this.painter.dataRange = axisRange;
60787
+ this.painter.paintAxis(ctx, pixelWidth, pixelHeight);
60788
+ } else if (this.arcType === "inView" || this.arcType === "partialInView") {
60789
+ this.painter.flipAxis = !this.arcOrientation;
60790
+ this.painter.dataRange = axisRange;
60791
+ this.painter.paintAxis(ctx, pixelWidth, pixelHeight);
60792
+ } else {
60793
+ this.clearAxis(ctx, pixelWidth, pixelHeight);
60794
+ }
60795
+ }
60796
+
60107
60797
  menuItemList() {
60108
60798
  let items = [{
60109
60799
  name: "Set track color",
@@ -60114,11 +60804,14 @@
60114
60804
 
60115
60805
  if (this.hasValue) {
60116
60806
  const lut = {
60117
- "nested": "Nested Arcs",
60118
- "proportional": "Proportional Arcs"
60807
+ "nested": "Nested",
60808
+ "proportional": "Proportional - All",
60809
+ "inView": "Proportional - Both Ends in View",
60810
+ "partialInView": "Proportional - One End in View"
60119
60811
  };
60812
+ items.push("<b>Arc Type</b>");
60120
60813
 
60121
- for (let arcType of ["nested", "proportional"]) {
60814
+ for (let arcType of ["nested", "proportional", "inView", "partialInView"]) {
60122
60815
  items.push({
60123
60816
  object: $$1(createCheckbox$1(lut[arcType], arcType === this.arcType)),
60124
60817
  click: () => {
@@ -60129,48 +60822,35 @@
60129
60822
  }
60130
60823
  }
60131
60824
 
60825
+ items.push("<hr/>");
60132
60826
  items.push({
60133
- object: $$1(createCheckbox$1("Show Blocks", this.showBlocks)),
60827
+ name: "Toggle arc direction",
60134
60828
  click: () => {
60135
- this.showBlocks = !this.showBlocks;
60829
+ this.arcOrientation = !this.arcOrientation;
60136
60830
  this.trackView.repaintViews();
60137
60831
  }
60138
60832
  });
60139
60833
  items.push({
60140
- name: "Toggle arc direction",
60834
+ name: this.showBlocks ? "Hide Blocks" : "Show Blocks",
60141
60835
  click: () => {
60142
- this.arcOrientation = !this.arcOrientation;
60836
+ this.showBlocks = !this.showBlocks;
60143
60837
  this.trackView.repaintViews();
60144
60838
  }
60145
60839
  });
60146
60840
 
60147
- if (this.arcType === "proportional") {
60148
- items.push("<HR>");
60841
+ if (this.arcType === "proportional" || this.arcType === "inView" || this.arcType === "partialInView") {
60842
+ // MenuUtils.numericDataMenuItems(this.trackView).forEach(item => items.push(item))
60149
60843
  items = items.concat(MenuUtils.numericDataMenuItems(this.trackView));
60150
60844
  }
60151
60845
 
60152
60846
  if (this.browser.circularView && true === this.browser.circularViewVisible) {
60847
+ items.push('<hr/>');
60153
60848
  items.push({
60154
60849
  label: 'Add interactions to circular view',
60155
60850
  click: () => {
60156
- const inView = [];
60157
-
60158
60851
  for (let viewport of this.trackView.viewports) {
60159
- const refFrame = viewport.referenceFrame;
60160
-
60161
- for (let f of viewport.getCachedFeatures()) {
60162
- if (f.end >= refFrame.start && f.start <= refFrame.end) {
60163
- inView.push(f);
60164
- }
60165
- }
60852
+ this.addChordsForViewport(viewport.referenceFrame);
60166
60853
  }
60167
-
60168
- const chords = makeBedPEChords(inView);
60169
- const color = IGVColor.addAlpha(this.color, 0.5);
60170
- this.browser.circularView.addChords(chords, {
60171
- track: this.name,
60172
- color: color
60173
- });
60174
60854
  }
60175
60855
  });
60176
60856
  }
@@ -60186,21 +60866,40 @@
60186
60866
  list.push({
60187
60867
  label: 'Add interactions to circular view',
60188
60868
  click: () => {
60189
- const refFrame = viewport.referenceFrame;
60190
- const inView = "all" === refFrame.chr ? this.featureSource.getAllFeatures() : this.featureSource.featureCache.queryFeatures(refFrame.chr, refFrame.start, refFrame.end);
60191
- this.browser.circularViewVisible = true;
60192
- const chords = makeBedPEChords(inView);
60193
- const color = IGVColor.addAlpha(this.color, 0.5);
60194
- this.browser.circularView.addChords(chords, {
60195
- track: this.name,
60196
- color: color
60197
- });
60869
+ const refFrame = viewport.referenceFrame; // first pass: to get all the relevant features
60870
+
60871
+ this.addChordsForViewport(refFrame);
60198
60872
  }
60199
60873
  });
60200
60874
  list.push('<hr/>');
60201
60875
  return list;
60202
60876
  }
60203
60877
  }
60878
+ /**
60879
+ * Add chords to the circular view for the given viewport, represented by its reference frame
60880
+ * @param refFrame
60881
+ */
60882
+
60883
+
60884
+ addChordsForViewport(refFrame) {
60885
+ const cachedFeatures = "all" === refFrame.chr ? this.featureSource.getAllFeatures() : this.featureSource.featureCache.queryFeatures(refFrame.chr, refFrame.start, refFrame.end); // inView features are simply features that have been drawn, i.e. have a drawState
60886
+
60887
+ const inView = cachedFeatures.filter(f => f.drawState);
60888
+ if (inView.length === 0) erturn;
60889
+ this.browser.circularViewVisible = true;
60890
+ const chords = makeBedPEChords(inView); // for filtered set, distinguishing the chromosomes is more critical than tracks
60891
+
60892
+ const chordSetColor = IGVColor.addAlpha("all" === refFrame.chr ? this.color : getChrColor(refFrame.chr), 0.5);
60893
+ const trackColor = IGVColor.addAlpha(this.color, 0.5); // name the chord set to include filtering information
60894
+
60895
+ const encodedName = this.name.replaceAll(' ', '%20');
60896
+ const chordSetName = "all" === refFrame.chr ? encodedName : `${encodedName} (${refFrame.chr}:${refFrame.start}-${refFrame.end} ; range:${this.dataRange.min}-${this.dataRange.max})`;
60897
+ this.browser.circularView.addChords(chords, {
60898
+ track: chordSetName,
60899
+ color: chordSetColor,
60900
+ trackColor: trackColor
60901
+ });
60902
+ }
60204
60903
 
60205
60904
  doAutoscale(features) {
60206
60905
  // if ("proportional" === this.arcType) {
@@ -60290,7 +60989,7 @@
60290
60989
  const candidates = [];
60291
60990
 
60292
60991
  if (featureList) {
60293
- const proportional = this.arcType === "proportional";
60992
+ const proportional = this.arcType === "proportional" || this.arcType === "inView" || this.arcType === "partialInView";
60294
60993
 
60295
60994
  for (let feature of featureList) {
60296
60995
  if (!feature.drawState) continue;
@@ -60358,6 +61057,24 @@
60358
61057
 
60359
61058
  return candidates.map(c => c.feature);
60360
61059
  }
61060
+ /**
61061
+ * Return the current state of the track. Used to create sessions and bookmarks.
61062
+ *
61063
+ * @returns {*|{}}
61064
+ */
61065
+
61066
+
61067
+ getState() {
61068
+ const config = super.getState(); // if (this.height !== undefined) config.height = this.height;
61069
+
61070
+ if (this.arcType !== undefined) config.arcType = this.arcType;
61071
+ if (this.arcOrientation !== undefined) config.arcOrientation = this.arcOrientation;
61072
+ if (this.showBlocks !== undefined) config.showBlocks = this.showBlocks;
61073
+ if (this.blockHeight !== undefined) config.blockHeight = this.blockHeight;
61074
+ if (this.thickness !== undefined) config.thickness = this.thickness;
61075
+ if (this.alpha !== undefined) config.alpha = this.alpha;
61076
+ return config;
61077
+ }
60361
61078
 
60362
61079
  }
60363
61080
 
@@ -60423,32 +61140,104 @@
60423
61140
  return c;
60424
61141
  }
60425
61142
  /**
60426
- * Called in the context of FeatureSource
61143
+ * Called in the context of FeatureSource (i.e. this == the feature source (a TextFeatureSource) for the track
61144
+ *
60427
61145
  * @param allFeatures
60428
61146
  * @returns {[]}
60429
61147
  */
60430
61148
 
60431
61149
 
60432
61150
  function getWGFeatures(allFeatures) {
60433
- const genome = this.genome;
60434
- const wgFeatures = [];
61151
+ const makeWGFeature = f => {
61152
+ const wg = Object.assign({}, f);
61153
+ wg.chr = "all";
61154
+ wg.start = genome.getGenomeCoordinate(f.chr1, f.start1);
61155
+ wg.end = genome.getGenomeCoordinate(f.chr2, f.end2);
61156
+ return wg;
61157
+ };
61158
+
61159
+ const genome = this.genome; // First pass -- find the max score feature
61160
+
61161
+ let maxScoreFeature;
61162
+ let totalFeatureCount = 0;
60435
61163
 
60436
61164
  for (let c of genome.wgChromosomeNames) {
60437
- const chrFeatures = allFeatures[c];
61165
+ let chrFeatures = allFeatures[c];
60438
61166
 
60439
61167
  if (chrFeatures) {
60440
61168
  for (let f of chrFeatures) {
60441
61169
  if (!f.dup) {
60442
- const wg = Object.assign({}, f);
60443
- wg.chr = "all";
60444
- wg.start = genome.getGenomeCoordinate(f.chr1, f.start1);
60445
- wg.end = genome.getGenomeCoordinate(f.chr2, f.end2);
60446
- wgFeatures.push(wg);
61170
+ totalFeatureCount++;
61171
+
61172
+ if (f.score && (!maxScoreFeature || f.score > maxScoreFeature.score)) {
61173
+ maxScoreFeature = f;
61174
+ }
61175
+ }
61176
+ }
61177
+ }
61178
+ }
61179
+
61180
+ const maxCount = this.maxWGCount;
61181
+ const nBins = maxScoreFeature && maxScoreFeature.score > 0 && totalFeatureCount > maxCount ? 5 : 1; // TODO make a function of total # of features & maxCount?
61182
+
61183
+ const featuresPerBin = Math.floor(maxCount / nBins);
61184
+ const binSize = maxScoreFeature && maxScoreFeature.score > 0 ? Math.log(maxScoreFeature.score) / nBins : Number.MAX_SAFE_INTEGER;
61185
+ let binnedFeatures = [];
61186
+ let counts = [];
61187
+
61188
+ for (let i = 0; i < nBins; i++) {
61189
+ counts.push([0]);
61190
+ binnedFeatures.push([]);
61191
+ }
61192
+
61193
+ for (let c of genome.wgChromosomeNames) {
61194
+ let chrFeatures = allFeatures[c];
61195
+
61196
+ if (chrFeatures) {
61197
+ for (let f of chrFeatures) {
61198
+ if (!f.dup) {
61199
+ const bin = f.score ? Math.min(nBins - 1, Math.floor(Math.log(f.score) / binSize)) : 0;
61200
+
61201
+ if (binnedFeatures[bin].length < featuresPerBin) {
61202
+ binnedFeatures[bin].push(makeWGFeature(f));
61203
+ } else {
61204
+ //Reservoir sampling
61205
+ const samplingProb = featuresPerBin / (counts[bin] + 1);
61206
+
61207
+ if (Math.random() < samplingProb) {
61208
+ const idx = Math.floor(Math.random() * (featuresPerBin - 1));
61209
+ binnedFeatures[bin][idx] = makeWGFeature(f);
61210
+ }
61211
+ }
61212
+
61213
+ counts[bin]++;
60447
61214
  }
60448
61215
  }
60449
61216
  }
60450
61217
  }
60451
61218
 
61219
+ let wgFeatures;
61220
+
61221
+ if (nBins === 1) {
61222
+ wgFeatures = binnedFeatures[0];
61223
+ } else {
61224
+ wgFeatures = [];
61225
+
61226
+ for (let bf of binnedFeatures) {
61227
+ for (let f of bf) wgFeatures.push(f);
61228
+ } // Keep the feature with max score
61229
+
61230
+
61231
+ if (maxScoreFeature) {
61232
+ wgFeatures.push(makeWGFeature(maxScoreFeature));
61233
+ }
61234
+
61235
+ wgFeatures.sort(function (a, b) {
61236
+ return a.start - b.start;
61237
+ });
61238
+ console.log(wgFeatures.length);
61239
+ }
61240
+
60452
61241
  return wgFeatures;
60453
61242
  }
60454
61243
  /**
@@ -61579,8 +62368,6 @@
61579
62368
  this.divider = config.divider || "rgb(225,225,225)";
61580
62369
  this.dotSize = config.dotSize || 3;
61581
62370
  this.popoverWindow = config.popoverWindow === undefined ? DEFAULT_POPOVER_WINDOW : config.popoverWindow;
61582
- this.description = config.description; // might be null
61583
-
61584
62371
  this.colorScales = config.color ? new ConstantColorScale(config.color) : {
61585
62372
  "*": new BinnedColorScale(config.colorScale || {
61586
62373
  thresholds: [5e-8, 5e-4, 0.5],
@@ -63149,10 +63936,6 @@
63149
63936
 
63150
63937
  return data;
63151
63938
  }
63152
-
63153
- description() {
63154
- return this.name;
63155
- }
63156
63939
  /**
63157
63940
  * Called when the track is removed. Do any needed cleanup here
63158
63941
  */
@@ -63689,7 +64472,7 @@
63689
64472
 
63690
64473
  this.end = end;
63691
64474
  this.bpPerPixel = bpPerPixel;
63692
- this.id = guid$1();
64475
+ this.id = guid$2();
63693
64476
  }
63694
64477
 
63695
64478
  calculateEnd(pixels) {
@@ -64385,7 +65168,7 @@
64385
65168
  });
64386
65169
  columnContainer.appendChild(this.verticalGuide);
64387
65170
  this.addMouseHandler(browser);
64388
- this.setVisibility(browser.config.showCursorTrackingGuide);
65171
+ this.setVisibility(browser.config.showCursorGuide);
64389
65172
  }
64390
65173
 
64391
65174
  addMouseHandler(browser) {
@@ -64401,42 +65184,44 @@
64401
65184
  const target = document.elementFromPoint(event.clientX, event.clientY);
64402
65185
  let viewport = undefined;
64403
65186
 
64404
- if (target.parentElement.classList.contains('igv-viewport-content')) {
64405
- viewport = target.parentElement.parentElement;
64406
- } else if (target.parentElement.classList.contains('igv-viewport') && target.classList.contains('igv-viewport-content')) {
64407
- viewport = target.parentElement;
64408
- }
65187
+ if (target.parentElement) {
65188
+ if (target.parentElement.classList.contains('igv-viewport-content')) {
65189
+ viewport = target.parentElement.parentElement;
65190
+ } else if (target.parentElement.classList.contains('igv-viewport') && target.classList.contains('igv-viewport-content')) {
65191
+ viewport = target.parentElement;
65192
+ }
64409
65193
 
64410
- if (viewport && browser.getRulerTrackView()) {
64411
- this.verticalGuide.style.left = `${x}px`;
64412
- const columns = browser.root.querySelectorAll('.igv-column');
64413
- let index = undefined;
64414
- const viewportParent = viewport.parentElement;
65194
+ if (viewport && browser.getRulerTrackView()) {
65195
+ this.verticalGuide.style.left = `${x}px`;
65196
+ const columns = browser.root.querySelectorAll('.igv-column');
65197
+ let index = undefined;
65198
+ const viewportParent = viewport.parentElement;
64415
65199
 
64416
- for (let i = 0; i < columns.length; i++) {
64417
- if (undefined === index && viewportParent === columns[i]) {
64418
- index = i;
65200
+ for (let i = 0; i < columns.length; i++) {
65201
+ if (undefined === index && viewportParent === columns[i]) {
65202
+ index = i;
65203
+ }
64419
65204
  }
64420
- }
64421
65205
 
64422
- const rulerViewport = browser.getRulerTrackView().viewports[index];
64423
- const result = rulerViewport.mouseMove(event);
65206
+ const rulerViewport = browser.getRulerTrackView().viewports[index];
65207
+ const result = rulerViewport.mouseMove(event);
64424
65208
 
64425
- if (result) {
64426
- const {
64427
- start,
64428
- bp,
64429
- end
64430
- } = result;
64431
- const interpolant = (bp - start) / (end - start);
64432
-
64433
- if (this.customMouseHandler) {
64434
- this.customMouseHandler({
65209
+ if (result) {
65210
+ const {
64435
65211
  start,
64436
65212
  bp,
64437
- end,
64438
- interpolant
64439
- });
65213
+ end
65214
+ } = result;
65215
+ const interpolant = (bp - start) / (end - start);
65216
+
65217
+ if (this.customMouseHandler) {
65218
+ this.customMouseHandler({
65219
+ start,
65220
+ bp,
65221
+ end,
65222
+ interpolant
65223
+ });
65224
+ }
64440
65225
  }
64441
65226
  }
64442
65227
  }
@@ -64447,8 +65232,8 @@
64447
65232
  this.columnContainer.removeEventListener('mousemove', this.boundMouseMoveHandler);
64448
65233
  }
64449
65234
 
64450
- setVisibility(showCursorTrackingGuide) {
64451
- if (true === showCursorTrackingGuide) {
65235
+ setVisibility(showCursorGuide) {
65236
+ if (true === showCursorGuide) {
64452
65237
  this.show();
64453
65238
  } else {
64454
65239
  this.hide();
@@ -64609,46 +65394,49 @@
64609
65394
  * THE SOFTWARE.
64610
65395
  */
64611
65396
 
64612
- const TrackLabelControl = function (parent, browser) {
64613
- this.button = div$1({
64614
- class: 'igv-navbar-button'
64615
- });
64616
- parent.appendChild(this.button);
64617
- this.button.textContent = 'track labels';
64618
- this.button.addEventListener('click', () => {
64619
- browser.trackLabelsVisible = !browser.trackLabelsVisible;
65397
+ class TrackLabelControl {
65398
+ constructor(parent, browser) {
65399
+ this.button = div$1({
65400
+ class: 'igv-navbar-button'
65401
+ });
65402
+ parent.appendChild(this.button);
65403
+ this.button.textContent = 'track labels';
65404
+ this.button.addEventListener('click', () => {
65405
+ browser.trackLabelsVisible = !browser.trackLabelsVisible;
65406
+ this.setState(browser.trackLabelsVisible);
65407
+ browser.setTrackLabelVisibility(browser.trackLabelsVisible);
65408
+ });
65409
+ this.browser = browser;
65410
+ this.setVisibility(browser.config.showTrackLabelButton);
64620
65411
  this.setState(browser.trackLabelsVisible);
64621
- browser.setTrackLabelVisibility(browser.trackLabelsVisible);
64622
- });
64623
- this.browser = browser;
64624
- this.setVisibility(browser.config.showTrackLabelButton);
64625
- this.setState(browser.trackLabelsVisible);
64626
- };
65412
+ }
64627
65413
 
64628
- TrackLabelControl.prototype.setVisibility = function (showTrackLabelButton) {
64629
- if (true === showTrackLabelButton) {
64630
- this.show();
64631
- } else {
64632
- this.hide();
65414
+ setVisibility(showTrackLabelButton) {
65415
+ if (true === showTrackLabelButton) {
65416
+ this.show();
65417
+ } else {
65418
+ this.hide();
65419
+ }
64633
65420
  }
64634
- };
64635
65421
 
64636
- TrackLabelControl.prototype.setState = function (trackLabelsVisible) {
64637
- if (true === trackLabelsVisible) {
64638
- this.button.classList.add('igv-navbar-button-clicked');
64639
- } else {
64640
- this.button.classList.remove('igv-navbar-button-clicked');
65422
+ setState(trackLabelsVisible) {
65423
+ if (true === trackLabelsVisible) {
65424
+ this.button.classList.add('igv-navbar-button-clicked');
65425
+ } else {
65426
+ this.button.classList.remove('igv-navbar-button-clicked');
65427
+ }
64641
65428
  }
64642
- };
64643
65429
 
64644
- TrackLabelControl.prototype.show = function () {
64645
- this.button.style.display = 'block';
64646
- this.setState(this.browser.trackLabelsVisible);
64647
- };
65430
+ show() {
65431
+ this.button.style.display = 'block';
65432
+ this.setState(this.browser.trackLabelsVisible);
65433
+ }
64648
65434
 
64649
- TrackLabelControl.prototype.hide = function () {
64650
- this.button.style.display = 'none';
64651
- };
65435
+ hide() {
65436
+ this.button.style.display = 'none';
65437
+ }
65438
+
65439
+ }
64652
65440
 
64653
65441
  /*
64654
65442
  * The MIT License (MIT)
@@ -64904,52 +65692,6 @@
64904
65692
  button.addEventListener('click', () => browser.saveSVGtoFile({}));
64905
65693
  };
64906
65694
 
64907
- const viewportColumnManager = {
64908
- createColumns: (columnContainer, count) => {
64909
- for (let i = 0; i < count; i++) {
64910
- if (0 === i) {
64911
- createColumn(columnContainer, 'igv-column');
64912
- } else {
64913
- columnContainer.appendChild(div$1({
64914
- class: 'igv-column-shim'
64915
- }));
64916
- createColumn(columnContainer, 'igv-column');
64917
- }
64918
- }
64919
- },
64920
- removeColumnAtIndex: (i, column) => {
64921
- const shim = 0 === i ? column.nextElementSibling : column.previousElementSibling;
64922
- column.remove();
64923
- shim.remove();
64924
- },
64925
- insertAfter: referenceElement => {
64926
- const shim = div$1({
64927
- class: 'igv-column-shim'
64928
- });
64929
- insertElementAfter(shim, referenceElement);
64930
- const column = div$1({
64931
- class: 'igv-column'
64932
- });
64933
- insertElementAfter(column, shim);
64934
- return column;
64935
- },
64936
- insertBefore: (referenceElement, count) => {
64937
- for (let i = 0; i < count; i++) {
64938
- const column = div$1({
64939
- class: 'igv-column'
64940
- });
64941
- insertElementBefore(column, referenceElement);
64942
-
64943
- if (count > 1 && i > 0) {
64944
- const columnShim = div$1({
64945
- class: 'igv-column-shim'
64946
- });
64947
- insertElementBefore(columnShim, column);
64948
- }
64949
- }
64950
- }
64951
- };
64952
-
64953
65695
  /*
64954
65696
  * The MIT License (MIT)
64955
65697
  *
@@ -65337,6 +66079,19 @@
65337
66079
  this.button.style.display = 'none';
65338
66080
  };
65339
66081
 
66082
+ /**
66083
+ * User supplied button for the navbar
66084
+ */
66085
+
66086
+ const CustomButton = function (parent, browser, b) {
66087
+ const button = div$1({
66088
+ class: 'igv-navbar-button'
66089
+ });
66090
+ parent.append(button);
66091
+ button.textContent = b.label;
66092
+ button.addEventListener('click', () => b.callback(browser));
66093
+ };
66094
+
65340
66095
  /*
65341
66096
  * The MIT License (MIT)
65342
66097
  *
@@ -65375,7 +66130,7 @@
65375
66130
  class Browser {
65376
66131
  constructor(config, parentDiv) {
65377
66132
  this.config = config;
65378
- this.guid = guid$1();
66133
+ this.guid = guid$2();
65379
66134
  this.namespace = '.browser_' + this.guid;
65380
66135
  this.parent = parentDiv;
65381
66136
  this.root = div$1({
@@ -65419,7 +66174,7 @@
65419
66174
 
65420
66175
  this.trackLabelsVisible = config.showTrackLabels;
65421
66176
  this.isCenterLineVisible = config.showCenterGuide;
65422
- this.cursorGuideVisible = config.showCursorTrackingGuide;
66177
+ this.cursorGuideVisible = config.showCursorGuide;
65423
66178
  this.showSampleNames = config.showSampleNames;
65424
66179
  this.showSampleNameButton = config.showSampleNameButton;
65425
66180
  this.sampleNameViewportWidth = config.sampleNameViewportWidth || defaultSampleNameViewportWidth;
@@ -65531,6 +66286,12 @@
65531
66286
  this.svgSaveControl = new SVGSaveControl($toggle_button_container.get(0), this);
65532
66287
  }
65533
66288
 
66289
+ if (config.customButtons) {
66290
+ for (let b of config.customButtons) {
66291
+ new CustomButton($toggle_button_container.get(0), this, b);
66292
+ }
66293
+ }
66294
+
65534
66295
  this.zoomWidget = new ZoomWidget(this, $navbarRightContainer.get(0));
65535
66296
 
65536
66297
  if (false === config.showNavigation) {
@@ -65538,14 +66299,14 @@
65538
66299
  }
65539
66300
 
65540
66301
  this.inputDialog = new InputDialog(this.root);
65541
- this.inputDialog.container.id = `igv-input-dialog-${guid$1()}`;
66302
+ this.inputDialog.container.id = `igv-input-dialog-${guid$2()}`;
65542
66303
  this.dataRangeDialog = new DataRangeDialog($$1(this.root));
65543
- this.dataRangeDialog.$container.get(0).id = `igv-data-range-dialog-${guid$1()}`;
66304
+ this.dataRangeDialog.$container.get(0).id = `igv-data-range-dialog-${guid$2()}`;
65544
66305
  this.genericColorPicker = new GenericColorPicker({
65545
66306
  parent: this.columnContainer,
65546
66307
  width: 432
65547
66308
  });
65548
- this.genericColorPicker.container.id = `igv-track-color-picker-${guid$1()}`;
66309
+ this.genericColorPicker.container.id = `igv-track-color-picker-${guid$2()}`;
65549
66310
  return $navBar;
65550
66311
  }
65551
66312
 
@@ -66580,37 +67341,6 @@
66580
67341
  await this.updateViews(true);
66581
67342
  }
66582
67343
 
66583
- async selectMultiLocusPanel(referenceFrame) {
66584
- const referenceFrameIndex = this.referenceFrameList.indexOf(referenceFrame); // Remove columns for unselected panels
66585
-
66586
- this.columnContainer.querySelectorAll('.igv-column').forEach((column, c) => {
66587
- if (c === referenceFrameIndex) ; else {
66588
- column.remove();
66589
- }
66590
- }); // Remove all column shims
66591
-
66592
- this.columnContainer.querySelectorAll('.igv-column-shim').forEach(shim => shim.remove()); // Discard viewports
66593
-
66594
- for (let trackView of this.trackViews) {
66595
- const retain = trackView.viewports[referenceFrameIndex];
66596
- trackView.viewports.filter((viewport, i) => i !== referenceFrameIndex).forEach(viewport => viewport.dispose());
66597
- trackView.viewports = [retain];
66598
- }
66599
-
66600
- const viewportWidth = this.calculateViewportWidth(1);
66601
- referenceFrame.bpPerPixel = (referenceFrame.end - referenceFrame.start) / viewportWidth;
66602
- this.referenceFrameList = [referenceFrame];
66603
- this.trackViews.forEach(_ref3 => {
66604
- let {
66605
- viewports
66606
- } = _ref3;
66607
- return viewports.forEach(viewport => viewport.setWidth(viewportWidth));
66608
- });
66609
- this.centerLineList = this.createCenterLineList(this.columnContainer);
66610
- this.updateUIWithReferenceFrameList();
66611
- await this.updateViews(true);
66612
- }
66613
-
66614
67344
  async rescaleForMultiLocus(scaleFactor) {
66615
67345
  const viewportWidth = this.calculateViewportWidth(this.referenceFrameList.length);
66616
67346
 
@@ -66799,6 +67529,7 @@
66799
67529
 
66800
67530
  const locus = [];
66801
67531
  const gtexSelections = {};
67532
+ let hasGtexSelections = false;
66802
67533
  let anyTrackView = this.trackViews[0];
66803
67534
 
66804
67535
  for (let {
@@ -66813,13 +67544,13 @@
66813
67544
  snp: referenceFrame.selection.snp
66814
67545
  };
66815
67546
  gtexSelections[locusString] = selection;
67547
+ hasGtexSelections = true;
66816
67548
  }
66817
67549
  }
66818
67550
 
66819
67551
  json["locus"] = locus.length === 1 ? locus[0] : locus;
66820
- const gtexKeys = Object.getOwnPropertyNames(gtexSelections);
66821
67552
 
66822
- if (gtexKeys.length > 0) {
67553
+ if (hasGtexSelections) {
66823
67554
  json["gtexSelections"] = gtexSelections;
66824
67555
  }
66825
67556
 
@@ -66849,29 +67580,22 @@
66849
67580
  trackJson.push(config);
66850
67581
  }
66851
67582
  } catch (e) {
66852
- errors.push(e);
67583
+ console.error(`Track: ${track.name}: ${e}`);
67584
+ errors.push(`Track: ${track.name}: ${e}`);
66853
67585
  }
66854
67586
  }
66855
67587
 
66856
67588
  if (errors.length > 0) {
66857
67589
  let n = 1;
66858
- let message = 'Errors encountered saving session:';
67590
+ let message = 'Errors encountered saving session: </br>';
66859
67591
 
66860
67592
  for (let e of errors) {
66861
- message += ` (${n++}) ${e.toString()}.`;
67593
+ message += ` (${n++}) ${e.toString()} <br/>`;
66862
67594
  }
66863
67595
 
66864
67596
  throw Error(message);
66865
67597
  }
66866
67598
 
66867
- const locaTrackFiles = trackJson.filter(track => {
66868
- track.url && isFile(track.url);
66869
- });
66870
-
66871
- if (locaTrackFiles.length > 0) {
66872
- throw new Error(`Error. Sessions cannot include local file references.`);
66873
- }
66874
-
66875
67599
  json["tracks"] = trackJson;
66876
67600
  return json; // This is an object, not a json string
66877
67601
  }
@@ -67240,7 +67964,7 @@
67240
67964
 
67241
67965
  setDefaults(config);
67242
67966
 
67243
- if (config.queryParametersSupported !== false) {
67967
+ if (config.queryParametersSupported) {
67244
67968
  extractQuery(config);
67245
67969
  }
67246
67970
 
@@ -67304,10 +68028,6 @@
67304
68028
  }
67305
68029
 
67306
68030
  function setDefaults(config) {
67307
- if (undefined === config.promisified) {
67308
- config.promisified = false;
67309
- }
67310
-
67311
68031
  if (undefined === config.minimumBases) {
67312
68032
  config.minimumBases = 40;
67313
68033
  }
@@ -67336,8 +68056,8 @@
67336
68056
  config.showCursorTrackingGuideButton = true;
67337
68057
  }
67338
68058
 
67339
- if (undefined === config.showCursorTrackingGuide) {
67340
- config.showCursorTrackingGuide = false;
68059
+ if (undefined === config.showCursorGuide) {
68060
+ config.showCursorGuide = config.showCursorTrackingGuide || false; // showCursorTrackingGuide is a synonym
67341
68061
  }
67342
68062
 
67343
68063
  if (undefined === config.showCenterGuideButton) {
@@ -67424,6 +68144,8 @@
67424
68144
  }
67425
68145
 
67426
68146
  i = j + 1;
68147
+ } else {
68148
+ i++;
67427
68149
  }
67428
68150
  }
67429
68151
  }
@@ -67461,7 +68183,7 @@
67461
68183
  }
67462
68184
 
67463
68185
  function embedCSS() {
67464
- var css = '.igv-navbar {\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: space-between;\n align-items: center;\n box-sizing: border-box;\n width: 100%;\n color: #444;\n font-size: 12px;\n font-family: \"Open Sans\", sans-serif;\n font-weight: 400;\n line-height: 32px;\n padding-left: 8px;\n padding-right: 8px;\n margin-top: 2px;\n margin-bottom: 6px;\n height: 32px;\n border-style: solid;\n border-radius: 3px;\n border-width: thin;\n border-color: #bfbfbf;\n background-color: #f3f3f3; }\n .igv-navbar .igv-navbar-left-container {\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: space-between;\n align-items: center;\n height: 32px;\n line-height: 32px; }\n .igv-navbar .igv-navbar-left-container .igv-logo {\n width: 34px;\n height: 32px;\n margin-right: 8px; }\n .igv-navbar .igv-navbar-left-container .igv-current-genome {\n height: 32px;\n margin-left: 4px;\n margin-right: 4px;\n user-select: none;\n line-height: 32px;\n vertical-align: middle;\n text-align: center; }\n .igv-navbar .igv-navbar-left-container .igv-navbar-genomic-location {\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: space-between;\n align-items: center;\n height: 100%; }\n .igv-navbar .igv-navbar-left-container .igv-navbar-genomic-location .igv-chromosome-select-widget-container {\n display: flex;\n flex-flow: column;\n flex-wrap: nowrap;\n justify-content: space-around;\n align-items: center;\n height: 100%;\n width: 125px;\n margin-right: 4px; }\n .igv-navbar .igv-navbar-left-container .igv-navbar-genomic-location .igv-chromosome-select-widget-container select {\n display: block;\n cursor: pointer;\n width: 100px;\n height: 75%;\n outline: none;\n font-size: 12px;\n font-family: \"Open Sans\", sans-serif;\n font-weight: 400; }\n .igv-navbar .igv-navbar-left-container .igv-navbar-genomic-location .igv-locus-size-group {\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: space-between;\n align-items: center;\n margin-left: 8px;\n height: 22px; }\n .igv-navbar .igv-navbar-left-container .igv-navbar-genomic-location .igv-locus-size-group .igv-search-container {\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: center;\n width: 210px;\n height: 22px;\n line-height: 22px; }\n .igv-navbar .igv-navbar-left-container .igv-navbar-genomic-location .igv-locus-size-group .igv-search-container input.igv-search-input {\n cursor: text;\n width: 85%;\n height: 22px;\n line-height: 22px;\n font-size: 12px;\n font-family: \"Open Sans\", sans-serif;\n font-weight: 400;\n text-align: left;\n padding-left: 8px;\n margin-right: 8px;\n outline: none;\n border-style: solid;\n border-radius: 3px;\n border-width: thin;\n border-color: #bfbfbf;\n background-color: white; }\n .igv-navbar .igv-navbar-left-container .igv-navbar-genomic-location .igv-locus-size-group .igv-search-container .igv-search-icon-container {\n cursor: pointer;\n height: 16px;\n width: 16px; }\n .igv-navbar .igv-navbar-left-container .igv-navbar-genomic-location .igv-locus-size-group .igv-windowsize-panel-container {\n margin-left: 4px;\n user-select: none; }\n .igv-navbar .igv-navbar-right-container {\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: space-between;\n align-items: center;\n height: 32px;\n line-height: 32px; }\n .igv-navbar .igv-navbar-right-container .igv-navbar-toggle-button-container {\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: space-between;\n align-items: center;\n height: 100%; }\n .igv-navbar .igv-navbar-right-container .igv-navbar-toggle-button-container div {\n margin-left: 0;\n margin-right: 4px; }\n .igv-navbar .igv-navbar-right-container .igv-navbar-toggle-button-container div:last-child {\n margin-left: 0;\n margin-right: 0; }\n .igv-navbar .igv-navbar-right-container .igv-navbar-toggle-button-container-750 {\n display: none; }\n .igv-navbar .igv-navbar-right-container .igv-zoom-widget {\n color: #737373;\n font-size: 18px;\n height: 32px;\n line-height: 32px;\n margin-left: 8px;\n user-select: none;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: flex-end;\n align-items: center; }\n .igv-navbar .igv-navbar-right-container .igv-zoom-widget div {\n cursor: pointer;\n margin-left: unset;\n margin-right: unset; }\n .igv-navbar .igv-navbar-right-container .igv-zoom-widget div:first-child {\n height: 24px;\n width: 24px;\n margin-left: unset;\n margin-right: 8px; }\n .igv-navbar .igv-navbar-right-container .igv-zoom-widget div:last-child {\n height: 24px;\n width: 24px;\n margin-left: 8px;\n margin-right: unset; }\n .igv-navbar .igv-navbar-right-container .igv-zoom-widget div:nth-child(even) {\n display: block;\n height: fit-content; }\n .igv-navbar .igv-navbar-right-container .igv-zoom-widget input {\n display: block;\n width: 125px; }\n .igv-navbar .igv-navbar-right-container .igv-zoom-widget svg {\n display: block; }\n .igv-navbar .igv-navbar-right-container .igv-zoom-widget-900 {\n color: #737373;\n font-size: 18px;\n height: 32px;\n line-height: 32px;\n margin-left: 8px;\n user-select: none;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: flex-end;\n align-items: center; }\n .igv-navbar .igv-navbar-right-container .igv-zoom-widget-900 div {\n cursor: pointer;\n margin-left: unset;\n margin-right: unset; }\n .igv-navbar .igv-navbar-right-container .igv-zoom-widget-900 div:first-child {\n height: 24px;\n width: 24px;\n margin-left: unset;\n margin-right: 8px; }\n .igv-navbar .igv-navbar-right-container .igv-zoom-widget-900 div:last-child {\n height: 24px;\n width: 24px;\n margin-left: 8px;\n margin-right: unset; }\n .igv-navbar .igv-navbar-right-container .igv-zoom-widget-900 div:nth-child(even) {\n width: 0;\n height: 0;\n display: none; }\n .igv-navbar .igv-navbar-right-container .igv-zoom-widget-900 input {\n width: 0;\n height: 0;\n display: none; }\n .igv-navbar .igv-navbar-right-container .igv-zoom-widget-900 svg {\n display: block; }\n .igv-navbar .igv-navbar-right-container .igv-zoom-widget-hidden {\n display: none; }\n\n.igv-navbar-button {\n display: block;\n box-sizing: unset;\n padding-left: 6px;\n padding-right: 6px;\n height: 18px;\n text-transform: capitalize;\n user-select: none;\n line-height: 18px;\n text-align: center;\n vertical-align: middle;\n font-family: \"Open Sans\", sans-serif;\n font-size: 11px;\n font-weight: 200;\n color: #737373;\n background-color: #f3f3f3;\n border-color: #737373;\n border-style: solid;\n border-width: thin;\n border-radius: 6px; }\n\n.igv-navbar-button-clicked {\n color: white;\n background-color: #737373; }\n\n.igv-navbar-button:hover {\n cursor: pointer; }\n\n.igv-zoom-in-notice-container {\n z-index: 1024;\n position: absolute;\n top: 8px;\n left: 50%;\n transform: translate(-50%, 0%);\n display: flex;\n flex-direction: row;\n flex-wrap: nowrap;\n justify-content: center;\n align-items: center;\n background-color: white; }\n .igv-zoom-in-notice-container > div {\n padding-left: 4px;\n padding-right: 4px;\n padding-top: 2px;\n padding-bottom: 2px;\n width: 100%;\n height: 100%;\n font-family: \"Open Sans\", sans-serif;\n font-size: 14px;\n font-weight: 400;\n color: #3f3f3f; }\n\n.igv-zoom-in-notice {\n position: absolute;\n top: 10px;\n left: 50%; }\n .igv-zoom-in-notice div {\n position: relative;\n left: -50%;\n font-family: \"Open Sans\", sans-serif;\n font-size: medium;\n font-weight: 400;\n color: #3f3f3f;\n background-color: rgba(255, 255, 255, 0.51);\n z-index: 64; }\n\n.igv-container-spinner {\n position: absolute;\n top: 90%;\n left: 50%;\n transform: translate(-50%, -50%);\n z-index: 1024;\n width: 24px;\n height: 24px;\n pointer-events: none;\n color: #737373; }\n\n.igv-multi-locus-close-button {\n position: absolute;\n top: 2px;\n right: 0;\n padding-left: 2px;\n padding-right: 2px;\n width: 14px;\n height: 14px;\n color: #666666;\n background-color: white;\n z-index: 1000; }\n .igv-multi-locus-close-button > svg {\n vertical-align: top; }\n\n.igv-multi-locus-close-button:hover {\n cursor: pointer;\n color: #434343; }\n\n.igv-multi-locus-ruler-label {\n z-index: 64;\n position: absolute;\n top: 2px;\n left: 0;\n width: 100%;\n height: 14px;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: center;\n align-items: center; }\n .igv-multi-locus-ruler-label div {\n font-family: \"Open Sans\", sans-serif;\n font-size: 14px;\n font-weight: 400;\n color: #101010;\n background-color: white; }\n\n.igv-multi-locus-ruler-label-square-dot {\n z-index: 64;\n position: absolute;\n left: 50%;\n top: 5%;\n transform: translate(-50%, 0%);\n background-color: white;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: center; }\n .igv-multi-locus-ruler-label-square-dot > div:first-child {\n width: 14px;\n height: 14px; }\n .igv-multi-locus-ruler-label-square-dot > div:last-child {\n margin-left: 16px;\n font-family: \"Open Sans\", sans-serif;\n font-size: 14px;\n font-weight: 400;\n color: #101010; }\n\n.igv-multi-locus-ruler-label:hover {\n cursor: pointer; }\n\n.igv-ruler-sweeper {\n display: none;\n pointer-events: none;\n position: absolute;\n top: 0;\n left: 0;\n width: 0;\n height: 100%;\n z-index: 99999;\n background-color: rgba(68, 134, 247, 0.25); }\n\n.igv-ruler-tooltip {\n pointer-events: none;\n z-index: 128;\n position: absolute;\n top: 0;\n left: 0;\n width: 1px;\n height: 32px;\n background-color: transparent;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: center; }\n .igv-ruler-tooltip > div {\n pointer-events: none;\n width: 128px;\n height: auto;\n padding: 1px;\n color: #373737;\n font-size: 10px;\n font-family: \"Open Sans\", sans-serif;\n font-weight: 400;\n background-color: white;\n border-style: solid;\n border-width: thin;\n border-color: #373737; }\n\n.igv-track-label {\n position: absolute;\n left: 8px;\n top: 8px;\n width: auto;\n height: auto;\n max-width: 200px;\n padding-left: 4px;\n padding-right: 4px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n font-family: \"Open Sans\", sans-serif;\n font-size: small;\n font-weight: 400;\n text-align: center;\n user-select: none;\n -moz-user-select: none;\n -webkit-user-select: none;\n border-color: #444;\n border-radius: 2px;\n border-style: solid;\n border-width: thin;\n background-color: white;\n z-index: 128;\n cursor: pointer; }\n\n.igv-track-label:hover,\n.igv-track-label:focus,\n.igv-track-label:active {\n background-color: #e8e8e8; }\n\n.igv-center-line {\n display: none;\n pointer-events: none;\n position: absolute;\n top: 0;\n bottom: 0;\n transform: translateX(-50%);\n z-index: 8;\n user-select: none;\n -moz-user-select: none;\n -webkit-user-select: none;\n border-left-style: dashed;\n border-left-width: thin;\n border-right-style: dashed;\n border-right-width: thin; }\n\n.igv-center-line-wide {\n background-color: rgba(0, 0, 0, 0);\n border-left-color: rgba(127, 127, 127, 0.51);\n border-right-color: rgba(127, 127, 127, 0.51); }\n\n.igv-center-line-thin {\n background-color: rgba(0, 0, 0, 0);\n border-left-color: rgba(127, 127, 127, 0.51);\n border-right-color: rgba(0, 0, 0, 0); }\n\n.igv-cursor-guide-horizontal {\n display: none;\n pointer-events: none;\n user-select: none;\n -moz-user-select: none;\n -webkit-user-select: none;\n position: absolute;\n left: 0;\n right: 0;\n top: 50%;\n height: 1px;\n z-index: 1;\n margin-left: 50px;\n margin-right: 54px;\n border-top-style: dotted;\n border-top-width: thin;\n border-top-color: rgba(127, 127, 127, 0.76); }\n\n.igv-cursor-guide-vertical {\n pointer-events: none;\n user-select: none;\n -moz-user-select: none;\n -webkit-user-select: none;\n position: absolute;\n top: 0;\n bottom: 0;\n left: 50%;\n width: 1px;\n z-index: 1;\n border-left-style: dotted;\n border-left-width: thin;\n border-left-color: rgba(127, 127, 127, 0.76);\n display: none; }\n\n.igv-user-feedback {\n position: fixed;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 512px;\n height: 360px;\n z-index: 2048;\n background-color: white;\n border-color: #a2a2a2;\n border-style: solid;\n border-width: thin;\n font-family: \"Open Sans\", sans-serif;\n font-size: medium;\n font-weight: 400;\n color: #444;\n display: flex;\n flex-direction: column;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: center; }\n .igv-user-feedback div:first-child {\n position: relative;\n height: 24px;\n width: 100%;\n background-color: white;\n border-bottom-color: #a2a2a2;\n border-bottom-style: solid;\n border-bottom-width: thin; }\n .igv-user-feedback div:first-child div {\n position: absolute;\n top: 2px;\n width: 16px;\n height: 16px;\n background-color: transparent; }\n .igv-user-feedback div:first-child div:first-child {\n left: 8px; }\n .igv-user-feedback div:first-child div:last-child {\n cursor: pointer;\n right: 8px; }\n .igv-user-feedback div:last-child {\n width: 100%;\n height: calc(100% - 24px);\n border-width: 0; }\n .igv-user-feedback div:last-child div {\n width: auto;\n height: auto;\n margin: 8px; }\n\n.igv-generic-dialog-container {\n position: absolute;\n top: 0;\n left: 0;\n width: 300px;\n height: 200px;\n border-color: #7F7F7F;\n border-radius: 4px;\n border-style: solid;\n border-width: thin;\n font-family: \"Open Sans\", sans-serif;\n font-size: medium;\n font-weight: 400;\n z-index: 2048;\n background-color: white;\n display: flex;\n flex-flow: column;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: center; }\n .igv-generic-dialog-container .igv-generic-dialog-header {\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: flex-end;\n align-items: center;\n width: 100%;\n height: 24px;\n cursor: move;\n border-top-left-radius: 4px;\n border-top-right-radius: 4px;\n border-bottom-color: #7F7F7F;\n border-bottom-style: solid;\n border-bottom-width: thin;\n background-color: #eee; }\n .igv-generic-dialog-container .igv-generic-dialog-header div {\n margin-right: 4px;\n margin-bottom: 2px;\n height: 12px;\n width: 12px;\n color: #7F7F7F; }\n .igv-generic-dialog-container .igv-generic-dialog-header div:hover {\n cursor: pointer;\n color: #444; }\n .igv-generic-dialog-container .igv-generic-dialog-one-liner {\n color: #373737;\n width: 95%;\n height: 24px;\n line-height: 24px;\n text-align: left;\n margin-top: 8px;\n padding-left: 8px;\n overflow-wrap: break-word;\n background-color: white; }\n .igv-generic-dialog-container .igv-generic-dialog-label-input {\n margin-top: 8px;\n width: 95%;\n height: 24px;\n color: #373737;\n line-height: 24px;\n padding-left: 8px;\n background-color: white;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: center; }\n .igv-generic-dialog-container .igv-generic-dialog-label-input div {\n width: 30%;\n height: 100%;\n font-size: 16px;\n text-align: right;\n padding-right: 8px;\n background-color: white; }\n .igv-generic-dialog-container .igv-generic-dialog-label-input input {\n display: block;\n height: 100%;\n width: 100%;\n padding-left: 4px;\n font-family: \"Open Sans\", sans-serif;\n font-weight: 400;\n color: #373737;\n text-align: left;\n outline: none;\n border-style: solid;\n border-width: thin;\n border-color: #7F7F7F;\n background-color: white; }\n .igv-generic-dialog-container .igv-generic-dialog-label-input input {\n width: 50%;\n font-size: 16px; }\n .igv-generic-dialog-container .igv-generic-dialog-input {\n margin-top: 8px;\n width: calc(100% - 16px);\n height: 24px;\n color: #373737;\n line-height: 24px;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: space-around;\n align-items: center; }\n .igv-generic-dialog-container .igv-generic-dialog-input input {\n display: block;\n height: 100%;\n width: 100%;\n padding-left: 4px;\n font-family: \"Open Sans\", sans-serif;\n font-weight: 400;\n color: #373737;\n text-align: left;\n outline: none;\n border-style: solid;\n border-width: thin;\n border-color: #7F7F7F;\n background-color: white; }\n .igv-generic-dialog-container .igv-generic-dialog-input input {\n font-size: 16px; }\n .igv-generic-dialog-container .igv-generic-dialog-ok-cancel {\n width: 100%;\n height: 28px;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: space-around;\n align-items: center; }\n .igv-generic-dialog-container .igv-generic-dialog-ok-cancel div {\n margin-top: 32px;\n color: white;\n font-family: \"Open Sans\", sans-serif;\n font-size: 14px;\n font-weight: 400;\n width: 75px;\n height: 28px;\n line-height: 28px;\n text-align: center;\n border-color: transparent;\n border-style: solid;\n border-width: thin;\n border-radius: 2px; }\n .igv-generic-dialog-container .igv-generic-dialog-ok-cancel div:first-child {\n margin-left: 32px;\n margin-right: 0;\n background-color: #5ea4e0; }\n .igv-generic-dialog-container .igv-generic-dialog-ok-cancel div:last-child {\n margin-left: 0;\n margin-right: 32px;\n background-color: #c4c4c4; }\n .igv-generic-dialog-container .igv-generic-dialog-ok-cancel div:first-child:hover {\n cursor: pointer;\n background-color: #3b5c7f; }\n .igv-generic-dialog-container .igv-generic-dialog-ok-cancel div:last-child:hover {\n cursor: pointer;\n background-color: #7f7f7f; }\n .igv-generic-dialog-container .igv-generic-dialog-ok {\n width: 100%;\n height: 36px;\n margin-top: 32px;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: space-around;\n align-items: center; }\n .igv-generic-dialog-container .igv-generic-dialog-ok div {\n width: 98px;\n height: 36px;\n line-height: 36px;\n text-align: center;\n color: white;\n font-family: \"Open Sans\", sans-serif;\n font-size: medium;\n font-weight: 400;\n border-color: white;\n border-style: solid;\n border-width: thin;\n border-radius: 4px;\n background-color: #2B81AF; }\n .igv-generic-dialog-container .igv-generic-dialog-ok div:hover {\n cursor: pointer;\n background-color: #25597f; }\n\n.igv-generic-container {\n position: absolute;\n top: 0;\n left: 0;\n z-index: 2048;\n background-color: white;\n cursor: pointer;\n display: flex;\n flex-direction: row;\n flex-wrap: wrap;\n justify-content: flex-start;\n align-items: center; }\n .igv-generic-container div:first-child {\n cursor: move;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: flex-end;\n align-items: center;\n height: 24px;\n width: 100%;\n background-color: #dddddd; }\n .igv-generic-container div:first-child i {\n display: block;\n color: #5f5f5f;\n cursor: pointer;\n width: 14px;\n height: 14px;\n margin-right: 8px;\n margin-bottom: 4px; }\n\n.igv-menu-popup {\n position: absolute;\n top: 0;\n left: 0;\n width: max-content;\n z-index: 4096;\n cursor: pointer;\n font-family: \"Open Sans\", sans-serif;\n font-size: small;\n font-weight: 400;\n color: #4b4b4b;\n background: white;\n border-radius: 4px;\n border-color: #7F7F7F;\n border-style: solid;\n border-width: thin;\n display: flex;\n flex-flow: column;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: flex-end;\n text-align: left; }\n .igv-menu-popup > div:not(:first-child) {\n width: 100%; }\n .igv-menu-popup > div:not(:first-child) > div {\n background: white; }\n .igv-menu-popup > div:not(:first-child) > div.context-menu {\n padding-left: 4px;\n padding-right: 4px; }\n .igv-menu-popup > div:not(:first-child) > div:last-child {\n border-bottom-left-radius: 4px;\n border-bottom-right-radius: 4px;\n border-bottom-color: transparent;\n border-bottom-style: solid;\n border-bottom-width: thin; }\n .igv-menu-popup > div:not(:first-child) > div:hover {\n background: #efefef; }\n\n.igv-menu-popup-shim {\n padding-left: 8px;\n padding-right: 8px; }\n\n.igv-menu-popup-header {\n position: relative;\n width: 100%;\n height: 24px;\n cursor: move;\n border-top-color: transparent;\n border-top-left-radius: 4px;\n border-top-right-radius: 4px;\n border-bottom-color: #7F7F7F;\n border-bottom-style: solid;\n border-bottom-width: thin;\n background-color: #eee;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: flex-end;\n align-items: center; }\n .igv-menu-popup-header div {\n margin-right: 4px;\n height: 12px;\n width: 12px;\n color: #7F7F7F; }\n .igv-menu-popup-header div:hover {\n cursor: pointer;\n color: #444; }\n\n.igv-menu-popup-check-container {\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: center;\n width: 100%;\n height: 20px;\n background-color: transparent; }\n .igv-menu-popup-check-container div {\n padding-top: 2px;\n padding-left: 8px; }\n .igv-menu-popup-check-container div:first-child {\n position: relative;\n width: 12px;\n height: 12px; }\n .igv-menu-popup-check-container div:first-child svg {\n position: absolute;\n width: 12px;\n height: 12px; }\n\n.igv-user-feedback {\n position: fixed;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 512px;\n height: 360px;\n z-index: 2048;\n background-color: white;\n border-color: #a2a2a2;\n border-style: solid;\n border-width: thin;\n font-family: \"Open Sans\", sans-serif;\n font-size: medium;\n font-weight: 400;\n color: #444;\n display: flex;\n flex-direction: column;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: center; }\n .igv-user-feedback div:first-child {\n position: relative;\n height: 24px;\n width: 100%;\n background-color: white;\n border-bottom-color: #a2a2a2;\n border-bottom-style: solid;\n border-bottom-width: thin; }\n .igv-user-feedback div:first-child div {\n position: absolute;\n top: 2px;\n width: 16px;\n height: 16px;\n background-color: transparent; }\n .igv-user-feedback div:first-child div:first-child {\n left: 8px; }\n .igv-user-feedback div:first-child div:last-child {\n cursor: pointer;\n right: 8px; }\n .igv-user-feedback div:last-child {\n width: 100%;\n height: calc(100% - 24px);\n border-width: 0; }\n .igv-user-feedback div:last-child div {\n width: auto;\n height: auto;\n margin: 8px; }\n\n.igv-loading-spinner-container {\n z-index: 1024;\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 32px;\n height: 32px;\n display: flex;\n flex-direction: row;\n flex-wrap: nowrap;\n justify-content: center;\n align-items: center; }\n .igv-loading-spinner-container > div {\n box-sizing: border-box;\n width: 100%;\n height: 100%;\n border-radius: 50%;\n border: 4px solid rgba(128, 128, 128, 0.5);\n border-top-color: white;\n animation: spin 1s ease-in-out infinite;\n -webkit-animation: spin 1s ease-in-out infinite; }\n\n@keyframes spin {\n to {\n -webkit-transform: rotate(360deg);\n transform: rotate(360deg); } }\n@-webkit-keyframes spin {\n to {\n -webkit-transform: rotate(360deg);\n transform: rotate(360deg); } }\n.igv-container {\n position: relative;\n display: flex;\n flex-direction: column;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: flex-start;\n padding-top: 4px;\n user-select: none;\n -webkit-user-select: none;\n -ms-user-select: none; }\n\n.igv-viewport {\n position: relative;\n margin-top: 5px;\n overflow-x: hidden;\n overflow-y: hidden; }\n\n.igv-viewport-content {\n position: relative;\n width: 100%; }\n .igv-viewport-content > canvas {\n position: relative;\n display: block; }\n\n.igv-column-container {\n position: relative;\n display: flex;\n flex-direction: row;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: stretch;\n width: 100%; }\n\n.igv-column-shim {\n width: 1px;\n margin-left: 2px;\n margin-right: 2px;\n background-color: #545453; }\n\n.igv-column {\n position: relative;\n display: flex;\n flex-direction: column;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: flex-start;\n box-sizing: border-box;\n height: 100%; }\n\n.igv-axis-column {\n display: flex;\n flex-direction: column;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: flex-start;\n box-sizing: border-box;\n height: 100%;\n width: 50px; }\n .igv-axis-column > div {\n margin-top: 5px;\n width: 100%; }\n\n.igv-sample-name-column {\n display: flex;\n flex-direction: column;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: flex-start;\n box-sizing: border-box;\n height: 100%; }\n\n.igv-scrollbar-column {\n display: flex;\n flex-direction: column;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: flex-start;\n box-sizing: border-box;\n height: 100%;\n width: 14px; }\n .igv-scrollbar-column > div {\n position: relative;\n margin-top: 5px;\n width: 14px; }\n .igv-scrollbar-column > div > div {\n cursor: pointer;\n position: absolute;\n top: 0;\n left: 2px;\n width: 8px;\n border-width: 1px;\n border-style: solid;\n border-color: #c4c4c4;\n border-top-left-radius: 4px;\n border-top-right-radius: 4px;\n border-bottom-left-radius: 4px;\n border-bottom-right-radius: 4px; }\n .igv-scrollbar-column > div > div:hover {\n background-color: #c4c4c4; }\n\n.igv-track-drag-column {\n display: flex;\n flex-direction: column;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: flex-start;\n box-sizing: border-box;\n height: 100%;\n width: 12px;\n background-color: white; }\n .igv-track-drag-column > .igv-track-drag-handle {\n z-index: 512;\n position: relative;\n cursor: pointer;\n margin-top: 5px;\n width: 100%;\n border-style: solid;\n border-width: 0;\n border-top-right-radius: 6px;\n border-bottom-right-radius: 6px;\n background-color: #c4c4c4; }\n .igv-track-drag-column .igv-track-drag-handle-hover {\n background-color: #787878; }\n .igv-track-drag-column > .igv-track-drag-shim {\n position: relative;\n margin-top: 5px;\n width: 100%;\n border-style: solid;\n border-width: 0; }\n\n.igv-gear-menu-column {\n display: flex;\n flex-direction: column;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: flex-start;\n box-sizing: border-box;\n height: 100%;\n width: 28px; }\n .igv-gear-menu-column > div {\n display: flex;\n flex-direction: column;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: center;\n margin-top: 5px;\n width: 100%;\n background: white; }\n .igv-gear-menu-column > div > div {\n position: relative;\n margin-top: 4px;\n width: 16px;\n height: 16px;\n color: #7F7F7F; }\n .igv-gear-menu-column > div > div:hover {\n cursor: pointer;\n color: #444; }\n\n/*# sourceMappingURL=dom.css.map */\n';
68186
+ var css = '.igv-navbar {\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: space-between;\n align-items: center;\n box-sizing: border-box;\n width: 100%;\n color: #444;\n font-size: 12px;\n font-family: \"Open Sans\", sans-serif;\n font-weight: 400;\n line-height: 32px;\n padding-left: 8px;\n padding-right: 8px;\n margin-top: 2px;\n margin-bottom: 6px;\n height: 32px;\n border-style: solid;\n border-radius: 3px;\n border-width: thin;\n border-color: #bfbfbf;\n background-color: #f3f3f3; }\n .igv-navbar .igv-navbar-left-container {\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: space-between;\n align-items: center;\n height: 32px;\n line-height: 32px; }\n .igv-navbar .igv-navbar-left-container .igv-logo {\n width: 34px;\n height: 32px;\n margin-right: 8px; }\n .igv-navbar .igv-navbar-left-container .igv-current-genome {\n height: 32px;\n margin-left: 4px;\n margin-right: 4px;\n user-select: none;\n line-height: 32px;\n vertical-align: middle;\n text-align: center; }\n .igv-navbar .igv-navbar-left-container .igv-navbar-genomic-location {\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: space-between;\n align-items: center;\n height: 100%; }\n .igv-navbar .igv-navbar-left-container .igv-navbar-genomic-location .igv-chromosome-select-widget-container {\n display: flex;\n flex-flow: column;\n flex-wrap: nowrap;\n justify-content: space-around;\n align-items: center;\n height: 100%;\n width: 125px;\n margin-right: 4px; }\n .igv-navbar .igv-navbar-left-container .igv-navbar-genomic-location .igv-chromosome-select-widget-container select {\n display: block;\n cursor: pointer;\n width: 100px;\n height: 75%;\n outline: none;\n font-size: 12px;\n font-family: \"Open Sans\", sans-serif;\n font-weight: 400; }\n .igv-navbar .igv-navbar-left-container .igv-navbar-genomic-location .igv-locus-size-group {\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: space-between;\n align-items: center;\n margin-left: 8px;\n height: 22px; }\n .igv-navbar .igv-navbar-left-container .igv-navbar-genomic-location .igv-locus-size-group .igv-search-container {\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: center;\n width: 210px;\n height: 22px;\n line-height: 22px; }\n .igv-navbar .igv-navbar-left-container .igv-navbar-genomic-location .igv-locus-size-group .igv-search-container input.igv-search-input {\n cursor: text;\n width: 85%;\n height: 22px;\n line-height: 22px;\n font-size: 12px;\n font-family: \"Open Sans\", sans-serif;\n font-weight: 400;\n text-align: left;\n padding-left: 8px;\n margin-right: 8px;\n outline: none;\n border-style: solid;\n border-radius: 3px;\n border-width: thin;\n border-color: #bfbfbf;\n background-color: white; }\n .igv-navbar .igv-navbar-left-container .igv-navbar-genomic-location .igv-locus-size-group .igv-search-container .igv-search-icon-container {\n cursor: pointer;\n height: 16px;\n width: 16px; }\n .igv-navbar .igv-navbar-left-container .igv-navbar-genomic-location .igv-locus-size-group .igv-windowsize-panel-container {\n margin-left: 4px;\n user-select: none; }\n .igv-navbar .igv-navbar-right-container {\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: space-between;\n align-items: center;\n height: 32px;\n line-height: 32px; }\n .igv-navbar .igv-navbar-right-container .igv-navbar-toggle-button-container {\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: space-between;\n align-items: center;\n height: 100%; }\n .igv-navbar .igv-navbar-right-container .igv-navbar-toggle-button-container div {\n margin-left: 0;\n margin-right: 4px; }\n .igv-navbar .igv-navbar-right-container .igv-navbar-toggle-button-container div:last-child {\n margin-left: 0;\n margin-right: 0; }\n .igv-navbar .igv-navbar-right-container .igv-navbar-toggle-button-container-750 {\n display: none; }\n .igv-navbar .igv-navbar-right-container .igv-zoom-widget {\n color: #737373;\n font-size: 18px;\n height: 32px;\n line-height: 32px;\n margin-left: 8px;\n user-select: none;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: flex-end;\n align-items: center; }\n .igv-navbar .igv-navbar-right-container .igv-zoom-widget div {\n cursor: pointer;\n margin-left: unset;\n margin-right: unset; }\n .igv-navbar .igv-navbar-right-container .igv-zoom-widget div:first-child {\n height: 24px;\n width: 24px;\n margin-left: unset;\n margin-right: 8px; }\n .igv-navbar .igv-navbar-right-container .igv-zoom-widget div:last-child {\n height: 24px;\n width: 24px;\n margin-left: 8px;\n margin-right: unset; }\n .igv-navbar .igv-navbar-right-container .igv-zoom-widget div:nth-child(even) {\n display: block;\n height: fit-content; }\n .igv-navbar .igv-navbar-right-container .igv-zoom-widget input {\n display: block;\n width: 125px; }\n .igv-navbar .igv-navbar-right-container .igv-zoom-widget svg {\n display: block; }\n .igv-navbar .igv-navbar-right-container .igv-zoom-widget-900 {\n color: #737373;\n font-size: 18px;\n height: 32px;\n line-height: 32px;\n margin-left: 8px;\n user-select: none;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: flex-end;\n align-items: center; }\n .igv-navbar .igv-navbar-right-container .igv-zoom-widget-900 div {\n cursor: pointer;\n margin-left: unset;\n margin-right: unset; }\n .igv-navbar .igv-navbar-right-container .igv-zoom-widget-900 div:first-child {\n height: 24px;\n width: 24px;\n margin-left: unset;\n margin-right: 8px; }\n .igv-navbar .igv-navbar-right-container .igv-zoom-widget-900 div:last-child {\n height: 24px;\n width: 24px;\n margin-left: 8px;\n margin-right: unset; }\n .igv-navbar .igv-navbar-right-container .igv-zoom-widget-900 div:nth-child(even) {\n width: 0;\n height: 0;\n display: none; }\n .igv-navbar .igv-navbar-right-container .igv-zoom-widget-900 input {\n width: 0;\n height: 0;\n display: none; }\n .igv-navbar .igv-navbar-right-container .igv-zoom-widget-900 svg {\n display: block; }\n .igv-navbar .igv-navbar-right-container .igv-zoom-widget-hidden {\n display: none; }\n\n.igv-navbar-button {\n display: block;\n box-sizing: unset;\n padding-left: 6px;\n padding-right: 6px;\n height: 18px;\n text-transform: capitalize;\n user-select: none;\n line-height: 18px;\n text-align: center;\n vertical-align: middle;\n font-family: \"Open Sans\", sans-serif;\n font-size: 11px;\n font-weight: 200;\n color: #737373;\n background-color: #f3f3f3;\n border-color: #737373;\n border-style: solid;\n border-width: thin;\n border-radius: 6px; }\n\n.igv-navbar-button-clicked {\n color: white;\n background-color: #737373; }\n\n.igv-navbar-button:hover {\n cursor: pointer; }\n\n.igv-zoom-in-notice-container {\n z-index: 1024;\n position: absolute;\n top: 8px;\n left: 50%;\n transform: translate(-50%, 0%);\n display: flex;\n flex-direction: row;\n flex-wrap: nowrap;\n justify-content: center;\n align-items: center;\n background-color: white; }\n .igv-zoom-in-notice-container > div {\n padding-left: 4px;\n padding-right: 4px;\n padding-top: 2px;\n padding-bottom: 2px;\n width: 100%;\n height: 100%;\n font-family: \"Open Sans\", sans-serif;\n font-size: 14px;\n font-weight: 400;\n color: #3f3f3f; }\n\n.igv-zoom-in-notice {\n position: absolute;\n top: 10px;\n left: 50%; }\n .igv-zoom-in-notice div {\n position: relative;\n left: -50%;\n font-family: \"Open Sans\", sans-serif;\n font-size: medium;\n font-weight: 400;\n color: #3f3f3f;\n background-color: rgba(255, 255, 255, 0.51);\n z-index: 64; }\n\n.igv-container-spinner {\n position: absolute;\n top: 90%;\n left: 50%;\n transform: translate(-50%, -50%);\n z-index: 1024;\n width: 24px;\n height: 24px;\n pointer-events: none;\n color: #737373; }\n\n.igv-multi-locus-close-button {\n position: absolute;\n top: 2px;\n right: 0;\n padding-left: 2px;\n padding-right: 2px;\n width: 18px;\n height: 18px;\n color: #666666;\n background-color: white;\n z-index: 1000; }\n .igv-multi-locus-close-button > svg {\n vertical-align: top; }\n\n.igv-multi-locus-close-button:hover {\n cursor: pointer;\n color: #434343; }\n\n.igv-multi-locus-ruler-label {\n z-index: 64;\n position: absolute;\n top: 2px;\n left: 0;\n width: 100%;\n height: 14px;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: center;\n align-items: center; }\n .igv-multi-locus-ruler-label div {\n font-family: \"Open Sans\", sans-serif;\n font-size: 14px;\n font-weight: 400;\n color: #101010;\n background-color: white; }\n\n.igv-multi-locus-ruler-label-square-dot {\n z-index: 64;\n position: absolute;\n left: 50%;\n top: 5%;\n transform: translate(-50%, 0%);\n background-color: white;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: center; }\n .igv-multi-locus-ruler-label-square-dot > div:first-child {\n width: 14px;\n height: 14px; }\n .igv-multi-locus-ruler-label-square-dot > div:last-child {\n margin-left: 16px;\n font-family: \"Open Sans\", sans-serif;\n font-size: 14px;\n font-weight: 400;\n color: #101010; }\n\n.igv-multi-locus-ruler-label:hover {\n cursor: pointer; }\n\n.igv-ruler-sweeper {\n display: none;\n pointer-events: none;\n position: absolute;\n top: 0;\n left: 0;\n width: 0;\n height: 100%;\n z-index: 99999;\n background-color: rgba(68, 134, 247, 0.25); }\n\n.igv-ruler-tooltip {\n pointer-events: none;\n z-index: 128;\n position: absolute;\n top: 0;\n left: 0;\n width: 1px;\n height: 32px;\n background-color: transparent;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: center; }\n .igv-ruler-tooltip > div {\n pointer-events: none;\n width: 128px;\n height: auto;\n padding: 1px;\n color: #373737;\n font-size: 10px;\n font-family: \"Open Sans\", sans-serif;\n font-weight: 400;\n background-color: white;\n border-style: solid;\n border-width: thin;\n border-color: #373737; }\n\n.igv-track-label {\n position: absolute;\n left: 8px;\n top: 8px;\n width: auto;\n height: auto;\n max-width: 200px;\n padding-left: 4px;\n padding-right: 4px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n font-family: \"Open Sans\", sans-serif;\n font-size: small;\n font-weight: 400;\n text-align: center;\n user-select: none;\n -moz-user-select: none;\n -webkit-user-select: none;\n border-color: #444;\n border-radius: 2px;\n border-style: solid;\n border-width: thin;\n background-color: white;\n z-index: 128;\n cursor: pointer; }\n\n.igv-track-label:hover,\n.igv-track-label:focus,\n.igv-track-label:active {\n background-color: #e8e8e8; }\n\n.igv-track-label-popup-shim {\n padding-left: 8px;\n padding-right: 8px;\n padding-top: 4px; }\n\n.igv-center-line {\n display: none;\n pointer-events: none;\n position: absolute;\n top: 0;\n bottom: 0;\n transform: translateX(-50%);\n z-index: 8;\n user-select: none;\n -moz-user-select: none;\n -webkit-user-select: none;\n border-left-style: dashed;\n border-left-width: thin;\n border-right-style: dashed;\n border-right-width: thin; }\n\n.igv-center-line-wide {\n background-color: rgba(0, 0, 0, 0);\n border-left-color: rgba(127, 127, 127, 0.51);\n border-right-color: rgba(127, 127, 127, 0.51); }\n\n.igv-center-line-thin {\n background-color: rgba(0, 0, 0, 0);\n border-left-color: rgba(127, 127, 127, 0.51);\n border-right-color: rgba(0, 0, 0, 0); }\n\n.igv-cursor-guide-horizontal {\n display: none;\n pointer-events: none;\n user-select: none;\n -moz-user-select: none;\n -webkit-user-select: none;\n position: absolute;\n left: 0;\n right: 0;\n top: 50%;\n height: 1px;\n z-index: 1;\n margin-left: 50px;\n margin-right: 54px;\n border-top-style: dotted;\n border-top-width: thin;\n border-top-color: rgba(127, 127, 127, 0.76); }\n\n.igv-cursor-guide-vertical {\n pointer-events: none;\n user-select: none;\n -moz-user-select: none;\n -webkit-user-select: none;\n position: absolute;\n top: 0;\n bottom: 0;\n left: 50%;\n width: 1px;\n z-index: 1;\n border-left-style: dotted;\n border-left-width: thin;\n border-left-color: rgba(127, 127, 127, 0.76);\n display: none; }\n\n.igv-user-feedback {\n position: fixed;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 512px;\n height: 360px;\n z-index: 2048;\n background-color: white;\n border-color: #a2a2a2;\n border-style: solid;\n border-width: thin;\n font-family: \"Open Sans\", sans-serif;\n font-size: medium;\n font-weight: 400;\n color: #444;\n display: flex;\n flex-direction: column;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: center; }\n .igv-user-feedback div:first-child {\n position: relative;\n height: 24px;\n width: 100%;\n background-color: white;\n border-bottom-color: #a2a2a2;\n border-bottom-style: solid;\n border-bottom-width: thin; }\n .igv-user-feedback div:first-child div {\n position: absolute;\n top: 2px;\n width: 16px;\n height: 16px;\n background-color: transparent; }\n .igv-user-feedback div:first-child div:first-child {\n left: 8px; }\n .igv-user-feedback div:first-child div:last-child {\n cursor: pointer;\n right: 8px; }\n .igv-user-feedback div:last-child {\n width: 100%;\n height: calc(100% - 24px);\n border-width: 0; }\n .igv-user-feedback div:last-child div {\n width: auto;\n height: auto;\n margin: 8px; }\n\n.igv-generic-dialog-container {\n position: absolute;\n top: 0;\n left: 0;\n width: 300px;\n height: 200px;\n border-color: #7F7F7F;\n border-radius: 4px;\n border-style: solid;\n border-width: thin;\n font-family: \"Open Sans\", sans-serif;\n font-size: medium;\n font-weight: 400;\n z-index: 2048;\n background-color: white;\n display: flex;\n flex-flow: column;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: center; }\n .igv-generic-dialog-container .igv-generic-dialog-header {\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: flex-end;\n align-items: center;\n width: 100%;\n height: 24px;\n cursor: move;\n border-top-left-radius: 4px;\n border-top-right-radius: 4px;\n border-bottom-color: #7F7F7F;\n border-bottom-style: solid;\n border-bottom-width: thin;\n background-color: #eee; }\n .igv-generic-dialog-container .igv-generic-dialog-header div {\n margin-right: 4px;\n margin-bottom: 2px;\n height: 12px;\n width: 12px;\n color: #7F7F7F; }\n .igv-generic-dialog-container .igv-generic-dialog-header div:hover {\n cursor: pointer;\n color: #444; }\n .igv-generic-dialog-container .igv-generic-dialog-one-liner {\n color: #373737;\n width: 95%;\n height: 24px;\n line-height: 24px;\n text-align: left;\n margin-top: 8px;\n padding-left: 8px;\n overflow-wrap: break-word;\n background-color: white; }\n .igv-generic-dialog-container .igv-generic-dialog-label-input {\n margin-top: 8px;\n width: 95%;\n height: 24px;\n color: #373737;\n line-height: 24px;\n padding-left: 8px;\n background-color: white;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: center; }\n .igv-generic-dialog-container .igv-generic-dialog-label-input div {\n width: 30%;\n height: 100%;\n font-size: 16px;\n text-align: right;\n padding-right: 8px;\n background-color: white; }\n .igv-generic-dialog-container .igv-generic-dialog-label-input input {\n display: block;\n height: 100%;\n width: 100%;\n padding-left: 4px;\n font-family: \"Open Sans\", sans-serif;\n font-weight: 400;\n color: #373737;\n text-align: left;\n outline: none;\n border-style: solid;\n border-width: thin;\n border-color: #7F7F7F;\n background-color: white; }\n .igv-generic-dialog-container .igv-generic-dialog-label-input input {\n width: 50%;\n font-size: 16px; }\n .igv-generic-dialog-container .igv-generic-dialog-input {\n margin-top: 8px;\n width: calc(100% - 16px);\n height: 24px;\n color: #373737;\n line-height: 24px;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: space-around;\n align-items: center; }\n .igv-generic-dialog-container .igv-generic-dialog-input input {\n display: block;\n height: 100%;\n width: 100%;\n padding-left: 4px;\n font-family: \"Open Sans\", sans-serif;\n font-weight: 400;\n color: #373737;\n text-align: left;\n outline: none;\n border-style: solid;\n border-width: thin;\n border-color: #7F7F7F;\n background-color: white; }\n .igv-generic-dialog-container .igv-generic-dialog-input input {\n font-size: 16px; }\n .igv-generic-dialog-container .igv-generic-dialog-ok-cancel {\n width: 100%;\n height: 28px;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: space-around;\n align-items: center; }\n .igv-generic-dialog-container .igv-generic-dialog-ok-cancel div {\n margin-top: 32px;\n color: white;\n font-family: \"Open Sans\", sans-serif;\n font-size: 14px;\n font-weight: 400;\n width: 75px;\n height: 28px;\n line-height: 28px;\n text-align: center;\n border-color: transparent;\n border-style: solid;\n border-width: thin;\n border-radius: 2px; }\n .igv-generic-dialog-container .igv-generic-dialog-ok-cancel div:first-child {\n margin-left: 32px;\n margin-right: 0;\n background-color: #5ea4e0; }\n .igv-generic-dialog-container .igv-generic-dialog-ok-cancel div:last-child {\n margin-left: 0;\n margin-right: 32px;\n background-color: #c4c4c4; }\n .igv-generic-dialog-container .igv-generic-dialog-ok-cancel div:first-child:hover {\n cursor: pointer;\n background-color: #3b5c7f; }\n .igv-generic-dialog-container .igv-generic-dialog-ok-cancel div:last-child:hover {\n cursor: pointer;\n background-color: #7f7f7f; }\n .igv-generic-dialog-container .igv-generic-dialog-ok {\n width: 100%;\n height: 36px;\n margin-top: 32px;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: space-around;\n align-items: center; }\n .igv-generic-dialog-container .igv-generic-dialog-ok div {\n width: 98px;\n height: 36px;\n line-height: 36px;\n text-align: center;\n color: white;\n font-family: \"Open Sans\", sans-serif;\n font-size: medium;\n font-weight: 400;\n border-color: white;\n border-style: solid;\n border-width: thin;\n border-radius: 4px;\n background-color: #2B81AF; }\n .igv-generic-dialog-container .igv-generic-dialog-ok div:hover {\n cursor: pointer;\n background-color: #25597f; }\n\n.igv-generic-container {\n position: absolute;\n top: 0;\n left: 0;\n z-index: 2048;\n background-color: white;\n cursor: pointer;\n display: flex;\n flex-direction: row;\n flex-wrap: wrap;\n justify-content: flex-start;\n align-items: center; }\n .igv-generic-container div:first-child {\n cursor: move;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: flex-end;\n align-items: center;\n height: 24px;\n width: 100%;\n background-color: #dddddd; }\n .igv-generic-container div:first-child i {\n display: block;\n color: #5f5f5f;\n cursor: pointer;\n width: 14px;\n height: 14px;\n margin-right: 8px;\n margin-bottom: 4px; }\n\n.igv-menu-popup {\n position: absolute;\n top: 0;\n left: 0;\n width: max-content;\n z-index: 4096;\n cursor: pointer;\n font-family: \"Open Sans\", sans-serif;\n font-size: small;\n font-weight: 400;\n color: #4b4b4b;\n background: white;\n border-radius: 4px;\n border-color: #7F7F7F;\n border-style: solid;\n border-width: thin;\n display: flex;\n flex-flow: column;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: flex-end;\n text-align: left; }\n .igv-menu-popup > div:not(:first-child) {\n width: 100%; }\n .igv-menu-popup > div:not(:first-child) > div {\n background: white; }\n .igv-menu-popup > div:not(:first-child) > div.context-menu {\n padding-left: 4px;\n padding-right: 4px; }\n .igv-menu-popup > div:not(:first-child) > div:last-child {\n border-bottom-left-radius: 4px;\n border-bottom-right-radius: 4px;\n border-bottom-color: transparent;\n border-bottom-style: solid;\n border-bottom-width: thin; }\n .igv-menu-popup > div:not(:first-child) > div:hover {\n background: #efefef; }\n\n.igv-menu-popup-shim {\n padding-left: 8px;\n padding-right: 8px;\n padding-bottom: 1px;\n padding-top: 1px; }\n\n.igv-menu-popup-header {\n position: relative;\n width: 100%;\n height: 24px;\n cursor: move;\n border-top-color: transparent;\n border-top-left-radius: 4px;\n border-top-right-radius: 4px;\n border-bottom-color: #7F7F7F;\n border-bottom-style: solid;\n border-bottom-width: thin;\n background-color: #eee;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: flex-end;\n align-items: center; }\n .igv-menu-popup-header div {\n margin-right: 4px;\n height: 12px;\n width: 12px;\n color: #7F7F7F; }\n .igv-menu-popup-header div:hover {\n cursor: pointer;\n color: #444; }\n\n.igv-menu-popup-check-container {\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: center;\n width: 100%;\n height: 20px;\n margin-right: 4px;\n background-color: transparent; }\n .igv-menu-popup-check-container div {\n padding-top: 2px;\n padding-left: 8px; }\n .igv-menu-popup-check-container div:first-child {\n position: relative;\n width: 12px;\n height: 12px; }\n .igv-menu-popup-check-container div:first-child svg {\n position: absolute;\n width: 12px;\n height: 12px; }\n\n.igv-user-feedback {\n position: fixed;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 512px;\n height: 360px;\n z-index: 2048;\n background-color: white;\n border-color: #a2a2a2;\n border-style: solid;\n border-width: thin;\n font-family: \"Open Sans\", sans-serif;\n font-size: medium;\n font-weight: 400;\n color: #444;\n display: flex;\n flex-direction: column;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: center; }\n .igv-user-feedback div:first-child {\n position: relative;\n height: 24px;\n width: 100%;\n background-color: white;\n border-bottom-color: #a2a2a2;\n border-bottom-style: solid;\n border-bottom-width: thin; }\n .igv-user-feedback div:first-child div {\n position: absolute;\n top: 2px;\n width: 16px;\n height: 16px;\n background-color: transparent; }\n .igv-user-feedback div:first-child div:first-child {\n left: 8px; }\n .igv-user-feedback div:first-child div:last-child {\n cursor: pointer;\n right: 8px; }\n .igv-user-feedback div:last-child {\n width: 100%;\n height: calc(100% - 24px);\n border-width: 0; }\n .igv-user-feedback div:last-child div {\n width: auto;\n height: auto;\n margin: 8px; }\n\n.igv-loading-spinner-container {\n z-index: 1024;\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 32px;\n height: 32px;\n display: flex;\n flex-direction: row;\n flex-wrap: nowrap;\n justify-content: center;\n align-items: center; }\n .igv-loading-spinner-container > div {\n box-sizing: border-box;\n width: 100%;\n height: 100%;\n border-radius: 50%;\n border: 4px solid rgba(128, 128, 128, 0.5);\n border-top-color: white;\n animation: spin 1s ease-in-out infinite;\n -webkit-animation: spin 1s ease-in-out infinite; }\n\n@keyframes spin {\n to {\n -webkit-transform: rotate(360deg);\n transform: rotate(360deg); } }\n@-webkit-keyframes spin {\n to {\n -webkit-transform: rotate(360deg);\n transform: rotate(360deg); } }\n.igv-container {\n position: relative;\n display: flex;\n flex-direction: column;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: flex-start;\n padding-top: 4px;\n user-select: none;\n -webkit-user-select: none;\n -ms-user-select: none; }\n\n.igv-viewport {\n position: relative;\n margin-top: 5px;\n overflow-x: hidden;\n overflow-y: hidden; }\n\n.igv-viewport-content {\n position: relative;\n width: 100%; }\n .igv-viewport-content > canvas {\n position: relative;\n display: block; }\n\n.igv-column-container {\n position: relative;\n display: flex;\n flex-direction: row;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: stretch;\n width: 100%; }\n\n.igv-column-shim {\n width: 1px;\n margin-left: 2px;\n margin-right: 2px;\n background-color: #545453; }\n\n.igv-column {\n position: relative;\n display: flex;\n flex-direction: column;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: flex-start;\n box-sizing: border-box;\n height: 100%; }\n\n.igv-axis-column {\n display: flex;\n flex-direction: column;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: flex-start;\n box-sizing: border-box;\n height: 100%;\n width: 50px; }\n .igv-axis-column > div {\n margin-top: 5px;\n width: 100%; }\n\n.igv-sample-name-column {\n display: flex;\n flex-direction: column;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: flex-start;\n box-sizing: border-box;\n height: 100%; }\n\n.igv-scrollbar-column {\n display: flex;\n flex-direction: column;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: flex-start;\n box-sizing: border-box;\n height: 100%;\n width: 14px; }\n .igv-scrollbar-column > div {\n position: relative;\n margin-top: 5px;\n width: 14px; }\n .igv-scrollbar-column > div > div {\n cursor: pointer;\n position: absolute;\n top: 0;\n left: 2px;\n width: 8px;\n border-width: 1px;\n border-style: solid;\n border-color: #c4c4c4;\n border-top-left-radius: 4px;\n border-top-right-radius: 4px;\n border-bottom-left-radius: 4px;\n border-bottom-right-radius: 4px; }\n .igv-scrollbar-column > div > div:hover {\n background-color: #c4c4c4; }\n\n.igv-track-drag-column {\n display: flex;\n flex-direction: column;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: flex-start;\n box-sizing: border-box;\n height: 100%;\n width: 12px;\n background-color: white; }\n .igv-track-drag-column > .igv-track-drag-handle {\n z-index: 512;\n position: relative;\n cursor: pointer;\n margin-top: 5px;\n width: 100%;\n border-style: solid;\n border-width: 0;\n border-top-right-radius: 6px;\n border-bottom-right-radius: 6px;\n background-color: #c4c4c4; }\n .igv-track-drag-column .igv-track-drag-handle-hover {\n background-color: #787878; }\n .igv-track-drag-column > .igv-track-drag-shim {\n position: relative;\n margin-top: 5px;\n width: 100%;\n border-style: solid;\n border-width: 0; }\n\n.igv-gear-menu-column {\n display: flex;\n flex-direction: column;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: flex-start;\n box-sizing: border-box;\n height: 100%;\n width: 28px; }\n .igv-gear-menu-column > div {\n display: flex;\n flex-direction: column;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: center;\n margin-top: 5px;\n width: 100%;\n background: white; }\n .igv-gear-menu-column > div > div {\n position: relative;\n margin-top: 4px;\n width: 16px;\n height: 16px;\n color: #7F7F7F; }\n .igv-gear-menu-column > div > div:hover {\n cursor: pointer;\n color: #444; }\n\n/*# sourceMappingURL=dom.css.map */\n';
67465
68187
  var style = document.createElement('style');
67466
68188
  style.setAttribute('type', 'text/css');
67467
68189
  style.innerHTML = css;