igv 3.0.7 → 3.0.9

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.esm.js CHANGED
@@ -18593,9 +18593,9 @@ function rgbStringHeatMapLerp(_a, _b, interpolant) {
18593
18593
 
18594
18594
  }
18595
18595
 
18596
- const colorPickerTrackTypeSet = new Set(['bedtype', 'alignment', 'annotation', 'variant', 'wig', 'interact']);
18596
+ const colorPickerTrackTypeSet = new Set(['bedtype', 'alignment', 'annotation', 'variant', 'wig', 'interact', 'shoebox']);
18597
18597
 
18598
- const vizWindowTypes = new Set(['alignment', 'annotation', 'variant', 'eqtl', 'qtl', 'snp', 'shoebox']);
18598
+ const vizWindowTypes = new Set(['alignment', 'annotation', 'variant', 'eqtl', 'qtl', 'snp', 'shoebox', 'wig']);
18599
18599
 
18600
18600
  const multiTrackSelectExclusionTypes = new Set(['sequence', 'ruler', 'ideogram']);
18601
18601
 
@@ -18672,7 +18672,7 @@ class MenuUtils {
18672
18672
 
18673
18673
  if (isVisibilityWindowType(trackView)) {
18674
18674
  list.push('<hr/>');
18675
- list.push(visibilityWindowMenuItem());
18675
+ list.push(visibilityWindowMenuItem(trackView.track.type));
18676
18676
  }
18677
18677
 
18678
18678
  return list
@@ -18755,7 +18755,7 @@ function groupAutoScaleMenuItem() {
18755
18755
  }
18756
18756
 
18757
18757
 
18758
- function visibilityWindowMenuItem() {
18758
+ function visibilityWindowMenuItem(trackType) {
18759
18759
 
18760
18760
  const object = $$1('<div>');
18761
18761
  object.text('Set visibility window');
@@ -18773,9 +18773,12 @@ function visibilityWindowMenuItem() {
18773
18773
  this.trackView.updateViews();
18774
18774
  };
18775
18775
 
18776
+ const label = 'wig' === trackType ?
18777
+ 'Visibility window (bp). Enter 0 for whole chromosome, -1 for whole genome.' :
18778
+ 'Visibility window (bp). Enter 0 for whole chromosome.';
18776
18779
  const config =
18777
18780
  {
18778
- label: 'Visibility Window',
18781
+ label,
18779
18782
  value: this.visibilityWindow,
18780
18783
  callback
18781
18784
  };
@@ -20933,125 +20936,6 @@ function createDOMPurify() {
20933
20936
  }
20934
20937
  var purify = createDOMPurify();
20935
20938
 
20936
- class SliderDialog {
20937
-
20938
- constructor(parent) {
20939
-
20940
- this.parent = parent;
20941
-
20942
- // dialog container
20943
- this.container = div({class: 'igv-ui-generic-dialog-container'});
20944
- parent.appendChild(this.container);
20945
-
20946
- // dialog header
20947
- const header = div({class: 'igv-ui-generic-dialog-header'});
20948
- this.container.appendChild(header);
20949
-
20950
- // dialog label
20951
- this.label = div({class: 'igv-ui-generic-dialog-one-liner'});
20952
- this.container.appendChild(this.label);
20953
- this.label.text = 'Unlabeled';
20954
-
20955
- // input container
20956
- this.input_container = div({class: 'igv-ui-generic-dialog-input'});
20957
- this.container.appendChild(this.input_container);
20958
-
20959
- // input element
20960
- let html = `<input type="range" id="igv-slider-dialog-input" name="igv-slider-dialog-input" />`;
20961
- this._input = document.createRange().createContextualFragment(html).firstChild;
20962
- this.input_container.appendChild(this._input);
20963
-
20964
- // output element
20965
- html = `<output id="igv-slider-dialog-output" name="igv-slider-dialog-output" for="igv-slider-dialog-input"></output>`;
20966
- this._output = document.createRange().createContextualFragment(html).firstChild;
20967
- this.input_container.appendChild(this._output);
20968
-
20969
-
20970
- // ok | cancel
20971
- const buttons = div({class: 'igv-ui-generic-dialog-ok-cancel'});
20972
- this.container.appendChild(buttons);
20973
-
20974
- // ok
20975
- this.ok = div();
20976
- buttons.appendChild(this.ok);
20977
- this.ok.textContent = 'OK';
20978
-
20979
- // cancel
20980
- this.cancel = div();
20981
- buttons.appendChild(this.cancel);
20982
- this.cancel.textContent = 'Cancel';
20983
-
20984
- hide(this.container);
20985
-
20986
- this._input.addEventListener('input', () => {
20987
- const number = parseFloat(this._input.value)/this._scaleFactor;
20988
- this.callback(number);
20989
- this._output.value = `${number.toFixed(2)}`;
20990
- }, false);
20991
-
20992
- this.ok.addEventListener('click', () => {
20993
- if (typeof this.callback === 'function') {
20994
- const number = parseFloat(this._input.value)/this._scaleFactor;
20995
- this.callback(number);
20996
- this.callback = undefined;
20997
- }
20998
- this._input.value = undefined;
20999
- hide(this.container);
21000
- });
21001
-
21002
- const cancel = () => {
21003
- this._input.value = undefined;
21004
- hide(this.container);
21005
- };
21006
-
21007
- this.cancel.addEventListener('click', cancel);
21008
-
21009
- attachDialogCloseHandlerWithParent(header, cancel);
21010
- makeDraggable(this.container, header);
21011
-
21012
- }
21013
-
21014
- get value() {
21015
- return purify.sanitize(this._input.value)
21016
- }
21017
-
21018
- present(options, e) {
21019
-
21020
- this.label.textContent = options.label;
21021
-
21022
- this._scaleFactor = options.scaleFactor;
21023
- const [ minS, maxS, valueS ] = [ options.min, options.max, options.value ].map(number => (Math.floor(this._scaleFactor * number)).toString());
21024
-
21025
- this._input.min = minS;
21026
- this._input.max = maxS;
21027
- this._input.value = valueS;
21028
-
21029
- const numer = parseFloat(valueS);
21030
- const denom = this._scaleFactor;
21031
- const number = numer/denom;
21032
- this._output.value = `${number.toFixed(2)}`;
21033
-
21034
- this.callback = options.callback || options.click;
21035
-
21036
- show(this.container);
21037
- this.clampLocation(e.clientX, e.clientY);
21038
-
21039
- }
21040
-
21041
- clampLocation(clientX, clientY) {
21042
-
21043
- const {width: w, height: h} = this.container.getBoundingClientRect();
21044
- const wh = window.innerHeight;
21045
- const ww = window.innerWidth;
21046
-
21047
- const y = Math.min(wh - h, clientY);
21048
- const x = Math.min(ww - w, clientX);
21049
- this.container.style.left = `${x}px`;
21050
- this.container.style.top = `${y}px`;
21051
-
21052
- }
21053
- }
21054
-
21055
20939
  class InputDialog {
21056
20940
 
21057
20941
  constructor(parent) {
@@ -24505,6 +24389,29 @@ function decodeSNP(tokens, header) {
24505
24389
 
24506
24390
  }
24507
24391
 
24392
+ function decodeShoebox(tokens, header, maxColumnCount = Number.MAX_SAFE_INTEGER) {
24393
+
24394
+ if (tokens.length < 4) return undefined
24395
+
24396
+ const chr = tokens[0];
24397
+ const start = parseInt(tokens[1]);
24398
+ const end = tokens.length > 2 ? parseInt(tokens[2]) : start + 1;
24399
+ if (isNaN(start) || isNaN(end)) {
24400
+ return new DecodeError(`Unparsable bed record.`)
24401
+ }
24402
+ const feature = new UCSCBedFeature({chr: chr, start: start, end: end, score: 1000});
24403
+
24404
+ const values = [];
24405
+ for(let i = 3; i< tokens.length; i++) {
24406
+ values.push(Number.parseInt(tokens[i]));
24407
+ }
24408
+ feature.values = values;
24409
+
24410
+
24411
+ return feature
24412
+ }
24413
+
24414
+
24508
24415
  class UCSCBedFeature {
24509
24416
 
24510
24417
  constructor(properties) {
@@ -25869,6 +25776,10 @@ class FeatureParser {
25869
25776
  this.decode = decodeGcnv;
25870
25777
  this.delimiter = "\t";
25871
25778
  break
25779
+ case "shoebox":
25780
+ this.decode = decodeShoebox;
25781
+ this.delimiter = "\t";
25782
+ break
25872
25783
  default:
25873
25784
  const customFormat = getFormat(format);
25874
25785
  if (customFormat !== undefined) {
@@ -31955,14 +31866,25 @@ class BWReader {
31955
31866
  this.config = config;
31956
31867
  this.bufferSize = BUFFER_SIZE;
31957
31868
  this.loader = isDataURL(this.path) ?
31958
- new DataBuffer(this.path) : igvxhr;
31869
+ new DataBuffer(decodeDataURI$1(this.path).buffer) :
31870
+ igvxhr;
31959
31871
 
31960
- if (config.searchTrix) {
31961
- this._trix = new Trix(`${config.searchTrix}x`, config.searchTrix);
31872
+ const trixURL = config.trixURL || config.searchTrix;
31873
+ if (trixURL) {
31874
+ this._trix = new Trix(`${trixURL}x`, trixURL);
31962
31875
  }
31963
31876
 
31964
31877
  }
31965
31878
 
31879
+ /**
31880
+ * Preload all the data for this bb file
31881
+ * @returns {Promise<void>}
31882
+ */
31883
+ async preload() {
31884
+ const data = await igvxhr.loadArrayBuffer(this.path);
31885
+ this.loader = new DataBuffer(data);
31886
+ }
31887
+
31966
31888
  async readWGFeatures(bpPerPixel, windowFunction) {
31967
31889
  await this.loadHeader();
31968
31890
  const chrIdx1 = 0;
@@ -31992,7 +31914,7 @@ class BWReader {
31992
31914
  // Select a biwig "zoom level" appropriate for the current resolution.
31993
31915
  const zoomLevelHeaders = await this.getZoomHeaders();
31994
31916
  let zoomLevelHeader = bpPerPixel ? zoomLevelForScale(bpPerPixel, zoomLevelHeaders) : undefined;
31995
- if (zoomLevelHeader) {
31917
+ if (zoomLevelHeader && windowFunction != "none") {
31996
31918
  treeOffset = zoomLevelHeader.indexOffset;
31997
31919
  decodeFunction = decodeZoomData;
31998
31920
  } else {
@@ -32628,8 +32550,8 @@ function decodeZoomData(data, chrIdx1, bpStart, chrIdx2, bpEnd, featureArray, ch
32628
32550
 
32629
32551
  class DataBuffer {
32630
32552
 
32631
- constructor(dataURI) {
32632
- this.data = decodeDataURI$1(dataURI).buffer;
32553
+ constructor(data) {
32554
+ this.data = data;
32633
32555
  }
32634
32556
 
32635
32557
  /**
@@ -32687,7 +32609,7 @@ class BWSource extends BaseFeatureSource {
32687
32609
 
32688
32610
  queryable = true
32689
32611
  #wgValues = {}
32690
- windowFunctions = ["mean", "min", "max"]
32612
+ windowFunctions = ["mean", "min", "max", "none"]
32691
32613
 
32692
32614
  constructor(config, genome) {
32693
32615
  super(genome);
@@ -32842,7 +32764,8 @@ class WigTrack extends TrackBase {
32842
32764
  scaleFactor: undefined,
32843
32765
  overflowColor: `rgb(255, 32, 255)`,
32844
32766
  baselineColor: 'lightGray',
32845
- summarize: true
32767
+ summarize: true,
32768
+ visibilityWindow: undefined
32846
32769
  }
32847
32770
 
32848
32771
  constructor(config, browser) {
@@ -32888,6 +32811,10 @@ class WigTrack extends TrackBase {
32888
32811
  if (header) this.setTrackProperties(header);
32889
32812
  }
32890
32813
 
32814
+ supportsWholeGenome() {
32815
+ return this.visibilityWindow === undefined || this.visibilityWindow < 0
32816
+ }
32817
+
32891
32818
  async getFeatures(chr, start, end, bpPerPixel) {
32892
32819
 
32893
32820
  const windowFunction = this.windowFunction;
@@ -38011,6 +37938,16 @@ class Hub {
38011
37938
  const groupsTxtURL = baseURL + genome.getProperty("groups");
38012
37939
  groups = await loadStanzas(groupsTxtURL);
38013
37940
  }
37941
+
37942
+ // If the genome has a chromSizes file, and it is not too large, set the chromSizesURL property. This will
37943
+ // enable whole genome view and the chromosome pulldown
37944
+ if (genome.hasProperty("chromSizes")) {
37945
+ const chromSizesURL = baseURL + genome.getProperty("chromSizes");
37946
+ const l = await getContentLength(chromSizesURL);
37947
+ if (l !== null && Number.parseInt(l) < 1000000) {
37948
+ genome.setProperty("chromSizesURL", chromSizesURL);
37949
+ }
37950
+ }
38014
37951
  }
38015
37952
 
38016
37953
  // TODO -- categorize extra "user" supplied and other tracks in some distinctive way before including them
@@ -38113,10 +38050,15 @@ isPcr dynablat-01.soe.ucsc.edu 4040 dynamic GCF/000/186/305/GCF_000186305.1
38113
38050
  name: name,
38114
38051
  twoBitURL: this.baseURL + this.genomeStanza.getProperty("twoBitPath"),
38115
38052
  nameSet: "ucsc",
38116
- wholeGenomeView: false,
38117
- showChromosomeWidget: false
38118
38053
  };
38119
38054
 
38055
+ if (this.genomeStanza.hasProperty("chromSizesURL")) {
38056
+ config.chromSizesURL = this.genomeStanza.getProperty("chromSizesURL");
38057
+ } else {
38058
+ config.wholeGenomeView = false;
38059
+ config.showChromosomeWidget = false;
38060
+ }
38061
+
38120
38062
  if (this.genomeStanza.hasProperty("defaultPos")) {
38121
38063
  const hubLocus = this.genomeStanza.getProperty("defaultPos");
38122
38064
  // Strip out coordinates => whole chromosome view
@@ -38317,7 +38259,7 @@ isPcr dynablat-01.soe.ucsc.edu 4040 dynamic GCF/000/186/305/GCF_000186305.1
38317
38259
  config.searchIndex = t.getProperty("searchIndex");
38318
38260
  }
38319
38261
  if (t.hasProperty("searchTrix")) {
38320
- config.searchTrix = this.baseURL + t.getProperty("searchTrix");
38262
+ config.trixURL = this.baseURL + t.getProperty("searchTrix");
38321
38263
  }
38322
38264
 
38323
38265
  if (t.hasProperty("group")) {
@@ -38404,6 +38346,26 @@ class Stanza {
38404
38346
  }
38405
38347
  }
38406
38348
 
38349
+
38350
+ /**
38351
+ * Return the content length of the resource. If the content length cannot be determined return null;
38352
+ * @param url
38353
+ * @returns {Promise<number|string>}
38354
+ */
38355
+ async function getContentLength(url) {
38356
+ try {
38357
+ const response = await fetch(url, {method: 'HEAD'});
38358
+ const headers = response.headers;
38359
+ if (headers.has("content-length")) {
38360
+ return headers.get("content-length")
38361
+ } else {
38362
+ return null
38363
+ }
38364
+ } catch (e) {
38365
+ return null
38366
+ }
38367
+ }
38368
+
38407
38369
  /**
38408
38370
  * Parse a UCSC file
38409
38371
  * @param url
@@ -41952,7 +41914,7 @@ const hideAllMenuPopups = parent => {
41952
41914
 
41953
41915
  class NavbarButton {
41954
41916
 
41955
- constructor(browser, parent, title, buttonLabel, imageSVG, imageHoverSVG, initialButtonState) {
41917
+ constructor(parent, browser, title, buttonLabel, imageSVG, imageHoverSVG, initialButtonState) {
41956
41918
 
41957
41919
  this.browser = browser;
41958
41920
 
@@ -42009,7 +41971,7 @@ class NavbarButton {
42009
41971
  }
42010
41972
 
42011
41973
  configureTextButton(textContent) {
42012
-
41974
+ console.log(`text ${this.title}`);
42013
41975
  this.button.classList.add('igv-navbar-text-button');
42014
41976
 
42015
41977
  const tempDiv = document.createElement('div');
@@ -42024,6 +41986,7 @@ class NavbarButton {
42024
41986
  }
42025
41987
 
42026
41988
  configureIconButton() {
41989
+ console.log(`icon ${this.title}`);
42027
41990
  this.button.classList.add('igv-navbar-icon-button');
42028
41991
  }
42029
41992
 
@@ -42063,11 +42026,6 @@ class NavbarButton {
42063
42026
  this.hide();
42064
42027
  }
42065
42028
  }
42066
-
42067
- static currentNavbarButtonClass(browser) {
42068
- const el = browser.$navigation.get(0).querySelector('.igv-navbar-text-button');
42069
- return el ? 'igv-navbar-text-button' : 'igv-navbar-icon-button'
42070
- }
42071
42029
  }
42072
42030
 
42073
42031
  const overlayTrackImage =
@@ -42276,6 +42234,19 @@ class MergedTrack extends TrackBase {
42276
42234
  return this._autoscale
42277
42235
  }
42278
42236
 
42237
+ set autoscaleGroup(g) {
42238
+ if(this.tracks) {
42239
+ for(let t of this.tracks) t.autoscaleGroup = g;
42240
+ }
42241
+ }
42242
+
42243
+ get autoscaleGroup() {
42244
+ if(this.tracks && this.tracks.length > 0) {
42245
+ const g = this.tracks[0].autoscaleGroup;
42246
+ return (this.tracks.some(t => g !== t.autoscaleGroup)) ? undefined : g
42247
+ }
42248
+ }
42249
+
42279
42250
  /**
42280
42251
  * Set the data range of all constitutive numeric tracks. This method is called from the menu item, i.e. an explicit
42281
42252
  * setting, so it should disable autoscale as well.
@@ -42640,9 +42611,9 @@ const numericTracks = (tracks) => {
42640
42611
  };
42641
42612
 
42642
42613
  class OverlayTrackButton extends NavbarButton {
42643
- constructor(browser, parent) {
42614
+ constructor(parent, browser) {
42644
42615
 
42645
- super(browser, parent, 'Overlay Tracks', buttonLabel, overlayTrackImage, overlayTrackImageHover, false);
42616
+ super(parent, browser, 'Overlay Tracks', buttonLabel, overlayTrackImage, overlayTrackImageHover, false);
42646
42617
 
42647
42618
  this.button.addEventListener('mouseenter', () => this.setState(true));
42648
42619
  this.button.addEventListener('mouseleave', () => this.setState(false));
@@ -42665,15 +42636,15 @@ function trackOverlayClickHandler(e) {
42665
42636
 
42666
42637
  if (true === isOverlayTrackCriteriaMet(this.browser)) {
42667
42638
 
42668
- const tracks = this.browser.getSelectedTrackViews().map(({ track }) => track);
42639
+ const tracks = this.browser.getSelectedTrackViews().map(({track}) => track);
42669
42640
  for (const track of tracks) {
42670
42641
  track.selected = false;
42671
42642
  }
42672
42643
 
42673
- // Flatten any merged tracks. Must do this before there removal
42644
+ // Flatten any merged tracks. Must do this before their removal
42674
42645
  const flattenedTracks = [];
42675
- for(let t of tracks) {
42676
- if("merged" === t.type) {
42646
+ for (let t of tracks) {
42647
+ if ("merged" === t.type) {
42677
42648
  flattenedTracks.push(...t.tracks);
42678
42649
  } else {
42679
42650
  flattenedTracks.push(t);
@@ -42686,17 +42657,20 @@ function trackOverlayClickHandler(e) {
42686
42657
  type: 'merged',
42687
42658
  autoscale: false,
42688
42659
  alpha: 0.5, //fudge * (1.0/tracks.length),
42689
- height: Math.max(...tracks.map(({ height }) => height)),
42690
- order: Math.min(...tracks.map(({ order }) => order)),
42660
+ height: Math.max(...tracks.map(({height}) => height)),
42661
+ order: Math.min(...tracks.map(({order}) => order)),
42691
42662
  };
42692
42663
 
42693
42664
  const mergedTrack = new MergedTrack(config, this.browser, flattenedTracks);
42694
42665
 
42695
42666
  for (const track of tracks) {
42696
- this.browser.removeTrack(track);
42667
+ const idx = this.browser.trackViews.indexOf(track.trackView);
42668
+ this.browser.trackViews.splice(idx, 1);
42669
+ track.trackView.dispose();
42697
42670
  }
42698
42671
 
42699
42672
  this.browser.addTrack(config, mergedTrack);
42673
+ mergedTrack.trackView.updateViews();
42700
42674
 
42701
42675
  }
42702
42676
 
@@ -42708,9 +42682,9 @@ function isOverlayTrackCriteriaMet(browser) {
42708
42682
 
42709
42683
  if (selected && selected.length > 1) {
42710
42684
 
42711
- const criteriaSet = new Set([ 'wig', 'merged' ]);
42685
+ const criteriaSet = new Set(['wig', 'merged']);
42712
42686
 
42713
- const list = selected.filter(({ track }) => criteriaSet.has(track.type));
42687
+ const list = selected.filter(({track}) => criteriaSet.has(track.type));
42714
42688
 
42715
42689
  return list.length > 1
42716
42690
 
@@ -42825,6 +42799,8 @@ class TrackView {
42825
42799
  createAxis(browser, track) {
42826
42800
 
42827
42801
  const axis = div();
42802
+ this.axis = axis;
42803
+
42828
42804
  browser.columnContainer.querySelector('.igv-axis-column').appendChild(axis);
42829
42805
 
42830
42806
  axis.dataset.tracktype = track.type;
@@ -42842,12 +42818,12 @@ class TrackView {
42842
42818
 
42843
42819
  if (false === multiTrackSelectExclusionTypes.has(this.track.type)) {
42844
42820
 
42845
- const trackSelectionContainer = div();
42846
- axis.appendChild(trackSelectionContainer);
42821
+ this.trackSelectionContainer = div();
42822
+ axis.appendChild(this.trackSelectionContainer);
42847
42823
 
42848
42824
  const html = `<input type="checkbox" name="track-select">`;
42849
42825
  const input = document.createRange().createContextualFragment(html).firstChild;
42850
- trackSelectionContainer.appendChild(input);
42826
+ this.trackSelectionContainer.appendChild(input);
42851
42827
  input.checked = this.track.selected || false;
42852
42828
 
42853
42829
  input.addEventListener('change', event => {
@@ -42855,10 +42831,10 @@ class TrackView {
42855
42831
  event.stopPropagation();
42856
42832
  this.track.selected = event.target.checked;
42857
42833
  this.setDragHandleSelectionState(event.target.checked);
42858
- this.browser.overlayTrackButton.setVisibility( isOverlayTrackCriteriaMet(this.browser) );
42834
+ this.browser.overlayTrackButton.setVisibility(isOverlayTrackCriteriaMet(this.browser));
42859
42835
  });
42860
42836
 
42861
- this.setTrackSelectionState(axis, false);
42837
+ this.enableTrackSelection(false);
42862
42838
 
42863
42839
  }
42864
42840
 
@@ -43668,13 +43644,19 @@ class TrackView {
43668
43644
  return Math.max(...this.viewports.map(viewport => viewport.getContentHeight()))
43669
43645
  }
43670
43646
 
43671
- setTrackSelectionState(axis, doEnableMultiSelection) {
43647
+ enableTrackSelection(doEnableMultiSelection) {
43648
+
43649
+ const container = this.trackSelectionContainer;
43672
43650
 
43673
- const container = axis.querySelector('div');
43651
+ if (!container || multiTrackSelectExclusionTypes.has(this.track.type)) {
43652
+ return
43653
+ }
43674
43654
 
43675
43655
  if (false !== doEnableMultiSelection) {
43676
43656
  container.style.display = 'grid';
43677
43657
  } else {
43658
+ // If disabling selection set track selection state to false
43659
+ this.track.selected = false;
43678
43660
 
43679
43661
  const trackSelectInput = container.querySelector('[name=track-select]');
43680
43662
  trackSelectInput.checked = this.track.selected;
@@ -43700,13 +43682,11 @@ class TrackView {
43700
43682
  dragHandle.classList.remove('igv-track-drag-handle-selected-color');
43701
43683
  dragHandle.classList.add('igv-track-drag-handle-color');
43702
43684
  }
43703
-
43704
43685
  }
43705
43686
 
43706
43687
  }
43707
43688
 
43708
43689
 
43709
-
43710
43690
  function renderSVGAxis(context, track, axisCanvas, deltaX, deltaY) {
43711
43691
 
43712
43692
  if (typeof track.paintAxis === 'function') {
@@ -43820,13 +43800,13 @@ class ConstantColorScale {
43820
43800
  *
43821
43801
  */
43822
43802
 
43823
- const defaultColorScaleConfig = {threshold: 2000, r: 0, g: 0, b: 255};
43803
+ const defaultColorScaleConfig$1 = {threshold: 2000, r: 0, g: 0, b: 255};
43824
43804
 
43825
43805
  class HicColorScale {
43826
43806
 
43827
43807
  constructor(scale) {
43828
43808
 
43829
- scale = scale || defaultColorScaleConfig;
43809
+ scale = scale || defaultColorScaleConfig$1;
43830
43810
  this.threshold = scale.threshold;
43831
43811
  this.r = scale.r;
43832
43812
  this.g = scale.g;
@@ -49279,7 +49259,7 @@ const SECONDARY_ALIGNMNET_FLAG = 0x100;
49279
49259
  const READ_FAILS_VENDOR_QUALITY_CHECK_FLAG = 0x200;
49280
49260
  const DUPLICATE_READ_FLAG = 0x400;
49281
49261
  const SUPPLEMENTARY_ALIGNMENT_FLAG = 0x800;
49282
- const ELEMENT_SIZE = {
49262
+ const ELEMENT_SIZE$1 = {
49283
49263
  c: 1,
49284
49264
  C: 1,
49285
49265
  s: 2,
@@ -49364,14 +49344,6 @@ class BamAlignment {
49364
49344
  }
49365
49345
 
49366
49346
  tags() {
49367
- if (!this.tagDict) {
49368
- if (this.tagBA) {
49369
- this.tagDict = decodeTags(this.tagBA);
49370
- this.tagBA = undefined;
49371
- } else {
49372
- this.tagDict = {}; // Mark so we don't try again. The record has no tags
49373
- }
49374
- }
49375
49347
  return this.tagDict
49376
49348
  }
49377
49349
 
@@ -49603,7 +49575,7 @@ class BamAlignment {
49603
49575
  }
49604
49576
 
49605
49577
  getBaseModificationSets() {
49606
- this.tags();
49578
+
49607
49579
  if (!this.baseModificationSets && (this.tagDict["MM"] || this.tagDict["Mm"])) {
49608
49580
 
49609
49581
  const mm = this.tagDict["MM"] || this.tagDict["Mm"];
@@ -49727,7 +49699,7 @@ function decodeTags(ba) {
49727
49699
  } else if (type === 'B') {
49728
49700
  //‘cCsSiIf’, corresponding to int8 , uint8 t, int16 t, uint16 t, int32 t, uint32 t and float
49729
49701
  const elementType = String.fromCharCode(ba[p++]);
49730
- let elementSize = ELEMENT_SIZE[elementType];
49702
+ let elementSize = ELEMENT_SIZE$1[elementType];
49731
49703
  if (elementSize === undefined) {
49732
49704
  tags[tag] = `Error: unknown element type '${elementType}'`;
49733
49705
  break
@@ -49882,13 +49854,22 @@ class BamFilter {
49882
49854
  * https://github.com/dasmoth/dalliance/blob/master/js/bam.js
49883
49855
  */
49884
49856
  //=ACMGRSVTWYHKDBN
49857
+ const BAM1_MAGIC_BYTES = new Uint8Array([0x42, 0x41, 0x4d, 0x01]); // BAM\1
49858
+ const BAM1_MAGIC_NUMBER = readInt(BAM1_MAGIC_BYTES, 0);
49859
+
49885
49860
  const SEQ_DECODER = ['=', 'A', 'C', 'M', 'G', 'R', 'S', 'V', 'T', 'W', 'Y', 'H', 'K', 'D', 'B', 'N'];
49886
49861
  const CIGAR_DECODER = ['M', 'I', 'D', 'N', 'S', 'H', 'P', '=', 'X', '?', '?', '?', '?', '?', '?', '?'];
49887
49862
  const READ_STRAND_FLAG$1 = 0x10;
49888
49863
  const MATE_STRAND_FLAG$1 = 0x20;
49889
-
49890
- const BAM1_MAGIC_BYTES = new Uint8Array([0x42, 0x41, 0x4d, 0x01]); // BAM\1
49891
- const BAM1_MAGIC_NUMBER = readInt(BAM1_MAGIC_BYTES, 0);
49864
+ const ELEMENT_SIZE = {
49865
+ c: 1,
49866
+ C: 1,
49867
+ s: 2,
49868
+ S: 2,
49869
+ i: 4,
49870
+ I: 4,
49871
+ f: 4
49872
+ };
49892
49873
 
49893
49874
  const DEFAULT_ALLELE_FREQ_THRESHOLD = 0.2;
49894
49875
  const DEFAULT_SAMPLING_WINDOW_SIZE = 100;
@@ -50137,7 +50118,9 @@ const BamUtils = {
50137
50118
 
50138
50119
  alignment.seq = seq;
50139
50120
  alignment.qual = qualArray;
50140
- alignment.tagBA = new Uint8Array(ba.buffer.slice(p, blockEnd)); // decode these on demand
50121
+
50122
+ const tagBA = new Uint8Array(ba.buffer.slice(p, blockEnd));
50123
+ alignment.tagDict = decodeBamTags(tagBA);
50141
50124
 
50142
50125
  this.setPairOrientation(alignment);
50143
50126
 
@@ -50448,6 +50431,109 @@ function decodeSamTags(tags) {
50448
50431
  return tagDict
50449
50432
  }
50450
50433
 
50434
+ /**
50435
+ * Decode bam tags from the supplied UInt8Array
50436
+ *
50437
+ * A [!-~] Printable character
50438
+ * i [-+]?[0-9]+ Signed integer16
50439
+ * f [-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)? Single-precision floating number
50440
+ * Z [ !-~]* Printable string, including space
50441
+ * H ([0-9A-F][0-9A-F])* Byte array in the Hex format17
50442
+ * B [cCsSiIf](,[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?)* Integer or numeric array
50443
+ *
50444
+ * @param ba A byte array (UInt8Array)
50445
+ * @returns {{}} Tag values
50446
+ */
50447
+ function decodeBamTags(ba) {
50448
+
50449
+ let p = 0;
50450
+ const len = ba.length;
50451
+ const tags = {};
50452
+ const dataView = new DataView(ba.buffer);
50453
+
50454
+ while (p < len) {
50455
+ const tag = String.fromCharCode(ba[p]) + String.fromCharCode(ba[p + 1]);
50456
+ p += 2;
50457
+
50458
+ const type = String.fromCharCode(ba[p++]);
50459
+ let value;
50460
+ if (type === 'A') {
50461
+ value = String.fromCharCode(ba[p]);
50462
+ p++;
50463
+ } else if (type === 'i' || type === 'I') {
50464
+ value = dataView.getInt32(p, true);
50465
+ p += 4;
50466
+ } else if (type === 'c') {
50467
+ value = dataView.getInt8(p, true);
50468
+ p++;
50469
+ } else if (type === 'C') {
50470
+ value = dataView.getUint8(p, true);
50471
+ p++;
50472
+ } else if (type === 's' || type === 'S') {
50473
+ value = dataView.getInt16(p, true);
50474
+ p += 2;
50475
+ } else if (type === 'f') {
50476
+ value = dataView.getFloat32(p, true);
50477
+ p += 4;
50478
+ } else if (type === 'Z') {
50479
+ value = '';
50480
+ for (; ;) {
50481
+ var cc = ba[p++];
50482
+ if (cc === 0) {
50483
+ break
50484
+ } else {
50485
+ value += String.fromCharCode(cc);
50486
+ }
50487
+ }
50488
+ } else if (type === 'B') {
50489
+ //‘cCsSiIf’, corresponding to int8 , uint8 t, int16 t, uint16 t, int32 t, uint32 t and float
50490
+ const elementType = String.fromCharCode(ba[p++]);
50491
+ let elementSize = ELEMENT_SIZE[elementType];
50492
+ if (elementSize === undefined) {
50493
+ tags[tag] = `Error: unknown element type '${elementType}'`;
50494
+ break
50495
+ }
50496
+ const numElements = dataView.getInt32(p, true);
50497
+ p += 4;
50498
+ const pEnd = p + numElements * elementSize;
50499
+ value = [];
50500
+
50501
+ while (p < pEnd) {
50502
+ switch (elementType) {
50503
+ case 'c':
50504
+ value.push(dataView.getInt8(p, true));
50505
+ break
50506
+ case 'C':
50507
+ value.push(dataView.getUint8(p, true));
50508
+ break
50509
+ case 's':
50510
+ value.push(dataView.getInt16(p, true));
50511
+ break
50512
+ case 'S':
50513
+ value.push(dataView.getUint16(p, true));
50514
+ break
50515
+ case 'i':
50516
+ value.push(dataView.getInt32(p, true));
50517
+ break
50518
+ case 'I':
50519
+ value.push(dataView.getUint32(p, true));
50520
+ break
50521
+ case 'f':
50522
+ value.push(dataView.getFloat32(p, true));
50523
+ }
50524
+ p += elementSize;
50525
+ }
50526
+ } else {
50527
+ //'Unknown type ' + type;
50528
+ value = 'Error unknown type: ' + type;
50529
+ tags[tag] = value;
50530
+ break
50531
+ }
50532
+ tags[tag] = value;
50533
+ }
50534
+ return tags
50535
+ }
50536
+
50451
50537
  /*
50452
50538
  * The MIT License (MIT)
50453
50539
  *
@@ -53923,6 +54009,10 @@ async function inferFileFormatFromContents(config) {
53923
54009
  if (firstLine.startsWith("##gff-version")) {
53924
54010
  return "gff"
53925
54011
  }
54012
+ if(firstLine.startsWith("##fileformat=")) {
54013
+ return firstLine.substring(13).toLowerCase(); // Non standard extension of VCF convention
54014
+ }
54015
+
53926
54016
 
53927
54017
  // QTL test must preceed GWAS test as GWAS files will also pass the QTL test
53928
54018
  if (QTLParser.isQTL(firstLine)) {
@@ -57159,10 +57249,6 @@ class AlignmentTrack extends TrackBase {
57159
57249
 
57160
57250
  function clickHandler() {
57161
57251
  this.alignmentTrack.colorBy = menuItem.key;
57162
- if ('strand' !== this.alignmentTrack.groupBy) {
57163
- this.alignmentTrack.groupBy = 'strand';
57164
- this.alignmentTrack.repackAlignments();
57165
- }
57166
57252
  this.trackView.repaintViews();
57167
57253
  }
57168
57254
 
@@ -67751,6 +67837,7 @@ async function searchFeatures(browser, name) {
67751
67837
  const searchConfig = browser.searchConfig || DEFAULT_SEARCH_CONFIG;
67752
67838
  let feature;
67753
67839
 
67840
+ name = name.toUpperCase();
67754
67841
  const searchableTracks = browser.tracks.filter(t => t.searchable);
67755
67842
  for (let track of searchableTracks) {
67756
67843
  const feature = await track.search(name);
@@ -70089,6 +70176,343 @@ class SpliceJunctionTrack extends TrackBase {
70089
70176
  }
70090
70177
  }
70091
70178
 
70179
+ /*
70180
+ * The MIT License (MIT)
70181
+ *
70182
+ * Copyright (c) 2016-2017 The Regents of the University of California
70183
+ *
70184
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
70185
+ * associated documentation files (the "Software"), to deal in the Software without restriction, including
70186
+ * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
70187
+ * copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the
70188
+ * following conditions:
70189
+ *
70190
+ * The above copyright notice and this permission notice shall be included in all copies or substantial
70191
+ * portions of the Software.
70192
+ *
70193
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
70194
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
70195
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
70196
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
70197
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
70198
+ * THE SOFTWARE.
70199
+ *
70200
+ */
70201
+
70202
+ const defaultColorScaleConfig = {min: 0, max: 3000, color: "rgb(0,0,255)"};
70203
+
70204
+ class ShoeboxColorScale {
70205
+
70206
+ constructor(scale) {
70207
+
70208
+ scale = scale || defaultColorScaleConfig;
70209
+ this.max = scale.max;
70210
+ this.min = scale.min || 0;
70211
+ this.cache = [];
70212
+ this.nbins = 1000;
70213
+ this.binsize = (this.max - this.min) / this.nbins;
70214
+ this.updateColor(scale.color || "rgb(0,0,255)");
70215
+
70216
+ }
70217
+
70218
+ updateColor(color) {
70219
+ const comps = color.substring(4).replace(")", "").split(",");
70220
+ if (comps.length === 3) {
70221
+ this.r = Number.parseInt(comps[0].trim());
70222
+ this.g = Number.parseInt(comps[1].trim());
70223
+ this.b = Number.parseInt(comps[2].trim());
70224
+ }
70225
+ this.cache = [];
70226
+ }
70227
+
70228
+ setMinMax(min, max) {
70229
+ this.min = min;
70230
+ this.max = max;
70231
+ this.cache = [];
70232
+ this.binsize = (this.max - this.min) / this.nbins;
70233
+ }
70234
+
70235
+ getColor(value) {
70236
+ const low = 0;
70237
+ if (value < this.min) return "white"
70238
+
70239
+ const bin = Math.floor((Math.min(this.max, value) - this.min) / this.binsize);
70240
+ if (undefined === this.cache[bin]) {
70241
+ const alpha = (IGVMath.clamp(value, low, this.max) - low) / (this.max - low);
70242
+ this.cache[bin] = `rgba(${this.r},${this.g},${this.b}, ${alpha})`;
70243
+ }
70244
+ return this.cache[bin]
70245
+ }
70246
+
70247
+ /**
70248
+ *
70249
+ * @returns {{min: (*|number), color: string, max}}
70250
+ */
70251
+ toJson() {
70252
+ return {
70253
+ min: this.min,
70254
+ max: this.max,
70255
+ color: `rgb(${this.r},${this.g},${this.b})`
70256
+ }
70257
+ }
70258
+
70259
+ // For short-term backward compatibility
70260
+ static parse(str) {
70261
+
70262
+ const tokens = str.split(",");
70263
+
70264
+ const cs = {
70265
+ min: Number.parseFloat(tokens[0]),
70266
+ max: Number.parseFloat(tokens[1]),
70267
+ color: `${tokens[2]},${tokens[3]},${tokens[4]}`
70268
+ };
70269
+ return new ShoeboxColorScale(cs)
70270
+ }
70271
+
70272
+ }
70273
+
70274
+ class ShoeboxTrack extends TrackBase {
70275
+
70276
+ static defaults = {
70277
+ height: 300,
70278
+ rowHeight: 3,
70279
+ max: 3000,
70280
+ visibilityWindow: 10000
70281
+ }
70282
+
70283
+ constructor(config, browser) {
70284
+ super(config, browser);
70285
+ }
70286
+
70287
+ init(config) {
70288
+ super.init(config);
70289
+
70290
+ this.type = "shoebox";
70291
+ this.height = config.height || 300;
70292
+ this.rowHeight = config.rowHeight || 3;
70293
+ this.max = config.max || 3000;
70294
+
70295
+ // Hardcoded -- todo get from track line
70296
+ this.sampleKeys = [];
70297
+ for (let i = 1; i <= 100; i++) {
70298
+ this.sampleKeys.push(i);
70299
+ }
70300
+
70301
+ // Create featureSource
70302
+ const configCopy = Object.assign({}, this.config);
70303
+ configCopy.format = 'shoebox'; // bit of a hack
70304
+ this.featureSource = FeatureSource(configCopy, this.browser.genome);
70305
+ }
70306
+
70307
+ async postInit() {
70308
+ if (typeof this.featureSource.getHeader === "function") {
70309
+ this.header = await this.featureSource.getHeader();
70310
+ if (this.disposed) return // This track was removed during async load
70311
+ }
70312
+ // Set properties from track line
70313
+ if (this.header) {
70314
+ this.setTrackProperties(this.header);
70315
+ }
70316
+
70317
+ // Must do the following after setting track properties as they can be overriden via a track line
70318
+
70319
+ // Color settings
70320
+ if (this.config.colorScale && this.config.colorScale.max && this.config.colorScale.color) { // Minimal validation
70321
+ this.colorScale = new ShoeboxColorScale(this.config.colorScale);
70322
+
70323
+ } else {
70324
+ const min = this.dataRange.min;
70325
+ const max = this.dataRange.max;
70326
+ this.colorScale = new ShoeboxColorScale({min, max, color: this.color});
70327
+ }
70328
+ }
70329
+
70330
+ get color() {
70331
+ return this._color || "rgb(0,0,255)"
70332
+ }
70333
+
70334
+ set color(color) {
70335
+ this._color = color;
70336
+ if (this.colorScale) {
70337
+ this.colorScale.updateColor(color);
70338
+ }
70339
+ }
70340
+
70341
+ menuItemList() {
70342
+
70343
+ const menuItems = [];
70344
+
70345
+
70346
+ menuItems.push('<hr/>');
70347
+
70348
+ // Data range
70349
+ let object = $$1('<div>');
70350
+ object.text('Set data range');
70351
+
70352
+ function dialogPresentationHandler() {
70353
+
70354
+ if (this.trackView.track.selected) {
70355
+ this.browser.dataRangeDialog.configure(this.trackView.browser.getSelectedTrackViews());
70356
+ } else {
70357
+ this.browser.dataRangeDialog.configure(this.trackView);
70358
+ }
70359
+ this.browser.dataRangeDialog.present($$1(this.browser.columnContainer));
70360
+ }
70361
+
70362
+ menuItems.push({object, dialog: dialogPresentationHandler});
70363
+
70364
+ return menuItems
70365
+ }
70366
+
70367
+ setDataRange({min, max}) {
70368
+ this.dataRange.min = min;
70369
+ this.dataRange.max = max;
70370
+ this.colorScale.min = min;
70371
+ this.colorScale.max = max;
70372
+ this.trackView.repaintViews();
70373
+ }
70374
+
70375
+ hasSamples() {
70376
+ return true // by definition
70377
+ }
70378
+
70379
+ getSamples() {
70380
+ return {
70381
+ names: this.sampleKeys,
70382
+ height: this.rowHeight,
70383
+ yOffset: 0
70384
+ }
70385
+ }
70386
+
70387
+ async getFeatures(chr, start, end, bpPerPixel) {
70388
+ const visibilityWindow = this.visibilityWindow;
70389
+ return this.featureSource.getFeatures({chr, start, end, bpPerPixel, visibilityWindow})
70390
+ }
70391
+
70392
+
70393
+ draw({context, pixelTop, pixelWidth, pixelHeight, features, bpPerPixel, bpStart}) {
70394
+
70395
+
70396
+ IGVGraphics.fillRect(context, 0, pixelTop, pixelWidth, pixelHeight, {'fillStyle': "rgb(255, 255, 255)"});
70397
+
70398
+ if (features && features.length > 0) {
70399
+
70400
+ const rowHeight = this.rowHeight;
70401
+ const pixelBottom = pixelTop + pixelHeight;
70402
+ const bpEnd = bpStart + pixelWidth * bpPerPixel + 1;
70403
+
70404
+ const h = rowHeight;
70405
+
70406
+ for (let f of features) {
70407
+
70408
+ // Test for overlap with in-view region
70409
+ if (f.end < bpStart || f.start > bpEnd) continue
70410
+
70411
+ // Pixel x values
70412
+ const xLeft = Math.round((f.start - bpStart) / bpPerPixel);
70413
+ const xRight = Math.round((f.end - bpStart) / bpPerPixel);
70414
+ const w = Math.max(1, xRight - xLeft);
70415
+
70416
+ // Loop through value array
70417
+ let row = 0;
70418
+
70419
+ for (let i = f.values.length - 1; i >= 0; i--) {
70420
+
70421
+ const v = f.values[i];
70422
+
70423
+ const y = row * rowHeight;
70424
+
70425
+
70426
+ const bottom = y + rowHeight;
70427
+
70428
+ if (bottom < pixelTop || y > pixelBottom) {
70429
+ continue
70430
+ }
70431
+
70432
+ const color = this.colorScale.getColor(v);
70433
+
70434
+ context.fillStyle = color;
70435
+
70436
+ context.fillRect(xLeft, y, w, h);
70437
+
70438
+ row++;
70439
+ }
70440
+ }
70441
+ }
70442
+
70443
+ }
70444
+
70445
+ /**
70446
+ * Optional method to compute pixel height to accomodate the list of features.
70447
+ *
70448
+ * @param features
70449
+ * @returns {number}
70450
+ */
70451
+ computePixelHeight(features) {
70452
+ if (!features || features.length === 0) return 0
70453
+ return features[0].values.length * this.rowHeight
70454
+ }
70455
+
70456
+
70457
+ clickedFeatures(clickState) {
70458
+
70459
+ const allFeatures = super.clickedFeatures(clickState);
70460
+ const y = clickState.y;
70461
+ return allFeatures.filter(function (feature) {
70462
+ const rect = feature.pixelRect;
70463
+ return rect && y >= rect.y && y <= (rect.y + rect.h)
70464
+ })
70465
+
70466
+ }
70467
+
70468
+ hoverText(clickState) {
70469
+ const features = this.clickedFeatures(clickState);
70470
+ if (features && features.length > 0) {
70471
+ return `${features[0].sample}: ${features[0].value}`
70472
+ }
70473
+ }
70474
+
70475
+ popupData(clickState, featureList) {
70476
+
70477
+ if (featureList === undefined) featureList = this.clickedFeatures(clickState);
70478
+
70479
+ const items = [];
70480
+
70481
+ for (let feature of featureList) {
70482
+
70483
+ // Double line divider between features
70484
+ if (items.length > 0) {
70485
+ items.push('<hr/>');
70486
+ items.push('<hr/>');
70487
+ }
70488
+
70489
+ // hack for whole genome features, which save the original feature as "_f"
70490
+ const f = feature._f || feature;
70491
+
70492
+ const data = (typeof f.popupData === 'function') ?
70493
+ f.popupData(this.type, this.browser.genome.id) :
70494
+ this.extractPopupData(f);
70495
+ Array.prototype.push.apply(items, data);
70496
+
70497
+ }
70498
+
70499
+ return items
70500
+ }
70501
+
70502
+ get supportsWholeGenome() {
70503
+ return false
70504
+ }
70505
+
70506
+ getState() {
70507
+
70508
+ const config = super.getState();
70509
+ config.colorScale = this.colorScale.toJson();
70510
+ return config
70511
+
70512
+ }
70513
+
70514
+ }
70515
+
70092
70516
  //import CNVPytorTrack from "./CNVpytor/cnvpytorTrack.js"
70093
70517
 
70094
70518
 
@@ -70100,7 +70524,7 @@ const trackFunctions =
70100
70524
  ['seg', (config, browser) => new SegTrack(config, browser)],
70101
70525
  ['mut', (config, browser) => new SegTrack(config, browser)],
70102
70526
  ['maf', (config, browser) => new SegTrack(config, browser)],
70103
- ['shoebox', (config, browser) => new SegTrack(config, browser)],
70527
+ ['shoebox', (config, browser) => new ShoeboxTrack(config, browser)],
70104
70528
  ['wig', (config, browser) => new WigTrack(config, browser)],
70105
70529
  ['merged', (config, browser) => new MergedTrack(config, browser)],
70106
70530
  ['alignment', (config, browser) => new BAMTrack(config, browser)],
@@ -70592,94 +71016,11 @@ function createReferenceFrameList(loci, genome, browserFlanking, minimumBases, v
70592
71016
  })
70593
71017
  }
70594
71018
 
70595
- const _version = "3.0.7";
71019
+ const _version = "3.0.9";
70596
71020
  function version() {
70597
71021
  return _version
70598
71022
  }
70599
71023
 
70600
- /*
70601
- * The MIT License (MIT)
70602
- *
70603
- * Copyright (c) 2014 Broad Institute
70604
- *
70605
- * Permission is hereby granted, free of charge, to any person obtaining a copy
70606
- * of this software and associated documentation files (the "Software"), to deal
70607
- * in the Software without restriction, including without limitation the rights
70608
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
70609
- * copies of the Software, and to permit persons to whom the Software is
70610
- * furnished to do so, subject to the following conditions:
70611
- *
70612
- * The above copyright notice and this permission notice shall be included in
70613
- * all copies or substantial portions of the Software.
70614
- *
70615
- *
70616
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
70617
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
70618
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
70619
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
70620
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
70621
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
70622
- * THE SOFTWARE.
70623
- */
70624
-
70625
- const navbarResponsiveClasses = {};
70626
-
70627
- const responsiveThreshold = 8;
70628
- let textButtonContainerWidth = undefined;
70629
-
70630
- function navbarDidResize(browser, width) {
70631
-
70632
- const currentClass = NavbarButton.currentNavbarButtonClass(browser);
70633
- if ('igv-navbar-text-button' === currentClass) {
70634
- textButtonContainerWidth = browser.$navigation.get(0).querySelector('.igv-navbar-right-container').getBoundingClientRect().width;
70635
- }
70636
-
70637
- const responsiveClasses = getResponsiveClasses(browser, width);
70638
-
70639
- $$1(browser.zoomWidget.zoomContainer).removeClass();
70640
- $$1(browser.zoomWidget.zoomContainer).addClass(responsiveClasses.zoomContainer);
70641
-
70642
- browser.fireEvent('navbar-resize', [ responsiveClasses.navbarButton ]);
70643
- }
70644
-
70645
- function getResponsiveClasses(browser, navbarWidth) {
70646
-
70647
- const isWGV =
70648
- (browser.isMultiLocusWholeGenomeView()) ||
70649
- (browser.referenceFrameList && GenomeUtils.isWholeGenomeView(browser.referenceFrameList[0].chr));
70650
-
70651
- isWGV ? browser.windowSizePanel.hide() : browser.windowSizePanel.show();
70652
-
70653
- const { x: leftContainerX, width: leftContainerWidth } = browser.$navigation.get(0).querySelector('.igv-navbar-left-container').getBoundingClientRect();
70654
- const leftContainerExtent = leftContainerX + leftContainerWidth;
70655
- const { x:rightContainerX} = browser.$navigation.get(0).querySelector('.igv-navbar-right-container').getBoundingClientRect();
70656
-
70657
- const delta = rightContainerX - leftContainerExtent;
70658
-
70659
- const currentClass = NavbarButton.currentNavbarButtonClass(browser);
70660
-
70661
- // console.log(`Current class ${ currentClass } Delta: ${ StringUtils.numberFormatter(Math.floor(delta))}`)
70662
-
70663
- if ('igv-navbar-text-button' === currentClass && delta < responsiveThreshold) {
70664
- navbarResponsiveClasses.navbarButton = 'igv-navbar-icon-button';
70665
- } else if (textButtonContainerWidth && 'igv-navbar-icon-button' === currentClass) {
70666
- const length = navbarWidth - leftContainerExtent;
70667
- if (length - textButtonContainerWidth > responsiveThreshold) {
70668
- navbarResponsiveClasses.navbarButton = 'igv-navbar-text-button';
70669
- }
70670
-
70671
- }
70672
-
70673
-
70674
- if (isWGV) {
70675
- navbarResponsiveClasses.zoomContainer = 'igv-zoom-widget-hidden';
70676
- } else {
70677
- navbarResponsiveClasses.zoomContainer = navbarWidth > 860 ? 'igv-zoom-widget' : 'igv-zoom-widget-900';
70678
- }
70679
-
70680
- return navbarResponsiveClasses
70681
- }
70682
-
70683
71024
  /*
70684
71025
  * The MIT License (MIT)
70685
71026
  *
@@ -70727,7 +71068,7 @@ class ChromosomeSelectWidget {
70727
71068
  });
70728
71069
 
70729
71070
  this.showAllChromosomes = browser.config.showAllChromosomes !== false; // i.e. default to true
70730
-
71071
+ this.genome = browser.genome;
70731
71072
  }
70732
71073
 
70733
71074
  show() {
@@ -70738,10 +71079,16 @@ class ChromosomeSelectWidget {
70738
71079
  this.container.style.display = 'none';
70739
71080
  }
70740
71081
 
71082
+ setValue(chrName) {
71083
+ this.select.value = this.genome.getChromosomeDisplayName(chrName);
71084
+ }
71085
+
70741
71086
  update(genome) {
70742
71087
 
71088
+ this.genome = genome;
71089
+
70743
71090
  // Start with explicit chromosome name list
70744
- const list = genome.wgChromosomeNames || [];
71091
+ const list = genome.wgChromosomeNames.map(nm => genome.getChromosomeDisplayName(nm)) || [];
70745
71092
 
70746
71093
  if (this.showAllChromosomes && genome.chromosomeNames.length > 1) {
70747
71094
  const exclude = new Set(list);
@@ -70752,6 +71099,7 @@ class ChromosomeSelectWidget {
70752
71099
  break
70753
71100
  }
70754
71101
  if (!exclude.has(nm)) {
71102
+ nm = genome.getChromosomeDisplayName(nm);
70755
71103
  list.push(nm);
70756
71104
  }
70757
71105
  }
@@ -70832,6 +71180,99 @@ class WindowSizePanel {
70832
71180
  }
70833
71181
  }
70834
71182
 
71183
+ const multiSelectImage =
71184
+ `<svg width="625px" height="625px" viewBox="0 0 625 625" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
71185
+ <title>multi select</title>
71186
+ <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
71187
+ <g id="multi-select">
71188
+ <rect id="backdrop-copy-3" stroke="#737373" stroke-width="12" fill="#FFFFFF" x="6" y="6" width="613" height="613" rx="135"></rect>
71189
+ <g id="row-copy-3" transform="translate(81, 427)" fill="#737373">
71190
+ <rect id="Rectangle" x="134" y="0" width="329" height="70"></rect>
71191
+ <rect id="Rectangle-Copy-16" stroke="#737373" stroke-width="12" x="6" y="6" width="58" height="58"></rect>
71192
+ </g>
71193
+ <g id="row-copy-2" transform="translate(82, 277)">
71194
+ <rect id="Rectangle" fill-opacity="0.33" fill="#CFCECE" x="133" y="0" width="329" height="70"></rect>
71195
+ <rect id="Rectangle-Copy-16" stroke-opacity="0.32659528" stroke="#CFCECE" stroke-width="12" x="6" y="6" width="58" height="58"></rect>
71196
+ </g>
71197
+ <g id="row-copy" transform="translate(81, 119)" fill="#737373">
71198
+ <rect id="Rectangle" x="134" y="0" width="329" height="70"></rect>
71199
+ <rect id="Rectangle-Copy-17" stroke="#737373" stroke-width="12" x="6" y="6" width="58" height="58"></rect>
71200
+ </g>
71201
+ </g>
71202
+ </g>
71203
+ </svg>`;
71204
+
71205
+ const multiSelectImageHover =
71206
+ `<svg width="625px" height="625px" viewBox="0 0 625 625" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
71207
+ <title>multi select hover</title>
71208
+ <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
71209
+ <g id="multi-select-hover">
71210
+ <rect id="backdrop-copy-4" stroke="#737373" stroke-width="12" fill="#737373" x="6" y="6" width="613" height="613" rx="135"></rect>
71211
+ <g id="row-copy-3" transform="translate(81, 427)" fill="#FFFFFF">
71212
+ <rect id="Rectangle" x="134" y="0" width="329" height="70"></rect>
71213
+ <rect id="Rectangle-Copy-16" stroke="#FFFFFF" stroke-width="12" x="6" y="6" width="58" height="58"></rect>
71214
+ </g>
71215
+ <g id="row-copy-2" transform="translate(82, 277)">
71216
+ <rect id="Rectangle" fill-opacity="0.33" fill="#CFCECE" x="133" y="0" width="329" height="70"></rect>
71217
+ <rect id="Rectangle-Copy-16" stroke-opacity="0.33" stroke="#CFCECE" stroke-width="12" x="6" y="6" width="58" height="58"></rect>
71218
+ </g>
71219
+ <g id="row-copy" transform="translate(81, 119)" fill="#FFFFFF">
71220
+ <rect id="Rectangle" x="134" y="0" width="329" height="70"></rect>
71221
+ <rect id="Rectangle-Copy-17" stroke="#FFFFFF" stroke-width="12" x="6" y="6" width="58" height="58"></rect>
71222
+ </g>
71223
+ </g>
71224
+ </g>
71225
+ </svg>`;
71226
+
71227
+ class MultiTrackSelectButton extends NavbarButton {
71228
+
71229
+ constructor(parent, browser, navbar, enableMultiTrackSelection) {
71230
+
71231
+ super(parent, browser, 'Select Tracks', buttonLabel, multiSelectImage, multiSelectImageHover, false);
71232
+
71233
+ this.navbar = navbar;
71234
+ this.enableMultiTrackSelection = false; // Initial state
71235
+ this.button.addEventListener('mouseenter', event => {
71236
+ if (false === enableMultiTrackSelection) {
71237
+ this.setState(true);
71238
+ }
71239
+ });
71240
+
71241
+ this.button.addEventListener('mouseleave', event => {
71242
+ if (false === enableMultiTrackSelection) {
71243
+ this.setState(false);
71244
+ }
71245
+ });
71246
+
71247
+ const mouseClickHandler = () => {
71248
+ // Toggle the selection state
71249
+ this.setMultiTrackSelection(!this.enableMultiTrackSelection);
71250
+ };
71251
+
71252
+ this.boundMouseClickHandler = mouseClickHandler.bind(this);
71253
+
71254
+ this.button.addEventListener('click', this.boundMouseClickHandler);
71255
+
71256
+ }
71257
+
71258
+ setMultiTrackSelection(enableMultiTrackSelection) {
71259
+
71260
+ this.enableMultiTrackSelection = enableMultiTrackSelection;
71261
+ this.setState(this.enableMultiTrackSelection);
71262
+
71263
+ // If enableMultiTrackSelection is false hide the Overly button
71264
+ if (false === this.enableMultiTrackSelection) {
71265
+ this.navbar.overlayTrackButton.setVisibility(false);
71266
+ }
71267
+
71268
+ for (const trackView of this.browser.trackViews) {
71269
+ trackView.enableTrackSelection(enableMultiTrackSelection);
71270
+ }
71271
+
71272
+ }
71273
+
71274
+ }
71275
+
70835
71276
  class CursorGuide {
70836
71277
 
70837
71278
  constructor(columnContainer, browser) {
@@ -71013,9 +71454,9 @@ const cursorImageHover =
71013
71454
 
71014
71455
  class CursorGuideButton extends NavbarButton {
71015
71456
 
71016
- constructor(browser, parent) {
71457
+ constructor(parent, browser) {
71017
71458
 
71018
- super(browser, parent, 'Crosshairs', buttonLabel, cursorImage, cursorImageHover, browser.doShowCursorGuide);
71459
+ super(parent, browser, 'Crosshairs', buttonLabel, cursorImage, cursorImageHover, browser.doShowCursorGuide);
71019
71460
 
71020
71461
  this.button.addEventListener('mouseenter', () => {
71021
71462
  if (false === browser.doShowCursorGuide) {
@@ -71101,9 +71542,9 @@ const centerlineImageHover =
71101
71542
 
71102
71543
  class CenterLineButton extends NavbarButton {
71103
71544
 
71104
- constructor(browser, parent) {
71545
+ constructor(parent, browser) {
71105
71546
 
71106
- super(browser, parent, 'Center Line', buttonLabel, centerlineImage, centerlineImageHover, browser.config.showCenterGuide);
71547
+ super(parent, browser, 'Center Line', buttonLabel, centerlineImage, centerlineImageHover, browser.config.showCenterGuide);
71107
71548
 
71108
71549
  this.button.addEventListener('mouseenter', () => {
71109
71550
  if (false === browser.doShowCenterLine) {
@@ -71192,7 +71633,7 @@ class TrackLabelControl extends NavbarButton {
71192
71633
 
71193
71634
  constructor(parent, browser) {
71194
71635
 
71195
- super(browser, parent, 'Track Labels', buttonLabel, trackLabelsImage, trackLabelsImageHover, browser.config.showTrackLabels);
71636
+ super(parent, browser, 'Track Labels', buttonLabel, trackLabelsImage, trackLabelsImageHover, browser.config.showTrackLabels);
71196
71637
 
71197
71638
  this.button.addEventListener('mouseenter', () => {
71198
71639
  if (false === browser.doShowTrackLabels) {
@@ -71222,28 +71663,28 @@ class TrackLabelControl extends NavbarButton {
71222
71663
 
71223
71664
  }
71224
71665
 
71225
- const sampleNameImage =
71666
+ const roiImage =
71226
71667
  `<svg width="625px" height="625px" viewBox="0 0 625 625" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
71227
- <title>sample names</title>
71668
+ <title>roi</title>
71228
71669
  <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
71229
- <g id="sample-names" stroke="#737373">
71230
- <rect id="Rectangle-Copy-13" stroke-width="12" fill="#FFFFFF" x="6" y="6" width="613" height="613" rx="135"></rect>
71231
- <line x1="80" y1="465" x2="541" y2="464.5" id="Line-3-Copy-3" stroke-width="32"></line>
71232
- <line x1="80" y1="312.5" x2="542" y2="313" id="Line-3" stroke-width="32"></line>
71233
- <line x1="80" y1="158" x2="541" y2="158" id="Line-3-Copy" stroke-width="32"></line>
71670
+ <g id="roi">
71671
+ <rect id="Rectangle-Copy-23" stroke="#737373" stroke-width="12" fill="#FFFFFF" x="6" y="6" width="613" height="613" rx="135"></rect>
71672
+ <text id="ROI" font-family="HelveticaNeue-Bold, Helvetica Neue" font-size="258" font-weight="bold" fill="#737373">
71673
+ <tspan x="81.445" y="389">ROI</tspan>
71674
+ </text>
71234
71675
  </g>
71235
71676
  </g>
71236
71677
  </svg>`;
71237
71678
 
71238
- const sampleNameImageHover =
71679
+ const roiImageHover =
71239
71680
  `<svg width="625px" height="625px" viewBox="0 0 625 625" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
71240
- <title>sample names hover</title>
71681
+ <title>roi hover</title>
71241
71682
  <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
71242
- <g id="sample-names-hover">
71243
- <rect id="Rectangle-Copy-18" stroke="#737373" stroke-width="12" fill="#737373" x="6" y="6" width="613" height="613" rx="135"></rect>
71244
- <line x1="80" y1="465" x2="541" y2="464.5" id="Line-3-Copy-3" stroke="#FFFFFF" stroke-width="32" fill="#FFFFFF"></line>
71245
- <line x1="80" y1="312.5" x2="542" y2="313" id="Line-3" stroke="#FFFFFF" stroke-width="32" fill="#FFFFFF"></line>
71246
- <line x1="80" y1="158" x2="541" y2="158" id="Line-3-Copy" stroke="#FFFFFF" stroke-width="32" fill="#FFFFFF"></line>
71683
+ <g id="roi-hover">
71684
+ <rect id="Rectangle-Copy-24" stroke="#737373" stroke-width="12" fill="#737373" x="6" y="6" width="613" height="613" rx="135"></rect>
71685
+ <text id="ROI" font-family="HelveticaNeue-Bold, Helvetica Neue" font-size="258" font-weight="bold" fill="#FFFFFF">
71686
+ <tspan x="81.445" y="389">ROI</tspan>
71687
+ </text>
71247
71688
  </g>
71248
71689
  </g>
71249
71690
  </svg>`;
@@ -71274,49 +71715,34 @@ const sampleNameImageHover =
71274
71715
  * THE SOFTWARE.
71275
71716
  */
71276
71717
 
71277
- class SampleNameControl extends NavbarButton {
71718
+ class ROITableControl extends NavbarButton {
71278
71719
 
71279
- constructor(parent, browser) {
71720
+ constructor(parent, browser) {
71280
71721
 
71281
- super(browser, parent, 'Sample Names', sampleNameButtonLabel, sampleNameImage, sampleNameImageHover, browser.config.showSampleNames);
71722
+ super(parent, browser, ['ROI', 'Regions of Interest Table'], buttonLabel, roiImage, roiImageHover, false);
71282
71723
 
71283
71724
  this.button.addEventListener('mouseenter', () => {
71284
- if (false === browser.showSampleNames) {
71725
+ if (false === browser.doShowROITable) {
71285
71726
  this.setState(true);
71286
71727
  }
71287
71728
  });
71288
71729
 
71289
71730
  this.button.addEventListener('mouseleave', () => {
71290
- if (false === browser.showSampleNames) {
71731
+ if (false === browser.doShowROITable) {
71291
71732
  this.setState(false);
71292
71733
  }
71293
71734
  });
71294
71735
 
71295
- this.button.addEventListener('click', () => {
71296
- this.performClickWithState(browser, undefined);
71297
- });
71736
+ this.button.addEventListener('click', () => this.buttonHandler(!browser.doShowROITable));
71298
71737
 
71299
- if (true === browser.config.showSampleNameButton) {
71300
- this.show();
71301
- } else {
71302
- this.hide();
71303
- }
71738
+ this.setVisibility(false); // Hide initially, it will be un-hidden if ROIs are loaded
71304
71739
 
71305
71740
  }
71306
71741
 
71307
- performClickWithState(browser, doShowSampleNamesOrUndefined) {
71308
-
71309
- browser.showSampleNames = undefined === doShowSampleNamesOrUndefined ? !browser.showSampleNames : doShowSampleNamesOrUndefined;
71310
-
71311
- const column = browser.columnContainer.querySelector('.igv-sample-name-column');
71312
- column.style.display = false === browser.showSampleNames ? 'none' : 'flex';
71313
-
71314
- this.setState(browser.showSampleNames);
71315
-
71316
- browser.layoutChange();
71317
-
71742
+ buttonHandler(status) {
71743
+ this.setState(status);
71744
+ this.browser.setROITableVisibility(status);
71318
71745
  }
71319
-
71320
71746
  }
71321
71747
 
71322
71748
  const sampleInfoImage =
@@ -71420,7 +71846,7 @@ class SampleInfoControl extends NavbarButton {
71420
71846
 
71421
71847
  constructor(parent, browser) {
71422
71848
 
71423
- super(browser, parent, 'Sample Info', buttonLabel, sampleInfoImage, sampleInfoImageHover, false);
71849
+ super(parent, browser, 'Sample Info', buttonLabel, sampleInfoImage, sampleInfoImageHover, false);
71424
71850
 
71425
71851
  this.showSampleInfo = false;
71426
71852
 
@@ -71470,141 +71896,102 @@ class SampleInfoControl extends NavbarButton {
71470
71896
 
71471
71897
  }
71472
71898
 
71473
- const sliderMin = 0;
71474
- let sliderMax = 23;
71475
- let sliderValueRaw = 0;
71476
-
71477
- const ZoomWidget = function (browser, parent) {
71478
-
71479
- this.browser = browser;
71480
-
71481
- this.zoomContainer = div({class: 'igv-zoom-widget'});
71482
- parent.appendChild(this.zoomContainer);
71483
-
71484
- // zoom out
71485
- this.zoomOutButton = div();
71486
- this.zoomContainer.appendChild(this.zoomOutButton);
71487
- this.zoomOutButton.appendChild(createIcon('minus-circle'));
71488
- this.zoomOutButton.addEventListener('click', () => {
71489
- // browser.zoomWithScaleFactor(2.0)
71490
- browser.zoomOut();
71491
- });
71492
-
71493
- // Range slider
71494
- const el = div();
71495
- this.zoomContainer.appendChild(el);
71496
- this.slider = document.createElement('input');
71497
- this.slider.type = 'range';
71498
-
71499
- this.slider.min = `${sliderMin}`;
71500
- this.slider.max = `${sliderMax}`;
71501
-
71502
- el.appendChild(this.slider);
71503
-
71504
- this.slider.addEventListener('change', e => {
71505
-
71506
- e.preventDefault();
71507
- e.stopPropagation();
71508
-
71509
- const referenceFrame = browser.referenceFrameList[0];
71510
- const {bpLength} = referenceFrame.genome.getChromosome(referenceFrame.chr);
71511
- const {end, start} = referenceFrame;
71899
+ const sampleNameImage =
71900
+ `<svg width="625px" height="625px" viewBox="0 0 625 625" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
71901
+ <title>sample names</title>
71902
+ <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
71903
+ <g id="sample-names" stroke="#737373">
71904
+ <rect id="Rectangle-Copy-13" stroke-width="12" fill="#FFFFFF" x="6" y="6" width="613" height="613" rx="135"></rect>
71905
+ <line x1="80" y1="465" x2="541" y2="464.5" id="Line-3-Copy-3" stroke-width="32"></line>
71906
+ <line x1="80" y1="312.5" x2="542" y2="313" id="Line-3" stroke-width="32"></line>
71907
+ <line x1="80" y1="158" x2="541" y2="158" id="Line-3-Copy" stroke-width="32"></line>
71908
+ </g>
71909
+ </g>
71910
+ </svg>`;
71512
71911
 
71513
- const extent = end - start;
71912
+ const sampleNameImageHover =
71913
+ `<svg width="625px" height="625px" viewBox="0 0 625 625" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
71914
+ <title>sample names hover</title>
71915
+ <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
71916
+ <g id="sample-names-hover">
71917
+ <rect id="Rectangle-Copy-18" stroke="#737373" stroke-width="12" fill="#737373" x="6" y="6" width="613" height="613" rx="135"></rect>
71918
+ <line x1="80" y1="465" x2="541" y2="464.5" id="Line-3-Copy-3" stroke="#FFFFFF" stroke-width="32" fill="#FFFFFF"></line>
71919
+ <line x1="80" y1="312.5" x2="542" y2="313" id="Line-3" stroke="#FFFFFF" stroke-width="32" fill="#FFFFFF"></line>
71920
+ <line x1="80" y1="158" x2="541" y2="158" id="Line-3-Copy" stroke="#FFFFFF" stroke-width="32" fill="#FFFFFF"></line>
71921
+ </g>
71922
+ </g>
71923
+ </svg>`;
71514
71924
 
71515
- // bpLength/(end - start)
71516
- const scaleFactor = Math.pow(2, e.target.valueAsNumber);
71925
+ /*
71926
+ * The MIT License (MIT)
71927
+ *
71928
+ * Copyright (c) 2016 University of California San Diego
71929
+ * Author: Jim Robinson
71930
+ *
71931
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
71932
+ * of this software and associated documentation files (the "Software"), to deal
71933
+ * in the Software without restriction, including without limitation the rights
71934
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
71935
+ * copies of the Software, and to permit persons to whom the Software is
71936
+ * furnished to do so, subject to the following conditions:
71937
+ *
71938
+ * The above copyright notice and this permission notice shall be included in
71939
+ * all copies or substantial portions of the Software.
71940
+ *
71941
+ *
71942
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
71943
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
71944
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
71945
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
71946
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
71947
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
71948
+ * THE SOFTWARE.
71949
+ */
71517
71950
 
71518
- // (end - start) = bpLength/scaleFactor
71519
- const zoomedExtent = bpLength / scaleFactor;
71951
+ class SampleNameControl extends NavbarButton {
71520
71952
 
71521
- // console.log(`zoom-widget - slider ${ e.target.value } scaleFactor ${ scaleFactor } extent-zoomed ${ StringUtils.numberFormatter(Math.round(zoomedExtent)) }`)
71953
+ constructor(parent, browser) {
71522
71954
 
71523
- browser.zoomWithScaleFactor(zoomedExtent / extent);
71955
+ super(parent, browser, 'Sample Names', sampleNameButtonLabel, sampleNameImage, sampleNameImageHover, browser.config.showSampleNames);
71524
71956
 
71525
- });
71957
+ this.button.addEventListener('mouseenter', () => {
71958
+ if (false === browser.showSampleNames) {
71959
+ this.setState(true);
71960
+ }
71961
+ });
71526
71962
 
71527
- // zoom in
71528
- this.zoomInButton = div();
71529
- this.zoomContainer.appendChild(this.zoomInButton);
71530
- this.zoomInButton.appendChild(createIcon('plus-circle'));
71531
- this.zoomInButton.addEventListener('click', () => {
71532
- // browser.zoomWithScaleFactor(0.5)
71533
- browser.zoomIn();
71534
- });
71963
+ this.button.addEventListener('mouseleave', () => {
71964
+ if (false === browser.showSampleNames) {
71965
+ this.setState(false);
71966
+ }
71967
+ });
71535
71968
 
71536
- browser.on('locuschange', (referenceFrameList) => {
71969
+ this.button.addEventListener('click', () => {
71970
+ this.performClickWithState(browser, undefined);
71971
+ });
71537
71972
 
71538
- if (this.browser.isMultiLocusMode()) {
71539
- this.disable();
71973
+ if (true === browser.config.showSampleNameButton) {
71974
+ this.show();
71540
71975
  } else {
71541
- this.enable();
71542
- this.update(referenceFrameList);
71976
+ this.hide();
71543
71977
  }
71544
71978
 
71545
- });
71546
-
71547
- };
71548
-
71549
- ZoomWidget.prototype.update = function (referenceFrameList) {
71550
-
71551
- const referenceFrame = referenceFrameList[0];
71552
- const {bpLength} = referenceFrame.genome.getChromosome(referenceFrame.chr);
71553
- const {start, end} = referenceFrame;
71554
-
71555
- sliderMax = Math.ceil(Math.log2(bpLength / this.browser.minimumBases()));
71556
-
71557
- this.slider.max = `${sliderMax}`;
71558
-
71559
- const scaleFactor = bpLength / (end - start);
71560
- sliderValueRaw = Math.log2(scaleFactor);
71561
- this.slider.value = `${Math.round(sliderValueRaw)}`;
71562
-
71563
- // referenceFrame.description('zoom.update')
71564
-
71565
- // console.log(`${ Date.now() } update - slider ${ this.slider.value } scaleFactor ${ Math.round(scaleFactor) } extent ${ StringUtils.numberFormatter(Math.round(extent)) }`)
71566
-
71567
- // console.log(`update - sliderMin ${ sliderMin } sliderValue ${ this.slider.value } sliderMax ${ sliderMax } scaleFactor ${ scaleFactor.toFixed(3) } derived-scaleFactor ${ derivedScalefactor.toFixed(3) }`)
71568
-
71569
- };
71570
-
71571
- ZoomWidget.prototype.enable = function () {
71572
-
71573
- // this.zoomInButton.style.color = appleCrayonPalette[ 'steel' ];
71574
- // this.zoomInButton.style.pointerEvents = 'auto';
71575
- //
71576
- // this.zoomOutButton.style.color = appleCrayonPalette[ 'steel' ];
71577
- // this.zoomOutButton.style.pointerEvents = 'auto';
71578
-
71579
- this.slider.disabled = false;
71580
- };
71979
+ }
71581
71980
 
71582
- ZoomWidget.prototype.disable = function () {
71981
+ performClickWithState(browser, doShowSampleNamesOrUndefined) {
71583
71982
 
71584
- // this.zoomInButton.style.color = appleCrayonPalette[ 'silver' ];
71585
- // this.zoomInButton.style.pointerEvents = 'none';
71586
- //
71587
- // this.zoomOutButton.style.color = appleCrayonPalette[ 'silver' ];
71588
- // this.zoomOutButton.style.pointerEvents = 'none';
71983
+ browser.showSampleNames = undefined === doShowSampleNamesOrUndefined ? !browser.showSampleNames : doShowSampleNamesOrUndefined;
71589
71984
 
71590
- this.slider.disabled = true;
71591
- };
71985
+ const column = browser.columnContainer.querySelector('.igv-sample-name-column');
71986
+ column.style.display = false === browser.showSampleNames ? 'none' : 'flex';
71592
71987
 
71593
- ZoomWidget.prototype.hide = function () {
71594
- this.zoomContainer.style.display = 'none';
71595
- };
71988
+ this.setState(browser.showSampleNames);
71596
71989
 
71597
- ZoomWidget.prototype.show = function () {
71598
- this.zoomContainer.style.display = 'block';
71599
- };
71990
+ browser.layoutChange();
71600
71991
 
71601
- ZoomWidget.prototype.hideSlider = function () {
71602
- this.slider.style.display = 'none';
71603
- };
71992
+ }
71604
71993
 
71605
- ZoomWidget.prototype.showSlider = function () {
71606
- this.slider.style.display = 'block';
71607
- };
71994
+ }
71608
71995
 
71609
71996
  class Dropdown {
71610
71997
  constructor(parent, shim) {
@@ -71747,7 +72134,7 @@ const imageSaveImageHoverSVG =
71747
72134
  class SaveImageControl extends NavbarButton {
71748
72135
  constructor(parent, browser) {
71749
72136
 
71750
- super(browser, parent, 'Save Image', buttonLabel, imageSaveImageSVG, imageSaveImageHoverSVG, false);
72137
+ super(parent, browser, 'Save Image', buttonLabel, imageSaveImageSVG, imageSaveImageHoverSVG, false);
71751
72138
 
71752
72139
  this.button.addEventListener('mouseenter', () => this.setState(true));
71753
72140
 
@@ -71813,6 +72200,422 @@ class SaveImageControl extends NavbarButton {
71813
72200
 
71814
72201
  }
71815
72202
 
72203
+ /**
72204
+ * User supplied button for the navbar
72205
+ */
72206
+
72207
+ const CustomButton = function (parent, browser, b) {
72208
+
72209
+ const button = div({class: 'igv-navbar-button'});
72210
+ parent.append(button);
72211
+ button.textContent = b.label;
72212
+ button.addEventListener('click', () => b.callback(browser));
72213
+ };
72214
+
72215
+ const sliderMin = 0;
72216
+ let sliderMax = 23;
72217
+ let sliderValueRaw = 0;
72218
+
72219
+ class ZoomWidget {
72220
+ constructor(config, browser, parent) {
72221
+
72222
+ this.browser = browser;
72223
+
72224
+ this.zoomContainer = div({class: 'igv-zoom-widget'});
72225
+ parent.appendChild(this.zoomContainer);
72226
+
72227
+ // zoom out
72228
+ this.zoomOutButton = div();
72229
+ this.zoomContainer.appendChild(this.zoomOutButton);
72230
+ this.zoomOutButton.appendChild(createIcon('minus-circle'));
72231
+ this.zoomOutButton.addEventListener('click', () => {
72232
+ // browser.zoomWithScaleFactor(2.0)
72233
+ browser.zoomOut();
72234
+ });
72235
+
72236
+ // Range slider
72237
+ const el = div();
72238
+ this.zoomContainer.appendChild(el);
72239
+ this.slider = document.createElement('input');
72240
+ this.slider.type = 'range';
72241
+
72242
+ this.slider.min = `${sliderMin}`;
72243
+ this.slider.max = `${sliderMax}`;
72244
+
72245
+ el.appendChild(this.slider);
72246
+
72247
+ this.slider.addEventListener('change', e => {
72248
+
72249
+ e.preventDefault();
72250
+ e.stopPropagation();
72251
+
72252
+ const referenceFrame = browser.referenceFrameList[0];
72253
+ const {bpLength} = referenceFrame.genome.getChromosome(referenceFrame.chr);
72254
+ const {end, start} = referenceFrame;
72255
+
72256
+ const extent = end - start;
72257
+
72258
+ // bpLength/(end - start)
72259
+ const scaleFactor = Math.pow(2, e.target.valueAsNumber);
72260
+
72261
+ // (end - start) = bpLength/scaleFactor
72262
+ const zoomedExtent = bpLength / scaleFactor;
72263
+
72264
+ // console.log(`zoom-widget - slider ${ e.target.value } scaleFactor ${ scaleFactor } extent-zoomed ${ StringUtils.numberFormatter(Math.round(zoomedExtent)) }`)
72265
+
72266
+ browser.zoomWithScaleFactor(zoomedExtent / extent);
72267
+
72268
+ });
72269
+
72270
+ // zoom in
72271
+ this.zoomInButton = div();
72272
+ this.zoomContainer.appendChild(this.zoomInButton);
72273
+ this.zoomInButton.appendChild(createIcon('plus-circle'));
72274
+ this.zoomInButton.addEventListener('click', () => {
72275
+ // browser.zoomWithScaleFactor(0.5)
72276
+ browser.zoomIn();
72277
+ });
72278
+
72279
+ browser.on('locuschange', (referenceFrameList) => {
72280
+
72281
+ if (this.browser.isMultiLocusMode()) {
72282
+ this.disable();
72283
+ } else {
72284
+ this.enable();
72285
+ this.update(referenceFrameList);
72286
+ }
72287
+
72288
+ });
72289
+
72290
+ }
72291
+
72292
+ update(referenceFrameList) {
72293
+
72294
+ if (this.slider) {
72295
+ const referenceFrame = referenceFrameList[0];
72296
+ const {bpLength} = referenceFrame.genome.getChromosome(referenceFrame.chr);
72297
+ const {start, end} = referenceFrame;
72298
+
72299
+ sliderMax = Math.ceil(Math.log2(bpLength / this.browser.minimumBases()));
72300
+ this.slider.max = `${sliderMax}`;
72301
+
72302
+ const scaleFactor = bpLength / (end - start);
72303
+ sliderValueRaw = Math.log2(scaleFactor);
72304
+ this.slider.value = `${Math.round(sliderValueRaw)}`;
72305
+ }
72306
+ }
72307
+
72308
+
72309
+ enable() {
72310
+
72311
+ // this.zoomInButton.style.color = appleCrayonPalette[ 'steel' ];
72312
+ // this.zoomInButton.style.pointerEvents = 'auto';
72313
+ //
72314
+ // this.zoomOutButton.style.color = appleCrayonPalette[ 'steel' ];
72315
+ // this.zoomOutButton.style.pointerEvents = 'auto';
72316
+
72317
+ if (this.slider) this.slider.disabled = false;
72318
+ }
72319
+
72320
+ disable() {
72321
+
72322
+ // this.zoomInButton.style.color = appleCrayonPalette[ 'silver' ];
72323
+ // this.zoomInButton.style.pointerEvents = 'none';
72324
+ //
72325
+ // this.zoomOutButton.style.color = appleCrayonPalette[ 'silver' ];
72326
+ // this.zoomOutButton.style.pointerEvents = 'none';
72327
+
72328
+ if (this.slider) this.slider.disabled = true;
72329
+ }
72330
+
72331
+ hide() {
72332
+ this.zoomContainer.style.display = 'none';
72333
+ }
72334
+
72335
+ show() {
72336
+ this.zoomContainer.style.display = 'block';
72337
+ }
72338
+
72339
+ hideSlider() {
72340
+ if (this.slider) this.slider.style.display = 'none';
72341
+ }
72342
+
72343
+ showSlider() {
72344
+ if (this.slider) this.slider.style.display = 'block';
72345
+ }
72346
+ }
72347
+
72348
+ /*
72349
+ * The MIT License (MIT)
72350
+ *
72351
+ * Copyright (c) 2014 Broad Institute
72352
+ *
72353
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
72354
+ * of this software and associated documentation files (the "Software"), to deal
72355
+ * in the Software without restriction, including without limitation the rights
72356
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
72357
+ * copies of the Software, and to permit persons to whom the Software is
72358
+ * furnished to do so, subject to the following conditions:
72359
+ *
72360
+ * The above copyright notice and this permission notice shall be included in
72361
+ * all copies or substantial portions of the Software.
72362
+ *
72363
+ *
72364
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
72365
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
72366
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
72367
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
72368
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
72369
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
72370
+ * THE SOFTWARE.
72371
+ */
72372
+
72373
+ class ResponsiveNavbar {
72374
+ constructor(config, browser) {
72375
+
72376
+ this.browser = browser;
72377
+ this.config = config;
72378
+
72379
+ this.currentClass = 'igv-navbar-text-button';
72380
+
72381
+ // DOM element for
72382
+ const $navBar = $$1('<div>', {class: 'igv-navbar'});
72383
+ this.$navigation = $navBar;
72384
+
72385
+ const $navbarLeftContainer = $$1('<div>', {class: 'igv-navbar-left-container'});
72386
+ $navBar.append($navbarLeftContainer);
72387
+ this.navbarLeftContainer = $navbarLeftContainer.get(0);
72388
+
72389
+ // IGV logo
72390
+ const $logo = $$1('<div>', {class: 'igv-logo'});
72391
+ $navbarLeftContainer.append($logo);
72392
+
72393
+ const logoSvg = logo();
72394
+ logoSvg.css("width", "34px");
72395
+ logoSvg.css("height", "32px");
72396
+ $logo.append(logoSvg);
72397
+
72398
+ this.$current_genome = $$1('<div>', {class: 'igv-current-genome'});
72399
+ $navbarLeftContainer.append(this.$current_genome);
72400
+ this.$current_genome.text('');
72401
+
72402
+ const $genomicLocation = $$1('<div>', {class: 'igv-navbar-genomic-location'});
72403
+ $navbarLeftContainer.append($genomicLocation);
72404
+
72405
+ // chromosome select widget
72406
+ this.chromosomeSelectWidget = new ChromosomeSelectWidget(browser, $genomicLocation.get(0));
72407
+ if (config.showChromosomeWidget !== false) {
72408
+ this.chromosomeSelectWidget.show();
72409
+ } else {
72410
+ this.chromosomeSelectWidget.hide();
72411
+ }
72412
+
72413
+ const $locusSizeGroup = $$1('<div>', {class: 'igv-locus-size-group'});
72414
+ $genomicLocation.append($locusSizeGroup);
72415
+
72416
+ const $searchContainer = $$1('<div>', {class: 'igv-search-container'});
72417
+ $locusSizeGroup.append($searchContainer);
72418
+
72419
+ // browser.$searchInput = $('<input type="text" placeholder="Locus Search">');
72420
+ this.$searchInput = $$1('<input>', {class: 'igv-search-input', type: 'text', placeholder: 'Locus Search'});
72421
+ $searchContainer.append(this.$searchInput);
72422
+ // Stop event propagation to prevent feature track keyboard navigation
72423
+ this.$searchInput[0].addEventListener('keyup', (event) => {
72424
+ event.stopImmediatePropagation();
72425
+ });
72426
+
72427
+ this.$searchInput.change(() => browser.doSearch(this.$searchInput.val()));
72428
+
72429
+ const searchIconContainer = div({class: 'igv-search-icon-container'});
72430
+ $searchContainer.append($$1(searchIconContainer));
72431
+ searchIconContainer.appendChild(createIcon("search"));
72432
+ searchIconContainer.addEventListener('click', () => browser.doSearch(this.$searchInput.val()));
72433
+
72434
+ this.windowSizePanel = new WindowSizePanel($locusSizeGroup.get(0), browser);
72435
+
72436
+ const $navbarRightContainer = $$1('<div>', {class: 'igv-navbar-right-container'});
72437
+ $navBar.append($navbarRightContainer);
72438
+ this.navbarRightContainer = $navbarRightContainer.get(0);
72439
+
72440
+ const $toggle_button_container = $$1('<div class="igv-navbar-toggle-button-container">');
72441
+ $navbarRightContainer.append($toggle_button_container);
72442
+ const toggleButtonContainer = $toggle_button_container.get(0);
72443
+ this.toggle_button_container = toggleButtonContainer; // TODO -- for circular view , refactor this
72444
+
72445
+ this.overlayTrackButton = new OverlayTrackButton(toggleButtonContainer, browser);
72446
+ this.overlayTrackButton.setVisibility(false);
72447
+
72448
+ const showMultiSelect = config.showMultiSelectButton !== false;
72449
+ this.multiTrackSelectButton = new MultiTrackSelectButton(toggleButtonContainer, browser, this, showMultiSelect);
72450
+
72451
+ this.cursorGuideButton = new CursorGuideButton(toggleButtonContainer, browser);
72452
+
72453
+ this.centerLineButton = new CenterLineButton(toggleButtonContainer, browser);
72454
+
72455
+ this.trackLabelControl = new TrackLabelControl(toggleButtonContainer, browser);
72456
+
72457
+ // ROI Control
72458
+ this.roiTableControl = new ROITableControl(toggleButtonContainer, browser);
72459
+
72460
+ this.sampleInfoControl = new SampleInfoControl(toggleButtonContainer, browser);
72461
+
72462
+ this.sampleNameControl = new SampleNameControl(toggleButtonContainer, browser);
72463
+
72464
+ if (true === config.showSVGButton) {
72465
+ this.saveImageControl = new SaveImageControl(toggleButtonContainer, browser);
72466
+ }
72467
+
72468
+ if (config.customButtons) {
72469
+ for (let b of config.customButtons) {
72470
+ new CustomButton(toggleButtonContainer, browser, b);
72471
+ }
72472
+ }
72473
+
72474
+ this.zoomWidget = new ZoomWidget(config, browser, $navbarRightContainer.get(0));
72475
+
72476
+ if (false === config.showNavigation) {
72477
+ this.$navigation.hide();
72478
+ }
72479
+
72480
+
72481
+
72482
+ }
72483
+
72484
+ navbarDidResize() {
72485
+
72486
+
72487
+ const navbarWidth = this.$navigation.width();
72488
+ const currentClass = this.currentNavbarButtonClass();
72489
+ if ('igv-navbar-text-button' === currentClass) {
72490
+ this.textButtonContainerWidth = this.navbarRightContainer.getBoundingClientRect().width;
72491
+ }
72492
+ const browser = this.browser;
72493
+ const isWGV =
72494
+ (browser.isMultiLocusWholeGenomeView()) ||
72495
+ (browser.referenceFrameList && GenomeUtils.isWholeGenomeView(browser.referenceFrameList[0].chr));
72496
+
72497
+ isWGV ? this.windowSizePanel.hide() : this.windowSizePanel.show();
72498
+
72499
+ const {
72500
+ x: leftContainerX,
72501
+ width: leftContainerWidth
72502
+ } = this.navbarLeftContainer.getBoundingClientRect();
72503
+ const leftContainerExtent = leftContainerX + leftContainerWidth;
72504
+ const {x: rightContainerX} = this.navbarRightContainer.getBoundingClientRect();
72505
+
72506
+ const delta = rightContainerX - leftContainerExtent;
72507
+
72508
+ let navbarButtonClass;
72509
+ const threshold = 8;
72510
+ if ('igv-navbar-text-button' === currentClass && delta < threshold) {
72511
+ navbarButtonClass = 'igv-navbar-icon-button';
72512
+ } else if (this.textButtonContainerWidth && 'igv-navbar-icon-button' === currentClass) {
72513
+ const length = navbarWidth - leftContainerExtent;
72514
+ if (length - this.textButtonContainerWidth > threshold) {
72515
+ navbarButtonClass = 'igv-navbar-text-button';
72516
+ }
72517
+ }
72518
+ // Update all the buttons (buttons are listeners)
72519
+ if(navbarButtonClass && currentClass !== navbarButtonClass) {
72520
+ this.currentClass = navbarButtonClass;
72521
+ this.browser.fireEvent('navbar-resize', [navbarButtonClass]);
72522
+ }
72523
+
72524
+ let zoomContainerClass;
72525
+ if (isWGV) {
72526
+ zoomContainerClass = 'igv-zoom-widget-hidden';
72527
+ } else {
72528
+ zoomContainerClass = navbarWidth > 860 ? 'igv-zoom-widget' : 'igv-zoom-widget-900';
72529
+ }
72530
+ $$1(this.zoomWidget.zoomContainer).removeClass();
72531
+ $$1(this.zoomWidget.zoomContainer).addClass(zoomContainerClass);
72532
+ }
72533
+
72534
+
72535
+ setCenterLineButtonVisibility(isWholeGenomeView) {
72536
+ if (isWholeGenomeView) {
72537
+ this.centerLineButton.setVisibility(!isWholeGenomeView);
72538
+ } else {
72539
+ this.centerLineButton.setVisibility(this.config.showCenterGuideButton);
72540
+ }
72541
+ }
72542
+
72543
+ setCursorGuideVisibility(doShowCursorGuide) {
72544
+ if (doShowCursorGuide) {
72545
+ this.cursorGuide.show();
72546
+ } else {
72547
+ this.cursorGuide.hide();
72548
+ }
72549
+ }
72550
+
72551
+ updateGenome(genome) {
72552
+
72553
+ let genomeLabel = (genome.id && genome.id.length < 20 ? genome.id : `${genome.id.substring(0, 8)}...${genome.id.substring(genome.id.length - 8)}`);
72554
+ this.$current_genome.text(genomeLabel);
72555
+ this.$current_genome.attr('title', genome.description);
72556
+
72557
+ // chromosome select widget -- Show this IFF its not explicitly hidden AND the genome has pre-loaded chromosomes
72558
+ const showChromosomeWidget =
72559
+ this.config.showChromosomeWidget !== false &&
72560
+ genome.showChromosomeWidget !== false &&
72561
+ genome.chromosomeNames &&
72562
+ genome.chromosomeNames.length > 1;
72563
+
72564
+ if (showChromosomeWidget) {
72565
+ this.chromosomeSelectWidget.update(genome);
72566
+ this.chromosomeSelectWidget.show();
72567
+ } else {
72568
+ this.chromosomeSelectWidget.hide();
72569
+ }
72570
+ }
72571
+
72572
+ updateLocus(loc, chrName) {
72573
+ if(this.$searchInput) {
72574
+ this.$searchInput.val(loc);
72575
+ }
72576
+ if (this.chromosomeSelectWidget) {
72577
+ this.chromosomeSelectWidget.select.value = chrName;
72578
+ }
72579
+ }
72580
+
72581
+ currentNavbarButtonClass() {
72582
+ return this.currentClass
72583
+ //const el = this.$navigation.get(0).querySelector('.igv-navbar-text-button')
72584
+ //return el ? 'igv-navbar-text-button' : 'igv-navbar-icon-button'
72585
+ }
72586
+
72587
+ setEnableTrackSelection(b) {
72588
+ this.multiTrackSelectButton.setMultiTrackSelection(b);
72589
+ }
72590
+ getEnableTrackSelection() {
72591
+ return this.multiTrackSelectButton.enableMultiTrackSelection
72592
+ }
72593
+
72594
+ hide() {
72595
+ this.$navigation.hide();
72596
+ }
72597
+
72598
+ show() {
72599
+ this.$navigation.show();
72600
+ }
72601
+
72602
+ }
72603
+
72604
+
72605
+ function logo() {
72606
+
72607
+ return $$1(
72608
+ '<svg width="690px" height="324px" viewBox="0 0 690 324" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">' +
72609
+ '<title>IGV</title>' +
72610
+ '<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">' +
72611
+ '<g id="IGV" fill="#666666">' +
72612
+ '<polygon id="Path" points="379.54574 8.00169252 455.581247 8.00169252 515.564813 188.87244 532.884012 253.529506 537.108207 253.529506 554.849825 188.87244 614.833392 8.00169252 689.60164 8.00169252 582.729511 320.722144 486.840288 320.722144"></polygon>' +
72613
+ '<path d="M261.482414,323.793286 C207.975678,323.793286 168.339046,310.552102 142.571329,284.069337 C116.803612,257.586572 103.919946,217.158702 103.919946,162.784513 C103.919946,108.410325 117.437235,67.8415913 144.472217,41.0770945 C171.507199,14.3125977 212.903894,0.930550071 268.663545,0.930550071 C283.025879,0.930550071 298.232828,1.84616386 314.284849,3.6774189 C330.33687,5.50867394 344.839793,7.97378798 357.794056,11.072835 L357.794056,68.968378 C339.48912,65.869331 323.578145,63.5450806 310.060654,61.9955571 C296.543163,60.4460336 284.574731,59.6712835 274.154998,59.6712835 C255.850062,59.6712835 240.502308,61.4320792 228.111274,64.9537236 C215.720241,68.4753679 205.793482,74.2507779 198.330701,82.2801269 C190.867919,90.309476 185.587729,100.87425 182.48997,113.974767 C179.392212,127.075284 177.843356,143.345037 177.843356,162.784513 C177.843356,181.942258 179.251407,198.000716 182.067551,210.960367 C184.883695,223.920018 189.671068,234.41436 196.429813,242.443709 C203.188559,250.473058 212.059279,256.178037 223.042241,259.558815 C234.025202,262.939594 247.683295,264.629958 264.01693,264.629958 C268.241146,264.629958 273.098922,264.489094 278.590403,264.207362 C284.081883,263.925631 289.643684,263.50304 295.275972,262.939577 L295.275972,159.826347 L361.595831,159.826347 L361.595831,308.579859 C344.698967,313.087564 327.239137,316.750019 309.215815,319.567334 C291.192494,322.38465 275.281519,323.793286 261.482414,323.793286 L261.482414,323.793286 L261.482414,323.793286 Z" id="Path"></path>;' +
72614
+ '<polygon id="Path" points="0.81355666 5.00169252 73.0472883 5.00169252 73.0472883 317.722144 0.81355666 317.722144"></polygon>' +
72615
+ '</g> </g> </svg>'
72616
+ )
72617
+ }
72618
+
71816
72619
  const viewportColumnManager =
71817
72620
  {
71818
72621
  createColumns: (columnContainer, count) => {
@@ -72024,18 +72827,6 @@ CircularViewControl.prototype.hide = function () {
72024
72827
  this.button.style.display = 'none';
72025
72828
  };
72026
72829
 
72027
- /**
72028
- * User supplied button for the navbar
72029
- */
72030
-
72031
- const CustomButton = function (parent, browser, b) {
72032
-
72033
- const button = div({class: 'igv-navbar-button'});
72034
- parent.append(button);
72035
- button.textContent = b.label;
72036
- button.addEventListener('click', () => b.callback(browser));
72037
- };
72038
-
72039
72830
  const maxSequenceSize = 1000000;
72040
72831
  const maxBlatSize = 25000;
72041
72832
 
@@ -72800,88 +73591,6 @@ class TrackROISet {
72800
73591
  }
72801
73592
  }
72802
73593
 
72803
- const roiImage =
72804
- `<svg width="625px" height="625px" viewBox="0 0 625 625" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
72805
- <title>roi</title>
72806
- <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
72807
- <g id="roi">
72808
- <rect id="Rectangle-Copy-23" stroke="#737373" stroke-width="12" fill="#FFFFFF" x="6" y="6" width="613" height="613" rx="135"></rect>
72809
- <text id="ROI" font-family="HelveticaNeue-Bold, Helvetica Neue" font-size="258" font-weight="bold" fill="#737373">
72810
- <tspan x="81.445" y="389">ROI</tspan>
72811
- </text>
72812
- </g>
72813
- </g>
72814
- </svg>`;
72815
-
72816
- const roiImageHover =
72817
- `<svg width="625px" height="625px" viewBox="0 0 625 625" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
72818
- <title>roi hover</title>
72819
- <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
72820
- <g id="roi-hover">
72821
- <rect id="Rectangle-Copy-24" stroke="#737373" stroke-width="12" fill="#737373" x="6" y="6" width="613" height="613" rx="135"></rect>
72822
- <text id="ROI" font-family="HelveticaNeue-Bold, Helvetica Neue" font-size="258" font-weight="bold" fill="#FFFFFF">
72823
- <tspan x="81.445" y="389">ROI</tspan>
72824
- </text>
72825
- </g>
72826
- </g>
72827
- </svg>`;
72828
-
72829
- /*
72830
- * The MIT License (MIT)
72831
- *
72832
- * Copyright (c) 2016 University of California San Diego
72833
- * Author: Jim Robinson
72834
- *
72835
- * Permission is hereby granted, free of charge, to any person obtaining a copy
72836
- * of this software and associated documentation files (the "Software"), to deal
72837
- * in the Software without restriction, including without limitation the rights
72838
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
72839
- * copies of the Software, and to permit persons to whom the Software is
72840
- * furnished to do so, subject to the following conditions:
72841
- *
72842
- * The above copyright notice and this permission notice shall be included in
72843
- * all copies or substantial portions of the Software.
72844
- *
72845
- *
72846
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
72847
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
72848
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
72849
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
72850
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
72851
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
72852
- * THE SOFTWARE.
72853
- */
72854
-
72855
- class ROITableControl extends NavbarButton {
72856
-
72857
- constructor(parent, browser) {
72858
-
72859
- super(browser, parent, [ 'ROI', 'Regions of Interest Table' ], buttonLabel, roiImage, roiImageHover, false);
72860
-
72861
- this.button.addEventListener('mouseenter', () => {
72862
- if (false === browser.doShowROITable) {
72863
- this.setState(true);
72864
- }
72865
- });
72866
-
72867
- this.button.addEventListener('mouseleave', () => {
72868
- if (false === browser.doShowROITable) {
72869
- this.setState(false);
72870
- }
72871
- });
72872
-
72873
- this.button.addEventListener('click', () => this.buttonHandler(!browser.doShowROITable));
72874
-
72875
- this.setVisibility(false); // Hide initially, it will be un-hidden if ROIs are loaded
72876
-
72877
- }
72878
-
72879
- buttonHandler(status) {
72880
- this.setState(status);
72881
- this.browser.setROITableVisibility(status);
72882
- }
72883
- }
72884
-
72885
73594
  async function translateSession(juiceboxSession) {
72886
73595
 
72887
73596
  const jbBrowser = juiceboxSession.browsers[0];
@@ -72918,101 +73627,6 @@ async function translateSession(juiceboxSession) {
72918
73627
 
72919
73628
  }
72920
73629
 
72921
- const multiSelectImage =
72922
- `<svg width="625px" height="625px" viewBox="0 0 625 625" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
72923
- <title>multi select</title>
72924
- <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
72925
- <g id="multi-select">
72926
- <rect id="backdrop-copy-3" stroke="#737373" stroke-width="12" fill="#FFFFFF" x="6" y="6" width="613" height="613" rx="135"></rect>
72927
- <g id="row-copy-3" transform="translate(81, 427)" fill="#737373">
72928
- <rect id="Rectangle" x="134" y="0" width="329" height="70"></rect>
72929
- <rect id="Rectangle-Copy-16" stroke="#737373" stroke-width="12" x="6" y="6" width="58" height="58"></rect>
72930
- </g>
72931
- <g id="row-copy-2" transform="translate(82, 277)">
72932
- <rect id="Rectangle" fill-opacity="0.33" fill="#CFCECE" x="133" y="0" width="329" height="70"></rect>
72933
- <rect id="Rectangle-Copy-16" stroke-opacity="0.32659528" stroke="#CFCECE" stroke-width="12" x="6" y="6" width="58" height="58"></rect>
72934
- </g>
72935
- <g id="row-copy" transform="translate(81, 119)" fill="#737373">
72936
- <rect id="Rectangle" x="134" y="0" width="329" height="70"></rect>
72937
- <rect id="Rectangle-Copy-17" stroke="#737373" stroke-width="12" x="6" y="6" width="58" height="58"></rect>
72938
- </g>
72939
- </g>
72940
- </g>
72941
- </svg>`;
72942
-
72943
- const multiSelectImageHover =
72944
- `<svg width="625px" height="625px" viewBox="0 0 625 625" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
72945
- <title>multi select hover</title>
72946
- <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
72947
- <g id="multi-select-hover">
72948
- <rect id="backdrop-copy-4" stroke="#737373" stroke-width="12" fill="#737373" x="6" y="6" width="613" height="613" rx="135"></rect>
72949
- <g id="row-copy-3" transform="translate(81, 427)" fill="#FFFFFF">
72950
- <rect id="Rectangle" x="134" y="0" width="329" height="70"></rect>
72951
- <rect id="Rectangle-Copy-16" stroke="#FFFFFF" stroke-width="12" x="6" y="6" width="58" height="58"></rect>
72952
- </g>
72953
- <g id="row-copy-2" transform="translate(82, 277)">
72954
- <rect id="Rectangle" fill-opacity="0.33" fill="#CFCECE" x="133" y="0" width="329" height="70"></rect>
72955
- <rect id="Rectangle-Copy-16" stroke-opacity="0.33" stroke="#CFCECE" stroke-width="12" x="6" y="6" width="58" height="58"></rect>
72956
- </g>
72957
- <g id="row-copy" transform="translate(81, 119)" fill="#FFFFFF">
72958
- <rect id="Rectangle" x="134" y="0" width="329" height="70"></rect>
72959
- <rect id="Rectangle-Copy-17" stroke="#FFFFFF" stroke-width="12" x="6" y="6" width="58" height="58"></rect>
72960
- </g>
72961
- </g>
72962
- </g>
72963
- </svg>`;
72964
-
72965
- class MultiTrackSelectButton extends NavbarButton {
72966
-
72967
- constructor(browser, parent, enableMultiTrackSelection) {
72968
-
72969
- super(browser, parent, 'Select Tracks', buttonLabel, multiSelectImage, multiSelectImageHover, enableMultiTrackSelection = false);
72970
- this.enableMultiTrackSelection = enableMultiTrackSelection;
72971
- this.button.addEventListener('mouseenter', event => {
72972
- if (false === enableMultiTrackSelection) {
72973
- this.setState(true);
72974
- }
72975
- });
72976
-
72977
- this.button.addEventListener('mouseleave', event => {
72978
- if (false === enableMultiTrackSelection) {
72979
- this.setState(false);
72980
- }
72981
- });
72982
-
72983
- const mouseClickHandler = () => {
72984
- this.setMultiTrackSelection(!this.enableMultiTrackSelection);
72985
- };
72986
-
72987
- this.boundMouseClickHandler = mouseClickHandler.bind(this);
72988
-
72989
- this.button.addEventListener('click', this.boundMouseClickHandler);
72990
-
72991
- this.setVisibility(true);
72992
-
72993
- }
72994
-
72995
- setMultiTrackSelection(enableMultiTrackSelection) {
72996
- this.enableMultiTrackSelection = enableMultiTrackSelection;
72997
- for (const trackView of this.browser.trackViews) {
72998
- if (false === multiTrackSelectExclusionTypes.has(trackView.track.type)) {
72999
- trackView.setTrackSelectionState(trackView.axis, this.enableMultiTrackSelection);
73000
-
73001
- // If closing the selection boxes set track selected property to false
73002
- if (!this.enableMultiTrackSelection) {
73003
- trackView.track.selected = false;
73004
- }
73005
- }
73006
- }
73007
- this.setState(this.enableMultiTrackSelection);
73008
-
73009
- // If enableMultiTrackSelection is false hide Overlay button
73010
- if (false === this.enableMultiTrackSelection) {
73011
- this.browser.overlayTrackButton.setVisibility(false);
73012
- }
73013
- }
73014
- }
73015
-
73016
73630
  /**
73017
73631
  * Chromosome alias source backed by a UCSC bigbed file
73018
73632
  *
@@ -73032,6 +73646,13 @@ class ChromAliasBB {
73032
73646
  this.reader = new BWReader(config, genome);
73033
73647
  }
73034
73648
 
73649
+ async preload(chrNames) {
73650
+ await this.reader.preload();
73651
+ for(let nm of chrNames) {
73652
+ await this.search(nm);
73653
+ }
73654
+ }
73655
+
73035
73656
  /**
73036
73657
  * Return the cached canonical chromosome name for the alias. If none found return the alias.
73037
73658
  *
@@ -73107,6 +73728,10 @@ class ChromAliasFile {
73107
73728
  this.genome = genome;
73108
73729
  }
73109
73730
 
73731
+ async preload() {
73732
+ return this.loadAliases();
73733
+ }
73734
+
73110
73735
  /**
73111
73736
  * Return the canonical chromosome name for the alias. If none found return the alias
73112
73737
  *
@@ -73159,6 +73784,9 @@ class ChromAliasFile {
73159
73784
  aliasRecord[key] = tokens[i];
73160
73785
  this.aliasRecordCache.set(tokens[i], aliasRecord);
73161
73786
  }
73787
+
73788
+ this.aliasRecordCache.set(chr.toLowerCase(), aliasRecord);
73789
+ this.aliasRecordCache.set(chr.toUpperCase(), aliasRecord);
73162
73790
  }
73163
73791
  }
73164
73792
  }
@@ -73330,6 +73958,9 @@ class ChromAliasDefaults {
73330
73958
  this.update(id, chromosomeNames);
73331
73959
  }
73332
73960
 
73961
+ async preload() {
73962
+ // no-op
73963
+ }
73333
73964
 
73334
73965
  /**
73335
73966
  * Return the canonical chromosome name for the alias. If none found return the alias
@@ -73431,6 +74062,8 @@ class ChromAliasDefaults {
73431
74062
  } else if (Number.isInteger(Number(name))) {
73432
74063
  record["ucsc"] = "chr" + name;
73433
74064
  }
74065
+
74066
+
73434
74067
  }
73435
74068
  }
73436
74069
 
@@ -73438,7 +74071,10 @@ class ChromAliasDefaults {
73438
74071
  for (let a of Object.values(rec)) {
73439
74072
  this.aliasRecordCache.set(a, rec);
73440
74073
  }
74074
+ this.aliasRecordCache.set(rec.chr.toLowerCase(), rec);
74075
+ this.aliasRecordCache.set(rec.chr.toUpperCase(), rec);
73441
74076
  }
74077
+
73442
74078
  }
73443
74079
  }
73444
74080
 
@@ -73506,7 +74142,7 @@ class Genome {
73506
74142
 
73507
74143
  if (config.chromAliasBbURL) {
73508
74144
  this.chromAlias = new ChromAliasBB(config.chromAliasBbURL, Object.assign({}, config), this);
73509
- if(!this.chromosomeNames) {
74145
+ if (!this.chromosomeNames) {
73510
74146
  this.chromosomeNames = await this.chromAlias.getChromosomeNames();
73511
74147
  }
73512
74148
  } else if (config.aliasURL) {
@@ -73517,17 +74153,17 @@ class Genome {
73517
74153
 
73518
74154
  if (config.cytobandBbURL) {
73519
74155
  this.cytobandSource = new CytobandFileBB(config.cytobandBbURL, Object.assign({}, config), this);
73520
- if(!this.chromosomeNames) {
74156
+ if (!this.chromosomeNames) {
73521
74157
  this.chromosomeNames = await this.cytobandSource.getChromosomeNames();
73522
74158
  }
73523
74159
  } else if (config.cytobandURL) {
73524
74160
  this.cytobandSource = new CytobandFile(config.cytobandURL, Object.assign({}, config));
73525
- if(!this.chromosomeNames) {
74161
+ if (!this.chromosomeNames) {
73526
74162
  this.chromosomeNames = await this.cytobandSource.getChromosomeNames();
73527
74163
  }
73528
- if(this.chromosomes.size === 0) {
74164
+ if (this.chromosomes.size === 0) {
73529
74165
  const c = await this.cytobandSource.getChromosomes();
73530
- for(let chromosome of c) {
74166
+ for (let chromosome of c) {
73531
74167
  this.chromosomes.set(c.name, c);
73532
74168
  }
73533
74169
  }
@@ -73545,6 +74181,7 @@ class Genome {
73545
74181
  } else {
73546
74182
  this.#wgChromosomeNames = trimSmallChromosomes(this.chromosomes);
73547
74183
  }
74184
+ await this.chromAlias.preload(this.#wgChromosomeNames);
73548
74185
  }
73549
74186
 
73550
74187
  // Optionally create the psuedo chromosome "all" to support whole genome view
@@ -73611,15 +74248,15 @@ class Genome {
73611
74248
  async loadChromosome(chr) {
73612
74249
 
73613
74250
  if (this.chromAlias) {
73614
- const chromAliasRecord = await this.chromAlias.search(chr);
73615
- if(chromAliasRecord) {
74251
+ const chromAliasRecord = await this.chromAlias.search(chr);
74252
+ if (chromAliasRecord) {
73616
74253
  chr = chromAliasRecord.chr;
73617
74254
  }
73618
74255
  }
73619
74256
 
73620
74257
  if (!this.chromosomes.has(chr)) {
73621
74258
  let chromosome;
73622
- const sequenceRecord = await this.sequence.getSequenceRecord(chr);
74259
+ const sequenceRecord = await this.sequence.getSequenceRecord(chr);
73623
74260
  if (sequenceRecord) {
73624
74261
  chromosome = new Chromosome(chr, 0, sequenceRecord.bpLength);
73625
74262
  }
@@ -73629,6 +74266,7 @@ class Genome {
73629
74266
 
73630
74267
  return this.chromosomes.get(chr)
73631
74268
  }
74269
+
73632
74270
  async getAliasRecord(chr) {
73633
74271
  if (this.chromAlias) {
73634
74272
  return this.chromAlias.search(chr)
@@ -73648,7 +74286,7 @@ class Genome {
73648
74286
  }
73649
74287
 
73650
74288
  get wgChromosomeNames() {
73651
- return this.#wgChromosomeNames ? this.#wgChromosomeNames.slice() : undefined
74289
+ return this.#wgChromosomeNames ? this.#wgChromosomeNames.slice() : undefined
73652
74290
  }
73653
74291
 
73654
74292
  get showChromosomeWidget() {
@@ -73752,7 +74390,7 @@ class Genome {
73752
74390
  * @param end
73753
74391
  */
73754
74392
  getSequenceInterval(chr, start, end) {
73755
- if(typeof this.sequence.getSequenceInterval === 'function') {
74393
+ if (typeof this.sequence.getSequenceInterval === 'function') {
73756
74394
  return this.sequence.getSequenceInterval(chr, start, end)
73757
74395
  } else {
73758
74396
  return undefined
@@ -73800,7 +74438,7 @@ function generateGenomeID(config) {
73800
74438
  }
73801
74439
  }
73802
74440
 
73803
- var igvCss = '.igv-ui-dropdown {\n cursor: default;\n position: absolute;\n top: 0;\n left: 0;\n z-index: 2048;\n border-color: #7F7F7F;\n border-style: solid;\n border-width: 1px;\n font-family: \"Open Sans\", sans-serif;\n font-size: small;\n font-weight: 400;\n background-color: white;\n}\n.igv-ui-dropdown > div {\n overflow-y: auto;\n overflow-x: hidden;\n background-color: white;\n}\n.igv-ui-dropdown > div > div {\n padding: 4px;\n width: 100%;\n overflow-x: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n border-bottom-color: #7F7F7F;\n border-bottom-style: solid;\n border-bottom-width: 1px;\n background-color: white;\n}\n.igv-ui-dropdown > div > div:last-child {\n border-bottom-color: transparent;\n border-bottom-width: 0;\n}\n.igv-ui-dropdown > div > div:hover {\n cursor: pointer;\n background-color: rgba(0, 0, 0, 0.04);\n}\n\n.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}\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-width: 0;\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}\n.igv-ui-popover > div:first-child > div:first-child {\n margin-left: 4px;\n}\n.igv-ui-popover > div:first-child > div:last-child {\n margin-right: 4px;\n height: 12px;\n width: 12px;\n color: #7F7F7F;\n}\n.igv-ui-popover > div:first-child > div:last-child:hover {\n cursor: pointer;\n color: #444;\n}\n.igv-ui-popover > div:last-child {\n user-select: text;\n overflow-y: auto;\n overflow-x: hidden;\n max-height: 400px;\n max-width: 800px;\n background-color: white;\n border-bottom-width: 0;\n border-bottom-left-radius: 4px;\n border-bottom-right-radius: 4px;\n}\n.igv-ui-popover > div:last-child > div {\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}\n.igv-ui-popover > div:last-child > div > span {\n font-weight: bolder;\n}\n.igv-ui-popover > div:last-child hr {\n width: 100%;\n}\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}\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}\n.igv-ui-alert-dialog-container > div:first-child div:first-child {\n padding-left: 8px;\n}\n.igv-ui-alert-dialog-container .igv-ui-alert-dialog-body {\n -webkit-user-select: text;\n -moz-user-select: text;\n -ms-user-select: text;\n user-select: text;\n color: #373737;\n width: 100%;\n height: calc(100% - 24px - 64px);\n overflow-y: scroll;\n}\n.igv-ui-alert-dialog-container .igv-ui-alert-dialog-body .igv-ui-alert-dialog-body-copy {\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}\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}\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}\n.igv-ui-alert-dialog-container > div:last-child div:hover {\n cursor: pointer;\n border-color: #25597f;\n background-color: #25597f;\n}\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\n.igv-ui-color-swatch:hover {\n border-color: dimgray;\n}\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}\n.igv-ui-colorpicker-menu-close-button i.fa {\n display: block;\n margin-left: 4px;\n margin-right: 4px;\n color: #5f5f5f;\n}\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\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: fit-content;\n padding-bottom: 16px;\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}\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}\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}\n.igv-ui-generic-dialog-container .igv-ui-generic-dialog-header div:hover {\n cursor: pointer;\n color: #444;\n}\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}\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}\n.igv-ui-generic-dialog-container .igv-ui-generic-dialog-label-input > div {\n width: fit-content;\n height: 100%;\n font-size: 16px;\n text-align: right;\n padding-right: 8px;\n background-color: white;\n}\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}\n.igv-ui-generic-dialog-container .igv-ui-generic-dialog-label-input input {\n width: 50%;\n font-size: 16px;\n}\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}\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}\n.igv-ui-generic-dialog-container .igv-ui-generic-dialog-input input {\n font-size: 16px;\n}\n.igv-ui-generic-dialog-container .igv-ui-generic-dialog-input input[type=range] {\n width: 70%;\n -webkit-appearance: none;\n background: linear-gradient(90deg, white, black);\n outline: none;\n margin: 0;\n}\n.igv-ui-generic-dialog-container .igv-ui-generic-dialog-input output {\n display: block;\n height: 100%;\n width: 20%;\n font-size: 16px;\n}\n.igv-ui-generic-dialog-container .igv-ui-generic-dialog-ok-cancel {\n width: 100%;\n height: 28px;\n padding-top: 16px;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: space-around;\n align-items: center;\n}\n.igv-ui-generic-dialog-container .igv-ui-generic-dialog-ok-cancel > div {\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}\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}\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}\n.igv-ui-generic-dialog-container .igv-ui-generic-dialog-ok-cancel > div:first-child:hover {\n cursor: pointer;\n background-color: #3b5c7f;\n}\n.igv-ui-generic-dialog-container .igv-ui-generic-dialog-ok-cancel > div:last-child:hover {\n cursor: pointer;\n background-color: #7f7f7f;\n}\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}\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}\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\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}\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}\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}\n.igv-ui-dialog .igv-ui-dialog-header div:hover {\n cursor: pointer;\n color: #444;\n}\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}\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}\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}\n.igv-ui-dialog .igv-ui-dialog-ok-cancel div:first-child {\n background-color: #5ea4e0;\n}\n.igv-ui-dialog .igv-ui-dialog-ok-cancel div:last-child {\n background-color: #c4c4c4;\n}\n.igv-ui-dialog .igv-ui-dialog-ok-cancel div:first-child:hover {\n cursor: pointer;\n background-color: #3b5c7f;\n}\n.igv-ui-dialog .igv-ui-dialog-ok-cancel div:last-child:hover {\n cursor: pointer;\n background-color: #7f7f7f;\n}\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}\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}\n.igv-ui-dialog .igv-ui-dialog-ok div:hover {\n cursor: pointer;\n background-color: #25597f;\n}\n\n.igv-ui-panel, .igv-ui-panel-row, .igv-ui-panel-column {\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\n.igv-ui-panel-column {\n display: flex;\n flex-direction: column;\n}\n\n.igv-ui-panel-row {\n display: flex;\n flex-direction: row;\n}\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\n.igv-ui-table {\n background-color: white;\n}\n\n.igv-ui-table thead {\n position: sticky;\n top: 0;\n}\n\n.igv-ui-table th {\n text-align: left;\n}\n\n.igv-ui-table td {\n padding-right: 20px;\n}\n\n.igv-ui-table tr:hover {\n background-color: lightblue;\n}\n\n.igv-ui-center-fixed {\n left: 50%;\n top: 50%;\n transform: translate(-50%, -50%);\n}\n\n.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}\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}\n.igv-navbar .igv-navbar-left-container .igv-logo {\n width: 34px;\n height: 32px;\n margin-right: 8px;\n}\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}\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}\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}\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}\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}\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: 240px;\n height: 22px;\n line-height: 22px;\n}\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}\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 display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: center;\n align-items: center;\n}\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}\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}\n.igv-navbar .igv-navbar-right-container .igv-navbar-toggle-button-container {\n position: relative;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: flex-end;\n align-items: center;\n}\n.igv-navbar .igv-navbar-right-container .igv-navbar-toggle-button-container-hidden {\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: center;\n height: 100%;\n}\n.igv-navbar .igv-navbar-right-container .igv-zoom-widget {\n color: #737373;\n font-size: 18px;\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}\n.igv-navbar .igv-navbar-right-container .igv-zoom-widget div {\n cursor: pointer;\n margin-left: unset;\n margin-right: unset;\n}\n.igv-navbar .igv-navbar-right-container .igv-zoom-widget div:first-child {\n height: 20px;\n width: 20px;\n margin-left: unset;\n margin-right: 4px;\n}\n.igv-navbar .igv-navbar-right-container .igv-zoom-widget div:last-child {\n height: 20px;\n width: 20px;\n margin-left: 4px;\n margin-right: unset;\n}\n.igv-navbar .igv-navbar-right-container .igv-zoom-widget div:nth-child(even) {\n display: block;\n height: fit-content;\n}\n.igv-navbar .igv-navbar-right-container .igv-zoom-widget input {\n display: block;\n width: 125px;\n}\n.igv-navbar .igv-navbar-right-container .igv-zoom-widget svg {\n display: block;\n}\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}\n.igv-navbar .igv-navbar-right-container .igv-zoom-widget-900 div {\n cursor: pointer;\n margin-left: unset;\n margin-right: unset;\n}\n.igv-navbar .igv-navbar-right-container .igv-zoom-widget-900 div:first-child {\n height: 20px;\n width: 20px;\n margin-left: unset;\n margin-right: 4px;\n}\n.igv-navbar .igv-navbar-right-container .igv-zoom-widget-900 div:last-child {\n height: 20px;\n width: 20px;\n margin-left: 4px;\n margin-right: unset;\n}\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}\n.igv-navbar .igv-navbar-right-container .igv-zoom-widget-900 input {\n width: 0;\n height: 0;\n display: none;\n}\n.igv-navbar .igv-navbar-right-container .igv-zoom-widget-900 svg {\n display: block;\n}\n.igv-navbar .igv-navbar-right-container .igv-zoom-widget-hidden {\n display: none;\n}\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\n.igv-navbar-button:hover {\n cursor: pointer;\n}\n\n.igv-navbar-button-clicked {\n color: white;\n background-color: #737373;\n}\n\n.igv-navbar-icon-button {\n cursor: pointer;\n position: relative;\n width: 24px;\n height: 24px;\n margin-left: 4px;\n margin-right: 4px;\n border: none;\n background-size: contain;\n background-repeat: no-repeat;\n background-position: center;\n}\n.igv-navbar-icon-button > div:first-child {\n z-index: 512;\n position: absolute;\n top: 36px;\n left: -18px;\n width: 24px;\n height: 24px;\n border: none;\n background-size: contain;\n background-repeat: no-repeat;\n background-position: center;\n}\n.igv-navbar-icon-button > div:last-child {\n z-index: 512;\n position: absolute;\n top: 36px;\n left: 18px;\n width: 24px;\n height: 24px;\n border: none;\n background-size: contain;\n background-repeat: no-repeat;\n background-position: center;\n}\n\n.igv-navbar-text-button {\n cursor: pointer;\n position: relative;\n margin-left: 2px;\n margin-right: 2px;\n border: none;\n display: flex;\n justify-content: center;\n align-items: center;\n}\n.igv-navbar-text-button > div:nth-child(2) {\n z-index: 512;\n position: absolute;\n top: 36px;\n left: 0;\n width: 38px;\n height: 18px;\n border: none;\n background-size: contain;\n background-repeat: no-repeat;\n background-position: center;\n}\n.igv-navbar-text-button > div:nth-child(3) {\n z-index: 512;\n position: absolute;\n top: 36px;\n left: 42px;\n width: 38px;\n height: 18px;\n border: none;\n background-size: contain;\n background-repeat: no-repeat;\n background-position: center;\n}\n\n#igv-text-button-label {\n text-anchor: middle;\n dominant-baseline: middle;\n}\n\n.igv-navbar-text-button-svg-inactive rect {\n stroke: #737373;\n fill: white;\n}\n.igv-navbar-text-button-svg-inactive text {\n fill: #737373;\n}\n.igv-navbar-text-button-svg-inactive tspan {\n dominant-baseline: middle;\n}\n\n.igv-navbar-text-button-svg-hover rect {\n stroke: #737373;\n fill: #737373;\n}\n.igv-navbar-text-button-svg-hover text {\n fill: white;\n}\n.igv-navbar-text-button-svg-hover tspan {\n dominant-baseline: middle;\n}\n\n#igv-save-svg-group rect {\n stroke: #737373;\n fill: white;\n}\n#igv-save-svg-group text {\n fill: #737373;\n}\n\n#igv-save-svg-group:hover rect {\n stroke: #737373;\n fill: #737373;\n}\n#igv-save-svg-group:hover text {\n fill: white;\n}\n\n#igv-save-png-group rect {\n stroke: #737373;\n fill: white;\n}\n#igv-save-png-group text {\n fill: #737373;\n}\n\n#igv-save-png-group:hover rect {\n stroke: #737373;\n fill: #737373;\n}\n#igv-save-png-group:hover text {\n fill: white;\n}\n\n.igv-zoom-in-notice-container {\n z-index: 256;\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}\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\n.igv-zoom-in-notice {\n position: absolute;\n top: 10px;\n left: 50%;\n}\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\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\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: 12px;\n height: 12px;\n color: #666666;\n background-color: white;\n z-index: 1000;\n}\n.igv-multi-locus-close-button > svg {\n vertical-align: top;\n}\n\n.igv-multi-locus-close-button:hover {\n cursor: pointer;\n color: #434343;\n}\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: 12px;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: center;\n align-items: center;\n}\n.igv-multi-locus-ruler-label > div {\n font-family: \"Open Sans\", sans-serif;\n font-size: 12px;\n color: rgb(16, 16, 16);\n background-color: white;\n}\n.igv-multi-locus-ruler-label > div {\n cursor: pointer;\n}\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}\n.igv-multi-locus-ruler-label-square-dot > div:first-child {\n width: 14px;\n height: 14px;\n}\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: rgb(16, 16, 16);\n}\n\n.igv-ruler-sweeper {\n display: none;\n pointer-events: none;\n position: absolute;\n top: 26px;\n bottom: 0;\n left: 0;\n width: 0;\n z-index: 99999;\n background-color: rgba(68, 134, 247, 0.25);\n}\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}\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\n.igv-track-label {\n position: absolute;\n left: 8px;\n top: 8px;\n width: auto;\n height: auto;\n max-width: 50%;\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\n.igv-track-label:hover,\n.igv-track-label:focus,\n.igv-track-label:active {\n background-color: #e8e8e8;\n}\n\n.igv-track-label-popup-shim {\n padding-left: 8px;\n padding-right: 8px;\n padding-top: 4px;\n}\n\n.igv-center-line {\n display: none;\n pointer-events: none;\n position: absolute;\n top: 0;\n bottom: 0;\n left: 50%;\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\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\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\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: 32;\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\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: 32;\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\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}\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}\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}\n.igv-user-feedback div:first-child div:first-child {\n left: 8px;\n}\n.igv-user-feedback div:first-child div:last-child {\n cursor: pointer;\n right: 8px;\n}\n.igv-user-feedback div:last-child {\n width: 100%;\n height: calc(100% - 24px);\n border-width: 0;\n}\n.igv-user-feedback div:last-child div {\n width: auto;\n height: auto;\n margin: 8px;\n}\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}\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}\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}\n.igv-generic-dialog-container .igv-generic-dialog-header div:hover {\n cursor: pointer;\n color: #444;\n}\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}\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}\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}\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}\n.igv-generic-dialog-container .igv-generic-dialog-label-input input {\n width: 50%;\n font-size: 16px;\n}\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}\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}\n.igv-generic-dialog-container .igv-generic-dialog-input input {\n font-size: 16px;\n}\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}\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}\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}\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}\n.igv-generic-dialog-container .igv-generic-dialog-ok-cancel div:first-child:hover {\n cursor: pointer;\n background-color: #3b5c7f;\n}\n.igv-generic-dialog-container .igv-generic-dialog-ok-cancel div:last-child:hover {\n cursor: pointer;\n background-color: #7f7f7f;\n}\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}\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}\n.igv-generic-dialog-container .igv-generic-dialog-ok div:hover {\n cursor: pointer;\n background-color: #25597f;\n}\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}\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}\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\n.igv-menu-popup {\n position: absolute;\n top: 0;\n left: 0;\n width: max-content;\n max-width: 400px;\n z-index: 512;\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}\n.igv-menu-popup > div:not(:first-child) {\n width: 100%;\n}\n.igv-menu-popup > div:not(:first-child) > div {\n background: white;\n}\n.igv-menu-popup > div:not(:first-child) > div.context-menu {\n padding-left: 4px;\n padding-right: 4px;\n}\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}\n.igv-menu-popup > div:not(:first-child) > div:hover {\n background: #efefef;\n}\n\n.igv-menu-popup-shim {\n padding-left: 8px;\n padding-right: 8px;\n padding-bottom: 1px;\n padding-top: 1px;\n}\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}\n.igv-menu-popup-header div {\n margin-right: 4px;\n height: 12px;\n width: 12px;\n color: #7F7F7F;\n}\n.igv-menu-popup-header div:hover {\n cursor: pointer;\n color: #444;\n}\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}\n.igv-menu-popup-check-container div {\n padding-top: 2px;\n padding-left: 8px;\n}\n.igv-menu-popup-check-container div:first-child {\n position: relative;\n width: 12px;\n height: 12px;\n}\n.igv-menu-popup-check-container div:first-child svg {\n position: absolute;\n width: 12px;\n height: 12px;\n}\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}\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}\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}\n.igv-user-feedback div:first-child div:first-child {\n left: 8px;\n}\n.igv-user-feedback div:first-child div:last-child {\n cursor: pointer;\n right: 8px;\n}\n.igv-user-feedback div:last-child {\n width: 100%;\n height: calc(100% - 24px);\n border-width: 0;\n}\n.igv-user-feedback div:last-child div {\n width: auto;\n height: auto;\n margin: 8px;\n}\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}\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: rgb(255, 255, 255);\n animation: spin 1s ease-in-out infinite;\n -webkit-animation: spin 1s ease-in-out infinite;\n}\n\n@keyframes spin {\n to {\n -webkit-transform: rotate(360deg);\n transform: rotate(360deg);\n }\n}\n@-webkit-keyframes spin {\n to {\n -webkit-transform: rotate(360deg);\n transform: rotate(360deg);\n }\n}\n.igv-roi-menu {\n position: absolute;\n z-index: 512;\n font-family: \"Open Sans\", sans-serif;\n font-size: small;\n font-weight: 400;\n color: #4b4b4b;\n background-color: white;\n width: 192px;\n border-radius: 4px;\n border-color: #7F7F7F;\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: stretch;\n}\n.igv-roi-menu > div:first-child {\n height: 24px;\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}\n.igv-roi-menu > div:first-child > div {\n margin-right: 4px;\n height: 12px;\n width: 12px;\n color: #7F7F7F;\n}\n.igv-roi-menu > div:first-child > div:hover {\n cursor: pointer;\n color: #444;\n}\n.igv-roi-menu > div:last-child {\n background-color: white;\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: 0;\n display: flex;\n flex-direction: column;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: stretch;\n text-align: start;\n vertical-align: middle;\n}\n.igv-roi-menu > div:last-child > div {\n height: 24px;\n padding-left: 4px;\n border-bottom-style: solid;\n border-bottom-width: thin;\n border-bottom-color: #7f7f7f;\n}\n.igv-roi-menu > div:last-child > div:not(:first-child):hover {\n cursor: pointer;\n background-color: rgba(127, 127, 127, 0.1);\n}\n.igv-roi-menu > div:last-child div:first-child {\n font-style: italic;\n text-align: center;\n padding-right: 4px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.igv-roi-menu > div:last-child > div:last-child {\n border-bottom-width: 0;\n border-bottom-color: transparent;\n}\n\n.igv-roi-placeholder {\n font-style: normal;\n color: rgba(75, 75, 75, 0.6);\n}\n\n.igv-roi-table {\n position: absolute;\n z-index: 1024;\n display: flex;\n flex-flow: column;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: stretch;\n resize: both;\n overflow: hidden;\n width: min-content;\n max-width: 1600px;\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: 12px;\n font-weight: 400;\n background-color: white;\n cursor: default;\n}\n.igv-roi-table > div {\n height: 24px;\n font-size: 14px;\n text-align: start;\n vertical-align: middle;\n line-height: 24px;\n}\n.igv-roi-table > div:first-child {\n border-color: transparent;\n border-top-left-radius: 4px;\n border-top-right-radius: 4px;\n border-top-width: 0;\n border-bottom-color: #7f7f7f;\n border-bottom-style: solid;\n border-bottom-width: thin;\n background-color: #eee;\n cursor: move;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: space-between;\n align-items: center;\n}\n.igv-roi-table > div:first-child > div:first-child {\n text-align: center;\n white-space: nowrap;\n text-overflow: ellipsis;\n overflow: hidden;\n margin-left: 4px;\n margin-right: 4px;\n width: calc(100% - 4px - 12px);\n}\n.igv-roi-table > div:first-child > div:last-child {\n margin-right: 4px;\n margin-bottom: 2px;\n height: 12px;\n width: 12px;\n color: #7f7f7f;\n}\n.igv-roi-table > div:first-child > div:last-child > svg {\n display: block;\n}\n.igv-roi-table > div:first-child > div:last-child:hover {\n cursor: pointer;\n color: #444;\n}\n.igv-roi-table > .igv-roi-table-description {\n padding: 4px;\n margin-left: 4px;\n word-break: break-all;\n overflow-y: auto;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n background-color: transparent;\n}\n.igv-roi-table > .igv-roi-table-goto-explainer {\n margin-top: 5px;\n margin-left: 4px;\n color: #7F7F7F;\n font-style: italic;\n height: 24px;\n border-top: solid lightgray;\n background-color: transparent;\n}\n.igv-roi-table > .igv-roi-table-column-titles {\n height: 24px;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: stretch;\n align-items: stretch;\n padding-right: 16px;\n background-color: white;\n border-top-color: #7f7f7f;\n border-top-style: solid;\n border-top-width: thin;\n border-bottom-color: #7f7f7f;\n border-bottom-style: solid;\n border-bottom-width: thin;\n}\n.igv-roi-table > .igv-roi-table-column-titles > div {\n font-size: 14px;\n vertical-align: middle;\n line-height: 24px;\n text-align: left;\n margin-left: 4px;\n height: 24px;\n overflow: hidden;\n text-overflow: ellipsis;\n border-right-color: #7f7f7f;\n border-right-style: solid;\n border-right-width: thin;\n}\n.igv-roi-table > .igv-roi-table-column-titles > div:last-child {\n border-right: unset;\n}\n.igv-roi-table > .igv-roi-table-row-container {\n display: flex;\n flex-flow: column;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: stretch;\n overflow: auto;\n height: 360px;\n flex: 1 1 auto;\n background-color: transparent;\n}\n.igv-roi-table > .igv-roi-table-row-container > .igv-roi-table-row {\n height: 24px;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: stretch;\n align-items: stretch;\n}\n.igv-roi-table > .igv-roi-table-row-container > .igv-roi-table-row > div {\n font-size: 14px;\n vertical-align: middle;\n line-height: 24px;\n text-align: left;\n margin-left: 4px;\n height: 24px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n border-right-color: transparent;\n border-right-style: solid;\n border-right-width: thin;\n}\n.igv-roi-table > .igv-roi-table-row-container > .igv-roi-table-row > div:last-child {\n border-right: unset;\n}\n.igv-roi-table > .igv-roi-table-row-container > .igv-roi-table-row-hover {\n background-color: rgba(0, 0, 0, 0.04);\n}\n.igv-roi-table > div:last-child {\n min-height: 32px;\n height: 32px;\n line-height: 32px;\n border-top-color: #7f7f7f;\n border-top-style: solid;\n border-top-width: thin;\n border-bottom-color: transparent;\n border-bottom-left-radius: 4px;\n border-bottom-right-radius: 4px;\n border-bottom-width: 0;\n background-color: #eee;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: space-around;\n align-items: center;\n}\n\n.igv-roi-table-row-selected {\n background-color: rgba(0, 0, 0, 0.125);\n}\n\n.igv-roi-table-button {\n cursor: pointer;\n height: 20px;\n user-select: none;\n line-height: 20px;\n text-align: center;\n vertical-align: middle;\n font-family: \"Open Sans\", sans-serif;\n font-size: 13px;\n font-weight: 400;\n color: black;\n padding-left: 6px;\n padding-right: 6px;\n background-color: rgb(239, 239, 239);\n border-color: black;\n border-style: solid;\n border-width: thin;\n border-radius: 3px;\n}\n\n.igv-roi-table-button:hover {\n font-weight: 400;\n background-color: rgba(0, 0, 0, 0.13);\n}\n\n.igv-roi-region {\n z-index: 64;\n position: absolute;\n top: 0;\n bottom: 0;\n pointer-events: none;\n overflow: visible;\n margin-top: 66px;\n display: flex;\n flex-direction: column;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: stretch;\n}\n.igv-roi-region > div {\n position: relative;\n width: 100%;\n height: 8px;\n pointer-events: auto;\n}\n\n.igv-roi-menu-row {\n height: 24px;\n padding-left: 8px;\n font-size: small;\n text-align: start;\n vertical-align: middle;\n line-height: 24px;\n background-color: white;\n}\n\n.igv-roi-menu-row-edit-description {\n width: -webkit-fill-available;\n font-size: small;\n text-align: start;\n vertical-align: middle;\n background-color: white;\n padding-left: 4px;\n padding-right: 4px;\n padding-bottom: 4px;\n display: flex;\n flex-direction: column;\n flex-wrap: nowrap;\n justify-content: stretch;\n align-items: stretch;\n}\n.igv-roi-menu-row-edit-description > label {\n margin-left: 2px;\n margin-bottom: 0;\n display: block;\n width: -webkit-fill-available;\n}\n.igv-roi-menu-row-edit-description > input {\n display: block;\n margin-left: 2px;\n margin-right: 2px;\n margin-bottom: 1px;\n width: -webkit-fill-available;\n}\n\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 min-height: 160px;\n}\n\n.igv-viewport {\n position: relative;\n margin-top: 5px;\n line-height: 1;\n overflow-x: hidden;\n overflow-y: hidden;\n}\n\n.igv-viewport-content {\n position: relative;\n width: 100%;\n}\n.igv-viewport-content > canvas {\n position: relative;\n display: block;\n}\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\n.igv-column-shim {\n width: 1px;\n margin-left: 2px;\n margin-right: 2px;\n background-color: #545453;\n}\n\n.igv-axis-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 width: 50px;\n}\n.igv-axis-column > div {\n position: relative;\n margin-top: 5px;\n width: 100%;\n}\n.igv-axis-column > div > div {\n z-index: 512;\n position: absolute;\n top: 8px;\n left: 8px;\n width: fit-content;\n height: fit-content;\n background-color: transparent;\n display: grid;\n align-items: start;\n justify-items: center;\n}\n.igv-axis-column > div > div > input {\n display: block;\n margin: unset;\n cursor: pointer;\n}\n\n.igv-column {\n position: relative;\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\n.igv-sample-info-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\n.igv-sample-name-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\n.igv-scrollbar-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 width: 14px;\n}\n.igv-scrollbar-column > div {\n position: relative;\n margin-top: 5px;\n width: 14px;\n}\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}\n.igv-scrollbar-column > div > div:hover {\n background-color: #c4c4c4;\n}\n\n.igv-track-drag-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 width: 12px;\n background-color: white;\n}\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}\n.igv-track-drag-column .igv-track-drag-handle-color {\n background-color: #c4c4c4;\n}\n.igv-track-drag-column .igv-track-drag-handle-hover-color {\n background-color: #787878;\n}\n.igv-track-drag-column .igv-track-drag-handle-selected-color {\n background-color: #0963fa;\n}\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\n.igv-gear-menu-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 width: 28px;\n}\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}\n.igv-gear-menu-column > div > div {\n position: relative;\n margin-top: 4px;\n width: 16px;\n height: 16px;\n color: #7F7F7F;\n}\n.igv-gear-menu-column > div > div:hover {\n cursor: pointer;\n color: #444;\n}\n\n/*# sourceMappingURL=igv.css.map */\n';
74441
+ var igvCss = '.igv-ui-dropdown {\n cursor: default;\n position: absolute;\n top: 0;\n left: 0;\n z-index: 2048;\n border-color: #7F7F7F;\n border-style: solid;\n border-width: 1px;\n font-family: \"Open Sans\", sans-serif;\n font-size: small;\n font-weight: 400;\n background-color: white;\n}\n.igv-ui-dropdown > div {\n overflow-y: auto;\n overflow-x: hidden;\n background-color: white;\n}\n.igv-ui-dropdown > div > div {\n padding: 4px;\n width: 100%;\n overflow-x: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n border-bottom-color: #7F7F7F;\n border-bottom-style: solid;\n border-bottom-width: 1px;\n background-color: white;\n}\n.igv-ui-dropdown > div > div:last-child {\n border-bottom-color: transparent;\n border-bottom-width: 0;\n}\n.igv-ui-dropdown > div > div:hover {\n cursor: pointer;\n background-color: rgba(0, 0, 0, 0.04);\n}\n\n.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}\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-width: 0;\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}\n.igv-ui-popover > div:first-child > div:first-child {\n margin-left: 4px;\n}\n.igv-ui-popover > div:first-child > div:last-child {\n margin-right: 4px;\n height: 12px;\n width: 12px;\n color: #7F7F7F;\n}\n.igv-ui-popover > div:first-child > div:last-child:hover {\n cursor: pointer;\n color: #444;\n}\n.igv-ui-popover > div:last-child {\n user-select: text;\n overflow-y: auto;\n overflow-x: hidden;\n max-height: 400px;\n max-width: 800px;\n background-color: white;\n border-bottom-width: 0;\n border-bottom-left-radius: 4px;\n border-bottom-right-radius: 4px;\n}\n.igv-ui-popover > div:last-child > div {\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}\n.igv-ui-popover > div:last-child > div > span {\n font-weight: bolder;\n}\n.igv-ui-popover > div:last-child hr {\n width: 100%;\n}\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}\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}\n.igv-ui-alert-dialog-container > div:first-child div:first-child {\n padding-left: 8px;\n}\n.igv-ui-alert-dialog-container .igv-ui-alert-dialog-body {\n -webkit-user-select: text;\n -moz-user-select: text;\n -ms-user-select: text;\n user-select: text;\n color: #373737;\n width: 100%;\n height: calc(100% - 24px - 64px);\n overflow-y: scroll;\n}\n.igv-ui-alert-dialog-container .igv-ui-alert-dialog-body .igv-ui-alert-dialog-body-copy {\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}\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}\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}\n.igv-ui-alert-dialog-container > div:last-child div:hover {\n cursor: pointer;\n border-color: #25597f;\n background-color: #25597f;\n}\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\n.igv-ui-color-swatch:hover {\n border-color: dimgray;\n}\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}\n.igv-ui-colorpicker-menu-close-button i.fa {\n display: block;\n margin-left: 4px;\n margin-right: 4px;\n color: #5f5f5f;\n}\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\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: fit-content;\n padding-bottom: 16px;\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}\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}\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}\n.igv-ui-generic-dialog-container .igv-ui-generic-dialog-header div:hover {\n cursor: pointer;\n color: #444;\n}\n.igv-ui-generic-dialog-container .igv-ui-generic-dialog-one-liner {\n color: #373737;\n width: 95%;\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}\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}\n.igv-ui-generic-dialog-container .igv-ui-generic-dialog-label-input > div {\n width: fit-content;\n height: 100%;\n font-size: 16px;\n text-align: right;\n padding-right: 8px;\n background-color: white;\n}\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}\n.igv-ui-generic-dialog-container .igv-ui-generic-dialog-label-input input {\n width: 50%;\n font-size: 16px;\n}\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}\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}\n.igv-ui-generic-dialog-container .igv-ui-generic-dialog-input input {\n font-size: 16px;\n}\n.igv-ui-generic-dialog-container .igv-ui-generic-dialog-input input[type=range] {\n width: 70%;\n -webkit-appearance: none;\n background: linear-gradient(90deg, white, black);\n outline: none;\n margin: 0;\n}\n.igv-ui-generic-dialog-container .igv-ui-generic-dialog-input output {\n display: block;\n height: 100%;\n width: 20%;\n font-size: 16px;\n}\n.igv-ui-generic-dialog-container .igv-ui-generic-dialog-ok-cancel {\n width: 100%;\n height: 28px;\n padding-top: 16px;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: space-around;\n align-items: center;\n}\n.igv-ui-generic-dialog-container .igv-ui-generic-dialog-ok-cancel > div {\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}\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}\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}\n.igv-ui-generic-dialog-container .igv-ui-generic-dialog-ok-cancel > div:first-child:hover {\n cursor: pointer;\n background-color: #3b5c7f;\n}\n.igv-ui-generic-dialog-container .igv-ui-generic-dialog-ok-cancel > div:last-child:hover {\n cursor: pointer;\n background-color: #7f7f7f;\n}\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}\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}\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\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}\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}\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}\n.igv-ui-dialog .igv-ui-dialog-header div:hover {\n cursor: pointer;\n color: #444;\n}\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}\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}\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}\n.igv-ui-dialog .igv-ui-dialog-ok-cancel div:first-child {\n background-color: #5ea4e0;\n}\n.igv-ui-dialog .igv-ui-dialog-ok-cancel div:last-child {\n background-color: #c4c4c4;\n}\n.igv-ui-dialog .igv-ui-dialog-ok-cancel div:first-child:hover {\n cursor: pointer;\n background-color: #3b5c7f;\n}\n.igv-ui-dialog .igv-ui-dialog-ok-cancel div:last-child:hover {\n cursor: pointer;\n background-color: #7f7f7f;\n}\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}\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}\n.igv-ui-dialog .igv-ui-dialog-ok div:hover {\n cursor: pointer;\n background-color: #25597f;\n}\n\n.igv-ui-panel, .igv-ui-panel-row, .igv-ui-panel-column {\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\n.igv-ui-panel-column {\n display: flex;\n flex-direction: column;\n}\n\n.igv-ui-panel-row {\n display: flex;\n flex-direction: row;\n}\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\n.igv-ui-table {\n background-color: white;\n}\n\n.igv-ui-table thead {\n position: sticky;\n top: 0;\n}\n\n.igv-ui-table th {\n text-align: left;\n}\n\n.igv-ui-table td {\n padding-right: 20px;\n}\n\n.igv-ui-table tr:hover {\n background-color: lightblue;\n}\n\n.igv-ui-center-fixed {\n left: 50%;\n top: 50%;\n transform: translate(-50%, -50%);\n}\n\n.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}\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}\n.igv-navbar .igv-navbar-left-container .igv-logo {\n width: 34px;\n height: 32px;\n margin-right: 8px;\n}\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}\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}\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}\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}\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}\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: 240px;\n height: 22px;\n line-height: 22px;\n}\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}\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 display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: center;\n align-items: center;\n}\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}\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}\n.igv-navbar .igv-navbar-right-container .igv-navbar-toggle-button-container {\n position: relative;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: flex-end;\n align-items: center;\n}\n.igv-navbar .igv-navbar-right-container .igv-navbar-toggle-button-container-hidden {\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: center;\n height: 100%;\n}\n.igv-navbar .igv-navbar-right-container .igv-zoom-widget {\n color: #737373;\n font-size: 18px;\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}\n.igv-navbar .igv-navbar-right-container .igv-zoom-widget div {\n cursor: pointer;\n margin-left: unset;\n margin-right: unset;\n}\n.igv-navbar .igv-navbar-right-container .igv-zoom-widget div:first-child {\n height: 20px;\n width: 20px;\n margin-left: unset;\n margin-right: 4px;\n}\n.igv-navbar .igv-navbar-right-container .igv-zoom-widget div:last-child {\n height: 20px;\n width: 20px;\n margin-left: 4px;\n margin-right: unset;\n}\n.igv-navbar .igv-navbar-right-container .igv-zoom-widget div:nth-child(even) {\n display: block;\n height: fit-content;\n}\n.igv-navbar .igv-navbar-right-container .igv-zoom-widget input {\n display: block;\n width: 125px;\n}\n.igv-navbar .igv-navbar-right-container .igv-zoom-widget svg {\n display: block;\n}\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}\n.igv-navbar .igv-navbar-right-container .igv-zoom-widget-900 div {\n cursor: pointer;\n margin-left: unset;\n margin-right: unset;\n}\n.igv-navbar .igv-navbar-right-container .igv-zoom-widget-900 div:first-child {\n height: 20px;\n width: 20px;\n margin-left: unset;\n margin-right: 4px;\n}\n.igv-navbar .igv-navbar-right-container .igv-zoom-widget-900 div:last-child {\n height: 20px;\n width: 20px;\n margin-left: 4px;\n margin-right: unset;\n}\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}\n.igv-navbar .igv-navbar-right-container .igv-zoom-widget-900 input {\n width: 0;\n height: 0;\n display: none;\n}\n.igv-navbar .igv-navbar-right-container .igv-zoom-widget-900 svg {\n display: block;\n}\n.igv-navbar .igv-navbar-right-container .igv-zoom-widget-hidden {\n display: none;\n}\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\n.igv-navbar-button:hover {\n cursor: pointer;\n}\n\n.igv-navbar-button-clicked {\n color: white;\n background-color: #737373;\n}\n\n.igv-navbar-icon-button {\n cursor: pointer;\n position: relative;\n width: 24px;\n height: 24px;\n margin-left: 4px;\n margin-right: 4px;\n border: none;\n background-size: contain;\n background-repeat: no-repeat;\n background-position: center;\n}\n.igv-navbar-icon-button > div:first-child {\n z-index: 512;\n position: absolute;\n top: 36px;\n left: -18px;\n width: 24px;\n height: 24px;\n border: none;\n background-size: contain;\n background-repeat: no-repeat;\n background-position: center;\n}\n.igv-navbar-icon-button > div:last-child {\n z-index: 512;\n position: absolute;\n top: 36px;\n left: 18px;\n width: 24px;\n height: 24px;\n border: none;\n background-size: contain;\n background-repeat: no-repeat;\n background-position: center;\n}\n\n.igv-navbar-text-button {\n cursor: pointer;\n position: relative;\n margin-left: 2px;\n margin-right: 2px;\n border: none;\n display: flex;\n justify-content: center;\n align-items: center;\n}\n.igv-navbar-text-button > div:nth-child(2) {\n z-index: 512;\n position: absolute;\n top: 36px;\n left: 0;\n width: 38px;\n height: 18px;\n border: none;\n background-size: contain;\n background-repeat: no-repeat;\n background-position: center;\n}\n.igv-navbar-text-button > div:nth-child(3) {\n z-index: 512;\n position: absolute;\n top: 36px;\n left: 42px;\n width: 38px;\n height: 18px;\n border: none;\n background-size: contain;\n background-repeat: no-repeat;\n background-position: center;\n}\n\n#igv-text-button-label {\n text-anchor: middle;\n dominant-baseline: middle;\n}\n\n.igv-navbar-text-button-svg-inactive rect {\n stroke: #737373;\n fill: white;\n}\n.igv-navbar-text-button-svg-inactive text {\n fill: #737373;\n}\n.igv-navbar-text-button-svg-inactive tspan {\n dominant-baseline: middle;\n}\n\n.igv-navbar-text-button-svg-hover rect {\n stroke: #737373;\n fill: #737373;\n}\n.igv-navbar-text-button-svg-hover text {\n fill: white;\n}\n.igv-navbar-text-button-svg-hover tspan {\n dominant-baseline: middle;\n}\n\n#igv-save-svg-group rect {\n stroke: #737373;\n fill: white;\n}\n#igv-save-svg-group text {\n fill: #737373;\n}\n\n#igv-save-svg-group:hover rect {\n stroke: #737373;\n fill: #737373;\n}\n#igv-save-svg-group:hover text {\n fill: white;\n}\n\n#igv-save-png-group rect {\n stroke: #737373;\n fill: white;\n}\n#igv-save-png-group text {\n fill: #737373;\n}\n\n#igv-save-png-group:hover rect {\n stroke: #737373;\n fill: #737373;\n}\n#igv-save-png-group:hover text {\n fill: white;\n}\n\n.igv-zoom-in-notice-container {\n z-index: 256;\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}\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\n.igv-zoom-in-notice {\n position: absolute;\n top: 10px;\n left: 50%;\n}\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\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\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: 12px;\n height: 12px;\n color: #666666;\n background-color: white;\n z-index: 1000;\n}\n.igv-multi-locus-close-button > svg {\n vertical-align: top;\n}\n\n.igv-multi-locus-close-button:hover {\n cursor: pointer;\n color: #434343;\n}\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: 12px;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: center;\n align-items: center;\n}\n.igv-multi-locus-ruler-label > div {\n font-family: \"Open Sans\", sans-serif;\n font-size: 12px;\n color: rgb(16, 16, 16);\n background-color: white;\n}\n.igv-multi-locus-ruler-label > div {\n cursor: pointer;\n}\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}\n.igv-multi-locus-ruler-label-square-dot > div:first-child {\n width: 14px;\n height: 14px;\n}\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: rgb(16, 16, 16);\n}\n\n.igv-ruler-sweeper {\n display: none;\n pointer-events: none;\n position: absolute;\n top: 26px;\n bottom: 0;\n left: 0;\n width: 0;\n z-index: 99999;\n background-color: rgba(68, 134, 247, 0.25);\n}\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}\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\n.igv-track-label {\n position: absolute;\n left: 8px;\n top: 8px;\n width: auto;\n height: auto;\n max-width: 50%;\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\n.igv-track-label:hover,\n.igv-track-label:focus,\n.igv-track-label:active {\n background-color: #e8e8e8;\n}\n\n.igv-track-label-popup-shim {\n padding-left: 8px;\n padding-right: 8px;\n padding-top: 4px;\n}\n\n.igv-center-line {\n display: none;\n pointer-events: none;\n position: absolute;\n top: 0;\n bottom: 0;\n left: 50%;\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\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\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\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: 32;\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\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: 32;\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\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}\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}\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}\n.igv-user-feedback div:first-child div:first-child {\n left: 8px;\n}\n.igv-user-feedback div:first-child div:last-child {\n cursor: pointer;\n right: 8px;\n}\n.igv-user-feedback div:last-child {\n width: 100%;\n height: calc(100% - 24px);\n border-width: 0;\n}\n.igv-user-feedback div:last-child div {\n width: auto;\n height: auto;\n margin: 8px;\n}\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}\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}\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}\n.igv-generic-dialog-container .igv-generic-dialog-header div:hover {\n cursor: pointer;\n color: #444;\n}\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}\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}\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}\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}\n.igv-generic-dialog-container .igv-generic-dialog-label-input input {\n width: 50%;\n font-size: 16px;\n}\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}\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}\n.igv-generic-dialog-container .igv-generic-dialog-input input {\n font-size: 16px;\n}\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}\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}\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}\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}\n.igv-generic-dialog-container .igv-generic-dialog-ok-cancel div:first-child:hover {\n cursor: pointer;\n background-color: #3b5c7f;\n}\n.igv-generic-dialog-container .igv-generic-dialog-ok-cancel div:last-child:hover {\n cursor: pointer;\n background-color: #7f7f7f;\n}\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}\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}\n.igv-generic-dialog-container .igv-generic-dialog-ok div:hover {\n cursor: pointer;\n background-color: #25597f;\n}\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}\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}\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\n.igv-menu-popup {\n position: absolute;\n top: 0;\n left: 0;\n width: max-content;\n max-width: 400px;\n z-index: 512;\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}\n.igv-menu-popup > div:not(:first-child) {\n width: 100%;\n}\n.igv-menu-popup > div:not(:first-child) > div {\n background: white;\n}\n.igv-menu-popup > div:not(:first-child) > div.context-menu {\n padding-left: 4px;\n padding-right: 4px;\n}\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}\n.igv-menu-popup > div:not(:first-child) > div:hover {\n background: #efefef;\n}\n\n.igv-menu-popup-shim {\n padding-left: 8px;\n padding-right: 8px;\n padding-bottom: 1px;\n padding-top: 1px;\n}\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}\n.igv-menu-popup-header div {\n margin-right: 4px;\n height: 12px;\n width: 12px;\n color: #7F7F7F;\n}\n.igv-menu-popup-header div:hover {\n cursor: pointer;\n color: #444;\n}\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}\n.igv-menu-popup-check-container div {\n padding-top: 2px;\n padding-left: 8px;\n}\n.igv-menu-popup-check-container div:first-child {\n position: relative;\n width: 12px;\n height: 12px;\n}\n.igv-menu-popup-check-container div:first-child svg {\n position: absolute;\n width: 12px;\n height: 12px;\n}\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}\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}\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}\n.igv-user-feedback div:first-child div:first-child {\n left: 8px;\n}\n.igv-user-feedback div:first-child div:last-child {\n cursor: pointer;\n right: 8px;\n}\n.igv-user-feedback div:last-child {\n width: 100%;\n height: calc(100% - 24px);\n border-width: 0;\n}\n.igv-user-feedback div:last-child div {\n width: auto;\n height: auto;\n margin: 8px;\n}\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}\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: rgb(255, 255, 255);\n animation: spin 1s ease-in-out infinite;\n -webkit-animation: spin 1s ease-in-out infinite;\n}\n\n@keyframes spin {\n to {\n -webkit-transform: rotate(360deg);\n transform: rotate(360deg);\n }\n}\n@-webkit-keyframes spin {\n to {\n -webkit-transform: rotate(360deg);\n transform: rotate(360deg);\n }\n}\n.igv-roi-menu {\n position: absolute;\n z-index: 512;\n font-family: \"Open Sans\", sans-serif;\n font-size: small;\n font-weight: 400;\n color: #4b4b4b;\n background-color: white;\n width: 192px;\n border-radius: 4px;\n border-color: #7F7F7F;\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: stretch;\n}\n.igv-roi-menu > div:first-child {\n height: 24px;\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}\n.igv-roi-menu > div:first-child > div {\n margin-right: 4px;\n height: 12px;\n width: 12px;\n color: #7F7F7F;\n}\n.igv-roi-menu > div:first-child > div:hover {\n cursor: pointer;\n color: #444;\n}\n.igv-roi-menu > div:last-child {\n background-color: white;\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: 0;\n display: flex;\n flex-direction: column;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: stretch;\n text-align: start;\n vertical-align: middle;\n}\n.igv-roi-menu > div:last-child > div {\n height: 24px;\n padding-left: 4px;\n border-bottom-style: solid;\n border-bottom-width: thin;\n border-bottom-color: #7f7f7f;\n}\n.igv-roi-menu > div:last-child > div:not(:first-child):hover {\n cursor: pointer;\n background-color: rgba(127, 127, 127, 0.1);\n}\n.igv-roi-menu > div:last-child div:first-child {\n font-style: italic;\n text-align: center;\n padding-right: 4px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.igv-roi-menu > div:last-child > div:last-child {\n border-bottom-width: 0;\n border-bottom-color: transparent;\n}\n\n.igv-roi-placeholder {\n font-style: normal;\n color: rgba(75, 75, 75, 0.6);\n}\n\n.igv-roi-table {\n position: absolute;\n z-index: 1024;\n display: flex;\n flex-flow: column;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: stretch;\n resize: both;\n overflow: hidden;\n width: min-content;\n max-width: 1600px;\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: 12px;\n font-weight: 400;\n background-color: white;\n cursor: default;\n}\n.igv-roi-table > div {\n height: 24px;\n font-size: 14px;\n text-align: start;\n vertical-align: middle;\n line-height: 24px;\n}\n.igv-roi-table > div:first-child {\n border-color: transparent;\n border-top-left-radius: 4px;\n border-top-right-radius: 4px;\n border-top-width: 0;\n border-bottom-color: #7f7f7f;\n border-bottom-style: solid;\n border-bottom-width: thin;\n background-color: #eee;\n cursor: move;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: space-between;\n align-items: center;\n}\n.igv-roi-table > div:first-child > div:first-child {\n text-align: center;\n white-space: nowrap;\n text-overflow: ellipsis;\n overflow: hidden;\n margin-left: 4px;\n margin-right: 4px;\n width: calc(100% - 4px - 12px);\n}\n.igv-roi-table > div:first-child > div:last-child {\n margin-right: 4px;\n margin-bottom: 2px;\n height: 12px;\n width: 12px;\n color: #7f7f7f;\n}\n.igv-roi-table > div:first-child > div:last-child > svg {\n display: block;\n}\n.igv-roi-table > div:first-child > div:last-child:hover {\n cursor: pointer;\n color: #444;\n}\n.igv-roi-table > .igv-roi-table-description {\n padding: 4px;\n margin-left: 4px;\n word-break: break-all;\n overflow-y: auto;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n background-color: transparent;\n}\n.igv-roi-table > .igv-roi-table-goto-explainer {\n margin-top: 5px;\n margin-left: 4px;\n color: #7F7F7F;\n font-style: italic;\n height: 24px;\n border-top: solid lightgray;\n background-color: transparent;\n}\n.igv-roi-table > .igv-roi-table-column-titles {\n height: 24px;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: stretch;\n align-items: stretch;\n padding-right: 16px;\n background-color: white;\n border-top-color: #7f7f7f;\n border-top-style: solid;\n border-top-width: thin;\n border-bottom-color: #7f7f7f;\n border-bottom-style: solid;\n border-bottom-width: thin;\n}\n.igv-roi-table > .igv-roi-table-column-titles > div {\n font-size: 14px;\n vertical-align: middle;\n line-height: 24px;\n text-align: left;\n margin-left: 4px;\n height: 24px;\n overflow: hidden;\n text-overflow: ellipsis;\n border-right-color: #7f7f7f;\n border-right-style: solid;\n border-right-width: thin;\n}\n.igv-roi-table > .igv-roi-table-column-titles > div:last-child {\n border-right: unset;\n}\n.igv-roi-table > .igv-roi-table-row-container {\n display: flex;\n flex-flow: column;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: stretch;\n overflow: auto;\n height: 360px;\n flex: 1 1 auto;\n background-color: transparent;\n}\n.igv-roi-table > .igv-roi-table-row-container > .igv-roi-table-row {\n height: 24px;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: stretch;\n align-items: stretch;\n}\n.igv-roi-table > .igv-roi-table-row-container > .igv-roi-table-row > div {\n font-size: 14px;\n vertical-align: middle;\n line-height: 24px;\n text-align: left;\n margin-left: 4px;\n height: 24px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n border-right-color: transparent;\n border-right-style: solid;\n border-right-width: thin;\n}\n.igv-roi-table > .igv-roi-table-row-container > .igv-roi-table-row > div:last-child {\n border-right: unset;\n}\n.igv-roi-table > .igv-roi-table-row-container > .igv-roi-table-row-hover {\n background-color: rgba(0, 0, 0, 0.04);\n}\n.igv-roi-table > div:last-child {\n min-height: 32px;\n height: 32px;\n line-height: 32px;\n border-top-color: #7f7f7f;\n border-top-style: solid;\n border-top-width: thin;\n border-bottom-color: transparent;\n border-bottom-left-radius: 4px;\n border-bottom-right-radius: 4px;\n border-bottom-width: 0;\n background-color: #eee;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: space-around;\n align-items: center;\n}\n\n.igv-roi-table-row-selected {\n background-color: rgba(0, 0, 0, 0.125);\n}\n\n.igv-roi-table-button {\n cursor: pointer;\n height: 20px;\n user-select: none;\n line-height: 20px;\n text-align: center;\n vertical-align: middle;\n font-family: \"Open Sans\", sans-serif;\n font-size: 13px;\n font-weight: 400;\n color: black;\n padding-left: 6px;\n padding-right: 6px;\n background-color: rgb(239, 239, 239);\n border-color: black;\n border-style: solid;\n border-width: thin;\n border-radius: 3px;\n}\n\n.igv-roi-table-button:hover {\n font-weight: 400;\n background-color: rgba(0, 0, 0, 0.13);\n}\n\n.igv-roi-region {\n z-index: 64;\n position: absolute;\n top: 0;\n bottom: 0;\n pointer-events: none;\n overflow: visible;\n margin-top: 66px;\n display: flex;\n flex-direction: column;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: stretch;\n}\n.igv-roi-region > div {\n position: relative;\n width: 100%;\n height: 8px;\n pointer-events: auto;\n}\n\n.igv-roi-menu-row {\n height: 24px;\n padding-left: 8px;\n font-size: small;\n text-align: start;\n vertical-align: middle;\n line-height: 24px;\n background-color: white;\n}\n\n.igv-roi-menu-row-edit-description {\n width: -webkit-fill-available;\n font-size: small;\n text-align: start;\n vertical-align: middle;\n background-color: white;\n padding-left: 4px;\n padding-right: 4px;\n padding-bottom: 4px;\n display: flex;\n flex-direction: column;\n flex-wrap: nowrap;\n justify-content: stretch;\n align-items: stretch;\n}\n.igv-roi-menu-row-edit-description > label {\n margin-left: 2px;\n margin-bottom: 0;\n display: block;\n width: -webkit-fill-available;\n}\n.igv-roi-menu-row-edit-description > input {\n display: block;\n margin-left: 2px;\n margin-right: 2px;\n margin-bottom: 1px;\n width: -webkit-fill-available;\n}\n\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 min-height: 160px;\n}\n\n.igv-viewport {\n position: relative;\n margin-top: 5px;\n line-height: 1;\n overflow-x: hidden;\n overflow-y: hidden;\n}\n\n.igv-viewport-content {\n position: relative;\n width: 100%;\n}\n.igv-viewport-content > canvas {\n position: relative;\n display: block;\n}\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\n.igv-column-shim {\n width: 1px;\n margin-left: 2px;\n margin-right: 2px;\n background-color: #545453;\n}\n\n.igv-axis-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 width: 50px;\n}\n.igv-axis-column > div {\n position: relative;\n margin-top: 5px;\n width: 100%;\n}\n.igv-axis-column > div > div {\n z-index: 512;\n position: absolute;\n top: 8px;\n left: 8px;\n width: fit-content;\n height: fit-content;\n background-color: transparent;\n display: grid;\n align-items: start;\n justify-items: center;\n}\n.igv-axis-column > div > div > input {\n display: block;\n margin: unset;\n cursor: pointer;\n}\n\n.igv-column {\n position: relative;\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\n.igv-sample-info-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\n.igv-sample-name-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\n.igv-scrollbar-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 width: 14px;\n}\n.igv-scrollbar-column > div {\n position: relative;\n margin-top: 5px;\n width: 14px;\n}\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}\n.igv-scrollbar-column > div > div:hover {\n background-color: #c4c4c4;\n}\n\n.igv-track-drag-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 width: 12px;\n background-color: white;\n}\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}\n.igv-track-drag-column .igv-track-drag-handle-color {\n background-color: #c4c4c4;\n}\n.igv-track-drag-column .igv-track-drag-handle-hover-color {\n background-color: #787878;\n}\n.igv-track-drag-column .igv-track-drag-handle-selected-color {\n background-color: #0963fa;\n}\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\n.igv-gear-menu-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 width: 28px;\n}\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}\n.igv-gear-menu-column > div > div {\n position: relative;\n margin-top: 4px;\n width: 16px;\n height: 16px;\n color: #7F7F7F;\n}\n.igv-gear-menu-column > div > div:hover {\n cursor: pointer;\n color: #444;\n}\n\n/*# sourceMappingURL=igv.css.map */\n';
73804
74442
 
73805
74443
  /**
73806
74444
  * Manages XQTL selections.
@@ -73921,6 +74559,125 @@ brewer.push("rgb(188, 128, 189)");
73921
74559
  brewer.push("rgb(204, 235, 197)");
73922
74560
  brewer.push("rgb(255, 237, 111)");
73923
74561
 
74562
+ class SliderDialog {
74563
+
74564
+ constructor(parent) {
74565
+
74566
+ this.parent = parent;
74567
+
74568
+ // dialog container
74569
+ this.container = div({class: 'igv-ui-generic-dialog-container'});
74570
+ parent.appendChild(this.container);
74571
+
74572
+ // dialog header
74573
+ const header = div({class: 'igv-ui-generic-dialog-header'});
74574
+ this.container.appendChild(header);
74575
+
74576
+ // dialog label
74577
+ this.label = div({class: 'igv-ui-generic-dialog-one-liner'});
74578
+ this.container.appendChild(this.label);
74579
+ this.label.text = 'Unlabeled';
74580
+
74581
+ // input container
74582
+ this.input_container = div({class: 'igv-ui-generic-dialog-input'});
74583
+ this.container.appendChild(this.input_container);
74584
+
74585
+ // input element
74586
+ let html = `<input type="range" id="igv-slider-dialog-input" name="igv-slider-dialog-input" />`;
74587
+ this._input = document.createRange().createContextualFragment(html).firstChild;
74588
+ this.input_container.appendChild(this._input);
74589
+
74590
+ // output element
74591
+ html = `<output id="igv-slider-dialog-output" name="igv-slider-dialog-output" for="igv-slider-dialog-input"></output>`;
74592
+ this._output = document.createRange().createContextualFragment(html).firstChild;
74593
+ this.input_container.appendChild(this._output);
74594
+
74595
+
74596
+ // ok | cancel
74597
+ const buttons = div({class: 'igv-ui-generic-dialog-ok-cancel'});
74598
+ this.container.appendChild(buttons);
74599
+
74600
+ // ok
74601
+ this.ok = div();
74602
+ buttons.appendChild(this.ok);
74603
+ this.ok.textContent = 'OK';
74604
+
74605
+ // cancel
74606
+ this.cancel = div();
74607
+ buttons.appendChild(this.cancel);
74608
+ this.cancel.textContent = 'Cancel';
74609
+
74610
+ hide(this.container);
74611
+
74612
+ this._input.addEventListener('input', () => {
74613
+ const number = parseFloat(this._input.value)/this._scaleFactor;
74614
+ this.callback(number);
74615
+ this._output.value = `${number.toFixed(2)}`;
74616
+ }, false);
74617
+
74618
+ this.ok.addEventListener('click', () => {
74619
+ if (typeof this.callback === 'function') {
74620
+ const number = parseFloat(this._input.value)/this._scaleFactor;
74621
+ this.callback(number);
74622
+ this.callback = undefined;
74623
+ }
74624
+ this._input.value = undefined;
74625
+ hide(this.container);
74626
+ });
74627
+
74628
+ const cancel = () => {
74629
+ this._input.value = undefined;
74630
+ hide(this.container);
74631
+ };
74632
+
74633
+ this.cancel.addEventListener('click', cancel);
74634
+
74635
+ attachDialogCloseHandlerWithParent(header, cancel);
74636
+ makeDraggable(this.container, header);
74637
+
74638
+ }
74639
+
74640
+ get value() {
74641
+ return purify.sanitize(this._input.value)
74642
+ }
74643
+
74644
+ present(options, e) {
74645
+
74646
+ this.label.textContent = options.label;
74647
+
74648
+ this._scaleFactor = options.scaleFactor;
74649
+ const [ minS, maxS, valueS ] = [ options.min, options.max, options.value ].map(number => (Math.floor(this._scaleFactor * number)).toString());
74650
+
74651
+ this._input.min = minS;
74652
+ this._input.max = maxS;
74653
+ this._input.value = valueS;
74654
+
74655
+ const numer = parseFloat(valueS);
74656
+ const denom = this._scaleFactor;
74657
+ const number = numer/denom;
74658
+ this._output.value = `${number.toFixed(2)}`;
74659
+
74660
+ this.callback = options.callback || options.click;
74661
+
74662
+ show(this.container);
74663
+ this.clampLocation(e.clientX, e.clientY);
74664
+
74665
+ }
74666
+
74667
+ clampLocation(clientX, clientY) {
74668
+
74669
+ const {width: w, height: h} = this.container.getBoundingClientRect();
74670
+ const wh = window.innerHeight;
74671
+ const ww = window.innerWidth;
74672
+
74673
+ const y = Math.min(wh - h, clientY);
74674
+ const x = Math.min(ww - w, clientX);
74675
+ this.container.style.left = `${x}px`;
74676
+ this.container.style.top = `${y}px`;
74677
+
74678
+ }
74679
+ }
74680
+
73924
74681
  // css - $igv-scrollbar-outer-width: 14px;
73925
74682
  const igv_scrollbar_outer_width = 14;
73926
74683
 
@@ -74010,7 +74767,6 @@ class Browser {
74010
74767
  this.sampleNameControl.setState(this.showSampleNames);
74011
74768
  this.sampleNameControl.hide();
74012
74769
 
74013
-
74014
74770
  this.layoutChange();
74015
74771
  }
74016
74772
  });
@@ -74029,7 +74785,7 @@ class Browser {
74029
74785
 
74030
74786
  this.sampleInfo = new SampleInfo(this);
74031
74787
 
74032
- this.setControls(config);
74788
+ this.createStandardControls(config);
74033
74789
 
74034
74790
  // Region of interest
74035
74791
  this.roiManager = new ROIManager(this);
@@ -74087,121 +74843,18 @@ class Browser {
74087
74843
  }
74088
74844
  }
74089
74845
 
74090
- setControls(config) {
74091
-
74092
- const $navBar = this.createStandardControls(config);
74093
- $navBar.insertBefore($$1(this.columnContainer));
74094
- this.$navigation = $navBar;
74095
-
74096
- if (false === config.showControls) {
74097
- $navBar.hide();
74098
- }
74099
-
74100
- }
74101
-
74102
74846
  createStandardControls(config) {
74103
74847
 
74104
- const $navBar = $$1('<div>', {class: 'igv-navbar'});
74105
- this.$navigation = $navBar;
74106
-
74107
- const $navbarLeftContainer = $$1('<div>', {class: 'igv-navbar-left-container'});
74108
- $navBar.append($navbarLeftContainer);
74109
-
74110
- // IGV logo
74111
- const $logo = $$1('<div>', {class: 'igv-logo'});
74112
- $navbarLeftContainer.append($logo);
74113
-
74114
- const logoSvg = logo();
74115
- logoSvg.css("width", "34px");
74116
- logoSvg.css("height", "32px");
74117
- $logo.append(logoSvg);
74118
-
74119
- this.$current_genome = $$1('<div>', {class: 'igv-current-genome'});
74120
- $navbarLeftContainer.append(this.$current_genome);
74121
- this.$current_genome.text('');
74122
-
74123
- const $genomicLocation = $$1('<div>', {class: 'igv-navbar-genomic-location'});
74124
- $navbarLeftContainer.append($genomicLocation);
74125
-
74126
- // chromosome select widget
74127
- this.chromosomeSelectWidget = new ChromosomeSelectWidget(this, $genomicLocation.get(0));
74128
- if (config.showChromosomeWidget !== false) {
74129
- this.chromosomeSelectWidget.show();
74130
- } else {
74131
- this.chromosomeSelectWidget.hide();
74132
- }
74133
-
74134
- const $locusSizeGroup = $$1('<div>', {class: 'igv-locus-size-group'});
74135
- $genomicLocation.append($locusSizeGroup);
74136
-
74137
- const $searchContainer = $$1('<div>', {class: 'igv-search-container'});
74138
- $locusSizeGroup.append($searchContainer);
74139
-
74140
- // browser.$searchInput = $('<input type="text" placeholder="Locus Search">');
74141
- this.$searchInput = $$1('<input>', {class: 'igv-search-input', type: 'text', placeholder: 'Locus Search'});
74142
- $searchContainer.append(this.$searchInput);
74143
- // Stop event propagation to prevent feature track keyboard navigation
74144
- this.$searchInput[0].addEventListener('keyup', (event) => {
74145
- event.stopImmediatePropagation();
74146
- });
74147
-
74148
- this.$searchInput.change(() => this.doSearch(this.$searchInput.val()));
74149
-
74150
- const searchIconContainer = div({class: 'igv-search-icon-container'});
74151
- $searchContainer.append($$1(searchIconContainer));
74152
-
74153
- searchIconContainer.appendChild(createIcon("search"));
74154
-
74155
- searchIconContainer.addEventListener('click', () => this.doSearch(this.$searchInput.val()));
74156
-
74157
- this.windowSizePanel = new WindowSizePanel($locusSizeGroup.get(0), this);
74158
-
74159
- const $navbarRightContainer = $$1('<div>', {class: 'igv-navbar-right-container'});
74160
- $navBar.append($navbarRightContainer);
74161
-
74162
- const $toggle_button_container = $$1('<div class="igv-navbar-toggle-button-container">');
74163
- $navbarRightContainer.append($toggle_button_container);
74164
- this.$toggle_button_container = $toggle_button_container;
74165
-
74166
- this.overlayTrackButton = new OverlayTrackButton(this, $toggle_button_container.get(0));
74167
- this.overlayTrackButton.setVisibility(false);
74168
-
74169
- this.multiTrackSelectButton = new MultiTrackSelectButton(this, $toggle_button_container.get(0));
74170
-
74171
- this.cursorGuide = new CursorGuide(this.columnContainer, this);
74172
-
74173
- this.cursorGuideButton = new CursorGuideButton(this, $toggle_button_container.get(0));
74174
-
74175
- this.centerLineButton = new CenterLineButton(this, $toggle_button_container.get(0));
74176
-
74177
74848
  this.setTrackLabelVisibility(config.showTrackLabels);
74178
- this.trackLabelControl = new TrackLabelControl($toggle_button_container.get(0), this);
74179
74849
 
74180
- // ROI Control
74181
- this.roiTableControl = new ROITableControl($toggle_button_container.get(0), this);
74182
-
74183
- this.sampleInfoControl = new SampleInfoControl($toggle_button_container.get(0), this);
74850
+ this.navbar = new ResponsiveNavbar(config, this);
74184
74851
 
74185
- this.sampleNameControl = new SampleNameControl($toggle_button_container.get(0), this);
74186
-
74187
- if (true === config.showSVGButton) {
74188
- this.saveImageControl = new SaveImageControl($toggle_button_container.get(0), this);
74189
- }
74852
+ this.navbar.$navigation.insertBefore($$1(this.columnContainer));
74190
74853
 
74191
- if (config.customButtons) {
74192
- for (let b of config.customButtons) {
74193
- new CustomButton($toggle_button_container.get(0), this, b);
74194
- }
74195
- }
74196
-
74197
- this.zoomWidget = new ZoomWidget(this, $navbarRightContainer.get(0));
74198
-
74199
- if (false === config.showNavigation) {
74200
- this.$navigation.hide();
74854
+ if (false === config.showControls) {
74855
+ this.navbar.hide();
74201
74856
  }
74202
-
74203
- this.sliderDialog = new SliderDialog(this.root);
74204
- this.sliderDialog.container.id = `igv-slider-dialog-${guid$2()}`;
74857
+ this.cursorGuide = new CursorGuide(this.columnContainer, this);
74205
74858
 
74206
74859
  this.inputDialog = new InputDialog(this.root);
74207
74860
  this.inputDialog.container.id = `igv-input-dialog-${guid$2()}`;
@@ -74212,7 +74865,8 @@ class Browser {
74212
74865
  this.genericColorPicker = new GenericColorPicker({parent: this.columnContainer, width: 432});
74213
74866
  this.genericColorPicker.container.id = `igv-track-color-picker-${guid$2()}`;
74214
74867
 
74215
- return $navBar
74868
+ this.sliderDialog = new SliderDialog(this.root);
74869
+ this.sliderDialog.container.id = `igv-slider-dialog-${guid$2()}`;
74216
74870
 
74217
74871
  }
74218
74872
 
@@ -74443,10 +75097,10 @@ class Browser {
74443
75097
  session = await translateSession(session);
74444
75098
  }
74445
75099
 
74446
- this.sampleInfoControl.setButtonVisibility(false);
75100
+ this.navbar.sampleInfoControl.setButtonVisibility(false);
74447
75101
 
74448
75102
  this.showSampleNames = session.showSampleNames || false;
74449
- this.sampleNameControl.setState(this.showSampleNames === true);
75103
+ this.navbar.sampleNameControl.setState(this.showSampleNames === true);
74450
75104
 
74451
75105
  if (session.sampleNameViewportWidth) {
74452
75106
  this.sampleNameViewportWidth = session.sampleNameViewportWidth;
@@ -74566,9 +75220,9 @@ class Browser {
74566
75220
  await rtv.updateViews();
74567
75221
  }
74568
75222
 
74569
- // If any tracks are selected show the selectino buttons
75223
+ // If any tracks are selected show the selection buttons
74570
75224
  if (this.trackViews.some(tv => tv.track.selected)) {
74571
- this.multiTrackSelectButton.setMultiTrackSelection(true);
75225
+ this.navbar.setEnableTrackSelection(true);
74572
75226
  }
74573
75227
 
74574
75228
  this.updateUIWithReferenceFrameList();
@@ -74609,7 +75263,8 @@ class Browser {
74609
75263
 
74610
75264
  this.removeAllTracks(); // Do this first, before new genome is set
74611
75265
  this.roiManager.clearROIs();
74612
- this.multiTrackSelectButton.setMultiTrackSelection(false);
75266
+
75267
+ this.navbar.setEnableTrackSelection(false);
74613
75268
 
74614
75269
  let genome;
74615
75270
  if (genomeConfig.gbkURL) {
@@ -74622,8 +75277,7 @@ class Browser {
74622
75277
 
74623
75278
  this.genome = genome;
74624
75279
 
74625
- this.updateNavbarDOMWithGenome(genome);
74626
-
75280
+ this.navbar.updateGenome(genome);
74627
75281
 
74628
75282
  let locus = initialLocus || genome.initialLocus;
74629
75283
  if (Array.isArray(locus)) {
@@ -74654,26 +75308,6 @@ class Browser {
74654
75308
  }
74655
75309
  }
74656
75310
 
74657
- updateNavbarDOMWithGenome(genome) {
74658
- let genomeLabel = (genome.id && genome.id.length < 20 ? genome.id : `${genome.id.substring(0, 8)}...${genome.id.substring(genome.id.length - 8)}`);
74659
- this.$current_genome.text(genomeLabel);
74660
- this.$current_genome.attr('title', genome.description);
74661
-
74662
- // chromosome select widget -- Show this IFF its not explicitly hidden AND the genome has pre-loaded chromosomes
74663
- const showChromosomeWidget =
74664
- this.config.showChromosomeWidget !== false &&
74665
- this.genome.showChromosomeWidget !== false &&
74666
- genome.chromosomeNames &&
74667
- genome.chromosomeNames.length > 1;
74668
-
74669
- if (showChromosomeWidget) {
74670
- this.chromosomeSelectWidget.update(genome);
74671
- this.chromosomeSelectWidget.show();
74672
- } else {
74673
- this.chromosomeSelectWidget.hide();
74674
- }
74675
- }
74676
-
74677
75311
  /**
74678
75312
  * Load a genome, defined by a string ID or a json-like configuration object. This includes a fasta reference
74679
75313
  * as well as optional cytoband and annotation tracks.
@@ -74758,16 +75392,16 @@ class Browser {
74758
75392
 
74759
75393
  (this.isMultiLocusWholeGenomeView() || GenomeUtils.isWholeGenomeView(referenceFrameList[0].chr));
74760
75394
 
74761
- navbarDidResize(this, this.$navigation.width());
75395
+ this.navbar.navbarDidResize();
74762
75396
 
74763
75397
  toggleTrackLabels(this.trackViews, this.doShowTrackLabels);
74764
75398
 
74765
75399
  if (this.doShowCenterLine && GenomeUtils.isWholeGenomeView(referenceFrameList[0].chr)) {
74766
- this.centerLineButton.boundMouseClickHandler();
75400
+ this.navbar.centerLineButton.boundMouseClickHandler();
74767
75401
  }
74768
75402
 
74769
75403
  if (this.doShowCursorGuide && GenomeUtils.isWholeGenomeView(referenceFrameList[0].chr)) {
74770
- this.cursorGuideButton.boundMouseClickHandler();
75404
+ this.navbar.cursorGuideButton.boundMouseClickHandler();
74771
75405
  }
74772
75406
 
74773
75407
  this.setCenterLineAndCenterLineButtonVisibility(GenomeUtils.isWholeGenomeView(referenceFrameList[0].chr));
@@ -74777,9 +75411,9 @@ class Browser {
74777
75411
  setCenterLineAndCenterLineButtonVisibility(isWholeGenomeView) {
74778
75412
 
74779
75413
  if (isWholeGenomeView) {
74780
- this.centerLineButton.setVisibility(!isWholeGenomeView);
75414
+ this.navbar.centerLineButton.setVisibility(false);
74781
75415
  } else {
74782
- this.centerLineButton.setVisibility(this.config.showCenterGuideButton);
75416
+ this.navbar.centerLineButton.setVisibility(this.config.showCenterGuideButton);
74783
75417
  }
74784
75418
 
74785
75419
  for (let centerLine of this.centerLineList) {
@@ -74985,7 +75619,7 @@ class Browser {
74985
75619
  this.reorderTracks();
74986
75620
  this.fireEvent('trackorderchanged', [this.getTrackOrder()]);
74987
75621
 
74988
- this.multiTrackSelectButton.setMultiTrackSelection(this.multiTrackSelectButton.enableMultiTrackSelection);
75622
+ newTrack.trackView.enableTrackSelection(this.navbar.getEnableTrackSelection());
74989
75623
 
74990
75624
  return newTrack
74991
75625
 
@@ -75353,8 +75987,7 @@ class Browser {
75353
75987
  }
75354
75988
 
75355
75989
  if (this.referenceFrameList) {
75356
- this.isMultiLocusWholeGenomeView() || GenomeUtils.isWholeGenomeView(this.referenceFrameList[0].chr);
75357
- navbarDidResize(this, this.$navigation.width());
75990
+ this.navbar.navbarDidResize();
75358
75991
  }
75359
75992
 
75360
75993
  resize.call(this);
@@ -75436,13 +76069,11 @@ class Browser {
75436
76069
  referenceFrame.end = referenceFrame.start + referenceFrame.bpPerPixel * width;
75437
76070
  }
75438
76071
 
75439
- if (this.chromosomeSelectWidget) {
75440
- this.chromosomeSelectWidget.select.value = referenceFrameList.length === 1 ? this.referenceFrameList[0].chr : '';
75441
- }
76072
+ const chrName = referenceFrameList.length === 1 ? this.referenceFrameList[0].chr : '';
75442
76073
 
75443
76074
  const loc = this.referenceFrameList.map(rf => rf.getLocusString()).join(' ');
75444
76075
 
75445
- this.$searchInput.val(loc);
76076
+ this.navbar.updateLocus(loc, chrName);
75446
76077
 
75447
76078
  this.fireEvent('locuschange', [this.referenceFrameList]);
75448
76079
  }
@@ -75717,7 +76348,7 @@ class Browser {
75717
76348
  async loadSampleInfo(config) {
75718
76349
 
75719
76350
  await this.sampleInfo.loadSampleInfoFile(config.url);
75720
-
76351
+
75721
76352
  for (const {sampleInfoViewport} of this.trackViews) {
75722
76353
  sampleInfoViewport.setWidth(this.getSampleInfoColumnWidth());
75723
76354
  }
@@ -76173,7 +76804,7 @@ class Browser {
76173
76804
  createCircularView(container, show) {
76174
76805
  show = show === true; // convert undefined to boolean
76175
76806
  this.circularView = createCircularView(container, this);
76176
- this.circularViewControl = new CircularViewControl(this.$toggle_button_container.get(0), this);
76807
+ this.circularViewControl = new CircularViewControl(this.navbar.toggle_button_container, this);
76177
76808
  this.circularView.setAssembly({
76178
76809
  name: this.genome.id,
76179
76810
  id: this.genome.id,
@@ -76193,6 +76824,30 @@ class Browser {
76193
76824
  this.circularViewControl.setState(isVisible);
76194
76825
  }
76195
76826
  }
76827
+
76828
+
76829
+
76830
+ // Navbar delegates
76831
+ get sampleInfoControl() {
76832
+ return this.navbar.sampleInfoControl
76833
+ }
76834
+
76835
+ get overlayTrackButton() {
76836
+ return this.navbar.overlayTrackButton
76837
+ }
76838
+
76839
+ get roiTableControl() {
76840
+ return this.navbar.roiTableControl
76841
+ }
76842
+
76843
+ get sampleInfoControl() {
76844
+ return this.navbar.sampleInfoControl
76845
+ }
76846
+
76847
+ get sampleNameControl() {
76848
+ return this.navbar.sampleNameControl
76849
+ }
76850
+
76196
76851
  }
76197
76852
 
76198
76853
  function getFileExtension(input) {
@@ -76402,21 +77057,6 @@ async function keyUpHandler(event) {
76402
77057
  }
76403
77058
  }
76404
77059
 
76405
-
76406
- function logo() {
76407
-
76408
- return $$1(
76409
- '<svg width="690px" height="324px" viewBox="0 0 690 324" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">' +
76410
- '<title>IGV</title>' +
76411
- '<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">' +
76412
- '<g id="IGV" fill="#666666">' +
76413
- '<polygon id="Path" points="379.54574 8.00169252 455.581247 8.00169252 515.564813 188.87244 532.884012 253.529506 537.108207 253.529506 554.849825 188.87244 614.833392 8.00169252 689.60164 8.00169252 582.729511 320.722144 486.840288 320.722144"></polygon>' +
76414
- '<path d="M261.482414,323.793286 C207.975678,323.793286 168.339046,310.552102 142.571329,284.069337 C116.803612,257.586572 103.919946,217.158702 103.919946,162.784513 C103.919946,108.410325 117.437235,67.8415913 144.472217,41.0770945 C171.507199,14.3125977 212.903894,0.930550071 268.663545,0.930550071 C283.025879,0.930550071 298.232828,1.84616386 314.284849,3.6774189 C330.33687,5.50867394 344.839793,7.97378798 357.794056,11.072835 L357.794056,68.968378 C339.48912,65.869331 323.578145,63.5450806 310.060654,61.9955571 C296.543163,60.4460336 284.574731,59.6712835 274.154998,59.6712835 C255.850062,59.6712835 240.502308,61.4320792 228.111274,64.9537236 C215.720241,68.4753679 205.793482,74.2507779 198.330701,82.2801269 C190.867919,90.309476 185.587729,100.87425 182.48997,113.974767 C179.392212,127.075284 177.843356,143.345037 177.843356,162.784513 C177.843356,181.942258 179.251407,198.000716 182.067551,210.960367 C184.883695,223.920018 189.671068,234.41436 196.429813,242.443709 C203.188559,250.473058 212.059279,256.178037 223.042241,259.558815 C234.025202,262.939594 247.683295,264.629958 264.01693,264.629958 C268.241146,264.629958 273.098922,264.489094 278.590403,264.207362 C284.081883,263.925631 289.643684,263.50304 295.275972,262.939577 L295.275972,159.826347 L361.595831,159.826347 L361.595831,308.579859 C344.698967,313.087564 327.239137,316.750019 309.215815,319.567334 C291.192494,322.38465 275.281519,323.793286 261.482414,323.793286 L261.482414,323.793286 L261.482414,323.793286 Z" id="Path"></path>;' +
76415
- '<polygon id="Path" points="0.81355666 5.00169252 73.0472883 5.00169252 73.0472883 317.722144 0.81355666 317.722144"></polygon>' +
76416
- '</g> </g> </svg>'
76417
- )
76418
- }
76419
-
76420
77060
  function toggleTrackLabels(trackViews, isVisible) {
76421
77061
 
76422
77062
  for (let {viewports} of trackViews) {
@@ -76511,7 +77151,7 @@ async function createBrowser(parentDiv, config) {
76511
77151
  }
76512
77152
 
76513
77153
  browser.stopSpinner();
76514
- navbarDidResize(browser, browser.$navigation.width());
77154
+ browser.navbar.navbarDidResize();
76515
77155
 
76516
77156
  return browser
76517
77157