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.js CHANGED
@@ -18599,9 +18599,9 @@
18599
18599
 
18600
18600
  }
18601
18601
 
18602
- const colorPickerTrackTypeSet = new Set(['bedtype', 'alignment', 'annotation', 'variant', 'wig', 'interact']);
18602
+ const colorPickerTrackTypeSet = new Set(['bedtype', 'alignment', 'annotation', 'variant', 'wig', 'interact', 'shoebox']);
18603
18603
 
18604
- const vizWindowTypes = new Set(['alignment', 'annotation', 'variant', 'eqtl', 'qtl', 'snp', 'shoebox']);
18604
+ const vizWindowTypes = new Set(['alignment', 'annotation', 'variant', 'eqtl', 'qtl', 'snp', 'shoebox', 'wig']);
18605
18605
 
18606
18606
  const multiTrackSelectExclusionTypes = new Set(['sequence', 'ruler', 'ideogram']);
18607
18607
 
@@ -18678,7 +18678,7 @@
18678
18678
 
18679
18679
  if (isVisibilityWindowType(trackView)) {
18680
18680
  list.push('<hr/>');
18681
- list.push(visibilityWindowMenuItem());
18681
+ list.push(visibilityWindowMenuItem(trackView.track.type));
18682
18682
  }
18683
18683
 
18684
18684
  return list
@@ -18761,7 +18761,7 @@
18761
18761
  }
18762
18762
 
18763
18763
 
18764
- function visibilityWindowMenuItem() {
18764
+ function visibilityWindowMenuItem(trackType) {
18765
18765
 
18766
18766
  const object = $$1('<div>');
18767
18767
  object.text('Set visibility window');
@@ -18779,9 +18779,12 @@
18779
18779
  this.trackView.updateViews();
18780
18780
  };
18781
18781
 
18782
+ const label = 'wig' === trackType ?
18783
+ 'Visibility window (bp). Enter 0 for whole chromosome, -1 for whole genome.' :
18784
+ 'Visibility window (bp). Enter 0 for whole chromosome.';
18782
18785
  const config =
18783
18786
  {
18784
- label: 'Visibility Window',
18787
+ label,
18785
18788
  value: this.visibilityWindow,
18786
18789
  callback
18787
18790
  };
@@ -20939,125 +20942,6 @@
20939
20942
  }
20940
20943
  var purify = createDOMPurify();
20941
20944
 
20942
- class SliderDialog {
20943
-
20944
- constructor(parent) {
20945
-
20946
- this.parent = parent;
20947
-
20948
- // dialog container
20949
- this.container = div({class: 'igv-ui-generic-dialog-container'});
20950
- parent.appendChild(this.container);
20951
-
20952
- // dialog header
20953
- const header = div({class: 'igv-ui-generic-dialog-header'});
20954
- this.container.appendChild(header);
20955
-
20956
- // dialog label
20957
- this.label = div({class: 'igv-ui-generic-dialog-one-liner'});
20958
- this.container.appendChild(this.label);
20959
- this.label.text = 'Unlabeled';
20960
-
20961
- // input container
20962
- this.input_container = div({class: 'igv-ui-generic-dialog-input'});
20963
- this.container.appendChild(this.input_container);
20964
-
20965
- // input element
20966
- let html = `<input type="range" id="igv-slider-dialog-input" name="igv-slider-dialog-input" />`;
20967
- this._input = document.createRange().createContextualFragment(html).firstChild;
20968
- this.input_container.appendChild(this._input);
20969
-
20970
- // output element
20971
- html = `<output id="igv-slider-dialog-output" name="igv-slider-dialog-output" for="igv-slider-dialog-input"></output>`;
20972
- this._output = document.createRange().createContextualFragment(html).firstChild;
20973
- this.input_container.appendChild(this._output);
20974
-
20975
-
20976
- // ok | cancel
20977
- const buttons = div({class: 'igv-ui-generic-dialog-ok-cancel'});
20978
- this.container.appendChild(buttons);
20979
-
20980
- // ok
20981
- this.ok = div();
20982
- buttons.appendChild(this.ok);
20983
- this.ok.textContent = 'OK';
20984
-
20985
- // cancel
20986
- this.cancel = div();
20987
- buttons.appendChild(this.cancel);
20988
- this.cancel.textContent = 'Cancel';
20989
-
20990
- hide(this.container);
20991
-
20992
- this._input.addEventListener('input', () => {
20993
- const number = parseFloat(this._input.value)/this._scaleFactor;
20994
- this.callback(number);
20995
- this._output.value = `${number.toFixed(2)}`;
20996
- }, false);
20997
-
20998
- this.ok.addEventListener('click', () => {
20999
- if (typeof this.callback === 'function') {
21000
- const number = parseFloat(this._input.value)/this._scaleFactor;
21001
- this.callback(number);
21002
- this.callback = undefined;
21003
- }
21004
- this._input.value = undefined;
21005
- hide(this.container);
21006
- });
21007
-
21008
- const cancel = () => {
21009
- this._input.value = undefined;
21010
- hide(this.container);
21011
- };
21012
-
21013
- this.cancel.addEventListener('click', cancel);
21014
-
21015
- attachDialogCloseHandlerWithParent(header, cancel);
21016
- makeDraggable(this.container, header);
21017
-
21018
- }
21019
-
21020
- get value() {
21021
- return purify.sanitize(this._input.value)
21022
- }
21023
-
21024
- present(options, e) {
21025
-
21026
- this.label.textContent = options.label;
21027
-
21028
- this._scaleFactor = options.scaleFactor;
21029
- const [ minS, maxS, valueS ] = [ options.min, options.max, options.value ].map(number => (Math.floor(this._scaleFactor * number)).toString());
21030
-
21031
- this._input.min = minS;
21032
- this._input.max = maxS;
21033
- this._input.value = valueS;
21034
-
21035
- const numer = parseFloat(valueS);
21036
- const denom = this._scaleFactor;
21037
- const number = numer/denom;
21038
- this._output.value = `${number.toFixed(2)}`;
21039
-
21040
- this.callback = options.callback || options.click;
21041
-
21042
- show(this.container);
21043
- this.clampLocation(e.clientX, e.clientY);
21044
-
21045
- }
21046
-
21047
- clampLocation(clientX, clientY) {
21048
-
21049
- const {width: w, height: h} = this.container.getBoundingClientRect();
21050
- const wh = window.innerHeight;
21051
- const ww = window.innerWidth;
21052
-
21053
- const y = Math.min(wh - h, clientY);
21054
- const x = Math.min(ww - w, clientX);
21055
- this.container.style.left = `${x}px`;
21056
- this.container.style.top = `${y}px`;
21057
-
21058
- }
21059
- }
21060
-
21061
20945
  class InputDialog {
21062
20946
 
21063
20947
  constructor(parent) {
@@ -24511,6 +24395,29 @@
24511
24395
 
24512
24396
  }
24513
24397
 
24398
+ function decodeShoebox(tokens, header, maxColumnCount = Number.MAX_SAFE_INTEGER) {
24399
+
24400
+ if (tokens.length < 4) return undefined
24401
+
24402
+ const chr = tokens[0];
24403
+ const start = parseInt(tokens[1]);
24404
+ const end = tokens.length > 2 ? parseInt(tokens[2]) : start + 1;
24405
+ if (isNaN(start) || isNaN(end)) {
24406
+ return new DecodeError(`Unparsable bed record.`)
24407
+ }
24408
+ const feature = new UCSCBedFeature({chr: chr, start: start, end: end, score: 1000});
24409
+
24410
+ const values = [];
24411
+ for(let i = 3; i< tokens.length; i++) {
24412
+ values.push(Number.parseInt(tokens[i]));
24413
+ }
24414
+ feature.values = values;
24415
+
24416
+
24417
+ return feature
24418
+ }
24419
+
24420
+
24514
24421
  class UCSCBedFeature {
24515
24422
 
24516
24423
  constructor(properties) {
@@ -25875,6 +25782,10 @@
25875
25782
  this.decode = decodeGcnv;
25876
25783
  this.delimiter = "\t";
25877
25784
  break
25785
+ case "shoebox":
25786
+ this.decode = decodeShoebox;
25787
+ this.delimiter = "\t";
25788
+ break
25878
25789
  default:
25879
25790
  const customFormat = getFormat(format);
25880
25791
  if (customFormat !== undefined) {
@@ -31961,14 +31872,25 @@
31961
31872
  this.config = config;
31962
31873
  this.bufferSize = BUFFER_SIZE;
31963
31874
  this.loader = isDataURL(this.path) ?
31964
- new DataBuffer(this.path) : igvxhr;
31875
+ new DataBuffer(decodeDataURI$1(this.path).buffer) :
31876
+ igvxhr;
31965
31877
 
31966
- if (config.searchTrix) {
31967
- this._trix = new Trix(`${config.searchTrix}x`, config.searchTrix);
31878
+ const trixURL = config.trixURL || config.searchTrix;
31879
+ if (trixURL) {
31880
+ this._trix = new Trix(`${trixURL}x`, trixURL);
31968
31881
  }
31969
31882
 
31970
31883
  }
31971
31884
 
31885
+ /**
31886
+ * Preload all the data for this bb file
31887
+ * @returns {Promise<void>}
31888
+ */
31889
+ async preload() {
31890
+ const data = await igvxhr.loadArrayBuffer(this.path);
31891
+ this.loader = new DataBuffer(data);
31892
+ }
31893
+
31972
31894
  async readWGFeatures(bpPerPixel, windowFunction) {
31973
31895
  await this.loadHeader();
31974
31896
  const chrIdx1 = 0;
@@ -31998,7 +31920,7 @@
31998
31920
  // Select a biwig "zoom level" appropriate for the current resolution.
31999
31921
  const zoomLevelHeaders = await this.getZoomHeaders();
32000
31922
  let zoomLevelHeader = bpPerPixel ? zoomLevelForScale(bpPerPixel, zoomLevelHeaders) : undefined;
32001
- if (zoomLevelHeader) {
31923
+ if (zoomLevelHeader && windowFunction != "none") {
32002
31924
  treeOffset = zoomLevelHeader.indexOffset;
32003
31925
  decodeFunction = decodeZoomData;
32004
31926
  } else {
@@ -32634,8 +32556,8 @@
32634
32556
 
32635
32557
  class DataBuffer {
32636
32558
 
32637
- constructor(dataURI) {
32638
- this.data = decodeDataURI$1(dataURI).buffer;
32559
+ constructor(data) {
32560
+ this.data = data;
32639
32561
  }
32640
32562
 
32641
32563
  /**
@@ -32693,7 +32615,7 @@
32693
32615
 
32694
32616
  queryable = true
32695
32617
  #wgValues = {}
32696
- windowFunctions = ["mean", "min", "max"]
32618
+ windowFunctions = ["mean", "min", "max", "none"]
32697
32619
 
32698
32620
  constructor(config, genome) {
32699
32621
  super(genome);
@@ -32848,7 +32770,8 @@
32848
32770
  scaleFactor: undefined,
32849
32771
  overflowColor: `rgb(255, 32, 255)`,
32850
32772
  baselineColor: 'lightGray',
32851
- summarize: true
32773
+ summarize: true,
32774
+ visibilityWindow: undefined
32852
32775
  }
32853
32776
 
32854
32777
  constructor(config, browser) {
@@ -32894,6 +32817,10 @@
32894
32817
  if (header) this.setTrackProperties(header);
32895
32818
  }
32896
32819
 
32820
+ supportsWholeGenome() {
32821
+ return this.visibilityWindow === undefined || this.visibilityWindow < 0
32822
+ }
32823
+
32897
32824
  async getFeatures(chr, start, end, bpPerPixel) {
32898
32825
 
32899
32826
  const windowFunction = this.windowFunction;
@@ -38017,6 +37944,16 @@
38017
37944
  const groupsTxtURL = baseURL + genome.getProperty("groups");
38018
37945
  groups = await loadStanzas(groupsTxtURL);
38019
37946
  }
37947
+
37948
+ // If the genome has a chromSizes file, and it is not too large, set the chromSizesURL property. This will
37949
+ // enable whole genome view and the chromosome pulldown
37950
+ if (genome.hasProperty("chromSizes")) {
37951
+ const chromSizesURL = baseURL + genome.getProperty("chromSizes");
37952
+ const l = await getContentLength(chromSizesURL);
37953
+ if (l !== null && Number.parseInt(l) < 1000000) {
37954
+ genome.setProperty("chromSizesURL", chromSizesURL);
37955
+ }
37956
+ }
38020
37957
  }
38021
37958
 
38022
37959
  // TODO -- categorize extra "user" supplied and other tracks in some distinctive way before including them
@@ -38119,10 +38056,15 @@
38119
38056
  name: name,
38120
38057
  twoBitURL: this.baseURL + this.genomeStanza.getProperty("twoBitPath"),
38121
38058
  nameSet: "ucsc",
38122
- wholeGenomeView: false,
38123
- showChromosomeWidget: false
38124
38059
  };
38125
38060
 
38061
+ if (this.genomeStanza.hasProperty("chromSizesURL")) {
38062
+ config.chromSizesURL = this.genomeStanza.getProperty("chromSizesURL");
38063
+ } else {
38064
+ config.wholeGenomeView = false;
38065
+ config.showChromosomeWidget = false;
38066
+ }
38067
+
38126
38068
  if (this.genomeStanza.hasProperty("defaultPos")) {
38127
38069
  const hubLocus = this.genomeStanza.getProperty("defaultPos");
38128
38070
  // Strip out coordinates => whole chromosome view
@@ -38323,7 +38265,7 @@
38323
38265
  config.searchIndex = t.getProperty("searchIndex");
38324
38266
  }
38325
38267
  if (t.hasProperty("searchTrix")) {
38326
- config.searchTrix = this.baseURL + t.getProperty("searchTrix");
38268
+ config.trixURL = this.baseURL + t.getProperty("searchTrix");
38327
38269
  }
38328
38270
 
38329
38271
  if (t.hasProperty("group")) {
@@ -38410,6 +38352,26 @@
38410
38352
  }
38411
38353
  }
38412
38354
 
38355
+
38356
+ /**
38357
+ * Return the content length of the resource. If the content length cannot be determined return null;
38358
+ * @param url
38359
+ * @returns {Promise<number|string>}
38360
+ */
38361
+ async function getContentLength(url) {
38362
+ try {
38363
+ const response = await fetch(url, {method: 'HEAD'});
38364
+ const headers = response.headers;
38365
+ if (headers.has("content-length")) {
38366
+ return headers.get("content-length")
38367
+ } else {
38368
+ return null
38369
+ }
38370
+ } catch (e) {
38371
+ return null
38372
+ }
38373
+ }
38374
+
38413
38375
  /**
38414
38376
  * Parse a UCSC file
38415
38377
  * @param url
@@ -41958,7 +41920,7 @@
41958
41920
 
41959
41921
  class NavbarButton {
41960
41922
 
41961
- constructor(browser, parent, title, buttonLabel, imageSVG, imageHoverSVG, initialButtonState) {
41923
+ constructor(parent, browser, title, buttonLabel, imageSVG, imageHoverSVG, initialButtonState) {
41962
41924
 
41963
41925
  this.browser = browser;
41964
41926
 
@@ -42015,7 +41977,7 @@
42015
41977
  }
42016
41978
 
42017
41979
  configureTextButton(textContent) {
42018
-
41980
+ console.log(`text ${this.title}`);
42019
41981
  this.button.classList.add('igv-navbar-text-button');
42020
41982
 
42021
41983
  const tempDiv = document.createElement('div');
@@ -42030,6 +41992,7 @@
42030
41992
  }
42031
41993
 
42032
41994
  configureIconButton() {
41995
+ console.log(`icon ${this.title}`);
42033
41996
  this.button.classList.add('igv-navbar-icon-button');
42034
41997
  }
42035
41998
 
@@ -42069,11 +42032,6 @@
42069
42032
  this.hide();
42070
42033
  }
42071
42034
  }
42072
-
42073
- static currentNavbarButtonClass(browser) {
42074
- const el = browser.$navigation.get(0).querySelector('.igv-navbar-text-button');
42075
- return el ? 'igv-navbar-text-button' : 'igv-navbar-icon-button'
42076
- }
42077
42035
  }
42078
42036
 
42079
42037
  const overlayTrackImage =
@@ -42282,6 +42240,19 @@
42282
42240
  return this._autoscale
42283
42241
  }
42284
42242
 
42243
+ set autoscaleGroup(g) {
42244
+ if(this.tracks) {
42245
+ for(let t of this.tracks) t.autoscaleGroup = g;
42246
+ }
42247
+ }
42248
+
42249
+ get autoscaleGroup() {
42250
+ if(this.tracks && this.tracks.length > 0) {
42251
+ const g = this.tracks[0].autoscaleGroup;
42252
+ return (this.tracks.some(t => g !== t.autoscaleGroup)) ? undefined : g
42253
+ }
42254
+ }
42255
+
42285
42256
  /**
42286
42257
  * Set the data range of all constitutive numeric tracks. This method is called from the menu item, i.e. an explicit
42287
42258
  * setting, so it should disable autoscale as well.
@@ -42646,9 +42617,9 @@
42646
42617
  };
42647
42618
 
42648
42619
  class OverlayTrackButton extends NavbarButton {
42649
- constructor(browser, parent) {
42620
+ constructor(parent, browser) {
42650
42621
 
42651
- super(browser, parent, 'Overlay Tracks', buttonLabel, overlayTrackImage, overlayTrackImageHover, false);
42622
+ super(parent, browser, 'Overlay Tracks', buttonLabel, overlayTrackImage, overlayTrackImageHover, false);
42652
42623
 
42653
42624
  this.button.addEventListener('mouseenter', () => this.setState(true));
42654
42625
  this.button.addEventListener('mouseleave', () => this.setState(false));
@@ -42671,15 +42642,15 @@
42671
42642
 
42672
42643
  if (true === isOverlayTrackCriteriaMet(this.browser)) {
42673
42644
 
42674
- const tracks = this.browser.getSelectedTrackViews().map(({ track }) => track);
42645
+ const tracks = this.browser.getSelectedTrackViews().map(({track}) => track);
42675
42646
  for (const track of tracks) {
42676
42647
  track.selected = false;
42677
42648
  }
42678
42649
 
42679
- // Flatten any merged tracks. Must do this before there removal
42650
+ // Flatten any merged tracks. Must do this before their removal
42680
42651
  const flattenedTracks = [];
42681
- for(let t of tracks) {
42682
- if("merged" === t.type) {
42652
+ for (let t of tracks) {
42653
+ if ("merged" === t.type) {
42683
42654
  flattenedTracks.push(...t.tracks);
42684
42655
  } else {
42685
42656
  flattenedTracks.push(t);
@@ -42692,17 +42663,20 @@
42692
42663
  type: 'merged',
42693
42664
  autoscale: false,
42694
42665
  alpha: 0.5, //fudge * (1.0/tracks.length),
42695
- height: Math.max(...tracks.map(({ height }) => height)),
42696
- order: Math.min(...tracks.map(({ order }) => order)),
42666
+ height: Math.max(...tracks.map(({height}) => height)),
42667
+ order: Math.min(...tracks.map(({order}) => order)),
42697
42668
  };
42698
42669
 
42699
42670
  const mergedTrack = new MergedTrack(config, this.browser, flattenedTracks);
42700
42671
 
42701
42672
  for (const track of tracks) {
42702
- this.browser.removeTrack(track);
42673
+ const idx = this.browser.trackViews.indexOf(track.trackView);
42674
+ this.browser.trackViews.splice(idx, 1);
42675
+ track.trackView.dispose();
42703
42676
  }
42704
42677
 
42705
42678
  this.browser.addTrack(config, mergedTrack);
42679
+ mergedTrack.trackView.updateViews();
42706
42680
 
42707
42681
  }
42708
42682
 
@@ -42714,9 +42688,9 @@
42714
42688
 
42715
42689
  if (selected && selected.length > 1) {
42716
42690
 
42717
- const criteriaSet = new Set([ 'wig', 'merged' ]);
42691
+ const criteriaSet = new Set(['wig', 'merged']);
42718
42692
 
42719
- const list = selected.filter(({ track }) => criteriaSet.has(track.type));
42693
+ const list = selected.filter(({track}) => criteriaSet.has(track.type));
42720
42694
 
42721
42695
  return list.length > 1
42722
42696
 
@@ -42831,6 +42805,8 @@
42831
42805
  createAxis(browser, track) {
42832
42806
 
42833
42807
  const axis = div();
42808
+ this.axis = axis;
42809
+
42834
42810
  browser.columnContainer.querySelector('.igv-axis-column').appendChild(axis);
42835
42811
 
42836
42812
  axis.dataset.tracktype = track.type;
@@ -42848,12 +42824,12 @@
42848
42824
 
42849
42825
  if (false === multiTrackSelectExclusionTypes.has(this.track.type)) {
42850
42826
 
42851
- const trackSelectionContainer = div();
42852
- axis.appendChild(trackSelectionContainer);
42827
+ this.trackSelectionContainer = div();
42828
+ axis.appendChild(this.trackSelectionContainer);
42853
42829
 
42854
42830
  const html = `<input type="checkbox" name="track-select">`;
42855
42831
  const input = document.createRange().createContextualFragment(html).firstChild;
42856
- trackSelectionContainer.appendChild(input);
42832
+ this.trackSelectionContainer.appendChild(input);
42857
42833
  input.checked = this.track.selected || false;
42858
42834
 
42859
42835
  input.addEventListener('change', event => {
@@ -42861,10 +42837,10 @@
42861
42837
  event.stopPropagation();
42862
42838
  this.track.selected = event.target.checked;
42863
42839
  this.setDragHandleSelectionState(event.target.checked);
42864
- this.browser.overlayTrackButton.setVisibility( isOverlayTrackCriteriaMet(this.browser) );
42840
+ this.browser.overlayTrackButton.setVisibility(isOverlayTrackCriteriaMet(this.browser));
42865
42841
  });
42866
42842
 
42867
- this.setTrackSelectionState(axis, false);
42843
+ this.enableTrackSelection(false);
42868
42844
 
42869
42845
  }
42870
42846
 
@@ -43674,13 +43650,19 @@
43674
43650
  return Math.max(...this.viewports.map(viewport => viewport.getContentHeight()))
43675
43651
  }
43676
43652
 
43677
- setTrackSelectionState(axis, doEnableMultiSelection) {
43653
+ enableTrackSelection(doEnableMultiSelection) {
43654
+
43655
+ const container = this.trackSelectionContainer;
43678
43656
 
43679
- const container = axis.querySelector('div');
43657
+ if (!container || multiTrackSelectExclusionTypes.has(this.track.type)) {
43658
+ return
43659
+ }
43680
43660
 
43681
43661
  if (false !== doEnableMultiSelection) {
43682
43662
  container.style.display = 'grid';
43683
43663
  } else {
43664
+ // If disabling selection set track selection state to false
43665
+ this.track.selected = false;
43684
43666
 
43685
43667
  const trackSelectInput = container.querySelector('[name=track-select]');
43686
43668
  trackSelectInput.checked = this.track.selected;
@@ -43706,13 +43688,11 @@
43706
43688
  dragHandle.classList.remove('igv-track-drag-handle-selected-color');
43707
43689
  dragHandle.classList.add('igv-track-drag-handle-color');
43708
43690
  }
43709
-
43710
43691
  }
43711
43692
 
43712
43693
  }
43713
43694
 
43714
43695
 
43715
-
43716
43696
  function renderSVGAxis(context, track, axisCanvas, deltaX, deltaY) {
43717
43697
 
43718
43698
  if (typeof track.paintAxis === 'function') {
@@ -43826,13 +43806,13 @@
43826
43806
  *
43827
43807
  */
43828
43808
 
43829
- const defaultColorScaleConfig = {threshold: 2000, r: 0, g: 0, b: 255};
43809
+ const defaultColorScaleConfig$1 = {threshold: 2000, r: 0, g: 0, b: 255};
43830
43810
 
43831
43811
  class HicColorScale {
43832
43812
 
43833
43813
  constructor(scale) {
43834
43814
 
43835
- scale = scale || defaultColorScaleConfig;
43815
+ scale = scale || defaultColorScaleConfig$1;
43836
43816
  this.threshold = scale.threshold;
43837
43817
  this.r = scale.r;
43838
43818
  this.g = scale.g;
@@ -49285,7 +49265,7 @@
49285
49265
  const READ_FAILS_VENDOR_QUALITY_CHECK_FLAG = 0x200;
49286
49266
  const DUPLICATE_READ_FLAG = 0x400;
49287
49267
  const SUPPLEMENTARY_ALIGNMENT_FLAG = 0x800;
49288
- const ELEMENT_SIZE = {
49268
+ const ELEMENT_SIZE$1 = {
49289
49269
  c: 1,
49290
49270
  C: 1,
49291
49271
  s: 2,
@@ -49370,14 +49350,6 @@
49370
49350
  }
49371
49351
 
49372
49352
  tags() {
49373
- if (!this.tagDict) {
49374
- if (this.tagBA) {
49375
- this.tagDict = decodeTags(this.tagBA);
49376
- this.tagBA = undefined;
49377
- } else {
49378
- this.tagDict = {}; // Mark so we don't try again. The record has no tags
49379
- }
49380
- }
49381
49353
  return this.tagDict
49382
49354
  }
49383
49355
 
@@ -49609,7 +49581,7 @@
49609
49581
  }
49610
49582
 
49611
49583
  getBaseModificationSets() {
49612
- this.tags();
49584
+
49613
49585
  if (!this.baseModificationSets && (this.tagDict["MM"] || this.tagDict["Mm"])) {
49614
49586
 
49615
49587
  const mm = this.tagDict["MM"] || this.tagDict["Mm"];
@@ -49733,7 +49705,7 @@
49733
49705
  } else if (type === 'B') {
49734
49706
  //‘cCsSiIf’, corresponding to int8 , uint8 t, int16 t, uint16 t, int32 t, uint32 t and float
49735
49707
  const elementType = String.fromCharCode(ba[p++]);
49736
- let elementSize = ELEMENT_SIZE[elementType];
49708
+ let elementSize = ELEMENT_SIZE$1[elementType];
49737
49709
  if (elementSize === undefined) {
49738
49710
  tags[tag] = `Error: unknown element type '${elementType}'`;
49739
49711
  break
@@ -49888,13 +49860,22 @@
49888
49860
  * https://github.com/dasmoth/dalliance/blob/master/js/bam.js
49889
49861
  */
49890
49862
  //=ACMGRSVTWYHKDBN
49863
+ const BAM1_MAGIC_BYTES = new Uint8Array([0x42, 0x41, 0x4d, 0x01]); // BAM\1
49864
+ const BAM1_MAGIC_NUMBER = readInt(BAM1_MAGIC_BYTES, 0);
49865
+
49891
49866
  const SEQ_DECODER = ['=', 'A', 'C', 'M', 'G', 'R', 'S', 'V', 'T', 'W', 'Y', 'H', 'K', 'D', 'B', 'N'];
49892
49867
  const CIGAR_DECODER = ['M', 'I', 'D', 'N', 'S', 'H', 'P', '=', 'X', '?', '?', '?', '?', '?', '?', '?'];
49893
49868
  const READ_STRAND_FLAG$1 = 0x10;
49894
49869
  const MATE_STRAND_FLAG$1 = 0x20;
49895
-
49896
- const BAM1_MAGIC_BYTES = new Uint8Array([0x42, 0x41, 0x4d, 0x01]); // BAM\1
49897
- const BAM1_MAGIC_NUMBER = readInt(BAM1_MAGIC_BYTES, 0);
49870
+ const ELEMENT_SIZE = {
49871
+ c: 1,
49872
+ C: 1,
49873
+ s: 2,
49874
+ S: 2,
49875
+ i: 4,
49876
+ I: 4,
49877
+ f: 4
49878
+ };
49898
49879
 
49899
49880
  const DEFAULT_ALLELE_FREQ_THRESHOLD = 0.2;
49900
49881
  const DEFAULT_SAMPLING_WINDOW_SIZE = 100;
@@ -50143,7 +50124,9 @@
50143
50124
 
50144
50125
  alignment.seq = seq;
50145
50126
  alignment.qual = qualArray;
50146
- alignment.tagBA = new Uint8Array(ba.buffer.slice(p, blockEnd)); // decode these on demand
50127
+
50128
+ const tagBA = new Uint8Array(ba.buffer.slice(p, blockEnd));
50129
+ alignment.tagDict = decodeBamTags(tagBA);
50147
50130
 
50148
50131
  this.setPairOrientation(alignment);
50149
50132
 
@@ -50454,6 +50437,109 @@
50454
50437
  return tagDict
50455
50438
  }
50456
50439
 
50440
+ /**
50441
+ * Decode bam tags from the supplied UInt8Array
50442
+ *
50443
+ * A [!-~] Printable character
50444
+ * i [-+]?[0-9]+ Signed integer16
50445
+ * f [-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)? Single-precision floating number
50446
+ * Z [ !-~]* Printable string, including space
50447
+ * H ([0-9A-F][0-9A-F])* Byte array in the Hex format17
50448
+ * B [cCsSiIf](,[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?)* Integer or numeric array
50449
+ *
50450
+ * @param ba A byte array (UInt8Array)
50451
+ * @returns {{}} Tag values
50452
+ */
50453
+ function decodeBamTags(ba) {
50454
+
50455
+ let p = 0;
50456
+ const len = ba.length;
50457
+ const tags = {};
50458
+ const dataView = new DataView(ba.buffer);
50459
+
50460
+ while (p < len) {
50461
+ const tag = String.fromCharCode(ba[p]) + String.fromCharCode(ba[p + 1]);
50462
+ p += 2;
50463
+
50464
+ const type = String.fromCharCode(ba[p++]);
50465
+ let value;
50466
+ if (type === 'A') {
50467
+ value = String.fromCharCode(ba[p]);
50468
+ p++;
50469
+ } else if (type === 'i' || type === 'I') {
50470
+ value = dataView.getInt32(p, true);
50471
+ p += 4;
50472
+ } else if (type === 'c') {
50473
+ value = dataView.getInt8(p, true);
50474
+ p++;
50475
+ } else if (type === 'C') {
50476
+ value = dataView.getUint8(p, true);
50477
+ p++;
50478
+ } else if (type === 's' || type === 'S') {
50479
+ value = dataView.getInt16(p, true);
50480
+ p += 2;
50481
+ } else if (type === 'f') {
50482
+ value = dataView.getFloat32(p, true);
50483
+ p += 4;
50484
+ } else if (type === 'Z') {
50485
+ value = '';
50486
+ for (; ;) {
50487
+ var cc = ba[p++];
50488
+ if (cc === 0) {
50489
+ break
50490
+ } else {
50491
+ value += String.fromCharCode(cc);
50492
+ }
50493
+ }
50494
+ } else if (type === 'B') {
50495
+ //‘cCsSiIf’, corresponding to int8 , uint8 t, int16 t, uint16 t, int32 t, uint32 t and float
50496
+ const elementType = String.fromCharCode(ba[p++]);
50497
+ let elementSize = ELEMENT_SIZE[elementType];
50498
+ if (elementSize === undefined) {
50499
+ tags[tag] = `Error: unknown element type '${elementType}'`;
50500
+ break
50501
+ }
50502
+ const numElements = dataView.getInt32(p, true);
50503
+ p += 4;
50504
+ const pEnd = p + numElements * elementSize;
50505
+ value = [];
50506
+
50507
+ while (p < pEnd) {
50508
+ switch (elementType) {
50509
+ case 'c':
50510
+ value.push(dataView.getInt8(p, true));
50511
+ break
50512
+ case 'C':
50513
+ value.push(dataView.getUint8(p, true));
50514
+ break
50515
+ case 's':
50516
+ value.push(dataView.getInt16(p, true));
50517
+ break
50518
+ case 'S':
50519
+ value.push(dataView.getUint16(p, true));
50520
+ break
50521
+ case 'i':
50522
+ value.push(dataView.getInt32(p, true));
50523
+ break
50524
+ case 'I':
50525
+ value.push(dataView.getUint32(p, true));
50526
+ break
50527
+ case 'f':
50528
+ value.push(dataView.getFloat32(p, true));
50529
+ }
50530
+ p += elementSize;
50531
+ }
50532
+ } else {
50533
+ //'Unknown type ' + type;
50534
+ value = 'Error unknown type: ' + type;
50535
+ tags[tag] = value;
50536
+ break
50537
+ }
50538
+ tags[tag] = value;
50539
+ }
50540
+ return tags
50541
+ }
50542
+
50457
50543
  /*
50458
50544
  * The MIT License (MIT)
50459
50545
  *
@@ -53929,6 +54015,10 @@
53929
54015
  if (firstLine.startsWith("##gff-version")) {
53930
54016
  return "gff"
53931
54017
  }
54018
+ if(firstLine.startsWith("##fileformat=")) {
54019
+ return firstLine.substring(13).toLowerCase(); // Non standard extension of VCF convention
54020
+ }
54021
+
53932
54022
 
53933
54023
  // QTL test must preceed GWAS test as GWAS files will also pass the QTL test
53934
54024
  if (QTLParser.isQTL(firstLine)) {
@@ -57165,10 +57255,6 @@
57165
57255
 
57166
57256
  function clickHandler() {
57167
57257
  this.alignmentTrack.colorBy = menuItem.key;
57168
- if ('strand' !== this.alignmentTrack.groupBy) {
57169
- this.alignmentTrack.groupBy = 'strand';
57170
- this.alignmentTrack.repackAlignments();
57171
- }
57172
57258
  this.trackView.repaintViews();
57173
57259
  }
57174
57260
 
@@ -67757,6 +67843,7 @@
67757
67843
  const searchConfig = browser.searchConfig || DEFAULT_SEARCH_CONFIG;
67758
67844
  let feature;
67759
67845
 
67846
+ name = name.toUpperCase();
67760
67847
  const searchableTracks = browser.tracks.filter(t => t.searchable);
67761
67848
  for (let track of searchableTracks) {
67762
67849
  const feature = await track.search(name);
@@ -70095,6 +70182,343 @@
70095
70182
  }
70096
70183
  }
70097
70184
 
70185
+ /*
70186
+ * The MIT License (MIT)
70187
+ *
70188
+ * Copyright (c) 2016-2017 The Regents of the University of California
70189
+ *
70190
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
70191
+ * associated documentation files (the "Software"), to deal in the Software without restriction, including
70192
+ * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
70193
+ * copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the
70194
+ * following conditions:
70195
+ *
70196
+ * The above copyright notice and this permission notice shall be included in all copies or substantial
70197
+ * portions of the Software.
70198
+ *
70199
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
70200
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
70201
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
70202
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
70203
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
70204
+ * THE SOFTWARE.
70205
+ *
70206
+ */
70207
+
70208
+ const defaultColorScaleConfig = {min: 0, max: 3000, color: "rgb(0,0,255)"};
70209
+
70210
+ class ShoeboxColorScale {
70211
+
70212
+ constructor(scale) {
70213
+
70214
+ scale = scale || defaultColorScaleConfig;
70215
+ this.max = scale.max;
70216
+ this.min = scale.min || 0;
70217
+ this.cache = [];
70218
+ this.nbins = 1000;
70219
+ this.binsize = (this.max - this.min) / this.nbins;
70220
+ this.updateColor(scale.color || "rgb(0,0,255)");
70221
+
70222
+ }
70223
+
70224
+ updateColor(color) {
70225
+ const comps = color.substring(4).replace(")", "").split(",");
70226
+ if (comps.length === 3) {
70227
+ this.r = Number.parseInt(comps[0].trim());
70228
+ this.g = Number.parseInt(comps[1].trim());
70229
+ this.b = Number.parseInt(comps[2].trim());
70230
+ }
70231
+ this.cache = [];
70232
+ }
70233
+
70234
+ setMinMax(min, max) {
70235
+ this.min = min;
70236
+ this.max = max;
70237
+ this.cache = [];
70238
+ this.binsize = (this.max - this.min) / this.nbins;
70239
+ }
70240
+
70241
+ getColor(value) {
70242
+ const low = 0;
70243
+ if (value < this.min) return "white"
70244
+
70245
+ const bin = Math.floor((Math.min(this.max, value) - this.min) / this.binsize);
70246
+ if (undefined === this.cache[bin]) {
70247
+ const alpha = (IGVMath.clamp(value, low, this.max) - low) / (this.max - low);
70248
+ this.cache[bin] = `rgba(${this.r},${this.g},${this.b}, ${alpha})`;
70249
+ }
70250
+ return this.cache[bin]
70251
+ }
70252
+
70253
+ /**
70254
+ *
70255
+ * @returns {{min: (*|number), color: string, max}}
70256
+ */
70257
+ toJson() {
70258
+ return {
70259
+ min: this.min,
70260
+ max: this.max,
70261
+ color: `rgb(${this.r},${this.g},${this.b})`
70262
+ }
70263
+ }
70264
+
70265
+ // For short-term backward compatibility
70266
+ static parse(str) {
70267
+
70268
+ const tokens = str.split(",");
70269
+
70270
+ const cs = {
70271
+ min: Number.parseFloat(tokens[0]),
70272
+ max: Number.parseFloat(tokens[1]),
70273
+ color: `${tokens[2]},${tokens[3]},${tokens[4]}`
70274
+ };
70275
+ return new ShoeboxColorScale(cs)
70276
+ }
70277
+
70278
+ }
70279
+
70280
+ class ShoeboxTrack extends TrackBase {
70281
+
70282
+ static defaults = {
70283
+ height: 300,
70284
+ rowHeight: 3,
70285
+ max: 3000,
70286
+ visibilityWindow: 10000
70287
+ }
70288
+
70289
+ constructor(config, browser) {
70290
+ super(config, browser);
70291
+ }
70292
+
70293
+ init(config) {
70294
+ super.init(config);
70295
+
70296
+ this.type = "shoebox";
70297
+ this.height = config.height || 300;
70298
+ this.rowHeight = config.rowHeight || 3;
70299
+ this.max = config.max || 3000;
70300
+
70301
+ // Hardcoded -- todo get from track line
70302
+ this.sampleKeys = [];
70303
+ for (let i = 1; i <= 100; i++) {
70304
+ this.sampleKeys.push(i);
70305
+ }
70306
+
70307
+ // Create featureSource
70308
+ const configCopy = Object.assign({}, this.config);
70309
+ configCopy.format = 'shoebox'; // bit of a hack
70310
+ this.featureSource = FeatureSource(configCopy, this.browser.genome);
70311
+ }
70312
+
70313
+ async postInit() {
70314
+ if (typeof this.featureSource.getHeader === "function") {
70315
+ this.header = await this.featureSource.getHeader();
70316
+ if (this.disposed) return // This track was removed during async load
70317
+ }
70318
+ // Set properties from track line
70319
+ if (this.header) {
70320
+ this.setTrackProperties(this.header);
70321
+ }
70322
+
70323
+ // Must do the following after setting track properties as they can be overriden via a track line
70324
+
70325
+ // Color settings
70326
+ if (this.config.colorScale && this.config.colorScale.max && this.config.colorScale.color) { // Minimal validation
70327
+ this.colorScale = new ShoeboxColorScale(this.config.colorScale);
70328
+
70329
+ } else {
70330
+ const min = this.dataRange.min;
70331
+ const max = this.dataRange.max;
70332
+ this.colorScale = new ShoeboxColorScale({min, max, color: this.color});
70333
+ }
70334
+ }
70335
+
70336
+ get color() {
70337
+ return this._color || "rgb(0,0,255)"
70338
+ }
70339
+
70340
+ set color(color) {
70341
+ this._color = color;
70342
+ if (this.colorScale) {
70343
+ this.colorScale.updateColor(color);
70344
+ }
70345
+ }
70346
+
70347
+ menuItemList() {
70348
+
70349
+ const menuItems = [];
70350
+
70351
+
70352
+ menuItems.push('<hr/>');
70353
+
70354
+ // Data range
70355
+ let object = $$1('<div>');
70356
+ object.text('Set data range');
70357
+
70358
+ function dialogPresentationHandler() {
70359
+
70360
+ if (this.trackView.track.selected) {
70361
+ this.browser.dataRangeDialog.configure(this.trackView.browser.getSelectedTrackViews());
70362
+ } else {
70363
+ this.browser.dataRangeDialog.configure(this.trackView);
70364
+ }
70365
+ this.browser.dataRangeDialog.present($$1(this.browser.columnContainer));
70366
+ }
70367
+
70368
+ menuItems.push({object, dialog: dialogPresentationHandler});
70369
+
70370
+ return menuItems
70371
+ }
70372
+
70373
+ setDataRange({min, max}) {
70374
+ this.dataRange.min = min;
70375
+ this.dataRange.max = max;
70376
+ this.colorScale.min = min;
70377
+ this.colorScale.max = max;
70378
+ this.trackView.repaintViews();
70379
+ }
70380
+
70381
+ hasSamples() {
70382
+ return true // by definition
70383
+ }
70384
+
70385
+ getSamples() {
70386
+ return {
70387
+ names: this.sampleKeys,
70388
+ height: this.rowHeight,
70389
+ yOffset: 0
70390
+ }
70391
+ }
70392
+
70393
+ async getFeatures(chr, start, end, bpPerPixel) {
70394
+ const visibilityWindow = this.visibilityWindow;
70395
+ return this.featureSource.getFeatures({chr, start, end, bpPerPixel, visibilityWindow})
70396
+ }
70397
+
70398
+
70399
+ draw({context, pixelTop, pixelWidth, pixelHeight, features, bpPerPixel, bpStart}) {
70400
+
70401
+
70402
+ IGVGraphics.fillRect(context, 0, pixelTop, pixelWidth, pixelHeight, {'fillStyle': "rgb(255, 255, 255)"});
70403
+
70404
+ if (features && features.length > 0) {
70405
+
70406
+ const rowHeight = this.rowHeight;
70407
+ const pixelBottom = pixelTop + pixelHeight;
70408
+ const bpEnd = bpStart + pixelWidth * bpPerPixel + 1;
70409
+
70410
+ const h = rowHeight;
70411
+
70412
+ for (let f of features) {
70413
+
70414
+ // Test for overlap with in-view region
70415
+ if (f.end < bpStart || f.start > bpEnd) continue
70416
+
70417
+ // Pixel x values
70418
+ const xLeft = Math.round((f.start - bpStart) / bpPerPixel);
70419
+ const xRight = Math.round((f.end - bpStart) / bpPerPixel);
70420
+ const w = Math.max(1, xRight - xLeft);
70421
+
70422
+ // Loop through value array
70423
+ let row = 0;
70424
+
70425
+ for (let i = f.values.length - 1; i >= 0; i--) {
70426
+
70427
+ const v = f.values[i];
70428
+
70429
+ const y = row * rowHeight;
70430
+
70431
+
70432
+ const bottom = y + rowHeight;
70433
+
70434
+ if (bottom < pixelTop || y > pixelBottom) {
70435
+ continue
70436
+ }
70437
+
70438
+ const color = this.colorScale.getColor(v);
70439
+
70440
+ context.fillStyle = color;
70441
+
70442
+ context.fillRect(xLeft, y, w, h);
70443
+
70444
+ row++;
70445
+ }
70446
+ }
70447
+ }
70448
+
70449
+ }
70450
+
70451
+ /**
70452
+ * Optional method to compute pixel height to accomodate the list of features.
70453
+ *
70454
+ * @param features
70455
+ * @returns {number}
70456
+ */
70457
+ computePixelHeight(features) {
70458
+ if (!features || features.length === 0) return 0
70459
+ return features[0].values.length * this.rowHeight
70460
+ }
70461
+
70462
+
70463
+ clickedFeatures(clickState) {
70464
+
70465
+ const allFeatures = super.clickedFeatures(clickState);
70466
+ const y = clickState.y;
70467
+ return allFeatures.filter(function (feature) {
70468
+ const rect = feature.pixelRect;
70469
+ return rect && y >= rect.y && y <= (rect.y + rect.h)
70470
+ })
70471
+
70472
+ }
70473
+
70474
+ hoverText(clickState) {
70475
+ const features = this.clickedFeatures(clickState);
70476
+ if (features && features.length > 0) {
70477
+ return `${features[0].sample}: ${features[0].value}`
70478
+ }
70479
+ }
70480
+
70481
+ popupData(clickState, featureList) {
70482
+
70483
+ if (featureList === undefined) featureList = this.clickedFeatures(clickState);
70484
+
70485
+ const items = [];
70486
+
70487
+ for (let feature of featureList) {
70488
+
70489
+ // Double line divider between features
70490
+ if (items.length > 0) {
70491
+ items.push('<hr/>');
70492
+ items.push('<hr/>');
70493
+ }
70494
+
70495
+ // hack for whole genome features, which save the original feature as "_f"
70496
+ const f = feature._f || feature;
70497
+
70498
+ const data = (typeof f.popupData === 'function') ?
70499
+ f.popupData(this.type, this.browser.genome.id) :
70500
+ this.extractPopupData(f);
70501
+ Array.prototype.push.apply(items, data);
70502
+
70503
+ }
70504
+
70505
+ return items
70506
+ }
70507
+
70508
+ get supportsWholeGenome() {
70509
+ return false
70510
+ }
70511
+
70512
+ getState() {
70513
+
70514
+ const config = super.getState();
70515
+ config.colorScale = this.colorScale.toJson();
70516
+ return config
70517
+
70518
+ }
70519
+
70520
+ }
70521
+
70098
70522
  //import CNVPytorTrack from "./CNVpytor/cnvpytorTrack.js"
70099
70523
 
70100
70524
 
@@ -70106,7 +70530,7 @@
70106
70530
  ['seg', (config, browser) => new SegTrack(config, browser)],
70107
70531
  ['mut', (config, browser) => new SegTrack(config, browser)],
70108
70532
  ['maf', (config, browser) => new SegTrack(config, browser)],
70109
- ['shoebox', (config, browser) => new SegTrack(config, browser)],
70533
+ ['shoebox', (config, browser) => new ShoeboxTrack(config, browser)],
70110
70534
  ['wig', (config, browser) => new WigTrack(config, browser)],
70111
70535
  ['merged', (config, browser) => new MergedTrack(config, browser)],
70112
70536
  ['alignment', (config, browser) => new BAMTrack(config, browser)],
@@ -70598,94 +71022,11 @@
70598
71022
  })
70599
71023
  }
70600
71024
 
70601
- const _version = "3.0.7";
71025
+ const _version = "3.0.9";
70602
71026
  function version() {
70603
71027
  return _version
70604
71028
  }
70605
71029
 
70606
- /*
70607
- * The MIT License (MIT)
70608
- *
70609
- * Copyright (c) 2014 Broad Institute
70610
- *
70611
- * Permission is hereby granted, free of charge, to any person obtaining a copy
70612
- * of this software and associated documentation files (the "Software"), to deal
70613
- * in the Software without restriction, including without limitation the rights
70614
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
70615
- * copies of the Software, and to permit persons to whom the Software is
70616
- * furnished to do so, subject to the following conditions:
70617
- *
70618
- * The above copyright notice and this permission notice shall be included in
70619
- * all copies or substantial portions of the Software.
70620
- *
70621
- *
70622
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
70623
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
70624
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
70625
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
70626
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
70627
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
70628
- * THE SOFTWARE.
70629
- */
70630
-
70631
- const navbarResponsiveClasses = {};
70632
-
70633
- const responsiveThreshold = 8;
70634
- let textButtonContainerWidth = undefined;
70635
-
70636
- function navbarDidResize(browser, width) {
70637
-
70638
- const currentClass = NavbarButton.currentNavbarButtonClass(browser);
70639
- if ('igv-navbar-text-button' === currentClass) {
70640
- textButtonContainerWidth = browser.$navigation.get(0).querySelector('.igv-navbar-right-container').getBoundingClientRect().width;
70641
- }
70642
-
70643
- const responsiveClasses = getResponsiveClasses(browser, width);
70644
-
70645
- $$1(browser.zoomWidget.zoomContainer).removeClass();
70646
- $$1(browser.zoomWidget.zoomContainer).addClass(responsiveClasses.zoomContainer);
70647
-
70648
- browser.fireEvent('navbar-resize', [ responsiveClasses.navbarButton ]);
70649
- }
70650
-
70651
- function getResponsiveClasses(browser, navbarWidth) {
70652
-
70653
- const isWGV =
70654
- (browser.isMultiLocusWholeGenomeView()) ||
70655
- (browser.referenceFrameList && GenomeUtils.isWholeGenomeView(browser.referenceFrameList[0].chr));
70656
-
70657
- isWGV ? browser.windowSizePanel.hide() : browser.windowSizePanel.show();
70658
-
70659
- const { x: leftContainerX, width: leftContainerWidth } = browser.$navigation.get(0).querySelector('.igv-navbar-left-container').getBoundingClientRect();
70660
- const leftContainerExtent = leftContainerX + leftContainerWidth;
70661
- const { x:rightContainerX} = browser.$navigation.get(0).querySelector('.igv-navbar-right-container').getBoundingClientRect();
70662
-
70663
- const delta = rightContainerX - leftContainerExtent;
70664
-
70665
- const currentClass = NavbarButton.currentNavbarButtonClass(browser);
70666
-
70667
- // console.log(`Current class ${ currentClass } Delta: ${ StringUtils.numberFormatter(Math.floor(delta))}`)
70668
-
70669
- if ('igv-navbar-text-button' === currentClass && delta < responsiveThreshold) {
70670
- navbarResponsiveClasses.navbarButton = 'igv-navbar-icon-button';
70671
- } else if (textButtonContainerWidth && 'igv-navbar-icon-button' === currentClass) {
70672
- const length = navbarWidth - leftContainerExtent;
70673
- if (length - textButtonContainerWidth > responsiveThreshold) {
70674
- navbarResponsiveClasses.navbarButton = 'igv-navbar-text-button';
70675
- }
70676
-
70677
- }
70678
-
70679
-
70680
- if (isWGV) {
70681
- navbarResponsiveClasses.zoomContainer = 'igv-zoom-widget-hidden';
70682
- } else {
70683
- navbarResponsiveClasses.zoomContainer = navbarWidth > 860 ? 'igv-zoom-widget' : 'igv-zoom-widget-900';
70684
- }
70685
-
70686
- return navbarResponsiveClasses
70687
- }
70688
-
70689
71030
  /*
70690
71031
  * The MIT License (MIT)
70691
71032
  *
@@ -70733,7 +71074,7 @@
70733
71074
  });
70734
71075
 
70735
71076
  this.showAllChromosomes = browser.config.showAllChromosomes !== false; // i.e. default to true
70736
-
71077
+ this.genome = browser.genome;
70737
71078
  }
70738
71079
 
70739
71080
  show() {
@@ -70744,10 +71085,16 @@
70744
71085
  this.container.style.display = 'none';
70745
71086
  }
70746
71087
 
71088
+ setValue(chrName) {
71089
+ this.select.value = this.genome.getChromosomeDisplayName(chrName);
71090
+ }
71091
+
70747
71092
  update(genome) {
70748
71093
 
71094
+ this.genome = genome;
71095
+
70749
71096
  // Start with explicit chromosome name list
70750
- const list = genome.wgChromosomeNames || [];
71097
+ const list = genome.wgChromosomeNames.map(nm => genome.getChromosomeDisplayName(nm)) || [];
70751
71098
 
70752
71099
  if (this.showAllChromosomes && genome.chromosomeNames.length > 1) {
70753
71100
  const exclude = new Set(list);
@@ -70758,6 +71105,7 @@
70758
71105
  break
70759
71106
  }
70760
71107
  if (!exclude.has(nm)) {
71108
+ nm = genome.getChromosomeDisplayName(nm);
70761
71109
  list.push(nm);
70762
71110
  }
70763
71111
  }
@@ -70838,6 +71186,99 @@
70838
71186
  }
70839
71187
  }
70840
71188
 
71189
+ const multiSelectImage =
71190
+ `<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">
71191
+ <title>multi select</title>
71192
+ <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
71193
+ <g id="multi-select">
71194
+ <rect id="backdrop-copy-3" stroke="#737373" stroke-width="12" fill="#FFFFFF" x="6" y="6" width="613" height="613" rx="135"></rect>
71195
+ <g id="row-copy-3" transform="translate(81, 427)" fill="#737373">
71196
+ <rect id="Rectangle" x="134" y="0" width="329" height="70"></rect>
71197
+ <rect id="Rectangle-Copy-16" stroke="#737373" stroke-width="12" x="6" y="6" width="58" height="58"></rect>
71198
+ </g>
71199
+ <g id="row-copy-2" transform="translate(82, 277)">
71200
+ <rect id="Rectangle" fill-opacity="0.33" fill="#CFCECE" x="133" y="0" width="329" height="70"></rect>
71201
+ <rect id="Rectangle-Copy-16" stroke-opacity="0.32659528" stroke="#CFCECE" stroke-width="12" x="6" y="6" width="58" height="58"></rect>
71202
+ </g>
71203
+ <g id="row-copy" transform="translate(81, 119)" fill="#737373">
71204
+ <rect id="Rectangle" x="134" y="0" width="329" height="70"></rect>
71205
+ <rect id="Rectangle-Copy-17" stroke="#737373" stroke-width="12" x="6" y="6" width="58" height="58"></rect>
71206
+ </g>
71207
+ </g>
71208
+ </g>
71209
+ </svg>`;
71210
+
71211
+ const multiSelectImageHover =
71212
+ `<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">
71213
+ <title>multi select hover</title>
71214
+ <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
71215
+ <g id="multi-select-hover">
71216
+ <rect id="backdrop-copy-4" stroke="#737373" stroke-width="12" fill="#737373" x="6" y="6" width="613" height="613" rx="135"></rect>
71217
+ <g id="row-copy-3" transform="translate(81, 427)" fill="#FFFFFF">
71218
+ <rect id="Rectangle" x="134" y="0" width="329" height="70"></rect>
71219
+ <rect id="Rectangle-Copy-16" stroke="#FFFFFF" stroke-width="12" x="6" y="6" width="58" height="58"></rect>
71220
+ </g>
71221
+ <g id="row-copy-2" transform="translate(82, 277)">
71222
+ <rect id="Rectangle" fill-opacity="0.33" fill="#CFCECE" x="133" y="0" width="329" height="70"></rect>
71223
+ <rect id="Rectangle-Copy-16" stroke-opacity="0.33" stroke="#CFCECE" stroke-width="12" x="6" y="6" width="58" height="58"></rect>
71224
+ </g>
71225
+ <g id="row-copy" transform="translate(81, 119)" fill="#FFFFFF">
71226
+ <rect id="Rectangle" x="134" y="0" width="329" height="70"></rect>
71227
+ <rect id="Rectangle-Copy-17" stroke="#FFFFFF" stroke-width="12" x="6" y="6" width="58" height="58"></rect>
71228
+ </g>
71229
+ </g>
71230
+ </g>
71231
+ </svg>`;
71232
+
71233
+ class MultiTrackSelectButton extends NavbarButton {
71234
+
71235
+ constructor(parent, browser, navbar, enableMultiTrackSelection) {
71236
+
71237
+ super(parent, browser, 'Select Tracks', buttonLabel, multiSelectImage, multiSelectImageHover, false);
71238
+
71239
+ this.navbar = navbar;
71240
+ this.enableMultiTrackSelection = false; // Initial state
71241
+ this.button.addEventListener('mouseenter', event => {
71242
+ if (false === enableMultiTrackSelection) {
71243
+ this.setState(true);
71244
+ }
71245
+ });
71246
+
71247
+ this.button.addEventListener('mouseleave', event => {
71248
+ if (false === enableMultiTrackSelection) {
71249
+ this.setState(false);
71250
+ }
71251
+ });
71252
+
71253
+ const mouseClickHandler = () => {
71254
+ // Toggle the selection state
71255
+ this.setMultiTrackSelection(!this.enableMultiTrackSelection);
71256
+ };
71257
+
71258
+ this.boundMouseClickHandler = mouseClickHandler.bind(this);
71259
+
71260
+ this.button.addEventListener('click', this.boundMouseClickHandler);
71261
+
71262
+ }
71263
+
71264
+ setMultiTrackSelection(enableMultiTrackSelection) {
71265
+
71266
+ this.enableMultiTrackSelection = enableMultiTrackSelection;
71267
+ this.setState(this.enableMultiTrackSelection);
71268
+
71269
+ // If enableMultiTrackSelection is false hide the Overly button
71270
+ if (false === this.enableMultiTrackSelection) {
71271
+ this.navbar.overlayTrackButton.setVisibility(false);
71272
+ }
71273
+
71274
+ for (const trackView of this.browser.trackViews) {
71275
+ trackView.enableTrackSelection(enableMultiTrackSelection);
71276
+ }
71277
+
71278
+ }
71279
+
71280
+ }
71281
+
70841
71282
  class CursorGuide {
70842
71283
 
70843
71284
  constructor(columnContainer, browser) {
@@ -71019,9 +71460,9 @@
71019
71460
 
71020
71461
  class CursorGuideButton extends NavbarButton {
71021
71462
 
71022
- constructor(browser, parent) {
71463
+ constructor(parent, browser) {
71023
71464
 
71024
- super(browser, parent, 'Crosshairs', buttonLabel, cursorImage, cursorImageHover, browser.doShowCursorGuide);
71465
+ super(parent, browser, 'Crosshairs', buttonLabel, cursorImage, cursorImageHover, browser.doShowCursorGuide);
71025
71466
 
71026
71467
  this.button.addEventListener('mouseenter', () => {
71027
71468
  if (false === browser.doShowCursorGuide) {
@@ -71107,9 +71548,9 @@
71107
71548
 
71108
71549
  class CenterLineButton extends NavbarButton {
71109
71550
 
71110
- constructor(browser, parent) {
71551
+ constructor(parent, browser) {
71111
71552
 
71112
- super(browser, parent, 'Center Line', buttonLabel, centerlineImage, centerlineImageHover, browser.config.showCenterGuide);
71553
+ super(parent, browser, 'Center Line', buttonLabel, centerlineImage, centerlineImageHover, browser.config.showCenterGuide);
71113
71554
 
71114
71555
  this.button.addEventListener('mouseenter', () => {
71115
71556
  if (false === browser.doShowCenterLine) {
@@ -71198,7 +71639,7 @@
71198
71639
 
71199
71640
  constructor(parent, browser) {
71200
71641
 
71201
- super(browser, parent, 'Track Labels', buttonLabel, trackLabelsImage, trackLabelsImageHover, browser.config.showTrackLabels);
71642
+ super(parent, browser, 'Track Labels', buttonLabel, trackLabelsImage, trackLabelsImageHover, browser.config.showTrackLabels);
71202
71643
 
71203
71644
  this.button.addEventListener('mouseenter', () => {
71204
71645
  if (false === browser.doShowTrackLabels) {
@@ -71228,28 +71669,28 @@
71228
71669
 
71229
71670
  }
71230
71671
 
71231
- const sampleNameImage =
71672
+ const roiImage =
71232
71673
  `<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">
71233
- <title>sample names</title>
71674
+ <title>roi</title>
71234
71675
  <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
71235
- <g id="sample-names" stroke="#737373">
71236
- <rect id="Rectangle-Copy-13" stroke-width="12" fill="#FFFFFF" x="6" y="6" width="613" height="613" rx="135"></rect>
71237
- <line x1="80" y1="465" x2="541" y2="464.5" id="Line-3-Copy-3" stroke-width="32"></line>
71238
- <line x1="80" y1="312.5" x2="542" y2="313" id="Line-3" stroke-width="32"></line>
71239
- <line x1="80" y1="158" x2="541" y2="158" id="Line-3-Copy" stroke-width="32"></line>
71676
+ <g id="roi">
71677
+ <rect id="Rectangle-Copy-23" stroke="#737373" stroke-width="12" fill="#FFFFFF" x="6" y="6" width="613" height="613" rx="135"></rect>
71678
+ <text id="ROI" font-family="HelveticaNeue-Bold, Helvetica Neue" font-size="258" font-weight="bold" fill="#737373">
71679
+ <tspan x="81.445" y="389">ROI</tspan>
71680
+ </text>
71240
71681
  </g>
71241
71682
  </g>
71242
71683
  </svg>`;
71243
71684
 
71244
- const sampleNameImageHover =
71685
+ const roiImageHover =
71245
71686
  `<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">
71246
- <title>sample names hover</title>
71687
+ <title>roi hover</title>
71247
71688
  <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
71248
- <g id="sample-names-hover">
71249
- <rect id="Rectangle-Copy-18" stroke="#737373" stroke-width="12" fill="#737373" x="6" y="6" width="613" height="613" rx="135"></rect>
71250
- <line x1="80" y1="465" x2="541" y2="464.5" id="Line-3-Copy-3" stroke="#FFFFFF" stroke-width="32" fill="#FFFFFF"></line>
71251
- <line x1="80" y1="312.5" x2="542" y2="313" id="Line-3" stroke="#FFFFFF" stroke-width="32" fill="#FFFFFF"></line>
71252
- <line x1="80" y1="158" x2="541" y2="158" id="Line-3-Copy" stroke="#FFFFFF" stroke-width="32" fill="#FFFFFF"></line>
71689
+ <g id="roi-hover">
71690
+ <rect id="Rectangle-Copy-24" stroke="#737373" stroke-width="12" fill="#737373" x="6" y="6" width="613" height="613" rx="135"></rect>
71691
+ <text id="ROI" font-family="HelveticaNeue-Bold, Helvetica Neue" font-size="258" font-weight="bold" fill="#FFFFFF">
71692
+ <tspan x="81.445" y="389">ROI</tspan>
71693
+ </text>
71253
71694
  </g>
71254
71695
  </g>
71255
71696
  </svg>`;
@@ -71280,49 +71721,34 @@
71280
71721
  * THE SOFTWARE.
71281
71722
  */
71282
71723
 
71283
- class SampleNameControl extends NavbarButton {
71724
+ class ROITableControl extends NavbarButton {
71284
71725
 
71285
- constructor(parent, browser) {
71726
+ constructor(parent, browser) {
71286
71727
 
71287
- super(browser, parent, 'Sample Names', sampleNameButtonLabel, sampleNameImage, sampleNameImageHover, browser.config.showSampleNames);
71728
+ super(parent, browser, ['ROI', 'Regions of Interest Table'], buttonLabel, roiImage, roiImageHover, false);
71288
71729
 
71289
71730
  this.button.addEventListener('mouseenter', () => {
71290
- if (false === browser.showSampleNames) {
71731
+ if (false === browser.doShowROITable) {
71291
71732
  this.setState(true);
71292
71733
  }
71293
71734
  });
71294
71735
 
71295
71736
  this.button.addEventListener('mouseleave', () => {
71296
- if (false === browser.showSampleNames) {
71737
+ if (false === browser.doShowROITable) {
71297
71738
  this.setState(false);
71298
71739
  }
71299
71740
  });
71300
71741
 
71301
- this.button.addEventListener('click', () => {
71302
- this.performClickWithState(browser, undefined);
71303
- });
71742
+ this.button.addEventListener('click', () => this.buttonHandler(!browser.doShowROITable));
71304
71743
 
71305
- if (true === browser.config.showSampleNameButton) {
71306
- this.show();
71307
- } else {
71308
- this.hide();
71309
- }
71744
+ this.setVisibility(false); // Hide initially, it will be un-hidden if ROIs are loaded
71310
71745
 
71311
71746
  }
71312
71747
 
71313
- performClickWithState(browser, doShowSampleNamesOrUndefined) {
71314
-
71315
- browser.showSampleNames = undefined === doShowSampleNamesOrUndefined ? !browser.showSampleNames : doShowSampleNamesOrUndefined;
71316
-
71317
- const column = browser.columnContainer.querySelector('.igv-sample-name-column');
71318
- column.style.display = false === browser.showSampleNames ? 'none' : 'flex';
71319
-
71320
- this.setState(browser.showSampleNames);
71321
-
71322
- browser.layoutChange();
71323
-
71748
+ buttonHandler(status) {
71749
+ this.setState(status);
71750
+ this.browser.setROITableVisibility(status);
71324
71751
  }
71325
-
71326
71752
  }
71327
71753
 
71328
71754
  const sampleInfoImage =
@@ -71426,7 +71852,7 @@
71426
71852
 
71427
71853
  constructor(parent, browser) {
71428
71854
 
71429
- super(browser, parent, 'Sample Info', buttonLabel, sampleInfoImage, sampleInfoImageHover, false);
71855
+ super(parent, browser, 'Sample Info', buttonLabel, sampleInfoImage, sampleInfoImageHover, false);
71430
71856
 
71431
71857
  this.showSampleInfo = false;
71432
71858
 
@@ -71476,141 +71902,102 @@
71476
71902
 
71477
71903
  }
71478
71904
 
71479
- const sliderMin = 0;
71480
- let sliderMax = 23;
71481
- let sliderValueRaw = 0;
71482
-
71483
- const ZoomWidget = function (browser, parent) {
71484
-
71485
- this.browser = browser;
71486
-
71487
- this.zoomContainer = div({class: 'igv-zoom-widget'});
71488
- parent.appendChild(this.zoomContainer);
71489
-
71490
- // zoom out
71491
- this.zoomOutButton = div();
71492
- this.zoomContainer.appendChild(this.zoomOutButton);
71493
- this.zoomOutButton.appendChild(createIcon('minus-circle'));
71494
- this.zoomOutButton.addEventListener('click', () => {
71495
- // browser.zoomWithScaleFactor(2.0)
71496
- browser.zoomOut();
71497
- });
71498
-
71499
- // Range slider
71500
- const el = div();
71501
- this.zoomContainer.appendChild(el);
71502
- this.slider = document.createElement('input');
71503
- this.slider.type = 'range';
71504
-
71505
- this.slider.min = `${sliderMin}`;
71506
- this.slider.max = `${sliderMax}`;
71507
-
71508
- el.appendChild(this.slider);
71509
-
71510
- this.slider.addEventListener('change', e => {
71511
-
71512
- e.preventDefault();
71513
- e.stopPropagation();
71514
-
71515
- const referenceFrame = browser.referenceFrameList[0];
71516
- const {bpLength} = referenceFrame.genome.getChromosome(referenceFrame.chr);
71517
- const {end, start} = referenceFrame;
71905
+ const sampleNameImage =
71906
+ `<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">
71907
+ <title>sample names</title>
71908
+ <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
71909
+ <g id="sample-names" stroke="#737373">
71910
+ <rect id="Rectangle-Copy-13" stroke-width="12" fill="#FFFFFF" x="6" y="6" width="613" height="613" rx="135"></rect>
71911
+ <line x1="80" y1="465" x2="541" y2="464.5" id="Line-3-Copy-3" stroke-width="32"></line>
71912
+ <line x1="80" y1="312.5" x2="542" y2="313" id="Line-3" stroke-width="32"></line>
71913
+ <line x1="80" y1="158" x2="541" y2="158" id="Line-3-Copy" stroke-width="32"></line>
71914
+ </g>
71915
+ </g>
71916
+ </svg>`;
71518
71917
 
71519
- const extent = end - start;
71918
+ const sampleNameImageHover =
71919
+ `<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">
71920
+ <title>sample names hover</title>
71921
+ <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
71922
+ <g id="sample-names-hover">
71923
+ <rect id="Rectangle-Copy-18" stroke="#737373" stroke-width="12" fill="#737373" x="6" y="6" width="613" height="613" rx="135"></rect>
71924
+ <line x1="80" y1="465" x2="541" y2="464.5" id="Line-3-Copy-3" stroke="#FFFFFF" stroke-width="32" fill="#FFFFFF"></line>
71925
+ <line x1="80" y1="312.5" x2="542" y2="313" id="Line-3" stroke="#FFFFFF" stroke-width="32" fill="#FFFFFF"></line>
71926
+ <line x1="80" y1="158" x2="541" y2="158" id="Line-3-Copy" stroke="#FFFFFF" stroke-width="32" fill="#FFFFFF"></line>
71927
+ </g>
71928
+ </g>
71929
+ </svg>`;
71520
71930
 
71521
- // bpLength/(end - start)
71522
- const scaleFactor = Math.pow(2, e.target.valueAsNumber);
71931
+ /*
71932
+ * The MIT License (MIT)
71933
+ *
71934
+ * Copyright (c) 2016 University of California San Diego
71935
+ * Author: Jim Robinson
71936
+ *
71937
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
71938
+ * of this software and associated documentation files (the "Software"), to deal
71939
+ * in the Software without restriction, including without limitation the rights
71940
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
71941
+ * copies of the Software, and to permit persons to whom the Software is
71942
+ * furnished to do so, subject to the following conditions:
71943
+ *
71944
+ * The above copyright notice and this permission notice shall be included in
71945
+ * all copies or substantial portions of the Software.
71946
+ *
71947
+ *
71948
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
71949
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
71950
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
71951
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
71952
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
71953
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
71954
+ * THE SOFTWARE.
71955
+ */
71523
71956
 
71524
- // (end - start) = bpLength/scaleFactor
71525
- const zoomedExtent = bpLength / scaleFactor;
71957
+ class SampleNameControl extends NavbarButton {
71526
71958
 
71527
- // console.log(`zoom-widget - slider ${ e.target.value } scaleFactor ${ scaleFactor } extent-zoomed ${ StringUtils.numberFormatter(Math.round(zoomedExtent)) }`)
71959
+ constructor(parent, browser) {
71528
71960
 
71529
- browser.zoomWithScaleFactor(zoomedExtent / extent);
71961
+ super(parent, browser, 'Sample Names', sampleNameButtonLabel, sampleNameImage, sampleNameImageHover, browser.config.showSampleNames);
71530
71962
 
71531
- });
71963
+ this.button.addEventListener('mouseenter', () => {
71964
+ if (false === browser.showSampleNames) {
71965
+ this.setState(true);
71966
+ }
71967
+ });
71532
71968
 
71533
- // zoom in
71534
- this.zoomInButton = div();
71535
- this.zoomContainer.appendChild(this.zoomInButton);
71536
- this.zoomInButton.appendChild(createIcon('plus-circle'));
71537
- this.zoomInButton.addEventListener('click', () => {
71538
- // browser.zoomWithScaleFactor(0.5)
71539
- browser.zoomIn();
71540
- });
71969
+ this.button.addEventListener('mouseleave', () => {
71970
+ if (false === browser.showSampleNames) {
71971
+ this.setState(false);
71972
+ }
71973
+ });
71541
71974
 
71542
- browser.on('locuschange', (referenceFrameList) => {
71975
+ this.button.addEventListener('click', () => {
71976
+ this.performClickWithState(browser, undefined);
71977
+ });
71543
71978
 
71544
- if (this.browser.isMultiLocusMode()) {
71545
- this.disable();
71979
+ if (true === browser.config.showSampleNameButton) {
71980
+ this.show();
71546
71981
  } else {
71547
- this.enable();
71548
- this.update(referenceFrameList);
71982
+ this.hide();
71549
71983
  }
71550
71984
 
71551
- });
71552
-
71553
- };
71554
-
71555
- ZoomWidget.prototype.update = function (referenceFrameList) {
71556
-
71557
- const referenceFrame = referenceFrameList[0];
71558
- const {bpLength} = referenceFrame.genome.getChromosome(referenceFrame.chr);
71559
- const {start, end} = referenceFrame;
71560
-
71561
- sliderMax = Math.ceil(Math.log2(bpLength / this.browser.minimumBases()));
71562
-
71563
- this.slider.max = `${sliderMax}`;
71564
-
71565
- const scaleFactor = bpLength / (end - start);
71566
- sliderValueRaw = Math.log2(scaleFactor);
71567
- this.slider.value = `${Math.round(sliderValueRaw)}`;
71568
-
71569
- // referenceFrame.description('zoom.update')
71570
-
71571
- // console.log(`${ Date.now() } update - slider ${ this.slider.value } scaleFactor ${ Math.round(scaleFactor) } extent ${ StringUtils.numberFormatter(Math.round(extent)) }`)
71572
-
71573
- // console.log(`update - sliderMin ${ sliderMin } sliderValue ${ this.slider.value } sliderMax ${ sliderMax } scaleFactor ${ scaleFactor.toFixed(3) } derived-scaleFactor ${ derivedScalefactor.toFixed(3) }`)
71574
-
71575
- };
71576
-
71577
- ZoomWidget.prototype.enable = function () {
71578
-
71579
- // this.zoomInButton.style.color = appleCrayonPalette[ 'steel' ];
71580
- // this.zoomInButton.style.pointerEvents = 'auto';
71581
- //
71582
- // this.zoomOutButton.style.color = appleCrayonPalette[ 'steel' ];
71583
- // this.zoomOutButton.style.pointerEvents = 'auto';
71584
-
71585
- this.slider.disabled = false;
71586
- };
71985
+ }
71587
71986
 
71588
- ZoomWidget.prototype.disable = function () {
71987
+ performClickWithState(browser, doShowSampleNamesOrUndefined) {
71589
71988
 
71590
- // this.zoomInButton.style.color = appleCrayonPalette[ 'silver' ];
71591
- // this.zoomInButton.style.pointerEvents = 'none';
71592
- //
71593
- // this.zoomOutButton.style.color = appleCrayonPalette[ 'silver' ];
71594
- // this.zoomOutButton.style.pointerEvents = 'none';
71989
+ browser.showSampleNames = undefined === doShowSampleNamesOrUndefined ? !browser.showSampleNames : doShowSampleNamesOrUndefined;
71595
71990
 
71596
- this.slider.disabled = true;
71597
- };
71991
+ const column = browser.columnContainer.querySelector('.igv-sample-name-column');
71992
+ column.style.display = false === browser.showSampleNames ? 'none' : 'flex';
71598
71993
 
71599
- ZoomWidget.prototype.hide = function () {
71600
- this.zoomContainer.style.display = 'none';
71601
- };
71994
+ this.setState(browser.showSampleNames);
71602
71995
 
71603
- ZoomWidget.prototype.show = function () {
71604
- this.zoomContainer.style.display = 'block';
71605
- };
71996
+ browser.layoutChange();
71606
71997
 
71607
- ZoomWidget.prototype.hideSlider = function () {
71608
- this.slider.style.display = 'none';
71609
- };
71998
+ }
71610
71999
 
71611
- ZoomWidget.prototype.showSlider = function () {
71612
- this.slider.style.display = 'block';
71613
- };
72000
+ }
71614
72001
 
71615
72002
  class Dropdown {
71616
72003
  constructor(parent, shim) {
@@ -71753,7 +72140,7 @@
71753
72140
  class SaveImageControl extends NavbarButton {
71754
72141
  constructor(parent, browser) {
71755
72142
 
71756
- super(browser, parent, 'Save Image', buttonLabel, imageSaveImageSVG, imageSaveImageHoverSVG, false);
72143
+ super(parent, browser, 'Save Image', buttonLabel, imageSaveImageSVG, imageSaveImageHoverSVG, false);
71757
72144
 
71758
72145
  this.button.addEventListener('mouseenter', () => this.setState(true));
71759
72146
 
@@ -71819,6 +72206,422 @@
71819
72206
 
71820
72207
  }
71821
72208
 
72209
+ /**
72210
+ * User supplied button for the navbar
72211
+ */
72212
+
72213
+ const CustomButton = function (parent, browser, b) {
72214
+
72215
+ const button = div({class: 'igv-navbar-button'});
72216
+ parent.append(button);
72217
+ button.textContent = b.label;
72218
+ button.addEventListener('click', () => b.callback(browser));
72219
+ };
72220
+
72221
+ const sliderMin = 0;
72222
+ let sliderMax = 23;
72223
+ let sliderValueRaw = 0;
72224
+
72225
+ class ZoomWidget {
72226
+ constructor(config, browser, parent) {
72227
+
72228
+ this.browser = browser;
72229
+
72230
+ this.zoomContainer = div({class: 'igv-zoom-widget'});
72231
+ parent.appendChild(this.zoomContainer);
72232
+
72233
+ // zoom out
72234
+ this.zoomOutButton = div();
72235
+ this.zoomContainer.appendChild(this.zoomOutButton);
72236
+ this.zoomOutButton.appendChild(createIcon('minus-circle'));
72237
+ this.zoomOutButton.addEventListener('click', () => {
72238
+ // browser.zoomWithScaleFactor(2.0)
72239
+ browser.zoomOut();
72240
+ });
72241
+
72242
+ // Range slider
72243
+ const el = div();
72244
+ this.zoomContainer.appendChild(el);
72245
+ this.slider = document.createElement('input');
72246
+ this.slider.type = 'range';
72247
+
72248
+ this.slider.min = `${sliderMin}`;
72249
+ this.slider.max = `${sliderMax}`;
72250
+
72251
+ el.appendChild(this.slider);
72252
+
72253
+ this.slider.addEventListener('change', e => {
72254
+
72255
+ e.preventDefault();
72256
+ e.stopPropagation();
72257
+
72258
+ const referenceFrame = browser.referenceFrameList[0];
72259
+ const {bpLength} = referenceFrame.genome.getChromosome(referenceFrame.chr);
72260
+ const {end, start} = referenceFrame;
72261
+
72262
+ const extent = end - start;
72263
+
72264
+ // bpLength/(end - start)
72265
+ const scaleFactor = Math.pow(2, e.target.valueAsNumber);
72266
+
72267
+ // (end - start) = bpLength/scaleFactor
72268
+ const zoomedExtent = bpLength / scaleFactor;
72269
+
72270
+ // console.log(`zoom-widget - slider ${ e.target.value } scaleFactor ${ scaleFactor } extent-zoomed ${ StringUtils.numberFormatter(Math.round(zoomedExtent)) }`)
72271
+
72272
+ browser.zoomWithScaleFactor(zoomedExtent / extent);
72273
+
72274
+ });
72275
+
72276
+ // zoom in
72277
+ this.zoomInButton = div();
72278
+ this.zoomContainer.appendChild(this.zoomInButton);
72279
+ this.zoomInButton.appendChild(createIcon('plus-circle'));
72280
+ this.zoomInButton.addEventListener('click', () => {
72281
+ // browser.zoomWithScaleFactor(0.5)
72282
+ browser.zoomIn();
72283
+ });
72284
+
72285
+ browser.on('locuschange', (referenceFrameList) => {
72286
+
72287
+ if (this.browser.isMultiLocusMode()) {
72288
+ this.disable();
72289
+ } else {
72290
+ this.enable();
72291
+ this.update(referenceFrameList);
72292
+ }
72293
+
72294
+ });
72295
+
72296
+ }
72297
+
72298
+ update(referenceFrameList) {
72299
+
72300
+ if (this.slider) {
72301
+ const referenceFrame = referenceFrameList[0];
72302
+ const {bpLength} = referenceFrame.genome.getChromosome(referenceFrame.chr);
72303
+ const {start, end} = referenceFrame;
72304
+
72305
+ sliderMax = Math.ceil(Math.log2(bpLength / this.browser.minimumBases()));
72306
+ this.slider.max = `${sliderMax}`;
72307
+
72308
+ const scaleFactor = bpLength / (end - start);
72309
+ sliderValueRaw = Math.log2(scaleFactor);
72310
+ this.slider.value = `${Math.round(sliderValueRaw)}`;
72311
+ }
72312
+ }
72313
+
72314
+
72315
+ enable() {
72316
+
72317
+ // this.zoomInButton.style.color = appleCrayonPalette[ 'steel' ];
72318
+ // this.zoomInButton.style.pointerEvents = 'auto';
72319
+ //
72320
+ // this.zoomOutButton.style.color = appleCrayonPalette[ 'steel' ];
72321
+ // this.zoomOutButton.style.pointerEvents = 'auto';
72322
+
72323
+ if (this.slider) this.slider.disabled = false;
72324
+ }
72325
+
72326
+ disable() {
72327
+
72328
+ // this.zoomInButton.style.color = appleCrayonPalette[ 'silver' ];
72329
+ // this.zoomInButton.style.pointerEvents = 'none';
72330
+ //
72331
+ // this.zoomOutButton.style.color = appleCrayonPalette[ 'silver' ];
72332
+ // this.zoomOutButton.style.pointerEvents = 'none';
72333
+
72334
+ if (this.slider) this.slider.disabled = true;
72335
+ }
72336
+
72337
+ hide() {
72338
+ this.zoomContainer.style.display = 'none';
72339
+ }
72340
+
72341
+ show() {
72342
+ this.zoomContainer.style.display = 'block';
72343
+ }
72344
+
72345
+ hideSlider() {
72346
+ if (this.slider) this.slider.style.display = 'none';
72347
+ }
72348
+
72349
+ showSlider() {
72350
+ if (this.slider) this.slider.style.display = 'block';
72351
+ }
72352
+ }
72353
+
72354
+ /*
72355
+ * The MIT License (MIT)
72356
+ *
72357
+ * Copyright (c) 2014 Broad Institute
72358
+ *
72359
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
72360
+ * of this software and associated documentation files (the "Software"), to deal
72361
+ * in the Software without restriction, including without limitation the rights
72362
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
72363
+ * copies of the Software, and to permit persons to whom the Software is
72364
+ * furnished to do so, subject to the following conditions:
72365
+ *
72366
+ * The above copyright notice and this permission notice shall be included in
72367
+ * all copies or substantial portions of the Software.
72368
+ *
72369
+ *
72370
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
72371
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
72372
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
72373
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
72374
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
72375
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
72376
+ * THE SOFTWARE.
72377
+ */
72378
+
72379
+ class ResponsiveNavbar {
72380
+ constructor(config, browser) {
72381
+
72382
+ this.browser = browser;
72383
+ this.config = config;
72384
+
72385
+ this.currentClass = 'igv-navbar-text-button';
72386
+
72387
+ // DOM element for
72388
+ const $navBar = $$1('<div>', {class: 'igv-navbar'});
72389
+ this.$navigation = $navBar;
72390
+
72391
+ const $navbarLeftContainer = $$1('<div>', {class: 'igv-navbar-left-container'});
72392
+ $navBar.append($navbarLeftContainer);
72393
+ this.navbarLeftContainer = $navbarLeftContainer.get(0);
72394
+
72395
+ // IGV logo
72396
+ const $logo = $$1('<div>', {class: 'igv-logo'});
72397
+ $navbarLeftContainer.append($logo);
72398
+
72399
+ const logoSvg = logo();
72400
+ logoSvg.css("width", "34px");
72401
+ logoSvg.css("height", "32px");
72402
+ $logo.append(logoSvg);
72403
+
72404
+ this.$current_genome = $$1('<div>', {class: 'igv-current-genome'});
72405
+ $navbarLeftContainer.append(this.$current_genome);
72406
+ this.$current_genome.text('');
72407
+
72408
+ const $genomicLocation = $$1('<div>', {class: 'igv-navbar-genomic-location'});
72409
+ $navbarLeftContainer.append($genomicLocation);
72410
+
72411
+ // chromosome select widget
72412
+ this.chromosomeSelectWidget = new ChromosomeSelectWidget(browser, $genomicLocation.get(0));
72413
+ if (config.showChromosomeWidget !== false) {
72414
+ this.chromosomeSelectWidget.show();
72415
+ } else {
72416
+ this.chromosomeSelectWidget.hide();
72417
+ }
72418
+
72419
+ const $locusSizeGroup = $$1('<div>', {class: 'igv-locus-size-group'});
72420
+ $genomicLocation.append($locusSizeGroup);
72421
+
72422
+ const $searchContainer = $$1('<div>', {class: 'igv-search-container'});
72423
+ $locusSizeGroup.append($searchContainer);
72424
+
72425
+ // browser.$searchInput = $('<input type="text" placeholder="Locus Search">');
72426
+ this.$searchInput = $$1('<input>', {class: 'igv-search-input', type: 'text', placeholder: 'Locus Search'});
72427
+ $searchContainer.append(this.$searchInput);
72428
+ // Stop event propagation to prevent feature track keyboard navigation
72429
+ this.$searchInput[0].addEventListener('keyup', (event) => {
72430
+ event.stopImmediatePropagation();
72431
+ });
72432
+
72433
+ this.$searchInput.change(() => browser.doSearch(this.$searchInput.val()));
72434
+
72435
+ const searchIconContainer = div({class: 'igv-search-icon-container'});
72436
+ $searchContainer.append($$1(searchIconContainer));
72437
+ searchIconContainer.appendChild(createIcon("search"));
72438
+ searchIconContainer.addEventListener('click', () => browser.doSearch(this.$searchInput.val()));
72439
+
72440
+ this.windowSizePanel = new WindowSizePanel($locusSizeGroup.get(0), browser);
72441
+
72442
+ const $navbarRightContainer = $$1('<div>', {class: 'igv-navbar-right-container'});
72443
+ $navBar.append($navbarRightContainer);
72444
+ this.navbarRightContainer = $navbarRightContainer.get(0);
72445
+
72446
+ const $toggle_button_container = $$1('<div class="igv-navbar-toggle-button-container">');
72447
+ $navbarRightContainer.append($toggle_button_container);
72448
+ const toggleButtonContainer = $toggle_button_container.get(0);
72449
+ this.toggle_button_container = toggleButtonContainer; // TODO -- for circular view , refactor this
72450
+
72451
+ this.overlayTrackButton = new OverlayTrackButton(toggleButtonContainer, browser);
72452
+ this.overlayTrackButton.setVisibility(false);
72453
+
72454
+ const showMultiSelect = config.showMultiSelectButton !== false;
72455
+ this.multiTrackSelectButton = new MultiTrackSelectButton(toggleButtonContainer, browser, this, showMultiSelect);
72456
+
72457
+ this.cursorGuideButton = new CursorGuideButton(toggleButtonContainer, browser);
72458
+
72459
+ this.centerLineButton = new CenterLineButton(toggleButtonContainer, browser);
72460
+
72461
+ this.trackLabelControl = new TrackLabelControl(toggleButtonContainer, browser);
72462
+
72463
+ // ROI Control
72464
+ this.roiTableControl = new ROITableControl(toggleButtonContainer, browser);
72465
+
72466
+ this.sampleInfoControl = new SampleInfoControl(toggleButtonContainer, browser);
72467
+
72468
+ this.sampleNameControl = new SampleNameControl(toggleButtonContainer, browser);
72469
+
72470
+ if (true === config.showSVGButton) {
72471
+ this.saveImageControl = new SaveImageControl(toggleButtonContainer, browser);
72472
+ }
72473
+
72474
+ if (config.customButtons) {
72475
+ for (let b of config.customButtons) {
72476
+ new CustomButton(toggleButtonContainer, browser, b);
72477
+ }
72478
+ }
72479
+
72480
+ this.zoomWidget = new ZoomWidget(config, browser, $navbarRightContainer.get(0));
72481
+
72482
+ if (false === config.showNavigation) {
72483
+ this.$navigation.hide();
72484
+ }
72485
+
72486
+
72487
+
72488
+ }
72489
+
72490
+ navbarDidResize() {
72491
+
72492
+
72493
+ const navbarWidth = this.$navigation.width();
72494
+ const currentClass = this.currentNavbarButtonClass();
72495
+ if ('igv-navbar-text-button' === currentClass) {
72496
+ this.textButtonContainerWidth = this.navbarRightContainer.getBoundingClientRect().width;
72497
+ }
72498
+ const browser = this.browser;
72499
+ const isWGV =
72500
+ (browser.isMultiLocusWholeGenomeView()) ||
72501
+ (browser.referenceFrameList && GenomeUtils.isWholeGenomeView(browser.referenceFrameList[0].chr));
72502
+
72503
+ isWGV ? this.windowSizePanel.hide() : this.windowSizePanel.show();
72504
+
72505
+ const {
72506
+ x: leftContainerX,
72507
+ width: leftContainerWidth
72508
+ } = this.navbarLeftContainer.getBoundingClientRect();
72509
+ const leftContainerExtent = leftContainerX + leftContainerWidth;
72510
+ const {x: rightContainerX} = this.navbarRightContainer.getBoundingClientRect();
72511
+
72512
+ const delta = rightContainerX - leftContainerExtent;
72513
+
72514
+ let navbarButtonClass;
72515
+ const threshold = 8;
72516
+ if ('igv-navbar-text-button' === currentClass && delta < threshold) {
72517
+ navbarButtonClass = 'igv-navbar-icon-button';
72518
+ } else if (this.textButtonContainerWidth && 'igv-navbar-icon-button' === currentClass) {
72519
+ const length = navbarWidth - leftContainerExtent;
72520
+ if (length - this.textButtonContainerWidth > threshold) {
72521
+ navbarButtonClass = 'igv-navbar-text-button';
72522
+ }
72523
+ }
72524
+ // Update all the buttons (buttons are listeners)
72525
+ if(navbarButtonClass && currentClass !== navbarButtonClass) {
72526
+ this.currentClass = navbarButtonClass;
72527
+ this.browser.fireEvent('navbar-resize', [navbarButtonClass]);
72528
+ }
72529
+
72530
+ let zoomContainerClass;
72531
+ if (isWGV) {
72532
+ zoomContainerClass = 'igv-zoom-widget-hidden';
72533
+ } else {
72534
+ zoomContainerClass = navbarWidth > 860 ? 'igv-zoom-widget' : 'igv-zoom-widget-900';
72535
+ }
72536
+ $$1(this.zoomWidget.zoomContainer).removeClass();
72537
+ $$1(this.zoomWidget.zoomContainer).addClass(zoomContainerClass);
72538
+ }
72539
+
72540
+
72541
+ setCenterLineButtonVisibility(isWholeGenomeView) {
72542
+ if (isWholeGenomeView) {
72543
+ this.centerLineButton.setVisibility(!isWholeGenomeView);
72544
+ } else {
72545
+ this.centerLineButton.setVisibility(this.config.showCenterGuideButton);
72546
+ }
72547
+ }
72548
+
72549
+ setCursorGuideVisibility(doShowCursorGuide) {
72550
+ if (doShowCursorGuide) {
72551
+ this.cursorGuide.show();
72552
+ } else {
72553
+ this.cursorGuide.hide();
72554
+ }
72555
+ }
72556
+
72557
+ updateGenome(genome) {
72558
+
72559
+ let genomeLabel = (genome.id && genome.id.length < 20 ? genome.id : `${genome.id.substring(0, 8)}...${genome.id.substring(genome.id.length - 8)}`);
72560
+ this.$current_genome.text(genomeLabel);
72561
+ this.$current_genome.attr('title', genome.description);
72562
+
72563
+ // chromosome select widget -- Show this IFF its not explicitly hidden AND the genome has pre-loaded chromosomes
72564
+ const showChromosomeWidget =
72565
+ this.config.showChromosomeWidget !== false &&
72566
+ genome.showChromosomeWidget !== false &&
72567
+ genome.chromosomeNames &&
72568
+ genome.chromosomeNames.length > 1;
72569
+
72570
+ if (showChromosomeWidget) {
72571
+ this.chromosomeSelectWidget.update(genome);
72572
+ this.chromosomeSelectWidget.show();
72573
+ } else {
72574
+ this.chromosomeSelectWidget.hide();
72575
+ }
72576
+ }
72577
+
72578
+ updateLocus(loc, chrName) {
72579
+ if(this.$searchInput) {
72580
+ this.$searchInput.val(loc);
72581
+ }
72582
+ if (this.chromosomeSelectWidget) {
72583
+ this.chromosomeSelectWidget.select.value = chrName;
72584
+ }
72585
+ }
72586
+
72587
+ currentNavbarButtonClass() {
72588
+ return this.currentClass
72589
+ //const el = this.$navigation.get(0).querySelector('.igv-navbar-text-button')
72590
+ //return el ? 'igv-navbar-text-button' : 'igv-navbar-icon-button'
72591
+ }
72592
+
72593
+ setEnableTrackSelection(b) {
72594
+ this.multiTrackSelectButton.setMultiTrackSelection(b);
72595
+ }
72596
+ getEnableTrackSelection() {
72597
+ return this.multiTrackSelectButton.enableMultiTrackSelection
72598
+ }
72599
+
72600
+ hide() {
72601
+ this.$navigation.hide();
72602
+ }
72603
+
72604
+ show() {
72605
+ this.$navigation.show();
72606
+ }
72607
+
72608
+ }
72609
+
72610
+
72611
+ function logo() {
72612
+
72613
+ return $$1(
72614
+ '<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">' +
72615
+ '<title>IGV</title>' +
72616
+ '<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">' +
72617
+ '<g id="IGV" fill="#666666">' +
72618
+ '<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>' +
72619
+ '<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>;' +
72620
+ '<polygon id="Path" points="0.81355666 5.00169252 73.0472883 5.00169252 73.0472883 317.722144 0.81355666 317.722144"></polygon>' +
72621
+ '</g> </g> </svg>'
72622
+ )
72623
+ }
72624
+
71822
72625
  const viewportColumnManager =
71823
72626
  {
71824
72627
  createColumns: (columnContainer, count) => {
@@ -72030,18 +72833,6 @@
72030
72833
  this.button.style.display = 'none';
72031
72834
  };
72032
72835
 
72033
- /**
72034
- * User supplied button for the navbar
72035
- */
72036
-
72037
- const CustomButton = function (parent, browser, b) {
72038
-
72039
- const button = div({class: 'igv-navbar-button'});
72040
- parent.append(button);
72041
- button.textContent = b.label;
72042
- button.addEventListener('click', () => b.callback(browser));
72043
- };
72044
-
72045
72836
  const maxSequenceSize = 1000000;
72046
72837
  const maxBlatSize = 25000;
72047
72838
 
@@ -72806,88 +73597,6 @@
72806
73597
  }
72807
73598
  }
72808
73599
 
72809
- const roiImage =
72810
- `<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">
72811
- <title>roi</title>
72812
- <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
72813
- <g id="roi">
72814
- <rect id="Rectangle-Copy-23" stroke="#737373" stroke-width="12" fill="#FFFFFF" x="6" y="6" width="613" height="613" rx="135"></rect>
72815
- <text id="ROI" font-family="HelveticaNeue-Bold, Helvetica Neue" font-size="258" font-weight="bold" fill="#737373">
72816
- <tspan x="81.445" y="389">ROI</tspan>
72817
- </text>
72818
- </g>
72819
- </g>
72820
- </svg>`;
72821
-
72822
- const roiImageHover =
72823
- `<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">
72824
- <title>roi hover</title>
72825
- <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
72826
- <g id="roi-hover">
72827
- <rect id="Rectangle-Copy-24" stroke="#737373" stroke-width="12" fill="#737373" x="6" y="6" width="613" height="613" rx="135"></rect>
72828
- <text id="ROI" font-family="HelveticaNeue-Bold, Helvetica Neue" font-size="258" font-weight="bold" fill="#FFFFFF">
72829
- <tspan x="81.445" y="389">ROI</tspan>
72830
- </text>
72831
- </g>
72832
- </g>
72833
- </svg>`;
72834
-
72835
- /*
72836
- * The MIT License (MIT)
72837
- *
72838
- * Copyright (c) 2016 University of California San Diego
72839
- * Author: Jim Robinson
72840
- *
72841
- * Permission is hereby granted, free of charge, to any person obtaining a copy
72842
- * of this software and associated documentation files (the "Software"), to deal
72843
- * in the Software without restriction, including without limitation the rights
72844
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
72845
- * copies of the Software, and to permit persons to whom the Software is
72846
- * furnished to do so, subject to the following conditions:
72847
- *
72848
- * The above copyright notice and this permission notice shall be included in
72849
- * all copies or substantial portions of the Software.
72850
- *
72851
- *
72852
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
72853
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
72854
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
72855
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
72856
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
72857
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
72858
- * THE SOFTWARE.
72859
- */
72860
-
72861
- class ROITableControl extends NavbarButton {
72862
-
72863
- constructor(parent, browser) {
72864
-
72865
- super(browser, parent, [ 'ROI', 'Regions of Interest Table' ], buttonLabel, roiImage, roiImageHover, false);
72866
-
72867
- this.button.addEventListener('mouseenter', () => {
72868
- if (false === browser.doShowROITable) {
72869
- this.setState(true);
72870
- }
72871
- });
72872
-
72873
- this.button.addEventListener('mouseleave', () => {
72874
- if (false === browser.doShowROITable) {
72875
- this.setState(false);
72876
- }
72877
- });
72878
-
72879
- this.button.addEventListener('click', () => this.buttonHandler(!browser.doShowROITable));
72880
-
72881
- this.setVisibility(false); // Hide initially, it will be un-hidden if ROIs are loaded
72882
-
72883
- }
72884
-
72885
- buttonHandler(status) {
72886
- this.setState(status);
72887
- this.browser.setROITableVisibility(status);
72888
- }
72889
- }
72890
-
72891
73600
  async function translateSession(juiceboxSession) {
72892
73601
 
72893
73602
  const jbBrowser = juiceboxSession.browsers[0];
@@ -72924,101 +73633,6 @@
72924
73633
 
72925
73634
  }
72926
73635
 
72927
- const multiSelectImage =
72928
- `<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">
72929
- <title>multi select</title>
72930
- <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
72931
- <g id="multi-select">
72932
- <rect id="backdrop-copy-3" stroke="#737373" stroke-width="12" fill="#FFFFFF" x="6" y="6" width="613" height="613" rx="135"></rect>
72933
- <g id="row-copy-3" transform="translate(81, 427)" fill="#737373">
72934
- <rect id="Rectangle" x="134" y="0" width="329" height="70"></rect>
72935
- <rect id="Rectangle-Copy-16" stroke="#737373" stroke-width="12" x="6" y="6" width="58" height="58"></rect>
72936
- </g>
72937
- <g id="row-copy-2" transform="translate(82, 277)">
72938
- <rect id="Rectangle" fill-opacity="0.33" fill="#CFCECE" x="133" y="0" width="329" height="70"></rect>
72939
- <rect id="Rectangle-Copy-16" stroke-opacity="0.32659528" stroke="#CFCECE" stroke-width="12" x="6" y="6" width="58" height="58"></rect>
72940
- </g>
72941
- <g id="row-copy" transform="translate(81, 119)" fill="#737373">
72942
- <rect id="Rectangle" x="134" y="0" width="329" height="70"></rect>
72943
- <rect id="Rectangle-Copy-17" stroke="#737373" stroke-width="12" x="6" y="6" width="58" height="58"></rect>
72944
- </g>
72945
- </g>
72946
- </g>
72947
- </svg>`;
72948
-
72949
- const multiSelectImageHover =
72950
- `<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">
72951
- <title>multi select hover</title>
72952
- <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
72953
- <g id="multi-select-hover">
72954
- <rect id="backdrop-copy-4" stroke="#737373" stroke-width="12" fill="#737373" x="6" y="6" width="613" height="613" rx="135"></rect>
72955
- <g id="row-copy-3" transform="translate(81, 427)" fill="#FFFFFF">
72956
- <rect id="Rectangle" x="134" y="0" width="329" height="70"></rect>
72957
- <rect id="Rectangle-Copy-16" stroke="#FFFFFF" stroke-width="12" x="6" y="6" width="58" height="58"></rect>
72958
- </g>
72959
- <g id="row-copy-2" transform="translate(82, 277)">
72960
- <rect id="Rectangle" fill-opacity="0.33" fill="#CFCECE" x="133" y="0" width="329" height="70"></rect>
72961
- <rect id="Rectangle-Copy-16" stroke-opacity="0.33" stroke="#CFCECE" stroke-width="12" x="6" y="6" width="58" height="58"></rect>
72962
- </g>
72963
- <g id="row-copy" transform="translate(81, 119)" fill="#FFFFFF">
72964
- <rect id="Rectangle" x="134" y="0" width="329" height="70"></rect>
72965
- <rect id="Rectangle-Copy-17" stroke="#FFFFFF" stroke-width="12" x="6" y="6" width="58" height="58"></rect>
72966
- </g>
72967
- </g>
72968
- </g>
72969
- </svg>`;
72970
-
72971
- class MultiTrackSelectButton extends NavbarButton {
72972
-
72973
- constructor(browser, parent, enableMultiTrackSelection) {
72974
-
72975
- super(browser, parent, 'Select Tracks', buttonLabel, multiSelectImage, multiSelectImageHover, enableMultiTrackSelection = false);
72976
- this.enableMultiTrackSelection = enableMultiTrackSelection;
72977
- this.button.addEventListener('mouseenter', event => {
72978
- if (false === enableMultiTrackSelection) {
72979
- this.setState(true);
72980
- }
72981
- });
72982
-
72983
- this.button.addEventListener('mouseleave', event => {
72984
- if (false === enableMultiTrackSelection) {
72985
- this.setState(false);
72986
- }
72987
- });
72988
-
72989
- const mouseClickHandler = () => {
72990
- this.setMultiTrackSelection(!this.enableMultiTrackSelection);
72991
- };
72992
-
72993
- this.boundMouseClickHandler = mouseClickHandler.bind(this);
72994
-
72995
- this.button.addEventListener('click', this.boundMouseClickHandler);
72996
-
72997
- this.setVisibility(true);
72998
-
72999
- }
73000
-
73001
- setMultiTrackSelection(enableMultiTrackSelection) {
73002
- this.enableMultiTrackSelection = enableMultiTrackSelection;
73003
- for (const trackView of this.browser.trackViews) {
73004
- if (false === multiTrackSelectExclusionTypes.has(trackView.track.type)) {
73005
- trackView.setTrackSelectionState(trackView.axis, this.enableMultiTrackSelection);
73006
-
73007
- // If closing the selection boxes set track selected property to false
73008
- if (!this.enableMultiTrackSelection) {
73009
- trackView.track.selected = false;
73010
- }
73011
- }
73012
- }
73013
- this.setState(this.enableMultiTrackSelection);
73014
-
73015
- // If enableMultiTrackSelection is false hide Overlay button
73016
- if (false === this.enableMultiTrackSelection) {
73017
- this.browser.overlayTrackButton.setVisibility(false);
73018
- }
73019
- }
73020
- }
73021
-
73022
73636
  /**
73023
73637
  * Chromosome alias source backed by a UCSC bigbed file
73024
73638
  *
@@ -73038,6 +73652,13 @@
73038
73652
  this.reader = new BWReader(config, genome);
73039
73653
  }
73040
73654
 
73655
+ async preload(chrNames) {
73656
+ await this.reader.preload();
73657
+ for(let nm of chrNames) {
73658
+ await this.search(nm);
73659
+ }
73660
+ }
73661
+
73041
73662
  /**
73042
73663
  * Return the cached canonical chromosome name for the alias. If none found return the alias.
73043
73664
  *
@@ -73113,6 +73734,10 @@
73113
73734
  this.genome = genome;
73114
73735
  }
73115
73736
 
73737
+ async preload() {
73738
+ return this.loadAliases();
73739
+ }
73740
+
73116
73741
  /**
73117
73742
  * Return the canonical chromosome name for the alias. If none found return the alias
73118
73743
  *
@@ -73165,6 +73790,9 @@
73165
73790
  aliasRecord[key] = tokens[i];
73166
73791
  this.aliasRecordCache.set(tokens[i], aliasRecord);
73167
73792
  }
73793
+
73794
+ this.aliasRecordCache.set(chr.toLowerCase(), aliasRecord);
73795
+ this.aliasRecordCache.set(chr.toUpperCase(), aliasRecord);
73168
73796
  }
73169
73797
  }
73170
73798
  }
@@ -73336,6 +73964,9 @@
73336
73964
  this.update(id, chromosomeNames);
73337
73965
  }
73338
73966
 
73967
+ async preload() {
73968
+ // no-op
73969
+ }
73339
73970
 
73340
73971
  /**
73341
73972
  * Return the canonical chromosome name for the alias. If none found return the alias
@@ -73437,6 +74068,8 @@
73437
74068
  } else if (Number.isInteger(Number(name))) {
73438
74069
  record["ucsc"] = "chr" + name;
73439
74070
  }
74071
+
74072
+
73440
74073
  }
73441
74074
  }
73442
74075
 
@@ -73444,7 +74077,10 @@
73444
74077
  for (let a of Object.values(rec)) {
73445
74078
  this.aliasRecordCache.set(a, rec);
73446
74079
  }
74080
+ this.aliasRecordCache.set(rec.chr.toLowerCase(), rec);
74081
+ this.aliasRecordCache.set(rec.chr.toUpperCase(), rec);
73447
74082
  }
74083
+
73448
74084
  }
73449
74085
  }
73450
74086
 
@@ -73512,7 +74148,7 @@
73512
74148
 
73513
74149
  if (config.chromAliasBbURL) {
73514
74150
  this.chromAlias = new ChromAliasBB(config.chromAliasBbURL, Object.assign({}, config), this);
73515
- if(!this.chromosomeNames) {
74151
+ if (!this.chromosomeNames) {
73516
74152
  this.chromosomeNames = await this.chromAlias.getChromosomeNames();
73517
74153
  }
73518
74154
  } else if (config.aliasURL) {
@@ -73523,17 +74159,17 @@
73523
74159
 
73524
74160
  if (config.cytobandBbURL) {
73525
74161
  this.cytobandSource = new CytobandFileBB(config.cytobandBbURL, Object.assign({}, config), this);
73526
- if(!this.chromosomeNames) {
74162
+ if (!this.chromosomeNames) {
73527
74163
  this.chromosomeNames = await this.cytobandSource.getChromosomeNames();
73528
74164
  }
73529
74165
  } else if (config.cytobandURL) {
73530
74166
  this.cytobandSource = new CytobandFile(config.cytobandURL, Object.assign({}, config));
73531
- if(!this.chromosomeNames) {
74167
+ if (!this.chromosomeNames) {
73532
74168
  this.chromosomeNames = await this.cytobandSource.getChromosomeNames();
73533
74169
  }
73534
- if(this.chromosomes.size === 0) {
74170
+ if (this.chromosomes.size === 0) {
73535
74171
  const c = await this.cytobandSource.getChromosomes();
73536
- for(let chromosome of c) {
74172
+ for (let chromosome of c) {
73537
74173
  this.chromosomes.set(c.name, c);
73538
74174
  }
73539
74175
  }
@@ -73551,6 +74187,7 @@
73551
74187
  } else {
73552
74188
  this.#wgChromosomeNames = trimSmallChromosomes(this.chromosomes);
73553
74189
  }
74190
+ await this.chromAlias.preload(this.#wgChromosomeNames);
73554
74191
  }
73555
74192
 
73556
74193
  // Optionally create the psuedo chromosome "all" to support whole genome view
@@ -73617,15 +74254,15 @@
73617
74254
  async loadChromosome(chr) {
73618
74255
 
73619
74256
  if (this.chromAlias) {
73620
- const chromAliasRecord = await this.chromAlias.search(chr);
73621
- if(chromAliasRecord) {
74257
+ const chromAliasRecord = await this.chromAlias.search(chr);
74258
+ if (chromAliasRecord) {
73622
74259
  chr = chromAliasRecord.chr;
73623
74260
  }
73624
74261
  }
73625
74262
 
73626
74263
  if (!this.chromosomes.has(chr)) {
73627
74264
  let chromosome;
73628
- const sequenceRecord = await this.sequence.getSequenceRecord(chr);
74265
+ const sequenceRecord = await this.sequence.getSequenceRecord(chr);
73629
74266
  if (sequenceRecord) {
73630
74267
  chromosome = new Chromosome(chr, 0, sequenceRecord.bpLength);
73631
74268
  }
@@ -73635,6 +74272,7 @@
73635
74272
 
73636
74273
  return this.chromosomes.get(chr)
73637
74274
  }
74275
+
73638
74276
  async getAliasRecord(chr) {
73639
74277
  if (this.chromAlias) {
73640
74278
  return this.chromAlias.search(chr)
@@ -73654,7 +74292,7 @@
73654
74292
  }
73655
74293
 
73656
74294
  get wgChromosomeNames() {
73657
- return this.#wgChromosomeNames ? this.#wgChromosomeNames.slice() : undefined
74295
+ return this.#wgChromosomeNames ? this.#wgChromosomeNames.slice() : undefined
73658
74296
  }
73659
74297
 
73660
74298
  get showChromosomeWidget() {
@@ -73758,7 +74396,7 @@
73758
74396
  * @param end
73759
74397
  */
73760
74398
  getSequenceInterval(chr, start, end) {
73761
- if(typeof this.sequence.getSequenceInterval === 'function') {
74399
+ if (typeof this.sequence.getSequenceInterval === 'function') {
73762
74400
  return this.sequence.getSequenceInterval(chr, start, end)
73763
74401
  } else {
73764
74402
  return undefined
@@ -73806,7 +74444,7 @@
73806
74444
  }
73807
74445
  }
73808
74446
 
73809
- 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';
74447
+ 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';
73810
74448
 
73811
74449
  /**
73812
74450
  * Manages XQTL selections.
@@ -73927,6 +74565,125 @@
73927
74565
  brewer.push("rgb(204, 235, 197)");
73928
74566
  brewer.push("rgb(255, 237, 111)");
73929
74567
 
74568
+ class SliderDialog {
74569
+
74570
+ constructor(parent) {
74571
+
74572
+ this.parent = parent;
74573
+
74574
+ // dialog container
74575
+ this.container = div({class: 'igv-ui-generic-dialog-container'});
74576
+ parent.appendChild(this.container);
74577
+
74578
+ // dialog header
74579
+ const header = div({class: 'igv-ui-generic-dialog-header'});
74580
+ this.container.appendChild(header);
74581
+
74582
+ // dialog label
74583
+ this.label = div({class: 'igv-ui-generic-dialog-one-liner'});
74584
+ this.container.appendChild(this.label);
74585
+ this.label.text = 'Unlabeled';
74586
+
74587
+ // input container
74588
+ this.input_container = div({class: 'igv-ui-generic-dialog-input'});
74589
+ this.container.appendChild(this.input_container);
74590
+
74591
+ // input element
74592
+ let html = `<input type="range" id="igv-slider-dialog-input" name="igv-slider-dialog-input" />`;
74593
+ this._input = document.createRange().createContextualFragment(html).firstChild;
74594
+ this.input_container.appendChild(this._input);
74595
+
74596
+ // output element
74597
+ html = `<output id="igv-slider-dialog-output" name="igv-slider-dialog-output" for="igv-slider-dialog-input"></output>`;
74598
+ this._output = document.createRange().createContextualFragment(html).firstChild;
74599
+ this.input_container.appendChild(this._output);
74600
+
74601
+
74602
+ // ok | cancel
74603
+ const buttons = div({class: 'igv-ui-generic-dialog-ok-cancel'});
74604
+ this.container.appendChild(buttons);
74605
+
74606
+ // ok
74607
+ this.ok = div();
74608
+ buttons.appendChild(this.ok);
74609
+ this.ok.textContent = 'OK';
74610
+
74611
+ // cancel
74612
+ this.cancel = div();
74613
+ buttons.appendChild(this.cancel);
74614
+ this.cancel.textContent = 'Cancel';
74615
+
74616
+ hide(this.container);
74617
+
74618
+ this._input.addEventListener('input', () => {
74619
+ const number = parseFloat(this._input.value)/this._scaleFactor;
74620
+ this.callback(number);
74621
+ this._output.value = `${number.toFixed(2)}`;
74622
+ }, false);
74623
+
74624
+ this.ok.addEventListener('click', () => {
74625
+ if (typeof this.callback === 'function') {
74626
+ const number = parseFloat(this._input.value)/this._scaleFactor;
74627
+ this.callback(number);
74628
+ this.callback = undefined;
74629
+ }
74630
+ this._input.value = undefined;
74631
+ hide(this.container);
74632
+ });
74633
+
74634
+ const cancel = () => {
74635
+ this._input.value = undefined;
74636
+ hide(this.container);
74637
+ };
74638
+
74639
+ this.cancel.addEventListener('click', cancel);
74640
+
74641
+ attachDialogCloseHandlerWithParent(header, cancel);
74642
+ makeDraggable(this.container, header);
74643
+
74644
+ }
74645
+
74646
+ get value() {
74647
+ return purify.sanitize(this._input.value)
74648
+ }
74649
+
74650
+ present(options, e) {
74651
+
74652
+ this.label.textContent = options.label;
74653
+
74654
+ this._scaleFactor = options.scaleFactor;
74655
+ const [ minS, maxS, valueS ] = [ options.min, options.max, options.value ].map(number => (Math.floor(this._scaleFactor * number)).toString());
74656
+
74657
+ this._input.min = minS;
74658
+ this._input.max = maxS;
74659
+ this._input.value = valueS;
74660
+
74661
+ const numer = parseFloat(valueS);
74662
+ const denom = this._scaleFactor;
74663
+ const number = numer/denom;
74664
+ this._output.value = `${number.toFixed(2)}`;
74665
+
74666
+ this.callback = options.callback || options.click;
74667
+
74668
+ show(this.container);
74669
+ this.clampLocation(e.clientX, e.clientY);
74670
+
74671
+ }
74672
+
74673
+ clampLocation(clientX, clientY) {
74674
+
74675
+ const {width: w, height: h} = this.container.getBoundingClientRect();
74676
+ const wh = window.innerHeight;
74677
+ const ww = window.innerWidth;
74678
+
74679
+ const y = Math.min(wh - h, clientY);
74680
+ const x = Math.min(ww - w, clientX);
74681
+ this.container.style.left = `${x}px`;
74682
+ this.container.style.top = `${y}px`;
74683
+
74684
+ }
74685
+ }
74686
+
73930
74687
  // css - $igv-scrollbar-outer-width: 14px;
73931
74688
  const igv_scrollbar_outer_width = 14;
73932
74689
 
@@ -74016,7 +74773,6 @@
74016
74773
  this.sampleNameControl.setState(this.showSampleNames);
74017
74774
  this.sampleNameControl.hide();
74018
74775
 
74019
-
74020
74776
  this.layoutChange();
74021
74777
  }
74022
74778
  });
@@ -74035,7 +74791,7 @@
74035
74791
 
74036
74792
  this.sampleInfo = new SampleInfo(this);
74037
74793
 
74038
- this.setControls(config);
74794
+ this.createStandardControls(config);
74039
74795
 
74040
74796
  // Region of interest
74041
74797
  this.roiManager = new ROIManager(this);
@@ -74093,121 +74849,18 @@
74093
74849
  }
74094
74850
  }
74095
74851
 
74096
- setControls(config) {
74097
-
74098
- const $navBar = this.createStandardControls(config);
74099
- $navBar.insertBefore($$1(this.columnContainer));
74100
- this.$navigation = $navBar;
74101
-
74102
- if (false === config.showControls) {
74103
- $navBar.hide();
74104
- }
74105
-
74106
- }
74107
-
74108
74852
  createStandardControls(config) {
74109
74853
 
74110
- const $navBar = $$1('<div>', {class: 'igv-navbar'});
74111
- this.$navigation = $navBar;
74112
-
74113
- const $navbarLeftContainer = $$1('<div>', {class: 'igv-navbar-left-container'});
74114
- $navBar.append($navbarLeftContainer);
74115
-
74116
- // IGV logo
74117
- const $logo = $$1('<div>', {class: 'igv-logo'});
74118
- $navbarLeftContainer.append($logo);
74119
-
74120
- const logoSvg = logo();
74121
- logoSvg.css("width", "34px");
74122
- logoSvg.css("height", "32px");
74123
- $logo.append(logoSvg);
74124
-
74125
- this.$current_genome = $$1('<div>', {class: 'igv-current-genome'});
74126
- $navbarLeftContainer.append(this.$current_genome);
74127
- this.$current_genome.text('');
74128
-
74129
- const $genomicLocation = $$1('<div>', {class: 'igv-navbar-genomic-location'});
74130
- $navbarLeftContainer.append($genomicLocation);
74131
-
74132
- // chromosome select widget
74133
- this.chromosomeSelectWidget = new ChromosomeSelectWidget(this, $genomicLocation.get(0));
74134
- if (config.showChromosomeWidget !== false) {
74135
- this.chromosomeSelectWidget.show();
74136
- } else {
74137
- this.chromosomeSelectWidget.hide();
74138
- }
74139
-
74140
- const $locusSizeGroup = $$1('<div>', {class: 'igv-locus-size-group'});
74141
- $genomicLocation.append($locusSizeGroup);
74142
-
74143
- const $searchContainer = $$1('<div>', {class: 'igv-search-container'});
74144
- $locusSizeGroup.append($searchContainer);
74145
-
74146
- // browser.$searchInput = $('<input type="text" placeholder="Locus Search">');
74147
- this.$searchInput = $$1('<input>', {class: 'igv-search-input', type: 'text', placeholder: 'Locus Search'});
74148
- $searchContainer.append(this.$searchInput);
74149
- // Stop event propagation to prevent feature track keyboard navigation
74150
- this.$searchInput[0].addEventListener('keyup', (event) => {
74151
- event.stopImmediatePropagation();
74152
- });
74153
-
74154
- this.$searchInput.change(() => this.doSearch(this.$searchInput.val()));
74155
-
74156
- const searchIconContainer = div({class: 'igv-search-icon-container'});
74157
- $searchContainer.append($$1(searchIconContainer));
74158
-
74159
- searchIconContainer.appendChild(createIcon("search"));
74160
-
74161
- searchIconContainer.addEventListener('click', () => this.doSearch(this.$searchInput.val()));
74162
-
74163
- this.windowSizePanel = new WindowSizePanel($locusSizeGroup.get(0), this);
74164
-
74165
- const $navbarRightContainer = $$1('<div>', {class: 'igv-navbar-right-container'});
74166
- $navBar.append($navbarRightContainer);
74167
-
74168
- const $toggle_button_container = $$1('<div class="igv-navbar-toggle-button-container">');
74169
- $navbarRightContainer.append($toggle_button_container);
74170
- this.$toggle_button_container = $toggle_button_container;
74171
-
74172
- this.overlayTrackButton = new OverlayTrackButton(this, $toggle_button_container.get(0));
74173
- this.overlayTrackButton.setVisibility(false);
74174
-
74175
- this.multiTrackSelectButton = new MultiTrackSelectButton(this, $toggle_button_container.get(0));
74176
-
74177
- this.cursorGuide = new CursorGuide(this.columnContainer, this);
74178
-
74179
- this.cursorGuideButton = new CursorGuideButton(this, $toggle_button_container.get(0));
74180
-
74181
- this.centerLineButton = new CenterLineButton(this, $toggle_button_container.get(0));
74182
-
74183
74854
  this.setTrackLabelVisibility(config.showTrackLabels);
74184
- this.trackLabelControl = new TrackLabelControl($toggle_button_container.get(0), this);
74185
74855
 
74186
- // ROI Control
74187
- this.roiTableControl = new ROITableControl($toggle_button_container.get(0), this);
74188
-
74189
- this.sampleInfoControl = new SampleInfoControl($toggle_button_container.get(0), this);
74856
+ this.navbar = new ResponsiveNavbar(config, this);
74190
74857
 
74191
- this.sampleNameControl = new SampleNameControl($toggle_button_container.get(0), this);
74192
-
74193
- if (true === config.showSVGButton) {
74194
- this.saveImageControl = new SaveImageControl($toggle_button_container.get(0), this);
74195
- }
74858
+ this.navbar.$navigation.insertBefore($$1(this.columnContainer));
74196
74859
 
74197
- if (config.customButtons) {
74198
- for (let b of config.customButtons) {
74199
- new CustomButton($toggle_button_container.get(0), this, b);
74200
- }
74201
- }
74202
-
74203
- this.zoomWidget = new ZoomWidget(this, $navbarRightContainer.get(0));
74204
-
74205
- if (false === config.showNavigation) {
74206
- this.$navigation.hide();
74860
+ if (false === config.showControls) {
74861
+ this.navbar.hide();
74207
74862
  }
74208
-
74209
- this.sliderDialog = new SliderDialog(this.root);
74210
- this.sliderDialog.container.id = `igv-slider-dialog-${guid$2()}`;
74863
+ this.cursorGuide = new CursorGuide(this.columnContainer, this);
74211
74864
 
74212
74865
  this.inputDialog = new InputDialog(this.root);
74213
74866
  this.inputDialog.container.id = `igv-input-dialog-${guid$2()}`;
@@ -74218,7 +74871,8 @@
74218
74871
  this.genericColorPicker = new GenericColorPicker({parent: this.columnContainer, width: 432});
74219
74872
  this.genericColorPicker.container.id = `igv-track-color-picker-${guid$2()}`;
74220
74873
 
74221
- return $navBar
74874
+ this.sliderDialog = new SliderDialog(this.root);
74875
+ this.sliderDialog.container.id = `igv-slider-dialog-${guid$2()}`;
74222
74876
 
74223
74877
  }
74224
74878
 
@@ -74449,10 +75103,10 @@
74449
75103
  session = await translateSession(session);
74450
75104
  }
74451
75105
 
74452
- this.sampleInfoControl.setButtonVisibility(false);
75106
+ this.navbar.sampleInfoControl.setButtonVisibility(false);
74453
75107
 
74454
75108
  this.showSampleNames = session.showSampleNames || false;
74455
- this.sampleNameControl.setState(this.showSampleNames === true);
75109
+ this.navbar.sampleNameControl.setState(this.showSampleNames === true);
74456
75110
 
74457
75111
  if (session.sampleNameViewportWidth) {
74458
75112
  this.sampleNameViewportWidth = session.sampleNameViewportWidth;
@@ -74572,9 +75226,9 @@
74572
75226
  await rtv.updateViews();
74573
75227
  }
74574
75228
 
74575
- // If any tracks are selected show the selectino buttons
75229
+ // If any tracks are selected show the selection buttons
74576
75230
  if (this.trackViews.some(tv => tv.track.selected)) {
74577
- this.multiTrackSelectButton.setMultiTrackSelection(true);
75231
+ this.navbar.setEnableTrackSelection(true);
74578
75232
  }
74579
75233
 
74580
75234
  this.updateUIWithReferenceFrameList();
@@ -74615,7 +75269,8 @@
74615
75269
 
74616
75270
  this.removeAllTracks(); // Do this first, before new genome is set
74617
75271
  this.roiManager.clearROIs();
74618
- this.multiTrackSelectButton.setMultiTrackSelection(false);
75272
+
75273
+ this.navbar.setEnableTrackSelection(false);
74619
75274
 
74620
75275
  let genome;
74621
75276
  if (genomeConfig.gbkURL) {
@@ -74628,8 +75283,7 @@
74628
75283
 
74629
75284
  this.genome = genome;
74630
75285
 
74631
- this.updateNavbarDOMWithGenome(genome);
74632
-
75286
+ this.navbar.updateGenome(genome);
74633
75287
 
74634
75288
  let locus = initialLocus || genome.initialLocus;
74635
75289
  if (Array.isArray(locus)) {
@@ -74660,26 +75314,6 @@
74660
75314
  }
74661
75315
  }
74662
75316
 
74663
- updateNavbarDOMWithGenome(genome) {
74664
- let genomeLabel = (genome.id && genome.id.length < 20 ? genome.id : `${genome.id.substring(0, 8)}...${genome.id.substring(genome.id.length - 8)}`);
74665
- this.$current_genome.text(genomeLabel);
74666
- this.$current_genome.attr('title', genome.description);
74667
-
74668
- // chromosome select widget -- Show this IFF its not explicitly hidden AND the genome has pre-loaded chromosomes
74669
- const showChromosomeWidget =
74670
- this.config.showChromosomeWidget !== false &&
74671
- this.genome.showChromosomeWidget !== false &&
74672
- genome.chromosomeNames &&
74673
- genome.chromosomeNames.length > 1;
74674
-
74675
- if (showChromosomeWidget) {
74676
- this.chromosomeSelectWidget.update(genome);
74677
- this.chromosomeSelectWidget.show();
74678
- } else {
74679
- this.chromosomeSelectWidget.hide();
74680
- }
74681
- }
74682
-
74683
75317
  /**
74684
75318
  * Load a genome, defined by a string ID or a json-like configuration object. This includes a fasta reference
74685
75319
  * as well as optional cytoband and annotation tracks.
@@ -74764,16 +75398,16 @@
74764
75398
 
74765
75399
  (this.isMultiLocusWholeGenomeView() || GenomeUtils.isWholeGenomeView(referenceFrameList[0].chr));
74766
75400
 
74767
- navbarDidResize(this, this.$navigation.width());
75401
+ this.navbar.navbarDidResize();
74768
75402
 
74769
75403
  toggleTrackLabels(this.trackViews, this.doShowTrackLabels);
74770
75404
 
74771
75405
  if (this.doShowCenterLine && GenomeUtils.isWholeGenomeView(referenceFrameList[0].chr)) {
74772
- this.centerLineButton.boundMouseClickHandler();
75406
+ this.navbar.centerLineButton.boundMouseClickHandler();
74773
75407
  }
74774
75408
 
74775
75409
  if (this.doShowCursorGuide && GenomeUtils.isWholeGenomeView(referenceFrameList[0].chr)) {
74776
- this.cursorGuideButton.boundMouseClickHandler();
75410
+ this.navbar.cursorGuideButton.boundMouseClickHandler();
74777
75411
  }
74778
75412
 
74779
75413
  this.setCenterLineAndCenterLineButtonVisibility(GenomeUtils.isWholeGenomeView(referenceFrameList[0].chr));
@@ -74783,9 +75417,9 @@
74783
75417
  setCenterLineAndCenterLineButtonVisibility(isWholeGenomeView) {
74784
75418
 
74785
75419
  if (isWholeGenomeView) {
74786
- this.centerLineButton.setVisibility(!isWholeGenomeView);
75420
+ this.navbar.centerLineButton.setVisibility(false);
74787
75421
  } else {
74788
- this.centerLineButton.setVisibility(this.config.showCenterGuideButton);
75422
+ this.navbar.centerLineButton.setVisibility(this.config.showCenterGuideButton);
74789
75423
  }
74790
75424
 
74791
75425
  for (let centerLine of this.centerLineList) {
@@ -74991,7 +75625,7 @@
74991
75625
  this.reorderTracks();
74992
75626
  this.fireEvent('trackorderchanged', [this.getTrackOrder()]);
74993
75627
 
74994
- this.multiTrackSelectButton.setMultiTrackSelection(this.multiTrackSelectButton.enableMultiTrackSelection);
75628
+ newTrack.trackView.enableTrackSelection(this.navbar.getEnableTrackSelection());
74995
75629
 
74996
75630
  return newTrack
74997
75631
 
@@ -75359,8 +75993,7 @@
75359
75993
  }
75360
75994
 
75361
75995
  if (this.referenceFrameList) {
75362
- this.isMultiLocusWholeGenomeView() || GenomeUtils.isWholeGenomeView(this.referenceFrameList[0].chr);
75363
- navbarDidResize(this, this.$navigation.width());
75996
+ this.navbar.navbarDidResize();
75364
75997
  }
75365
75998
 
75366
75999
  resize.call(this);
@@ -75442,13 +76075,11 @@
75442
76075
  referenceFrame.end = referenceFrame.start + referenceFrame.bpPerPixel * width;
75443
76076
  }
75444
76077
 
75445
- if (this.chromosomeSelectWidget) {
75446
- this.chromosomeSelectWidget.select.value = referenceFrameList.length === 1 ? this.referenceFrameList[0].chr : '';
75447
- }
76078
+ const chrName = referenceFrameList.length === 1 ? this.referenceFrameList[0].chr : '';
75448
76079
 
75449
76080
  const loc = this.referenceFrameList.map(rf => rf.getLocusString()).join(' ');
75450
76081
 
75451
- this.$searchInput.val(loc);
76082
+ this.navbar.updateLocus(loc, chrName);
75452
76083
 
75453
76084
  this.fireEvent('locuschange', [this.referenceFrameList]);
75454
76085
  }
@@ -75723,7 +76354,7 @@
75723
76354
  async loadSampleInfo(config) {
75724
76355
 
75725
76356
  await this.sampleInfo.loadSampleInfoFile(config.url);
75726
-
76357
+
75727
76358
  for (const {sampleInfoViewport} of this.trackViews) {
75728
76359
  sampleInfoViewport.setWidth(this.getSampleInfoColumnWidth());
75729
76360
  }
@@ -76179,7 +76810,7 @@
76179
76810
  createCircularView(container, show) {
76180
76811
  show = show === true; // convert undefined to boolean
76181
76812
  this.circularView = createCircularView(container, this);
76182
- this.circularViewControl = new CircularViewControl(this.$toggle_button_container.get(0), this);
76813
+ this.circularViewControl = new CircularViewControl(this.navbar.toggle_button_container, this);
76183
76814
  this.circularView.setAssembly({
76184
76815
  name: this.genome.id,
76185
76816
  id: this.genome.id,
@@ -76199,6 +76830,30 @@
76199
76830
  this.circularViewControl.setState(isVisible);
76200
76831
  }
76201
76832
  }
76833
+
76834
+
76835
+
76836
+ // Navbar delegates
76837
+ get sampleInfoControl() {
76838
+ return this.navbar.sampleInfoControl
76839
+ }
76840
+
76841
+ get overlayTrackButton() {
76842
+ return this.navbar.overlayTrackButton
76843
+ }
76844
+
76845
+ get roiTableControl() {
76846
+ return this.navbar.roiTableControl
76847
+ }
76848
+
76849
+ get sampleInfoControl() {
76850
+ return this.navbar.sampleInfoControl
76851
+ }
76852
+
76853
+ get sampleNameControl() {
76854
+ return this.navbar.sampleNameControl
76855
+ }
76856
+
76202
76857
  }
76203
76858
 
76204
76859
  function getFileExtension(input) {
@@ -76408,21 +77063,6 @@
76408
77063
  }
76409
77064
  }
76410
77065
 
76411
-
76412
- function logo() {
76413
-
76414
- return $$1(
76415
- '<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">' +
76416
- '<title>IGV</title>' +
76417
- '<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">' +
76418
- '<g id="IGV" fill="#666666">' +
76419
- '<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>' +
76420
- '<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>;' +
76421
- '<polygon id="Path" points="0.81355666 5.00169252 73.0472883 5.00169252 73.0472883 317.722144 0.81355666 317.722144"></polygon>' +
76422
- '</g> </g> </svg>'
76423
- )
76424
- }
76425
-
76426
77066
  function toggleTrackLabels(trackViews, isVisible) {
76427
77067
 
76428
77068
  for (let {viewports} of trackViews) {
@@ -76517,7 +77157,7 @@
76517
77157
  }
76518
77158
 
76519
77159
  browser.stopSpinner();
76520
- navbarDidResize(browser, browser.$navigation.width());
77160
+ browser.navbar.navbarDidResize();
76521
77161
 
76522
77162
  return browser
76523
77163